【轉】QEMU Monitor機制實例分析


轉自http://www.just4coding.com/blog/2017/11/19/qemu-monitor/

QEMU實例運行時,用戶可以通過monitor機制來與實例進行交互,通過它可以獲取當前運行的虛擬機信息,處理熱插拔設備,管理虛擬機快照等。要了解全部能力,可以參考文檔: https://qemu.weilnetz.de/doc/qemu-doc.html#pcsys_005fmonitor

QEMU啟動時,需要使用-monitor選項指定做為console設備,官方文檔說明如下:

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實例:

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設備:

除了標准輸入輸出設備,也可以使用網絡連接做為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並查詢虛擬機狀態:

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實例。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM