nixos/qemu-vm: allow custom partitions and filesystems in VM

Potential use cases for disabling `useDefaultFilesystems` include:

  - Testing with uncommon filesystem layouts
  - Testing scenarios where swapping occurs
  - Testing with LUKS-encrypted disks

Closes #177963
This commit is contained in:
T0astBread 2022-06-22 04:03:43 +02:00
parent 057fb30998
commit 87cd533a32
No known key found for this signature in database
GPG Key ID: B1E4DE455BF9767F

View File

@ -684,6 +684,21 @@ in
''; '';
}; };
virtualisation.useDefaultFilesystems =
mkOption {
type = types.bool;
default = true;
description =
''
If enabled, the boot disk of the virtual machine will be
formatted and mounted with the default filesystems for
testing. Swap devices and LUKS will be disabled.
If disabled, a root filesystem has to be specified and
formatted (for example in the initial ramdisk).
'';
};
virtualisation.efiVars = virtualisation.efiVars =
mkOption { mkOption {
type = types.str; type = types.str;
@ -754,13 +769,13 @@ in
); );
boot.loader.grub.gfxmodeBios = with cfg.resolution; "${toString x}x${toString y}"; boot.loader.grub.gfxmodeBios = with cfg.resolution; "${toString x}x${toString y}";
boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) boot.initrd.extraUtilsCommands = lib.mkIf (cfg.useDefaultFilesystems && !config.boot.initrd.systemd.enable)
'' ''
# We need mke2fs in the initrd. # We need mke2fs in the initrd.
copy_bin_and_libs ${pkgs.e2fsprogs}/bin/mke2fs copy_bin_and_libs ${pkgs.e2fsprogs}/bin/mke2fs
''; '';
boot.initrd.postDeviceCommands = lib.mkIf (!config.boot.initrd.systemd.enable) boot.initrd.postDeviceCommands = lib.mkIf (cfg.useDefaultFilesystems && !config.boot.initrd.systemd.enable)
'' ''
# If the disk image appears to be empty, run mke2fs to # If the disk image appears to be empty, run mke2fs to
# initialise. # initialise.
@ -930,38 +945,41 @@ in
}; };
in in
mkVMOverride (cfg.fileSystems // mkVMOverride (cfg.fileSystems //
{ optionalAttrs cfg.useDefaultFilesystems {
"/".device = cfg.bootDevice; "/".device = cfg.bootDevice;
"/".fsType = "ext4"; "/".fsType = "ext4";
"/".autoFormat = true; "/".autoFormat = true;
} //
"/tmp" = mkIf config.boot.tmpOnTmpfs optionalAttrs config.boot.tmpOnTmpfs {
{ device = "tmpfs"; "/tmp" = {
fsType = "tmpfs"; device = "tmpfs";
neededForBoot = true; fsType = "tmpfs";
# Sync with systemd's tmp.mount; neededForBoot = true;
options = [ "mode=1777" "strictatime" "nosuid" "nodev" "size=${toString config.boot.tmpOnTmpfsSize}" ]; # Sync with systemd's tmp.mount;
}; options = [ "mode=1777" "strictatime" "nosuid" "nodev" "size=${toString config.boot.tmpOnTmpfsSize}" ];
};
"/nix/${if cfg.writableStore then ".ro-store" else "store"}" = } //
mkIf cfg.useNixStoreImage optionalAttrs cfg.useNixStoreImage {
{ device = "${lookupDriveDeviceName "nix-store" cfg.qemu.drives}"; "/nix/${if cfg.writableStore then ".ro-store" else "store"}" = {
neededForBoot = true; device = "${lookupDriveDeviceName "nix-store" cfg.qemu.drives}";
options = [ "ro" ]; neededForBoot = true;
}; options = [ "ro" ];
};
"/nix/.rw-store" = mkIf (cfg.writableStore && cfg.writableStoreUseTmpfs) } //
{ fsType = "tmpfs"; optionalAttrs (cfg.writableStore && cfg.writableStoreUseTmpfs) {
options = [ "mode=0755" ]; "/nix/.rw-store" = {
neededForBoot = true; fsType = "tmpfs";
}; options = [ "mode=0755" ];
neededForBoot = true;
"/boot" = mkIf cfg.useBootLoader };
# see note [Disk layout with `useBootLoader`] } //
{ device = "${lookupDriveDeviceName "boot" cfg.qemu.drives}2"; # 2 for e.g. `vdb2`, as created in `bootDisk` optionalAttrs cfg.useBootLoader {
fsType = "vfat"; # see note [Disk layout with `useBootLoader`]
noCheck = true; # fsck fails on a r/o filesystem "/boot" = {
}; device = "${lookupDriveDeviceName "boot" cfg.qemu.drives}2"; # 2 for e.g. `vdb2`, as created in `bootDisk`
fsType = "vfat";
noCheck = true; # fsck fails on a r/o filesystem
};
} // lib.mapAttrs' mkSharedDir cfg.sharedDirectories); } // lib.mapAttrs' mkSharedDir cfg.sharedDirectories);
boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) { boot.initrd.systemd = lib.mkIf (config.boot.initrd.systemd.enable && cfg.writableStore) {
@ -986,8 +1004,8 @@ in
}; };
}; };
swapDevices = mkVMOverride [ ]; swapDevices = (if cfg.useDefaultFilesystems then mkVMOverride else mkDefault) [ ];
boot.initrd.luks.devices = mkVMOverride {}; boot.initrd.luks.devices = (if cfg.useDefaultFilesystems then mkVMOverride else mkDefault) {};
# Don't run ntpd in the guest. It should get the correct time from KVM. # Don't run ntpd in the guest. It should get the correct time from KVM.
services.timesyncd.enable = false; services.timesyncd.enable = false;