Skip to content

Commit d1908ae

Browse files
committed
cloud-hypervisor: respect microvm.vsock.cid instead of hardcoding
Previously, cloud-hypervisor always configured vsock with cid=3, causing problems when runnning multiple VMs from running on the same host due to CID conflicts. This change respects `microvm.vsock.cid` when set and allows users to configure vsock via `microvm.cloud-hypervisor.extraArgs`. The implementation: - Uses `microvm.vsock.cid` when specified - Extracts and merges `--vsock` options from extraArgs - Throws an error if both vsock.cid and --vsock cid=... are provided - Warns users when vsock is not configured (disabling systemd-notify) Fixes: microvm-nix#378 Builds on and requires PR microvm-nix#336 (for the extractOptValues function)
1 parent c3ee0b6 commit d1908ae

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

lib/default.nix

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,26 @@ rec {
133133
processArgs (builtins.tail args) values (acc ++ [(builtins.head args)]);
134134
in
135135
processArgs extraArgs [] [];
136+
137+
/*
138+
extractParamValue - Extract a parameter value from comma-separated key=value options
139+
140+
Description:
141+
Extracts the value of a specified parameter from a comma-separated string
142+
of key=value pairs (e.g., "key1=val1,key2=val2"). Returns the first match.
143+
144+
Parameters:
145+
param :: String - The parameter name to search for
146+
opts :: String - The options string
147+
148+
Returns:
149+
String | null - The parameter value if found, null otherwise
150+
151+
Example:
152+
extractParamValue "socket" "cid=5,socket=notify.vsock" => "notify.vsock"
153+
*/
154+
extractParamValue = param: opts:
155+
if opts == "" || opts == null then null
156+
else let m = builtins.match ".*${param}=([^,]+).*" opts;
157+
in if m == null then null else builtins.head m;
136158
}

lib/runner.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ let
88

99
inherit (microvmConfig) hostName;
1010

11-
inherit (import ./. { inherit lib; }) createVolumesScript makeMacvtap withDriveLetters extractOptValues;
11+
inherit (import ./. { inherit lib; }) createVolumesScript makeMacvtap withDriveLetters extractOptValues extractParamValue;
1212
inherit (makeMacvtap {
1313
inherit microvmConfig hypervisorConfig;
1414
}) openMacvtapFds macvtapFds;
1515

1616
hypervisorConfig = import (./runners + "/${microvmConfig.hypervisor}.nix") {
17-
inherit pkgs microvmConfig macvtapFds withDriveLetters extractOptValues;
17+
inherit pkgs microvmConfig macvtapFds withDriveLetters extractOptValues extractParamValue;
1818
};
1919

2020
inherit (hypervisorConfig) command canShutdown shutdownCommand;

lib/runners/cloud-hypervisor.nix

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22
, microvmConfig
33
, macvtapFds
44
, extractOptValues
5+
, extractParamValue
56
, ...
67
}:
78

89
let
910
inherit (pkgs) lib;
10-
inherit (microvmConfig) vcpu mem balloon initialBalloonMem deflateOnOOM hotplugMem hotpluggedMem user interfaces volumes shares socket devices hugepageMem graphics storeDisk storeOnDisk kernel initrdPath;
11+
inherit (microvmConfig) vcpu mem balloon initialBalloonMem deflateOnOOM hotplugMem hotpluggedMem user interfaces volumes shares socket devices hugepageMem graphics storeDisk storeOnDisk kernel initrdPath vsock;
1112
inherit (microvmConfig.cloud-hypervisor) platformOEMStrings extraArgs;
1213

14+
# extract all the extra args that we merge with up front
15+
processedExtraArgs = builtins.foldl'
16+
(args: opt: (extractOptValues opt args).args)
17+
extraArgs
18+
["--vsock" "--platform"];
19+
1320
hasUserConsole = (extractOptValues "--console" extraArgs).values != [];
1421
hasUserSerial = (extractOptValues "--serial" extraArgs).values != [];
1522
userSerial = if hasUserSerial then (extractOptValues "--serial" extraArgs).values else "";
@@ -30,6 +37,24 @@ let
3037

3138
kernelCmdLine = "${kernelConsole} reboot=t panic=-1 ${builtins.unsafeDiscardStringContext (toString microvmConfig.kernelParams)}";
3239

