Port automatic filesystem creation to systemd

This commit is contained in:
Eelco Dolstra 2012-10-12 17:32:36 -04:00
parent 12d1cd87ce
commit 161c837c49
2 changed files with 29 additions and 111 deletions

View File

@ -101,10 +101,9 @@ with utils;
mkswap ${sw.device} mkswap ${sw.device}
fi fi
''; '';
unitConfig.RequiresMountsFor = "${dirOf sw.device}"; unitConfig.RequiresMountsFor = [ "${dirOf sw.device}" ];
unitConfig.DefaultDependencies = false; # needed to prevent a cycle unitConfig.DefaultDependencies = false; # needed to prevent a cycle
serviceConfig.Type = "oneshot"; serviceConfig.Type = "oneshot";
serviceConfig.RemainAfterExit = true;
}; };
in listToAttrs (map createSwapDevice (filter (sw: sw.size != null) config.swapDevices)); in listToAttrs (map createSwapDevice (filter (sw: sw.size != null) config.swapDevices));

View File

@ -1,6 +1,7 @@
{ config, pkgs, ... }: { config, pkgs, utils, ... }:
with pkgs.lib; with pkgs.lib;
with utils;
let let
@ -27,7 +28,7 @@ let
''; '';
in in
{ {
###### interface ###### interface
@ -170,7 +171,7 @@ in
# Add the mount helpers to the system path so that `mount' can find them. # Add the mount helpers to the system path so that `mount' can find them.
system.fsPackages = [ pkgs.dosfstools ]; system.fsPackages = [ pkgs.dosfstools ];
environment.systemPackages = environment.systemPackages =
[ pkgs.ntfs3g pkgs.cifs_utils ] [ pkgs.ntfs3g pkgs.cifs_utils ]
++ config.system.fsPackages; ++ config.system.fsPackages;
@ -186,119 +187,37 @@ in
wants = [ "local-fs.target" "remote-fs.target" ]; wants = [ "local-fs.target" "remote-fs.target" ];
}; };
/* # Emit systemd services to format requested filesystems.
jobs.mountall = boot.systemd.services =
{ startOn = "started udev or config-changed"; let
task = true; formatDevice = fs:
let
path = [ pkgs.utillinux pkgs.mountall ] ++ config.system.fsPackages; mountPoint' = escapeSystemdPath fs.mountPoint;
device' = escapeSystemdPath fs.device;
console = "output"; in nameValuePair "mkfs-${device'}"
{ description = "Initialisation of Filesystem ${fs.device}";
preStart = wantedBy = [ "${mountPoint'}.mount" ];
'' before = [ "${mountPoint'}.mount" ];
# Ensure that this job is restarted when fstab changed: require = [ "${device'}.device" ];
# ${fstab} after = [ "${device'}.device" ];
echo "mounting filesystems..." path = [ pkgs.utillinux ] ++ config.system.fsPackages;
script =
# Format devices. ''
${flip concatMapStrings config.fileSystems (fs: optionalString fs.autoFormat '' if ! [ -e "${fs.device}" ]; then exit 1; fi
if [ -e "${fs.device}" ]; then # FIXME: this is scary. The test could be more robust.
type=$(blkid -p -s TYPE -o value "${fs.device}" || true) type=$(blkid -p -s TYPE -o value "${fs.device}" || true)
if [ -z "$type" ]; then if [ -z "$type" ]; then
echo "creating ${fs.fsType} filesystem on ${fs.device}..." echo "creating ${fs.fsType} filesystem on ${fs.device}..."
mkfs.${fs.fsType} "${fs.device}" mkfs.${fs.fsType} "${fs.device}"
fi fi
fi '';
'')} unitConfig.RequiresMountsFor = [ "${dirOf fs.device}" ];
unitConfig.DefaultDependencies = false; # needed to prevent a cycle
serviceConfig.Type = "oneshot";
};
''; in listToAttrs (map formatDevice (filter (fs: fs.autoFormat) config.fileSystems));
daemonType = "daemon";
exec = "mountall --daemon";
};
# The `mount-failed' event is emitted synchronously, but we don't
# want `mountall' to wait for the emergency shell. So use this
# intermediate job to make the event asynchronous.
jobs."mount-failed" =
{ task = true;
startOn = "mount-failed";
restartIfChanged = false;
script =
''
# Don't start the emergency shell if the X server is
# running. The user won't see it, and the "console owner"
# stanza breaks VT switching and causes the X server to go
# to 100% CPU time.
status="$(status xserver || true)"
[[ "$status" =~ start/ ]] && exit 0
stop ${config.boot.ttyEmergency} || true
start --no-wait emergency-shell \
DEVICE="$DEVICE" MOUNTPOINT="$MOUNTPOINT"
'';
};
# On an `ip-up' event, notify mountall so that it retries mounting
# remote filesystems.
jobs."mountall-ip-up" =
{
task = true;
startOn = "ip-up";
restartIfChanged = false;
script =
''
# Send USR1 to the mountall process. Can't use "pkill
# mountall" here because that has a race condition: we may
# accidentally send USR1 to children of mountall (such as
# fsck) just before they do execve().
status="$(status mountall)"
if [[ "$status" =~ "start/running, process "([0-9]+) ]]; then
pid=''${BASH_REMATCH[1]}
echo "sending USR1 to $pid..."
kill -USR1 "$pid"
fi
'';
};
jobs."emergency-shell" =
{ task = true;
restartIfChanged = false;
console = "owner";
script =
''
cat <<EOF
<<< Emergency shell >>>
The filesystem \`$DEVICE' could not be mounted on \`$MOUNTPOINT'.
Please do one of the following:
- Repair the filesystem (\`fsck $DEVICE') and exit the emergency
shell to resume booting.
- Ignore any failed filesystems and continue booting by running
\`initctl emit filesystem'.
- Remove the failed filesystem from the system configuration in
/etc/nixos/configuration.nix and run \`nixos-rebuild switch'.
EOF
${pkgs.shadow}/bin/login root || false
initctl start --no-wait mountall
'';
};
*/
}; };