at master 7.7 kB view raw
1{ 2 system ? builtins.currentSystem, 3 config ? { }, 4 pkgs ? import ../.. { inherit system config; }, 5}: 6 7with import ../lib/testing-python.nix { inherit system pkgs; }; 8with pkgs.lib; 9 10let 11 # A testScript fragment that prepares a disk with some empty, unpartitioned 12 # space. and uses it to boot the test with. 13 # Takes two arguments, `machine` from which the diskImage is extracted, 14 # as well an optional `sizeDiff` (defaulting to +32M), describing how should 15 # be resized. 16 useDiskImage = 17 { 18 machine, 19 sizeDiff ? "+32M", 20 }: 21 '' 22 import os 23 import shutil 24 import subprocess 25 import tempfile 26 27 tmp_disk_image = tempfile.NamedTemporaryFile() 28 29 shutil.copyfile("${machine.system.build.diskImage}/nixos.img", tmp_disk_image.name) 30 31 subprocess.run([ 32 "${machine.virtualisation.qemu.package}/bin/qemu-img", 33 "resize", 34 "-f", 35 "raw", 36 tmp_disk_image.name, 37 "${sizeDiff}", 38 ]) 39 40 # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image. 41 os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name 42 ''; 43 44 common = 45 { 46 config, 47 pkgs, 48 lib, 49 ... 50 }: 51 { 52 virtualisation.useDefaultFilesystems = false; 53 virtualisation.fileSystems = { 54 "/" = { 55 device = "/dev/vda2"; 56 fsType = "ext4"; 57 }; 58 }; 59 60 # systemd-repart operates on disks with a partition table. The qemu module, 61 # however, creates separate filesystem images without a partition table, so 62 # we have to create a disk image manually. 63 # 64 # This creates two partitions, an ESP available as /dev/vda1 and the root 65 # partition available as /dev/vda2. 66 system.build.diskImage = import ../lib/make-disk-image.nix { 67 inherit config pkgs lib; 68 # Use a raw format disk so that it can be resized before starting the 69 # test VM. 70 format = "raw"; 71 # Keep the image as small as possible but leave some room for changes. 72 bootSize = "32M"; 73 additionalSpace = "0M"; 74 # GPT with an EFI System Partition is the typical use case for 75 # systemd-repart because it does not support MBR. 76 partitionTableType = "efi"; 77 # We do not actually care much about the content of the partitions, so we 78 # do not need a bootloader installed. 79 installBootLoader = false; 80 # Improve determinism by not copying a channel. 81 copyChannel = false; 82 }; 83 }; 84in 85{ 86 basic = makeTest { 87 name = "systemd-repart"; 88 meta.maintainers = with maintainers; [ nikstur ]; 89 90 nodes.machine = 91 { config, pkgs, ... }: 92 { 93 imports = [ common ]; 94 95 boot.initrd.systemd.enable = true; 96 97 boot.initrd.systemd.repart.enable = true; 98 systemd.repart.partitions = { 99 "10-root" = { 100 Type = "linux-generic"; 101 }; 102 }; 103 }; 104 105 testScript = 106 { nodes, ... }: 107 '' 108 ${useDiskImage { inherit (nodes) machine; }} 109 110 machine.start() 111 machine.wait_for_unit("multi-user.target") 112 113 systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service") 114 assert "Growing existing partition 1." in systemd_repart_logs 115 ''; 116 }; 117 118 encrypt-tpm2 = makeTest { 119 name = "systemd-repart-encrypt-tpm2"; 120 meta.maintainers = with maintainers; [ flokli ]; 121 122 nodes.machine = 123 { 124 config, 125 pkgs, 126 lib, 127 ... 128 }: 129 { 130 imports = [ common ]; 131 132 boot.initrd.systemd.enable = true; 133 134 boot.initrd.availableKernelModules = [ "dm_crypt" ]; 135 boot.initrd.luks.devices = lib.mkVMOverride { 136 created-crypt = { 137 device = "/dev/disk/by-partlabel/created-crypt"; 138 crypttabExtraOpts = [ "tpm2-device=auto" ]; 139 }; 140 }; 141 boot.initrd.systemd.repart.enable = true; 142 boot.initrd.systemd.repart.extraArgs = [ 143 "--tpm2-pcrs=7" 144 ]; 145 systemd.repart.partitions = { 146 "10-root" = { 147 Type = "linux-generic"; 148 }; 149 "10-crypt" = { 150 Type = "var"; 151 Label = "created-crypt"; 152 Format = "ext4"; 153 Encrypt = "tpm2"; 154 }; 155 }; 156 virtualisation.tpm.enable = true; 157 virtualisation.fileSystems = { 158 "/var" = { 159 device = "/dev/mapper/created-crypt"; 160 fsType = "ext4"; 161 }; 162 }; 163 }; 164 165 testScript = 166 { nodes, ... }: 167 '' 168 ${useDiskImage { 169 inherit (nodes) machine; 170 sizeDiff = "+100M"; 171 }} 172 173 machine.start() 174 machine.wait_for_unit("multi-user.target") 175 176 systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service") 177 assert "Encrypting future partition 2" in systemd_repart_logs 178 179 assert "/dev/mapper/created-crypt" in machine.succeed("mount") 180 ''; 181 }; 182 183 after-initrd = makeTest { 184 name = "systemd-repart-after-initrd"; 185 meta.maintainers = with maintainers; [ nikstur ]; 186 187 nodes.machine = 188 { config, pkgs, ... }: 189 { 190 imports = [ common ]; 191 192 systemd.repart.enable = true; 193 systemd.repart.partitions = { 194 "10-root" = { 195 Type = "linux-generic"; 196 }; 197 }; 198 }; 199 200 testScript = 201 { nodes, ... }: 202 '' 203 ${useDiskImage { inherit (nodes) machine; }} 204 205 machine.start() 206 machine.wait_for_unit("multi-user.target") 207 208 systemd_repart_logs = machine.succeed("journalctl --unit systemd-repart.service") 209 assert "Growing existing partition 1." in systemd_repart_logs 210 ''; 211 }; 212 213 create-root = makeTest { 214 name = "systemd-repart-create-root"; 215 meta.maintainers = with maintainers; [ nikstur ]; 216 217 nodes.machine = 218 { 219 config, 220 lib, 221 pkgs, 222 ... 223 }: 224 { 225 virtualisation.useDefaultFilesystems = false; 226 virtualisation.mountHostNixStore = false; 227 virtualisation.fileSystems = { 228 "/" = { 229 device = "/dev/disk/by-partlabel/created-root"; 230 fsType = "ext4"; 231 }; 232 "/nix/store" = { 233 device = "/dev/vda2"; 234 fsType = "ext4"; 235 }; 236 }; 237 238 # Create an image containing only the Nix store. This enables creating 239 # the root partition with systemd-repart and then successfully booting 240 # into a working system. 241 # 242 # This creates two partitions, an ESP available as /dev/vda1 and the Nix 243 # store available as /dev/vda2. 244 system.build.diskImage = import ../lib/make-disk-image.nix { 245 inherit config pkgs lib; 246 onlyNixStore = true; 247 format = "raw"; 248 bootSize = "32M"; 249 additionalSpace = "0M"; 250 partitionTableType = "efi"; 251 installBootLoader = false; 252 copyChannel = false; 253 }; 254 255 boot.initrd.systemd.enable = true; 256 257 boot.initrd.systemd.repart.enable = true; 258 boot.initrd.systemd.repart.device = "/dev/vda"; 259 systemd.repart.partitions = { 260 "10-root" = { 261 Type = "root"; 262 Label = "created-root"; 263 Format = "ext4"; 264 }; 265 }; 266 }; 267 268 testScript = 269 { nodes, ... }: 270 '' 271 ${useDiskImage { inherit (nodes) machine; }} 272 273 machine.start() 274 machine.wait_for_unit("multi-user.target") 275 276 systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service") 277 assert "Adding new partition 2 to partition table." in systemd_repart_logs 278 ''; 279 }; 280}