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 :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!!!

http://www.humblec.com/qmp-qemu-monitor-protocol-and-different-ways-of-accessing-it/

原文地址:https://www.cnblogs.com/CasonChan/p/4865964.html