qemu-openrc
qemu-openrc copied to clipboard
allow shutdown via guest agent socket
This allows shutdown events to be sent via qemu guest agent, which works for BSD agents which don't handle ACPI events correctly.
Tested with OpenBSD 7.0.
Signed-off-by: Aisha Tammy [email protected]
@jirutka any idea if this will be merged? It's super useful for BSD agents (like OP said)
Is it really needed to do guest-exec
? Mine works fine with {"execute":"guest-shutdown"}
. I tested it with Windows 10 guest however, as I am not a BSD expert.
I think that sending guest-shutdown
to guest agent and letting it decide how to shutdown the OS it runs on should be more preferred solution instead of calling binaries by their path, which is certainly not going to work in every OS. One example is Windows,
And qga already supports it: https://github.com/search?q=repo%3Aqemu%2Fqemu%20qmp_guest_shutdown&type=code.
One more remark: you forgor to include cleanup code for created socket(s).
My variant of this change is below. You can test it with BSD if you will :)
diff --git a/qemu.confd b/qemu.confd
index 9dfd1cf..6733b08 100644
--- a/qemu.confd
+++ b/qemu.confd
@@ -98,6 +98,8 @@
# Path of the QEMU monitor socket for this VM.
#monitor_socket="/run/qemu/${VM_NAME}/monitor.sock"
+# Path of the QEMU Guest Agent socket for this VM.
+#qemu_ga_socket="/run/qemu/${VM_NAME}/qemu_ga.sock"
##
# Network interfaces
diff --git a/qemu.initd b/qemu.initd
index 9cfb3c7..ee87243 100644
--- a/qemu.initd
+++ b/qemu.initd
@@ -26,6 +26,7 @@ VM_NAME="${RC_SVCNAME#qemu.}"
: ${vnc_listen:=0.0.0.0}
: ${hugepages_path:=/dev/hugepages}
: ${monitor_socket:=/run/qemu/${VM_NAME}/monitor.sock}
+: ${qemu_ga_socket:=/run/qemu/${VM_NAME}/qemu-ga.sock}
: ${extra_args:=}
name="VM $VM_NAME"
@@ -54,7 +55,10 @@ command_args="
-vga $vga
-device virtio-rng-pci
-device virtio-scsi-pci,id=scsi
- -monitor unix:$monitor_socket,server,nowait"
+ -monitor unix:$monitor_socket,server,nowait
+ -chardev socket,path=$qemu_ga_socket,server,nowait,id=qga0
+ -device virtio-serial
+ -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0"
command_background='yes'
command_user="$user"
command_group="$group"
@@ -102,7 +106,7 @@ start_pre() {
einfo "Command: $command $(printf '%s ' $command_args)"
fi
- local path; for path in "$pidfile" "$monitor_socket" "$logfile"; do
+ local path; for path in "$pidfile" "$monitor_socket" "$qemu_ga_socket" "$logfile"; do
# checkpath doesn't create intermediate directories
mkdir -p "$(dirname "$path")"
checkpath -d -m 0750 -o $user:$group "$(dirname "$path")"
@@ -112,8 +116,8 @@ start_pre() {
}
start_post() {
- ewaitfile 5 "$monitor_socket" || {
- eerror 'Monitor socket has not been created!'; return 1
+ ewaitfile 5 "$monitor_socket" "$qemu_ga_socket" || {
+ eerror 'Monitor socket or guest agent socket have not been created!'; return 1
}
if [ -n "$vnc_password" ]; then
qemush "set_password vnc $vnc_password" || eerror 'Failed to set VNC password!'
@@ -126,7 +130,7 @@ stop() {
ebegin "Stopping $name"
- if is_running && qemush 'system_powerdown'; then
+ if is_running && guestcmd '{"execute":"guest-shutdown"}' && qemush 'system_powerdown'; then
count="$shutdown_timeout"
printf " Waiting $count seconds for VM shutdown "
@@ -152,6 +156,7 @@ stop() {
stop_post() {
[ -S "$monitor_socket" ] && rm -f "$monitor_socket"
+ [ -S "$qemu_ga_socket" ] && rm -f "$qemu_ga_socket"
[ -f "$pidfile" ] && rm -f "$pidfile"
return 0
}
@@ -290,6 +295,11 @@ qemush_show() {
printf "%b\n" "$*" | socat - "UNIX-CONNECT:${monitor_socket}" | tail -n +3 | head -n -1
}
+guestcmd() {
+ local IFS=$'\n'
+ printf "%b\n" "$*" | socat - "UNIX-CONNECT:${qemu_ga_socket}" 1>/dev/null
+}
+
gen_macaddr() {
printf "$1" | md5sum | sed -E 's/^(..)(..)(..)(..).*$/52:54:\1:\2:\3:\4/'
}