QMP ( qemu monitor protocol ) and Different ways of accessing it

The QEMU Monitor Protocol (QMP) is a JSON-based protocol which allows applications to communicate with a QEMU instance.

Read more about QMP here :http://wiki.qemu.org/QMP

Its a client server architecture where the data can be exchanged. The monitor protocol is really useful for debugging, experimenting and also useful for collecting statistics and for fetching data about the qemu instance or VM.

There are different ways to access and talk over “QMP”:


1) Virsh/libvirt way using ‘qemu-monitor-command’
2) Using ‘telnet’ over ‘qmp’ socket
3) Using utitilties ‘qmp-shell’, nc, socat/rlwrap over ‘qmp’ socket..

Previously I used different hacks to talk with the VM instances via qemu monitor protocol, but things are changing fast and now libvirt has a decent interface to talk with the qemu instance using “QMP” protocol.

When talking over QMP , we have to use “qmp” syntax which is JSON formatted data for the communication. How-ever QMP’s subset called ‘hmp’ is also available to make life easy.

libvirt has added an option with ‘virsh’ to talk over QMP. Its “qemu-monitor-command”. It has the capability of exchanging information in ‘hmp’ format as well. You just need to on ‘-hmp’ over command line for this .

As soon as you are connected to “QMP” server you will receive a “greetings” banner from the server : Then you have to execute “qmp_capabilities” command to start the communication:

“QMP” greeting banner will look like this:

{“QMP”: {“version”: {“qemu”: {“micro”: 50, “minor”: 5, “major”: 1}, “package”: “”}, “capabilities”: []}} ==> “greetings” banner is provided by “QMP”

{ “execute”: “qmp_capabilities” } ======> “You are moving into data exchange”

Now, let me show you the examples of using different utilities for this purpose..

1) VIRSH / LIBVIRT WAY:

qemu-monitor-command [–hmp] {[–cmd] }…

Below example will show you ‘virsh’ way of using it via ‘HMP’ and ‘QMP’:

I have a guest running with domain id :3 . You may have different id, get it using “virsh list”

To get information about ‘VM’ block devices, registers, uuid, spice..etc :

[root@humbles-lap QMP]# virsh qemu-monitor-command –hmp 3 info block drive-virtio-disk0: removable=0 io-status=ok file=/export/vmimgs/L1-f18.qcow2 ro=0 drv=qcow2 encrypted=0 bps=0 bps_rd=0 bps_wr=0 iops=0 iops_rd=0 iops_wr=0

[root@humbles-lap QMP]# virsh qemu-monitor-command –hmp 3 info registers RAX=0000000000000096 RBX=00000000000f4240 RCX=0000000000000008 RDX=000000000000acac RSI=0000000000000096 RDI=ffffffff81edd950 RBP=ffff88007fc03e68 RSP=ffff88007fc03e68 R8 =0000000000000002 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000001 R12=00000000000e7aa4 R13=00000000000e7aa4 R14=fffffffffff0bdc0 R15=0000000000000007 RIP=ffffffff816628e4 RFL=00000086 [–S–P-] CPL=0 II=0 A20=1 SMM=0 HLT=0

root@humbles-lap QMP]# virsh qemu-monitor-command –hmp 3 info uuid 0d0946d1-9b07-4480-6647-815237b910e2

[root@humbles-lap QMP]# virsh qemu-monitor-command –hmp 3 info spice Server: address: 0.0.0.0:5900 migrated: false auth: spice compiled: 0.12.2 mouse-mode: client Channel: address: 127.0.0.1:47690 session: 1804289383 channel: 1:0 Channel: address: 127.0.0.1:47695 session: 1804289383 channel: 4:0 Channel: address: 127.0.0.1:47694 session: 1804289383 channel: 2:0 Channel: address: 127.0.0.1:47696 session: 1804289383 channel: 3:0

Above examples used ‘hmp’ format, how-ever if you would like to use ‘qmp’ format , you just need to exclude ‘-hmp’ option from virsh command as shown below:

[root@humbles-lap QMP]# virsh qemu-monitor-command 3 ‘{“execute”:”query-kvm”}’ {“return”:{“enabled”:true,”present”:true},”id”:”libvirt-34″}

[root@humbles-lap QMP]#

Now lets look at other possibilities of talking to qemu instance via “qmp” protocol:

1) Start a qemu instance with a socket option and telnet to that:

[root@humbles-lap QMP]./x86_64-softmmu/qemu-system-x86_64 –enable-kvm -smp 2 -m 1024 /export/vmimgs/L1-f18.qcow2 -nographic -qmp tcp:localhost:4444,server

[root@humbles-lap qemu]$ telnet localhost 4444 Trying ::1… Connected to localhost. Escape character is ‘^]’. {“QMP”: {“version”: {“qemu”: {“micro”: 50, “minor”: 5, “major”: 1}, “package”: “”}, “capabilities”: []}}

2) Try starting a qemu instance via ‘qmp’ UNIX socket and access it via ‘qmp-shell’, “nc”, “socat &rwrap” ..etc

[root@humbles-lap qemu]# ./x86_64-softmmu/qemu-system-x86_64 –enable-kvm -smp 2 -m 1024 /export/vmimgs/L1-f18.qcow2 -nographic -qmp unix:./qmp-sock-exp,server

There is a program called ‘qmp-shell” shipped or available from upstream qemu:

Inside “QMP” directory you have the mentioned programm:

[root@humbles-lap qemu]# ./QMP/qmp-shell ./qmp-sock-exp Welcome to the QMP low-level shell! Connected to QEMU 1.5.50

