lib.types: turn _create, _mount and _config into values

This commit is contained in:
lassulus 2023-07-01 19:02:01 +02:00 committed by mergify[bot]
parent 8002e7cb89
commit ab9b880db2
17 changed files with 194 additions and 146 deletions

View file

@ -178,16 +178,15 @@ let
lib.mkOption { lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
type = lib.types.functionTo lib.types.str; type = lib.types.str;
default = args: default = ''
'' ( # ${config.type} ${concatMapStringsSep " " (n: toString (config.${n} or "")) ["name" "device" "format" "mountpoint"]}
( # ${config.type} ${concatMapStringsSep " " (n: toString (config.${n} or "")) ["name" "device" "format" "mountpoint"]} ${diskoLib.defineHookVariables { inherit config options; }}
${diskoLib.defineHookVariables { inherit config options; }} ${config.preCreateHook}
${config.preCreateHook} ${attrs.default}
${attrs.default args} ${config.postCreateHook}
${config.postCreateHook} )
) '';
'';
description = "Creation script"; description = "Creation script";
}; };
@ -195,7 +194,7 @@ let
lib.mkOption { lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
type = lib.types.functionTo diskoLib.jsonType; type = diskoLib.jsonType;
default = attrs.default; default = attrs.default;
description = "Mount script"; description = "Mount script";
}; };
@ -231,7 +230,7 @@ let
trap 'rm -rf "$disko_devices_dir"' EXIT trap 'rm -rf "$disko_devices_dir"' EXIT
mkdir -p "$disko_devices_dir" mkdir -p "$disko_devices_dir"
${concatMapStrings (dev: (attrByPath (dev ++ [ "_create" ]) (_: {}) devices) {}) sortedDeviceList} ${concatMapStrings (dev: (attrByPath (dev ++ [ "_create" ]) "" devices)) sortedDeviceList}
''; '';
/* Takes a disko device specification and returns a string which mounts the disks /* Takes a disko device specification and returns a string which mounts the disks
@ -239,13 +238,13 @@ let
*/ */
mount = devices: mount = devices:
let let
fsMounts = diskoLib.deepMergeMap (dev: (dev._mount { }).fs or { }) (flatten (map attrValues (attrValues devices))); fsMounts = diskoLib.deepMergeMap (dev: dev._mount.fs or { }) (flatten (map attrValues (attrValues devices)));
sortedDeviceList = diskoLib.sortDevicesByDependencies ((diskoLib.meta devices).deviceDependencies or { }) devices; sortedDeviceList = diskoLib.sortDevicesByDependencies ((diskoLib.meta devices).deviceDependencies or { }) devices;
in in
'' ''
set -efux set -efux
# first create the necessary devices # first create the necessary devices
${concatMapStrings (dev: ((attrByPath (dev ++ [ "_mount" ]) {} devices) {}).dev or "") sortedDeviceList} ${concatMapStrings (dev: ((attrByPath (dev ++ [ "_mount" ]) {} devices)).dev or "") sortedDeviceList}
# and then mount the filesystems in alphabetical order # and then mount the filesystems in alphabetical order
${concatStrings (attrValues fsMounts)} ${concatStrings (attrValues fsMounts)}

View file

