systemd bug: systemd-tmpfiles-setup.service fails with unknown user “systemd-network”

I had a strange error after updating “systemd” on one of my Opensuse server systems from version 228.41.1 to version 228.44.1. This update seems harmless, but it is not. With it substantial changes appear in the file /usr/lib/tmpfiles.d/systemd.conf. Especially the lines:

d /run/systemd/netif 0755 systemd-network systemd-network -
d /run/systemd/netif/links 0755 systemd-network systemd-network -
d /run/systemd/netif/leases 0755 systemd-network systemd-network -
</p>

In my case this lead to trouble – service “systemd-tmpfiles-setup.service” started to fail :

# systemctl status -l systemd-tmpfiles-setup
● systemd-tmpfiles-setup.service - Create Volatile Files and Directories
   Loaded: loaded (/lib/systemd/system/systemd-tmpfiles-setup.service; static)
   Active: failed (Result: exit-code) .....
...
...
Mar 12 11:33:32 myserv systemd-tmpfiles[509]: [/usr/lib/tmpfiles.d/systemd.conf:19] Unknown user 'systemd-network'.

I checked whether user “systemd-network” existed with YaST. Yes, it was there – with all its default details.
However the command

getent passwd systemd-network

did not give me anything!

It took me a bit to find out what had happened. On this server I had once experimented with NIS, NISplus. The “/etc/passwd”-file still contained a line

+::::::

The “/etc/group”-file had a corresponding “+:::”. However, no active NIS server is any longer defined. Should not matter as long as the file have a correct format, i.e. as long as the NIS-lines are placed at the bottom of the files …

But:
At some point in time (?) systemd had created the user “systemd-network” and a corresponding group. Unfortunately, both entries were dumbly added at the end of the files “/etc/passwd” and “/etc/group” – i.e. after the already existing NIS-lines.

systemd-timesync:x:478:478:systemd Time Synchronization:/:/sbin/nologin
+::::::
systemd-network:x:475:475:systemd Network Management:/:/sbin/nologin

Not funny! Because, this in turn became the cause for the empty “getent”-answer!

However, it seems that systemd now uses “getent” to check the existence of some special systemd-users like “systemd-network” as a requirement for starting certain services. Which then leads to errors …

Summary
“systemd” seems to add new user- and group-entries at the bottom of the files “/etc/passwd” and “/etc/group” – without checking for NIS lines. Or it at least did at some point in the past. This may prevent the start of some initial services for which the existence of user or group entries are checked.

So, if you run across a similar problem check your “passwd” and “group” files for wrong entries at the end of the file! Move the NIS lines to the very bottom of the files. Afterward “getent” will work again for all user entries – and your failed services hopefully will start again.

Note: If you still get errors for “unknown systemd-users” you have to check whether entries for all the required users really exist in “/etc/passwd”.

P.S.: The stupid thing on Opensuse is that YaST shows you the required users with passwd-entries below a NIS line as existing, whereas “getent” does not.

Linux-Namensgebung für physikalische Netzwerk-Devices

Opensuse nutzt ja seit längerem “systemd”. Zwei der größten Veränderungen, die damit einhergingen, war die intensive Nutzung von “udev” durch “systemd” im Rahmen des Systemstarts und eine resultierende Veränderung der Namensgebung für physikalische Devices – u.a. Netzwerkdevices. Alles unter dem Schlagwort “predictable device names”.

Einen großen Einfluss hatte das u.a. auf Netzwerk-Devices: An die Stelle der alten NIC-Bezeichnungen “eth0”, “eth1”, etc. traten dann auf meinem Desktop-System z.B. so illustre Ausdrücke wie “enp8s0”, “enp9s0” oder noch komplexere Namen.

Aus den netzwerk-bezogenen “udev”-Regeln in den Dateien unter “/lib/udev/rules.d” alleine konnte ich mir bislang nicht erklären, wie es zur Festlegung der Device-Namen kam. “Die “udev”-Regeln betreffen ja etliche unterschiedliche Identifikations-Bezeichnungen. Ich hatte die Namensvergabe daher bislang einfach als Ergebnis einer für mich nicht nachvollziehbaren “udev/systemd”-Logik abgetan.

In der Auseinandersetzung mit virtuellen Bridges bin ich jedoch wieder über das Thema und inzwischen auch über zwei Artikel gestolpert, die das Ganze erklären. Ich möchte an dieser Stelle gerne auf die betreffenden Artikel hinweisen:

Der erste lesenswerte Artikel stammt von Major Hayden, der der Sache mal nachgegangen ist:
https://major.io/2015/08/21/understanding-systemds-predictable-network-device-names/

