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 {
@ -34,30 +57,32 @@ in {
} }
] ]
''; '';
default = []; default = [ ];
description = '' description = ''
This option lists files to be copied to fixed locations in the This option lists files to be copied to fixed locations in the
generated image. Glob patterns work. generated image. Glob patterns work.
''; '';
}; };
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,8 +137,13 @@ with lib;
}; };
}; };
qemuExtraConf = mkOption { qemuExtraConf = mkOption {
type = with types; attrsOf (oneOf [ str int ]); type =
default = {}; with types;
attrsOf (oneOf [
str
int
]);
default = { };
example = literalExpression '' example = literalExpression ''
{ {
cpu = "host"; cpu = "host";
@ -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,11 +82,21 @@ 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 = ''
Parameters passed to the Virtualbox export command. Parameters passed to the Virtualbox export command.
@ -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)