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