systemd/machinectl: add systemd-vmspawn tests (#506751)

This commit is contained in:
Christian Kögler
2026-04-13 16:36:12 +00:00
committed by GitHub
+109 -25
View File
@@ -1,33 +1,38 @@
{ pkgs, ... }:
{ pkgs, lib, ... }:
let
evalConfig =
module:
(import ../lib/eval-config.nix {
system = null;
modules = [ module ];
}).config.system.build.toplevel;
container =
common =
{ config, ... }:
{
# We re-use the NixOS container option ...
boot.isNspawnContainer = true;
# ... and revert unwanted defaults
networking.useHostResolvConf = false;
# use networkd to obtain systemd network setup
networking.useNetworkd = true;
networking.useDHCP = false;
# systemd-nspawn expects /sbin/init
boot.loader.initScript.enable = true;
imports = [ ../modules/profiles/minimal.nix ];
system.stateVersion = config.system.nixos.release;
nixpkgs.pkgs = pkgs;
# use networkd to obtain systemd network setup
networking.useNetworkd = true;
};
containerSystem =
(import ../lib/eval-config.nix {
system = null;
modules = [ container ];
}).config.system.build.toplevel;
container = {
imports = [ common ];
# We re-use the NixOS container option ...
boot.isNspawnContainer = true;
# ... and revert unwanted defaults
networking.useHostResolvConf = false;
# systemd-nspawn expects /sbin/init
boot.loader.initScript.enable = true;
};
containerSystem = evalConfig container;
containerName = "container";
containerRoot = "/var/lib/machines/${containerName}";
@@ -51,16 +56,52 @@ let
}
];
};
vm = {
imports = [
common
../modules/profiles/qemu-guest.nix
];
# improvement: move following configuration to qemu-guest.nix
boot.initrd.availableKernelModules = [
"virtiofs"
];
boot.initrd.systemd.enable = true;
# root is defined by systemd-vmspawn
boot.initrd.systemd.root = null;
boot.loader.grub.enable = false;
services.openssh.enable = true;
};
vmSystem = evalConfig vm;
vmShared = {
imports = [ vm ];
fileSystems."/nix/store" = {
device = "mnt0";
fsType = "virtiofs";
neededForBoot = true;
};
};
vmSharedSystem = evalConfig vmShared;
in
{
name = "systemd-machinectl";
meta.maintainers = with lib.maintainers; [ ck3d ];
nodes.machine =
{ lib, ... }:
{
config,
lib,
pkgs,
...
}:
{
# use networkd to obtain systemd network setup
networking.useNetworkd = true;
networking.useDHCP = false;
# do not try to access cache.nixos.org
nix.settings.substituters = lib.mkForce [ ];
@@ -71,8 +112,12 @@ in
virtualisation.additionalPaths = [
containerSystem
containerTarball
vmSystem
vmSharedSystem
];
virtualisation.diskSize = 2048;
systemd.tmpfiles.rules = [
"d /var/lib/machines/shared-decl 0755 root root - -"
];
@@ -102,22 +147,62 @@ in
overrideStrategy = "asDropin";
};
# open DHCP for container
networking.firewall.extraCommands = ''
# open DHCP for nspawn interfaces
${pkgs.iptables}/bin/iptables -A nixos-fw -i ve-+ -p udp -m udp --dport 67 -j nixos-fw-accept
# open DHCP for vmspawn interfaces
${pkgs.iptables}/bin/iptables -A nixos-fw -i vt-+ -p udp -m udp --dport 67 -j nixos-fw-accept
'';
environment.systemPackages =
let
# improvement: following wrapper should be moved to pkgs
vmspawn-wrapped =
pkgs.runCommand "systemd-vmspawn-wrapped" { nativeBuildInputs = [ pkgs.makeWrapper ]; }
''
makeWrapper ${config.systemd.package}/bin/systemd-vmspawn $out/bin/systemd-vmspawn-wrapped \
--prefix PATH : ${
lib.makeBinPath [
pkgs.qemu
pkgs.virtiofsd
pkgs.openssh # ssh-keygen
]
} \
--prefix XDG_CONFIG_HOME : ${pkgs.qemu}/share
'';
in
[ vmspawn-wrapped ];
};
testScript = ''
start_all()
machine.wait_for_unit("default.target");
# Workaround for nixos-install
machine.succeed("chmod o+rx /var/lib/machines");
with subtest("vm-shared"):
machine.succeed("mkdir -p /var/lib/machines/vm-shared");
# Start vm-shared
machine.succeed("systemd-run systemd-vmspawn-wrapped --directory=/var/lib/machines/vm-shared --bind-ro=/nix/store --linux=${vmSharedSystem}/kernel --initrd=${vmSharedSystem}/initrd ${vmSharedSystem}/kernel-params init=${vmSharedSystem}/init")
machine.wait_until_succeeds("machinectl status vm-shared");
machine.wait_until_succeeds("eval $(machinectl show vm-shared --property=SSHPrivateKeyPath --property=SSHAddress) && ssh -i $SSHPrivateKeyPath $SSHAddress true")
machine.succeed("machinectl stop vm-shared");
with subtest("vm"):
machine.succeed("mkdir -p /var/lib/machines/vm");
# Install vm
machine.succeed("nixos-install --root /var/lib/machines/vm --system ${vmSystem} --no-channel-copy --no-root-passwd");
# Start vm
machine.succeed("systemd-run systemd-vmspawn-wrapped --directory=/var/lib/machines/vm --linux=${vmSystem}/kernel --initrd=${vmSystem}/initrd ${vmSystem}/kernel-params init=${vmSystem}/init")
machine.wait_until_succeeds("machinectl status vm");
machine.wait_until_succeeds("eval $(machinectl show vm --property=SSHPrivateKeyPath --property=SSHAddress) && ssh -i $SSHPrivateKeyPath $SSHAddress true")
machine.succeed("machinectl stop vm");
# Test machinectl start stop of shared-decl
machine.succeed("machinectl start shared-decl");
machine.wait_until_succeeds("systemctl -M shared-decl is-active default.target");
machine.succeed("machinectl stop shared-decl");
# create containers root
machine.succeed("mkdir -p ${containerRoot}");
# start container with shared nix store by using same arguments as for systemd-nspawn@.service
@@ -128,8 +213,6 @@ in
machine.succeed("machinectl stop ${containerName}");
# Install container
# Workaround for nixos-install
machine.succeed("chmod o+rx /var/lib/machines");
machine.succeed("nixos-install --root ${containerRoot} --system ${containerSystem} --no-channel-copy --no-root-passwd");
# Allow systemd-nspawn to apply user namespace on immutable files
@@ -183,6 +266,7 @@ in
# Test auto-start
machine.succeed("machinectl show ${containerName}")
machine.wait_until_succeeds("systemctl -M ${containerName} is-active default.target");
# Test machinectl stop
machine.succeed("machinectl stop ${containerName}");