at 23.05-pre 34 kB view raw
1{ system ? builtins.currentSystem, 2 config ? {}, 3 pkgs ? import ../.. { inherit system config; }, 4 systemdStage1 ? false 5}: 6 7with import ../lib/testing-python.nix { inherit system pkgs; }; 8with pkgs.lib; 9 10let 11 12 # The configuration to install. 13 makeConfig = { bootLoader, grubVersion, grubDevice, grubIdentifier, grubUseEfi 14 , extraConfig, forceGrubReinstallCount ? 0 15 }: 16 pkgs.writeText "configuration.nix" '' 17 { config, lib, pkgs, modulesPath, ... }: 18 19 { imports = 20 [ ./hardware-configuration.nix 21 <nixpkgs/nixos/modules/testing/test-instrumentation.nix> 22 ]; 23 24 # To ensure that we can rebuild the grub configuration on the nixos-rebuild 25 system.extraDependencies = with pkgs; [ stdenvNoCC ]; 26 27 ${optionalString systemdStage1 "boot.initrd.systemd.enable = true;"} 28 29 ${optionalString (bootLoader == "grub") '' 30 boot.loader.grub.version = ${toString grubVersion}; 31 ${optionalString (grubVersion == 1) '' 32 boot.loader.grub.splashImage = null; 33 ''} 34 35 boot.loader.grub.extraConfig = "serial; terminal_output serial"; 36 ${if grubUseEfi then '' 37 boot.loader.grub.device = "nodev"; 38 boot.loader.grub.efiSupport = true; 39 boot.loader.grub.efiInstallAsRemovable = true; # XXX: needed for OVMF? 40 '' else '' 41 boot.loader.grub.device = "${grubDevice}"; 42 boot.loader.grub.fsIdentifier = "${grubIdentifier}"; 43 ''} 44 45 boot.loader.grub.configurationLimit = 100 + ${toString forceGrubReinstallCount}; 46 ''} 47 48 ${optionalString (bootLoader == "systemd-boot") '' 49 boot.loader.systemd-boot.enable = true; 50 ''} 51 52 users.users.alice = { 53 isNormalUser = true; 54 home = "/home/alice"; 55 description = "Alice Foobar"; 56 }; 57 58 hardware.enableAllFirmware = lib.mkForce false; 59 60 ${replaceChars ["\n"] ["\n "] extraConfig} 61 } 62 ''; 63 64 65 # The test script boots a NixOS VM, installs NixOS on an empty hard 66 # disk, and then reboot from the hard disk. It's parameterized with 67 # a test script fragment `createPartitions', which must create 68 # partitions and filesystems. 69 testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi 70 , grubIdentifier, preBootCommands, postBootCommands, extraConfig 71 , testSpecialisationConfig 72 }: 73 let iface = if grubVersion == 1 then "ide" else "virtio"; 74 isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); 75 bios = if pkgs.stdenv.isAarch64 then "QEMU_EFI.fd" else "OVMF.fd"; 76 in if !isEfi && !pkgs.stdenv.hostPlatform.isx86 then 77 throw "Non-EFI boot methods are only supported on i686 / x86_64" 78 else '' 79 def assemble_qemu_flags(): 80 flags = "-cpu max" 81 ${if (system == "x86_64-linux" || system == "i686-linux") 82 then ''flags += " -m 1024"'' 83 else ''flags += " -m 768 -enable-kvm -machine virt,gic-version=host"'' 84 } 85 return flags 86 87 88 qemu_flags = {"qemuFlags": assemble_qemu_flags()} 89 90 hd_flags = { 91 "hdaInterface": "${iface}", 92 "hda": "vm-state-machine/machine.qcow2", 93 } 94 ${optionalString isEfi '' 95 hd_flags.update( 96 bios="${pkgs.OVMF.fd}/FV/${bios}" 97 )'' 98 } 99 default_flags = {**hd_flags, **qemu_flags} 100 101 102 def create_machine_named(name): 103 return create_machine({**default_flags, "name": name}) 104 105 106 machine.start() 107 108 with subtest("Assert readiness of login prompt"): 109 machine.succeed("echo hello") 110 111 with subtest("Wait for hard disks to appear in /dev"): 112 machine.succeed("udevadm settle") 113 114 ${createPartitions} 115 116 with subtest("Create the NixOS configuration"): 117 machine.succeed("nixos-generate-config --root /mnt") 118 machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2") 119 machine.copy_from_host( 120 "${ makeConfig { 121 inherit bootLoader grubVersion grubDevice grubIdentifier 122 grubUseEfi extraConfig; 123 } 124 }", 125 "/mnt/etc/nixos/configuration.nix", 126 ) 127 128 with subtest("Perform the installation"): 129 machine.succeed("nixos-install < /dev/null >&2") 130 131 with subtest("Do it again to make sure it's idempotent"): 132 machine.succeed("nixos-install < /dev/null >&2") 133 134 with subtest("Shutdown system after installation"): 135 machine.succeed("umount /mnt/boot || true") 136 machine.succeed("umount /mnt") 137 machine.succeed("sync") 138 machine.shutdown() 139 140 # Now see if we can boot the installation. 141 machine = create_machine_named("boot-after-install") 142 143 # For example to enter LUKS passphrase. 144 ${preBootCommands} 145 146 with subtest("Assert that /boot get mounted"): 147 machine.wait_for_unit("local-fs.target") 148 ${if bootLoader == "grub" 149 then ''machine.succeed("test -e /boot/grub")'' 150 else ''machine.succeed("test -e /boot/loader/loader.conf")'' 151 } 152 153 with subtest("Check whether /root has correct permissions"): 154 assert "700" in machine.succeed("stat -c '%a' /root") 155 156 with subtest("Assert swap device got activated"): 157 # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved 158 machine.wait_for_unit("swap.target") 159 machine.succeed("cat /proc/swaps | grep -q /dev") 160 161 with subtest("Check that the store is in good shape"): 162 machine.succeed("nix-store --verify --check-contents >&2") 163 164 with subtest("Check whether the channel works"): 165 machine.succeed("nix-env -iA nixos.procps >&2") 166 assert ".nix-profile" in machine.succeed("type -tP ps | tee /dev/stderr") 167 168 with subtest( 169 "Check that the daemon works, and that non-root users can run builds " 170 "(this will build a new profile generation through the daemon)" 171 ): 172 machine.succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2") 173 174 with subtest("Configure system with writable Nix store on next boot"): 175 # we're not using copy_from_host here because the installer image 176 # doesn't know about the host-guest sharing mechanism. 177 machine.copy_from_host_via_shell( 178 "${ makeConfig { 179 inherit bootLoader grubVersion grubDevice grubIdentifier 180 grubUseEfi extraConfig; 181 forceGrubReinstallCount = 1; 182 } 183 }", 184 "/etc/nixos/configuration.nix", 185 ) 186 187 with subtest("Check whether nixos-rebuild works"): 188 machine.succeed("nixos-rebuild switch >&2") 189 190 # FIXME: Nix 2.4 broke nixos-option, someone has to fix it. 191 # with subtest("Test nixos-option"): 192 # kernel_modules = machine.succeed("nixos-option boot.initrd.kernelModules") 193 # assert "virtio_console" in kernel_modules 194 # assert "List of modules" in kernel_modules 195 # assert "qemu-guest.nix" in kernel_modules 196 197 machine.shutdown() 198 199 # Check whether a writable store build works 200 machine = create_machine_named("rebuild-switch") 201 ${preBootCommands} 202 machine.wait_for_unit("multi-user.target") 203 204 # we're not using copy_from_host here because the installer image 205 # doesn't know about the host-guest sharing mechanism. 206 machine.copy_from_host_via_shell( 207 "${ makeConfig { 208 inherit bootLoader grubVersion grubDevice grubIdentifier 209 grubUseEfi extraConfig; 210 forceGrubReinstallCount = 2; 211 } 212 }", 213 "/etc/nixos/configuration.nix", 214 ) 215 machine.succeed("nixos-rebuild boot >&2") 216 machine.shutdown() 217 218 # And just to be sure, check that the machine still boots after 219 # "nixos-rebuild switch". 220 machine = create_machine_named("boot-after-rebuild-switch") 221 ${preBootCommands} 222 machine.wait_for_unit("network.target") 223 ${postBootCommands} 224 machine.shutdown() 225 226 # Tests for validating clone configuration entries in grub menu 227 '' 228 + optionalString testSpecialisationConfig '' 229 # Reboot Machine 230 machine = create_machine_named("clone-default-config") 231 ${preBootCommands} 232 machine.wait_for_unit("multi-user.target") 233 234 with subtest("Booted configuration name should be 'Home'"): 235 # This is not the name that shows in the grub menu. 236 # The default configuration is always shown as "Default" 237 machine.succeed("cat /run/booted-system/configuration-name >&2") 238 assert "Home" in machine.succeed("cat /run/booted-system/configuration-name") 239 240 with subtest("We should **not** find a file named /etc/gitconfig"): 241 machine.fail("test -e /etc/gitconfig") 242 243 with subtest("Set grub to boot the second configuration"): 244 machine.succeed("grub-reboot 1") 245 246 ${postBootCommands} 247 machine.shutdown() 248 249 # Reboot Machine 250 machine = create_machine_named("clone-alternate-config") 251 ${preBootCommands} 252 253 machine.wait_for_unit("multi-user.target") 254 with subtest("Booted configuration name should be Work"): 255 machine.succeed("cat /run/booted-system/configuration-name >&2") 256 assert "Work" in machine.succeed("cat /run/booted-system/configuration-name") 257 258 with subtest("We should find a file named /etc/gitconfig"): 259 machine.succeed("test -e /etc/gitconfig") 260 261 ${postBootCommands} 262 machine.shutdown() 263 ''; 264 265 266 makeInstallerTest = name: 267 { createPartitions, preBootCommands ? "", postBootCommands ? "", extraConfig ? "" 268 , extraInstallerConfig ? {} 269 , bootLoader ? "grub" # either "grub" or "systemd-boot" 270 , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false 271 , enableOCR ? false, meta ? {} 272 , testSpecialisationConfig ? false 273 }: 274 makeTest { 275 inherit enableOCR; 276 name = "installer-" + name; 277 meta = with pkgs.lib.maintainers; { 278 # put global maintainers here, individuals go into makeInstallerTest fkt call 279 maintainers = (meta.maintainers or []); 280 }; 281 nodes = { 282 283 # The configuration of the machine used to run "nixos-install". 284 machine = { pkgs, ... }: { 285 imports = [ 286 ../modules/profiles/installation-device.nix 287 ../modules/profiles/base.nix 288 extraInstallerConfig 289 ]; 290 291 # builds stuff in the VM, needs more juice 292 virtualisation.diskSize = 8 * 1024; 293 virtualisation.cores = 8; 294 virtualisation.memorySize = 1536; 295 296 boot.initrd.systemd.enable = systemdStage1; 297 298 # Use a small /dev/vdb as the root disk for the 299 # installer. This ensures the target disk (/dev/vda) is 300 # the same during and after installation. 301 virtualisation.emptyDiskImages = [ 512 ]; 302 virtualisation.bootDevice = 303 if grubVersion == 1 then "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive2" else "/dev/vdb"; 304 virtualisation.qemu.diskInterface = 305 if grubVersion == 1 then "scsi" else "virtio"; 306 307 # We don't want to have any networking in the guest whatsoever. 308 # Also, if any vlans are enabled, the guest will reboot 309 # (with a different configuration for legacy reasons), 310 # and spend 5 minutes waiting for the vlan interface to show up 311 # (which will never happen). 312 virtualisation.vlans = []; 313 314 boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true; 315 316 hardware.enableAllFirmware = mkForce false; 317 318 # The test cannot access the network, so any packages we 319 # need must be included in the VM. 320 system.extraDependencies = with pkgs; [ 321 brotli 322 brotli.dev 323 brotli.lib 324 desktop-file-utils 325 docbook5 326 docbook_xsl_ns 327 (docbook-xsl-ns.override { 328 withManOptDedupPatch = true; 329 }) 330 kmod.dev 331 libarchive.dev 332 libxml2.bin 333 libxslt.bin 334 nixos-artwork.wallpapers.simple-dark-gray-bottom 335 ntp 336 perlPackages.ListCompare 337 perlPackages.XMLLibXML 338 python3Minimal 339 # make-options-doc/default.nix 340 (let 341 self = (pkgs.python3Minimal.override { 342 inherit self; 343 includeSiteCustomize = true; 344 }); 345 in self.withPackages (p: [ p.mistune ])) 346 shared-mime-info 347 sudo 348 texinfo 349 unionfs-fuse 350 xorg.lndir 351 352 # add curl so that rather than seeing the test attempt to download 353 # curl's tarball, we see what it's trying to download 354 curl 355 ] 356 ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub 357 ++ optionals (bootLoader == "grub" && grubVersion == 2) (let 358 zfsSupport = lib.any (x: x == "zfs") 359 (extraInstallerConfig.boot.supportedFilesystems or []); 360 in [ 361 (pkgs.grub2.override { inherit zfsSupport; }) 362 (pkgs.grub2_efi.override { inherit zfsSupport; }) 363 ]); 364 365 nix.settings = { 366 substituters = mkForce []; 367 hashed-mirrors = null; 368 connect-timeout = 1; 369 }; 370 }; 371 372 }; 373 374 testScript = testScriptFun { 375 inherit bootLoader createPartitions preBootCommands postBootCommands 376 grubVersion grubDevice grubIdentifier grubUseEfi extraConfig 377 testSpecialisationConfig; 378 }; 379 }; 380 381 makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name { 382 createPartitions = '' 383 machine.succeed( 384 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 385 + " mkpart primary ext2 1M 100MB" # /boot 386 + " mkpart primary linux-swap 100M 1024M" 387 + " mkpart primary 1024M -1s", # LUKS 388 "udevadm settle", 389 "mkswap /dev/vda2 -L swap", 390 "swapon -L swap", 391 "modprobe dm_mod dm_crypt", 392 "echo -n supersecret | cryptsetup luksFormat ${luksFormatOpts} -q /dev/vda3 -", 393 "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda3 cryptroot", 394 "mkfs.ext3 -L nixos /dev/mapper/cryptroot", 395 "mount LABEL=nixos /mnt", 396 "mkfs.ext3 -L boot /dev/vda1", 397 "mkdir -p /mnt/boot", 398 "mount LABEL=boot /mnt/boot", 399 ) 400 ''; 401 extraConfig = '' 402 boot.kernelParams = lib.mkAfter [ "console=tty0" ]; 403 ''; 404 enableOCR = true; 405 preBootCommands = '' 406 machine.start() 407 machine.wait_for_text("Passphrase for") 408 machine.send_chars("supersecret\n") 409 ''; 410 }; 411 412 # The (almost) simplest partitioning scheme: a swap partition and 413 # one big filesystem partition. 414 simple-test-config = { 415 createPartitions = '' 416 machine.succeed( 417 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 418 + " mkpart primary linux-swap 1M 1024M" 419 + " mkpart primary ext2 1024M -1s", 420 "udevadm settle", 421 "mkswap /dev/vda1 -L swap", 422 "swapon -L swap", 423 "mkfs.ext3 -L nixos /dev/vda2", 424 "mount LABEL=nixos /mnt", 425 ) 426 ''; 427 }; 428 429 simple-uefi-grub-config = { 430 createPartitions = '' 431 machine.succeed( 432 "flock /dev/vda parted --script /dev/vda -- mklabel gpt" 433 + " mkpart ESP fat32 1M 100MiB" # /boot 434 + " set 1 boot on" 435 + " mkpart primary linux-swap 100MiB 1024MiB" 436 + " mkpart primary ext2 1024MiB -1MiB", # / 437 "udevadm settle", 438 "mkswap /dev/vda2 -L swap", 439 "swapon -L swap", 440 "mkfs.ext3 -L nixos /dev/vda3", 441 "mount LABEL=nixos /mnt", 442 "mkfs.vfat -n BOOT /dev/vda1", 443 "mkdir -p /mnt/boot", 444 "mount LABEL=BOOT /mnt/boot", 445 ) 446 ''; 447 bootLoader = "grub"; 448 grubUseEfi = true; 449 }; 450 451 specialisation-test-extraconfig = { 452 extraConfig = '' 453 environment.systemPackages = [ pkgs.grub2 ]; 454 boot.loader.grub.configurationName = "Home"; 455 specialisation.work.configuration = { 456 boot.loader.grub.configurationName = lib.mkForce "Work"; 457 458 environment.etc = { 459 "gitconfig".text = " 460 [core] 461 gitproxy = none for work.com 462 "; 463 }; 464 }; 465 ''; 466 testSpecialisationConfig = true; 467 }; 468 469 470in { 471 472 # !!! `parted mkpart' seems to silently create overlapping partitions. 473 474 475 # The (almost) simplest partitioning scheme: a swap partition and 476 # one big filesystem partition. 477 simple = makeInstallerTest "simple" simple-test-config; 478 479 # Test cloned configurations with the simple grub configuration 480 simpleSpecialised = makeInstallerTest "simpleSpecialised" (simple-test-config // specialisation-test-extraconfig); 481 482 # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem 483 simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" { 484 createPartitions = '' 485 machine.succeed( 486 "flock /dev/vda parted --script /dev/vda -- mklabel gpt" 487 + " mkpart ESP fat32 1M 100MiB" # /boot 488 + " set 1 boot on" 489 + " mkpart primary linux-swap 100MiB 1024MiB" 490 + " mkpart primary ext2 1024MiB -1MiB", # / 491 "udevadm settle", 492 "mkswap /dev/vda2 -L swap", 493 "swapon -L swap", 494 "mkfs.ext3 -L nixos /dev/vda3", 495 "mount LABEL=nixos /mnt", 496 "mkfs.vfat -n BOOT /dev/vda1", 497 "mkdir -p /mnt/boot", 498 "mount LABEL=BOOT /mnt/boot", 499 ) 500 ''; 501 bootLoader = "systemd-boot"; 502 }; 503 504 simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config; 505 506 # Test cloned configurations with the uefi grub configuration 507 simpleUefiGrubSpecialisation = makeInstallerTest "simpleUefiGrubSpecialisation" (simple-uefi-grub-config // specialisation-test-extraconfig); 508 509 # Same as the previous, but now with a separate /boot partition. 510 separateBoot = makeInstallerTest "separateBoot" { 511 createPartitions = '' 512 machine.succeed( 513 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 514 + " mkpart primary ext2 1M 100MB" # /boot 515 + " mkpart primary linux-swap 100MB 1024M" 516 + " mkpart primary ext2 1024M -1s", # / 517 "udevadm settle", 518 "mkswap /dev/vda2 -L swap", 519 "swapon -L swap", 520 "mkfs.ext3 -L nixos /dev/vda3", 521 "mount LABEL=nixos /mnt", 522 "mkfs.ext3 -L boot /dev/vda1", 523 "mkdir -p /mnt/boot", 524 "mount LABEL=boot /mnt/boot", 525 ) 526 ''; 527 }; 528 529 # Same as the previous, but with fat32 /boot. 530 separateBootFat = makeInstallerTest "separateBootFat" { 531 createPartitions = '' 532 machine.succeed( 533 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 534 + " mkpart primary ext2 1M 100MB" # /boot 535 + " mkpart primary linux-swap 100MB 1024M" 536 + " mkpart primary ext2 1024M -1s", # / 537 "udevadm settle", 538 "mkswap /dev/vda2 -L swap", 539 "swapon -L swap", 540 "mkfs.ext3 -L nixos /dev/vda3", 541 "mount LABEL=nixos /mnt", 542 "mkfs.vfat -n BOOT /dev/vda1", 543 "mkdir -p /mnt/boot", 544 "mount LABEL=BOOT /mnt/boot", 545 ) 546 ''; 547 }; 548 549 # zfs on / with swap 550 zfsroot = makeInstallerTest "zfs-root" { 551 extraInstallerConfig = { 552 boot.supportedFilesystems = [ "zfs" ]; 553 }; 554 555 extraConfig = '' 556 boot.supportedFilesystems = [ "zfs" ]; 557 558 # Using by-uuid overrides the default of by-id, and is unique 559 # to the qemu disks, as they don't produce by-id paths for 560 # some reason. 561 boot.zfs.devNodes = "/dev/disk/by-uuid/"; 562 networking.hostId = "00000000"; 563 ''; 564 565 createPartitions = '' 566 machine.succeed( 567 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 568 + " mkpart primary linux-swap 1M 1024M" 569 + " mkpart primary 1024M -1s", 570 "udevadm settle", 571 "mkswap /dev/vda1 -L swap", 572 "swapon -L swap", 573 "zpool create rpool /dev/vda2", 574 "zfs create -o mountpoint=legacy rpool/root", 575 "mount -t zfs rpool/root /mnt", 576 "udevadm settle", 577 ) 578 ''; 579 }; 580 581 # Create two physical LVM partitions combined into one volume group 582 # that contains the logical swap and root partitions. 583 lvm = makeInstallerTest "lvm" { 584 createPartitions = '' 585 machine.succeed( 586 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 587 + " mkpart primary 1M 2048M" # PV1 588 + " set 1 lvm on" 589 + " mkpart primary 2048M -1s" # PV2 590 + " set 2 lvm on", 591 "udevadm settle", 592 "pvcreate /dev/vda1 /dev/vda2", 593 "vgcreate MyVolGroup /dev/vda1 /dev/vda2", 594 "lvcreate --size 1G --name swap MyVolGroup", 595 "lvcreate --size 6G --name nixos MyVolGroup", 596 "mkswap -f /dev/MyVolGroup/swap -L swap", 597 "swapon -L swap", 598 "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", 599 "mount LABEL=nixos /mnt", 600 ) 601 ''; 602 }; 603 604 # Boot off an encrypted root partition with the default LUKS header format 605 luksroot = makeLuksRootTest "luksroot-format1" ""; 606 607 # Boot off an encrypted root partition with LUKS1 format 608 luksroot-format1 = makeLuksRootTest "luksroot-format1" "--type=LUKS1"; 609 610 # Boot off an encrypted root partition with LUKS2 format 611 luksroot-format2 = makeLuksRootTest "luksroot-format2" "--type=LUKS2"; 612 613 # Test whether opening encrypted filesystem with keyfile 614 # Checks for regression of missing cryptsetup, when no luks device without 615 # keyfile is configured 616 encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile" { 617 createPartitions = '' 618 machine.succeed( 619 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 620 + " mkpart primary ext2 1M 100MB" # /boot 621 + " mkpart primary linux-swap 100M 1024M" 622 + " mkpart primary 1024M 1280M" # LUKS with keyfile 623 + " mkpart primary 1280M -1s", 624 "udevadm settle", 625 "mkswap /dev/vda2 -L swap", 626 "swapon -L swap", 627 "mkfs.ext3 -L nixos /dev/vda4", 628 "mount LABEL=nixos /mnt", 629 "mkfs.ext3 -L boot /dev/vda1", 630 "mkdir -p /mnt/boot", 631 "mount LABEL=boot /mnt/boot", 632 "modprobe dm_mod dm_crypt", 633 "echo -n supersecret > /mnt/keyfile", 634 "cryptsetup luksFormat -q /dev/vda3 --key-file /mnt/keyfile", 635 "cryptsetup luksOpen --key-file /mnt/keyfile /dev/vda3 crypt", 636 "mkfs.ext3 -L test /dev/mapper/crypt", 637 "cryptsetup luksClose crypt", 638 "mkdir -p /mnt/test", 639 ) 640 ''; 641 extraConfig = '' 642 fileSystems."/test" = { 643 device = "/dev/disk/by-label/test"; 644 fsType = "ext3"; 645 encrypted.enable = true; 646 encrypted.blkDev = "/dev/vda3"; 647 encrypted.label = "crypt"; 648 encrypted.keyFile = "/mnt-root/keyfile"; 649 }; 650 ''; 651 }; 652 653 swraid = makeInstallerTest "swraid" { 654 createPartitions = '' 655 machine.succeed( 656 "flock /dev/vda parted --script /dev/vda --" 657 + " mklabel msdos" 658 + " mkpart primary ext2 1M 100MB" # /boot 659 + " mkpart extended 100M -1s" 660 + " mkpart logical 102M 3102M" # md0 (root), first device 661 + " mkpart logical 3103M 6103M" # md0 (root), second device 662 + " mkpart logical 6104M 6360M" # md1 (swap), first device 663 + " mkpart logical 6361M 6617M", # md1 (swap), second device 664 "udevadm settle", 665 "ls -l /dev/vda* >&2", 666 "cat /proc/partitions >&2", 667 "udevadm control --stop-exec-queue", 668 "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 " 669 + "--raid-devices=2 /dev/vda5 /dev/vda6", 670 "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 " 671 + "--raid-devices=2 /dev/vda7 /dev/vda8", 672 "udevadm control --start-exec-queue", 673 "udevadm settle", 674 "mkswap -f /dev/md1 -L swap", 675 "swapon -L swap", 676 "mkfs.ext3 -L nixos /dev/md0", 677 "mount LABEL=nixos /mnt", 678 "mkfs.ext3 -L boot /dev/vda1", 679 "mkdir /mnt/boot", 680 "mount LABEL=boot /mnt/boot", 681 "udevadm settle", 682 ) 683 ''; 684 preBootCommands = '' 685 machine.start() 686 machine.fail("dmesg | grep 'immediate safe mode'") 687 ''; 688 }; 689 690 bcache = makeInstallerTest "bcache" { 691 createPartitions = '' 692 machine.succeed( 693 "flock /dev/vda parted --script /dev/vda --" 694 + " mklabel msdos" 695 + " mkpart primary ext2 1M 100MB" # /boot 696 + " mkpart primary 100MB 512MB " # swap 697 + " mkpart primary 512MB 1024MB" # Cache (typically SSD) 698 + " mkpart primary 1024MB -1s ", # Backing device (typically HDD) 699 "modprobe bcache", 700 "udevadm settle", 701 "make-bcache -B /dev/vda4 -C /dev/vda3", 702 "udevadm settle", 703 "mkfs.ext3 -L nixos /dev/bcache0", 704 "mount LABEL=nixos /mnt", 705 "mkfs.ext3 -L boot /dev/vda1", 706 "mkdir /mnt/boot", 707 "mount LABEL=boot /mnt/boot", 708 "mkswap -f /dev/vda2 -L swap", 709 "swapon -L swap", 710 ) 711 ''; 712 }; 713 714 bcachefsSimple = makeInstallerTest "bcachefs-simple" { 715 extraInstallerConfig = { 716 boot.supportedFilesystems = [ "bcachefs" ]; 717 }; 718 719 createPartitions = '' 720 machine.succeed( 721 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 722 + " mkpart primary ext2 1M 100MB" # /boot 723 + " mkpart primary linux-swap 100M 1024M" # swap 724 + " mkpart primary 1024M -1s", # / 725 "udevadm settle", 726 "mkswap /dev/vda2 -L swap", 727 "swapon -L swap", 728 "mkfs.bcachefs -L root /dev/vda3", 729 "mount -t bcachefs /dev/vda3 /mnt", 730 "mkfs.ext3 -L boot /dev/vda1", 731 "mkdir -p /mnt/boot", 732 "mount /dev/vda1 /mnt/boot", 733 ) 734 ''; 735 }; 736 737 bcachefsEncrypted = makeInstallerTest "bcachefs-encrypted" { 738 extraInstallerConfig = { 739 boot.supportedFilesystems = [ "bcachefs" ]; 740 environment.systemPackages = with pkgs; [ keyutils ]; 741 }; 742 743 # We don't want to use the normal way of unlocking bcachefs defined in tasks/filesystems/bcachefs.nix. 744 # So, override initrd.postDeviceCommands completely and simply unlock with the predefined password. 745 extraConfig = '' 746 boot.initrd.postDeviceCommands = lib.mkForce "echo password | bcachefs unlock /dev/vda3"; 747 ''; 748 749 createPartitions = '' 750 machine.succeed( 751 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 752 + " mkpart primary ext2 1M 100MB" # /boot 753 + " mkpart primary linux-swap 100M 1024M" # swap 754 + " mkpart primary 1024M -1s", # / 755 "udevadm settle", 756 "mkswap /dev/vda2 -L swap", 757 "swapon -L swap", 758 "keyctl link @u @s", 759 "echo password | mkfs.bcachefs -L root --encrypted /dev/vda3", 760 "echo password | bcachefs unlock /dev/vda3", 761 "mount -t bcachefs /dev/vda3 /mnt", 762 "mkfs.ext3 -L boot /dev/vda1", 763 "mkdir -p /mnt/boot", 764 "mount /dev/vda1 /mnt/boot", 765 ) 766 ''; 767 }; 768 769 bcachefsMulti = makeInstallerTest "bcachefs-multi" { 770 extraInstallerConfig = { 771 boot.supportedFilesystems = [ "bcachefs" ]; 772 }; 773 774 createPartitions = '' 775 machine.succeed( 776 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 777 + " mkpart primary ext2 1M 100MB" # /boot 778 + " mkpart primary linux-swap 100M 1024M" # swap 779 + " mkpart primary 1024M 4096M" # / 780 + " mkpart primary 4096M -1s", # / 781 "udevadm settle", 782 "mkswap /dev/vda2 -L swap", 783 "swapon -L swap", 784 "mkfs.bcachefs -L root --metadata_replicas 2 --foreground_target ssd --promote_target ssd --background_target hdd --label ssd /dev/vda3 --label hdd /dev/vda4", 785 "mount -t bcachefs /dev/vda3:/dev/vda4 /mnt", 786 "mkfs.ext3 -L boot /dev/vda1", 787 "mkdir -p /mnt/boot", 788 "mount /dev/vda1 /mnt/boot", 789 ) 790 ''; 791 }; 792 793 # Test a basic install using GRUB 1. 794 grub1 = makeInstallerTest "grub1" rec { 795 createPartitions = '' 796 machine.succeed( 797 "flock ${grubDevice} parted --script ${grubDevice} -- mklabel msdos" 798 + " mkpart primary linux-swap 1M 1024M" 799 + " mkpart primary ext2 1024M -1s", 800 "udevadm settle", 801 "mkswap ${grubDevice}-part1 -L swap", 802 "swapon -L swap", 803 "mkfs.ext3 -L nixos ${grubDevice}-part2", 804 "mount LABEL=nixos /mnt", 805 "mkdir -p /mnt/tmp", 806 ) 807 ''; 808 grubVersion = 1; 809 # /dev/sda is not stable, even when the SCSI disk number is. 810 grubDevice = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive1"; 811 }; 812 813 # Test using labels to identify volumes in grub 814 simpleLabels = makeInstallerTest "simpleLabels" { 815 createPartitions = '' 816 machine.succeed( 817 "sgdisk -Z /dev/vda", 818 "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", 819 "mkswap /dev/vda2 -L swap", 820 "swapon -L swap", 821 "mkfs.ext4 -L root /dev/vda3", 822 "mount LABEL=root /mnt", 823 ) 824 ''; 825 grubIdentifier = "label"; 826 }; 827 828 # Test using the provided disk name within grub 829 # TODO: Fix udev so the symlinks are unneeded in /dev/disks 830 simpleProvided = makeInstallerTest "simpleProvided" { 831 createPartitions = '' 832 uuid = "$(blkid -s UUID -o value /dev/vda2)" 833 machine.succeed( 834 "sgdisk -Z /dev/vda", 835 "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 " 836 + "-t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda", 837 "mkswap /dev/vda3 -L swap", 838 "swapon -L swap", 839 "mkfs.ext4 -L boot /dev/vda2", 840 "mkfs.ext4 -L root /dev/vda4", 841 ) 842 machine.execute(f"ln -s ../../vda2 /dev/disk/by-uuid/{uuid}") 843 machine.execute("ln -s ../../vda4 /dev/disk/by-label/root") 844 machine.succeed( 845 "mount /dev/disk/by-label/root /mnt", 846 "mkdir /mnt/boot", 847 f"mount /dev/disk/by-uuid/{uuid} /mnt/boot", 848 ) 849 ''; 850 grubIdentifier = "provided"; 851 }; 852 853 # Simple btrfs grub testing 854 btrfsSimple = makeInstallerTest "btrfsSimple" { 855 createPartitions = '' 856 machine.succeed( 857 "sgdisk -Z /dev/vda", 858 "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", 859 "mkswap /dev/vda2 -L swap", 860 "swapon -L swap", 861 "mkfs.btrfs -L root /dev/vda3", 862 "mount LABEL=root /mnt", 863 ) 864 ''; 865 }; 866 867 # Test to see if we can detect /boot and /nix on subvolumes 868 btrfsSubvols = makeInstallerTest "btrfsSubvols" { 869 createPartitions = '' 870 machine.succeed( 871 "sgdisk -Z /dev/vda", 872 "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", 873 "mkswap /dev/vda2 -L swap", 874 "swapon -L swap", 875 "mkfs.btrfs -L root /dev/vda3", 876 "btrfs device scan", 877 "mount LABEL=root /mnt", 878 "btrfs subvol create /mnt/boot", 879 "btrfs subvol create /mnt/nixos", 880 "btrfs subvol create /mnt/nixos/default", 881 "umount /mnt", 882 "mount -o defaults,subvol=nixos/default LABEL=root /mnt", 883 "mkdir /mnt/boot", 884 "mount -o defaults,subvol=boot LABEL=root /mnt/boot", 885 ) 886 ''; 887 }; 888 889 # Test to see if we can detect default and aux subvolumes correctly 890 btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" { 891 createPartitions = '' 892 machine.succeed( 893 "sgdisk -Z /dev/vda", 894 "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", 895 "mkswap /dev/vda2 -L swap", 896 "swapon -L swap", 897 "mkfs.btrfs -L root /dev/vda3", 898 "btrfs device scan", 899 "mount LABEL=root /mnt", 900 "btrfs subvol create /mnt/badpath", 901 "btrfs subvol create /mnt/badpath/boot", 902 "btrfs subvol create /mnt/nixos", 903 "btrfs subvol set-default " 904 + "$(btrfs subvol list /mnt | grep 'nixos' | awk '{print $2}') /mnt", 905 "umount /mnt", 906 "mount -o defaults LABEL=root /mnt", 907 "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism 908 # is actually looking up subvolumes 909 "mkdir /mnt/boot", 910 "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", 911 ) 912 ''; 913 }; 914 915 # Test to see if we can deal with subvols that need to be escaped in fstab 916 btrfsSubvolEscape = makeInstallerTest "btrfsSubvolEscape" { 917 createPartitions = '' 918 machine.succeed( 919 "sgdisk -Z /dev/vda", 920 "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", 921 "mkswap /dev/vda2 -L swap", 922 "swapon -L swap", 923 "mkfs.btrfs -L root /dev/vda3", 924 "btrfs device scan", 925 "mount LABEL=root /mnt", 926 "btrfs subvol create '/mnt/nixos in space'", 927 "btrfs subvol create /mnt/boot", 928 "umount /mnt", 929 "mount -o 'defaults,subvol=nixos in space' LABEL=root /mnt", 930 "mkdir /mnt/boot", 931 "mount -o defaults,subvol=boot LABEL=root /mnt/boot", 932 ) 933 ''; 934 }; 935}