feat: list systemd services in one round trip and control them, once for every driver
Listing a host's services and starting or stopping one is the same on every host that runs systemd, so the command, its parse, the check of a unit name and the reading of an action's exit status live here once, and a driver supplies only the transport (napalm-linux#7, napalm-proxmox#6): - SYSTEMD_SERVICES_COMMAND: one read-only POSIX sh line. list-unit-files, then one systemctl show over every loaded service unit (Id, Names, LoadState, ActiveState, SubState, UnitFileState, MainPID), and is-enabled only for generated units, whose boot state lives in a SysV script's rc links. Framed; [no-systemd] when /run/systemd/system is missing. Replaces an is-enabled and a show per unit: 0.8 s instead of 6 s on a 180-unit Ubuntu host. - parse_systemd_services(): loaded units except not-found, plus installed unit files that are not loaded; no templates, no aliases (also not the ones older systemd lists as "enabled"). enabled = UnitFileState enabled or enabled-runtime, read from systemctl show and never from list-unit-files' second column, which has had a preset column after it since systemd 245. A report whose end is missing raises ValueError, so a list cut short never reads as services that went away; a host without systemd raises SystemdUnavailable, a NotImplementedError, so a driver can fall back. - unit_name() / service_action_command() / parse_action_result(): template instances, dots, colons and \xHH escapes accepted; a bare template, a leading "-" and anything a shell reads refused. The action runs as "timeout 45 systemctl --no-ask-password <action> -- <unit>.service" with its exit status printed after it; only that status decides, 124 is not called done, and terminal colour codes are dropped. The marker also keeps the output from ever being empty, which a transport that retries on an empty answer would take as a reason to run the action twice. - SystemdServicesMixin, in the template form: get_services() and manage_service() are concrete, _run_service_command(command, *, privileged, timeout) is the driver's hook. Mixed in by the drivers whose host runs systemd, not by OSDriver. Version 2.2.0.
This commit is contained in:
@@ -79,6 +79,15 @@ everywhere, so the command and its parse are concrete here and a driver supplies
|
||||
`_run_kernel_facts_command`. `OSDriver` does not carry it — a Windows host is an OS driver
|
||||
too, and `hasattr(driver, "get_kernel_facts")` has to stay truthful.
|
||||
|
||||
`SystemdServicesMixin` (`get_services`, `manage_service`) is mixed in the same way, by
|
||||
the drivers whose host runs systemd. Listing the services, checking a unit name and
|
||||
reading an action's exit status are the same on every such host, so they are concrete
|
||||
here, and a driver supplies only `_run_service_command(command, *, privileged, timeout)`
|
||||
— how a command reaches its host and how it gains root there. The listing is one round
|
||||
trip (`list-unit-files` plus one `systemctl show` over every loaded unit) instead of an
|
||||
`is-enabled` and a `show` per unit. A host without systemd raises `SystemdUnavailable`,
|
||||
a `NotImplementedError`, so a driver can fall back to another init system.
|
||||
|
||||
A function class may use the **template form** — public method concrete, the
|
||||
device-specific part a `_hook` declared under `if TYPE_CHECKING` — *when the base
|
||||
genuinely does work* on the result: normalising, sorting, validating, or orchestrating
|
||||
|
||||
Reference in New Issue
Block a user