40+
41+
userVSockOpts = (extractOptValues "--vsock" extraArgs).values;
42+
userVSockStr = if userVSockOpts == [] then null else builtins.head userVSockOpts;
43+
userVSockPath = extractParamValue "socket" userVSockStr;
44+
userVSockCID = extractParamValue "cid" userVSockStr;
45+
vsockCID = if vsock.cid != null && userVSockCID != null
46+
then throw "Cannot set vsock.cid and --vsock 'cid=${userVSockCID}...' at the same time"
47+
else if vsock.cid != null
48+
then vsock.cid
49+
else userVSockCID;
50+
supportsNotifySocket = vsockCID != null;
51+
vsockPath = if userVSockPath != null then userVSockPath else "notify.vsock";
52+
vsockOpts =
53+
if vsockCID == null then
54+
lib.warn "cloud-hypervisor supports systemd-notify via vsock, but `microvm.vsock.cid` must be set to enable this." ""
55+
else
56+
"cid=${toString vsockCID},socket=${vsockPath}";
57+
3358
useHotPlugMemory = hotplugMem > 0;
3459

3560
useVirtiofs = builtins.any ({ proto, ... }: proto == "virtiofs") shares;
@@ -101,14 +126,18 @@ let
101126
vulkan = true;
102127
};
103128

104-
supportsNotifySocket = true;
105-
106129
oemStringValues = platformOEMStrings ++ lib.optional supportsNotifySocket "io.systemd.credential:vmm.notify_socket=vsock-stream:2:8888";
107130
oemStringOptions = lib.optional (oemStringValues != []) "oem_strings=[${lib.concatStringsSep "," oemStringValues}]";
108131
platformExtracted = extractOptValues "--platform" extraArgs;
109132
extraArgsWithoutPlatform = platformExtracted.args;
110133
userPlatformOpts = platformExtracted.values;
111-
platformOps = lib.concatStringsSep "," (oemStringOptions ++ userPlatformOpts);
134+
userPlatformStr = if userPlatformOpts == [] then "" else builtins.head userPlatformOpts;
135+
userHasOemStrings = (extractParamValue "oem_strings" userPlatformStr) != null;
136+
platformOps =
137+
if userHasOemStrings then
138+
throw "Use `microvm.cloud-hypervisor.platformOEMStrings` instead of passing oem_strings via --platform"
139+
else
140+
lib.concatStringsSep "," (oemStringOptions ++ userPlatformOpts);
112141
in {
113142
inherit tapMultiQueue;
114143

@@ -122,13 +151,13 @@ in {
122151
123152
'' + lib.optionalString supportsNotifySocket ''
124153
# Ensure notify sockets are removed if cloud-hypervisor didn't exit cleanly the last time
125-
rm -f notify.vsock notify.vsock_8888
154+
rm -f ${vsockPath} ${vsockPath}_8888
126155
127156
# Start socat to forward systemd notify socket over vsock
128157
if [ -n "''${NOTIFY_SOCKET:-}" ]; then
129158
# -T2 is required because cloud-hypervisor does not handle partial
130159
# shutdown of the stream, like systemd v256+ does.
131-
${pkgs.socat}/bin/socat -T2 UNIX-LISTEN:notify.vsock_8888,fork UNIX-SENDTO:$NOTIFY_SOCKET &
160+
${pkgs.socat}/bin/socat -T2 UNIX-LISTEN:${vsockPath}_8888,fork UNIX-SENDTO:$NOTIFY_SOCKET &
132161
fi
133162
'' + lib.optionalString graphics.enable ''
134163
rm -f ${graphics.socket}
@@ -142,7 +171,6 @@ in {
142171
done
143172
'';
144173

145-
inherit supportsNotifySocket;
146174

147175
command =
148176
if user != null
@@ -167,9 +195,7 @@ in {
167195
++
168196
lib.optionals (!hasUserSerial) ["--serial" "tty"]
169197
++
170-
lib.optionals supportsNotifySocket [
171-
"--vsock" "cid=3,socket=notify.vsock"
172-
]
198+
lib.optionals (vsockOpts != "") ["--vsock" vsockOpts]
173199
++
174200
lib.optionals graphics.enable [
175201
"--gpu" "socket=${graphics.socket}"
@@ -240,7 +266,7 @@ in {
240266
usb = throw "USB passthrough is not supported on cloud-hypervisor";
241267
}.${bus}) devices
242268
)
243-
) + " " + lib.escapeShellArgs extraArgsWithoutPlatform;
269+
) + " " + lib.escapeShellArgs processedExtraArgs;
244270

245271
canShutdown = socket != null;
246272

0 commit comments

Comments
 (0)