[arch-projects] [netcfg] [PATCH 3/3] systemd: add alternative units with proper dependencies
Dave Reisner
d at falconindy.com
Wed Oct 24 19:01:49 EDT 2012
On Thu, Oct 25, 2012 at 12:27:41AM +0200, Thomas Bächler wrote:
> 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=() in
> /etc/conf.d/netcfg and run
> systemctl enable netcfg-profiles.target
> If you add a new profile, you need to reload the systemd configuration
> so the service file shows up.
>
> While this scheme is less intuitive than netcfg at profilename.service, it
> is the only way to provide proper dependencies during boot.
>
> Due to a bug in systemd's dependency resolution with devices, this patch
> requires systemd v195 to work.
> ---
> Makefile | 2 ++
> systemd/netcfg-generator | 58 ++++++++++++++++++++++++++++++++++++++++++
> systemd/netcfg-profiles.target | 5 ++++
> 3 files changed, 65 insertions(+)
> create mode 100755 systemd/netcfg-generator
> create mode 100644 systemd/netcfg-profiles.target
>
> diff --git a/Makefile b/Makefile
> index bbada3f..3a80c41 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -37,7 +37,9 @@ install: install-docs
> install -d $(DESTDIR)/usr/lib/systemd/system
> install -m644 \
> systemd/*.service \
> + systemd/*.target \
> $(DESTDIR)/usr/lib/systemd/system/
> + 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/systemd/netcfg-generator b/systemd/netcfg-generator
> new file mode 100755
> index 0000000..983dceb
> --- /dev/null
> +++ b/systemd/netcfg-generator
> @@ -0,0 +1,58 @@
> +#!/bin/bash
> +
> +[[ -d $1 ]] || exit 1
> +
> +. /usr/lib/network/network
> +
> +profile_tmpl_unit="[Unit]
> +Description=Netcfg networking service for profile @PROFILE@
> +SourcePath=/etc/network.d/@PROFILE@
> +Before=network.target
> +Wants=network.target"
> +
> +profile_tmpl_service="[Service]
> +Type=oneshot
> +RemainAfterExit=yes
> +ExecStart=/usr/bin/netcfg check-iface @PROFILE@
> +ExecStop=-/usr/bin/netcfg down @PROFILE@
> +KillMode=none"
> +
> +for pf in /etc/network.d/*; do
> + [[ -f ${pf} && -r ${pf} ]] || continue
> + p=${pf#/etc/network.d/}
I think you just want to use p=${pf##*/}.
> + load_profile ${p}
> + systemd_devices=
> + case ${CONNECTION} in
> + bond)
> + for iface in ${SLAVE_INTERFACES[@]}; do
> + systemd_devices="${systemd_devices}sys-subsystem-net-devices-${iface}.device "
Please use arrays for this...
systemd_devices+=(....)
> + done
> + ;;
> + bridge)
> + for iface in ${BRIDGE_INTERFACES[@]}; do
> + systemd_devices="${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=${systemd_devices% }
> + if [[ ${systemd_devices} ]]; then
> + bindsto="BindsTo=${systemd_devices}"
> + after="After=${systemd_devices}"
Array here too...
extra_deps+=("BindsTo=${systemd_devices[*]}" "After=${systemd_devices[*]}")
> + else
> + bindsto=
> + after=
> + fi
> + echo -e "${profile_tmpl_unit//@PROFILE@/$p}\n${bindsto}\n${after}\n\n${profile_tmpl_service//@PROFILE@/$p}" > $1/netcfg-profile-$p.service
This is dirty (and pretty much unreadable). I suggest using a function
along the lines of:
write_template() {
local profile=$1; shift
cat <<EOF
[Unit]
Description=Netcfg profile for $profile
SourcePath=/etc/network.d/$profile
Before=network.target
Wants=network.target
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
}
And then you can just do something like:
write_template "$1" "${extra_deps[@]}" >"$1/netcfg-profile-$p.service"
> +done
> +
> +. /etc/conf.d/netcfg
> +mkdir $1/netcfg-profiles.target.wants
> +for network in "${NETWORKS[@]}"; do
> + 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..ba310fa
> --- /dev/null
> +++ b/systemd/netcfg-profiles.target
> @@ -0,0 +1,5 @@
> +[Unit]
> +Description=Netcfg network profiles
> +
> +[Install]
> +WantedBy=multi-user.target
> --
> 1.8.0
>
More information about the arch-projects
mailing list