Besonders hilfreich fand ich in dem zitierten Artikel den Auszug aus “src/udev/udev-builtin-net_id.c”, der einem hilft eine Zugang zu einer Namensvergabe wie “enp8s0” zu finden:

  
 * Two character prefixes based on the type of interface:
 *   en -- ethernet
 *   sl -- serial line IP (slip)
 *   wl -- wlan
 *   ww -- wwan
 *
 * Type of names:
 *   b<number>                             -- BCMA bus core number
 *   ccw<name>                             -- CCW bus group name
 *   o<index>[d<dev_port>]                 -- on-board device index number
 *   s<slot>[f<function>][d<dev_port>]     -- hotplug slot index number
 *   x<MAC>                                -- MAC address
 *   [P<domain>]p<bus>s<slot>[f<function>][d<dev_port>]
 *                                         -- PCI geographical location
 *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
 *                                         -- USB port number chain

 
Der zweite Artikel betrifft die Regeln, nach denen “systemd” verschiedene Varianten der Namensgebung bis zu einer endgültigen Entscheidung für ein Netzwerk-Device durchexerziert:

http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

Ich zitiere aus dem Artikel:

  
The following different naming schemes for network interfaces are now supported by udev natively:

    Names incorporating Firmware/BIOS provided index numbers for on-board devices (example: eno1)
    Names incorporating Firmware/BIOS provided PCI Express hotplug slot index numbers (example: ens1)
    Names incorporating physical/geographical location of the connector of the hardware (example: enp2s0)
    Names incorporating the interfaces's MAC address (example: enx78e7d1ea46da)
    Classic, unpredictable kernel-native ethX naming (example: eth0)

By default, systemd v197 will now name interfaces following policy 1) if that 
information from the firmware is applicable and available, falling back to 2) if that information from the firmware is applicable and available, falling back to 3) if applicable, falling back to 5) in all other cases. Policy 4) is not used by default, but is available if the user chooses so. 

 
Aha – das kann ich nachvollziehen.

Wer sich mit diesem Wissen ausgestattet auch mal ansehen will, was “udev” auf einem System alles an Definitionen für gefundene Netzwerk-Devices hinterlegt, nutze das Kommando

“udevadm info -e”

mit Filtern. Auf meinem Desktop-System etwa finde ich:

   
mytux:~ # udevadm info -e | grep net            
E: ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard)
E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller
P: /devices/pci0000:00/0000:00:1c.4/0000:08:00.0/net/enp8s0
E: DEVPATH=/devices/pci0000:00/0000:00:1c.4/0000:08:00.0/net/enp8s0
E: ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard)
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/enp8s0 /sys/subsystem/net/devices/enp8s0

E: ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard)
E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller
P: /devices/pci0000:00/0000:00:1c.5/0000:09:00.0/net/enp9s0
E: DEVPATH=/devices/pci0000:00/0000:00:1c.5/0000:09:00.0/net/enp9s0
E: ID_MODEL_FROM_DATABASE=RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (Motherboard)
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_PCI_SUBCLASS_FROM_DATABASE=Ethernet controller
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/enp9s0 /sys/subsystem/net/devices/enp9s0

P: /devices/virtual/misc/network_latency
N: network_latency
E: DEVNAME=/dev/network_latency
E: DEVPATH=/devices/virtual/misc/network_latency
P: /devices/virtual/misc/network_throughput
N: network_throughput
E: DEVNAME=/dev/network_throughput
E: DEVPATH=/devices/virtual/misc/network_throughput
N: net/tun
E: DEVNAME=/dev/net/tun

P: /devices/virtual/net/br0
E: DEVPATH=/devices/virtual/net/br0
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/br0

P: /devices/virtual/net/lo
E: DEVPATH=/devices/virtual/net/lo
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net

P: /devices/virtual/net/virbr0
E: DEVPATH=/devices/virtual/net/virbr0
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/virbr0

P: /devices/virtual/net/virbr0-nic
E: DEVPATH=/devices/virtual/net/virbr0-nic
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/virbr0-nic

P: /devices/virtual/net/virbr1
E: DEVPATH=/devices/virtual/net/virbr1
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/virbr1

P: /devices/virtual/net/virbr1-nic
E: DEVPATH=/devices/virtual/net/virbr1-nic
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/virbr1-nic

P: /devices/virtual/net/vmnet0
E: DEVPATH=/devices/virtual/net/vmnet0
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: INTERFACE=vmnet0
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/vmnet0

P: /devices/virtual/net/vmnet1
E: DEVPATH=/devices/virtual/net/vmnet1
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
nE: INTERFACE=vmnet1
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/vmnet1

P: /devices/virtual/net/vmnet2
E: DEVPATH=/devices/virtual/net/vmnet2
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: INTERFACE=vmnet2
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/vmnet2

 
(Der erfahrene Leser erkennt, dass hier neben physikalischen Devices qemu-Bridges und auch VMware-Bridges aktiv sind. Für entsprechende Devices werden im Zusammenspiel mit den Generatoren der Virtualisierungs-Tools offenbar Standardnamen vergeben, da eindeutige Vendor- oder “geographische” Bus-Bezeichnungen nicht ermittelbar sind.)

Mein Dank gilt den Verfassern der oben genannten Artikel, die zumindest bei mir eine Verständnislücke geschlossen haben.