summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2020-02-08 15:36:28 +0100
committerGitHub <noreply@github.com>2020-02-08 15:36:28 +0100
commitdd5f92f20b2ed369f4707c6fa42b5802d7df8754 (patch)
tree959b165ecf1b1eacaa9c12322d03acd8cb18a1f2 /nixos
parent26d618bce298a97e81a0aa620eb6f16b79004aae (diff)
parent942f0fd7c00ec0b829e65e656f96e28afbbd5348 (diff)
downloadnixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar.gz
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar.bz2
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar.lz
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar.xz
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.tar.zst
nixpkgs-dd5f92f20b2ed369f4707c6fa42b5802d7df8754.zip
Merge pull request #78670 from tfc/port-installer-test
nixosTests.installer: Port installer and ZFS test to python
Diffstat (limited to 'nixos')
-rw-r--r--nixos/lib/test-driver/test-driver.py44
-rw-r--r--nixos/tests/all-tests.nix1
-rw-r--r--nixos/tests/installer.nix1027
-rw-r--r--nixos/tests/zfs.nix75
4 files changed, 597 insertions, 550 deletions
diff --git a/nixos/lib/test-driver/test-driver.py b/nixos/lib/test-driver/test-driver.py
index 75f80df53f2..2b8dffec7d5 100644
--- a/nixos/lib/test-driver/test-driver.py
+++ b/nixos/lib/test-driver/test-driver.py
@@ -1,13 +1,17 @@
 #! /somewhere/python3
 from contextlib import contextmanager, _GeneratorContextManager
+from queue import Queue, Empty
+from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
 from xml.sax.saxutils import XMLGenerator
 import _thread
 import atexit
+import base64
 import os
+import pathlib
 import ptpython.repl
 import pty
-from queue import Queue, Empty
 import re
+import shlex
 import shutil
 import socket
 import subprocess
@@ -15,9 +19,6 @@ import sys
 import tempfile
 import time
 import unicodedata
