Skip to content

Commit fae4c42

Browse files
committed
fix: use RegisterMachineEx fallback path and add targeted machined regressions
1 parent fcde362 commit fae4c42

File tree

9 files changed

+1449
-937
lines changed

9 files changed

+1449
-937
lines changed

checks/default.nix

Lines changed: 307 additions & 204 deletions
Large diffs are not rendered by default.

checks/imperative-template.nix

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
self,
3+
nixpkgs,
4+
system,
5+
...
6+
}:
7+
8+
{
9+
imperative-template =
10+
import (nixpkgs + "/nixos/tests/make-test-python.nix")
11+
(
12+
{ ... }:
13+
{
14+
name = "imperative-template";
15+
16+
nodes.host = {
17+
imports = [ self.nixosModules.host ];
18+
microvm.host.enable = true;
19+
};
20+
21+
testScript = ''
22+
host.wait_for_unit("multi-user.target")
23+
24+
host.succeed("mkdir -p /var/lib/microvms/test/current/bin")
25+
26+
host.succeed("""cat > /var/lib/microvms/test/current/bin/microvm-run <<'EOF'
27+
#!/bin/sh
28+
trap 'exit 0' TERM INT
29+
while true; do sleep 1; done
30+
EOF
31+
chmod +x /var/lib/microvms/test/current/bin/microvm-run
32+
""")
33+
34+
host.succeed("""cat > /var/lib/microvms/test/current/bin/microvm-shutdown <<'EOF'
35+
#!/bin/sh
36+
exit 0
37+
EOF
38+
chmod +x /var/lib/microvms/test/current/bin/microvm-shutdown
39+
""")
40+
41+
# Should work in imperative mode without microvm-register/microvm-unregister scripts.
42+
host.succeed("systemctl start microvm@test.service")
43+
host.wait_for_unit("microvm@test.service")
44+
45+
host.succeed("systemctl stop microvm@test.service")
46+
host.wait_until_succeeds("! systemctl is-active --quiet microvm@test.service")
47+
'';
48+
49+
meta.timeout = 600;
50+
}
51+
)
52+
{
53+
inherit system;
54+
pkgs = nixpkgs.legacyPackages.${system};
55+
};
56+
}

checks/machined.nix

Lines changed: 68 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,82 @@
1-
{ self, nixpkgs, system, hypervisor }:
1+
{
2+
self,
3+
nixpkgs,
4+
system,
5+
hypervisor,
6+
}:
27

38
let
4-
pkgs = nixpkgs.legacyPackages.${system};
59
vmName = "machined-test";
10+
vsockCid = 4242;
611
in
712
{
813
# Test that MicroVMs can be registered with systemd-machined
9-
"machined-${hypervisor}" = pkgs.nixosTest {
10-
name = "machined-${hypervisor}";
11-
nodes.host = { lib, ... }: {
12-
imports = [ self.nixosModules.host ];
13-
14-
virtualisation.qemu.options = [
15-
"-cpu"
14+
"machined-${hypervisor}" =
15+
import (nixpkgs + "/nixos/tests/make-test-python.nix")
16+
(
17+
{ lib, ... }:
1618
{
17-
"aarch64-linux" = "cortex-a72";
18-
"x86_64-linux" = "kvm64,+svm,+vmx";
19-
}.${system}
20-
];
21-
virtualisation.diskSize = 4096;
22-
23-
# Define a VM with machined registration enabled
24-
microvm.vms.${vmName}.config = {
25-
microvm = {
26-
hypervisor = hypervisor;
27-
# Enable machined registration on the VM
28-
registerWithMachined = true;
29-
};
30-
networking.hostName = vmName;
31-
system.stateVersion = lib.trivial.release;
32-
};
33-
};
34-
testScript = ''
35-
# Wait for the MicroVM service to start
36-
host.wait_for_unit("microvm@${vmName}.service", timeout = 1200)
19+
name = "machined-${hypervisor}";
20+
nodes.host = {
21+
imports = [ self.nixosModules.host ];
22+
23+
virtualisation.qemu.options = [
24+
"-cpu"
25+
{
26+
"aarch64-linux" = "cortex-a72";
27+
"x86_64-linux" = "kvm64,+svm,+vmx";
28+
}
29+
.${system}
30+
];
31+
virtualisation.diskSize = 4096;
3732

38-
# Verify the VM is registered with machined
39-
host.succeed("machinectl list | grep -q '${vmName}'")
33+
# Define a VM with machined registration enabled
34+
microvm.vms.${vmName}.config = {
35+
microvm = {
36+
hypervisor = hypervisor;
37+
# Enable machined registration on the VM
38+
registerWithMachined = true;
39+
}
40+
// lib.optionalAttrs (hypervisor != "cloud-hypervisor") {
41+
vsock.cid = vsockCid;
42+
};
43+
networking.hostName = vmName;
44+
system.stateVersion = lib.trivial.release;
45+
};
46+
};
47+
testScript = ''
48+
# Wait for the MicroVM service to start
49+
host.wait_for_unit("microvm@${vmName}.service", timeout = 1200)
4050
41-
# Verify machine status works
42-
host.succeed("machinectl status '${vmName}'")
51+
# Verify the VM is registered with machined
52+
host.succeed("machinectl list | grep -q '${vmName}'")
4353
44-
# Verify the machine class is 'vm'
45-
host.succeed("machinectl show '${vmName}' --property=Class | grep -q 'vm'")
54+
# Verify machine status works
55+
host.succeed("machinectl status '${vmName}'")
4656
47-
# Verify leader PID exists
48-
host.succeed("machinectl show '${vmName}' --property=Leader | grep -q '^Leader=[0-9]'")
57+
# Verify the machine class is 'vm'
58+
host.succeed("machinectl show '${vmName}' --property=Class | grep -q 'vm'")
4959
50-
# Terminate the VM via machinectl (sends SIGTERM to hypervisor)
51-
host.succeed("machinectl terminate '${vmName}'")
60+
${lib.optionalString (hypervisor != "cloud-hypervisor") ''
61+
# On systemd >=259 RegisterMachineEx path should expose VSOCK/SSH metadata
62+
host.succeed("machinectl show '${vmName}' --property=VSockCID | grep -q 'VSockCID=${toString vsockCid}'")
63+
host.succeed("machinectl show '${vmName}' --property=SSHAddress | grep -q 'SSHAddress=vsock/${toString vsockCid}'")
64+
''}
5265
53-
# Wait for the service to stop
54-
host.wait_until_fails("machinectl status '${vmName}'", timeout = 30)
55-
'';
56-
meta.timeout = 1800;
57-
};
66+
# Test kill command (send signal 0 to check process exists)
67+
host.succeed("machinectl kill '${vmName}' --signal=0")
68+
69+
# Terminate the VM via machinectl (sends SIGTERM to hypervisor)
70+
host.succeed("machinectl terminate '${vmName}'")
71+
72+
# Wait for the service to stop
73+
host.wait_until_fails("machinectl status '${vmName}'", timeout = 30)
74+
'';
75+
meta.timeout = 1800;
76+
}
77+
)
78+
{
79+
inherit system;
80+
pkgs = nixpkgs.legacyPackages.${system};
81+
};
5882
}

