http://kashyapc.com/2013/03/31/multiple-ways-to-access-qemu-machine-protocol-qmp/
Once QEMU is built, to get a finer understanding of it, or even for plain old debugging, having familiarity with QMP (QEMU Monitor Protocol) is quite useful. QMP allows applications — like libvirt — to communicate with a running QEMU’s instance. There are a few different ways to access the QEMU monitor to query the guest, get device (eg: PCI, block, etc) information, modify the guest state (useful to understand the block layer operations) using QMP commands. This post discusses a few aspects of it.
Access QMP via libvirt’s qemu-monitor-command
Libvirt had this capability for a long time, and this is the simplest. It can be invoked by virsh
— on a running guest, in this case, called ‘devstack’:
$ virsh qemu-monitor-command devstack \ --pretty '{"execute":"query-kvm"}' { "return": { "enabled": true, "present": true }, "id": "libvirt-8" }
In the above example, I ran the simple command query-kvm
which checks if (1) the host is capable of running KVM (2) and if KVM is enabled. Refer below for a list of possible ‘qeury’ commands.
QMP via telnet
To access monitor via any other way, we need to have qemu instance running in control mode, via telnet:
$ ./x86_64-softmmu/qemu-system-x86_64 \ --enable-kvm -smp 2 -m 1024 \ /export/images/el6box1.qcow2 \ -qmp tcp:localhost:4444,server --monitor stdio QEMU waiting for connection on: tcp::127.0.0.14444,server VNC server running on `127.0.0.1:5900' QEMU 1.4.50 monitor - type 'help' for more information (qemu)
And, from a different shell, connect to that listening port 4444 via telnet
:
$ telnet localhost 4444 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. {"QMP": {"version": {"qemu": {"micro": 50, "minor": 4, "major": 1}, "package": ""}, "capabilities": []}}
We have to first enable QMP capabilities. This needs to be run before invoking any other commands, do:
{ "execute": "qmp_capabilities" }
QMP via unix socket
First, invoke the qemu binary in control mode using qmp, and create a unix socket as below:
$ ./x86_64-softmmu/qemu-system-x86_64 \ --enable-kvm -smp 2 -m 1024 \ /export/images/el6box1.qcow2 \ -qmp unix:./qmp-sock,server --monitor stdio QEMU waiting for connection on: unix:./qmp-sock,server
A few different ways to connect to the above qemu instance running in control mode, vi QMP:
nc
: $ nc -U ./qmp-sock {"QMP": {"version": {"qemu": {"micro": 50, "minor": 4, "major": 1}, "package": ""}, "capabilities": []}}
But, with the above, you have to manually enable the QMP capabilities, and type each command in JSON syntax. It’s a bit cumbersome, & no history of commands typed is saved.
qmp-shell
is located in the QEMU source tree, under qemu/scripts/qmp/qmp-shell, which hides some details — like manually running the qmp_capabilities. Connect to the unix socket using the qmp-shell
script:
$ ./qmp-shell ../qmp-sock Welcome to the QMP low-level shell! Connected to QEMU 1.4.50 (QEMU)
Then, just hit the key, and all the possible commands would be listed. To see a list of query commands:
(QEMU) query-<TAB> query-balloon query-commands query-kvm query-migrate-capabilities query-uuid query-block query-cpu-definitions query-machines query-name query-version query-block-jobs query-cpus query-mice query-pci query-vnc query-blockstats query-events query-migrate query-status query-chardev query-fdsets query-migrate-cache-size query-target (QEMU)
socat
and rlwrap
. Thanks to upstream qemu developer Markus Armbruster for this hint. Invoke it this way, also execute a couple of commands — qmp_capabilities
, and query-kvm
, to view the response from the server.
$ rlwrap -H ~/.qmp_history \ socat UNIX-CONNECT:./qmp-sock STDIO {"QMP": {"version": {"qemu": {"micro": 50, "minor": 4, "major": 1}, "package": ""}, "capabilities": []}} {"execute":"qmp_capabilities"} {"return": {}} { "execute": "query-kvm" } {"return": {"enabled": true, "present": true}}
Where, qmp_history contains recently ran QMP commands in JSON syntax. And rlwrap
adds decent editing capabilities, recursive search & history. So, once you run all your commands, the ~/.qmp_history
has a neat stack of all the QMP commands in JSON syntax.
For instance, this is what my ~/.qmp_history file contains as I write this:
$ cat ~/.qmp_history { "execute": "qmp_capabilities" } { "execute": "query-version" } { "execute": "query-events" } { "execute": "query-chardev" } { "execute": "query-block" } { "execute": "query-blockstats" } { "execute": "query-cpus" } { "execute": "query-pci" } { "execute": "query-kvm" } { "execute": "query-mice" } { "execute": "query-vnc" } { "execute": "query-spice " } { "execute": "query-uuid" } { "execute": "query-migrate" } { "execute": "query-migrate-capabilities" } { "execute": "query-balloon" }
To illustrate, I ran a few query commands (noted above) which provides an informative response from the server — no change is done to the state of the guest — so these can be executed safely.
I personally prefer the libvirt way, & accessing via unix socket with socat
& rlwrap
.
NOTE: To try each of the above variants, fisrst quit — type quit
on the (qemu)
shell — the qemu instance running in control mode, reinvoke it, then access it via one of the 3 different ways.