Containers: Use systemd startup notification

Systemd in a container will call sd_notify when it has finished
booting, so we can use that to signal that the container is
ready. This does require some fiddling with $NOTIFY_SOCKET.
This commit is contained in:
Eelco Dolstra
2014-08-18 17:16:13 +02:00
parent 11d99048c1
commit 2c899859bf
+11 -15
View File
@@ -32,7 +32,10 @@ let
fi fi
fi fi
exec "$1" # Start the regular stage 1 script, passing the bind-mounted
# notification socket from the host to allow the container
# systemd to signal readiness to the host systemd.
NOTIFY_SOCKET=/var/lib/private/host-notify exec "$1"
''; '';
system = config.nixpkgs.system; system = config.nixpkgs.system;
@@ -174,18 +177,12 @@ in
if [ "$PRIVATE_NETWORK" = 1 ]; then if [ "$PRIVATE_NETWORK" = 1 ]; then
ip link del dev "ve-$INSTANCE" 2> /dev/null || true ip link del dev "ve-$INSTANCE" 2> /dev/null || true
fi fi
mkdir -p -m 0755 $root/var/lib
# Create a named pipe to get a signal when the container
# has finished booting.
rm -f $root/var/lib/startup-done
mkfifo -m 0600 $root/var/lib/startup-done
''; '';
script = script =
'' ''
mkdir -p -m 0755 "$root/etc" "$root/var/lib" mkdir -p -m 0755 "$root/etc" "$root/var/lib"
mkdir -p -m 0700 "$root/var/lib/private"
if ! [ -e "$root/etc/os-release" ]; then if ! [ -e "$root/etc/os-release" ]; then
touch "$root/etc/os-release" touch "$root/etc/os-release"
fi fi
@@ -212,13 +209,16 @@ in
fi fi
''} ''}
EXIT_ON_REBOOT=1 \ # Run systemd-nspawn without startup notification (we'll
# wait for the container systemd to signal readiness).
EXIT_ON_REBOOT=1 NOTIFY_SOCKET= \
exec ${config.systemd.package}/bin/systemd-nspawn \ exec ${config.systemd.package}/bin/systemd-nspawn \
--keep-unit \ --keep-unit \
-M "$INSTANCE" -D "$root" $extraFlags \ -M "$INSTANCE" -D "$root" $extraFlags \
--bind-ro=/nix/store \ --bind-ro=/nix/store \
--bind-ro=/nix/var/nix/db \ --bind-ro=/nix/var/nix/db \
--bind-ro=/nix/var/nix/daemon-socket \ --bind-ro=/nix/var/nix/daemon-socket \
--bind=/run/systemd/notify:/var/lib/private/host-notify \
--bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \ --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles" \
--bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \ --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots" \
--setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \ --setenv PRIVATE_NETWORK="$PRIVATE_NETWORK" \
@@ -240,12 +240,6 @@ in
ip route add $LOCAL_ADDRESS dev $ifaceHost ip route add $LOCAL_ADDRESS dev $ifaceHost
fi fi
fi fi
# This blocks until the container-startup-done service
# writes something to this pipe. FIXME: it also hangs
# until the start timeout expires if systemd-nspawn exits.
read x < $root/var/lib/startup-done
rm -f $root/var/lib/startup-done
''; '';
preStop = preStop =
@@ -271,6 +265,8 @@ in
Type = "notify"; Type = "notify";
NotifyAccess = "all";
# Note that on reboot, systemd-nspawn returns 10, so this # Note that on reboot, systemd-nspawn returns 10, so this
# unit will be restarted. On poweroff, it returns 0, so the # unit will be restarted. On poweroff, it returns 0, so the
# unit won't be restarted. # unit won't be restarted.