mirror of
https://github.com/nix-community/disko
synced 2024-11-10 06:14:14 +00:00
zfs: Add topology attribute to zpool
This commit is contained in:
parent
7e1b215a0a
commit
b2a106f8ed
2 changed files with 110 additions and 9 deletions
|
@ -195,6 +195,7 @@ let
|
||||||
|| isAttrsOfSubmodule o
|
|| isAttrsOfSubmodule o
|
||||||
# TODO don't hardcode diskoLib.subType options.
|
# TODO don't hardcode diskoLib.subType options.
|
||||||
|| n == "content" || n == "partitions" || n == "datasets" || n == "swap"
|
|| n == "content" || n == "partitions" || n == "datasets" || n == "swap"
|
||||||
|
|| n == "topology"
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
lib.toShellVars
|
lib.toShellVars
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
{ config, options, lib, diskoLib, rootMountPoint, ... }:
|
{ config, options, lib, diskoLib, rootMountPoint, ... }:
|
||||||
|
let
|
||||||
|
modeOptions = [
|
||||||
|
""
|
||||||
|
"mirror"
|
||||||
|
"raidz"
|
||||||
|
"raidz2"
|
||||||
|
"raidz3"
|
||||||
|
];
|
||||||
|
format_output = (mode: members: ''
|
||||||
|
entries+=("${mode}=${
|
||||||
|
lib.concatMapStringsSep " "
|
||||||
|
(d: "/dev/disk/by-partlabel/disk-${d}-zfs") members
|
||||||
|
}")
|
||||||
|
'');
|
||||||
|
format_vdev = (vdev: format_output vdev.mode vdev.members);
|
||||||
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption {
|
name = lib.mkOption {
|
||||||
|
@ -13,13 +29,7 @@
|
||||||
description = "Type";
|
description = "Type";
|
||||||
};
|
};
|
||||||
mode = lib.mkOption {
|
mode = lib.mkOption {
|
||||||
type = lib.types.enum [
|
type = lib.types.enum (modeOptions ++ [ "prescribed" ]);
|
||||||
""
|
|
||||||
"mirror"
|
|
||||||
"raidz"
|
|
||||||
"raidz2"
|
|
||||||
"raidz3"
|
|
||||||
];
|
|
||||||
default = "";
|
default = "";
|
||||||
description = "Mode of the ZFS pool";
|
description = "Mode of the ZFS pool";
|
||||||
};
|
};
|
||||||
|
@ -50,6 +60,55 @@
|
||||||
});
|
});
|
||||||
description = "List of datasets to define";
|
description = "List of datasets to define";
|
||||||
};
|
};
|
||||||
|
topology = lib.mkOption {
|
||||||
|
type =
|
||||||
|
let
|
||||||
|
vdev = lib.types.submodule ({ name, ... }: {
|
||||||
|
options = {
|
||||||
|
mode = lib.mkOption {
|
||||||
|
type = lib.types.enum modeOptions;
|
||||||
|
default = "";
|
||||||
|
description = "mode of the zfs vdev";
|
||||||
|
};
|
||||||
|
members = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
description = "Members of the vdev";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
parent = config;
|
||||||
|
in
|
||||||
|
lib.types.nullOr
|
||||||
|
(lib.types.submodule
|
||||||
|
({ config, name, ... }: {
|
||||||
|
options = {
|
||||||
|
type = lib.mkOption {
|
||||||
|
type = lib.types.enum [ "zfs_topology" ];
|
||||||
|
default = "zfs_topology";
|
||||||
|
internal = true;
|
||||||
|
description = "Type";
|
||||||
|
};
|
||||||
|
# zfs disk types
|
||||||
|
vdev = lib.mkOption {
|
||||||
|
type = lib.types.listOf vdev;
|
||||||
|
default = [ ];
|
||||||
|
description = "A list of storage vdevs";
|
||||||
|
};
|
||||||
|
special = lib.mkOption {
|
||||||
|
type = lib.types.nullOr vdev;
|
||||||
|
default = null;
|
||||||
|
description = "A list of devices for the special vdev";
|
||||||
|
};
|
||||||
|
cache = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "The cache device";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = null;
|
||||||
|
description = "Topology of the ZFS pool";
|
||||||
|
};
|
||||||
_meta = lib.mkOption {
|
_meta = lib.mkOption {
|
||||||
internal = true;
|
internal = true;
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
|
@ -84,11 +143,52 @@
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ $continue -eq 1 ]; then
|
if [ $continue -eq 1 ]; then
|
||||||
|
topology=""
|
||||||
|
# For shell check
|
||||||
|
mode="${config.mode}"
|
||||||
|
if [ $mode != "prescribed" ]; then
|
||||||
|
${if config.topology == null then
|
||||||
|
''topology="${config.mode} \"''${zfs_devices}\""''
|
||||||
|
else
|
||||||
|
''
|
||||||
|
echo "topology cannot be set when mode != 'prescribed', skipping creating zpool ${config.name}" >&2
|
||||||
|
continue=0
|
||||||
|
''
|
||||||
|
}
|
||||||
|
else
|
||||||
|
entries=()
|
||||||
|
${lib.concatMapStrings format_vdev config.topology.vdev}
|
||||||
|
${lib.optionalString (config.topology.special != null)
|
||||||
|
(format_output "special ${config.topology.special.mode}" config.topology.special.members)}
|
||||||
|
${lib.optionalString (config.topology.cache != null)
|
||||||
|
(format_output "cache" [config.topology.cache])}
|
||||||
|
all_devices=()
|
||||||
|
for line in "''${entries[@]}"; do
|
||||||
|
# lineformat is mode=device1 device2 device3
|
||||||
|
mode=''${line%%=*}
|
||||||
|
devs=''${line#*=}
|
||||||
|
IFS=' ' read -r -a devices <<< "$devs"
|
||||||
|
all_devices+=("''${devices[@]}")
|
||||||
|
# shellcheck disable=SC2089
|
||||||
|
topology+=" ''${mode} ''${devices[*]}"
|
||||||
|
done
|
||||||
|
# all_devices sorted should equal zfs_devices sorted
|
||||||
|
all_devices_list=$(echo "''${all_devices[*]}" | tr ' ' '\n' | sort)
|
||||||
|
zfs_devices_list=$(echo "''${zfs_devices[*]}" | tr ' ' '\n' | sort)
|
||||||
|
if [[ "$all_devices_list" != "$zfs_devices_list" ]]; then
|
||||||
|
echo "not all disks accounted for, skipping creating zpool ${config.name}" >&2
|
||||||
|
diff <(echo "$all_devices_list" ) <(echo "$zfs_devices_list") >&2
|
||||||
|
continue=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $continue -eq 1 ]; then
|
||||||
|
# shellcheck disable=SC2090
|
||||||
zpool create -f ${config.name} \
|
zpool create -f ${config.name} \
|
||||||
-R ${rootMountPoint} ${config.mode} \
|
-R ${rootMountPoint} \
|
||||||
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} \
|
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} \
|
||||||
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-O ${n}=${v}") config.rootFsOptions)} \
|
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-O ${n}=${v}") config.rootFsOptions)} \
|
||||||
"''${zfs_devices[@]}"
|
''${topology:+ $topology}
|
||||||
if [[ $(zfs get -H mounted ${config.name} | cut -f3) == "yes" ]]; then
|
if [[ $(zfs get -H mounted ${config.name} | cut -f3) == "yes" ]]; then
|
||||||
zfs unmount ${config.name}
|
zfs unmount ${config.name}
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue