at 16.09-beta 20 kB view raw
1{ system ? builtins.currentSystem }: 2 3with import ../lib/testing.nix { inherit system; }; 4with import ../lib/qemu-flags.nix; 5with pkgs.lib; 6 7let 8 9 # The configuration to install. 10 makeConfig = { bootLoader, grubVersion, grubDevice, grubIdentifier 11 , extraConfig, forceGrubReinstallCount ? 0 12 }: 13 pkgs.writeText "configuration.nix" '' 14 { config, lib, pkgs, modulesPath, ... }: 15 16 { imports = 17 [ ./hardware-configuration.nix 18 <nixpkgs/nixos/modules/testing/test-instrumentation.nix> 19 ]; 20 21 ${optionalString (bootLoader == "grub") '' 22 boot.loader.grub.version = ${toString grubVersion}; 23 ${optionalString (grubVersion == 1) '' 24 boot.loader.grub.splashImage = null; 25 ''} 26 boot.loader.grub.device = "${grubDevice}"; 27 boot.loader.grub.extraConfig = "serial; terminal_output.serial"; 28 boot.loader.grub.fsIdentifier = "${grubIdentifier}"; 29 30 boot.loader.grub.configurationLimit = 100 + ${toString forceGrubReinstallCount}; 31 ''} 32 33 ${optionalString (bootLoader == "systemd-boot") '' 34 boot.loader.systemd-boot.enable = true; 35 ''} 36 37 hardware.enableAllFirmware = lib.mkForce false; 38 39 ${replaceChars ["\n"] ["\n "] extraConfig} 40 } 41 ''; 42 43 44 channelContents = [ pkgs.rlwrap ]; 45 46 47 # The test script boots a NixOS VM, installs NixOS on an empty hard 48 # disk, and then reboot from the hard disk. It's parameterized with 49 # a test script fragment `createPartitions', which must create 50 # partitions and filesystems. 51 testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice 52 , grubIdentifier, preBootCommands, extraConfig 53 }: 54 let 55 iface = if grubVersion == 1 then "ide" else "virtio"; 56 qemuFlags = 57 (if system == "x86_64-linux" then "-m 768 " else "-m 512 ") + 58 (optionalString (system == "x86_64-linux") "-cpu kvm64 "); 59 hdFlags = ''hda => "vm-state-machine/machine.qcow2", hdaInterface => "${iface}", '' 60 + optionalString (bootLoader == "systemd-boot") ''bios => "${pkgs.OVMF}/FV/OVMF.fd", ''; 61 in 62 '' 63 $machine->start; 64 65 # Make sure that we get a login prompt etc. 66 $machine->succeed("echo hello"); 67 #$machine->waitForUnit('getty@tty2'); 68 $machine->waitForUnit("rogue"); 69 $machine->waitForUnit("nixos-manual"); 70 71 # Wait for hard disks to appear in /dev 72 $machine->succeed("udevadm settle"); 73 74 # Partition the disk. 75 ${createPartitions} 76 77 # Create the NixOS configuration. 78 $machine->succeed("nixos-generate-config --root /mnt"); 79 80 $machine->succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2"); 81 82 $machine->copyFileFromHost( 83 "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier extraConfig; } }", 84 "/mnt/etc/nixos/configuration.nix"); 85 86 # Perform the installation. 87 $machine->succeed("nixos-install < /dev/null >&2"); 88 89 # Do it again to make sure it's idempotent. 90 $machine->succeed("nixos-install < /dev/null >&2"); 91 92 $machine->succeed("umount /mnt/boot || true"); 93 $machine->succeed("umount /mnt"); 94 $machine->succeed("sync"); 95 96 $machine->shutdown; 97 98 # Now see if we can boot the installation. 99 $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" }); 100 101 # For example to enter LUKS passphrase. 102 ${preBootCommands} 103 104 # Did /boot get mounted? 105 $machine->waitForUnit("local-fs.target"); 106 107 ${if bootLoader == "grub" then 108 ''$machine->succeed("test -e /boot/grub");'' 109 else 110 ''$machine->succeed("test -e /boot/loader/loader.conf");'' 111 } 112 113 # Check whether /root has correct permissions. 114 $machine->succeed("stat -c '%a' /root") =~ /700/ or die; 115 116 # Did the swap device get activated? 117 # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved 118 #$machine->waitForUnit("swap.target"); 119 $machine->waitUntilSucceeds("cat /proc/swaps | grep -q /dev"); 120 121 # Check whether the channel works. 122 $machine->succeed("nix-env -iA nixos.procps >&2"); 123 $machine->succeed("type -tP ps | tee /dev/stderr") =~ /.nix-profile/ 124 or die "nix-env failed"; 125 126 # We need to a writable nix-store on next boot. 127 $machine->copyFileFromHost( 128 "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier extraConfig; forceGrubReinstallCount = 1; } }", 129 "/etc/nixos/configuration.nix"); 130 131 # Check whether nixos-rebuild works. 132 $machine->succeed("nixos-rebuild switch >&2"); 133 134 # Test nixos-option. 135 $machine->succeed("nixos-option boot.initrd.kernelModules | grep virtio_console"); 136 $machine->succeed("nixos-option boot.initrd.kernelModules | grep 'List of modules'"); 137 $machine->succeed("nixos-option boot.initrd.kernelModules | grep qemu-guest.nix"); 138 139 $machine->shutdown; 140 141 # Check whether a writable store build works 142 $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" }); 143 ${preBootCommands} 144 $machine->waitForUnit("multi-user.target"); 145 $machine->copyFileFromHost( 146 "${ makeConfig { inherit bootLoader grubVersion grubDevice grubIdentifier extraConfig; forceGrubReinstallCount = 2; } }", 147 "/etc/nixos/configuration.nix"); 148 $machine->succeed("nixos-rebuild boot >&2"); 149 $machine->shutdown; 150 151 # And just to be sure, check that the machine still boots after 152 # "nixos-rebuild switch". 153 $machine = createMachine({ ${hdFlags} qemuFlags => "${qemuFlags}" }); 154 ${preBootCommands} 155 $machine->waitForUnit("network.target"); 156 $machine->shutdown; 157 ''; 158 159 160 makeInstallerTest = name: 161 { createPartitions, preBootCommands ? "", extraConfig ? "" 162 , bootLoader ? "grub" # either "grub" or "systemd-boot" 163 , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid" 164 , enableOCR ? false, meta ? {} 165 }: 166 makeTest { 167 inherit enableOCR; 168 name = "installer-" + name; 169 meta = with pkgs.stdenv.lib.maintainers; { 170 # put global maintainers here, individuals go into makeInstallerTest fkt call 171 maintainers = [ wkennington ] ++ (meta.maintainers or []); 172 }; 173 nodes = { 174 175 # The configuration of the machine used to run "nixos-install". It 176 # also has a web server that simulates cache.nixos.org. 177 machine = 178 { config, lib, pkgs, ... }: 179 180 { imports = 181 [ ../modules/profiles/installation-device.nix 182 ../modules/profiles/base.nix 183 ]; 184 185 virtualisation.diskSize = 8 * 1024; 186 virtualisation.memorySize = 1024; 187 virtualisation.writableStore = true; 188 189 # Use a small /dev/vdb as the root disk for the 190 # installer. This ensures the target disk (/dev/vda) is 191 # the same during and after installation. 192 virtualisation.emptyDiskImages = [ 512 ]; 193 virtualisation.bootDevice = 194 if grubVersion == 1 then "/dev/sdb" else "/dev/vdb"; 195 virtualisation.qemu.diskInterface = 196 if grubVersion == 1 then "scsi" else "virtio"; 197 198 boot.loader.systemd-boot.enable = mkIf (bootLoader == "systemd-boot") true; 199 200 hardware.enableAllFirmware = mkForce false; 201 202 # The test cannot access the network, so any packages we 203 # need must be included in the VM. 204 system.extraDependencies = with pkgs; 205 [ sudo 206 libxml2.bin 207 libxslt.bin 208 docbook5 209 docbook5_xsl 210 unionfs-fuse 211 ntp 212 nixos-artwork 213 perlPackages.XMLLibXML 214 perlPackages.ListCompare 215 216 # add curl so that rather than seeing the test attempt to download 217 # curl's tarball, we see what it's trying to download 218 curl 219 ] 220 ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub 221 ++ optionals (bootLoader == "grub" && grubVersion == 2) [ pkgs.grub2 pkgs.grub2_efi ]; 222 223 nix.binaryCaches = mkForce [ ]; 224 }; 225 226 }; 227 228 testScript = testScriptFun { 229 inherit bootLoader createPartitions preBootCommands 230 grubVersion grubDevice grubIdentifier extraConfig; 231 }; 232 }; 233 234 235in { 236 237 # !!! `parted mkpart' seems to silently create overlapping partitions. 238 239 240 # The (almost) simplest partitioning scheme: a swap partition and 241 # one big filesystem partition. 242 simple = makeInstallerTest "simple" 243 { createPartitions = 244 '' 245 $machine->succeed( 246 "parted /dev/vda mklabel msdos", 247 "parted /dev/vda -- mkpart primary linux-swap 1M 1024M", 248 "parted /dev/vda -- mkpart primary ext2 1024M -1s", 249 "udevadm settle", 250 "mkswap /dev/vda1 -L swap", 251 "swapon -L swap", 252 "mkfs.ext3 -L nixos /dev/vda2", 253 "mount LABEL=nixos /mnt", 254 ); 255 ''; 256 }; 257 258 # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem 259 simpleUefiGummiboot = makeInstallerTest "simpleUefiGummiboot" 260 { createPartitions = 261 '' 262 $machine->succeed( 263 "parted /dev/vda mklabel gpt", 264 "parted -s /dev/vda -- mkpart ESP fat32 1M 50MiB", # /boot 265 "parted -s /dev/vda -- set 1 boot on", 266 "parted -s /dev/vda -- mkpart primary linux-swap 50MiB 1024MiB", 267 "parted -s /dev/vda -- mkpart primary ext2 1024MiB -1MiB", # / 268 "udevadm settle", 269 "mkswap /dev/vda2 -L swap", 270 "swapon -L swap", 271 "mkfs.ext3 -L nixos /dev/vda3", 272 "mount LABEL=nixos /mnt", 273 "mkfs.vfat -n BOOT /dev/vda1", 274 "mkdir -p /mnt/boot", 275 "mount LABEL=BOOT /mnt/boot", 276 ); 277 ''; 278 bootLoader = "systemd-boot"; 279 }; 280 281 # Same as the previous, but now with a separate /boot partition. 282 separateBoot = makeInstallerTest "separateBoot" 283 { createPartitions = 284 '' 285 $machine->succeed( 286 "parted /dev/vda mklabel msdos", 287 "parted /dev/vda -- mkpart primary ext2 1M 50MB", # /boot 288 "parted /dev/vda -- mkpart primary linux-swap 50MB 1024M", 289 "parted /dev/vda -- mkpart primary ext2 1024M -1s", # / 290 "udevadm settle", 291 "mkswap /dev/vda2 -L swap", 292 "swapon -L swap", 293 "mkfs.ext3 -L nixos /dev/vda3", 294 "mount LABEL=nixos /mnt", 295 "mkfs.ext3 -L boot /dev/vda1", 296 "mkdir -p /mnt/boot", 297 "mount LABEL=boot /mnt/boot", 298 ); 299 ''; 300 }; 301 302 # Same as the previous, but with fat32 /boot. 303 separateBootFat = makeInstallerTest "separateBootFat" 304 { createPartitions = 305 '' 306 $machine->succeed( 307 "parted /dev/vda mklabel msdos", 308 "parted /dev/vda -- mkpart primary ext2 1M 50MB", # /boot 309 "parted /dev/vda -- mkpart primary linux-swap 50MB 1024M", 310 "parted /dev/vda -- mkpart primary ext2 1024M -1s", # / 311 "udevadm settle", 312 "mkswap /dev/vda2 -L swap", 313 "swapon -L swap", 314 "mkfs.ext3 -L nixos /dev/vda3", 315 "mount LABEL=nixos /mnt", 316 "mkfs.vfat -n BOOT /dev/vda1", 317 "mkdir -p /mnt/boot", 318 "mount LABEL=BOOT /mnt/boot", 319 ); 320 ''; 321 }; 322 323 # Create two physical LVM partitions combined into one volume group 324 # that contains the logical swap and root partitions. 325 lvm = makeInstallerTest "lvm" 326 { createPartitions = 327 '' 328 $machine->succeed( 329 "parted /dev/vda mklabel msdos", 330 "parted /dev/vda -- mkpart primary 1M 2048M", # PV1 331 "parted /dev/vda -- set 1 lvm on", 332 "parted /dev/vda -- mkpart primary 2048M -1s", # PV2 333 "parted /dev/vda -- set 2 lvm on", 334 "udevadm settle", 335 "pvcreate /dev/vda1 /dev/vda2", 336 "vgcreate MyVolGroup /dev/vda1 /dev/vda2", 337 "lvcreate --size 1G --name swap MyVolGroup", 338 "lvcreate --size 2G --name nixos MyVolGroup", 339 "mkswap -f /dev/MyVolGroup/swap -L swap", 340 "swapon -L swap", 341 "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", 342 "mount LABEL=nixos /mnt", 343 ); 344 ''; 345 }; 346 347 # Boot off an encrypted root partition 348 luksroot = makeInstallerTest "luksroot" 349 { createPartitions = '' 350 $machine->succeed( 351 "parted /dev/vda mklabel msdos", 352 "parted /dev/vda -- mkpart primary ext2 1M 50MB", # /boot 353 "parted /dev/vda -- mkpart primary linux-swap 50M 1024M", 354 "parted /dev/vda -- mkpart primary 1024M -1s", # LUKS 355 "udevadm settle", 356 "mkswap /dev/vda2 -L swap", 357 "swapon -L swap", 358 "modprobe dm_mod dm_crypt", 359 "echo -n supersecret | cryptsetup luksFormat -q /dev/vda3 -", 360 "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda3 cryptroot", 361 "mkfs.ext3 -L nixos /dev/mapper/cryptroot", 362 "mount LABEL=nixos /mnt", 363 "mkfs.ext3 -L boot /dev/vda1", 364 "mkdir -p /mnt/boot", 365 "mount LABEL=boot /mnt/boot", 366 ); 367 ''; 368 extraConfig = '' 369 boot.kernelParams = lib.mkAfter [ "console=tty0" ]; 370 ''; 371 enableOCR = true; 372 preBootCommands = '' 373 $machine->start; 374 $machine->waitForText(qr/Enter passphrase/); 375 $machine->sendChars("supersecret\n"); 376 ''; 377 }; 378 379 swraid = makeInstallerTest "swraid" 380 { createPartitions = 381 '' 382 $machine->succeed( 383 "parted /dev/vda --" 384 . " mklabel msdos" 385 . " mkpart primary ext2 1M 100MB" # /boot 386 . " mkpart extended 100M -1s" 387 . " mkpart logical 102M 1602M" # md0 (root), first device 388 . " mkpart logical 1603M 3103M" # md0 (root), second device 389 . " mkpart logical 3104M 3360M" # md1 (swap), first device 390 . " mkpart logical 3361M 3617M", # md1 (swap), second device 391 "udevadm settle", 392 "ls -l /dev/vda* >&2", 393 "cat /proc/partitions >&2", 394 "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda5 /dev/vda6", 395 "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda7 /dev/vda8", 396 "udevadm settle", 397 "mkswap -f /dev/md1 -L swap", 398 "swapon -L swap", 399 "mkfs.ext3 -L nixos /dev/md0", 400 "mount LABEL=nixos /mnt", 401 "mkfs.ext3 -L boot /dev/vda1", 402 "mkdir /mnt/boot", 403 "mount LABEL=boot /mnt/boot", 404 "udevadm settle", 405 ); 406 ''; 407 preBootCommands = '' 408 $machine->start; 409 $machine->fail("dmesg | grep 'immediate safe mode'"); 410 ''; 411 }; 412 413 # Test a basic install using GRUB 1. 414 grub1 = makeInstallerTest "grub1" 415 { createPartitions = 416 '' 417 $machine->succeed( 418 "parted /dev/sda mklabel msdos", 419 "parted /dev/sda -- mkpart primary linux-swap 1M 1024M", 420 "parted /dev/sda -- mkpart primary ext2 1024M -1s", 421 "udevadm settle", 422 "mkswap /dev/sda1 -L swap", 423 "swapon -L swap", 424 "mkfs.ext3 -L nixos /dev/sda2", 425 "mount LABEL=nixos /mnt", 426 ); 427 ''; 428 grubVersion = 1; 429 grubDevice = "/dev/sda"; 430 }; 431 432 # Test using labels to identify volumes in grub 433 simpleLabels = makeInstallerTest "simpleLabels" { 434 createPartitions = '' 435 $machine->succeed( 436 "sgdisk -Z /dev/vda", 437 "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", 438 "mkswap /dev/vda2 -L swap", 439 "swapon -L swap", 440 "mkfs.ext4 -L root /dev/vda3", 441 "mount LABEL=root /mnt", 442 ); 443 ''; 444 grubIdentifier = "label"; 445 }; 446 447 # Test using the provided disk name within grub 448 # TODO: Fix udev so the symlinks are unneeded in /dev/disks 449 simpleProvided = makeInstallerTest "simpleProvided" { 450 createPartitions = '' 451 my $UUID = "\$(blkid -s UUID -o value /dev/vda2)"; 452 $machine->succeed( 453 "sgdisk -Z /dev/vda", 454 "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 -t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda", 455 "mkswap /dev/vda3 -L swap", 456 "swapon -L swap", 457 "mkfs.ext4 -L boot /dev/vda2", 458 "mkfs.ext4 -L root /dev/vda4", 459 ); 460 $machine->execute("ln -s ../../vda2 /dev/disk/by-uuid/$UUID"); 461 $machine->execute("ln -s ../../vda4 /dev/disk/by-label/root"); 462 $machine->succeed( 463 "mount /dev/disk/by-label/root /mnt", 464 "mkdir /mnt/boot", 465 "mount /dev/disk/by-uuid/$UUID /mnt/boot" 466 ); 467 ''; 468 grubIdentifier = "provided"; 469 }; 470 471 # Simple btrfs grub testing 472 btrfsSimple = makeInstallerTest "btrfsSimple" { 473 createPartitions = '' 474 $machine->succeed( 475 "sgdisk -Z /dev/vda", 476 "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", 477 "mkswap /dev/vda2 -L swap", 478 "swapon -L swap", 479 "mkfs.btrfs -L root /dev/vda3", 480 "mount LABEL=root /mnt", 481 ); 482 ''; 483 }; 484 485 # Test to see if we can detect /boot and /nix on subvolumes 486 btrfsSubvols = makeInstallerTest "btrfsSubvols" { 487 createPartitions = '' 488 $machine->succeed( 489 "sgdisk -Z /dev/vda", 490 "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", 491 "mkswap /dev/vda2 -L swap", 492 "swapon -L swap", 493 "mkfs.btrfs -L root /dev/vda3", 494 "btrfs device scan", 495 "mount LABEL=root /mnt", 496 "btrfs subvol create /mnt/boot", 497 "btrfs subvol create /mnt/nixos", 498 "btrfs subvol create /mnt/nixos/default", 499 "umount /mnt", 500 "mount -o defaults,subvol=nixos/default LABEL=root /mnt", 501 "mkdir /mnt/boot", 502 "mount -o defaults,subvol=boot LABEL=root /mnt/boot", 503 ); 504 ''; 505 }; 506 507 # Test to see if we can detect default and aux subvolumes correctly 508 btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" { 509 createPartitions = '' 510 $machine->succeed( 511 "sgdisk -Z /dev/vda", 512 "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", 513 "mkswap /dev/vda2 -L swap", 514 "swapon -L swap", 515 "mkfs.btrfs -L root /dev/vda3", 516 "btrfs device scan", 517 "mount LABEL=root /mnt", 518 "btrfs subvol create /mnt/badpath", 519 "btrfs subvol create /mnt/badpath/boot", 520 "btrfs subvol create /mnt/nixos", 521 "btrfs subvol set-default \$(btrfs subvol list /mnt | grep 'nixos' | awk '{print \$2}') /mnt", 522 "umount /mnt", 523 "mount -o defaults LABEL=root /mnt", 524 "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism is actually looking up subvolumes 525 "mkdir /mnt/boot", 526 "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", 527 ); 528 ''; 529 }; 530 531}