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


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

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

 

 

 

 

通過網絡連接到QEMU MONITO

http://smilejay.com/2014/01/access-qemu-monitor-accross-network/

 

qemu-system-aarch64  -name vm2 -daemonize \
  -enable-kvm -M virt -cpu host -smp 2 -m 4096 \
  -object memory-backend-file,id=mem,size=4096M,mem-path=/mnt/huge,share=on \
  -numa node,memdev=mem -mem-prealloc \
  -global virtio-blk-device.scsi=off \
  -device virtio-scsi-device,id=scsi \
  -kernel vmlinuz-4.18 --append "console=ttyAMA0  root=UUID=6a09973e-e8fd-4a6d-a8c0-1deb9556f477 iommu=pt intel_iommu=on iommu.passthrough=1" \
  -initrd initramfs-4.18 \
 -drive file=vhuser-test1.qcow2  \
 -device vfio-pci,host=0000:05:00.0 \
 -net nic,macaddr=00:00:00:99:99:01 \
 -monitor telnet:localhost:4321,server,nowait\ -vnc :10

 

 

 

 

system_powerdown不能關機,quit可以關機
[root@localhost cloud_images]# telnet localhost 4321
Trying ::1...
Connected to localhost.
Escape character is '^]'.
QEMU 5.1.90 monitor - type 'help' for more information
(qemu) system_powerdown
(qemu) quit
Connection closed by foreign host.
[root@localhost cloud_images]# 

 

 

 關機命令

{ "execute": "stop" }

[root@localhost cloud_images]# telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{"QMP": {"version": {"qemu": {"micro": 90, "minor": 1, "major": 5}, "package": "v5.2.0-rc0-dirty"}, "capabilities": ["oob"]}}
ifo^H^H
{"error": {"class": "GenericError", "desc": "JSON parse error, invalid keyword 'ifo'"}}
{"error": {"class": "GenericError", "desc": "JSON parse error, stray '\b'"}}
{"error": {"class": "GenericError", "desc": "JSON parse error, stray '\b'"}}
info
{"error": {"class": "GenericError", "desc": "JSON parse error, invalid keyword 'info'"}}


qmp_system_powerdown
{"error": {"class": "GenericError", "desc": "JSON parse error, invalid keyword 'qmp'"}}
{"error": {"class": "GenericError", "desc": "JSON parse error, stray '_'"}}

^]
telnet>
^]
telnet> qmp_system_powerdown
?Invalid command
telnet> ^[[A^H^H
?Invalid command
telnet> shutdown
?Invalid command
telnet> powerwo^H^H
?Invalid command
telnet> powerdown
?Invalid command
telnet> quit
Connection closed.
[root@localhost cloud_images]# telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{"QMP": {"version": {"qemu": {"micro": 90, "minor": 1, "major": 5}, "package": "v5.2.0-rc0-dirty"}, "capabilities": ["oob"]}}
{ "execute": "stop" }
Connection closed by foreign host.
[root@localhost cloud_images]#

 

 

 

[root@localhost binary]# nc -U qmp.sock
{"QMP": {"version": {"qemu": {"micro": 90, "minor": 1, "major": 5}, "package": "v5.2.0-rc0-dirty"}, "capabilities": ["oob"]}}
{ "execute": "stop" }
Ncat: Connection reset by peer.
[root@localhost binary]#

 

 

1. QEMU monitor支持遠程telnet訪問:

 

關於這里-monitor的選項,做如下說明:


通過telnet連接到遠程的QEMU monitor上:

 

2. QEMU monitor支持RAW socket的遠程訪問:

 

可以使用netcat去連接這個socket:

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" } }

 


免責聲明!

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



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