about summary refs log tree commit diff
path: root/nixpkgs/nixos/tests/systemd-repart.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/tests/systemd-repart.nix')
-rw-r--r--nixpkgs/nixos/tests/systemd-repart.nix182
1 files changed, 182 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/systemd-repart.nix b/nixpkgs/nixos/tests/systemd-repart.nix
new file mode 100644
index 000000000000..3914d5b32397
--- /dev/null
+++ b/nixpkgs/nixos/tests/systemd-repart.nix
@@ -0,0 +1,182 @@
+{ system ? builtins.currentSystem
+, config ? { }
+, pkgs ? import ../.. { inherit system config; }
+}:
+
+with import ../lib/testing-python.nix { inherit system pkgs; };
+with pkgs.lib;
+
+let
+  # A testScript fragment that prepares a disk with some empty, unpartitioned
+  # space. and uses it to boot the test with. Takes a single argument `machine`
+  # from which the diskImage is extracted.
+  useDiskImage = machine: ''
+    import os
+    import shutil
+    import subprocess
+    import tempfile
+
+    tmp_disk_image = tempfile.NamedTemporaryFile()
+
+    shutil.copyfile("${machine.system.build.diskImage}/nixos.img", tmp_disk_image.name)
+
+    subprocess.run([
+      "${machine.config.virtualisation.qemu.package}/bin/qemu-img",
+      "resize",
+      "-f",
+      "raw",
+      tmp_disk_image.name,
+      "+32M",
+    ])
+
+    # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
+    os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
+  '';
+
+  common = { config, pkgs, lib, ... }: {
+    virtualisation.useDefaultFilesystems = false;
+    virtualisation.fileSystems = {
+      "/" = {
+        device = "/dev/vda2";
+        fsType = "ext4";
+      };
+    };
+
+    # systemd-repart operates on disks with a partition table. The qemu module,
+    # however, creates separate filesystem images without a partition table, so
+    # we have to create a disk image manually.
+    #
+    # This creates two partitions, an ESP available as /dev/vda1 and the root
+    # partition available as /dev/vda2.
+    system.build.diskImage = import ../lib/make-disk-image.nix {
+      inherit config pkgs lib;
+      # Use a raw format disk so that it can be resized before starting the
+      # test VM.
+      format = "raw";
+      # Keep the image as small as possible but leave some room for changes.
+      bootSize = "32M";
+      additionalSpace = "0M";
+      # GPT with an EFI System Partition is the typical use case for
+      # systemd-repart because it does not support MBR.
+      partitionTableType = "efi";
+      # We do not actually care much about the content of the partitions, so we
+      # do not need a bootloader installed.
+      installBootLoader = false;
+      # Improve determinism by not copying a channel.
+      copyChannel = false;
+    };
+  };
+in
+{
+  basic = makeTest {
+    name = "systemd-repart";
+    meta.maintainers = with maintainers; [ nikstur ];
+
+    nodes.machine = { config, pkgs, ... }: {
+      imports = [ common ];
+
+      boot.initrd.systemd.enable = true;
+
+      boot.initrd.systemd.repart.enable = true;
+      systemd.repart.partitions = {
+        "10-root" = {
+          Type = "linux-generic";
+        };
+      };
+    };
+
+    testScript = { nodes, ... }: ''
+      ${useDiskImage nodes.machine}
+
+      machine.start()
+      machine.wait_for_unit("multi-user.target")
+
+      systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service")
+      assert "Growing existing partition 1." in systemd_repart_logs
+    '';
+  };
+
+  after-initrd = makeTest {
+    name = "systemd-repart-after-initrd";
+    meta.maintainers = with maintainers; [ nikstur ];
+
+    nodes.machine = { config, pkgs, ... }: {
+      imports = [ common ];
+
+      systemd.repart.enable = true;
+      systemd.repart.partitions = {
+        "10-root" = {
+          Type = "linux-generic";
+        };
+      };
+    };
+
+    testScript = { nodes, ... }: ''
+      ${useDiskImage nodes.machine}
+
+      machine.start()
+      machine.wait_for_unit("multi-user.target")
+
+      systemd_repart_logs = machine.succeed("journalctl --unit systemd-repart.service")
+      assert "Growing existing partition 1." in systemd_repart_logs
+    '';
+  };
+
+  create-root = makeTest {
+    name = "systemd-repart-create-root";
+    meta.maintainers = with maintainers; [ nikstur ];
+
+    nodes.machine = { config, lib, pkgs, ... }: {
+      virtualisation.useDefaultFilesystems = false;
+      virtualisation.fileSystems = {
+        "/" = {
+          device = "/dev/disk/by-partlabel/created-root";
+          fsType = "ext4";
+        };
+        "/nix/store" = {
+          device = "/dev/vda2";
+          fsType = "ext4";
+        };
+      };
+
+      # Create an image containing only the Nix store. This enables creating
+      # the root partition with systemd-repart and then successfully booting
+      # into a working system.
+      #
+      # This creates two partitions, an ESP available as /dev/vda1 and the Nix
+      # store available as /dev/vda2.
+      system.build.diskImage = import ../lib/make-disk-image.nix {
+        inherit config pkgs lib;
+        onlyNixStore = true;
+        format = "raw";
+        bootSize = "32M";
+        additionalSpace = "0M";
+        partitionTableType = "efi";
+        installBootLoader = false;
+        copyChannel = false;
+      };
+
+      boot.initrd.systemd.enable = true;
+
+      boot.initrd.systemd.repart.enable = true;
+      boot.initrd.systemd.repart.device = "/dev/vda";
+      systemd.repart.partitions = {
+        "10-root" = {
+          Type = "root";
+          Label = "created-root";
+          Format = "ext4";
+        };
+      };
+    };
+
+    testScript = { nodes, ... }: ''
+      ${useDiskImage nodes.machine}
+
+      machine.start()
+      machine.wait_for_unit("multi-user.target")
+
+      systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service")
+      assert "Adding new partition 2 to partition table." in systemd_repart_logs
+    '';
+  };
+}