From 059845b11dee568f84c6d10423896109bd31a3cb Mon Sep 17 00:00:00 2001 From: Jacek Galowicz Date: Tue, 28 Jan 2020 08:54:05 +0100 Subject: [PATCH] nixosTests.installer: Port to python --- nixos/tests/installer.nix | 999 +++++++++++++++++++------------------- 1 file changed, 510 insertions(+), 489 deletions(-) diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 024445b01b6c..983861911e0d 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -3,7 +3,7 @@ pkgs ? import ../.. { inherit system config; } }: -with import ../lib/testing.nix { inherit system pkgs; }; +with import ../lib/testing-python.nix { inherit system pkgs; }; with pkgs.lib; let @@ -67,161 +67,193 @@ let , grubIdentifier, preBootCommands, extraConfig , testCloneConfig }: - let - iface = if grubVersion == 1 then "ide" else "virtio"; - isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); - - # FIXME don't duplicate the -enable-kvm etc. flags here yet again! - qemuFlags = - (if system == "x86_64-linux" then "-m 768 " else "-m 512 ") + - (optionalString (system == "x86_64-linux") "-cpu host ") + - (optionalString (system == "aarch64-linux") "-enable-kvm -machine virt,gic-version=host -cpu host "); - - hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", '' - + optionalString isEfi (if pkgs.stdenv.isAarch64 - then ''bios => "${pkgs.OVMF.fd}/FV/QEMU_EFI.fd", '' - else ''bios => "${pkgs.OVMF.fd}/FV/OVMF.fd", ''); + let iface = if grubVersion == 1 then "ide" else "virtio"; + isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); + bios = if pkgs.stdenv.isAarch64 then "QEMU_EFI.fd" else "OVMF.fd"; in if !isEfi && !(pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then throw "Non-EFI boot methods are only supported on i686 / x86_64" else '' + def assemble_qemu_flags(): + flags = "-cpu host" + ${if system == "x86_64-linux" + then ''flags += " -m 768"'' + else ''flags += " -m 512 -enable-kvm -machine virt,gic-version=host"'' + } + return flags - $machine->start; - # Make sure that we get a login prompt etc. - $machine->succeed("echo hello"); - #$machine->waitForUnit('getty@tty2'); - #$machine->waitForUnit("rogue"); - $machine->waitForUnit("nixos-manual"); + qemu_flags = {"qemuFlags": assemble_qemu_flags()} - # Wait for hard disks to appear in /dev - $machine->succeed("udevadm settle"); + hd_flags = { + "hdaInterface": "${iface}", + "hda": "vm-state-machine/machine.qcow2", + } + ${optionalString isEfi '' + hd_flags.update( + bios="${pkgs.OVMF.fd}/FV/${bios}" + )'' + } + default_flags = {**hd_flags, **qemu_flags} + + + def create_machine_named(name): + return create_machine({**default_flags, "name": "boot-after-install"}) + + + machine.start() + + with subtest("Assert readiness of login prompt"): + machine.succeed("echo hello") + machine.wait_for_unit("nixos-manual") + + with subtest("Wait for hard disks to appear in /dev"): + machine.succeed("udevadm settle") - # Partition the disk. ${createPartitions} - # Create the NixOS configuration. - $machine->succeed("nixos-generate-config --root /mnt"); + with subtest("Create the NixOS configuration"): + machine.succeed("nixos-generate-config --root /mnt") + machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2") + machine.copy_from_host( + "${ makeConfig { + inherit bootLoader grubVersion grubDevice grubIdentifier + grubUseEfi extraConfig; + } + }", + "/mnt/etc/nixos/configuration.nix", + ) - $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2"); + with subtest("Perform the installation"): + machine.succeed("nixos-install < /dev/null >&2") - $machine->copyFileFromHost( - "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; } }", - "/mnt/etc/nixos/configuration.nix"); + with subtest("Do it again to make sure it's idempotent"): + machine.succeed("nixos-install < /dev/null >&2") - # Perform the installation. - $machine->succeed("nixos-install < /dev/null >&2"); - - # Do it again to make sure it's idempotent. - $machine->succeed("nixos-install < /dev/null >&2"); - - $machine->succeed("umount /mnt/boot || true"); - $machine->succeed("umount /mnt"); - $machine->succeed("sync"); - - $machine->shutdown; + with subtest("Shutdown system after installation"): + machine.succeed("umount /mnt/boot || true") + machine.succeed("umount /mnt") + machine.succeed("sync") + machine.shutdown() # Now see if we can boot the installation. - $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "boot-after-install" }); + machine = create_machine_named("boot-after-install") # For example to enter LUKS passphrase. ${preBootCommands} - # Did /boot get mounted? - $machine->waitForUnit("local-fs.target"); + with subtest("Assert that /boot get mounted"): + machine.wait_for_unit("local-fs.target") + ${if bootLoader == "grub" + then ''machine.succeed("test -e /boot/grub")'' + else ''machine.succeed("test -e /boot/loader/loader.conf")'' + } - ${if bootLoader == "grub" then - ''$machine->succeed("test -e /boot/grub");'' - else - ''$machine->succeed("test -e /boot/loader/loader.conf");'' - } + with subtest("Check whether /root has correct permissions"): + assert "700" in machine.succeed("stat -c '%a' /root") - # Check whether /root has correct permissions. - $machine->succeed("stat -c '%a' /root") =~ /700/ or die; + with subtest("Assert swap device got activated"): + # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved + machine.wait_for_unit("swap.target") + machine.succeed("cat /proc/swaps | grep -q /dev") - # Did the swap device get activated? - # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved - $machine->waitForUnit("swap.target"); - $machine->succeed("cat /proc/swaps | grep -q /dev"); + with subtest("Check that the store is in good shape"): + machine.succeed("nix-store --verify --check-contents >&2") - # Check that the store is in good shape - $machine->succeed("nix-store --verify --check-contents >&2"); + with subtest("Check whether the channel works"): + machine.succeed("nix-env -iA nixos.procps >&2") + assert ".nix-profile" in machine.succeed("type -tP ps | tee /dev/stderr") - # Check whether the channel works. - $machine->succeed("nix-env -iA nixos.procps >&2"); - $machine->succeed("type -tP ps | tee /dev/stderr") =~ /.nix-profile/ - or die "nix-env failed"; + with subtest( + "Check that the daemon works, and that non-root users can run builds " + "(this will build a new profile generation through the daemon)" + ): + machine.succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2") - # Check that the daemon works, and that non-root users can run builds (this will build a new profile generation through the daemon) - $machine->succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2"); + with subtest("Configure system with writable Nix store on next boot"): + # we're not using copy_from_host here because the installer image + # doesn't know about the host-guest sharing mechanism. + machine.copy_from_host_via_shell( + "${ makeConfig { + inherit bootLoader grubVersion grubDevice grubIdentifier + grubUseEfi extraConfig; + forceGrubReinstallCount = 1; + } + }", + "/etc/nixos/configuration.nix", + ) - # We need a writable Nix store on next boot. - $machine->copyFileFromHost( - "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 1; } }", - "/etc/nixos/configuration.nix"); + with subtest("Check whether nixos-rebuild works"): + machine.succeed("nixos-rebuild switch >&2") - # Check whether nixos-rebuild works. - $machine->succeed("nixos-rebuild switch >&2"); + with subtest("Test nixos-option"): + kernel_modules = machine.succeed("nixos-option boot.initrd.kernelModules") + assert "virtio_console" in kernel_modules + assert "List of modules" in kernel_modules + assert "qemu-guest.nix" in kernel_modules - # Test nixos-option. - $machine->succeed("nixos-option boot.initrd.kernelModules | grep virtio_console"); - $machine->succeed("nixos-option boot.initrd.kernelModules | grep 'List of modules'"); - $machine->succeed("nixos-option boot.initrd.kernelModules | grep qemu-guest.nix"); - - $machine->shutdown; + machine.shutdown() # Check whether a writable store build works - $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "rebuild-switch" }); + machine = create_machine_named("rebuild-switch") ${preBootCommands} - $machine->waitForUnit("multi-user.target"); - $machine->copyFileFromHost( - "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 2; } }", - "/etc/nixos/configuration.nix"); - $machine->succeed("nixos-rebuild boot >&2"); - $machine->shutdown; + machine.wait_for_unit("multi-user.target") + + # we're not using copy_from_host here because the installer image + # doesn't know about the host-guest sharing mechanism. + machine.copy_from_host_via_shell( + "${ makeConfig { + inherit bootLoader grubVersion grubDevice grubIdentifier + grubUseEfi extraConfig; + forceGrubReinstallCount = 2; + } + }", + "/etc/nixos/configuration.nix", + ) + machine.succeed("nixos-rebuild boot >&2") + machine.shutdown() # And just to be sure, check that the machine still boots after # "nixos-rebuild switch". - $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", "boot-after-rebuild-switch" }); + machine = create_machine_named("boot-after-rebuild-switch") ${preBootCommands} - $machine->waitForUnit("network.target"); - $machine->shutdown; + machine.wait_for_unit("network.target") + machine.shutdown() # Tests for validating clone configuration entries in grub menu - ${optionalString testCloneConfig '' - # Reboot Machine - $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "clone-default-config" }); - ${preBootCommands} - $machine->waitForUnit("multi-user.target"); + '' + + optionalString testCloneConfig '' + # Reboot Machine + machine = create_machine_named("clone-default-config") + ${preBootCommands} + machine.wait_for_unit("multi-user.target") - # Booted configuration name should be Home - # This is not the name that shows in the grub menu. - # The default configuration is always shown as "Default" - $machine->succeed("cat /run/booted-system/configuration-name >&2"); - $machine->succeed("cat /run/booted-system/configuration-name | grep Home"); + with subtest("Booted configuration name should be 'Home'"): + # This is not the name that shows in the grub menu. + # The default configuration is always shown as "Default" + machine.succeed("cat /run/booted-system/configuration-name >&2") + assert "Home" in machine.succeed("cat /run/booted-system/configuration-name") - # We should find **not** a file named /etc/gitconfig - $machine->fail("test -e /etc/gitconfig"); + with subtest("We should **not** find a file named /etc/gitconfig"): + machine.fail("test -e /etc/gitconfig") - # Set grub to boot the second configuration - $machine->succeed("grub-reboot 1"); + with subtest("Set grub to boot the second configuration"): + machine.succeed("grub-reboot 1") - $machine->shutdown; + machine.shutdown() - # Reboot Machine - $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "clone-alternate-config" }); - ${preBootCommands} + # Reboot Machine + machine = create_machine_named("clone-alternate-config") + ${preBootCommands} - $machine->waitForUnit("multi-user.target"); - # Booted configuration name should be Work - $machine->succeed("cat /run/booted-system/configuration-name >&2"); - $machine->succeed("cat /run/booted-system/configuration-name | grep Work"); + machine.wait_for_unit("multi-user.target") + with subtest("Booted configuration name should be Work"): + machine.succeed("cat /run/booted-system/configuration-name >&2") + assert "Work" in machine.succeed("cat /run/booted-system/configuration-name") - # We should find a file named /etc/gitconfig - $machine->succeed("test -e /etc/gitconfig"); - - $machine->shutdown; - ''} + with subtest("We should find a file named /etc/gitconfig"): + machine.succeed("test -e /etc/gitconfig") + machine.shutdown() ''; @@ -243,63 +275,63 @@ let nodes = { # The configuration of the machine used to run "nixos-install". - machine = - { pkgs, ... }: + machine = { pkgs, ... }: { + imports = [ + ../modules/profiles/installation-device.nix + ../modules/profiles/base.nix + extraInstallerConfig + ]; - { imports = - [ ../modules/profiles/installation-device.nix - ../modules/profiles/base.nix - extraInstallerConfig - ]; + virtualisation.diskSize = 8 * 1024; + virtualisation.memorySize = 1024; - virtualisation.diskSize = 8 * 1024; - virtualisation.memorySize = 1024; + # Use a small /dev/vdb as the root disk for the + # installer. This ensures the target disk (/dev/vda) is + # the same during and after installation. + virtualisation.emptyDiskImages = [ 512 ]; + virtualisation.bootDevice = + if grubVersion == 1 then "/dev/sdb" else "/dev/vdb"; + virtualisation.qemu.diskInterface = + if grubVersion == 1 then "scsi" else "virtio"; - # Use a small /dev/vdb as the root disk for the - # installer. This ensures the target disk (/dev/vda) is - # the same during and after installation. - virtualisation.emptyDiskImages = [ 512 ]; - virtualisation.bootDevice = - if grubVersion == 1 then "/dev/sdb" else "/dev/vdb"; - virtualisation.qemu.diskInterface = - if grubVersion == 1 then "scsi" else "virtio"; + boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true; - boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true; + hardware.enableAllFirmware = mkForce false; - hardware.enableAllFirmware = mkForce false; + # The test cannot access the network, so any packages we + # need must be included in the VM. + system.extraDependencies = with pkgs; [ + desktop-file-utils + docbook5 + docbook_xsl_ns + libxml2.bin + libxslt.bin + nixos-artwork.wallpapers.simple-dark-gray-bottom + ntp + perlPackages.ListCompare + perlPackages.XMLLibXML + shared-mime-info + sudo + texinfo + unionfs-fuse + xorg.lndir - # The test cannot access the network, so any packages we - # need must be included in the VM. - system.extraDependencies = with pkgs; - [ sudo - libxml2.bin - libxslt.bin - desktop-file-utils - docbook5 - docbook_xsl_ns - unionfs-fuse - ntp - nixos-artwork.wallpapers.simple-dark-gray-bottom - perlPackages.XMLLibXML - perlPackages.ListCompare - shared-mime-info - texinfo - xorg.lndir + # add curl so that rather than seeing the test attempt to download + # curl's tarball, we see what it's trying to download + curl + ] + ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub + ++ optionals (bootLoader == "grub" && grubVersion == 2) [ + pkgs.grub2 + pkgs.grub2_efi + ]; - # add curl so that rather than seeing the test attempt to download - # curl's tarball, we see what it's trying to download - curl - ] - ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub - ++ optionals (bootLoader == "grub" && grubVersion == 2) [ pkgs.grub2 pkgs.grub2_efi ]; - - nix.binaryCaches = mkForce [ ]; - nix.extraOptions = - '' - hashed-mirrors = - connect-timeout = 1 - ''; - }; + nix.binaryCaches = mkForce [ ]; + nix.extraOptions = '' + hashed-mirrors = + connect-timeout = 1 + ''; + }; }; @@ -310,13 +342,13 @@ let }; }; - makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name - { createPartitions = '' - $machine->succeed( + makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name { + createPartitions = '' + machine.succeed( "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary ext2 1M 50MB" # /boot - . " mkpart primary linux-swap 50M 1024M" - . " mkpart primary 1024M -1s", # LUKS + + " mkpart primary ext2 1M 50MB" # /boot + + " mkpart primary linux-swap 50M 1024M" + + " mkpart primary 1024M -1s", # LUKS "udevadm settle", "mkswap /dev/vda2 -L swap", "swapon -L swap", @@ -328,77 +360,74 @@ let "mkfs.ext3 -L boot /dev/vda1", "mkdir -p /mnt/boot", "mount LABEL=boot /mnt/boot", - ); - ''; - extraConfig = '' - boot.kernelParams = lib.mkAfter [ "console=tty0" ]; - ''; - enableOCR = true; - preBootCommands = '' - $machine->start; - $machine->waitForText(qr/Passphrase for/); - $machine->sendChars("supersecret\n"); - ''; - }; + ) + ''; + extraConfig = '' + boot.kernelParams = lib.mkAfter [ "console=tty0" ]; + ''; + enableOCR = true; + preBootCommands = '' + machine.start() + machine.wait_for_text("Passphrase for") + machine.send_chars("supersecret\n") + ''; + }; # The (almost) simplest partitioning scheme: a swap partition and # one big filesystem partition. - simple-test-config = { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary linux-swap 1M 1024M" - . " mkpart primary ext2 1024M -1s", - "udevadm settle", - "mkswap /dev/vda1 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda2", - "mount LABEL=nixos /mnt", - ); - ''; - }; + simple-test-config = { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel msdos" + + " mkpart primary linux-swap 1M 1024M" + + " mkpart primary ext2 1024M -1s", + "udevadm settle", + "mkswap /dev/vda1 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda2", + "mount LABEL=nixos /mnt", + ) + ''; + }; - simple-uefi-grub-config = - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel gpt" - . " mkpart ESP fat32 1M 50MiB" # /boot - . " set 1 boot on" - . " mkpart primary linux-swap 50MiB 1024MiB" - . " mkpart primary ext2 1024MiB -1MiB", # / - "udevadm settle", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda3", - "mount LABEL=nixos /mnt", - "mkfs.vfat -n BOOT /dev/vda1", - "mkdir -p /mnt/boot", - "mount LABEL=BOOT /mnt/boot", - ); - ''; - bootLoader = "grub"; - grubUseEfi = true; - }; + simple-uefi-grub-config = { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel gpt" + + " mkpart ESP fat32 1M 50MiB" # /boot + + " set 1 boot on" + + " mkpart primary linux-swap 50MiB 1024MiB" + + " mkpart primary ext2 1024MiB -1MiB", # / + "udevadm settle", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda3", + "mount LABEL=nixos /mnt", + "mkfs.vfat -n BOOT /dev/vda1", + "mkdir -p /mnt/boot", + "mount LABEL=BOOT /mnt/boot", + ) + ''; + bootLoader = "grub"; + grubUseEfi = true; + }; - clone-test-extraconfig = { extraConfig = - '' - environment.systemPackages = [ pkgs.grub2 ]; - boot.loader.grub.configurationName = "Home"; - nesting.clone = [ - { - boot.loader.grub.configurationName = lib.mkForce "Work"; + clone-test-extraconfig = { + extraConfig = '' + environment.systemPackages = [ pkgs.grub2 ]; + boot.loader.grub.configurationName = "Home"; + nesting.clone = [ { + boot.loader.grub.configurationName = lib.mkForce "Work"; - environment.etc = { - "gitconfig".text = " - [core] - gitproxy = none for work.com - "; - }; - } - ]; - ''; - testCloneConfig = true; + environment.etc = { + "gitconfig".text = " + [core] + gitproxy = none for work.com + "; + }; + } ]; + ''; + testCloneConfig = true; }; @@ -415,27 +444,26 @@ in { simpleClone = makeInstallerTest "simpleClone" (simple-test-config // clone-test-extraconfig); # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem - simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel gpt" - . " mkpart ESP fat32 1M 50MiB" # /boot - . " set 1 boot on" - . " mkpart primary linux-swap 50MiB 1024MiB" - . " mkpart primary ext2 1024MiB -1MiB", # / - "udevadm settle", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda3", - "mount LABEL=nixos /mnt", - "mkfs.vfat -n BOOT /dev/vda1", - "mkdir -p /mnt/boot", - "mount LABEL=BOOT /mnt/boot", - ); - ''; - bootLoader = "systemd-boot"; - }; + simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel gpt" + + " mkpart ESP fat32 1M 50MiB" # /boot + + " set 1 boot on" + + " mkpart primary linux-swap 50MiB 1024MiB" + + " mkpart primary ext2 1024MiB -1MiB", # / + "udevadm settle", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda3", + "mount LABEL=nixos /mnt", + "mkfs.vfat -n BOOT /dev/vda1", + "mkdir -p /mnt/boot", + "mount LABEL=BOOT /mnt/boot", + ) + ''; + bootLoader = "systemd-boot"; + }; simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config; @@ -443,107 +471,99 @@ in { simpleUefiGrubClone = makeInstallerTest "simpleUefiGrubClone" (simple-uefi-grub-config // clone-test-extraconfig); # Same as the previous, but now with a separate /boot partition. - separateBoot = makeInstallerTest "separateBoot" - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary ext2 1M 50MB" # /boot - . " mkpart primary linux-swap 50MB 1024M" - . " mkpart primary ext2 1024M -1s", # / - "udevadm settle", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda3", - "mount LABEL=nixos /mnt", - "mkfs.ext3 -L boot /dev/vda1", - "mkdir -p /mnt/boot", - "mount LABEL=boot /mnt/boot", - ); - ''; - }; + separateBoot = makeInstallerTest "separateBoot" { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel msdos" + + " mkpart primary ext2 1M 50MB" # /boot + + " mkpart primary linux-swap 50MB 1024M" + + " mkpart primary ext2 1024M -1s", # / + "udevadm settle", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda3", + "mount LABEL=nixos /mnt", + "mkfs.ext3 -L boot /dev/vda1", + "mkdir -p /mnt/boot", + "mount LABEL=boot /mnt/boot", + ) + ''; + }; # Same as the previous, but with fat32 /boot. - separateBootFat = makeInstallerTest "separateBootFat" - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary ext2 1M 50MB" # /boot - . " mkpart primary linux-swap 50MB 1024M" - . " mkpart primary ext2 1024M -1s", # / - "udevadm settle", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda3", - "mount LABEL=nixos /mnt", - "mkfs.vfat -n BOOT /dev/vda1", - "mkdir -p /mnt/boot", - "mount LABEL=BOOT /mnt/boot", - ); - ''; - }; + separateBootFat = makeInstallerTest "separateBootFat" { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel msdos" + + " mkpart primary ext2 1M 50MB" # /boot + + " mkpart primary linux-swap 50MB 1024M" + + " mkpart primary ext2 1024M -1s", # / + "udevadm settle", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda3", + "mount LABEL=nixos /mnt", + "mkfs.vfat -n BOOT /dev/vda1", + "mkdir -p /mnt/boot", + "mount LABEL=BOOT /mnt/boot", + ) + ''; + }; # zfs on / with swap - zfsroot = makeInstallerTest "zfs-root" - { - extraInstallerConfig = { - boot.supportedFilesystems = [ "zfs" ]; - }; - - extraConfig = '' - boot.supportedFilesystems = [ "zfs" ]; - - # Using by-uuid overrides the default of by-id, and is unique - # to the qemu disks, as they don't produce by-id paths for - # some reason. - boot.zfs.devNodes = "/dev/disk/by-uuid/"; - networking.hostId = "00000000"; - ''; - - createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary linux-swap 1M 1024M" - . " mkpart primary 1024M -1s", - "udevadm settle", - - "mkswap /dev/vda1 -L swap", - "swapon -L swap", - - "zpool create rpool /dev/vda2", - "zfs create -o mountpoint=legacy rpool/root", - "mount -t zfs rpool/root /mnt", - - "udevadm settle" - ); - ''; + zfsroot = makeInstallerTest "zfs-root" { + extraInstallerConfig = { + boot.supportedFilesystems = [ "zfs" ]; }; + extraConfig = '' + boot.supportedFilesystems = [ "zfs" ]; + + # Using by-uuid overrides the default of by-id, and is unique + # to the qemu disks, as they don't produce by-id paths for + # some reason. + boot.zfs.devNodes = "/dev/disk/by-uuid/"; + networking.hostId = "00000000"; + ''; + + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel msdos" + + " mkpart primary linux-swap 1M 1024M" + + " mkpart primary 1024M -1s", + "udevadm settle", + "mkswap /dev/vda1 -L swap", + "swapon -L swap", + "zpool create rpool /dev/vda2", + "zfs create -o mountpoint=legacy rpool/root", + "mount -t zfs rpool/root /mnt", + "udevadm settle", + ) + ''; + }; + # Create two physical LVM partitions combined into one volume group # that contains the logical swap and root partitions. - lvm = makeInstallerTest "lvm" - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary 1M 2048M" # PV1 - . " set 1 lvm on" - . " mkpart primary 2048M -1s" # PV2 - . " set 2 lvm on", - "udevadm settle", - "pvcreate /dev/vda1 /dev/vda2", - "vgcreate MyVolGroup /dev/vda1 /dev/vda2", - "lvcreate --size 1G --name swap MyVolGroup", - "lvcreate --size 2G --name nixos MyVolGroup", - "mkswap -f /dev/MyVolGroup/swap -L swap", - "swapon -L swap", - "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", - "mount LABEL=nixos /mnt", - ); - ''; - }; + lvm = makeInstallerTest "lvm" { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda -- mklabel msdos" + + " mkpart primary 1M 2048M" # PV1 + + " set 1 lvm on" + + " mkpart primary 2048M -1s" # PV2 + + " set 2 lvm on", + "udevadm settle", + "pvcreate /dev/vda1 /dev/vda2", + "vgcreate MyVolGroup /dev/vda1 /dev/vda2", + "lvcreate --size 1G --name swap MyVolGroup", + "lvcreate --size 2G --name nixos MyVolGroup", + "mkswap -f /dev/MyVolGroup/swap -L swap", + "swapon -L swap", + "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", + "mount LABEL=nixos /mnt", + ) + ''; + }; # Boot off an encrypted root partition with the default LUKS header format luksroot = makeLuksRootTest "luksroot-format1" ""; @@ -557,14 +577,14 @@ in { # Test whether opening encrypted filesystem with keyfile # Checks for regression of missing cryptsetup, when no luks device without # keyfile is configured - encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile" - { createPartitions = '' - $machine->succeed( + encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile" { + createPartitions = '' + machine.succeed( "flock /dev/vda parted --script /dev/vda -- mklabel msdos" - . " mkpart primary ext2 1M 50MB" # /boot - . " mkpart primary linux-swap 50M 1024M" - . " mkpart primary 1024M 1280M" # LUKS with keyfile - . " mkpart primary 1280M -1s", + + " mkpart primary ext2 1M 50MB" # /boot + + " mkpart primary linux-swap 50M 1024M" + + " mkpart primary 1024M 1280M" # LUKS with keyfile + + " mkpart primary 1280M -1s", "udevadm settle", "mkswap /dev/vda2 -L swap", "swapon -L swap", @@ -579,89 +599,88 @@ in { "cryptsetup luksOpen --key-file /mnt/keyfile /dev/vda3 crypt", "mkfs.ext3 -L test /dev/mapper/crypt", "cryptsetup luksClose crypt", - "mkdir -p /mnt/test" - ); - ''; - extraConfig = '' - fileSystems."/test" = - { device = "/dev/disk/by-label/test"; - fsType = "ext3"; - encrypted.enable = true; - encrypted.blkDev = "/dev/vda3"; - encrypted.label = "crypt"; - encrypted.keyFile = "/mnt-root/keyfile"; - }; - ''; - }; + "mkdir -p /mnt/test", + ) + ''; + extraConfig = '' + fileSystems."/test" = { + device = "/dev/disk/by-label/test"; + fsType = "ext3"; + encrypted.enable = true; + encrypted.blkDev = "/dev/vda3"; + encrypted.label = "crypt"; + encrypted.keyFile = "/mnt-root/keyfile"; + }; + ''; + }; - - swraid = makeInstallerTest "swraid" - { createPartitions = - '' - $machine->succeed( - "flock /dev/vda parted --script /dev/vda --" - . " mklabel msdos" - . " mkpart primary ext2 1M 100MB" # /boot - . " mkpart extended 100M -1s" - . " mkpart logical 102M 2102M" # md0 (root), first device - . " mkpart logical 2103M 4103M" # md0 (root), second device - . " mkpart logical 4104M 4360M" # md1 (swap), first device - . " mkpart logical 4361M 4617M", # md1 (swap), second device - "udevadm settle", - "ls -l /dev/vda* >&2", - "cat /proc/partitions >&2", - "udevadm control --stop-exec-queue", - "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda5 /dev/vda6", - "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda7 /dev/vda8", - "udevadm control --start-exec-queue", - "udevadm settle", - "mkswap -f /dev/md1 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/md0", - "mount LABEL=nixos /mnt", - "mkfs.ext3 -L boot /dev/vda1", - "mkdir /mnt/boot", - "mount LABEL=boot /mnt/boot", - "udevadm settle", - ); - ''; - preBootCommands = '' - $machine->start; - $machine->fail("dmesg | grep 'immediate safe mode'"); - ''; - }; + swraid = makeInstallerTest "swraid" { + createPartitions = '' + machine.succeed( + "flock /dev/vda parted --script /dev/vda --" + + " mklabel msdos" + + " mkpart primary ext2 1M 100MB" # /boot + + " mkpart extended 100M -1s" + + " mkpart logical 102M 2102M" # md0 (root), first device + + " mkpart logical 2103M 4103M" # md0 (root), second device + + " mkpart logical 4104M 4360M" # md1 (swap), first device + + " mkpart logical 4361M 4617M", # md1 (swap), second device + "udevadm settle", + "ls -l /dev/vda* >&2", + "cat /proc/partitions >&2", + "udevadm control --stop-exec-queue", + "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 " + + "--raid-devices=2 /dev/vda5 /dev/vda6", + "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 " + + "--raid-devices=2 /dev/vda7 /dev/vda8", + "udevadm control --start-exec-queue", + "udevadm settle", + "mkswap -f /dev/md1 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/md0", + "mount LABEL=nixos /mnt", + "mkfs.ext3 -L boot /dev/vda1", + "mkdir /mnt/boot", + "mount LABEL=boot /mnt/boot", + "udevadm settle", + ) + ''; + preBootCommands = '' + machine.start() + machine.fail("dmesg | grep 'immediate safe mode'") + ''; + }; # Test a basic install using GRUB 1. - grub1 = makeInstallerTest "grub1" - { createPartitions = - '' - $machine->succeed( - "flock /dev/sda parted --script /dev/sda -- mklabel msdos" - . " mkpart primary linux-swap 1M 1024M" - . " mkpart primary ext2 1024M -1s", - "udevadm settle", - "mkswap /dev/sda1 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos /dev/sda2", - "mount LABEL=nixos /mnt", - "mkdir -p /mnt/tmp", - ); - ''; - grubVersion = 1; - grubDevice = "/dev/sda"; - }; + grub1 = makeInstallerTest "grub1" { + createPartitions = '' + machine.succeed( + "flock /dev/sda parted --script /dev/sda -- mklabel msdos" + + " mkpart primary linux-swap 1M 1024M" + + " mkpart primary ext2 1024M -1s", + "udevadm settle", + "mkswap /dev/sda1 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/sda2", + "mount LABEL=nixos /mnt", + "mkdir -p /mnt/tmp", + ) + ''; + grubVersion = 1; + grubDevice = "/dev/sda"; + }; # Test using labels to identify volumes in grub simpleLabels = makeInstallerTest "simpleLabels" { createPartitions = '' - $machine->succeed( - "sgdisk -Z /dev/vda", - "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.ext4 -L root /dev/vda3", - "mount LABEL=root /mnt", - ); + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext4 -L root /dev/vda3", + "mount LABEL=root /mnt", + ) ''; grubIdentifier = "label"; }; @@ -670,22 +689,23 @@ in { # TODO: Fix udev so the symlinks are unneeded in /dev/disks simpleProvided = makeInstallerTest "simpleProvided" { createPartitions = '' - my $UUID = "\$(blkid -s UUID -o value /dev/vda2)"; - $machine->succeed( - "sgdisk -Z /dev/vda", - "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 -t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda", - "mkswap /dev/vda3 -L swap", - "swapon -L swap", - "mkfs.ext4 -L boot /dev/vda2", - "mkfs.ext4 -L root /dev/vda4", - ); - $machine->execute("ln -s ../../vda2 /dev/disk/by-uuid/$UUID"); - $machine->execute("ln -s ../../vda4 /dev/disk/by-label/root"); - $machine->succeed( - "mount /dev/disk/by-label/root /mnt", - "mkdir /mnt/boot", - "mount /dev/disk/by-uuid/$UUID /mnt/boot" - ); + uuid = "$(blkid -s UUID -o value /dev/vda2)" + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 " + + "-t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda", + "mkswap /dev/vda3 -L swap", + "swapon -L swap", + "mkfs.ext4 -L boot /dev/vda2", + "mkfs.ext4 -L root /dev/vda4", + ) + machine.execute(f"ln -s ../../vda2 /dev/disk/by-uuid/{uuid}") + machine.execute("ln -s ../../vda4 /dev/disk/by-label/root") + machine.succeed( + "mount /dev/disk/by-label/root /mnt", + "mkdir /mnt/boot", + f"mount /dev/disk/by-uuid/{uuid} /mnt/boot", + ) ''; grubIdentifier = "provided"; }; @@ -693,61 +713,62 @@ in { # Simple btrfs grub testing btrfsSimple = makeInstallerTest "btrfsSimple" { createPartitions = '' - $machine->succeed( - "sgdisk -Z /dev/vda", - "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.btrfs -L root /dev/vda3", - "mount LABEL=root /mnt", - ); + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.btrfs -L root /dev/vda3", + "mount LABEL=root /mnt", + ) ''; }; # Test to see if we can detect /boot and /nix on subvolumes btrfsSubvols = makeInstallerTest "btrfsSubvols" { createPartitions = '' - $machine->succeed( - "sgdisk -Z /dev/vda", - "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.btrfs -L root /dev/vda3", - "btrfs device scan", - "mount LABEL=root /mnt", - "btrfs subvol create /mnt/boot", - "btrfs subvol create /mnt/nixos", - "btrfs subvol create /mnt/nixos/default", - "umount /mnt", - "mount -o defaults,subvol=nixos/default LABEL=root /mnt", - "mkdir /mnt/boot", - "mount -o defaults,subvol=boot LABEL=root /mnt/boot", - ); + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.btrfs -L root /dev/vda3", + "btrfs device scan", + "mount LABEL=root /mnt", + "btrfs subvol create /mnt/boot", + "btrfs subvol create /mnt/nixos", + "btrfs subvol create /mnt/nixos/default", + "umount /mnt", + "mount -o defaults,subvol=nixos/default LABEL=root /mnt", + "mkdir /mnt/boot", + "mount -o defaults,subvol=boot LABEL=root /mnt/boot", + ) ''; }; # Test to see if we can detect default and aux subvolumes correctly btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" { createPartitions = '' - $machine->succeed( - "sgdisk -Z /dev/vda", - "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", - "mkswap /dev/vda2 -L swap", - "swapon -L swap", - "mkfs.btrfs -L root /dev/vda3", - "btrfs device scan", - "mount LABEL=root /mnt", - "btrfs subvol create /mnt/badpath", - "btrfs subvol create /mnt/badpath/boot", - "btrfs subvol create /mnt/nixos", - "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt", - "umount /mnt", - "mount -o defaults LABEL=root /mnt", - "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes - "mkdir /mnt/boot", - "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", - ); + machine.succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.btrfs -L root /dev/vda3", + "btrfs device scan", + "mount LABEL=root /mnt", + "btrfs subvol create /mnt/badpath", + "btrfs subvol create /mnt/badpath/boot", + "btrfs subvol create /mnt/nixos", + "btrfs subvol set-default " + + "$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt", + "umount /mnt", + "mount -o defaults LABEL=root /mnt", + "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism + # is actually looking up subvolumes + "mkdir /mnt/boot", + "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", + ) ''; }; - }