image-info: Add workaround for listing services by status

`image-info` tools parses output of `systemctl list-unit-files` run on a
different tree (with `--root` option), to determine the list of enabled
and disabled services on the inspected image. However since Fedora 33
(and presumably since systemd v246), the output of `systemctl
list-unit-files` changed. Some units previously reported as "enabled" or
"disabled" are now reported as "alias", which means, that they are just
a symlink to a different unit.

There is no systemd command, that would take an "alias" unit and would
report its state as "enabled" or "disabled" and could run on a different
tree (with "--root" option).

To make the list of reported services in the given state consistent on
systems with older and new (v246+) systemd version, check all "alias"
units and append them to the list of services with a specific status,
if their target is also listed in in the list.

Example of the `systemctl list-unit-files` output change:

~]# rpm -q systemd
systemd-246.6-3.fc33.x86_64
~]# systemctl list-unit-files ctrl-alt-del.target
UNIT FILE           STATE VENDOR PRESET
ctrl-alt-del.target alias -

~]# rpm -q systemd
systemd-245.8-2.fc32.x86_64
~]# systemctl list-unit-files ctrl-alt-del.target
UNIT FILE           STATE   VENDOR PRESET
ctrl-alt-del.target enabled disabled

This change makes it possible to produce consistent output for an
inspected image, regardless if the `image-info` tool is run on Fedora
32, Fedora 33 or RHEL-8.

Also regenerate all Fedora 33 test cases, since this commit changes the
content of produced list of enabled / disabled services since Fedora 33.
The list is now consistent with what would be produced by `image-info`
for an image on older Fedora (e.g. 32) or RHEL-8.

Signed-off-by: Tomas Hozza <thozza@redhat.com>
This commit is contained in:
Tomas Hozza 2021-01-28 18:03:50 +01:00 committed by Ondřej Budai
parent 9b7fb4fb63
commit 1a3cbb282a
9 changed files with 137 additions and 8 deletions

View file

