add mdadm support

This commit is contained in:
lassulus 2022-08-24 16:46:36 +02:00
parent 9bca66ca7d
commit 88cb7a4719
3 changed files with 99 additions and 91 deletions

60
example/raid.nix Normal file
View File

@ -0,0 +1,60 @@
# usage: nix-instantiate --eval --json --strict example/config.nix | jq .
{
type = "devices";
content = {
vdb = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
part-type = "primary";
start = "1MiB";
end = "100%";
content = {
type = "mdraid";
name = "raid1";
};
}
];
};
vdc = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
part-type = "primary";
start = "1MiB";
end = "100%";
content = {
type = "mdraid";
name = "raid1";
};
}
];
};
raid1 = {
type = "mdadm";
level = 1;
content = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
part-type = "primary";
start = "1MiB";
end = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/raid";
};
}
];
};
};
};
}

View File

@ -2,12 +2,7 @@
with lib;
with builtins;
let {
body.config = config-f {};
body.create = create-f {};
body.mount = mount-f {};
let
helper.find-device = device: let
environment = helper.device-id device;
@ -16,14 +11,14 @@ let {
if hasPrefix "/dev/disk" device then
"${environment}='${device}'"
else ''
${environment}=$(for x in /dev/disk/by-path/*; do
${environment}=$(for x in $(find /dev/disk/{by-path,by-id}/); do
dev=$x
if [ "$(readlink -f $x)" = '${device}' ]; then
if [ "$(readlink -f $x)" = "$(readlink -f '${device}')" ]; then
target=$dev
break
fi
done
if test -z $target; then
if test -z ''${target+x}; then
echo 'unable to find path of disk: ${device}, bailing out' >&2
exit 1
else
@ -71,8 +66,23 @@ let {
mkfs.${x.format} ${q.device}
'';
create.devices = q: x: ''
${concatStrings (mapAttrsToList (name: create-f { device = "/dev/${name}"; }) x.content)}
create.devices = q: x: let
raid-devices = lib.filterAttrs (_: dev: dev.type == "mdadm") x.content;
other-devices = lib.filterAttrs (_: dev: dev.type != "mdadm") x.content;
in ''
${concatStrings (mapAttrsToList (name: create-f { device = "/dev/${name}"; }) other-devices)}
${concatStrings (mapAttrsToList (name: create-f { device = "/dev/${name}"; name = name; }) raid-devices)}
'';
create.mdraid = q: x: ''
RAIDDEVICES_N_${x.name}=$((''${RAIDDEVICES_N_${x.name}:-0}+1))
RAIDDEVICES_${x.name}="''${RAIDDEVICES_${x.name}:-}${q.device} "
'';
create.mdadm = q: x: ''
echo 'y' | mdadm --create /dev/md/${q.name} --level=${toString x.level or 1} --raid-devices=''${RAIDDEVICES_N_${q.name}} ''${RAIDDEVICES_${q.name}}
udevadm trigger --subsystem-match=block; udevadm settle
${create-f { device = "/dev/md/${q.name}"; } x.content}
'';
create.luks = q: x: ''
@ -158,6 +168,10 @@ let {
mount.noop = q: x: {};
# TODO maybe we need to do something here?
mount.mdadm = mount.noop;
mount.mdraid = mount.noop;
mount.partition = q: x:
mount-f { device = "\"\${${q.device}}\"-part" + toString q.index; } x.content;
@ -166,4 +180,15 @@ let {
(foldl' recursiveUpdate {} (imap (index: mount-f (q // { inherit index; device = helper.device-id q.device; })) x.partitions))
{table.${q.device} = helper.find-device q.device;}
);
in {
config = config-f {};
create = cfg: ''
set -efux
${create-f {} cfg}
'';
mount = cfg: ''
set -efux
${mount-f {} cfg}
'';
}

View File

@ -7,84 +7,7 @@ let
inherit pkgs;
inherit (pkgs) system;
};
disko-config = {
type = "devices";
content = {
vdb = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
part-type = "ESP";
start = "1MiB";
end = "100MiB";
fs-type = "FAT32";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
options = [
"defaults"
];
};
}
{
type = "partition";
part-type = "primary";
start = "100MiB";
end = "100%";
content = {
type = "luks";
algo = "aes-xts...";
name = "crypted";
keyfile = "/tmp/secret.key";
extraArgs = [
"--hash sha512"
"--iter-time 5000"
];
content = {
type = "lvm";
name = "pool";
lvs = {
root = {
type = "lv";
size = "100M";
mountpoint = "/";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
options = [
"defaults"
];
};
};
home = {
type = "lv";
size = "10M";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/home";
};
};
raw = {
type = "lv";
size = "10M";
content = {
type = "noop";
};
};
};
};
};
}
];
};
};
};
disko-config = import ../example/raid.nix;
tsp-create = pkgs.writeScript "create" ((pkgs.callPackage ../. {}).create disko-config);
tsp-mount = pkgs.writeScript "mount" ((pkgs.callPackage ../. {}).mount disko-config);
in makeTest' {
@ -102,7 +25,7 @@ in makeTest' {
# speed-up eval
documentation.enable = false;
virtualisation.emptyDiskImages = [ 512 ];
virtualisation.emptyDiskImages = [ 512 512 ];
};
testScript = ''
@ -110,6 +33,6 @@ in makeTest' {
machine.succeed("${tsp-create}");
machine.succeed("${tsp-mount}");
machine.succeed("${tsp-mount}"); # verify that the command is idempotent
machine.succeed("test -b /dev/mapper/pool-raw");
machine.succeed("test -b /dev/md/raid1");
'';
}