"""Generic service status fetcher using systemctl""" import subprocess from typing import List from selfprivacy_api.models.services import ServiceStatus def get_service_status(unit: str) -> ServiceStatus: """ Return service status from systemd. Use systemctl show to get the status of a service. Get ActiveState from the output. """ service_status = subprocess.check_output(["systemctl", "show", unit]) if b"LoadState=not-found" in service_status: return ServiceStatus.OFF if b"ActiveState=active" in service_status: return ServiceStatus.ACTIVE if b"ActiveState=inactive" in service_status: return ServiceStatus.INACTIVE if b"ActiveState=activating" in service_status: return ServiceStatus.ACTIVATING if b"ActiveState=deactivating" in service_status: return ServiceStatus.DEACTIVATING if b"ActiveState=failed" in service_status: return ServiceStatus.FAILED if b"ActiveState=reloading" in service_status: return ServiceStatus.RELOADING return ServiceStatus.OFF def get_service_status_from_several_units(services: list[str]) -> ServiceStatus: """ Fetch all service statuses for all services and return the worst status. Statuses from worst to best: - OFF - FAILED - RELOADING - ACTIVATING - DEACTIVATING - INACTIVE - ACTIVE """ service_statuses = [] for service in services: service_statuses.append(get_service_status(service)) if ServiceStatus.OFF in service_statuses: return ServiceStatus.OFF if ServiceStatus.FAILED in service_statuses: return ServiceStatus.FAILED if ServiceStatus.RELOADING in service_statuses: return ServiceStatus.RELOADING if ServiceStatus.ACTIVATING in service_statuses: return ServiceStatus.ACTIVATING if ServiceStatus.DEACTIVATING in service_statuses: return ServiceStatus.DEACTIVATING if ServiceStatus.INACTIVE in service_statuses: return ServiceStatus.INACTIVE if ServiceStatus.ACTIVE in service_statuses: return ServiceStatus.ACTIVE return ServiceStatus.OFF def get_last_log_lines(service: str, lines_count: int) -> List[str]: if lines_count < 1: raise ValueError("lines_count must be greater than 0") try: logs = subprocess.check_output( [ "journalctl", "-u", service, "-n", str(lines_count), "-o", "cat", ], shell=False, ).decode("utf-8") return logs.splitlines() except subprocess.CalledProcessError: return []