[arch-projects] [netcfg] [PATCH 3/3] systemd: Replace netcfg.service with a generator in order to get proper dependencies

Thomas Bächler thomas at archlinux.org
Thu Oct 25 17:20:33 EDT 2012


Until now, netcfg might fail to start because it is started too early (this actually
happened to me quite regularly). To fix this, we need to make systemd aware of the
dependencies of a profile.

This commit adds a systemd generator that creates profiles with the names
   netcfg-profile-$PROFILE.service
on boot. The ugly part: You cannot permanently enable such a profile, as it is
generated during boot. To enable it, put it in NETWORKS=() - it will always be
loaded, unless netcfg-profiles.target is masked. The old netcfg.service has
been removed. This scheme does not support NETWORKS=(last) anymore, since we
cannot determine which units were manually started or stopped before.

If you add a new profile, you need to reload the systemd configuration so the
service file shows up. We should encourage people to use systemctl to start
and stop their profiles instead of netcfg.

While this scheme is less intuitive than netcfg at profilename.service, it
is the only way to provide proper dependencies during boot.

A note on backgrounding: All netcfg profiles are now started in parallel,
so backgrounding is unnecessary. However, due to the correct dependencies
in the units, everything should work fine.

Due to a bug in systemd's dependency resolution with devices, this patch
requires systemd v195 to work.
---
 Makefile                       |  4 +++
 config/netcfg                  |  5 +---
 systemd/netcfg-generator       | 59 ++++++++++++++++++++++++++++++++++++++++++
 systemd/netcfg-profiles.target |  2 ++
 systemd/netcfg.service         | 14 ----------
 5 files changed, 66 insertions(+), 18 deletions(-)
 create mode 100755 systemd/netcfg-generator
 create mode 100644 systemd/netcfg-profiles.target
 delete mode 100644 systemd/netcfg.service

diff --git a/Makefile b/Makefile
index bbada3f..009bca5 100644
--- a/Makefile
+++ b/Makefile
@@ -35,9 +35,13 @@ install: install-docs
 	    rc.d/net-auto-wireless \
 	    $(DESTDIR)/etc/rc.d/
 	install -d $(DESTDIR)/usr/lib/systemd/system
+	install -d $(DESTDIR)/usr/lib/systemd/system/multi-user.target.wants
 	install -m644 \
 	    systemd/*.service \
+	    systemd/*.target \
 	    $(DESTDIR)/usr/lib/systemd/system/
+	ln -sf /usr/lib/systemd/system/netcfg-profiles.target $(DESTDIR)/usr/lib/systemd/system/multi-user.target.wants/
+	install -Dm755 systemd/netcfg-generator /usr/lib/systemd/system-generators/netcfg-generator
 
 install-docs: docs
 	install -d $(DESTDIR)/usr/share/man/{man5,man8}
diff --git a/config/netcfg b/config/netcfg
index 59ee57c..d68d06f 100644
--- a/config/netcfg
+++ b/config/netcfg
@@ -1,9 +1,6 @@
 # Enable these netcfg profiles at boot time.
-#   - prefix an entry with a '@' to background its startup
-#   - set to 'last' to restore the profiles running at the last shutdown
-#   - set to 'menu' to present a menu (requires the dialog package)
 # Network profiles are found in /etc/network.d
-NETWORKS=(last)
+NETWORKS=()
 
 # Specify the name of your wired interface for net-auto-wired
 WIRED_INTERFACE="eth0"
diff --git a/systemd/netcfg-generator b/systemd/netcfg-generator
new file mode 100755
index 0000000..2e37873
--- /dev/null
+++ b/systemd/netcfg-generator
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+[[ -d $1 ]] || exit 1
+
+. /usr/lib/network/network
+
+write_template() {
+    local profile=$1; shift
+    cat << EOF
+[Unit]
+Description=Netcfg networking service for profile ${profile}
+SourcePath=${PROFILE_DIR}/${profile}
+Before=network.target
+Wants=network.target
+Conflicts=netcfg@${profile}.service
+EOF
+    (( $# )) && printf '%s\n' "$@"
+    cat << EOF
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/bin/netcfg check-iface ${profile}
+ExecStop=-/usr/bin/netcfg down ${profile}
+KillMode=none
+EOF
+}
+
+list_profiles | while read p; do
+    load_profile "${p}" || continue
+    systemd_devices=()
+    extra_deps=()
+    case ${CONNECTION} in
+        bond)
+            for iface in ${SLAVE_INTERFACES[*]}; do
+                systemd_devices+=(sys-subsystem-net-devices-${iface}.device)
+            done
+            ;;
+        bridge)
+            for iface in ${BRIDGE_INTERFACES[*]}; do
+                systemd_devices+=(sys-subsystem-net-devices-${iface}.device)
+            done
+            ;;
+        ethernet|pppoe|wireless)
+            systemd_devices+=(sys-subsystem-net-devices-${INTERFACE}.device)
+            ;;
+        vlan)
+            systemd_devices+=(sys-subsystem-net-devices-${VLAN_PHYS_DEV}.device)
+            ;;
+    esac
+    [[ ${#systemd_devices[@]} > 0 ]] && extra_deps+=("BindsTo=${systemd_devices[*]}" "After=${systemd_devices[*]}")
+    write_template "${p}" "${extra_deps[@]}" > "$1/netcfg-profile-${p}.service"
+done
+
+. /etc/conf.d/netcfg
+mkdir "$1/netcfg-profiles.target.wants"
+for p in "${NETWORKS[@]}"; do
+    [[ -f "$1/netcfg-profile-${p}.service" ]] && ln -s "$1/netcfg-profile-${p}.service" "$1/netcfg-profiles.target.wants/netcfg-profile-${p}.service"
+done
diff --git a/systemd/netcfg-profiles.target b/systemd/netcfg-profiles.target
new file mode 100644
index 0000000..54af553
--- /dev/null
+++ b/systemd/netcfg-profiles.target
@@ -0,0 +1,2 @@
+[Unit]
+Description=Netcfg network profiles
diff --git a/systemd/netcfg.service b/systemd/netcfg.service
deleted file mode 100644
index f400be0..0000000
--- a/systemd/netcfg.service
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description=Netcfg multi-profile daemon
-Before=network.target
-Wants=network.target
-
-[Service]
-Type=oneshot
-RemainAfterExit=yes
-ExecStart=/usr/bin/netcfg-daemon start
-ExecStop=/usr/bin/netcfg-daemon stop
-KillMode=none
-
-[Install]
-WantedBy=multi-user.target
-- 
1.8.0



More information about the arch-projects mailing list