@ -1,4 +1,4 @@
{ config, options, diskoLib, lib, rootMountPoint, parent, ... }: { config, options, diskoLib, lib, rootMountPoint, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device to use";
};
extraArgs = lib.mkOption { extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
@ -63,17 +68,17 @@
internal = true; internal = true;
readOnly = true; readOnly = true;
type = lib.types.functionTo diskoLib.jsonType; type = lib.types.functionTo diskoLib.jsonType;
default = _dev: { }; default = dev: { };
description = "Metadata"; description = "Metadata";
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
mkfs.btrfs ${dev} ${toString config.extraArgs} mkfs.btrfs ${config.device} ${toString config.extraArgs}
${lib.concatMapStrings (subvol: '' ${lib.concatMapStrings (subvol: ''
( (
MNTPOINT=$(mktemp -d) MNTPOINT=$(mktemp -d)
mount ${dev} "$MNTPOINT" -o subvol=/ mount ${config.device} "$MNTPOINT" -o subvol=/
trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT trap 'umount $MNTPOINT; rm -rf $MNTPOINT' EXIT
btrfs subvolume create "$MNTPOINT"/${subvol.name} ${toString subvol.extraArgs} btrfs subvolume create "$MNTPOINT"/${subvol.name} ${toString subvol.extraArgs}
) )
@ -82,7 +87,7 @@
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default =
let let
subvolMounts = lib.concatMapAttrs subvolMounts = lib.concatMapAttrs
(_: subvol: (_: subvol:
@ -94,8 +99,8 @@
in in
lib.optionalAttrs (mountpoint != null) { lib.optionalAttrs (mountpoint != null) {
${mountpoint} = '' ${mountpoint} = ''
if ! findmnt ${dev} "${rootMountPoint}${mountpoint}" > /dev/null 2>&1; then if ! findmnt ${config.device} "${rootMountPoint}${mountpoint}" > /dev/null 2>&1; then
mount ${dev} "${rootMountPoint}${mountpoint}" \ mount ${config.device} "${rootMountPoint}${mountpoint}" \
${lib.concatMapStringsSep " " (opt: "-o ${opt}") (subvol.mountOptions ++ [ "subvol=${subvol.name}" ])} \ ${lib.concatMapStringsSep " " (opt: "-o ${opt}") (subvol.mountOptions ++ [ "subvol=${subvol.name}" ])} \
-o X-mount.mkdir -o X-mount.mkdir
fi fi
@ -107,8 +112,8 @@
{ {
fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) { fs = subvolMounts // lib.optionalAttrs (config.mountpoint != null) {
${config.mountpoint} = '' ${config.mountpoint} = ''
if ! findmnt ${dev} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then if ! findmnt ${config.device} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
mount ${dev} "${rootMountPoint}${config.mountpoint}" \ mount ${config.device} "${rootMountPoint}${config.mountpoint}" \
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \ ${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
-o X-mount.mkdir -o X-mount.mkdir
fi fi
@ -119,7 +124,7 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: [ default = [
(map (map
(subvol: (subvol:
let let
@ -130,7 +135,7 @@
in in
lib.optional (mountpoint != null) { lib.optional (mountpoint != null) {
fileSystems.${mountpoint} = { fileSystems.${mountpoint} = {
device = dev; device = config.device;
fsType = "btrfs"; fsType = "btrfs";
options = subvol.mountOptions ++ [ "subvol=${subvol.name}" ]; options = subvol.mountOptions ++ [ "subvol=${subvol.name}" ];
}; };
@ -139,7 +144,7 @@
(lib.attrValues config.subvolumes)) (lib.attrValues config.subvolumes))
(lib.optional (config.mountpoint != null) { (lib.optional (config.mountpoint != null) {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = dev; device = config.device;
fsType = "btrfs"; fsType = "btrfs";
options = config.mountOptions; options = config.mountOptions;
}; };

View file

@ -16,7 +16,7 @@
type = diskoLib.optionTypes.absolute-pathname; # TODO check if subpath of /dev ? - No! eg: /.swapfile type = diskoLib.optionTypes.absolute-pathname; # TODO check if subpath of /dev ? - No! eg: /.swapfile
description = "Device path"; description = "Device path";
}; };
content = diskoLib.deviceType { parent = config; }; content = diskoLib.deviceType { parent = config; device = config.device; };
_meta = lib.mkOption { _meta = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
@ -27,18 +27,17 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = _: config.content._create { dev = config.device; }; default = config.content._create;
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = _: default = lib.optionalAttrs (config.content != null) (config.content._mount);
lib.optionalAttrs (config.content != null) (config.content._mount { dev = config.device; });
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
lib.optional (config.content != null) (config.content._config config.device); lib.optional (config.content != null) (config.content._config);
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, rootMountPoint, parent, ... }: { config, options, lib, diskoLib, rootMountPoint, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device to use";
};
extraArgs = lib.mkOption { extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
@ -38,18 +43,18 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
mkfs.${config.format} \ mkfs.${config.format} \
${toString config.extraArgs} \ ${toString config.extraArgs} \
${dev} ${config.device}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: lib.optionalAttrs (config.mountpoint != null) { default = lib.optionalAttrs (config.mountpoint != null) {
fs.${config.mountpoint} = '' fs.${config.mountpoint} = ''
if ! findmnt ${dev} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then if ! findmnt ${config.device} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
mount ${dev} "${rootMountPoint}${config.mountpoint}" \ mount ${config.device} "${rootMountPoint}${config.mountpoint}" \
-t "${config.format}" \ -t "${config.format}" \
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \ ${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
-o X-mount.mkdir -o X-mount.mkdir
@ -60,9 +65,9 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: lib.optional (config.mountpoint != null) { default = lib.optional (config.mountpoint != null) {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = dev; device = config.device;
fsType = config.format; fsType = config.format;
options = config.mountOptions; options = config.mountOptions;
}; };

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }@args: { config, options, lib, diskoLib, parent, device, ... }@args:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Partition table"; description = "Partition table";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device to use for the partition table";
};
partitions = lib.mkOption { partitions = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@partition: { type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@partition: {
options = { options = {
@ -14,6 +19,11 @@
default = "8300"; default = "8300";
description = "Filesystem type to use, run sgdisk -L to see what is available"; description = "Filesystem type to use, run sgdisk -L to see what is available";
}; };
device = lib.mkOption {
type = lib.types.str;
default = "/dev/disk/by-partlabel/${partition.config.label}";
description = "Device to use for the partition";
};
priority = lib.mkOption { priority = lib.mkOption {
type = lib.types.int; type = lib.types.int;
default = if (partition.config.size or "" == "100%") then 9001 else 1000; default = if (partition.config.size or "" == "100%") then 9001 else 1000;
@ -51,7 +61,7 @@
or - for relative sizes from the disks end or - for relative sizes from the disks end
''; '';
}; };
content = diskoLib.partitionType { parent = config; }; content = diskoLib.partitionType { parent = config; device = partition.config.device; };
}; };
})); }));
default = [ ]; default = [ ];
@ -75,27 +85,27 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
${lib.concatStrings (lib.imap (index: partition: '' ${lib.concatStrings (lib.imap (index: partition: ''
sgdisk \ sgdisk \
--new=${toString index}:${partition.start}:${partition.end} \ --new=${toString index}:${partition.start}:${partition.end} \
--change-name=${toString index}:${partition.label} \ --change-name=${toString index}:${partition.label} \
--typecode=${toString index}:${partition.type} \ --typecode=${toString index}:${partition.type} \
${dev} ${config.device}
# ensure /dev/disk/by-path/..-partN exists before continuing # ensure /dev/disk/by-path/..-partN exists before continuing
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${lib.optionalString (partition.content != null) (partition.content._create { dev = "/dev/disk/by-partlabel/${partition.label}"; })} ${lib.optionalString (partition.content != null) partition.content._create}
'') (lib.sort (x: y: x.priority < y.priority) (lib.attrValues config.partitions)))} '') (lib.sort (x: y: x.priority < y.priority) (lib.attrValues config.partitions)))}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default =
let let
partMounts = lib.foldr lib.recursiveUpdate { } (lib.imap partMounts = lib.foldr lib.recursiveUpdate { } (lib.imap
(index: partition: (index: partition:
lib.optionalAttrs (partition.content != null) (partition.content._mount { dev = "/dev/disk/by-partlabel/${partition.label}"; }) lib.optionalAttrs (partition.content != null) partition.content._mount
) )
(lib.attrValues config.partitions)); (lib.attrValues config.partitions));
in in
@ -107,10 +117,9 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default = map
lib.imap (partition:
(index: partition: lib.optional (partition.content != null) partition.content._config
lib.optional (partition.content != null) (partition.content._config "/dev/disk/by-partlabel/${partition.label}")
) )
(lib.attrValues config.partitions); (lib.attrValues config.partitions);
description = "NixOS configuration"; description = "NixOS configuration";

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }: { config, options, lib, diskoLib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
description = "Device to encrypt";
default = device;
};
name = lib.mkOption { name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "Name of the LUKS"; description = "Name of the LUKS";
@ -33,7 +38,7 @@
description = "Extra arguments to pass to `cryptsetup luksOpen` when opening"; description = "Extra arguments to pass to `cryptsetup luksOpen` when opening";
example = [ "--allow-discards" ]; example = [ "--allow-discards" ];
}; };
content = diskoLib.deviceType { parent = config; }; content = diskoLib.deviceType { parent = config; device = "/dev/mapper/${config.name}"; };
_parent = lib.mkOption { _parent = lib.mkOption {
internal = true; internal = true;
default = parent; default = parent;
@ -48,22 +53,22 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
cryptsetup -q luksFormat ${dev} ${diskoLib.maybeStr config.keyFile} ${toString config.extraFormatArgs} cryptsetup -q luksFormat ${config.device} ${diskoLib.maybeStr config.keyFile} ${toString config.extraFormatArgs}
cryptsetup luksOpen ${dev} ${config.name} ${toString config.extraOpenArgs} ${lib.optionalString (config.keyFile != null) "--key-file ${config.keyFile}"} cryptsetup luksOpen ${config.device} ${config.name} ${toString config.extraOpenArgs} ${lib.optionalString (config.keyFile != null) "--key-file ${config.keyFile}"}
${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/mapper/${config.name}";})} ${lib.optionalString (config.content != null) config.content._create}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default =
let let
contentMount = config.content._mount { dev = "/dev/mapper/${config.name}"; }; contentMount = config.content._mount;
in in
{ {
dev = '' dev = ''
cryptsetup status ${config.name} >/dev/null 2>/dev/null || cryptsetup status ${config.name} >/dev/null 2>/dev/null ||
cryptsetup luksOpen ${dev} ${config.name} ${lib.optionalString (config.keyFile != null) "--key-file ${config.keyFile}"} cryptsetup luksOpen ${config.device} ${config.name} ${lib.optionalString (config.keyFile != null) "--key-file ${config.keyFile}"}
${lib.optionalString (config.content != null) contentMount.dev or ""} ${lib.optionalString (config.content != null) contentMount.dev or ""}
''; '';
fs = lib.optionalAttrs (config.content != null) contentMount.fs or { }; fs = lib.optionalAttrs (config.content != null) contentMount.fs or { };
@ -72,10 +77,10 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: [ ] default = [ ]
# If initrdUnlock is true, then add a device entry to the initrd.luks.devices config. # If initrdUnlock is true, then add a device entry to the initrd.luks.devices config.
++ (lib.optional config.initrdUnlock [{ boot.initrd.luks.devices.${config.name}.device = dev; }]) ++ (lib.optional config.initrdUnlock [{ boot.initrd.luks.devices.${config.name}.device = config.device; }])
++ (lib.optional (config.content != null) (config.content._config "/dev/mapper/${config.name}")); ++ (lib.optional (config.content != null) config.content._config);
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }: { config, options, lib, diskoLib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
description = "Device";
default = device;
};
vg = lib.mkOption { vg = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "Volume group"; description = "Volume group";
@ -25,20 +30,19 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
pvcreate ${dev} pvcreate ${config.device}
echo "${dev}" >> "$disko_devices_dir"/lvm_${config.vg} echo "${config.device}" >> "$disko_devices_dir"/lvm_${config.vg}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default = { };
{ };
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = _dev: [ ]; default = [ ];
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -12,11 +12,11 @@
description = "Type"; description = "Type";
}; };
lvs = lib.mkOption { lvs = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ config, ... }: { type = lib.types.attrsOf (lib.types.submodule ({ name, ... }@lv: {
options = { options = {
name = lib.mkOption { name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = config._module.args.name; default = name;
description = "Name of the logical volume"; description = "Name of the logical volume";
}; };
size = lib.mkOption { size = lib.mkOption {
@ -33,7 +33,7 @@
default = [ ]; default = [ ];
description = "Extra arguments"; description = "Extra arguments";
}; };
content = diskoLib.partitionType { parent = config; }; content = diskoLib.partitionType { parent = config; device = "/dev/${config.name}/${lv.config.name}"; };
}; };
})); }));
default = { }; default = { };
@ -53,7 +53,7 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = _: default =
let let
sortedLvs = lib.sort (a: _: !lib.hasInfix "100%" a.size) (lib.attrValues config.lvs); sortedLvs = lib.sort (a: _: !lib.hasInfix "100%" a.size) (lib.attrValues config.lvs);
in in
@ -69,17 +69,17 @@
${lib.optionalString (lv.lvm_type != null) "--type=${lv.lvm_type}"} \ ${lib.optionalString (lv.lvm_type != null) "--type=${lv.lvm_type}"} \
${toString lv.extraArgs} \ ${toString lv.extraArgs} \
${config.name} ${config.name}
${lib.optionalString (lv.content != null) (lv.content._create {dev = "/dev/${config.name}/${lv.name}";})} ${lib.optionalString (lv.content != null) lv.content._create}
'') sortedLvs} '') sortedLvs}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = _: default =
let let
lvMounts = diskoLib.deepMergeMap lvMounts = diskoLib.deepMergeMap
(lv: (lv:
lib.optionalAttrs (lv.content != null) (lv.content._mount { dev = "/dev/${config.name}/${lv.name}"; }) lib.optionalAttrs (lv.content != null) lv.content._mount
) )
(lib.attrValues config.lvs); (lib.attrValues config.lvs);
in in
@ -97,7 +97,7 @@
default = default =
map map
(lv: [ (lv: [
(lib.optional (lv.content != null) (lv.content._config "/dev/${config.name}/${lv.name}")) (lib.optional (lv.content != null) lv.content._config)
(lib.optional (lv.lvm_type != null) { (lib.optional (lv.lvm_type != null) {
boot.initrd.kernelModules = [ "dm-${lv.lvm_type}" ]; boot.initrd.kernelModules = [ "dm-${lv.lvm_type}" ];
}) })

View file

@ -22,7 +22,7 @@
default = "default"; default = "default";
description = "Metadata"; description = "Metadata";
}; };
content = diskoLib.deviceType { parent = config; }; content = diskoLib.deviceType { parent = config; device = "/dev/md/${config.name}"; };
_meta = lib.mkOption { _meta = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
@ -33,7 +33,7 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = _: '' default = ''
readarray -t disk_devices < <(cat "$disko_devices_dir"/raid_${config.name}) readarray -t disk_devices < <(cat "$disko_devices_dir"/raid_${config.name})
echo 'y' | mdadm --create /dev/md/${config.name} \ echo 'y' | mdadm --create /dev/md/${config.name} \
--level=${toString config.level} \ --level=${toString config.level} \
@ -43,20 +43,20 @@
--homehost=any \ --homehost=any \
"''${disk_devices[@]}" "''${disk_devices[@]}"
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/md/${config.name}";})} ${lib.optionalString (config.content != null) config.content._create}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = _: default =
lib.optionalAttrs (config.content != null) (config.content._mount { dev = "/dev/md/${config.name}"; }); lib.optionalAttrs (config.content != null) config.content._mount;
# TODO we probably need to assemble the mdadm somehow # TODO we probably need to assemble the mdadm somehow
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
lib.optional (config.content != null) (config.content._config "/dev/md/${config.name}"); lib.optional (config.content != null) config.content._config;
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }: { config, options, lib, diskoLib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
description = "Device";
default = device;
};
name = lib.mkOption { name = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@ -26,19 +31,18 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
echo "${dev}" >> "$disko_devices_dir"/raid_${config.name} echo "${config.device}" >> "$disko_devices_dir"/raid_${config.name}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default = { };
{ };
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = _dev: [ ]; default = [ ];
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -35,11 +35,11 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = _: ""; default = "";
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = _: lib.optionalAttrs (config.mountpoint != null) { default = lib.optionalAttrs (config.mountpoint != null) {
fs.${config.mountpoint} = '' fs.${config.mountpoint} = ''
if ! findmnt ${config.fsType} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then if ! findmnt ${config.fsType} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
mount -t ${config.fsType} ${config.device} "${rootMountPoint}${config.mountpoint}" \ mount -t ${config.fsType} ${config.device} "${rootMountPoint}${config.mountpoint}" \

View file

@ -1,4 +1,4 @@
{ diskoLib, config, options, lib, parent, ... }: { diskoLib, config, options, lib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device";
};
randomEncryption = lib.mkOption { randomEncryption = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = false; default = false;
@ -24,16 +29,16 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
mkswap ${dev} mkswap ${config.device}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: { default = {
fs.${dev} = '' fs.${config.device} = ''
if ! swapon --show | grep -q '^${dev} '; then if ! swapon --show | grep -q '^${config.device} '; then
swapon ${dev} swapon ${config.device}
fi fi
''; '';
}; };
@ -41,9 +46,9 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: [{ default = [{
swapDevices = [{ swapDevices = [{
device = dev; device = config.device;
randomEncryption = config.randomEncryption; randomEncryption = config.randomEncryption;
}]; }];
}]; }];

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }: { config, options, lib, diskoLib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,13 +6,18 @@
internal = true; internal = true;
description = "Partition table"; description = "Partition table";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device to partition";
};
format = lib.mkOption { format = lib.mkOption {
type = lib.types.enum [ "gpt" "msdos" ]; type = lib.types.enum [ "gpt" "msdos" ];
default = "gpt"; default = "gpt";
description = "The kind of partition table"; description = "The kind of partition table";
}; };
partitions = lib.mkOption { partitions = lib.mkOption {
type = lib.types.listOf (lib.types.submodule ({ ... }: { type = lib.types.listOf (lib.types.submodule ({ name, ... }@partition: {
options = { options = {
part-type = lib.mkOption { part-type = lib.mkOption {
type = lib.types.enum [ "primary" "logical" "extended" ]; type = lib.types.enum [ "primary" "logical" "extended" ];
@ -48,7 +53,11 @@
default = false; default = false;
description = "Whether to make the partition bootable"; description = "Whether to make the partition bootable";
}; };
content = diskoLib.partitionType { parent = config; }; content = diskoLib.partitionType { parent = config; device = diskoLib.deviceNumbering config.device partition.config._index; };
_index = lib.mkOption {
internal = true;
default = lib.toInt (lib.head (builtins.match ".*entry ([[:digit:]]+)]" name));
};
}; };
})); }));
default = [ ]; default = [ ];
@ -72,36 +81,36 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
parted -s ${dev} -- mklabel ${config.format} parted -s ${config.device} -- mklabel ${config.format}
${lib.concatStrings (lib.imap (index: partition: '' ${lib.concatStrings (map (partition: ''
${lib.optionalString (config.format == "gpt") '' ${lib.optionalString (config.format == "gpt") ''
parted -s ${dev} -- mkpart ${partition.name} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} parted -s ${config.device} -- mkpart ${partition.name} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
''} ''}
${lib.optionalString (config.format == "msdos") '' ${lib.optionalString (config.format == "msdos") ''
parted -s ${dev} -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end} parted -s ${config.device} -- mkpart ${partition.part-type} ${diskoLib.maybeStr partition.fs-type} ${diskoLib.maybeStr partition.fs-type} ${partition.start} ${partition.end}
''} ''}
# ensure /dev/disk/by-path/..-partN exists before continuing # ensure /dev/disk/by-path/..-partN exists before continuing
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${lib.optionalString partition.bootable '' ${lib.optionalString partition.bootable ''
parted -s ${dev} -- set ${toString index} boot on parted -s ${config.device} -- set ${toString partition._index} boot on
''} ''}
${lib.concatMapStringsSep "" (flag: '' ${lib.concatMapStringsSep "" (flag: ''
parted -s ${dev} -- set ${toString index} ${flag} on parted -s ${config.device} -- set ${toString partition._index} ${flag} on
'') partition.flags} '') partition.flags}
# ensure further operations can detect new partitions # ensure further operations can detect new partitions
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${lib.optionalString (partition.content != null) (partition.content._create { dev = diskoLib.deviceNumbering dev index; })} ${lib.optionalString (partition.content != null) partition.content._create}
'') config.partitions)} '') config.partitions)}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default =
let let
partMounts = lib.foldr lib.recursiveUpdate { } (lib.imap partMounts = lib.foldr lib.recursiveUpdate { } (map
(index: partition: (partition:
lib.optionalAttrs (partition.content != null) (partition.content._mount { dev = diskoLib.deviceNumbering dev index; }) lib.optionalAttrs (partition.content != null) partition.content._mount
) )
config.partitions); config.partitions);
in in
@ -113,10 +122,10 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default =
lib.imap map
(index: partition: (partition:
lib.optional (partition.content != null) (partition.content._config (diskoLib.deviceNumbering dev index)) lib.optional (partition.content != null) partition.content._config
) )
config.partitions; config.partitions;
description = "NixOS configuration"; description = "NixOS configuration";

View file

@ -1,4 +1,4 @@
{ config, options, lib, diskoLib, parent, ... }: { config, options, lib, diskoLib, parent, device, ... }:
{ {
options = { options = {
type = lib.mkOption { type = lib.mkOption {
@ -6,6 +6,11 @@
internal = true; internal = true;
description = "Type"; description = "Type";
}; };
device = lib.mkOption {
type = lib.types.str;
default = device;
description = "Device";
};
pool = lib.mkOption { pool = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "Name of the ZFS pool"; description = "Name of the ZFS pool";
@ -25,19 +30,18 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { dev }: '' default = ''
echo "${dev}" >> "$disko_devices_dir"/zfs_${config.pool} echo "${config.device}" >> "$disko_devices_dir"/zfs_${config.pool}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { dev }: default = { };
{ };
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = _dev: [ ]; default = [ ];
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -46,18 +46,18 @@
# important to prevent accidental shadowing of mount points # important to prevent accidental shadowing of mount points
# since (create order != mount order) # since (create order != mount order)
# -p creates parents automatically # -p creates parents automatically
default = { zpool }: '' default = ''
zfs create -up ${zpool}/${config.name} \ zfs create -up ${config._parent.name}/${config.name} \
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { zpool }: default =
lib.optionalAttrs (config.options.mountpoint or "" != "none") { lib.optionalAttrs (config.options.mountpoint or "" != "none") {
fs.${config.mountpoint} = '' fs.${config.mountpoint} = ''
if ! findmnt ${zpool}/${config.name} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then if ! findmnt ${config._parent.name}/${config.name} "${rootMountPoint}${config.mountpoint}" > /dev/null 2>&1; then
mount ${zpool}/${config.name} "${rootMountPoint}${config.mountpoint}" \ mount ${config._parent.name}/${config.name} "${rootMountPoint}${config.mountpoint}" \
-o X-mount.mkdir \ -o X-mount.mkdir \
${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \ ${lib.concatMapStringsSep " " (opt: "-o ${opt}") config.mountOptions} \
${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \ ${lib.optionalString ((config.options.mountpoint or "") != "legacy") "-o zfsutil"} \
@ -69,10 +69,10 @@
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = zpool: default =
lib.optional (config.options.mountpoint or "" != "none") { lib.optional (config.options.mountpoint or "" != "none") {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = "${zpool}/${config.name}"; device = "${config._parent.name}/${config.name}";
fsType = "zfs"; fsType = "zfs";
options = config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; options = config.mountOptions ++ lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
}; };

View file

@ -30,7 +30,7 @@
description = "Size of the dataset"; description = "Size of the dataset";
}; };
content = diskoLib.partitionType { parent = config; }; content = diskoLib.partitionType { parent = config; device = "/dev/zvol/${config._parent.name}/${config.name}"; };
_parent = lib.mkOption { _parent = lib.mkOption {
internal = true; internal = true;
@ -46,23 +46,23 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = { zpool }: '' default = ''
zfs create ${zpool}/${config.name} \ zfs create ${config._parent.name}/${config.name} \
${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} -V ${config.size} ${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "-o ${n}=${v}") config.options)} -V ${config.size}
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${lib.optionalString (config.content != null) (config.content._create {dev = "/dev/zvol/${zpool}/${config.name}";})} ${lib.optionalString (config.content != null) config.content._create}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = { zpool }: default =
lib.optionalAttrs (config.content != null) (config.content._mount { dev = "/dev/zvol/${zpool}/${config.name}"; }); lib.optionalAttrs (config.content != null) config.content._mount;
}; };
_config = lib.mkOption { _config = lib.mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = zpool: default =
lib.optional (config.content != null) (config.content._config "/dev/zvol/${zpool}/${config.name}"); lib.optional (config.content != null) config.content._config;
description = "NixOS configuration"; description = "NixOS configuration";
}; };
_pkgs = lib.mkOption { _pkgs = lib.mkOption {

View file

@ -65,21 +65,21 @@
}; };
_create = diskoLib.mkCreateOption { _create = diskoLib.mkCreateOption {
inherit config options; inherit config options;
default = _: '' default = ''
readarray -t zfs_devices < <(cat "$disko_devices_dir"/zfs_${config.name}) readarray -t zfs_devices < <(cat "$disko_devices_dir"/zfs_${config.name})
zpool create -f ${config.name} \ zpool create -f ${config.name} \
-R ${config.mountRoot} ${config.mode} \ -R ${config.mountRoot} ${config.mode} \
${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[@]}" "''${zfs_devices[@]}"
${lib.concatMapStrings (dataset: dataset._create {zpool = config.name;}) (lib.attrValues config.datasets)} ${lib.concatMapStrings (dataset: dataset._create) (lib.attrValues config.datasets)}
''; '';
}; };
_mount = diskoLib.mkMountOption { _mount = diskoLib.mkMountOption {
inherit config options; inherit config options;
default = _: default =
let let
datasetMounts = diskoLib.deepMergeMap (dataset: dataset._mount { zpool = config.name; }) (lib.attrValues config.datasets); datasetMounts = diskoLib.deepMergeMap (dataset: dataset._mount) (lib.attrValues config.datasets);
in in
{ {
dev = '' dev = ''
@ -104,7 +104,7 @@
internal = true; internal = true;
readOnly = true; readOnly = true;
default = [ default = [
(map (dataset: dataset._config config.name) (lib.attrValues config.datasets)) (map (dataset: dataset._config) (lib.attrValues config.datasets))
(lib.optional (config.mountpoint != null) { (lib.optional (config.mountpoint != null) {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = config.name; device = config.name;