at 23.11-pre 5.8 kB view raw
1{ system ? builtins.currentSystem 2, config ? { } 3, pkgs ? import ../.. { inherit system config; } 4}: 5 6with import ../lib/testing-python.nix { inherit system pkgs; }; 7with pkgs.lib; 8 9let 10 # A testScript fragment that prepares a disk with some empty, unpartitioned 11 # space. and uses it to boot the test with. Takes a single argument `machine` 12 # from which the diskImage is extracted. 13 useDiskImage = machine: '' 14 import os 15 import shutil 16 import subprocess 17 import tempfile 18 19 tmp_disk_image = tempfile.NamedTemporaryFile() 20 21 shutil.copyfile("${machine.system.build.diskImage}/nixos.img", tmp_disk_image.name) 22 23 subprocess.run([ 24 "${machine.config.virtualisation.qemu.package}/bin/qemu-img", 25 "resize", 26 "-f", 27 "raw", 28 tmp_disk_image.name, 29 "+32M", 30 ]) 31 32 # Fix the GPT table by moving the backup table to the end of the enlarged 33 # disk image. This is necessary because we increased the size of the disk 34 # before. The disk needs to be a raw disk because sgdisk can only run on 35 # raw images. 36 subprocess.run([ 37 "${pkgs.gptfdisk}/bin/sgdisk", 38 "--move-second-header", 39 tmp_disk_image.name, 40 ]) 41 42 # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image. 43 os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name 44 ''; 45 46 common = { config, pkgs, lib, ... }: { 47 virtualisation.useDefaultFilesystems = false; 48 virtualisation.fileSystems = { 49 "/" = { 50 device = "/dev/vda2"; 51 fsType = "ext4"; 52 }; 53 }; 54 55 # systemd-repart operates on disks with a partition table. The qemu module, 56 # however, creates separate filesystem images without a partition table, so 57 # we have to create a disk image manually. 58 # 59 # This creates two partitions, an ESP available as /dev/vda1 and the root 60 # partition available as /dev/vda2. 61 system.build.diskImage = import ../lib/make-disk-image.nix { 62 inherit config pkgs lib; 63 # Use a raw format disk so that it can be resized before starting the 64 # test VM. 65 format = "raw"; 66 # Keep the image as small as possible but leave some room for changes. 67 bootSize = "32M"; 68 additionalSpace = "0M"; 69 # GPT with an EFI System Partition is the typical use case for 70 # systemd-repart because it does not support MBR. 71 partitionTableType = "efi"; 72 # We do not actually care much about the content of the partitions, so we 73 # do not need a bootloader installed. 74 installBootLoader = false; 75 # Improve determinism by not copying a channel. 76 copyChannel = false; 77 }; 78 }; 79in 80{ 81 basic = makeTest { 82 name = "systemd-repart"; 83 meta.maintainers = with maintainers; [ nikstur ]; 84 85 nodes.machine = { config, pkgs, ... }: { 86 imports = [ common ]; 87 88 boot.initrd.systemd.enable = true; 89 90 boot.initrd.systemd.repart.enable = true; 91 systemd.repart.partitions = { 92 "10-root" = { 93 Type = "linux-generic"; 94 }; 95 }; 96 }; 97 98 testScript = { nodes, ... }: '' 99 ${useDiskImage nodes.machine} 100 101 machine.start() 102 machine.wait_for_unit("multi-user.target") 103 104 systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service") 105 assert "Growing existing partition 1." in systemd_repart_logs 106 ''; 107 }; 108 109 after-initrd = makeTest { 110 name = "systemd-repart-after-initrd"; 111 meta.maintainers = with maintainers; [ nikstur ]; 112 113 nodes.machine = { config, pkgs, ... }: { 114 imports = [ common ]; 115 116 systemd.repart.enable = true; 117 systemd.repart.partitions = { 118 "10-root" = { 119 Type = "linux-generic"; 120 }; 121 }; 122 }; 123 124 testScript = { nodes, ... }: '' 125 ${useDiskImage nodes.machine} 126 127 machine.start() 128 machine.wait_for_unit("multi-user.target") 129 130 systemd_repart_logs = machine.succeed("journalctl --unit systemd-repart.service") 131 assert "Growing existing partition 1." in systemd_repart_logs 132 ''; 133 }; 134 135 create-root = makeTest { 136 name = "systemd-repart-create-root"; 137 meta.maintainers = with maintainers; [ nikstur ]; 138 139 nodes.machine = { config, lib, pkgs, ... }: { 140 virtualisation.useDefaultFilesystems = false; 141 virtualisation.fileSystems = { 142 "/" = { 143 device = "/dev/disk/by-partlabel/created-root"; 144 fsType = "ext4"; 145 }; 146 "/nix/store" = { 147 device = "/dev/vda2"; 148 fsType = "ext4"; 149 }; 150 }; 151 152 # Create an image containing only the Nix store. This enables creating 153 # the root partition with systemd-repart and then successfully booting 154 # into a working system. 155 # 156 # This creates two partitions, an ESP available as /dev/vda1 and the Nix 157 # store available as /dev/vda2. 158 system.build.diskImage = import ../lib/make-disk-image.nix { 159 inherit config pkgs lib; 160 onlyNixStore = true; 161 format = "raw"; 162 bootSize = "32M"; 163 additionalSpace = "0M"; 164 partitionTableType = "efi"; 165 installBootLoader = false; 166 copyChannel = false; 167 }; 168 169 boot.initrd.systemd.enable = true; 170 171 boot.initrd.systemd.repart.enable = true; 172 boot.initrd.systemd.repart.device = "/dev/vda"; 173 systemd.repart.partitions = { 174 "10-root" = { 175 Type = "root"; 176 Label = "created-root"; 177 Format = "ext4"; 178 }; 179 }; 180 }; 181 182 testScript = { nodes, ... }: '' 183 ${useDiskImage nodes.machine} 184 185 machine.start() 186 machine.wait_for_unit("multi-user.target") 187 188 systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service") 189 assert "Adding new partition 2 to partition table." in systemd_repart_logs 190 ''; 191 }; 192}