0

I'm trying to create a custom network management service for a CentOS 7 netboot image. The service gets a list of all interfaces on the host, finds one with a physical connection, and then uses it to pull the DHCP configuration.

The problem is making sure that it starts after all the network devices exist on the system, so it can get a list of them. Here's my unit file:

[Unit]
Description=Configure networking
Wants=network.target
After=network-pre.target
Before=network.target multi-user.target

[Service]
ExecStart=/usr/local/bin/netboot-cfg
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

As you can see, it runs after the network-pre target, and before the network target. I confirmed this with systemd-analyze plot. However, it's unable to find any interfaces on the system at that point in the boot process. The list is created by looking at the /sys/class/net directory. The sys-subsystem-net-devices-<iface>.device units are started later, which I'm guessing populate that directory.

It seems strange to me that the network device units start after network.target.

So the question is: How can I reliably determine when all the interfaces will be available, using systemd unit file syntax?

  • 1
    Systemd is not flexible enough to do this. You need to modify the network manager's startup scripts to run your script. The other option is to use network-online.target, but that presumes that at least one interface came up with an address. This explains the problem Freedesktop NetworkTarget. – Andrew Domaszek Mar 27 '17 at 20:15
  • The interfaces exist as soon as Linux has loaded their drivers, which generally happens as the kernel boots. I would suggest that you need to revisit how your script looks for interfaces. – Michael Hampton Mar 27 '17 at 22:51
  • @MichaelHampton I'm using the netifaces Python module, which wraps a C library that calls getifaceaddrs. Is there something lower level than getifaddrs that I should be using? Will it even work if sysfs hasn't been populated yet? – orodbhen Mar 28 '17 at 17:47
  • @AndrewDomaszek I think you may be right, in that there appears to be no way to do this using systemd. Probably the simplest solution is to poll until getifaddrs returns a usable interface. One would think there would be a target after which sysfs is definitely populated, though. – orodbhen Mar 28 '17 at 18:15
1

it seems strange to me that the network device units start after network.target.

So the question is: How can I reliably determine when all the interfaces will be available, using systemd unit file syntax?

Parts of this question are answered by this Unix SE thread.

Basically, per the documentation for network.target:

  • network.target guarantees only that the network stack is up:

    only indicates that the network management stack is up after it has been reached. Whether any network interfaces are already configured when it is reached is undefined.

  • network-online.target

    is a target that actively waits until the nework is "up", where the definition of "up" is defined by the network management software. Usually it indicates a configured, routable IP address of some kind.

So you may want to adjust your requirements to reflect this: I think you might want to run your script After=network.target, but Before=network-online.target.

  • I'll give that a try. I put my service before network.target because that's what the built-in network management services do. However, perhaps they don't need the interfaces to exist yet before starting. – orodbhen Mar 28 '17 at 9:33
  • Ok, I tried putting it after network.target and before network-online.target, and it made no difference. Still no interfaces at that point in the boot process. So it doesn't seem like network.target really means anything. Something's adding the interfaces, because they're there later. – orodbhen Mar 28 '17 at 17:39
  • Hmmm..... Yeah, the docs sort of seemed vague about that. Maybe PartOf=network-online.target, and Before=NetworkManager.service? Although thinking about this a little more, I would sort of wonder if you couldn't just run after network-online, and deal with physically up interfaces without IPs? – iwaseatenbyagrue Mar 28 '17 at 17:48
  • I'm thinking that network.target only means that a network management server has finished starting that has Wants=network.target in its unit file. So it's all up to the management service to make sure the stack is actually up. It seems from this that sysfs is populated by the kernel, not a user-space service. But udev must jump in somewhere to name the interfaces. So this may not be doable with systemd alone. I may just need to poll until I find a usable interface. – orodbhen Mar 28 '17 at 18:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.