OpenBSD Journal

Using qemu guest agent on OpenBSD kvm/qemu guests

Contributed by Paul 'WEiRD' de Weerd on from the turtles all the way down dept.

In a post to the ports@ mailing list, Landry Breuil (landry@) shared some of his notes on using qemu guest agent on OpenBSD kvm/qemu guests. He made a few enhancements for Undeadly:

Experimenting with proxmox VE since some years (but that also applies to plain kvm/qemu OpenBSD vms), today i had a look at the qemu guest agent feature:

in the host config/webui, enabling the guest agent adds a virtio-serial device to the kvm cmdline:

-chardev socket,path=/var/run/qemu-server/100.qga,server,nowait,id=qga0
-device virtio-serial,id=qga0,bus=pci.0,addr=0x8
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0

in the guest, this is detected as a new virtio device for which we have no dedicated driver, so it stays unconfigured:

virtio1 at pci0 dev 8 function 0 "Qumranet Virtio Console" rev 0x00
virtio1: no matching child driver; not configured

but looking at the qemu-guest-agent & proxmox qm docs:

there's a way to tell proxmox to use the 'isa-serial' device type:

proxmox# grep agent /etc/pve/qemu-server/100.conf 
agent: 1,type=isa

which adds another device type to the kvm cmdline:

-chardev socket,path=/var/run/qemu-server/100.qga,server,nowait,id=qga0
-device isa-serial,chardev=qga0

and in the guest.. there's a new serial device (com0 is used by the qemu console):

com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
com0: console
com1 at isa0 port 0x2f8/8 irq 3: ns16550a, 16 byte fifo

from that point, one can run qemu-ga, pointing at this serial port (-f and -t are used because otherwise qemu-ga hardcodes /usr/local/$something):

guest$ doas qemu-ga -m isa-serial -p /dev/cua01 -f /tmp/xx.pid -t /tmp/ -v
1589361079.833754: debug: disabling command: guest-suspend-disk
1589361079.833788: debug: disabling command: guest-suspend-ram
1589361079.833799: debug: disabling command: guest-suspend-hybrid
1589361079.833809: debug: disabling command: guest-network-get-interfaces
1589361079.833818: debug: disabling command: guest-get-vcpus
1589361079.833827: debug: disabling command: guest-set-vcpus
1589361079.833836: debug: disabling command: guest-get-memory-blocks
1589361079.833852: debug: disabling command: guest-set-memory-blocks
1589361079.833862: debug: disabling command: guest-get-memory-block-size
1589361079.833872: debug: disabling command: guest-get-memory-block-info
1589361079.833881: debug: disabling command: guest-get-fsinfo
1589361079.833890: debug: disabling command: guest-fsfreeze-status
1589361079.833898: debug: disabling command: guest-fsfreeze-freeze
1589361079.833907: debug: disabling command: guest-fsfreeze-freeze-list
1589361079.833916: debug: disabling command: guest-fsfreeze-thaw
1589361079.833924: debug: disabling command: guest-get-fsinfo
1589361079.833933: debug: disabling command: guest-fstrim

(yeah, some commands are disabled, something to probably fix w/ upstream, freebsd has some work done in https://github.com/aborche/qemu-guest-agent)

After that one can send commands via the host:

proxmox# qm agent 100 get-host-name
{
   "host-name" : "c64.proxmox2"
}

proxmox# qm agent 100 get-time
1589361360033920000
proxmox# qm agent 100 get-osinfo
{
   "kernel-release" : "6.7",
   "kernel-version" : "GENERIC.MP#182",
   "machine" : "amd64"
}

sadly, upstream hardcodes shutdown arguments in the guest-shutdown command (cf https://git.qemu.org/?p=qemu.git;a=blob;f=qga/commands-posix.c;hb=HEAD#l84) so trying qm agent 100 shutdown wont work out of the box, but that should be patchable.

according to the 'info' command, those qemu commands should work:

proxmox# qm guest cmd 100 info | jq '.supported_commands | .[] | select(.enabled == true) | select (."success-response" == true) | .name'
"guest-get-osinfo"
"guest-get-timezone"
"guest-get-users"
"guest-get-host-name"
"guest-exec"
"guest-exec-status"
"guest-set-user-password"
"guest-file-flush"
"guest-file-seek"
"guest-file-write"
"guest-file-read"
"guest-file-close"
"guest-file-open"
"guest-info"
"guest-set-time"
"guest-get-time"
"guest-ping"
"guest-sync"
"guest-sync-delimited"

testing shows some are broken at runtime, but that allows the host to list files within the guest:

proxmox# qm guest exec 100 -- ls -l /tmp 2>&1 | jq -r '."out-data"'
total 32
drwxrwxrwt  2 root    wheel  512 May 13 11:54 .ICE-unix
drwxrwxrwt  2 root    wheel  512 May 13 11:54 .X11-unix
-rw-r--r--  1 root    wheel   25 May 13 13:25 qga.state
drwxr-xr-x  2 root    wheel  512 May 13 11:54 sndio
drwx------  2 landry  wheel  512 May 14 07:56 tmp.8Nf9OuNyW4
drwx------  2 landry  wheel  512 May 14 07:54 tmp.QxizXbfyA0
drwx------  2 landry  wheel  512 May 13 11:57 tmux-1000
drwxrwxrwt  2 root    wheel  512 Feb 13 17:07 vi.recover

and finally, this allows a graceful shutdown of the guest from the host:

proxmox# qm guest exec 100 -- halt -p
QEMU guest agent is not running

(and the vm is properly stopped)

Hoping that can be useful for people who use OpenBSD in qemu/kvm VMs, haven't found any kind of doc on that specific to OpenBSD so far.

bits to consider portswise: i think it would make sense to subpackage qemu-ga binary, having to install the complete qemu package with all its dependencies in a VM if a bit much imo. Will see if that's feasible.. fixing hardcoded paths and some commands would be nice too :)

Many thanks to Landry for sharing his notes with us!

(Comments are closed)


Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]