@ -9817,12 +9817,12 @@
"version": "5.8.15-301.fc33.aarch64" "version": "5.8.15-301.fc33.aarch64"
} }
], ],
"default-target": "graphical.target",
"firewall-enabled": [ "firewall-enabled": [
"ssh", "ssh",
"mdns", "mdns",
"dhcpv6-client" "dhcpv6-client"
], ],
"default-target": "graphical.target",
"fstab": [ "fstab": [
[ [
"UUID=46BB-8120", "UUID=46BB-8120",
@ -10372,6 +10372,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -10397,9 +10398,16 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.fedoraproject.FirewallD1.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"firewalld.service", "firewalld.service",
@ -10409,6 +10417,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -9396,12 +9396,12 @@
"version": "5.8.15-301.fc33.x86_64" "version": "5.8.15-301.fc33.x86_64"
} }
], ],
"default-target": "graphical.target",
"firewall-enabled": [ "firewall-enabled": [
"ssh", "ssh",
"mdns", "mdns",
"dhcpv6-client" "dhcpv6-client"
], ],
"default-target": "graphical.target",
"fstab": [ "fstab": [
[ [
"UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac", "UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac",
@ -9904,6 +9904,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -9929,9 +9930,16 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.fedoraproject.FirewallD1.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"firewalld.service", "firewalld.service",
@ -9941,6 +9949,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -11143,6 +11143,7 @@
"remote-cryptsetup.target", "remote-cryptsetup.target",
"rpm-ostree-bootstatus.service", "rpm-ostree-bootstatus.service",
"rpm-ostreed-automatic.timer", "rpm-ostreed-automatic.timer",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -11164,10 +11165,19 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"bluetooth.service", "bluetooth.service",
"chronyd.service", "chronyd.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.bluez.service",
"dbus-org.fedoraproject.FirewallD1.service",
"dbus-org.freedesktop.ModemManager1.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus-parsec.service", "dbus-parsec.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dm-event.socket", "dm-event.socket",
"firewalld.service", "firewalld.service",
@ -11190,6 +11200,7 @@
"remote-fs.target", "remote-fs.target",
"rngd.service", "rngd.service",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"systemd-homed.service", "systemd-homed.service",

View file

@ -9711,12 +9711,12 @@
"version": "5.8.15-301.fc33.x86_64" "version": "5.8.15-301.fc33.x86_64"
} }
], ],
"default-target": "graphical.target",
"firewall-enabled": [ "firewall-enabled": [
"ssh", "ssh",
"mdns", "mdns",
"dhcpv6-client" "dhcpv6-client"
], ],
"default-target": "graphical.target",
"fstab": [ "fstab": [
[ [
"UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac", "UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac",
@ -10235,6 +10235,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -10260,12 +10261,19 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-config.service", "cloud-config.service",
"cloud-final.service", "cloud-final.service",
"cloud-init-local.service", "cloud-init-local.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.fedoraproject.FirewallD1.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"firewalld.service", "firewalld.service",
@ -10276,6 +10284,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -9790,6 +9790,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -9815,12 +9816,18 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-config.service", "cloud-config.service",
"cloud-final.service", "cloud-final.service",
"cloud-init-local.service", "cloud-init-local.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"fstrim.timer", "fstrim.timer",
@ -9829,6 +9836,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -9892,6 +9892,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sssd-autofs.socket", "sssd-autofs.socket",
@ -9916,12 +9917,18 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-config.service", "cloud-config.service",
"cloud-final.service", "cloud-final.service",
"cloud-init-local.service", "cloud-init-local.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"fstrim.timer", "fstrim.timer",
@ -9930,6 +9937,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sshd.socket", "sshd.socket",

View file

@ -8997,12 +8997,12 @@
"version": "5.8.15-301.fc33.x86_64" "version": "5.8.15-301.fc33.x86_64"
} }
], ],
"default-target": "graphical.target",
"firewall-enabled": [ "firewall-enabled": [
"ssh", "ssh",
"mdns", "mdns",
"dhcpv6-client" "dhcpv6-client"
], ],
"default-target": "graphical.target",
"fstab": [ "fstab": [
[ [
"UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac", "UUID=76a22bf4-f153-4541-b6c7-0332c0dfaeac",
@ -9479,6 +9479,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -9504,8 +9505,15 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.fedoraproject.FirewallD1.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"firewalld.service", "firewalld.service",
@ -9515,6 +9523,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -9790,6 +9790,7 @@
"rdisc.service", "rdisc.service",
"rdma.service", "rdma.service",
"remote-cryptsetup.target", "remote-cryptsetup.target",
"runlevel0.target",
"serial-getty@.service", "serial-getty@.service",
"sshd-keygen@.service", "sshd-keygen@.service",
"sshd.socket", "sshd.socket",
@ -9815,12 +9816,18 @@
"NetworkManager-wait-online.service", "NetworkManager-wait-online.service",
"NetworkManager.service", "NetworkManager.service",
"auditd.service", "auditd.service",
"autovt@.service",
"chronyd.service", "chronyd.service",
"cloud-config.service", "cloud-config.service",
"cloud-final.service", "cloud-final.service",
"cloud-init-local.service", "cloud-init-local.service",
"cloud-init.service", "cloud-init.service",
"ctrl-alt-del.target",
"dbus-broker.service", "dbus-broker.service",
"dbus-org.freedesktop.home1.service",
"dbus-org.freedesktop.nm-dispatcher.service",
"dbus-org.freedesktop.resolve1.service",
"dbus.service",
"dbus.socket", "dbus.socket",
"dnf-makecache.timer", "dnf-makecache.timer",
"fstrim.timer", "fstrim.timer",
@ -9829,6 +9836,7 @@
"reboot.target", "reboot.target",
"remote-fs.target", "remote-fs.target",
"rpmdb-rebuild.service", "rpmdb-rebuild.service",
"runlevel6.target",
"selinux-autorelabel-mark.service", "selinux-autorelabel-mark.service",
"sshd.service", "sshd.service",
"sssd-kcm.socket", "sssd-kcm.socket",

View file

@ -134,9 +134,6 @@ def parse_unit_files(s, expected_state):
continue continue
r.append(unit) r.append(unit)
# deduplicate and sort
r = list(set(r))
r.sort()
return r return r
@ -265,8 +262,69 @@ def rpm_packages(tree, is_ostree):
return list(sorted(pkgs)) return list(sorted(pkgs))
@contextlib.contextmanager
def change_root(root):
real_root = os.open("/", os.O_RDONLY)
try:
os.chroot(root)
yield None
finally:
os.fchdir(real_root)
os.chroot(".")
os.close(real_root)
def read_services(tree, state): def read_services(tree, state):
return subprocess_check_output(["systemctl", f"--root={tree}", "list-unit-files"], (lambda s: parse_unit_files(s, state))) services_state = subprocess_check_output(["systemctl", f"--root={tree}", "list-unit-files"], (lambda s: parse_unit_files(s, state)))
# Since systemd v246, some services previously reported as "enabled" /
# "disabled" are now reported as "alias". There is no systemd command, that
# would take an "alias" unit and report its state as enabled/disabled
# and could run on a different tree (with "--root" option).
# To make the produced list of services in the given state consistent on
# pre/post v246 systemd versions, check all "alias" units and append them
# to the list, if their target is also listed in 'services_state'.
if state != "alias":
services_alias = subprocess_check_output(["systemctl", f"--root={tree}", "list-unit-files"], (lambda s: parse_unit_files(s, "alias")))
for alias in services_alias:
# The service may be in one of the following places (output of
# "systemd-analyze unit-paths", it should not change too often).
unit_paths = [
"/etc/systemd/system.control",
"/run/systemd/system.control",
"/run/systemd/transient",
"/run/systemd/generator.early",
"/etc/systemd/system",
"/run/systemd/system",
"/run/systemd/generator",
"/usr/local/lib/systemd/system",
"/usr/lib/systemd/system",
"/run/systemd/generator.late"
]
with change_root(tree):
for path in unit_paths:
unit_path = os.path.join(path, alias)
if os.path.exists(unit_path):
real_unit_path = os.path.realpath(unit_path)
# Skip the alias, if there was a symlink cycle.
# When symbolic link cycles occur, the returned path will
# be one member of the cycle, but no guarantee is made about
# which member that will be.
if os.path.islink(real_unit_path):
continue
# Append the alias unit to the list, if its target is
# already there.
if os.path.basename(real_unit_path) in services_state:
services_state.append(alias)
# deduplicate and sort
services_state = list(set(services_state))
services_state.sort()
return services_state
def read_default_target(tree): def read_default_target(tree):