checks/microvm-command.nix

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{ nixpkgs, system, ... }:
2+
3+
let
4+
pkgs = nixpkgs.legacyPackages.${system};
5+
6+
fakeOpenSSH = pkgs.runCommandLocal "fake-openssh" { } ''
7+
mkdir -p $out/bin
8+
cat > $out/bin/ssh <<'EOF'
9+
#!/bin/sh
10+
out="''${SSH_ARGS_OUT:?SSH_ARGS_OUT must be set}"
11+
: > "$out"
12+
for arg in "$@"; do
13+
printf '%s\n' "$arg" >> "$out"
14+
done
15+
EOF
16+
chmod +x $out/bin/ssh
17+
'';
18+
19+
microvmCommand = import ../pkgs/microvm-command.nix {
20+
pkgs = pkgs // {
21+
openssh = fakeOpenSSH;
22+
};
23+
stateDir = "/tmp/microvms";
24+
};
25+
in
26+
{
27+
microvm-command =
28+
pkgs.runCommandLocal "microvm-command"
29+
{
30+
nativeBuildInputs = [
31+
microvmCommand
32+
pkgs.diffutils
33+
];
34+
}
35+
''
36+
set -euo pipefail
37+
38+
mkdir -p /tmp/microvms/vm/current/share/microvm
39+
echo 4242 > /tmp/microvms/vm/current/share/microvm/vsock-cid
40+
echo qemu > /tmp/microvms/vm/current/share/microvm/hypervisor
41+
42+
export SSH_ARGS_OUT="$PWD/ssh-args-extra-opts"
43+
microvm -s vm -- -l root -i /tmp/test-key
44+
cat > "$PWD/expected-extra-opts" <<'EOF'
45+
-o
46+
StrictHostKeyChecking=no
47+
-o
48+
UserKnownHostsFile=/dev/null
49+
-l
50+
root
51+
-i
52+
/tmp/test-key
53+
vsock/4242
54+
EOF
55+
diff -u "$PWD/expected-extra-opts" "$PWD/ssh-args-extra-opts"
56+
57+
export SSH_ARGS_OUT="$PWD/ssh-args-remote-cmd"
58+
microvm -s vm uname -a
59+
cat > "$PWD/expected-remote-cmd" <<'EOF'
60+
-o
61+
StrictHostKeyChecking=no
62+
-o
63+
UserKnownHostsFile=/dev/null
64+
vsock/4242
65+
uname
66+
-a
67+
EOF
68+
diff -u "$PWD/expected-remote-cmd" "$PWD/ssh-args-remote-cmd"
69+
70+
mkdir $out
71+
'';
72+
}

0 commit comments

Comments
 (0)