modules/virtualisation: add shared options, merge various diskSize options (#341058)

This commit is contained in:
Robert Hensing 2024-10-27 17:49:33 +01:00 committed by GitHub
commit 2ba15d4f55
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 1681 additions and 1282 deletions

View file

@ -192,3 +192,6 @@ ce21e97a1f20dee15da85c084f9d1148d84f853b
# percona: apply nixfmt # percona: apply nixfmt
8d14fa2886fec877690c6d28cfcdba4503dbbcea 8d14fa2886fec877690c6d28cfcdba4503dbbcea
# nixos/virtualisation: format image-related files
88b285c01d84de82c0b2b052fd28eaf6709c2d26

View file

@ -1,24 +1,47 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
inherit (lib) mkOption optionalString types versionAtLeast; inherit (lib)
mkOption
optionalString
types
versionAtLeast
;
inherit (lib.options) literalExpression; inherit (lib.options) literalExpression;
cfg = config.amazonImage; cfg = config.amazonImage;
amiBootMode = if config.ec2.efi then "uefi" else "legacy-bios"; amiBootMode = if config.ec2.efi then "uefi" else "legacy-bios";
in
in { {
imports = [
imports = [ ../../../modules/virtualisation/amazon-image.nix ]; ../../../modules/virtualisation/amazon-image.nix
../../../modules/virtualisation/disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"amazonImage"
"sizeMB"
];
to = [
"virtualisation"
"diskSize"
];
})
];
# Amazon recommends setting this to the highest possible value for a good EBS # Amazon recommends setting this to the highest possible value for a good EBS
# experience, which prior to 4.15 was 255. # experience, which prior to 4.15 was 255.
# https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html#timeout-nvme-ebs-volumes # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nvme-ebs-volumes.html#timeout-nvme-ebs-volumes
config.boot.kernelParams = config.boot.kernelParams =
let timeout = let
if versionAtLeast config.boot.kernelPackages.kernel.version "4.15" timeout =
then "4294967295" if versionAtLeast config.boot.kernelPackages.kernel.version "4.15" then "4294967295" else "255";
else "255"; in
in [ "nvme_core.io_timeout=${timeout}" ]; [ "nvme_core.io_timeout=${timeout}" ];
options.amazonImage = { options.amazonImage = {
name = mkOption { name = mkOption {
@ -41,23 +64,25 @@ in {
''; '';
}; };
sizeMB = mkOption {
type = with types; either (enum [ "auto" ]) int;
default = 3072;
example = 8192;
description = "The size in MB of the image";
};
format = mkOption { format = mkOption {
type = types.enum [ "raw" "qcow2" "vpc" ]; type = types.enum [
"raw"
"qcow2"
"vpc"
];
default = "vpc"; default = "vpc";
description = "The image format to output"; description = "The image format to output";
}; };
}; };
config.system.build.amazonImage = let # Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
configFile = pkgs.writeText "configuration.nix" # to avoid breaking existing configs using that.
'' config.virtualisation.diskSize = lib.mkOverride 1490 (3 * 1024);
config.virtualisation.diskSizeAutoSupported = !config.ec2.zfs.enable;
config.system.build.amazonImage =
let
configFile = pkgs.writeText "configuration.nix" ''
{ modulesPath, ... }: { { modulesPath, ... }: {
imports = [ "''${modulesPath}/virtualisation/amazon-image.nix" ]; imports = [ "''${modulesPath}/virtualisation/amazon-image.nix" ];
${optionalString config.ec2.efi '' ${optionalString config.ec2.efi ''
@ -71,14 +96,19 @@ in {
''; '';
zfsBuilder = import ../../../lib/make-multi-disk-zfs-image.nix { zfsBuilder = import ../../../lib/make-multi-disk-zfs-image.nix {
inherit lib config configFile pkgs; inherit
lib
config
configFile
pkgs
;
inherit (cfg) contents format name; inherit (cfg) contents format name;
includeChannel = true; includeChannel = true;
bootSize = 1000; # 1G is the minimum EBS volume bootSize = 1000; # 1G is the minimum EBS volume
rootSize = cfg.sizeMB; rootSize = config.virtualisation.diskSize;
rootPoolProperties = { rootPoolProperties = {
ashift = 12; ashift = 12;
autoexpand = "on"; autoexpand = "on";
@ -119,14 +149,19 @@ in {
}; };
extBuilder = import ../../../lib/make-disk-image.nix { extBuilder = import ../../../lib/make-disk-image.nix {
inherit lib config configFile pkgs; inherit
lib
config
configFile
pkgs
;
inherit (cfg) contents format name; inherit (cfg) contents format name;
fsType = "ext4"; fsType = "ext4";
partitionTableType = if config.ec2.efi then "efi" else "legacy+gpt"; partitionTableType = if config.ec2.efi then "efi" else "legacy+gpt";
diskSize = cfg.sizeMB; inherit (config.virtualisation) diskSize;
postVM = '' postVM = ''
extension=''${diskImage##*.} extension=''${diskImage##*.}
@ -154,7 +189,8 @@ in {
' > $out/nix-support/image-info.json ' > $out/nix-support/image-info.json
''; '';
}; };
in if config.ec2.zfs.enable then zfsBuilder else extBuilder; in
if config.ec2.zfs.enable then zfsBuilder else extBuilder;
meta.maintainers = with lib.maintainers; [ arianvp ]; meta.maintainers = with lib.maintainers; [ arianvp ];
} }

View file

@ -1,6 +1,11 @@
# nix-build '<nixpkgs/nixos>' -A config.system.build.openstackImage --arg configuration "{ imports = [ ./nixos/maintainers/scripts/openstack/openstack-image.nix ]; }" # nix-build '<nixpkgs/nixos>' -A config.system.build.openstackImage --arg configuration "{ imports = [ ./nixos/maintainers/scripts/openstack/openstack-image.nix ]; }"
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
inherit (lib) mkOption types; inherit (lib) mkOption types;
copyChannel = true; copyChannel = true;
@ -10,9 +15,20 @@ in
{ {
imports = [ imports = [
../../../modules/virtualisation/openstack-config.nix ../../../modules/virtualisation/openstack-config.nix
../../../modules/virtualisation/disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"openstackImage"
"sizeMB"
];
to = [
"virtualisation"
"diskSize"
];
})
] ++ (lib.optional copyChannel ../../../modules/installer/cd-dvd/channel.nix); ] ++ (lib.optional copyChannel ../../../modules/installer/cd-dvd/channel.nix);
options.openstackImage = { options.openstackImage = {
name = mkOption { name = mkOption {
type = types.str; type = types.str;
@ -22,18 +38,15 @@ in
ramMB = mkOption { ramMB = mkOption {
type = types.int; type = types.int;
default = 1024; default = (3 * 1024);
description = "RAM allocation for build VM"; description = "RAM allocation for build VM";
}; };
sizeMB = mkOption {
type = types.int;
default = 8192;
description = "The size in MB of the image";
};
format = mkOption { format = mkOption {
type = types.enum [ "raw" "qcow2" ]; type = types.enum [
"raw"
"qcow2"
];
default = "qcow2"; default = "qcow2";
description = "The image format to output"; description = "The image format to output";
}; };
@ -54,13 +67,17 @@ in
}; };
}; };
# Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
# to avoid breaking existing configs using that.
virtualisation.diskSize = lib.mkOverride 1490 (8 * 1024);
virtualisation.diskSizeAutoSupported = false;
system.build.openstackImage = import ../../../lib/make-single-disk-zfs-image.nix { system.build.openstackImage = import ../../../lib/make-single-disk-zfs-image.nix {
inherit lib config; inherit lib config;
inherit (cfg) contents format name; inherit (cfg) contents format name;
pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package pkgs = import ../../../.. { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
configFile = pkgs.writeText "configuration.nix" configFile = pkgs.writeText "configuration.nix" ''
''
{ modulesPath, ... }: { { modulesPath, ... }: {
imports = [ "''${modulesPath}/virtualisation/openstack-config.nix" ]; imports = [ "''${modulesPath}/virtualisation/openstack-config.nix" ];
openstack.zfs.enable = true; openstack.zfs.enable = true;
@ -71,7 +88,7 @@ in
bootSize = 1000; bootSize = 1000;
memSize = cfg.ramMB; memSize = cfg.ramMB;
rootSize = cfg.sizeMB; rootSize = config.virtualisation.diskSize;
rootPoolProperties = { rootPoolProperties = {
ashift = 12; ashift = 12;
autoexpand = "on"; autoexpand = "on";

View file

@ -1,22 +1,33 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
let let
cfg = config.virtualisation.azureImage; cfg = config.virtualisation.azureImage;
in in
{ {
imports = [ ./azure-common.nix ]; imports = [
./azure-common.nix
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"virtualisation"
"azureImage"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options.virtualisation.azureImage = { options.virtualisation.azureImage = {
diskSize = mkOption {
type = with types; either (enum [ "auto" ]) int;
default = "auto";
example = 2048;
description = ''
Size of disk image. Unit is MB.
'';
};
bootSize = mkOption { bootSize = mkOption {
type = types.int; type = types.int;
default = 256; default = 256;
@ -35,7 +46,12 @@ in
}; };
vmGeneration = mkOption { vmGeneration = mkOption {
type = with types; enum [ "v1" "v2" ]; type =
with types;
enum [
"v1"
"v2"
];
default = "v1"; default = "v1";
description = '' description = ''
VM Generation to use. VM Generation to use.
@ -57,7 +73,8 @@ in
bootSize = "${toString cfg.bootSize}M"; bootSize = "${toString cfg.bootSize}M";
partitionTableType = if cfg.vmGeneration == "v2" then "efi" else "legacy"; partitionTableType = if cfg.vmGeneration == "v2" then "efi" else "legacy";
inherit (cfg) diskSize contents; inherit (cfg) contents;
inherit (config.virtualisation) diskSize;
inherit config lib pkgs; inherit config lib pkgs;
}; };
}; };

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
let let
@ -6,18 +11,24 @@ let
in in
{ {
imports = [ ./digital-ocean-config.nix ]; imports = [
./digital-ocean-config.nix
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"virtualisation"
"digitalOceanImage"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options = { options = {
virtualisation.digitalOceanImage.diskSize = mkOption {
type = with types; either (enum [ "auto" ]) int;
default = "auto";
example = 4096;
description = ''
Size of disk image. Unit is MB.
'';
};
virtualisation.digitalOceanImage.configFile = mkOption { virtualisation.digitalOceanImage.configFile = mkOption {
type = with types; nullOr path; type = with types; nullOr path;
default = null; default = null;
@ -31,7 +42,10 @@ in
}; };
virtualisation.digitalOceanImage.compressionMethod = mkOption { virtualisation.digitalOceanImage.compressionMethod = mkOption {
type = types.enum [ "gzip" "bzip2" ]; type = types.enum [
"gzip"
"bzip2"
];
default = "gzip"; default = "gzip";
example = "bzip2"; example = "bzip2";
description = '' description = ''
@ -44,27 +58,35 @@ in
#### implementation #### implementation
config = { config = {
system.build.digitalOceanImage = import ../../lib/make-disk-image.nix { system.build.digitalOceanImage = import ../../lib/make-disk-image.nix {
name = "digital-ocean-image"; name = "digital-ocean-image";
format = "qcow2"; format = "qcow2";
postVM = let postVM =
compress = { let
compress =
{
"gzip" = "${pkgs.gzip}/bin/gzip"; "gzip" = "${pkgs.gzip}/bin/gzip";
"bzip2" = "${pkgs.bzip2}/bin/bzip2"; "bzip2" = "${pkgs.bzip2}/bin/bzip2";
}.${cfg.compressionMethod}; }
in '' .${cfg.compressionMethod};
in
''
${compress} $diskImage ${compress} $diskImage
''; '';
configFile = if cfg.configFile == null configFile =
then config.virtualisation.digitalOcean.defaultConfigFile if cfg.configFile == null then
else cfg.configFile; config.virtualisation.digitalOcean.defaultConfigFile
inherit (cfg) diskSize; else
cfg.configFile;
inherit (config.virtualisation) diskSize;
inherit config lib pkgs; inherit config lib pkgs;
}; };
}; };
meta.maintainers = with maintainers; [ arianvp eamsden ]; meta.maintainers = with maintainers; [
arianvp
eamsden
];
} }

View file

@ -0,0 +1,38 @@
{ lib, config, ... }:
let
t = lib.types;
in
{
options = {
virtualisation.diskSizeAutoSupported = lib.mkOption {
type = t.bool;
default = true;
description = ''
Whether the current image builder or vm runner supports `virtualisation.diskSize = "auto".`
'';
internal = true;
};
virtualisation.diskSize = lib.mkOption {
type = t.either (t.enum [ "auto" ]) t.ints.positive;
default = if config.virtualisation.diskSizeAutoSupported then "auto" else 1024;
defaultText = "\"auto\" if diskSizeAutoSupported, else 1024";
description = ''
The disk size in megabytes of the virtual machine.
'';
};
};
config =
let
inherit (config.virtualisation) diskSize diskSizeAutoSupported;
in
{
assertions = [
{
assertion = diskSize != "auto" || diskSizeAutoSupported;
message = "Setting virtualisation.diskSize to `auto` is not supported by the current image build or vm runner; use an explicit size.";
}
];
};
}

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
let let
@ -14,18 +19,24 @@ let
in in
{ {
imports = [ ./google-compute-config.nix ]; imports = [
./google-compute-config.nix
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"virtualisation"
"googleComputeImage"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options = { options = {
virtualisation.googleComputeImage.diskSize = mkOption {
type = with types; either (enum [ "auto" ]) int;
default = "auto";
example = 1536;
description = ''
Size of disk image. Unit is MB.
'';
};
virtualisation.googleComputeImage.configFile = mkOption { virtualisation.googleComputeImage.configFile = mkOption {
type = with types; nullOr str; type = with types; nullOr str;
default = null; default = null;
@ -64,7 +75,13 @@ in
system.build.googleComputeImage = import ../../lib/make-disk-image.nix { system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
name = "google-compute-image"; name = "google-compute-image";
postVM = '' postVM = ''
PATH=$PATH:${with pkgs; lib.makeBinPath [ gnutar gzip ]} PATH=$PATH:${
with pkgs;
lib.makeBinPath [
gnutar
gzip
]
}
pushd $out pushd $out
mv $diskImage disk.raw mv $diskImage disk.raw
tar -Sc disk.raw | gzip -${toString cfg.compressionLevel} > \ tar -Sc disk.raw | gzip -${toString cfg.compressionLevel} > \
@ -75,7 +92,7 @@ in
format = "raw"; format = "raw";
configFile = if cfg.configFile == null then defaultConfigFile else cfg.configFile; configFile = if cfg.configFile == null then defaultConfigFile else cfg.configFile;
partitionTableType = if cfg.efi then "efi" else "legacy"; partitionTableType = if cfg.efi then "efi" else "legacy";
inherit (cfg) diskSize; inherit (config.virtualisation) diskSize;
inherit config lib pkgs; inherit config lib pkgs;
}; };

View file

@ -1,21 +1,34 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
let let
cfg = config.hyperv; cfg = config.hyperv;
in
{
imports = [
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"hyperv"
"baseImageSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
in {
options = { options = {
hyperv = { hyperv = {
baseImageSize = mkOption {
type = with types; either (enum [ "auto" ]) int;
default = "auto";
example = 2048;
description = ''
The size of the hyper-v base image in MiB.
'';
};
vmDerivationName = mkOption { vmDerivationName = mkOption {
type = types.str; type = types.str;
default = "nixos-hyperv-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}"; default = "nixos-hyperv-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}";
@ -34,6 +47,10 @@ in {
}; };
config = { config = {
# Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
# to avoid breaking existing configs using that.
virtualisation.diskSize = lib.mkOverride 1490 (4 * 1024);
system.build.hypervImage = import ../../lib/make-disk-image.nix { system.build.hypervImage = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName; name = cfg.vmDerivationName;
postVM = '' postVM = ''
@ -41,7 +58,7 @@ in {
rm $diskImage rm $diskImage
''; '';
format = "raw"; format = "raw";
diskSize = cfg.baseImageSize; inherit (config.virtualisation) diskSize;
partitionTableType = "efi"; partitionTableType = "efi";
inherit config lib pkgs; inherit config lib pkgs;
}; };

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
let let
@ -12,17 +17,24 @@ let
''; '';
in in
{ {
imports = [ ./linode-config.nix ]; imports = [
./linode-config.nix
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"virtualisation"
"linodeImage"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options = { options = {
virtualisation.linodeImage.diskSize = mkOption {
type = with types; either (enum (singleton "auto")) ints.positive;
default = "auto";
example = 1536;
description = ''
Size of disk image in MB.
'';
};
virtualisation.linodeImage.configFile = mkOption { virtualisation.linodeImage.configFile = mkOption {
type = with types; nullOr str; type = with types; nullOr str;
@ -57,7 +69,7 @@ in
format = "raw"; format = "raw";
partitionTableType = "none"; partitionTableType = "none";
configFile = if cfg.configFile == null then defaultConfigFile else cfg.configFile; configFile = if cfg.configFile == null then defaultConfigFile else cfg.configFile;
inherit (cfg) diskSize; inherit (config.virtualisation) diskSize;
inherit config lib pkgs; inherit config lib pkgs;
}; };
}; };

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
cfg = config.oci; cfg = config.oci;
@ -7,9 +12,14 @@ in
imports = [ ./oci-common.nix ]; imports = [ ./oci-common.nix ];
config = { config = {
# Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
# to avoid breaking existing configs using that.
virtualisation.diskSize = lib.mkOverride 1490 (8 * 1024);
virtualisation.diskSizeAutoSupported = false;
system.build.OCIImage = import ../../lib/make-disk-image.nix { system.build.OCIImage = import ../../lib/make-disk-image.nix {
inherit config lib pkgs; inherit config lib pkgs;
inherit (cfg) diskSize; inherit (config.virtualisation) diskSize;
name = "oci-image"; name = "oci-image";
configFile = ./oci-config-user.nix; configFile = ./oci-config-user.nix;
format = "qcow2"; format = "qcow2";
@ -25,7 +35,10 @@ in
after = [ "network-online.target" ]; after = [ "network-online.target" ];
wants = [ "network-online.target" ]; wants = [ "network-online.target" ];
path = [ pkgs.coreutils pkgs.curl ]; path = [
pkgs.coreutils
pkgs.curl
];
script = '' script = ''
mkdir -m 0700 -p /root/.ssh mkdir -m 0700 -p /root/.ssh
if [ -f /root/.ssh/authorized_keys ]; then if [ -f /root/.ssh/authorized_keys ]; then

View file

@ -1,5 +1,23 @@
{ config, lib, pkgs, ... }:
{ {
lib,
...
}:
{
imports = [
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"oci"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options = { options = {
oci = { oci = {
efi = lib.mkOption { efi = lib.mkOption {
@ -9,12 +27,6 @@
Whether the OCI instance is using EFI. Whether the OCI instance is using EFI.
''; '';
}; };
diskSize = lib.mkOption {
type = lib.types.int;
default = 8192;
description = "Size of the disk image created in MB.";
example = "diskSize = 12 * 1024; # 12GiB";
};
}; };
}; };
} }

View file

@ -1,8 +1,28 @@
{ config, pkgs, lib, ... }: {
config,
pkgs,
lib,
...
}:
with lib; with lib;
{ {
imports = [
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"proxmox"
"qemuConf"
"diskSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options.proxmox = { options.proxmox = {
qemuConf = { qemuConf = {
# essential configs # essential configs
@ -54,7 +74,10 @@ with lib;
''; '';
}; };
bios = mkOption { bios = mkOption {
type = types.enum [ "seabios" "ovmf" ]; type = types.enum [
"seabios"
"ovmf"
];
default = "seabios"; default = "seabios";
description = '' description = ''
Select BIOS implementation (seabios = Legacy BIOS, ovmf = UEFI). Select BIOS implementation (seabios = Legacy BIOS, ovmf = UEFI).
@ -87,16 +110,6 @@ with lib;
either "efi" or "hybrid". either "efi" or "hybrid".
''; '';
}; };
diskSize = mkOption {
type = types.str;
default = "auto";
example = "20480";
description = ''
The size of the disk, in megabytes.
if "auto" size is calculated based on the contents copied to it and
additionalSpace is taken into account.
'';
};
net0 = mkOption { net0 = mkOption {
type = types.commas; type = types.commas;
default = "virtio=00:00:00:00:00:00,bridge=vmbr0,firewall=1"; default = "virtio=00:00:00:00:00:00,bridge=vmbr0,firewall=1";
@ -124,7 +137,12 @@ with lib;
}; };
}; };
qemuExtraConf = mkOption { qemuExtraConf = mkOption {
type = with types; attrsOf (oneOf [ str int ]); type =
with types;
attrsOf (oneOf [
str
int
]);
default = { }; default = { };
example = literalExpression '' example = literalExpression ''
{ {
@ -137,7 +155,12 @@ with lib;
''; '';
}; };
partitionTableType = mkOption { partitionTableType = mkOption {
type = types.enum [ "efi" "hybrid" "legacy" "legacy+gpt" ]; type = types.enum [
"efi"
"hybrid"
"legacy"
"legacy+gpt"
];
description = '' description = ''
Partition table type to use. See make-disk-image.nix partitionTableType for details. Partition table type to use. See make-disk-image.nix partitionTableType for details.
Defaults to 'legacy' for 'proxmox.qemuConf.bios="seabios"' (default), other bios values defaults to 'efi'. Defaults to 'legacy' for 'proxmox.qemuConf.bios="seabios"' (default), other bios values defaults to 'efi'.
@ -185,23 +208,30 @@ with lib;
}; };
}; };
config = let config =
let
cfg = config.proxmox; cfg = config.proxmox;
cfgLine = name: value: '' cfgLine = name: value: ''
${name}: ${builtins.toString value} ${name}: ${builtins.toString value}
''; '';
virtio0Storage = builtins.head (builtins.split ":" cfg.qemuConf.virtio0); virtio0Storage = builtins.head (builtins.split ":" cfg.qemuConf.virtio0);
cfgFile = fileName: properties: pkgs.writeTextDir fileName '' cfgFile =
fileName: properties:
pkgs.writeTextDir fileName ''
# generated by NixOS # generated by NixOS
${lib.concatStrings (lib.mapAttrsToList cfgLine properties)} ${lib.concatStrings (lib.mapAttrsToList cfgLine properties)}
#qmdump#map:virtio0:drive-virtio0:${virtio0Storage}:raw: #qmdump#map:virtio0:drive-virtio0:${virtio0Storage}:raw:
''; '';
inherit (cfg) partitionTableType; inherit (cfg) partitionTableType;
supportEfi = partitionTableType == "efi" || partitionTableType == "hybrid"; supportEfi = partitionTableType == "efi" || partitionTableType == "hybrid";
supportBios = partitionTableType == "legacy" || partitionTableType == "hybrid" || partitionTableType == "legacy+gpt"; supportBios =
partitionTableType == "legacy"
|| partitionTableType == "hybrid"
|| partitionTableType == "legacy+gpt";
hasBootPartition = partitionTableType == "efi" || partitionTableType == "hybrid"; hasBootPartition = partitionTableType == "efi" || partitionTableType == "hybrid";
hasNoFsPartition = partitionTableType == "hybrid" || partitionTableType == "legacy+gpt"; hasNoFsPartition = partitionTableType == "hybrid" || partitionTableType == "legacy+gpt";
in { in
{
assertions = [ assertions = [
{ {
assertion = config.boot.loader.systemd-boot.enable -> config.proxmox.qemuConf.bios == "ovmf"; assertion = config.boot.loader.systemd-boot.enable -> config.proxmox.qemuConf.bios == "ovmf";
@ -223,9 +253,11 @@ with lib;
system.build.VMA = import ../../lib/make-disk-image.nix { system.build.VMA = import ../../lib/make-disk-image.nix {
name = "proxmox-${cfg.filenameSuffix}"; name = "proxmox-${cfg.filenameSuffix}";
inherit (cfg) partitionTableType; inherit (cfg) partitionTableType;
postVM = let postVM =
let
# Build qemu with PVE's patch that adds support for the VMA format # Build qemu with PVE's patch that adds support for the VMA format
vma = (pkgs.qemu_kvm.override { vma =
(pkgs.qemu_kvm.override {
alsaSupport = false; alsaSupport = false;
pulseSupport = false; pulseSupport = false;
sdlSupport = false; sdlSupport = false;
@ -240,7 +272,8 @@ with lib;
numaSupport = false; numaSupport = false;
seccompSupport = false; seccompSupport = false;
guestAgentSupport = false; guestAgentSupport = false;
}).overrideAttrs ( super: rec { }).overrideAttrs
(super: rec {
# Check https://github.com/proxmox/pve-qemu/tree/master for the version # Check https://github.com/proxmox/pve-qemu/tree/master for the version
# of qemu and patch to use # of qemu and patch to use
version = "9.0.0"; version = "9.0.0";
@ -250,12 +283,14 @@ with lib;
}; };
patches = [ patches = [
# Proxmox' VMA tool is published as a particular patch upon QEMU # Proxmox' VMA tool is published as a particular patch upon QEMU
"${pkgs.fetchFromGitHub { "${
pkgs.fetchFromGitHub {
owner = "proxmox"; owner = "proxmox";
repo = "pve-qemu"; repo = "pve-qemu";
rev = "14afbdd55f04d250bd679ca1ad55d3f47cd9d4c8"; rev = "14afbdd55f04d250bd679ca1ad55d3f47cd9d4c8";
hash = "sha256-lSJQA5SHIHfxJvMLIID2drv2H43crTPMNIlIT37w9Nc="; hash = "sha256-lSJQA5SHIHfxJvMLIID2drv2H43crTPMNIlIT37w9Nc=";
}}/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch" }
}/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch"
]; ];
buildInputs = super.buildInputs ++ [ pkgs.libuuid ]; buildInputs = super.buildInputs ++ [ pkgs.libuuid ];
@ -265,7 +300,9 @@ with lib;
in in
'' ''
${vma}/bin/vma create "vzdump-qemu-${cfg.filenameSuffix}.vma" \ ${vma}/bin/vma create "vzdump-qemu-${cfg.filenameSuffix}.vma" \
-c ${cfgFile "qemu-server.conf" (cfg.qemuConf // cfg.qemuExtraConf)}/qemu-server.conf drive-virtio0=$diskImage -c ${
cfgFile "qemu-server.conf" (cfg.qemuConf // cfg.qemuExtraConf)
}/qemu-server.conf drive-virtio0=$diskImage
rm $diskImage rm $diskImage
${pkgs.zstd}/bin/zstd "vzdump-qemu-${cfg.filenameSuffix}.vma" ${pkgs.zstd}/bin/zstd "vzdump-qemu-${cfg.filenameSuffix}.vma"
mv "vzdump-qemu-${cfg.filenameSuffix}.vma.zst" $out/ mv "vzdump-qemu-${cfg.filenameSuffix}.vma.zst" $out/
@ -273,7 +310,8 @@ with lib;
mkdir -p $out/nix-support mkdir -p $out/nix-support
echo "file vma $out/vzdump-qemu-${cfg.filenameSuffix}.vma.zst" > $out/nix-support/hydra-build-products echo "file vma $out/vzdump-qemu-${cfg.filenameSuffix}.vma.zst" > $out/nix-support/hydra-build-products
''; '';
inherit (cfg.qemuConf) additionalSpace diskSize bootSize; inherit (cfg.qemuConf) additionalSpace bootSize;
inherit (config.virtualisation) diskSize;
format = "raw"; format = "raw";
inherit config lib pkgs; inherit config lib pkgs;
}; };
@ -282,19 +320,25 @@ with lib;
growPartition = true; growPartition = true;
kernelParams = [ "console=ttyS0" ]; kernelParams = [ "console=ttyS0" ];
loader.grub = { loader.grub = {
device = lib.mkDefault (if (hasNoFsPartition || supportBios) then device = lib.mkDefault (
if (hasNoFsPartition || supportBios) then
# Even if there is a separate no-fs partition ("/dev/disk/by-partlabel/no-fs" i.e. "/dev/vda2"), # Even if there is a separate no-fs partition ("/dev/disk/by-partlabel/no-fs" i.e. "/dev/vda2"),
# which will be used the bootloader, do not set it as loader.grub.device. # which will be used the bootloader, do not set it as loader.grub.device.
# GRUB installation fails, unless the whole disk is selected. # GRUB installation fails, unless the whole disk is selected.
"/dev/vda" "/dev/vda"
else else
"nodev"); "nodev"
);
efiSupport = lib.mkDefault supportEfi; efiSupport = lib.mkDefault supportEfi;
efiInstallAsRemovable = lib.mkDefault supportEfi; efiInstallAsRemovable = lib.mkDefault supportEfi;
}; };
loader.timeout = 0; loader.timeout = 0;
initrd.availableKernelModules = [ "uas" "virtio_blk" "virtio_pci" ]; initrd.availableKernelModules = [
"uas"
"virtio_blk"
"virtio_pci"
];
}; };
fileSystems."/" = { fileSystems."/" = {

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,33 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
cfg = config.virtualbox; cfg = config.virtualbox;
in
in { {
imports = [
./disk-size-option.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
"virtualbox"
"baseImageSize"
];
to = [
"virtualisation"
"diskSize"
];
})
];
options = { options = {
virtualbox = { virtualbox = {
baseImageSize = lib.mkOption {
type = with lib.types; either (enum [ "auto" ]) int;
default = "auto";
example = 50 * 1024;
description = ''
The size of the VirtualBox base image in MiB.
'';
};
baseImageFreeSpace = lib.mkOption { baseImageFreeSpace = lib.mkOption {
type = with lib.types; int; type = lib.types.int;
default = 30 * 1024; default = 30 * 1024;
description = '' description = ''
Free space in the VirtualBox base image in MiB. Free space in the VirtualBox base image in MiB.
@ -51,7 +62,14 @@ in {
''; '';
}; };
params = lib.mkOption { params = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ str int bool (listOf str) ]); type =
with lib.types;
attrsOf (oneOf [
str
int
bool
(listOf str)
]);
example = { example = {
audio = "alsa"; audio = "alsa";
rtcuseutc = "on"; rtcuseutc = "on";
@ -64,9 +82,19 @@ in {
''; '';
}; };
exportParams = lib.mkOption { exportParams = lib.mkOption {
type = with lib.types; listOf (oneOf [ str int bool (listOf str) ]); type =
with lib.types;
listOf (oneOf [
str
int
bool
(listOf str)
]);
example = [ example = [
"--vsys" "0" "--vendor" "ACME Inc." "--vsys"
"0"
"--vendor"
"ACME Inc."
]; ];
default = [ ]; default = [ ];
description = '' description = ''
@ -86,7 +114,8 @@ in {
mountPoint = "/home/demo/storage"; mountPoint = "/home/demo/storage";
size = 100 * 1024; size = 100 * 1024;
}; };
type = lib.types.nullOr (lib.types.submodule { type = lib.types.nullOr (
lib.types.submodule {
options = { options = {
size = lib.mkOption { size = lib.mkOption {
type = lib.types.int; type = lib.types.int;
@ -102,7 +131,8 @@ in {
description = "Path where to mount this disk."; description = "Path where to mount this disk.";
}; };
}; };
}); }
);
}; };
postExportCommands = lib.mkOption { postExportCommands = lib.mkOption {
type = lib.types.lines; type = lib.types.lines;
@ -122,7 +152,14 @@ in {
''; '';
}; };
storageController = lib.mkOption { storageController = lib.mkOption {
type = with lib.types; attrsOf (oneOf [ str int bool (listOf str) ]); type =
with lib.types;
attrsOf (oneOf [
str
int
bool
(listOf str)
]);
example = { example = {
name = "SCSI"; name = "SCSI";
add = "scsi"; add = "scsi";
@ -148,6 +185,9 @@ in {
}; };
config = { config = {
# Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
# to avoid breaking existing configs using that.
virtualisation.diskSize = lib.mkOverride 1490 (50 * 1024);
virtualbox.params = lib.mkMerge [ virtualbox.params = lib.mkMerge [
(lib.mapAttrs (name: lib.mkDefault) { (lib.mapAttrs (name: lib.mkDefault) {
@ -172,11 +212,10 @@ in {
inherit pkgs lib config; inherit pkgs lib config;
partitionTableType = "legacy"; partitionTableType = "legacy";
diskSize = cfg.baseImageSize; inherit (config.virtualisation) diskSize;
additionalSpace = "${toString cfg.baseImageFreeSpace}M"; additionalSpace = "${toString cfg.baseImageFreeSpace}M";
postVM = postVM = ''
''
export HOME=$PWD export HOME=$PWD
export PATH=${pkgs.virtualbox}/bin:$PATH export PATH=${pkgs.virtualbox}/bin:$PATH
@ -225,13 +264,15 @@ in {
''; '';
}; };
fileSystems = { fileSystems =
{
"/" = { "/" = {
device = "/dev/disk/by-label/nixos"; device = "/dev/disk/by-label/nixos";
autoResize = true; autoResize = true;
fsType = "ext4"; fsType = "ext4";
}; };
} // (lib.optionalAttrs (cfg.extraDisk != null) { }
// (lib.optionalAttrs (cfg.extraDisk != null) {
${cfg.extraDisk.mountPoint} = { ${cfg.extraDisk.mountPoint} = {
device = "/dev/disk/by-label/" + cfg.extraDisk.label; device = "/dev/disk/by-label/" + cfg.extraDisk.label;
autoResize = true; autoResize = true;
@ -242,10 +283,12 @@ in {
boot.growPartition = true; boot.growPartition = true;
boot.loader.grub.device = "/dev/sda"; boot.loader.grub.device = "/dev/sda";
swapDevices = [{ swapDevices = [
{
device = "/var/swap"; device = "/var/swap";
size = 2048; size = 2048;
}]; }
];
virtualisation.virtualbox.guest.enable = true; virtualisation.virtualbox.guest.enable = true;

View file

@ -312,7 +312,7 @@ in rec {
[ configuration [ configuration
versionModule versionModule
./maintainers/scripts/ec2/amazon-image.nix ./maintainers/scripts/ec2/amazon-image.nix
({ ... }: { amazonImage.sizeMB = "auto"; }) ({ ... }: { amazonImage.virtualisation.diskSize = "auto"; })
]; ];
}).config.system.build.amazonImage) }).config.system.build.amazonImage)