at master 3.8 kB view raw
1# Tests building and running a GUID Partition Table (GPT) appliance image. 2# "Appliance" here means that the image does not contain the normal NixOS 3# infrastructure of a system profile and cannot be re-built via 4# `nixos-rebuild`. 5 6{ lib, ... }: 7 8let 9 rootPartitionLabel = "root"; 10 11 imageId = "nixos-appliance"; 12 imageVersion = "1-rc1"; 13in 14{ 15 name = "appliance-gpt-image"; 16 17 meta.maintainers = with lib.maintainers; [ nikstur ]; 18 19 nodes.machine = 20 { 21 config, 22 lib, 23 pkgs, 24 ... 25 }: 26 { 27 28 imports = [ ../modules/image/repart.nix ]; 29 30 virtualisation.directBoot.enable = false; 31 virtualisation.mountHostNixStore = false; 32 virtualisation.useEFIBoot = true; 33 34 # Disable boot loaders because we install one "manually". 35 # TODO(raitobezarius): revisit this when #244907 lands 36 boot.loader.grub.enable = false; 37 38 system.image.id = imageId; 39 system.image.version = imageVersion; 40 41 virtualisation.fileSystems = lib.mkForce { 42 "/" = { 43 device = "/dev/disk/by-partlabel/${rootPartitionLabel}"; 44 fsType = "ext4"; 45 }; 46 }; 47 48 image.repart = { 49 name = "appliance-gpt-image"; 50 # OVMF does not work with the default repart sector size of 4096 51 sectorSize = 512; 52 partitions = { 53 "esp" = { 54 contents = 55 let 56 efiArch = config.nixpkgs.hostPlatform.efiArch; 57 in 58 { 59 "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source = 60 "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi"; 61 62 "/EFI/Linux/${config.system.boot.loader.ukiFile}".source = 63 "${config.system.build.uki}/${config.system.boot.loader.ukiFile}"; 64 }; 65 repartConfig = { 66 Type = "esp"; 67 Format = "vfat"; 68 # Minimize = "guess" seems to not work very well for vfat 69 # partitions. It's better to set a sensible default instead. The 70 # aarch64 kernel seems to generally be a little bigger than the 71 # x86_64 kernel. To stay on the safe side, leave some more slack 72 # for every platform other than x86_64. 73 SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M"; 74 }; 75 }; 76 "swap" = { 77 repartConfig = { 78 Type = "swap"; 79 Format = "swap"; 80 SizeMinBytes = "10M"; 81 SizeMaxBytes = "10M"; 82 }; 83 }; 84 "root" = { 85 storePaths = [ config.system.build.toplevel ]; 86 repartConfig = { 87 Type = "root"; 88 Format = config.fileSystems."/".fsType; 89 Label = rootPartitionLabel; 90 Minimize = "guess"; 91 }; 92 }; 93 }; 94 }; 95 }; 96 97 testScript = 98 { nodes, ... }: 99 '' 100 import os 101 import subprocess 102 import tempfile 103 104 tmp_disk_image = tempfile.NamedTemporaryFile() 105 106 subprocess.run([ 107 "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", 108 "create", 109 "-f", 110 "qcow2", 111 "-b", 112 "${nodes.machine.system.build.image}/${nodes.machine.image.repart.imageFile}", 113 "-F", 114 "raw", 115 tmp_disk_image.name, 116 ]) 117 118 # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image. 119 os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name 120 121 os_release = machine.succeed("cat /etc/os-release") 122 assert 'IMAGE_ID="${imageId}"' in os_release 123 assert 'IMAGE_VERSION="${imageVersion}"' in os_release 124 125 bootctl_status = machine.succeed("bootctl status") 126 assert "Boot Loader Specification Type #2 (.efi)" in bootctl_status 127 ''; 128}