Source code for seamm_installer.services

# -*- coding: utf-8 -*-

"""Handle the services (daemons) for SEAMM."""

from pathlib import Path
import platform
import shutil

from tabulate import tabulate

from . import my


system = platform.system()
if system in ("Darwin",):
    from .mac import ServiceManager

    mgr = ServiceManager(prefix="org.molssi.seamm")
elif system in ("Linux",):
    from .linux import ServiceManager

    mgr = ServiceManager(prefix="org.molssi.seamm")
else:
    raise NotImplementedError(f"SEAMM does not support services on {system} yet.")

known_services = ["dashboard", "jobserver"]


[docs] def setup(parser): """Define the command-line interface for handling services. Parameters ---------- parser : argparse.ArgumentParser The main parser for the application. """ services_parser = parser.add_parser("services") subparser = services_parser.add_subparsers() # Create tmp_parser = subparser.add_parser("create") tmp_parser.set_defaults(func=create) tmp_parser.add_argument( "--force", action="store_true", help="Recreate the service if it already exists.", ) tmp_parser.add_argument( "-p", "--port", type=int, default=55155 if my.development else 55055, ) host = platform.node() if host == "": host = "unknown" tmp_parser.add_argument( "--dashboard-name", default=f"{host} Development" if my.development else host, ) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to create: %(default)s", ) # Delete tmp_parser = subparser.add_parser("delete") tmp_parser.set_defaults(func=delete) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to delete: %(default)s", ) # Start tmp_parser = subparser.add_parser("start") tmp_parser.set_defaults(func=start) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to start: %(default)s", ) # Stop tmp_parser = subparser.add_parser("stop") tmp_parser.set_defaults(func=stop) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to stop: %(default)s", ) # restart tmp_parser = subparser.add_parser("restart") tmp_parser.set_defaults(func=start) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to restart: %(default)s", ) # Show tmp_parser = subparser.add_parser("show") tmp_parser.set_defaults(func=show) tmp_parser.add_argument( "--all", action="store_true", help="Show both the normal and development services.", ) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to show: %(default)s", ) # Status tmp_parser = subparser.add_parser("status") tmp_parser.set_defaults(func=status) tmp_parser.add_argument( "--all", action="store_true", help="Show the status of both normal and development services.", ) tmp_parser.add_argument( "services", nargs="*", default=known_services, help="The services to show: %(default)s", )
[docs] def create(): services = mgr.list() for service in my.options.services: service_name = f"dev_{service}" if my.development else service if service_name in services: if my.options.force: mgr.delete(service_name) else: print( f"The service '{service_name}' already exists! Use --force to " "recreate the service from scratch." ) continue # Proceed to creating the service. exe_path = shutil.which(f"seamm-{service}") if exe_path is None: exe_path = shutil.which(service) if exe_path is None: print(f"Could not find seamm-{service} or {service}. Is it installed?") print() continue root = "~/SEAMM_DEV" if my.development else "~/SEAMM" stderr_path = Path(f"{my.options.root}/logs/{service}.out").expanduser() stdout_path = Path(f"{my.options.root}/logs/{service}.out").expanduser() if service == "dashboard": mgr.create( service_name, exe_path, "--root", root, "--port", my.options.port, "--dashboard-name", my.options.dashboard_name, stderr_path=str(stderr_path), stdout_path=str(stdout_path), ) else: mgr.create( service_name, exe_path, "--root", root, "JobServer", "--no-windows", stderr_path=str(stderr_path), stdout_path=str(stdout_path), ) # And start it up mgr.start(service_name) print(f"Created and started the service {service_name}")
[docs] def delete(): for service in my.options.services: service_name = f"dev_{service}" if my.development else service mgr.delete(service_name) print(f"The service {service_name} was deleted.")
[docs] def restart(): for service in my.options.services: service_name = f"dev_{service}" if my.development else service try: mgr.restart(service_name) except RuntimeError as e: print(e.text) except NotImplementedError as e: print(e.text) else: print(f"The service '{service_name}' was restarted.")
[docs] def show(): services = mgr.list() table = [] for development in [False, True] if my.options.all else [my.development]: for service in my.options.services: service_name = f"dev_{service}" if development else service if service_name in services: path = mgr.file_path(service_name) if path.is_relative_to(Path.home()): path = path.relative_to(Path.home()) table.append((service_name, "~/" + str(path))) else: table.append((service_name, str(path))) else: table.append((service_name, "not found")) if len(table) == 0: print("Found no services.") else: print(tabulate(table, ("Service", "Path"), tablefmt="fancy_grid"))
[docs] def start(): for service in my.options.services: service = f"dev_{service}" if my.development else service if mgr.is_running(service): print(f"The service '{service}' was already running.") else: try: mgr.start(service) except RuntimeError as e: print(e.text) except NotImplementedError as e: print(e.text) else: print(f"The service '{service}' has been started.")
[docs] def status(): services = mgr.list() table = [] for development in [False, True] if my.options.all else [my.development]: for service in my.options.services: service = f"dev_{service}" if development else service if service in services: status = mgr.status(service) row = [ service, "running" if status["running"] else "not running", "---" if status["root"] is None else status["root"], "---" if status["port"] is None else status["port"], ( "---" if status["dashboard name"] is None else status["dashboard name"] ), ] else: row = [service, "not created"] table.append(row) print( tabulate( table, ("Service", "Status", "Root", "Port", "Name"), tablefmt="fancy_grid", ) )
[docs] def stop(): for service in my.options.services: service_name = f"dev_{service}" if my.development else service if mgr.is_running(service_name): try: mgr.stop(service_name) except RuntimeError as e: print(e.text) except NotImplementedError as e: print(e.text) else: print(f"The service '{service_name}' has been stopped.") else: print(f"The service '{service_name}' was not running.")