From 73bbffe88801c40b344b5cf794cbc78b390be458 Mon Sep 17 00:00:00 2001 From: Tom Keffer Date: Wed, 28 Dec 2022 15:05:46 -0800 Subject: [PATCH] Implement `weectl daemon install --type=systemd` --- bin/wee_resources/util/__init__.py | 0 bin/weecfg/daemon_config.py | 68 +++++++++++++++++++++++++++++- bin/weectllib/parse_daemon.py | 22 ++++++++-- 3 files changed, 85 insertions(+), 5 deletions(-) delete mode 100644 bin/wee_resources/util/__init__.py diff --git a/bin/wee_resources/util/__init__.py b/bin/wee_resources/util/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/bin/weecfg/daemon_config.py b/bin/weecfg/daemon_config.py index 09e69fea..c3951c04 100644 --- a/bin/weecfg/daemon_config.py +++ b/bin/weecfg/daemon_config.py @@ -5,13 +5,77 @@ # """Install or uninstall files necessary to run as a daemon""" +import importlib.resources +import os.path -def daemon_install(daemon_type=None): +import weecfg +from weeutil.weeutil import bcolors + + +def daemon_install(daemon_type, config_path=None, user=None, weewxd_path=None, daemon_dir=None): """Install the daemon files. Args: - daemon_type(str): The type of daemon file. Can be either 'sysv' or 'systemd'. + daemon_type(str): The type of daemon file. Can be either 'sysv' or 'systemd'. Required. + config_path(str): Path to the weewx configuration file. Default is to find it in + the "usual places." + user(str): The user to run as. Default is 'root' + weewxd_path(str): Path to the weewxd executable. Default is to figure it out. + daemon_dir(str): The directory into which the finished daemon file should be put. If + not given, it will be determined on the basis of daemon_type. """ + config_path, config_dict = weecfg.read_config(config_path) + + print(f"The configuration file {bcolors.BOLD}{config_path}{bcolors.ENDC} will be used.") + + if not weewxd_path: + # Find it by importing weewxd.py + import weewxd + weewxd_path = weewxd.__file__ + + if daemon_type == 'systemd': + install_systemd(config_path=config_path, + user=user, + weewxd_path=weewxd_path, + daemon_dir=daemon_dir) + elif daemon_type == 'sysv': + """To appear""" + else: + raise ValueError(f"Unknown daemon type: {daemon_type}") + + +def install_systemd(config_path=None, user=None, weewxd_path=None, daemon_dir=None): + """Install a systemd file.""" + + service_file_name = 'weewx.service' + + # Get the systemd template from package resources. + with importlib.resources.path('wee_resources', 'util') as util_path: + systemd_template_path = os.path.join(util_path, 'systemd', service_file_name) + # Read it all in. + with open(systemd_template_path, 'rt') as fd: + in_lines = fd.readlines() + + # Process it line by line, making any necessary substitutions + out_lines = [] + for line in in_lines: + if '=' in line: + key, value = line.split('=') + if user and 'User' in key: + line = f'User={user}\n' + elif 'ExecStart' in key: + line = f'ExecStart={weewxd_path} {config_path}\n' + out_lines.append(line) + + # Figure out where the finished systemd file will go. + if not daemon_dir: + # No idea if this is true of all systemd systems. Probably not. + daemon_dir = '/etc/systemd/system' + target_path = os.path.join(daemon_dir, service_file_name) + + with open(target_path, 'w') as outd: + outd.writelines(out_lines) + print(f"Systemd file written to {bcolors.BOLD}{target_path}{bcolors.ENDC}") def daemon_uninstall(daemon_type=None): diff --git a/bin/weectllib/parse_daemon.py b/bin/weectllib/parse_daemon.py index b6b3336d..dba028c8 100644 --- a/bin/weectllib/parse_daemon.py +++ b/bin/weectllib/parse_daemon.py @@ -8,7 +8,8 @@ import weecfg.daemon_config from weeutil.weeutil import bcolors daemon_install_usage = f"""{bcolors.BOLD}weectl daemon install --type={{sysv|systemd}} - [--config=CONFIG-PATH]{bcolors.ENDC}""" + [--config=CONFIG-PATH] [--user=USER] + [--weewxd-path=WEEWXD-PATH] [-daemon-dir=DAEMON-DIR] {bcolors.ENDC}""" daemon_uninstall_usage = f"""{bcolors.BOLD}weectl daemon uninstall --type={{sysv|systemd}} [--config=CONFIG-PATH]{bcolors.ENDC}""" @@ -40,7 +41,18 @@ def add_subparser(subparsers): dest="daemon_type", required=True, help="Type of file to install. Required.") - + daemon_install_parser.add_argument('--config', + metavar='CONFIG-PATH', + help=f'Path to configuration file. ' + f'Default is "{weecfg.default_config_path}".') + daemon_install_parser.add_argument('--user', + help='Run as USER. If not given, "root" will be used.') + daemon_install_parser.add_argument('--weewxd-path', + help='Path to the weewxd.py file. If not given, it will ' + 'be inferred') + daemon_install_parser.add_argument('--daemon-dir', + help='Path to the directory in which the finished daemon ' + 'file should be put.') daemon_install_parser.set_defaults(func=daemon_install) # ---------- Action 'uninstall' ---------- @@ -60,7 +72,11 @@ def add_subparser(subparsers): def daemon_install(namespace): - weecfg.daemon_config.daemon_install(namespace.daemon_type) + weecfg.daemon_config.daemon_install(namespace.daemon_type, + config_path=namespace.config, + user=namespace.user, + weewxd_path=namespace.weewxd_path, + daemon_dir=namespace.daemon_dir) def daemon_uninstall(namespace):