mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-10-31 04:01:59 +01:00
feat: implement plugin manager service bootstrap and add tests
This commit is contained in:
1 parent
b65e54196b
commit
3afec59c1a
3 files changed
+148
No files matched your search
@@ -291,6 +291,17 @@ class RepeaterDaemon:
|
||||
|
||||
logger.info(f"Initializing repeater: {self.config['repeater']['node_name']}")
|
||||
|
||||
try:
|
||||
from repeater.service_utils import ensure_plugin_manager_service
|
||||
|
||||
ok, msg = ensure_plugin_manager_service()
|
||||
if ok:
|
||||
logger.info("Plugin-manager bootstrap: %s", msg)
|
||||
else:
|
||||
logger.warning("Plugin-manager bootstrap: %s", msg)
|
||||
except Exception as exc: # pragma: no cover - defensive safeguard
|
||||
logger.warning("Plugin-manager bootstrap check raised an exception: %s", exc)
|
||||
|
||||
# -----------------------------------------------
|
||||
# Get the actual Network IP Address
|
||||
try:
|
||||
|
||||
@@ -96,6 +96,123 @@ def get_container_restart_message() -> str:
|
||||
)
|
||||
|
||||
|
||||
def ensure_plugin_manager_service() -> Tuple[bool, str]:
|
||||
"""Ensure the packaged plugin-manager systemd unit is installed and running.
|
||||
|
||||
This is intentionally idempotent and root-only. It is safe to run during
|
||||
startup and after upgrades so a single upgrade can heal older installs that
|
||||
pre-date the plugin-manager system service.
|
||||
"""
|
||||
if is_container() or is_buildroot():
|
||||
return True, "Plugin-manager bootstrap skipped in container/buildroot environment"
|
||||
|
||||
if os.geteuid() != 0:
|
||||
logger.info(
|
||||
"Plugin-manager bootstrap skipped: root privileges required for systemd provisioning"
|
||||
)
|
||||
return (
|
||||
True,
|
||||
"Plugin-manager bootstrap skipped: root privileges required for systemd provisioning",
|
||||
)
|
||||
|
||||
venv_python = "/opt/openhop_repeater/venv/bin/python"
|
||||
if not os.path.isfile(venv_python):
|
||||
return False, "Plugin-manager bootstrap skipped: venv not present"
|
||||
|
||||
package_unit = None
|
||||
code = """
|
||||
from importlib.metadata import distribution
|
||||
from pathlib import Path
|
||||
import sys
|
||||
try:
|
||||
dist = distribution('openhop_repeater')
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
try:
|
||||
path = Path(dist.locate_file('repeater/plugins/openhop-plugin-manager.service'))
|
||||
except Exception:
|
||||
sys.exit(1)
|
||||
if path.is_file():
|
||||
print(path)
|
||||
sys.exit(0)
|
||||
sys.exit(1)
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[venv_python, "-I", "-c", code],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=20,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
package_unit = result.stdout.strip().splitlines()[-1]
|
||||
except (OSError, subprocess.TimeoutExpired) as exc:
|
||||
logger.warning("Plugin-manager bootstrap lookup failed: %s", exc)
|
||||
return False, f"Plugin-manager bootstrap lookup failed: {exc}"
|
||||
|
||||
if not package_unit:
|
||||
return (
|
||||
False,
|
||||
"Plugin-manager bootstrap skipped: packaged service not found in installed package",
|
||||
)
|
||||
|
||||
unit_path = "/etc/systemd/system/openhop-plugin-manager.service"
|
||||
changed = False
|
||||
try:
|
||||
if not os.path.exists(unit_path):
|
||||
logger.info("Plugin-manager unit missing; installing packaged service")
|
||||
changed = True
|
||||
else:
|
||||
with open(package_unit, "rb") as src, open(unit_path, "rb") as dst:
|
||||
if src.read() != dst.read():
|
||||
logger.info("Plugin-manager unit differs from packaged version; updating")
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
shutil.copy2(package_unit, unit_path)
|
||||
subprocess.run(
|
||||
[_SYSTEMCTL_BIN, "daemon-reload"], check=False, capture_output=True, text=True
|
||||
)
|
||||
logger.info("Plugin-manager unit installed or refreshed")
|
||||
else:
|
||||
logger.info("Plugin-manager unit already matches packaged version")
|
||||
|
||||
subprocess.run(
|
||||
[_SYSTEMCTL_BIN, "enable", "openhop-plugin-manager"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
active = subprocess.run(
|
||||
[_SYSTEMCTL_BIN, "is-active", "--quiet", "openhop-plugin-manager"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if active.returncode != 0:
|
||||
logger.info("Starting plugin-manager service")
|
||||
subprocess.run(
|
||||
[_SYSTEMCTL_BIN, "start", "openhop-plugin-manager"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
elif changed:
|
||||
logger.info("Restarting plugin-manager service after unit refresh")
|
||||
subprocess.run(
|
||||
[_SYSTEMCTL_BIN, "restart", "openhop-plugin-manager"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
return True, "Plugin-manager service is installed and active"
|
||||
except Exception as exc:
|
||||
logger.warning("Plugin-manager bootstrap failed: %s", exc)
|
||||
return False, f"Plugin-manager bootstrap failed: {exc}"
|
||||
|
||||
|
||||
def restart_service() -> Tuple[bool, str]:
|
||||
"""
|
||||
Restart the openhop-repeater service.
|
||||
|
||||
Reference in new issue
Block a user