|
20 | 20 | import urllib.error |
21 | 21 | import urllib.request |
22 | 22 | from datetime import datetime |
23 | | -from pathlib import Path |
| 23 | +from pathlib import Path, PureWindowsPath |
| 24 | + |
| 25 | +import psutil |
24 | 26 |
|
25 | 27 | # Get global values. |
26 | 28 | HERE = Path(__file__).absolute().parent |
@@ -196,6 +198,7 @@ def get_docker_cmd(): |
196 | 198 | docker = shutil.which("podman") or shutil.which("docker") |
197 | 199 | if not docker: |
198 | 200 | return None |
| 201 | + docker = PureWindowsPath(docker).as_posix() |
199 | 202 | if "podman" in docker: |
200 | 203 | docker = f"sudo {docker}" |
201 | 204 | return docker |
@@ -543,7 +546,10 @@ def clean_start(opts): |
543 | 546 | "server.pid", |
544 | 547 | ]: |
545 | 548 | if (mo_home / fname).exists(): |
546 | | - (mo_home / fname).unlink() |
| 549 | + try: |
| 550 | + (mo_home / fname).unlink() |
| 551 | + except PermissionError: |
| 552 | + pass |
547 | 553 |
|
548 | 554 |
|
549 | 555 | def start(opts): |
@@ -635,36 +641,93 @@ def start(opts): |
635 | 641 | LOGGER.info("Starting mongo-orchestration... done.") |
636 | 642 |
|
637 | 643 |
|
| 644 | +def shutdown_proc(proc: psutil.Process) -> None: |
| 645 | + try: |
| 646 | + proc.terminate() |
| 647 | + try: |
| 648 | + proc.wait(10) # Wait up to 10 seconds. |
| 649 | + except psutil.TimeoutExpired: |
| 650 | + proc.kill() |
| 651 | + except Exception as e: |
| 652 | + LOGGER.exception(e) |
| 653 | + |
| 654 | + |
| 655 | +def shutdown_docker(docker: str, container_id: str) -> None: |
| 656 | + if "podman" in docker: |
| 657 | + cmd = f"{docker} rm -f {container_id}" |
| 658 | + else: |
| 659 | + cmd = f"{docker} kill {container_id}" |
| 660 | + run_command(cmd, exit_on_error=False) |
| 661 | + |
| 662 | + |
638 | 663 | def stop(opts): |
639 | 664 | mo_home = Path(opts.mongo_orchestration_home) |
640 | 665 | pid_file = mo_home / "server.pid" |
641 | 666 | container_file = mo_home / "container_id.txt" |
642 | 667 | docker = get_docker_cmd() |
| 668 | + |
| 669 | + # First try to shut down using pid file. |
643 | 670 | if pid_file.exists(): |
644 | | - LOGGER.info("Stopping mongo-orchestration...") |
645 | | - py_exe = normalize_path(sys.executable) |
646 | | - run_command(f"{py_exe} -m mongo_orchestration.server stop") |
| 671 | + pid = int(pid_file.read_text().strip()) |
647 | 672 | pid_file.unlink(missing_ok=True) |
648 | | - LOGGER.info("Stopping mongo-orchestration... done.") |
649 | | - if container_file.exists(): |
650 | | - LOGGER.info("Stopping mongodb_atlas_local...") |
651 | | - container_id = container_file.read_text() |
652 | | - run_command(f"{docker} kill {container_id}", exit_on_error=False) |
| 673 | + if psutil.pid_exists(pid): |
| 674 | + LOGGER.info("Stopping mongo-orchestration using pid file...") |
| 675 | + shutdown_proc(psutil.Process(pid)) |
| 676 | + LOGGER.info("Stopping mongo-orchestration using pid file... done.") |
| 677 | + |
| 678 | + # Next try using a docker container file. |
| 679 | + if docker is not None and container_file.exists(): |
| 680 | + LOGGER.info("Stopping mongodb_atlas_local using container file...") |
| 681 | + shutdown_docker(docker, container_file.read_text()) |
653 | 682 | container_file.unlink() |
654 | | - LOGGER.info("Stopping mongodb_atlas_local... done.") |
655 | | - elif docker: |
656 | | - cmd = f"{docker} ps -a -q -f name=mongodb_atlas_local" |
| 683 | + LOGGER.info("Stopping mongodb_atlas_local using container file ... done.") |
| 684 | + |
| 685 | + all_procs = list(psutil.process_iter()) |
| 686 | + |
| 687 | + # Next look for mongo-orchestration by command line arguments. |
| 688 | + for proc in all_procs: |
657 | 689 | try: |
658 | | - result = subprocess.check_output(shlex.split(cmd), encoding="utf-8").strip() |
659 | | - except Exception: |
660 | | - result = None |
661 | | - if result: |
662 | | - LOGGER.info("Stopping mongodb_atlas_local...") |
663 | | - if "podman" in docker: |
664 | | - run_command(f"{docker} rm -f {result}") |
665 | | - else: |
666 | | - run_command(f"{docker} kill {result}") |
667 | | - LOGGER.info("Stopping mongodb_atlas_local... done.") |
| 690 | + cmdline = proc.cmdline() |
| 691 | + except (psutil.AccessDenied, psutil.NoSuchProcess): |
| 692 | + continue |
| 693 | + found = False |
| 694 | + for item in cmdline: |
| 695 | + if "mongo_orchestration.server" in item or "mongo-orchestration" in item: |
| 696 | + found = True |
| 697 | + break |
| 698 | + if not found: |
| 699 | + continue |
| 700 | + LOGGER.info("Stopping mongo-orchestration by process info...") |
| 701 | + shutdown_proc(proc) |
| 702 | + LOGGER.info("Stopping mongo-orchestration by process info... done.") |
| 703 | + |
| 704 | + # Next look for running docker images. |
| 705 | + if docker: |
| 706 | + cmd = f"{docker} ps --format '{{{{.Image}}}}\t{{{{.ID}}}}'" |
| 707 | + try: |
| 708 | + response = subprocess.check_output( |
| 709 | + shlex.split(cmd), encoding="utf-8" |
| 710 | + ).strip() |
| 711 | + except subprocess.CalledProcessError as e: |
| 712 | + LOGGER.exception(e) |
| 713 | + response = "" |
| 714 | + for line in response.splitlines(): |
| 715 | + image, container_id = line.split("\t") |
| 716 | + if image in ["mongodb/mongodb-atlas-local", "mongo"]: |
| 717 | + LOGGER.info(f"Stopping {image} by image name...") |
| 718 | + shutdown_docker(docker, container_id) |
| 719 | + LOGGER.info(f"Stopping {image} by image name... done.") |
| 720 | + |
| 721 | + # Finally, look for any processes that are named mongod or mongos. |
| 722 | + for proc in all_procs: |
| 723 | + try: |
| 724 | + name = proc.name() |
| 725 | + except psutil.NoSuchProcess: |
| 726 | + continue |
| 727 | + if name in ["mongod", "mongos"]: |
| 728 | + LOGGER.info(f"Stopping {name} by process name...") |
| 729 | + shutdown_proc(proc) |
| 730 | + LOGGER.info(f"Stopping {name} by process name... done.") |
668 | 731 |
|
669 | 732 |
|
670 | 733 | def main(): |
|
0 commit comments