-from typing import Tuple, Any, Callable, Dict, Iterator, Optional, List
-import shlex
-import pathlib
 
 CHAR_TO_KEY = {
     "A": "shift-a",
@@ -566,6 +567,41 @@ class Machine:
             if ret.returncode != 0:
                 raise Exception("Cannot convert screenshot")
 
+    def copy_from_host_via_shell(self, source: str, target: str) -> None:
+        """Copy a file from the host into the guest by piping it over the
+        shell into the destination file. Works without host-guest shared folder.
+        Prefer copy_from_host for whenever possible.
+        """
+        with open(source, "rb") as fh:
+            content_b64 = base64.b64encode(fh.read()).decode()
+            self.succeed(
+                f"mkdir -p $(dirname {target})",
+                f"echo -n {content_b64} | base64 -d > {target}",
+            )
+
+    def copy_from_host(self, source: str, target: str) -> None:
+        """Copy a file from the host into the guest via the `shared_dir` shared
+        among all the VMs (using a temporary directory).
+        """
+        host_src = pathlib.Path(source)
+        vm_target = pathlib.Path(target)
+        with tempfile.TemporaryDirectory(dir=self.shared_dir) as shared_td:
+            shared_temp = pathlib.Path(shared_td)
+            host_intermediate = shared_temp / host_src.name
+            vm_shared_temp = pathlib.Path("/tmp/shared") / shared_temp.name
+            vm_intermediate = vm_shared_temp / host_src.name
+
+            self.succeed(make_command(["mkdir", "-p", vm_shared_temp]))
+            if host_src.is_dir():
+                shutil.copytree(host_src, host_intermediate)
+            else:
+                shutil.copy(host_src, host_intermediate)
+            self.succeed("sync")
+            self.succeed(make_command(["mkdir", "-p", vm_target.parent]))
+            self.succeed(make_command(["cp", "-r", vm_intermediate, vm_target]))
+        # Make sure the cleanup is synced into VM
+        self.succeed("sync")
+
     def copy_from_vm(self, source: str, target_dir: str = "") -> None:
         """Copy a file from the VM (specified by an in-VM source path) to a path
         relative to `$out`. The file is copied via the `shared_dir` shared among
diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix
index e1c299b8413..bdac56169fd 100644
--- a/nixos/tests/all-tests.nix
+++ b/nixos/tests/all-tests.nix
@@ -308,6 +308,7 @@ in
   xss-lock = handleTest ./xss-lock.nix {};
   yabar = handleTest ./yabar.nix {};
   yggdrasil = handleTest ./yggdrasil.nix {};
+  zfs = handleTest ./zfs.nix {};
   zsh-history = handleTest ./zsh-history.nix {};
   zookeeper = handleTest ./zookeeper.nix {};
 }
diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix
index 024445b01b6..983861911e0 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}
 
-      # Partition the disk.
-      ${createPartitions}
 
-      # Create the NixOS configuration.
-      $machine->succeed("nixos-generate-config --root /mnt");
+      def create_machine_named(name):
+          return create_machine({**default_flags, "name": "boot-after-install"})
 
-      $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2");
 
-      $machine->copyFileFromHost(
-          "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier grubUseEfi extraConfig; } }",
-          "/mnt/etc/nixos/configuration.nix");
+      machine.start()
 
-      # Perform the installation.
-      $machine->succeed("nixos-install < /dev/null >&2");
+      with subtest("Assert readiness of login prompt"):
+          machine.succeed("echo hello")
+          machine.wait_for_unit("nixos-manual")
 
-      # Do it again to make sure it's idempotent.
-      $machine->succeed("nixos-install < /dev/null >&2");
+      with subtest("Wait for hard disks to appear in /dev"):
+          machine.succeed("udevadm settle")
 
-      $machine->succeed("umount /mnt/boot || true");
-      $machine->succeed("umount /mnt");
-      $machine->succeed("sync");
+      ${createPartitions}
 
-      $machine->shutdown;
+      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",
+          )
+
+      with subtest("Perform the installation"):
+          machine.succeed("nixos-install < /dev/null >&2")
+
+      with subtest("Do it again to make sure it's idempotent"):
+          machine.succeed("nixos-install < /dev/null >&2")
+
+      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");
-
-      ${if bootLoader == "grub" then
-          ''$machine->succeed("test -e /boot/grub");''
-        else
-          ''$machine->succeed("test -e /boot/loader/loader.conf");''
-      }
-
-      # Check whether /root has correct permissions.
-      $machine->succeed("stat -c '%a' /root") =~ /700/ or die;
-
-      # 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");
-
-      # Check that the store is in good shape
-      $machine->succeed("nix-store --verify --check-contents >&2");
-
-      # 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";
-
-      # 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");
-
-      # 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");
-
-      # Check whether nixos-rebuild works.
-      $machine->succeed("nixos-rebuild switch >&2");
-
-      # 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;
+      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")''
+          }
+
+      with subtest("Check whether /root has correct permissions"):
+          assert "700" in machine.succeed("stat -c '%a' /root")
+
+      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")
+
+      with subtest("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")
+
+      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")
+
+      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",
+          )
+
+      with subtest("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
+
+      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");
-
-        # 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");
+    ''
+    + optionalString testCloneConfig ''
+      # Reboot Machine
+      machine = create_machine_named("clone-default-config")
+      ${preBootCommands}
+      machine.wait_for_unit("multi-user.target")
 
-        # We should find **not** a file named /etc/gitconfig
-        $machine->fail("test -e /etc/gitconfig");
+      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")
 
-        # Set grub to boot the second configuration
-        $machine->succeed("grub-reboot 1");
+      with subtest("We should **not** find a file named /etc/gitconfig"):
+          machine.fail("test -e /etc/gitconfig")
 
-        $machine->shutdown;
+      with subtest("Set grub to boot the second configuration"):
+          machine.succeed("grub-reboot 1")
 
-        # Reboot Machine
-        $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}", name => "clone-alternate-config" });
-        ${preBootCommands}
+      machine.shutdown()
 
-        $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");
+      # Reboot Machine
+      machine = create_machine_named("clone-alternate-config")
+      ${preBootCommands}
 
-        # We should find a file named /etc/gitconfig
-        $machine->succeed("test -e /etc/gitconfig");
+      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")
 
-        $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, ... }:
-
-          { imports =
-              [ ../modules/profiles/installation-device.nix
-                ../modules/profiles/base.nix
-                extraInstallerConfig
-              ];
-
-            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";
-
-            boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true;
-
-            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;
-              [ 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 ];
-
-            nix.binaryCaches = mkForce [ ];
-            nix.extraOptions =
-              ''
-                hashed-mirrors =
-                connect-timeout = 1
-              '';
-          };
+        machine = { pkgs, ... }: {
+          imports = [
+            ../modules/profiles/installation-device.nix
+            ../modules/profiles/base.nix
+            extraInstallerConfig
+          ];
+
+          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";
+
+          boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true;
+
+          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
+
+            # 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
+          '';
+        };
 
       };
 
@@ -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-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-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;
+  };
 
-  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;
+  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;
   };
 
 
@@ -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",
+  zfsroot = makeInstallerTest "zfs-root" {
+    extraInstallerConfig = {
+      boot.supportedFilesystems = [ "zfs" ];
+    };
 
-              "mkswap /dev/vda1 -L swap",
-              "swapon -L swap",
+    extraConfig = ''
+      boot.supportedFilesystems = [ "zfs" ];
 
-              "zpool create rpool /dev/vda2",
-              "zfs create -o mountpoint=legacy rpool/root",
-              "mount -t zfs rpool/root /mnt",
+      # 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";
+    '';
 
-              "udevadm settle"
-          );
-        '';
-    };
+    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",
+      )
     '';
   };
-
 }
diff --git a/nixos/tests/zfs.nix b/nixos/tests/zfs.nix
index 8f844aca416..7ba60ee9806 100644
--- a/nixos/tests/zfs.nix
+++ b/nixos/tests/zfs.nix
@@ -3,12 +3,10 @@
   pkgs ? import ../.. { inherit system config; }
 }:
 
-with import ../lib/testing.nix { inherit system pkgs; };
+with import ../lib/testing-python.nix { inherit system pkgs; };
 
 let
 
-  makeTest = import ./make-test-python.nix;
-
   makeZfsTest = name:
     { kernelPackage ? pkgs.linuxPackages_latest
     , enableUnstable ? false
@@ -20,41 +18,33 @@ let
         maintainers = [ adisbladis ];
       };
 
-      machine = { pkgs, ... }:
-        {
-          virtualisation.emptyDiskImages = [ 4096 ];
-          networking.hostId = "deadbeef";
-          boot.kernelPackages = kernelPackage;
-          boot.supportedFilesystems = [ "zfs" ];
-          boot.zfs.enableUnstable = enableUnstable;
+      machine = { pkgs, ... }: {
+        virtualisation.emptyDiskImages = [ 4096 ];
+        networking.hostId = "deadbeef";
+        boot.kernelPackages = kernelPackage;
+        boot.supportedFilesystems = [ "zfs" ];
+        boot.zfs.enableUnstable = enableUnstable;
 
-          environment.systemPackages = with pkgs; [
-            parted
-          ];
-        };
+        environment.systemPackages = [ pkgs.parted ];
+      };
 
       testScript = ''
-        machine.succeed("modprobe zfs")
-        machine.succeed("zpool status")
-
-        machine.succeed("ls /dev")
-
         machine.succeed(
-          "mkdir /tmp/mnt",
-
-          "udevadm settle",
-          "parted --script /dev/vdb mklabel msdos",
-          "parted --script /dev/vdb -- mkpart primary 1024M -1s",
-          "udevadm settle",
-
-          "zpool create rpool /dev/vdb1",
-          "zfs create -o mountpoint=legacy rpool/root",
-          "mount -t zfs rpool/root /tmp/mnt",
-          "udevadm settle",
-
-          "umount /tmp/mnt",
-          "zpool destroy rpool",
-          "udevadm settle"
+            "modprobe zfs",
+            "zpool status",
+            "ls /dev",
+            "mkdir /tmp/mnt",
+            "udevadm settle",
+            "parted --script /dev/vdb mklabel msdos",
+            "parted --script /dev/vdb -- mkpart primary 1024M -1s",
+            "udevadm settle",
+            "zpool create rpool /dev/vdb1",
+            "zfs create -o mountpoint=legacy rpool/root",
+            "mount -t zfs rpool/root /tmp/mnt",
+            "udevadm settle",
+            "umount /tmp/mnt",
+            "zpool destroy rpool",
+            "udevadm settle",
         )
       '' + extraTest;
 
@@ -69,18 +59,17 @@ in {
     enableUnstable = true;
     extraTest = ''
       machine.succeed(
-        "echo password | zpool create -o altroot=\"/tmp/mnt\" -O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
-        "zfs create -o mountpoint=legacy rpool/root",
-        "mount -t zfs rpool/root /tmp/mnt",
-        "udevadm settle",
-
-        "umount /tmp/mnt",
-        "zpool destroy rpool",
-        "udevadm settle"
+          'echo password | zpool create -o altroot="/tmp/mnt" '
+          + "-O encryption=aes-256-gcm -O keyformat=passphrase rpool /dev/vdb1",
+          "zfs create -o mountpoint=legacy rpool/root",
+          "mount -t zfs rpool/root /tmp/mnt",
+          "udevadm settle",
+          "umount /tmp/mnt",
+          "zpool destroy rpool",
+          "udevadm settle",
       )
     '';
   };
 
   installer = (import ./installer.nix { }).zfsroot;
-
 }