Merge pull request #43 from nix-community/test-config

add nixos tests for disko.config
This commit is contained in:
Jörg Thalheim 2022-10-04 11:30:22 +02:00 committed by GitHub
commit c96ccd7d9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 492 additions and 142 deletions

117
example/boot-raid1.nix Normal file
View file

@ -0,0 +1,117 @@
{ disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = {
one = {
type = "disk";
device = builtins.elemAt disks 0;
content = {
type = "table";
format = "gpt";
partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "1M";
part-type = "primary";
flags = ["bios_grub"];
}
{
type = "partition";
name = "ESP";
start = "1MiB";
end = "128MiB";
fs-type = "fat32";
bootable = true;
content = {
type = "mdraid";
name = "boot";
};
}
{
type = "partition";
name = "mdadm";
start = "128MiB";
end = "100%";
content = {
type = "mdraid";
name = "raid1";
};
}
];
};
};
two = {
type = "disk";
device = builtins.elemAt disks 1;
content = {
type = "table";
format = "gpt";
partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "1M";
part-type = "primary";
flags = ["bios_grub"];
}
{
type = "partition";
name = "ESP";
start = "1MiB";
end = "128MiB";
fs-type = "fat32";
bootable = true;
content = {
type = "mdraid";
name = "boot";
};
}
{
type = "partition";
name = "mdadm";
start = "128MiB";
end = "100%";
content = {
type = "mdraid";
name = "raid1";
};
}
];
};
};
};
mdadm = {
boot = {
type = "mdadm";
level = 1;
metadata = "1.0";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
raid1 = {
type = "mdadm";
level = 1;
content = {
type = "table";
format = "gpt";
partitions = [
{
type = "partition";
name = "primary";
start = "1MiB";
end = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
}
];
};
};
};
}

View file

