1. 程式人生 > 實用技巧 >基於QMP實現對qemu虛擬機器進行互動

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

https://cloud.tencent.com/developer/article/1468105

qemu) "ctrl+]" to return to telnet, (qemu)"quit" to exit qemu applicatoin.

QMP介紹

qemu對外提供了一個socket介面,稱為qemu monitor,通過該介面,可以對虛擬機器例項的整個生命週期進行管理,主要有如下功能

▷ 狀態檢視、變更

▷ 裝置檢視、變更

▷ 效能檢視、限制

▷ 線上遷移

▷ 資料備份

▷ 訪問內部作業系統

通過該socket介面傳遞互動的協議是qmp,全稱是qemu monitor protocol,這是基於json格式的協議

在繼續往下講之前,需要先了解qemu、kvm、libvirt之間的區別(因為有很多童鞋對這三者的理解是混亂的)

▷ qemu:虛擬機器模擬器。通過軟體模擬出cpu、記憶體、磁碟、主機板、網絡卡等裝置

▷ kvm:高效能的cpu模擬器。由於軟體模擬的cpu效能很差,因此出現了kvm,這是通過硬體與核心的支援實現接近native效能的cpu模擬器,可以理解為虛擬機器裡的cpu任務直接交給物理機cpu完成。

▷ libvirt:虛擬機器管理平臺。能納管qemu、lxc、esx等虛擬化軟體,通過編寫xml實現對虛擬機器、儲存、網路等進行配置和管理

單獨使用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" } }

進入command模式後,不僅能夠執行命令,還同時成為了事件的輸出埠,比如執行磁碟備份命令後,應該就會陸續接收到一些關於備份成功或失敗的事件,比如:

{ "execute" : "drive-backup" , "arguments" : { "device" : "drive-virtio-disk0" , "sync" : "top" ,"target" : "/opt/ccvm/A" } }
{"timestamp": {"seconds": 1551061368, "microseconds": 725212}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "drive-virtio-disk0"}}
{"timestamp": {"seconds": 1551061368, "microseconds": 725330}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "drive-virtio-disk0"}}
{"return": {}}
{"timestamp": {"seconds": 1551061373, "microseconds": 276382}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "drive-virtio-disk0"}}
{"timestamp": {"seconds": 1551061373, "microseconds": 276462}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "drive-virtio-disk0"}}
{"timestamp": {"seconds": 1551061373, "microseconds": 276508}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drive-virtio-disk0", "len": 21474836480, "offset": 11141120, "speed": 0, "type": "backup"}}
{"timestamp": {"seconds": 1551061373, "microseconds": 276551}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "drive-virtio-disk0"}}
{"timestamp": {"seconds": 1551061373, "microseconds": 276583}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "drive-virtio-disk0"}}

上面第一行是執行命令,接下來的就是陸續接收到的事件,這與linux的tty終端很像 接收到的事件不僅是本視窗命令執行的相關事件,而是會收到所有qmp事件,比如開了多個qmp監聽器,那麼只要監聽器進入command模式,就都會同時接收到事件(下面還提到了libvirt啟動qmp,也是一樣的效果)

除了使用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

還有一種脫褲子放屁的hmp寫法,是將hmp套在qmp裡,

{
  "execute" : "human-monitor-command",
  "arguments" : {
      "command-line" : "這裡寫hmp語法"
  }
}

比如

{
  "execute" : "human-monitor-command",
  "arguments" : {
      "command-line" : "drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=xxxx,file.port=xxxx,file.export=colo1,node-name=nbd_client1"
  }
}