Release NixOS 23.11
[NixPkgs.git] / nixos / tests / appliance-repart-image.nix
blob3f256db8462144883cd5865448d93e4c00f97c15
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`.
6 { lib, ... }:
8 let
9   rootPartitionLabel = "root";
11   bootLoaderConfigPath = "/loader/entries/nixos.conf";
12   kernelPath = "/EFI/nixos/kernel.efi";
13   initrdPath = "/EFI/nixos/initrd.efi";
16   name = "appliance-gpt-image";
18   meta.maintainers = with lib.maintainers; [ nikstur ];
20   nodes.machine = { config, lib, pkgs, ... }: {
22     imports = [ ../modules/image/repart.nix ];
24     virtualisation.directBoot.enable = false;
25     virtualisation.mountHostNixStore = false;
26     virtualisation.useEFIBoot = true;
28     # Disable boot loaders because we install one "manually".
29     # TODO(raitobezarius): revisit this when #244907 lands
30     boot.loader.grub.enable = false;
32     virtualisation.fileSystems = lib.mkForce {
33       "/" = {
34         device = "/dev/disk/by-partlabel/${rootPartitionLabel}";
35         fsType = "ext4";
36       };
37     };
39     image.repart = {
40       name = "appliance-gpt-image";
41       partitions = {
42         "esp" = {
43           contents =
44             let
45               efiArch = config.nixpkgs.hostPlatform.efiArch;
46             in
47             {
48               "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
49                 "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
51               # TODO: create an abstraction for Boot Loader Specification (BLS) entries.
52               "${bootLoaderConfigPath}".source = pkgs.writeText "nixos.conf" ''
53                 title NixOS
54                 linux ${kernelPath}
55                 initrd ${initrdPath}
56                 options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
57               '';
59               "${kernelPath}".source =
60                 "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";
62               "${initrdPath}".source =
63                 "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
64             };
65           repartConfig = {
66             Type = "esp";
67             Format = "vfat";
68             # Minimize = "guess" seems to not work very vell for vfat
69             # partitons. 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         "root" = {
77           storePaths = [ config.system.build.toplevel ];
78           repartConfig = {
79             Type = "root";
80             Format = config.fileSystems."/".fsType;
81             Label = rootPartitionLabel;
82             Minimize = "guess";
83           };
84         };
85       };
86     };
87   };
89   testScript = { nodes, ... }: ''
90     import os
91     import subprocess
92     import tempfile
94     tmp_disk_image = tempfile.NamedTemporaryFile()
96     subprocess.run([
97       "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img",
98       "create",
99       "-f",
100       "qcow2",
101       "-b",
102       "${nodes.machine.system.build.image}/image.raw",
103       "-F",
104       "raw",
105       tmp_disk_image.name,
106     ])
108     # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image.
109     os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name
111     bootctl_status = machine.succeed("bootctl status")
112     assert "${bootLoaderConfigPath}" in bootctl_status
113     assert "${kernelPath}" in bootctl_status
114     assert "${initrdPath}" in bootctl_status
115   '';