转自http://www.just4coding.com/blog/2017/11/19/qemu-monitor/html
QEMU实例运行时,用户能够经过monitor机制来与实例进行交互,经过它能够获取当前运行的虚拟机信息,处理热插拔设备,管理虚拟机快照等。要了解所有能力,能够参考文档: https://qemu.weilnetz.de/doc/qemu-doc.html#pcsys_005fmonitorgit
QEMU启动时,须要使用-monitor
选项指定作为console
设备,官方文档说明以下:github
1
2 |
-monitor dev Redirect the monitor to host device dev (same devices as the serial port). The default device is vc in graphical mode and stdio in non graphical mode. Use -monitor none to disable the default monitor. |
下面首先以标准输入输出设备作为console
来启动QEMU实例:json
1
2 3 4 |
[root@localhost ~]# qemu-system-x86_64 cirros-0.3.5-x86_64-disk.img -smp 2,cores=2 -m 2G -vnc :20 -device virtio-net-pci,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -name vm0 -monitor stdio QEMU 2.0.0 monitor - type 'help' for more information (qemu) |
在console
里能够输入相关命令来完成咱们的操做,好比咱们查看虚拟机网络设备状态:服务器
1
2 3 |
(qemu) info network virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56 \ net0: index=0,type=tap,ifname=tap0,script=no,downscript=no |
也能够动态添加设备,好比咱们添加一个8M大小的ivshmem
设备:网络
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
(qemu) device_add ivshmem,size=8m,shm=flygoast_vm0,bus=pci.0,addr=0x1f (qemu) info pci Bus 0, device 0, function 0: Host bridge: PCI device 8086:1237 id "" Bus 0, device 1, function 0: ISA bridge: PCI device 8086:7000 id "" Bus 0, device 1, function 1: IDE controller: PCI device 8086:7010 BAR4: I/O at 0xc020 [0xc02f]. id "" Bus 0, device 1, function 3: Bridge: PCI device 8086:7113 IRQ 9. id "" Bus 0, device 2, function 0: VGA controller: PCI device 1013:00b8 BAR0: 32 bit prefetchable memory at 0xfc000000 [0xfdffffff]. BAR1: 32 bit memory at 0xfebd0000 [0xfebd0fff]. BAR6: 32 bit memory at 0xffffffffffffffff [0x0000fffe]. id "" Bus 0, device 3, function 0: Ethernet controller: PCI device 1af4:1000 IRQ 11. BAR0: I/O at 0xc000 [0xc01f]. BAR1: 32 bit memory at 0xfebd1000 [0xfebd1fff]. BAR6: 32 bit memory at 0xffffffffffffffff [0x0003fffe]. id "" Bus 0, device 31, function 0: RAM controller: PCI device 1af4:1110 IRQ 0. BAR0: 32 bit memory at 0x80800000 [0x808000ff]. BAR2: 64 bit prefetchable memory at 0x80000000 [0x807fffff]. id “" |
执行后,咱们在Guest OS里查看PCI设备, 能够看到已经检测到了新的PCI设备:dom
除了标准输入输出设备,也可使用网络链接作为console
, 好比TCP、UnixSocket等。下面使用TCP监听端口作为console
启动QEMU实例:异步
1
|
[root@localhost ~]# qemu-system-x86_64 cirros-0.3.5-x86_64-disk.img -smp 2,cores=2 -m 2G -vnc :20 -device virtio-net-pci,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -name vm0 -monitor tcp:127.0.0.1:4444,server,nowait -daemonize |
使用nc
链接console
并查询虚拟机状态:socket
1
2 3 4 5 6 |
[root@localhost ~]# nc 127.0.0.1 4444 QEMU 2.0.0 monitor - type 'help' for more information (qemu) info status info status VM status: running (qemu) |
上述这种方式更偏向用户直接输入命令进行交互,称为HMP(Human Machine Protocol),程序使用这种方式不是太方便。QEMU还提供了另一种基于JSON的QMP(QEMU Machine Protocol)来知足自动化处理的需求。Libvirt就是使用QMP来控制QEMU实例。tcp
QMP规范能够参考:
QMP协议的工做流程以下:
capabilities negotiation
)模式{“execute”:”qmp_capablities”}
{“return”:{}}
,不然return
中会含有error
。QMP方式console
也可使用多种设备形式, 如,标准输入输出、TCP、UnixSocket等。能够经过QEMU选项-mon
来指定console
设备, 咱们以标准输入输出设备作为console
启动QEMU实例:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[root@localhost ~]# qemu-system-x86_64 cirros-0.3.5-x86_64-disk.img -smp 2,cores=2 -m 2G -vnc :20 -device virtio-net-pci,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -name vm0 -chardev stdio,id=mon0 -mon chardev=mon0,mode=control,pretty=on { "QMP": { "version": { "qemu": { "micro": 0, "minor": 0, "major": 2 }, "package": "" }, "capabilities": [ ] } } |
能够看到服务器发送了欢迎信息到标准输出,咱们在标准输入设备里输入:
1
|
{"execute":"qmp_capabilities”} |
QEMU实例返回:
1
2 3 4 |
{ "return": { } } |
此时咱们能够发送命令了,咱们来查询虚拟机状态:
1
|
{"execute":"query-status”} |
服务器返回告终果:
1
2 3 4 5 6 7 |
{ "return": { "status": "running", "singlestep": false, "running": true } } |
咱们还可使用UnixSocket作为console
:
1
|
[root@localhost ~]# qemu-system-x86_64 cirros-0.3.5-x86_64-disk.img -smp 2,cores=2 -m 2G -vnc :20 -device virtio-net-pci,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -name vm0 -chardev socket,id=mon0,path=/tmp/vm0.monitor,server,nowait -mon chardev=mon0,mode=control,pretty=on -daemonize |
使用nc
链接UnixSocket文件, QEMU实例返回了欢迎信息:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[root@localhost ~]# nc -U /tmp/vm0.monitor { "QMP": { "version": { "qemu": { "micro": 0, "minor": 0, "major": 2 }, "package": "" }, "capabilities": [ ] } } |
除了使用-mon
选项,还能够直接使用-qmp
选项:
1
|
[root@localhost ~]# qemu-system-x86_64 cirros-0.3.5-x86_64-disk.img -smp 2,cores=2 -m 2G -vnc :20 -device virtio-net-pci,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -name vm0 -qmp unix:/tmp/vm0.monitor,server,nowait -daemonize |
使用nc
链接:
1
2 |
[root@localhost ~]# nc -U /tmp/vm0.monitor {"QMP": {"version": {"qemu": {"micro": 0, "minor": 0, "major": 2}, "package": ""}, "capabilities": []}} |
上面提到,Libvirt使用QMP与QEMU实例通讯,libvirt建立QEMU实例时会指定一个UnixSocket文件作为console
。咱们能够经过使用virsh
命令的qemu-monitor-command
子命令来访问QEMU monitor,好比咱们查询块文件信息:
1
2 |
[root@localhost ~]# virsh qemu-monitor-command i1 '{"execute":"query-block"}' {"return":[{"io-status":"ok","device":"drive-ide0-0-0","locked":false,"removable":false,"inserted":{"iops_rd":0,"detect_zeroes":"off","image":{"virtual-size":21474836480,"filename":"/tmp/i1.qcow2","cluster-size":65536,"format":"qcow2","actual-size":12482580480,"format-specific":{"type":"qcow2","data":{"compat":"0.10","refcount-bits":16}},"dirty-flag":false},"iops_wr":0,"ro":false,"backing_file_depth":0,"drv":"qcow2","iops":0,"bps_wr":0,"write_threshold":0,"encrypted":false,"bps":0,"bps_rd":0,"cache":{"no-flush":false,"direct":false,"writeback":true},"file":"/tmp/i1.qcow2","encryption_key_missing":false},"type":"unknown"},{"io-status":"ok","device":"drive-ide0-0-1","locked":false,"removable":true,"tray_open":false,"type":"unknown"}],"id":"libvirt-13”} |
这种方式使用的是JSON格式的QMP协议,能够加上—hmp
选项直接输入命令来交互:
1
2 |
[root@localhost ~]# virsh qemu-monitor-command --hmp i1 info kvm kvm support: enabled |
咱们若是想直接链接libvirt生成的Unix Socket文件来操做QEMU实例,须要先将libvirtd关闭,如:
1
2 3 4 5 6 7 |
[root@localhost ~]# service libvirtd stop Redirecting to /bin/systemctl stop libvirtd.service [root@localhost ~]# nc -U /var/lib/libvirt/qemu/domain-26-i1/monitor.sock {"QMP": {"version": {"qemu": {"micro": 0, "minor": 3, "major": 2}, "package": " (qemu-kvm-ev-2.3.0-31.0.el7_2.21.1)"}, "capabilities": []}} ^C [root@localhost ~]# service libvirtd start Redirecting to /bin/systemctl start libvirtd.service |