基於QMP實現對qemu虛擬機進行交互

基於QMP實現對qemu虛擬機進行交互

本文詳解QMP,包含qmp、hmp、qemu-guest-agent的介紹、工做原理、配置方法、範例html

小慢哥的原創文章,歡迎轉載node


目錄

▪ QMP介紹
▪ QMP語法
▪ 單獨使用qemu,啓用QMP
▪ 經過libvirt啓動qemu,啓用QMP
▪ qemu-guest-agent(qemu-ga)
▪ 官方參考文檔linux

QMP介紹

qemu對外提供了一個socket接口,稱爲qemu monitor,經過該接口,能夠對虛擬機實例的整個生命週期進行管理,主要有以下功能json

▷ 狀態查看、變動
▷ 設備查看、變動
▷ 性能查看、限制
▷ 在線遷移
▷ 數據備份
▷ 訪問內部操做系統windows

經過該socket接口傳遞交互的協議是qmp,全稱是qemu monitor protocol,這是基於json格式的協議centos

在繼續往下講以前,須要先了解qemu、kvm、libvirt之間的區別(由於有不少童鞋對這三者的理解是混亂的)api

▷ qemu:虛擬機仿真器。經過軟件模擬出cpu、內存、磁盤、主板、網卡等設備
▷ kvm:高性能的cpu仿真器。因爲軟件模擬的cpu性能不好,所以出現了kvm,這是經過硬件與內核的支持實現接近native性能的cpu仿真器,能夠理解爲虛擬機裏的cpu任務直接交給物理機cpu完成。
▷ libvirt:虛擬機管理平臺。能納管qemu、lxc、esx等虛擬化軟件,經過編寫xml實現對虛擬機、存儲、網絡等進行配置和管理網絡

上面只描述最核心的功能,另有一些高級功能,以及互相重疊的功能在這裏不作描述,不然容易混淆dom

QMP語法

# 不帶參數的指令
{ "execute" : "XXX" }

# 帶參數的指令
{ "execute" : "XXX", "arguments" : { ... } }

單獨使用qemu,啓用QMP

啓動qemu虛擬機異步

# qemu monitor採用tcp方式,監聽在127.0.0.1上,端口爲4444
/usr/libexec/qemu-kvm -qmp tcp:127.0.0.1:4444,server,nowait

# qemu monitor採用unix socket,socket文件生成於/opt/qmp.socket
/usr/libexec/qemu-kvm -qmp unix:/opt/qmp.socket,server,nowait

鏈接qemu monitor

# tcp能夠經過telnet進行鏈接,方法以下
> telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{"QMP": {"version": {"qemu": {"micro": 0, "minor": 12, "major": 2}, "package": "qemu-kvm-ev-2.12.0-18.el7_6.1.1"}, "capabilities": []}}

# unix socket能夠經過nc -U進行鏈接,方法以下
> nc -U qmp.socket
{"QMP": {"version": {"qemu": {"micro": 0, "minor": 12, "major": 2}, "package": "qemu-kvm-ev-2.12.0-18.el7_6.1.1"}, "capabilities": []}}

按照上面執行完命令後,不會退出而是繼續等待輸入,但這個時候還沒法使用,接着,須要輸入一條qmp指令才能夠

{ "execute" : "qmp_capabilities" }

此時屏幕會輸出如下內容,表示從"capabilities negotiation模式"進入了"command"模式

{"return": {}}

接下來,就能夠執行qmp的指令了,qmp指令很是多,因爲篇幅有限,這裏僅舉幾個例子(更多內容請參考官方文檔,本文最後附上網址)

# 查看支持哪些qmp指令
{ "execute": "query-commands" }

# 虛擬機狀態
{ "execute": "query-status" }

# 虛擬機暫停
{ "execute": "stop" }

# 磁盤查看
{ "execute": "query-block" }

# 磁盤在線插入
{ "execute": "blockdev-add", "arguments": { "driver": "qcow2", "node-name": "drive-virtio-disk1", "file": { "driver": "file", "filename": "/opt/data.qcow2" } } }
{ "execute": "device_add", "arguments": { "driver": "virtio-blk-pci", "drive": "drive-virtio-disk1" } }

# 磁盤完整備份
{ "execute" : "drive-backup" , "arguments" : { "device" : "drive-virtio-disk0" , "sync" : "full" , "target" : "/opt/backuptest/fullbackup.img" } }

除了使用telnet、nc從外部鏈接,還能夠在qemu啓動時候進入一個交互的cli界面,直接輸入指令,只不過這個時候輸入的是hmp(human monitor protocol),而不是qmp。hmp簡化了qmp的使用,但實際在底層依然是轉化爲qmp進行操做的,配置方法以下

/usr/libexec/qemu-kvm -qmp tcp:127.0.0.1:4444,server,nowait -monitor stdio

此時會出現交互界面,輸入help,就能夠看到hmp支持的全部命令

(qemu) help

使用hmp不須要輸入相似qmp的{ "execute" : "qmp_capabilities" }

這裏列出幾個範例

# 直接輸入info回車,能夠看到全部查詢類的指令使用方法
(qemu) info

# 查看塊設備
(qemu) info block