(QEMU) (QEMU) q qmp_capabilities query-block-jobs query-events query-migrate-capabilities query-tpm qom-get query-blockstats query-fdsets query-name query-tpm-models qom-list query-chardev query-kvm query-pci query-tpm-types qom-list-types query-command-line-options query-machines query-rx-filter query-uuid qom-set query-commands query-mice query-spice query-version query-balloon query-cpu-definitions query-migrate query-status query-vnc query-block query-cpus query-migrate-cache-size query-target quit (QEMU)

(QEMU) query-chardev {u’return’: [{u’label’: u’parallel0′, u’filename’: u’null’}, {u’label’: u’serial0′, u’filename’: u’stdio’}, {u’label’: u’compat_monitor0′, u’filename’: u’unix:./qmp-sock-exp,server’}]} (QEMU)

(QEMU) query-block {u’return’: [{u’locked’: False, u’type’: u’unknown’, u’io-status’: u’ok’, u’removable’: False, u’device’: u’ide0-hd0′, u’inserted’: {u’bps_rd’: 0, u’backing_file_depth’: 0, u’encrypted’: False, u’image’: {u’cluster-size’: 65536, u’format’: u’qcow2′, u’filename’: u’/export/vmimgs/L1-f18.qcow2′, u’virtual-size’: 15032385536, u’dirty-flag’: False, u’actual-size’: 8293609472}, u’bps_wr’: 0, u’drv’: u’qcow2′, u’bps’: 0, u’iops’: 0, u’file’: u’/export/vmimgs/L1-f18.qcow2′, u’iops_rd’: 0, u’encryption_key_missing’: False, u’ro’: False, u’iops_wr’: 0}}, {u’locked’: False, u’tray_open’: False, u’io-status’: u’ok’, u’removable’: True, u’device’: u’ide1-cd0′, u’type’: u’unknown’}, {u’device’: u’floppy0′, u’type’: u’unknown’, u’tray_open’: False, u’locked’: False, u’removable’: True}, {u’device’: u’sd0′, u’type’: u’unknown’, u’tray_open’: False, u’locked’: False, u’removable’: True}]} (QEMU)

(QEMU) query-kvm {u’return’: {u’enabled’: True, u’present’: True}} (QEMU)

(QEMU) query-vnc {u’return’: {u’enabled’: False}} (QEMU)

(QEMU) quit {u’return’: {}} (QEMU) quit Disconnected

Now , lets move to the example of using ‘nc’ :

[root@humbles-lap qemu]# nc -U ./qmp-sock-exp {“QMP”: {“version”: {“qemu”: {“micro”: 50, “minor”: 5, “major”: 1}, “package”: “”}, “capabilities”: []}} ==> “greetings” banner is provided by “QMP”

{ “execute”: “qmp_capabilities” } ======> “You are moving into data exchange” {“return”: {}}

{ “execute”: “query-vnc” } {“return”: {“enabled”: false}}

Ctrl+D

Last one to access “QMP” is via ‘socat’ and ‘rlwrap’:

You need to install ‘socat & rlwrap’ for experimenting this.

[root@humbles-lap qemu]# rlwrap socat UNIX-CONNECT:./qmp-sock-exp STDIO {“QMP”: {“version”: {“qemu”: {“micro”: 50, “minor”: 5, “major”: 1}, “package”: “”}, “capabilities”: []}}

{ “execute”: “query-pci” } {“return”: [{“bus”: 0, “devices”: [{“bus”: 0, “qdev_id”: “”, “slot”: 0, “class_info”: {“class”: 1536, “desc”: “Host bridge”}, “id”: {“device”: 4663, “vendor”: 32902}, “function”: 0, “regions”: []}, {“bus”: 0, “qdev_id”: “”, “slot”: 1, “class_info”: {“class”: 1537, “desc”: “ISA bridge”}, “id”: {“device”: 28672, “vendor”: 32902}, “function”: 0, “regions”: []}, {“bus”: 0, “qdev_id”: “”, “slot”: 1, “class_info”: {“class”: 257, “desc”: “IDE controller”}, “id”: {“device”: 28688, “vendor”: 32902}, “function”: 1, “regions”: [{“bar”: 4, “size”: 16, “address”: 49216, “type”: “io”}]}, {“bus”: 0, “qdev_id”: “”, “irq”: 9, “slot”: 1, “class_info”: {“class”: 1664, “desc”: “Bridge”}, “id”: {“device”: 28947, “vendor”: 32902}, “function”: 3, “regions”: []}, {“bus”: 0, “qdev_id”: “”, “slot”: 2, “class_info”: {“class”: 768, “desc”: “VGA controller”}, “id”: {“device”: 184, “vendor”: 4115}, “function”: 0, “regions”: [{“prefetch”: true, “mem_type_64”: false, “bar”: 0, “size”: 33554432, “address”: 4227858432, “type”: “memory”}, {“prefetch”: false, “mem_type_64”: false, “bar”: 1, “size”: 4096, “address”: 4273930240, “type”: “memory”}, {“prefetch”: false, “mem_type_64”: false, “bar”: 6, “size”: 65536, “address”: -1, “type”: “memory”}]}, {“bus”: 0, “qdev_id”: “”, “irq”: 11, “slot”: 3, “class_info”: {“class”: 512, “desc”: “Ethernet controller”}, “id”: {“device”: 4110, “vendor”: 32902}, “function”: 0, “regions”: [{“prefetch”: false, “mem_type_64”: false, “bar”: 0, “size”: 131072, “address”: 4273733632, “type”: “memory”}, {“bar”: 1, “size”: 64, “address”: 49152, “type”: “io”}, {“prefetch”: false, “mem_type_64”: false, “bar”: 6, “size”: 262144, “address”: -1, “type”: “memory”}]}]}]}

Ctrl+ D

Hope this was helpful!!!