virtualisation: Use system.build.image, normalize file names (#359339)

This commit is contained in:
Jonas Chevalier 2024-11-29 22:54:17 +01:00 committed by GitHub
commit 223586a617
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 324 additions and 166 deletions

View File

@ -209,3 +209,6 @@ ce21e97a1f20dee15da85c084f9d1148d84f853b
# treewide: migrate packages to pkgs/by-name, take 1
571c71e6f73af34a229414f51585738894211408
# format files with nixfmt (#347275)
adb9714bd909df283c66bbd641bd631ff50a4260

View File

@ -8,7 +8,21 @@
let
inherit (lib) types;
imageModules = { };
imageModules = {
azure = [ ../virtualisation/azure-image.nix ];
digital-ocean = [ ../virtualisation/digital-ocean-image.nix ];
google-compute = [ ../virtualisation/google-compute-image.nix ];
hyperv = [ ../virtualisation/hyperv-image.nix ];
linode = [ ../virtualisation/linode-image.nix ];
lxc = [ ../virtualisation/lxc-container.nix ];
lxc-metadata = [ ../virtualisation/lxc-image-metadata.nix ];
oci = [ ../virtualisation/oci-image.nix ];
proxmox = [ ../virtualisation/proxmox-image.nix ];
kubevirt = [ ../virtualisation/kubevirt.nix ];
vagrant-virtualbox = [ ../virtualisation/vagrant-virtualbox-image.nix ];
virtualbox = [ ../virtualisation/virtualbox-image.nix ];
vmware = [ ../virtualisation/vmware-image.nix ];
};
imageConfigs = lib.mapAttrs (
name: modules:
extendModules {

View File

@ -13,6 +13,7 @@ in
imports = [
./azure-common.nix
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -61,10 +62,14 @@ in
};
config = {
image.extension = "vhd";
system.nixos.tags = [ "azure" ];
system.build.image = config.system.build.azureImage;
system.build.azureImage = import ../../lib/make-disk-image.nix {
name = "azure-image";
inherit (config.image) baseName;
postVM = ''
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o subformat=fixed,force_size -O vpc $diskImage $out/disk.vhd
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o subformat=fixed,force_size -O vpc $diskImage $out/${config.image.fileName}
rm $diskImage
'';
configFile = ./azure-config-user.nix;

View File

@ -14,6 +14,7 @@ in
imports = [
./digital-ocean-config.nix
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -57,32 +58,53 @@ in
};
#### implementation
config = {
system.build.digitalOceanImage = import ../../lib/make-disk-image.nix {
name = "digital-ocean-image";
config =
let
format = "qcow2";
postVM =
let
compress =
{
"gzip" = "${pkgs.gzip}/bin/gzip";
"bzip2" = "${pkgs.bzip2}/bin/bzip2";
}
.${cfg.compressionMethod};
in
''
${compress} $diskImage
'';
configFile =
if cfg.configFile == null then
config.virtualisation.digitalOcean.defaultConfigFile
else
cfg.configFile;
inherit (config.virtualisation) diskSize;
inherit config lib pkgs;
};
in
{
image.extension = lib.concatStringsSep "." [
format
(
{
"gzip" = "gz";
"bzip2" = "bz2";
}
.${cfg.compressionMethod}
)
];
system.nixos.tags = [ "digital-ocean" ];
system.build.image = config.system.build.digitalOceanImage;
system.build.digitalOceanImage = import ../../lib/make-disk-image.nix {
name = "digital-ocean-image";
inherit (config.image) baseName;
inherit (config.virtualisation) diskSize;
inherit
config
lib
pkgs
format
;
postVM =
let
compress =
{
"gzip" = "${pkgs.gzip}/bin/gzip";
"bzip2" = "${pkgs.bzip2}/bin/bzip2";
}
.${cfg.compressionMethod};
in
''
${compress} $diskImage
'';
configFile =
if cfg.configFile == null then
config.virtualisation.digitalOcean.defaultConfigFile
else
cfg.configFile;
};
};
};
meta.maintainers = with maintainers; [
arianvp

View File

@ -22,6 +22,7 @@ in
imports = [
./google-compute-config.nix
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -72,8 +73,12 @@ in
fsType = "vfat";
};
system.nixos.tags = [ "google-compute" ];
image.extension = "raw.tar.gz";
system.build.image = config.system.build.googleComputeImage;
system.build.googleComputeImage = import ../../lib/make-disk-image.nix {
name = "google-compute-image";
inherit (config.image) baseName;
postVM = ''
PATH=$PATH:${
with pkgs;
@ -83,10 +88,9 @@ in
]
}
pushd $out
mv $diskImage disk.raw
tar -Sc disk.raw | gzip -${toString cfg.compressionLevel} > \
nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.raw.tar.gz
rm $out/disk.raw
tar -Sc $diskImage | gzip -${toString cfg.compressionLevel} > \
${config.image.fileName}
rm $diskImage
popd
'';
format = "raw";

View File

@ -14,6 +14,7 @@ in
imports = [
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -25,6 +26,18 @@ in
"diskSize"
];
})
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2505;
from = [
"virtualisation"
"hyperv"
"vmFileName"
];
to = [
"image"
"fileName"
];
})
];
options = {
@ -36,13 +49,6 @@ in
The name of the derivation for the hyper-v appliance.
'';
};
vmFileName = mkOption {
type = types.str;
default = "nixos-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.vhdx";
description = ''
The file name of the hyper-v appliance.
'';
};
};
};
@ -51,10 +57,14 @@ in
# to avoid breaking existing configs using that.
virtualisation.diskSize = lib.mkOverride 1490 (4 * 1024);
system.nixos.tags = [ "hyperv" ];
image.extension = "vhdx";
system.build.image = config.system.build.hypervImage;
system.build.hypervImage = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName;
baseName = config.image.baseName;
postVM = ''
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o subformat=dynamic -O vhdx $diskImage $out/${cfg.vmFileName}
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o subformat=dynamic -O vhdx $diskImage $out/${config.image.fileName}
rm $diskImage
'';
format = "raw";

View File

@ -1,8 +1,14 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
{
imports = [
../profiles/qemu-guest.nix
../image/file-options.nix
];
config = {
@ -22,8 +28,12 @@
services.cloud-init.enable = true;
systemd.services."serial-getty@ttyS0".enable = true;
system.nixos.tags = [ "kubevirt" ];
image.extension = "qcow2";
system.build.image = config.system.build.kubevirtImage;
system.build.kubevirtImage = import ../../lib/make-disk-image.nix {
inherit lib config pkgs;
inherit (config.image) baseName;
format = "qcow2";
};
};

View File

@ -20,6 +20,7 @@ in
imports = [
./linode-config.nix
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -57,13 +58,17 @@ in
};
config = {
system.nixos.tags = [ "linode" ];
image.extension = "img.gz";
system.build.image = config.system.build.linodeImage;
system.build.linodeImage = import ../../lib/make-disk-image.nix {
name = "linode-image";
baseName = config.image.baseName;
# NOTE: Linode specifically requires images to be `gzip`-ed prior to upload
# See: https://www.linode.com/docs/products/tools/images/guides/upload-an-image/#requirements-and-considerations
postVM = ''
${pkgs.gzip}/bin/gzip -${toString cfg.compressionLevel} -c -- $diskImage > \
$out/nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.img.gz
$out/${config.image.fileName}
rm $diskImage
'';
format = "raw";

View File

@ -1,4 +1,9 @@
{ lib, config, pkgs, ... }:
{
lib,
config,
pkgs,
...
}:
{
meta = {
@ -8,18 +13,27 @@
imports = [
./lxc-instance-common.nix
(lib.mkRemovedOptionModule [ "virtualisation" "lxc" "nestedContainer" ] "")
(lib.mkRemovedOptionModule [ "virtualisation" "lxc" "privilegedContainer" ] "")
(lib.mkRemovedOptionModule [
"virtualisation"
"lxc"
"nestedContainer"
] "")
(lib.mkRemovedOptionModule [
"virtualisation"
"lxc"
"privilegedContainer"
] "")
];
options = { };
config = let
initScript = if config.boot.initrd.systemd.enable then "prepare-root" else "init";
in {
boot.isContainer = true;
boot.postBootCommands =
''
config =
let
initScript = if config.boot.initrd.systemd.enable then "prepare-root" else "init";
in
{
boot.isContainer = true;
boot.postBootCommands = ''
# After booting, register the contents of the Nix store in the Nix
# database.
if [ -f /nix-path-registration ]; then
@ -31,78 +45,84 @@
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
# supplement 99-ethernet-default-dhcp which excludes veth
systemd.network = lib.mkIf config.networking.useDHCP {
networks."99-lxc-veth-default-dhcp" = {
matchConfig = {
Type = "ether";
Kind = "veth";
Name = [
"en*"
"eth*"
];
# supplement 99-ethernet-default-dhcp which excludes veth
systemd.network = lib.mkIf config.networking.useDHCP {
networks."99-lxc-veth-default-dhcp" = {
matchConfig = {
Type = "ether";
Kind = "veth";
Name = [
"en*"
"eth*"
];
};
DHCP = "yes";
networkConfig.IPv6PrivacyExtensions = "kernel";
};
DHCP = "yes";
networkConfig.IPv6PrivacyExtensions = "kernel";
};
system.nixos.tags = lib.mkOverride 99 [ "lxc" ];
image.extension = "tar.xz";
image.filePath = "tarball/${config.image.fileName}";
system.build.image = lib.mkOverride 99 config.system.build.tarball;
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
fileName = config.image.baseName;
extraArgs = "--owner=0";
storeContents = [
{
object = config.system.build.toplevel;
symlink = "none";
}
];
contents = [
{
source = config.system.build.toplevel + "/${initScript}";
target = "/sbin/init";
}
# Technically this is not required for lxc, but having also make this configuration work with systemd-nspawn.
# Nixos will setup the same symlink after start.
{
source = config.system.build.toplevel + "/etc/os-release";
target = "/etc/os-release";
}
];
extraCommands = "mkdir -p proc sys dev";
};
system.build.squashfs = pkgs.callPackage ../../lib/make-squashfs.nix {
fileName = "nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}";
hydraBuildProduct = true;
noStrip = true; # keep directory structure
comp = "zstd -Xcompression-level 6";
storeContents = [ config.system.build.toplevel ];
pseudoFiles = [
"/sbin d 0755 0 0"
"/sbin/init s 0555 0 0 ${config.system.build.toplevel}/${initScript}"
"/dev d 0755 0 0"
"/proc d 0555 0 0"
"/sys d 0555 0 0"
];
};
system.build.installBootLoader = pkgs.writeScript "install-lxc-sbin-init.sh" ''
#!${pkgs.runtimeShell}
${pkgs.coreutils}/bin/ln -fs "$1/${initScript}" /sbin/init
'';
# networkd depends on this, but systemd module disables this for containers
systemd.additionalUpstreamSystemUnits = [ "systemd-udev-trigger.service" ];
systemd.packages = [ pkgs.distrobuilder.generator ];
system.activationScripts.installInitScript = lib.mkForce ''
ln -fs $systemConfig/${initScript} /sbin/init
'';
};
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
extraArgs = "--owner=0";
storeContents = [
{
object = config.system.build.toplevel;
symlink = "none";
}
];
contents = [
{
source = config.system.build.toplevel + "/${initScript}";
target = "/sbin/init";
}
# Technically this is not required for lxc, but having also make this configuration work with systemd-nspawn.
# Nixos will setup the same symlink after start.
{
source = config.system.build.toplevel + "/etc/os-release";
target = "/etc/os-release";
}
];
extraCommands = "mkdir -p proc sys dev";
};
system.build.squashfs = pkgs.callPackage ../../lib/make-squashfs.nix {
fileName = "nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}";
hydraBuildProduct = true;
noStrip = true; # keep directory structure
comp = "zstd -Xcompression-level 6";
storeContents = [config.system.build.toplevel];
pseudoFiles = [
"/sbin d 0755 0 0"
"/sbin/init s 0555 0 0 ${config.system.build.toplevel}/${initScript}"
"/dev d 0755 0 0"
"/proc d 0555 0 0"
"/sys d 0555 0 0"
];
};
system.build.installBootLoader = pkgs.writeScript "install-lxc-sbin-init.sh" ''
#!${pkgs.runtimeShell}
${pkgs.coreutils}/bin/ln -fs "$1/${initScript}" /sbin/init
'';
# networkd depends on this, but systemd module disables this for containers
systemd.additionalUpstreamSystemUnits = ["systemd-udev-trigger.service"];
systemd.packages = [ pkgs.distrobuilder.generator ];
system.activationScripts.installInitScript = lib.mkForce ''
ln -fs $systemConfig/${initScript} /sbin/init
'';
};
}

View File

@ -46,6 +46,10 @@ let
else { files = []; properties = {}; };
in {
imports = [
../image/file-options.nix
];
meta = {
maintainers = lib.teams.lxc.members;
};
@ -87,7 +91,12 @@ in {
};
config = {
system.nixos.tags = [ "lxc" "metadata" ];
image.extension = "tar.xz";
image.filePath = "tarball/${config.image.fileName}";
system.build.image = config.system.build.metadata;
system.build.metadata = pkgs.callPackage ../../lib/make-system-tarball.nix {
fileName = config.image.baseName;
contents = [
{
source = toYAML "metadata.yaml" {

View File

@ -9,7 +9,10 @@ let
cfg = config.oci;
in
{
imports = [ ./oci-common.nix ];
imports = [
./oci-common.nix
../image/file-options.nix
];
config = {
# Use a priority just below mkOptionDefault (1500) instead of lib.mkDefault
@ -17,10 +20,14 @@ in
virtualisation.diskSize = lib.mkOverride 1490 (8 * 1024);
virtualisation.diskSizeAutoSupported = false;
system.nixos.tags = [ "oci" ];
image.extension = "qcow2";
system.build.image = config.system.build.OCIImage;
system.build.OCIImage = import ../../lib/make-disk-image.nix {
inherit config lib pkgs;
inherit (config.virtualisation) diskSize;
name = "oci-image";
baseName = config.image.baseName;
configFile = ./oci-config-user.nix;
format = "qcow2";
partitionTableType = if cfg.efi then "efi" else "legacy";

View File

@ -9,6 +9,7 @@ with lib;
{
imports = [
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -250,8 +251,12 @@ with lib;
message = "'legacy+gpt' disk partitioning requires 'seabios' bios";
}
];
image.baseName = lib.mkDefault "vzdump-qemu-${cfg.filenameSuffix}";
image.extension = "vma.zst";
system.build.image = config.system.build.VMA;
system.build.VMA = import ../../lib/make-disk-image.nix {
name = "proxmox-${cfg.filenameSuffix}";
baseName = config.image.baseName;
inherit (cfg) partitionTableType;
postVM =
let
@ -299,16 +304,16 @@ with lib;
});
in
''
${vma}/bin/vma create "vzdump-qemu-${cfg.filenameSuffix}.vma" \
${vma}/bin/vma create "${config.image.baseName}.vma" \
-c ${
cfgFile "qemu-server.conf" (cfg.qemuConf // cfg.qemuExtraConf)
}/qemu-server.conf drive-virtio0=$diskImage
rm $diskImage
${pkgs.zstd}/bin/zstd "vzdump-qemu-${cfg.filenameSuffix}.vma"
mv "vzdump-qemu-${cfg.filenameSuffix}.vma.zst" $out/
${pkgs.zstd}/bin/zstd "${config.image.baseName}.vma"
mv "${config.image.fileName}" $out/
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/${config.image.fileName}" > $out/nix-support/hydra-build-products
'';
inherit (cfg.qemuConf) additionalSpace bootSize;
inherit (config.virtualisation) diskSize;

View File

@ -8,6 +8,10 @@
with lib;
{
imports = [
../image/file-options.nix
];
options.proxmoxLXC = {
enable = mkOption {
default = true;
@ -46,7 +50,15 @@ with lib;
cfg = config.proxmoxLXC;
in
mkIf cfg.enable {
system.nixos.tags = [
"proxmox"
"lxc"
];
image.extension = "tar.xz";
image.filePath = "tarball/${config.image.fileName}";
system.build.image = config.system.build.tarball;
system.build.tarball = pkgs.callPackage ../../lib/make-system-tarball.nix {
fileName = config.image.baseName;
storeContents = [
{
object = config.system.build.toplevel;

View File

@ -1,6 +1,6 @@
# Vagrant + VirtualBox
{ config, pkgs, ... }:
{ config, pkgs, lib, ... }:
{
imports = [
@ -22,38 +22,41 @@
# generate the box v1 format which is much easier to generate
# https://www.vagrantup.com/docs/boxes/format.html
image.extension = lib.mkOverride 999 "${config.image.baseName}.box";
system.nixos.tags = [ "vagrant"];
system.build.image = lib.mkOverride 999 config.system.build.vagrantVirtualbox;
system.build.vagrantVirtualbox = pkgs.runCommand
"virtualbox-vagrant.box"
config.image.fileName
{}
''
mkdir workdir
cd workdir
# 1. create that metadata.json file
echo '{"provider":"virtualbox"}' > metadata.json
# 1. create that metadata.json file
echo '{"provider":"virtualbox"}' > metadata.json
# 2. create a default Vagrantfile config
cat <<VAGRANTFILE > Vagrantfile
Vagrant.configure("2") do |config|
config.vm.base_mac = "0800275F0936"
end
VAGRANTFILE
# 2. create a default Vagrantfile config
cat <<VAGRANTFILE > Vagrantfile
Vagrant.configure("2") do |config|
config.vm.base_mac = "0800275F0936"
end
VAGRANTFILE
# 3. add the exported VM files
tar xvf ${config.system.build.virtualBoxOVA}/*.ova
# 3. add the exported VM files
tar xvf ${config.system.build.virtualBoxOVA}/*.ova
# 4. move the ovf to the fixed location
mv *.ovf box.ovf
# 4. move the ovf to the fixed location
mv *.ovf box.ovf
# 5. generate OVF manifest file
rm *.mf
touch box.mf
for fname in *; do
checksum=$(sha256sum $fname | cut -d' ' -f 1)
echo "SHA256($fname)= $checksum" >> box.mf
done
# 5. generate OVF manifest file
rm *.mf
touch box.mf
for fname in *; do
checksum=$(sha256sum $fname | cut -d' ' -f 1)
echo "SHA256($fname)= $checksum" >> box.mf
done
# 6. compress everything back together
tar --owner=0 --group=0 --sort=name --numeric-owner -czf $out .
'';
# 6. compress everything back together
tar --owner=0 --group=0 --sort=name --numeric-owner -czf $out .
'';
}

View File

@ -11,6 +11,7 @@ in
{
imports = [
./disk-size-option.nix
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2411;
from = [
@ -22,6 +23,18 @@ in
"diskSize"
];
})
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2505;
from = [
"virtualisation"
"virtualbox"
"vmFileName"
];
to = [
"image"
"fileName"
];
})
];
options = {
@ -54,13 +67,6 @@ in
The name of the VirtualBox appliance.
'';
};
vmFileName = lib.mkOption {
type = lib.types.str;
default = "nixos-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.ova";
description = ''
The file name of the VirtualBox appliance.
'';
};
params = lib.mkOption {
type =
with lib.types;
@ -207,8 +213,12 @@ in
(lib.mkIf (pkgs.stdenv.hostPlatform.system == "i686-linux") { pae = "on"; })
];
system.nixos.tags = [ "virtualbox" ];
image.extension = "ova";
system.build.image = lib.mkDefault config.system.build.virtualBoxOVA;
system.build.virtualBoxOVA = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName;
baseName = config.image.baseName;
inherit pkgs lib config;
partitionTableType = "legacy";
@ -253,7 +263,7 @@ in
echo "exporting VirtualBox VM..."
mkdir -p $out
fn="$out/${cfg.vmFileName}"
fn="$out/${config.image.fileName}"
VBoxManage export "$vmName" --output "$fn" --options manifest ${lib.escapeShellArgs cfg.exportParams}
${cfg.postExportCommands}

View File

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
let
boolToStr = value: if value then "on" else "off";
cfg = config.vmware;
@ -12,6 +17,23 @@ let
];
in {
imports = [
../image/file-options.nix
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2505;
from = [
"virtualisation"
"vmware"
"vmFileName"
];
to = [
"image"
"fileName"
];
})
];
options = {
vmware = {
baseImageSize = lib.mkOption {
@ -29,13 +51,6 @@ in {
The name of the derivation for the VMWare appliance.
'';
};
vmFileName = lib.mkOption {
type = lib.types.str;
default = "nixos-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.vmdk";
description = ''
The file name of the VMWare appliance.
'';
};
vmSubformat = lib.mkOption {
type = lib.types.enum subformats;
default = "monolithicSparse";
@ -51,10 +66,14 @@ in {
};
config = {
system.nixos.tags = [ "vmware" ];
image.extension = "vmdk";
system.build.image = config.system.build.vmwareImage;
system.build.vmwareImage = import ../../lib/make-disk-image.nix {
name = cfg.vmDerivationName;
baseName = config.image.baseName;
postVM = ''
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o compat6=${boolToStr cfg.vmCompat6},subformat=${cfg.vmSubformat} -O vmdk $diskImage $out/${cfg.vmFileName}
${pkgs.vmTools.qemu}/bin/qemu-img convert -f raw -o compat6=${boolToStr cfg.vmCompat6},subformat=${cfg.vmSubformat} -O vmdk $diskImage $out/${config.image.fileName}
rm $diskImage
'';
format = "raw";