# 在線增長磁盤
(qemu) drive_add 0 file=/opt/data.qcow2,format=qcow2,id=drive-virtio-disk1,if=none
(qemu) device_add virtio-blk-pci,scsi=off,drive=drive-virtio-disk1

經過libvirt啓動qemu,啓用QMP

有2種方法:

1. xml裏不作任何額外配置,默認就會啓用QMP,但經過這種方法啓用的QMP,只能經過libvirt接口(好比virsh命令或libvirt api)來進行QMP指令的輸入,而不能經過telnet、nc之類的,由於默認啓用的QMP,只會生成unix socket(位於/var/lib/libvirt/qemu/domain-xx-DOMAIN/monitor.sock),而該socket被libvirtd始終鏈接佔用着。此時經過ps aux命令能夠看到qemu進程參數,和以前有點不太同樣,不是-qmp,而是以下

-chardev socket,id=charmonitor,fd=36,server,nowait \
-mon chardev=charmonitor,id=monitor,mode=control

qemu命令參數支持2種方法配置qmp,即-qmp和-mon

這裏經過virsh作個簡單示範

virsh qemu-monitor-command DOMAIN --pretty '{ "execute": "query-block" }'

使用--pretty是爲了讓json的輸出具備換行縮進的格式化效果,而不是打印在一行裏
不須要在執行其餘指令前執行{ "execute" : "qmp_capabilities" }

2. 在xml裏額外增長2段配置,注意看下面這個xml的第一行,須要增長一個xmlns:qemu,另外在<domain>裏增長<qemu:command>

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  ...
  <devices>
    ...
  </devices>
  <qemu:commandline>
    <qemu:arg value='-qmp'/>
    <qemu:arg value='unix:/tmp/qmp-sock,server,nowait'/>
  </qemu:commandline>
</domain>

接着經過libvirt啓動qemu(好比virsh start xxx),就建立了2個qmp通道,一個是libvirt默認建立的,能夠依然使用libvirt接口來執行QMP指令,另外一個就是自定義的qmp,能夠經過上面提到的nc來使用

nc -U /tmp/qmp-sock

libvirt也支持hmp:

virsh qemu-monitor-command DOMAIN --hmp 'info block'

qemu-guest-agent(qemu-ga)

經過qmp還能夠對虛擬機內的操做系統進行RPC操做,其原理是:

1. 先在xml裏配置channel段,而後啓動虛擬機,會在宿主機上生成一個unix socket,同時在vm裏生成一個字符設備,生成的unix socket和字符設備能夠理解爲一個channel隧道的兩端
2. 虛擬機裏要啓動qemu-guest-agent守護進程,該守護進程會監聽字符設備
3. 而後能夠在宿主機上將虛擬機裏的qemu-guest-agent所支持的RPC指令通過channel發送到虛擬機裏,虛擬機裏的qemu-guest-agent從字符設備收到數據後,執行指令,好比讀寫文件、修改密碼等等

若要使用qemu-guest-agent須要知足如下條件

1. xml裏配置channel,範例:

<domain type='kvm'>
  ...
  <devices>
    ...
    <channel type='unix'>
      <source mode='bind' path='/tmp/channel.sock'/>
      <target type='virtio' name='org.qemu.guest_agent.0'/>
    </channel>
  </devices>
</domain>

注意,path能夠自定義,但name須要保持org.qemu.guest_agent.0,由於這會影響虛擬機裏字符設備的文件名,而虛擬機裏的qemu-guest-agent服務默認讀取的是對應org.qemu.guest_agent.0的字符設備,若是改了name,那麼qemu-guest-agent的配置文件也要跟着改,改爲對應name的路徑

2. 虛擬機內的操做系統內核須要支持(linux、windows均支持)

3. 虛擬機裏要安裝並啓動qemu-ga的服務(好比centos能夠yum install qemu-ga && systemctl start qemu-guest-agent,windows經過導入virtio-win的iso,該iso裏包含有qemu-ga程序)

當按照上述配置好後,能夠在宿主機上進行RPC操做

# 測試虛擬機裏的qemu-guest-agent是否可用
virsh qemu-agent-command DOMAIN --pretty '{ "execute": "guest-ping" }'

# 查看支持的qemu-guest-agent指令
virsh qemu-agent-command DOMAIN --pretty '{ "execute": "guest-info" }'

# 得到網卡信息
virsh qemu-agent-command DOMAIN --pretty '{ "execute": "guest-network-get-interfaces" }'

# 執行命令,這是異步的,第一步會返回一個pid,假設爲797,在第二步須要帶上這個pid
virsh qemu-agent-command DOMAIN --pretty '{ "execute": "guest-exec", "arguments": { "path": "ip", "arg": [ "addr", "list" ], "capture-output": true } }'
virsh qemu-agent-command DOMAIN --pretty '{ "execute": "guest-exec-status", "arguments": { "pid": 797 } }'

qemu-guest-agent不支持hmp調用

虛擬機裏的/etc/sysconfig/qemu-ga內容中的BLACKLIST_RPC參數能夠配置禁止哪些指令

官方參考文檔

# qemu
https://qemu.weilnetz.de/doc/qemu-doc.html

# qmp
https://qemu.weilnetz.de/doc/qemu-qmp-ref.html

# qemu-guest-agent
https://qemu.weilnetz.de/doc/qemu-ga-ref.html
相關文章
相關標籤/搜索