add unmount feature

This commit is contained in:
Jörg Thalheim
2024-11-29 14:44:15 +01:00
parent 341482e2f4
commit aa006252c8
21 changed files with 247 additions and 4 deletions
+5 -1
View File
@@ -23,6 +23,7 @@ let
destroy = "_cliDestroyNoDeps";
format = "_cliFormatNoDeps";
mount = "_cliMountNoDeps";
unmount = "_cliUnmountNoDeps";
"format,mount" = "_cliFormatMountNoDeps";
"destroy,format,mount" = "_cliDestroyFormatMountNoDeps";
@@ -32,6 +33,7 @@ let
destroy = "destroyNoDeps";
format = "formatNoDeps";
mount = "mountNoDeps";
unmount = "unmountNoDeps";
"format,mount" = "formatMountNoDeps";
"destroy,format,mount" = "destroyFormatMountNoDeps";
@@ -47,6 +49,7 @@ let
destroy = "_cliDestroy";
format = "_cliFormat";
mount = "_cliMount";
unmount = "_cliUnmount";
"format,mount" = "_cliFormatMount";
"destroy,format,mount" = "_cliDestroyFormatMount";
@@ -55,7 +58,8 @@ let
{
destroy = "destroy";
format = "format";
mount = "munt";
mount = "mount";
unmount = "unmount";
"format,mount" = "formatMount";
"destroy,format,mount" = "destroyFormatMount";
+3
View File
@@ -31,6 +31,9 @@ in
_cliMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mount;
_cliMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).mountNoDeps;
_cliUnmount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmount;
_cliUnmountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).unmountNoDeps;
_cliFormatMount = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMount;
_cliFormatMountNoDeps = cfg: pkgs: ((eval cfg).config.disko.devices._scripts { inherit pkgs checked; }).formatMountNoDeps;
+2 -2
View File
@@ -26,7 +26,7 @@ or else from the disko module of a NixOS configuration of that name under .nixos
Options:
* -m, --mode mode
set the mode, either distroy, format, mount, format,mount or destroy,format,mount
set the mode, either distroy, format, mount, unmount, format,mount or destroy,format,mount
destroy: unmount filesystems and destroy partition tables of the selected disks
format: create partition tables, zpools, lvms, raids and filesystems if they don't exist yet
mount: mount the partitions at the specified root-mountpoint
@@ -136,7 +136,7 @@ nixBuild() {
if ! {
# Base modes
[[ $mode = "destroy" ]] || [[ $mode = "format" ]] || [[ $mode = "mount" ]] ||
[[ $mode = "destroy" ]] || [[ $mode = "format" ]] || [[ $mode = "mount" ]] || [[ $mode = "unmount" ]] ||
# Combined modes
[[ $mode = "format,mount" ]] ||
[[ $mode = "destroy,format,mount" ]] || # Replaces --mode disko
+48
View File
@@ -242,6 +242,8 @@ let
postCreateHook = diskoLib.mkHook "shell commands to run after create";
preMountHook = diskoLib.mkHook "shell commands to run before mount";
postMountHook = diskoLib.mkHook "shell commands to run after mount";
preUnmountHook = diskoLib.mkHook "shell commands to run before unmount";
postUnmountHook = diskoLib.mkHook "shell commands to run after unmount";
};
config._module.args = {
inherit diskoLib rootMountPoint;
@@ -284,6 +286,25 @@ let
description = "Mount script";
};
mkUnmountOption = { config, options, default }@attrs:
lib.mkOption {
internal = true;
readOnly = true;
type = diskoLib.jsonType;
default = lib.mapAttrsRecursive
(_name: value:
if builtins.isString value then ''
(
${diskoLib.indent (diskoLib.defineHookVariables { inherit options; })}
${diskoLib.indent config.preUnmountHook}
${diskoLib.indent value}
${diskoLib.indent config.postUnmountHook}
)
'' else value)
attrs.default;
description = "Unmount script";
};
/* Writer for optionally checking bash scripts before writing them to the store
writeCheckedBash :: AttrSet -> str -> str -> derivation
@@ -458,6 +479,10 @@ let
export PATH=${lib.makeBinPath (cfg.config._packages pkgs)}:$PATH
${cfg.config._mount}
'';
unmount = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "/bin/disko-unmount" ''
export PATH=${lib.makeBinPath (cfg.config._packages pkgs)}:$PATH
${cfg.config._unmount}
'';
formatMount = (diskoLib.writeCheckedBash { inherit pkgs checked; }) "/bin/disko-format-mount" ''
export PATH=${lib.makeBinPath ((cfg.config._packages pkgs) ++ [ pkgs.bash ])}:$PATH
${cfg.config._formatMount}
@@ -477,6 +502,9 @@ let
mountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-mount" ''
${cfg.config._mount}
'';
unmountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-unmount" ''
${cfg.config._unmount}
'';
formatMountNoDeps = (diskoLib.writeCheckedBash { inherit pkgs checked; noDeps = true; }) "/bin/disko-format-mount" ''
${cfg.config._formatMount}
'';
@@ -622,6 +650,26 @@ let
${concatStrings (attrValues fsMounts)}
'';
};
_unmount = lib.mkOption {
internal = true;
type = lib.types.str;
description = ''
The script to unmount all devices defined by disko.devices
'';
default =
with lib; let
fsMounts = diskoLib.deepMergeMap (dev: dev._unmount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies (cfg.config._meta.deviceDependencies or { }) devices;
in
''
set -efux
# first unmount the filesystems in reverse alphabetical order
${concatStrings (lib.reverseList (attrValues fsMounts))}
# Than close the devices
${concatMapStrings (dev: (attrByPath (dev ++ [ "_unmount" ]) {} devices).dev or "") (lib.reverseList sortedDeviceList)}
'';
};
_disko = lib.mkOption {
internal = true;
type = lib.types.str;
+4
View File
@@ -99,6 +99,7 @@ let
tsp-generator = pkgs.callPackage ../. { checked = true; };
tsp-format = (tsp-generator._cliFormat testConfigInstall) pkgs;
tsp-mount = (tsp-generator._cliMount testConfigInstall) pkgs;
tsp-unmount = (tsp-generator._cliUnmount testConfigInstall) pkgs;
tsp-disko = (tsp-generator._cliDestroyFormatMount testConfigInstall) pkgs;
tsp-config = tsp-generator.config testConfigBooted;
num-disks = builtins.length (lib.attrNames testConfigBooted.disko.devices.disk);
@@ -282,6 +283,9 @@ let
machine.succeed("${lib.getExe tsp-format}")
machine.succeed("${lib.getExe tsp-mount}")
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
machine.succeed("${lib.getExe tsp-unmount}")
machine.succeed("${lib.getExe tsp-unmount}") # verify that umount is idempotent
machine.succeed("${lib.getExe tsp-mount}") # verify that mount is idempotent
machine.succeed("${lib.getExe tsp-disko} --yes-wipe-all-disks") # verify that we can destroy and recreate
machine.succeed("mkdir -p /mnt/home")
machine.succeed("touch /mnt/home/testfile")
+28
View File
@@ -199,6 +199,34 @@ in
};
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
subvolMounts = lib.concatMapAttrs
(_: subvol:
lib.optionalAttrs
(subvol.mountpoint != null)
{
${subvol.mountpoint} = ''
if findmnt "${config.device}" "${rootMountPoint}${subvol.mountpoint}" > /dev/null 2>&1; then
umount "${rootMountPoint}${subvol.mountpoint}"
fi
'';
}
)
config.subvolumes;
in
{
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
${config.mountpoint} = ''
if findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
fi
'';
};
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+4
View File
@@ -49,6 +49,10 @@
inherit config options;
default = lib.optionalAttrs (config.content != null) config.content._mount;
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = lib.optionalAttrs (config.content != null) config.content._unmount;
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+10
View File
@@ -64,6 +64,16 @@
'';
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = lib.optionalAttrs (config.mountpoint != null) {
fs.${config.mountpoint} = ''
if findmnt "${config.device}" "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+16 -1
View File
@@ -45,7 +45,7 @@ in
defaultText = ''
if the parent is an mdadm device:
/dev/disk/by-id/md-name-any:''${config._parent.name}-part''${toString partition.config._index}
otherwise:
/dev/disk/by-partlabel/''${diskoLib.hexEscapeUdevSymlink partition.config.label}
'';
@@ -249,6 +249,21 @@ in
fs = partMounts.fs or { };
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
partMounts = lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) partition.content._unmount
)
(lib.attrValues config.partitions));
in
{
dev = partMounts.dev or "";
fs = partMounts.fs or { };
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+15
View File
@@ -170,6 +170,21 @@ in
fs = lib.optionalAttrs (config.content != null) contentMount.fs or { };
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
contentUnmount = config.content._unmount;
in
{
dev = ''
${lib.optionalString (config.content != null) contentUnmount.dev or ""}
if cryptsetup status "${config.name}" >/dev/null 2>/dev/null; then
cryptsetup close "${config.name}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+4
View File
@@ -41,6 +41,10 @@
inherit config options;
default = { };
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = { };
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+17
View File
@@ -127,6 +127,23 @@ in
fs = lvMounts.fs or { };
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
lvMounts = diskoLib.deepMergeMap
(lv:
lib.optionalAttrs (lv.content != null) lv.content._unmount
)
(lib.attrValues config.lvs);
in {
dev = ''
${lib.concatMapStrings (x: x.dev or "") (lib.attrValues lvMounts)}
vgchange -a n
'';
fs = lvMounts.fs or { };
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+14
View File
@@ -58,6 +58,20 @@
lib.optionalAttrs (config.content != null) config.content._mount;
# TODO we probably need to assemble the mdadm somehow
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = let
content = lib.optionalAttrs (config.content != null) config.content._unmount;
in {
fs = content.fs;
dev = ''
${content.dev or ""}
if [ -e "/dev/md/${config.name}" ]; then
mdadm --stop "/dev/md/${config.name}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+4
View File
@@ -39,6 +39,10 @@
inherit config options;
default = { };
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = { };
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+10
View File
@@ -49,6 +49,16 @@
'';
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = lib.optionalAttrs (config.mountpoint != null) {
fs.${config.mountpoint} = ''
if findmnt ${config.fsType} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+10
View File
@@ -95,6 +95,16 @@
'';
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = lib.optionalAttrs (!config.randomEncryption) {
fs.${config.device} = ''
if swapon --show | grep -q "^$(readlink -f "${config.device}") "; then
swapoff "${config.device}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+15
View File
@@ -137,6 +137,21 @@
fs = partMounts.fs or { };
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
partMounts = lib.foldr lib.recursiveUpdate { } (map
(partition:
lib.optionalAttrs (partition.content != null) partition.content._unmount
)
config.partitions);
in
{
dev = partMounts.dev or "";
fs = partMounts.fs or { };
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+4
View File
@@ -38,6 +38,10 @@
inherit config options;
default = { };
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default = { };
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+12
View File
@@ -114,6 +114,18 @@
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
lib.optionalAttrs (config.options.mountpoint or "" != "none" && config.options.canmount or "" != "off") {
fs.${config.mountpoint} = ''
if findmnt ${config._name} "${rootMountPoint}${config.mountpoint}" >/dev/null 2>&1; then
umount "${rootMountPoint}${config.mountpoint}"
fi
'';
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+5
View File
@@ -64,6 +64,11 @@
default =
lib.optionalAttrs (config.content != null) config.content._mount;
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
lib.optionalAttrs (config.content != null) config.content._unmount;
};
_config = lib.mkOption {
internal = true;
readOnly = true;
+17
View File
@@ -310,6 +310,23 @@ in
fs = datasetMounts.fs or { };
};
};
_unmount = diskoLib.mkUnmountOption {
inherit config options;
default =
let
datasetUnmounts = diskoLib.deepMergeMap (dataset: dataset._unmount) (lib.attrValues config.datasets);
in
{
dev = ''
${lib.concatMapStrings (x: x.dev or "") (lib.attrValues datasetUnmounts)}
if zpool list "${config.name}" >/dev/null 2>/dev/null; then
zpool export "${config.name}"
fi
'';
fs = datasetUnmounts.fs or { };
};
};
_config = lib.mkOption {
internal = true;
readOnly = true;