@ -1,16 +1,29 @@
{ { disks ? [ "/dev/vdb" ] }: {
disk = { disk = {
vdb = { vdb = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
type = "partition";
name = "ESP";
start = "1MiB";
end = "128MiB";
fs-type = "fat32";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
}
{ {
name = "root"; name = "root";
type = "partition"; type = "partition";
start = "0%"; start = "128MiB";
end = "100%"; end = "100%";
content = { content = {
type = "btrfs"; type = "btrfs";

View file

@ -1,25 +1,40 @@
{ { disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = { disk = {
disk1 = { disk0 = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{ {
type = "partition"; type = "partition";
start = "0"; name = "ESP";
end = "1M"; start = "1MiB";
name = "grub"; end = "128MiB";
flags = ["bios_grub"]; fs-type = "fat32";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
} }
];
};
};
disk1 = {
type = "disk";
device = builtins.elemAt disks 1;
content = {
type = "table";
format = "gpt";
partitions = [
{ {
type = "partition"; type = "partition";
start = "1M"; start = "1M";
end = "100%"; end = "100%";
name = "luks"; name = "luks";
bootable = true;
content = { content = {
type = "luks"; type = "luks";
name = "crypted1"; name = "crypted1";
@ -39,24 +54,16 @@
}; };
disk2 = { disk2 = {
type = "disk"; type = "disk";
device = "/dev/vdc"; device = builtins.elemAt disks 2;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
type = "partition";
start = "0";
end = "1M";
name = "grub";
flags = ["bios_grub"];
}
{ {
type = "partition"; type = "partition";
start = "1M"; start = "1M";
end = "100%"; end = "100%";
name = "luks"; name = "luks";
bootable = true;
content = { content = {
type = "luks"; type = "luks";
name = "crypted2"; name = "crypted2";
@ -81,17 +88,17 @@
level = 1; level = 1;
content = { content = {
type = "table"; type = "table";
format = "msdos"; format = "gpt";
partitions = [ partitions = [
{ {
type = "partition"; type = "partition";
name = "xfs"; name = "bla";
start = "1MiB"; start = "1MiB";
end = "100%"; end = "100%";
content = { content = {
type = "filesystem"; type = "filesystem";
format = "xfs"; format = "ext4";
mountpoint = "/xfs_mdadm_lvm"; mountpoint = "/ext4_mdadm_lvm";
}; };
} }
]; ];

View file

@ -1,14 +0,0 @@
# usage: nix-instantiate --eval --json --strict example | jq -r .
let
cfg = import ./config.nix;
#cfg = import ./config-gpt-bios.nix;
in
# TODO: get rid of NIX_PATH dependency here
with import ../. {};
{
config = config cfg;
create = create cfg;
mount = mount cfg;
}

View file

@ -1,8 +1,8 @@
# Example to create a bios compatible gpt partition # Example to create a bios compatible gpt partition
{ { disks ? [ "/dev/vdb" ] }: {
disk = { disk = {
vdb = { vdb = {
device = "/dev/vdb"; device = builtins.elemAt disks 0;
type = "disk"; type = "disk";
content = { content = {
type = "table"; type = "table";

View file

@ -1,8 +1,8 @@
{ { disks ? [ "/dev/vdb" ] }: {
disk = { disk = {
vdb = { vdb = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
@ -10,7 +10,6 @@
{ {
type = "partition"; type = "partition";
name = "ESP"; name = "ESP";
# fs-type = "FAT32";
start = "1MiB"; start = "1MiB";
end = "100MiB"; end = "100MiB";
bootable = true; bootable = true;
@ -34,7 +33,6 @@
keyFile = "/tmp/secret.key"; keyFile = "/tmp/secret.key";
extraArgs = [ extraArgs = [
"--hash sha512" "--hash sha512"
"--iter-time 5000"
]; ];
content = { content = {
type = "lvm_pv"; type = "lvm_pv";

View file

@ -1,16 +1,28 @@
{ { disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = { disk = {
vdb = { one = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "100M";
fs-type = "fat32";
bootable = true;
content = {
type = "mdraid";
name = "boot";
};
}
{ {
type = "partition"; type = "partition";
name = "primary"; name = "primary";
start = "0%"; start = "100M";
end = "100%"; end = "100%";
content = { content = {
type = "lvm_pv"; type = "lvm_pv";
@ -20,17 +32,29 @@
]; ];
}; };
}; };
vdc = { two = {
type = "disk"; type = "disk";
device = "/dev/vdc"; device = builtins.elemAt disks 1;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "100M";
fs-type = "fat32";
bootable = true;
content = {
type = "mdraid";
name = "boot";
};
}
{ {
type = "partition"; type = "partition";
name = "primary"; name = "primary";
start = "0%"; start = "100M";
end = "100%"; end = "100%";
content = { content = {
type = "lvm_pv"; type = "lvm_pv";
@ -41,6 +65,18 @@
}; };
}; };
}; };
mdadm = {
boot = {
type = "mdadm";
level = 1;
metadata = "1.0";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
};
lvm_vg = { lvm_vg = {
pool = { pool = {
type = "lvm_vg"; type = "lvm_vg";

View file

@ -1,12 +1,20 @@
{ { disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = { disk = {
vdb = { vdb = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "1M";
part-type = "primary";
flags = ["bios_grub"];
}
{ {
type = "partition"; type = "partition";
name = "mdadm"; name = "mdadm";
@ -22,11 +30,19 @@
}; };
vdc = { vdc = {
type = "disk"; type = "disk";
device = "/dev/vdc"; device = builtins.elemAt disks 1;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{
name = "boot";
type = "partition";
start = "0";
end = "1M";
part-type = "primary";
flags = ["bios_grub"];
}
{ {
type = "partition"; type = "partition";
name = "mdadm"; name = "mdadm";
@ -57,7 +73,7 @@
content = { content = {
type = "filesystem"; type = "filesystem";
format = "ext4"; format = "ext4";
mountpoint = "/raid"; mountpoint = "/";
}; };
} }
]; ];

View file

@ -1,15 +1,30 @@
{ { disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = { disk = {
vdb = { vdb = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "table"; type = "table";
format = "gpt"; format = "gpt";
partitions = [ partitions = [
{ {
type = "partition"; type = "partition";
start = "0%"; name = "ESP";
start = "1MiB";
end = "100MiB";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
options = [
"defaults"
];
};
}
{
type = "partition";
start = "100MiB";
end = "100%"; end = "100%";
name = "primary"; name = "primary";
bootable = true; bootable = true;
@ -24,7 +39,7 @@
}; };
vdc = { vdc = {
type = "disk"; type = "disk";
device = "/dev/vdc"; device = builtins.elemAt disks 1;
content = { content = {
type = "zfs"; type = "zfs";
pool = "zroot"; pool = "zroot";
@ -34,10 +49,16 @@
zpool = { zpool = {
zroot = { zroot = {
type = "zpool"; type = "zpool";
rootFsOptions.mountpoint = "none";
datasets = { datasets = {
zfs_fs = { "root" = {
zfs_type = "filesystem";
options.mountpoint = "none";
};
"root/zfs_fs" = {
zfs_type = "filesystem"; zfs_type = "filesystem";
mountpoint = "/zfs_fs"; mountpoint = "/zfs_fs";
options.mountpoint = "/zfs_fs";
options."com.sun:auto-snapshot" = "true"; options."com.sun:auto-snapshot" = "true";
}; };
}; };

View file

@ -1,19 +1,56 @@
{ { disks ? [ "/dev/vdb" "/dev/vdc" ] }: {
disk = { disk = {
vdb = { x = {
type = "disk"; type = "disk";
device = "/dev/vdb"; device = builtins.elemAt disks 0;
content = { content = {
type = "zfs"; type = "table";
pool = "zroot"; format = "gpt";
partitions = [
{
type = "partition";
name = "ESP";
start = "0";
end = "64MiB";
fs-type = "fat32";
bootable = true;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
}
{
type = "partition";
name = "zfs";
start = "128MiB";
end = "100%";
content = {
type = "zfs";
pool = "zroot";
};
}
];
}; };
}; };
vdc = { y = {
type = "disk"; type = "disk";
device = "/dev/vdc"; device = builtins.elemAt disks 1;
content = { content = {
type = "zfs"; type = "table";
pool = "zroot"; format = "gpt";
partitions = [
{
type = "partition";
name = "zfs";
start = "128MiB";
end = "100%";
content = {
type = "zfs";
pool = "zroot";
};
}
];
}; };
}; };
}; };

View file

@ -14,6 +14,7 @@
import ./tests { import ./tests {
inherit pkgs; inherit pkgs;
makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix"); makeTest = import (pkgs.path + "/nixos/tests/make-test-python.nix");
eval-config = import (pkgs.path + "/nixos/lib/eval-config.nix");
}; };
}; };
} }

10
tests/boot-raid1.nix Normal file
View file

@ -0,0 +1,10 @@
{ pkgs ? (import <nixpkgs> { })
, makeDiskoTest ? (pkgs.callPackage ./lib.nix { }).makeDiskoTest
}:
makeDiskoTest {
disko-config = import ../example/boot-raid1.nix;
extraTestScript = ''
machine.succeed("test -b /dev/md/boot");
machine.succeed("mountpoint /boot");
'';
}

View file

@ -4,8 +4,8 @@
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/btrfs-subvolumes.nix; disko-config = import ../example/btrfs-subvolumes.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("test -e /mnt/test"); machine.succeed("test -e /test");
machine.succeed("btrfs subvolume list /mnt | grep -qs 'path test$'"); machine.succeed("btrfs subvolume list / | grep -qs 'path test$'");
''; '';
} }

View file

@ -3,16 +3,23 @@
}: }:
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/complex.nix; disko-config = import ../example/complex.nix;
extraConfig = {
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
};
extraTestScript = '' extraTestScript = ''
machine.succeed("test -b /dev/zroot/zfs_testvolume"); machine.succeed("test -b /dev/zroot/zfs_testvolume");
machine.succeed("test -b /dev/md/raid1p1"); machine.succeed("test -b /dev/md/raid1p1");
machine.succeed("mountpoint /mnt"); machine.succeed("mountpoint /zfs_fs");
machine.succeed("mountpoint /mnt/zfs_fs"); machine.succeed("mountpoint /zfs_legacy_fs");
machine.succeed("mountpoint /mnt/zfs_legacy_fs"); machine.succeed("mountpoint /ext4onzfs");
machine.succeed("mountpoint /mnt/ext4onzfs"); machine.succeed("mountpoint /ext4_on_lvm");
machine.succeed("mountpoint /mnt/ext4_on_lvm"); '';
enableOCR = true;
bootCommands = ''
machine.wait_for_text("Passphrase for")
machine.send_chars("secret\n")
''; '';
extraConfig = { extraConfig = {
boot.kernelModules = [ "dm-raid" "dm-mirror" ]; boot.kernelModules = [ "dm-raid" "dm-mirror" ];

View file

@ -1,9 +1,10 @@
{ makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix> { makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
, pkgs ? (import <nixpkgs> { }) , pkgs ? (import <nixpkgs> { })
}@args: }@args:
let let
lib = pkgs.lib; lib = pkgs.lib;
makeDiskoTest = (pkgs.callPackage ./lib.nix { inherit makeTest; }).makeDiskoTest; makeDiskoTest = (pkgs.callPackage ./lib.nix { inherit makeTest eval-config; }).makeDiskoTest;
evalTest = name: configFile: let evalTest = name: configFile: let
disko-config = import configFile; disko-config = import configFile;

View file

@ -4,7 +4,8 @@
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/gpt-bios-compat.nix; disko-config = import ../example/gpt-bios-compat.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("mountpoint /mnt"); machine.succeed("mountpoint /");
machine.succeed("grub-install --target=i386-pc /dev/vdb");
''; '';
efi = false;
grub-devices = [ "/dev/vdb" ];
} }

View file

@ -1,12 +1,17 @@
{ pkgs ? (import <nixpkgs> { }) { pkgs ? (import <nixpkgs> { })
, makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix> , makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
, ... , ...
}: }:
{ {
makeDiskoTest = makeDiskoTest =
{ disko-config { disko-config
, extraTestScript , extraTestScript ? ""
, bootCommands ? ""
, extraConfig ? { } , extraConfig ? { }
, grub-devices ? [ "nodev" ]
, efi ? true
, enableOCR ? false
}: }:
let let
lib = pkgs.lib; lib = pkgs.lib;
@ -15,33 +20,107 @@
inherit pkgs; inherit pkgs;
inherit (pkgs) system; inherit (pkgs) system;
}; };
tsp-create = pkgs.writeScript "create" ((pkgs.callPackage ../. { }).create disko-config); disks = [ "/dev/vda" "/dev/vdb" "/dev/vdc" "/dev/vdd" "/dev/vde" "/dev/vdf" ];
tsp-mount = pkgs.writeScript "mount" ((pkgs.callPackage ../. { }).mount disko-config); tsp-create = pkgs.writeScript "create" ((pkgs.callPackage ../. { }).create (disko-config { disks = builtins.tail disks; }));
num-disks = builtins.length (lib.attrNames disko-config.disk); tsp-mount = pkgs.writeScript "mount" ((pkgs.callPackage ../. { }).mount (disko-config { disks = builtins.tail disks; }));
tsp-config = (pkgs.callPackage ../. { }).config (disko-config { inherit disks; });
num-disks = builtins.length (lib.attrNames (disko-config {}).disk);
installed-system = { modulesPath, ... }: {
imports = [
tsp-config
(modulesPath + "/testing/test-instrumentation.nix")
(modulesPath + "/profiles/qemu-guest.nix")
(modulesPath + "/profiles/minimal.nix")
extraConfig
];
fileSystems."/nix/store" = {
device = "nix-store";
fsType = "9p";
neededForBoot = true;
options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
};
documentation.enable = false;
hardware.enableAllFirmware = lib.mkForce false;
networking.hostId = "8425e349"; # from profiles/base.nix, needed for zfs
boot.kernelParams = lib.mkAfter [ "console=tty0" ]; # needed to have serial interaction during boot
boot.zfs.devNodes = "/dev/disk/by-uuid"; # needed because /dev/disk/by-id is empty in qemu-vms
boot.consoleLogLevel = lib.mkForce 100;
boot.loader.grub = {
devices = grub-devices;
efiSupport = efi;
efiInstallAsRemovable = efi;
};
};
installedTopLevel = (eval-config {
modules = [ installed-system ];
system = "x86_64-linux";
}).config.system.build.toplevel;
in in
makeTest' { makeTest' {
name = "disko"; name = "disko";
nodes.machine = inherit enableOCR;
{ config, pkgs, modulesPath, ... }: nodes.machine = { config, pkgs, modulesPath, ... }: {
imports = [
(modulesPath + "/profiles/base.nix")
(modulesPath + "/profiles/minimal.nix")
extraConfig
];
{ # speed-up eval
imports = [ documentation.enable = false;
(modulesPath + "/profiles/installation-device.nix")
(modulesPath + "/profiles/base.nix")
];
# speed-up eval nix.settings = {
documentation.enable = false; substituters = lib.mkForce [];
hashed-mirrors = null;
connect-timeout = 1;
};
virtualisation.emptyDiskImages = builtins.genList (_: 512) num-disks; virtualisation.emptyDiskImages = builtins.genList (_: 4096) num-disks;
} // extraConfig; };
testScript = '' testScript = ''
machine.succeed("echo 'secret' > /tmp/secret.key"); def disks(oldmachine, num_disks):
machine.succeed("${tsp-create}"); disk_flags = ""
machine.succeed("${tsp-mount}"); for i in range(num_disks):
machine.succeed("${tsp-mount}"); # verify that the command is idempotent disk_flags += f' -drive file={oldmachine.state_dir}/empty{i}.qcow2,id=drive{i + 1},if=none,index={i + 1},werror=report'
disk_flags += f' -device virtio-blk-pci,drive=drive{i + 1}'
return disk_flags
def create_test_machine(oldmachine=None, args={}): # taken from <nixpkgs/nixos/tests/installer.nix>
machine = create_machine({
"qemuFlags": "-cpu max -m 1024 -virtfs local,path=/nix/store,security_model=none,mount_tag=nix-store" + disks(oldmachine, ${toString num-disks}),
${lib.optionalString efi ''"bios": "${pkgs.OVMF.fd}/FV/OVMF.fd",''}
} | args)
driver.machines.append(machine)
return machine
machine.start()
machine.succeed("echo -n 'secret' > /tmp/secret.key")
machine.succeed("${tsp-create}")
machine.succeed("${tsp-mount}")
machine.succeed("${tsp-mount}") # verify that the command is idempotent
# mount nix-store in /mnt
machine.succeed("mkdir -p /mnt/nix/store")
machine.succeed("mount --bind /nix/store /mnt/nix/store")
machine.succeed("nix-store --load-db < ${pkgs.closureInfo {rootPaths = [installedTopLevel];}}/registration")
# fix "this is not a NixOS installation"
machine.succeed("mkdir -p /mnt/etc")
machine.succeed("touch /mnt/etc/NIXOS")
machine.succeed("mkdir -p /mnt/nix/var/nix/profiles")
machine.succeed("nix-env -p /mnt/nix/var/nix/profiles/system --set ${installedTopLevel}")
machine.succeed("NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root /mnt -- ${installedTopLevel}/bin/switch-to-configuration boot")
machine.succeed("sync")
machine.shutdown()
machine = create_test_machine(oldmachine=machine, args={ "name": "booted_machine" })
machine.start()
${bootCommands}
machine.wait_for_unit("local-fs.target")
${extraTestScript} ${extraTestScript}
''; '';
}; };

View file

@ -4,7 +4,12 @@
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/luks-lvm.nix; disko-config = import ../example/luks-lvm.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("cryptsetup isLuks /dev/vdb2"); machine.succeed("cryptsetup isLuks /dev/vda2");
machine.succeed("mountpoint /mnt/home"); machine.succeed("mountpoint /home");
'';
enableOCR = true;
bootCommands = ''
machine.wait_for_text("Passphrase for")
machine.send_chars("secret\n")
''; '';
} }

View file

@ -4,9 +4,9 @@
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/lvm-raid.nix; disko-config = import ../example/lvm-raid.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("mountpoint /mnt/home"); machine.succeed("mountpoint /home");
''; '';
extraConfig = { extraConfig = {
boot.kernelModules = [ "dm-raid" "dm-mirror" ]; boot.kernelModules = [ "dm-raid0" "dm-mirror" ];
}; };
} }

View file

@ -5,6 +5,8 @@ makeDiskoTest {
disko-config = import ../example/mdadm.nix; disko-config = import ../example/mdadm.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("test -b /dev/md/raid1"); machine.succeed("test -b /dev/md/raid1");
machine.succeed("mountpoint /mnt/raid"); machine.succeed("mountpoint /");
''; '';
efi = false;
grub-devices = [ "/dev/vdb" "/dev/vdc" ];
} }

View file

@ -4,9 +4,8 @@
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/zfs-over-legacy.nix; disko-config = import ../example/zfs-over-legacy.nix;
extraTestScript = '' extraTestScript = ''
machine.succeed("test -e /mnt/zfs_fs"); machine.succeed("test -e /zfs_fs");
machine.succeed("mountpoint /mnt"); machine.succeed("mountpoint /zfs_fs");
machine.succeed("mountpoint /mnt/zfs_fs");
''; '';
} }

View file

@ -3,6 +3,9 @@
}: }:
makeDiskoTest { makeDiskoTest {
disko-config = import ../example/zfs.nix; disko-config = import ../example/zfs.nix;
extraConfig = {
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
};
extraTestScript = '' extraTestScript = ''
machine.succeed("test -b /dev/zvol/zroot/zfs_testvolume"); machine.succeed("test -b /dev/zvol/zroot/zfs_testvolume");
@ -19,9 +22,8 @@ makeDiskoTest {
assert_property("zroot/zfs_testvolume", "volsize", "10M") assert_property("zroot/zfs_testvolume", "volsize", "10M")
assert_property("zroot/zfs_unmounted_fs", "mountpoint", "none") assert_property("zroot/zfs_unmounted_fs", "mountpoint", "none")
machine.succeed("mountpoint /mnt"); machine.succeed("mountpoint /zfs_fs");
machine.succeed("mountpoint /mnt/zfs_fs"); machine.succeed("mountpoint /zfs_legacy_fs");
machine.succeed("mountpoint /mnt/zfs_legacy_fs"); machine.succeed("mountpoint /ext4onzfs");
machine.succeed("mountpoint /mnt/ext4onzfs");
''; '';
} }

View file

@ -33,8 +33,8 @@ rec {
deepMergeMap :: -> (AttrSet -> AttrSet ) -> [ AttrSet ] -> Attrset deepMergeMap :: -> (AttrSet -> AttrSet ) -> [ AttrSet ] -> Attrset
Example: Example:
deepMergeMap (x: x.t = "test") [ { x = { y = 1; z = 3; }; } { x = { 123 = 234; }; } ] deepMergeMap (x: x.t = "test") [ { x = { y = 1; z = 3; }; } { x = { bla = 234; }; } ]
=> { x = { y = 1; z = 3; 123 = 234; t = "test"; }; } => { x = { y = 1; z = 3; bla = 234; t = "test"; }; }
*/ */
deepMergeMap = f: listOfAttrs: deepMergeMap = f: listOfAttrs:
foldr (attr: acc: (recursiveUpdate acc (f attr))) {} listOfAttrs; foldr (attr: acc: (recursiveUpdate acc (f attr))) {} listOfAttrs;
@ -216,12 +216,12 @@ rec {
}; };
config = mkOption { config = mkOption {
readOnly = true; readOnly = true;
default = diskoLib.deepMergeMap (dev: dev._config) (flatten (map attrValues [ default = { imports = flatten (map (dev: dev._config) (flatten (map attrValues [
config.devices.disk config.devices.disk
config.devices.lvm_vg config.devices.lvm_vg
config.devices.mdadm config.devices.mdadm
config.devices.zpool config.devices.zpool
])); ])));};
}; };
}; };
}); });
@ -283,12 +283,12 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: { default = dev: [{
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = dev; device = dev;
fsType = "btrfs"; fsType = "btrfs";
}; };
}; }];
}; };
}; };
}); });
@ -351,12 +351,12 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: { default = dev: [{
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = dev; device = dev;
fsType = config.format; fsType = config.format;
}; };
}; }];
}; };
}; };
}); });
@ -409,7 +409,7 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default = dev:
diskoLib.deepMergeMap (partition: partition._config dev) config.partitions; map (partition: partition._config dev) config.partitions;
}; };
}; };
}); });
@ -495,7 +495,7 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default = dev:
optionalAttrs (!isNull config.content) (config.content._config (diskoLib.deviceNumbering dev config.index)); optional (!isNull config.content) (config.content._config (diskoLib.deviceNumbering dev config.index));
}; };
}; };
}); });
@ -536,7 +536,7 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: {}; default = dev: [];
}; };
}; };
}); });
@ -589,7 +589,7 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
diskoLib.deepMergeMap (lv: lv._config config.name) (attrValues config.lvs); map (lv: lv._config config.name) (attrValues config.lvs);
}; };
}; };
}); });
@ -648,8 +648,13 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default = vg:
optionalAttrs (!isNull config.content) (config.content._config dev); [
(optional (!isNull config.content) (config.content._config "/dev/${vg}/${config.name}"))
(optional (!isNull config.lvm_type) {
boot.initrd.kernelModules = [ "dm-${config.lvm_type}" ];
})
];
}; };
}; };
}); });
@ -689,7 +694,7 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: {}; default = dev: [];
}; };
}; };
}); });
@ -775,15 +780,16 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
recursiveUpdate [
(diskoLib.deepMergeMap (dataset: dataset._config config.name) (attrValues config.datasets)) (map (dataset: dataset._config config.name) (attrValues config.datasets))
(optionalAttrs (!isNull config.mountpoint) { (optional (!isNull config.mountpoint) {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = config.name; device = config.name;
fsType = "zfs"; fsType = "zfs";
options = lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; options = lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
}; };
}); })
];
}; };
}; };
}); });
@ -865,14 +871,14 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = zpool: default = zpool:
optionalAttrs (config.zfs_type == "volume" && !isNull config.content) (config.content._config "/dev/zvol/${zpool}/${config.name}") // (optional (config.zfs_type == "volume" && !isNull config.content) (config.content._config "/dev/zvol/${zpool}/${config.name}")) ++
optionalAttrs (config.zfs_type == "filesystem" && config.options.mountpoint or "" != "none") { (optional (config.zfs_type == "filesystem" && config.options.mountpoint or "" != "none") {
fileSystems.${config.mountpoint} = { fileSystems.${config.mountpoint} = {
device = "${zpool}/${config.name}"; device = "${zpool}/${config.name}";
fsType = "zfs"; fsType = "zfs";
options = lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil"; options = lib.optional ((config.options.mountpoint or "") != "legacy") "zfsutil";
};
}; };
});
}; };
}; };
}); });
@ -892,6 +898,10 @@ rec {
type = types.int; type = types.int;
default = 1; default = 1;
}; };
metadata = mkOption {
type = types.enum [ "1" "1.0" "1.1" "1.2" "default" "ddf" "imsm" ];
default = "default";
};
content = diskoLib.deviceType; content = diskoLib.deviceType;
_meta = mkOption { _meta = mkOption {
internal = true; internal = true;
@ -908,6 +918,8 @@ rec {
echo 'y' | mdadm --create /dev/md/${config.name} \ echo 'y' | mdadm --create /dev/md/${config.name} \
--level=${toString config.level} \ --level=${toString config.level} \
--raid-devices=''${RAIDDEVICES_N_${config.name}} \ --raid-devices=''${RAIDDEVICES_N_${config.name}} \
--metadata=${config.metadata} \
--homehost=any \
''${RAIDDEVICES_${config.name}} ''${RAIDDEVICES_${config.name}}
udevadm trigger --subsystem-match=block; udevadm settle udevadm trigger --subsystem-match=block; udevadm settle
${optionalString (!isNull config.content) (config.content._create "/dev/md/${config.name}")} ${optionalString (!isNull config.content) (config.content._create "/dev/md/${config.name}")}
@ -925,7 +937,7 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
optionalAttrs (!isNull config.content) (config.content._config "/dev/md/${config.name}"); optional (!isNull config.content) (config.content._config "/dev/md/${config.name}");
}; };
}; };
}); });
@ -967,7 +979,7 @@ rec {
_config = mkOption { _config = mkOption {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: {}; default = dev: [];
}; };
}; };
}); });
@ -1028,10 +1040,10 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = dev: default = dev:
recursiveUpdate { [
# TODO do we need this always in initrd and only there? # TODO do we need this always in initrd and only there?
boot.initrd.luks.devices.${config.name}.device = dev; { boot.initrd.luks.devices.${config.name}.device = dev; }
} (optionalAttrs (!isNull config.content) (config.content._config "/dev/mapper/${config.name}")); ] ++ (optional (!isNull config.content) (config.content._config "/dev/mapper/${config.name}"));
}; };
}; };
}); });
@ -1073,7 +1085,7 @@ rec {
internal = true; internal = true;
readOnly = true; readOnly = true;
default = default =
optionalAttrs (!isNull config.content) (config.content._config config.device); optional (!isNull config.content) (config.content._config config.device);
}; };
}; };
}); });