qemu-guest-agent詳解

流年的夏天發表於2020-06-16

qemu guest agent簡稱qga, 是執行在虛擬機器內部的一個守護程式(qemu-guest-agent.service),他可以管理應用程式,執行宿主機發出的命令。

QEMU為宿主機和虛擬機器提供了一個資料通道(channel,這個通道的兩端分別是在虛擬機器內看到的串列埠和在宿主機上看到的unix socket檔案。

   

宿主機與虛擬機器內的qga通訊就擴充套件了對虛擬機器的控制能力,例如在宿主機上獲取虛擬機器的ip地址等。

   

libvrit提供了專門的 virDomainQemuAgentCommand API對應virsh qemu-agent-command命令)來和qemu-guest-agent通訊,

另外有些libvirt內建api也可以支援qga,例如rebootshutdown等。

   

下面的實踐分為兩種方式,虛擬機器的channeltargetname使用org.qemu.guest_agent.0不是用org.qemu.guest_agent.0

兩種方式在libvirt和宿主機中的qemu-guest-agent中都有所不同。

   

【使用org.qemu.guest_agent.0

宿主機上libvirt的虛擬機器xml配置channel

<channel type='unix'>

  <source mode='bind' path='/var/lib/libvirt/qemu/org.qemu.guest_agent.0'/>

  <target type='virtio' name='org.qemu.guest_agent.0'/>

</channel>

   

注意這裡targetname要使用org.qemu.guest_agent.0

   

虛擬機器內部:

yum install qemu-guest-agent

setenforce 0

systemctl restart qemu-guest-agent.service

   

在宿主機上測試功能:

virsh
virsh # qemu-agent-command centos '{"execute":"guest-info"}'

virsh # qemu-agent-command centos '{"execute":"guest-network-get-interfaces"}'

virsh # reboot --mode agent centos

   

上面的命令直接讀出了虛擬機器中的ip地址資訊。

   

【不使用org.qemu.guest_agent.0

如果在宿主機上libvirtxml配置channeltargetname不是org.qemu.guest_agent.0,例如下面的org.qemu.guest_agent.1

   

那麼在宿主機上的libvirt將不會建立與socket建立連線。在虛擬機器上qemu-guest-agent服務也無法執行。

   

宿主機上的libvirtxml

<channel type='unix'>

  <source mode='bind' path='/var/lib/libvirt/qemu/org.qemu.guest_agent.1'/>

  <target type='virtio' name='org.qemu.guest_agent.1'/>

</channel>

   

不使用org.qemu.guest_agent.0的情況下怎麼處理呢?

   

首先,在虛擬機器內部通訊串列埠的名字變為了org.qemu.guest_agent.1,此時需要手動修改/lib/systemd/system/qemu-guest-agent.service檔案,把所有的預設org.qemu.guest_agent.0改為使用者配置的名字org.qemu.guest_agent.1

   

其次,在宿主機上自己去連線socket檔案:

[root@node2 ~]# socat unix-connect:/var/lib/libvirt/qemu/org.qemu.guest_agent.1 readline

{"execute": "guest-info"}

   

【功能簡單介紹】

注:帶* 指的是win也支援

guest-sync-delimited*

宿主機傳送一個int數字給qgaqga返回這個數字,並且在後續返回字串響應中加入ascii碼為0xff的字元,
其作用是檢查宿主機與qga通訊的同步狀態,主要用在宿主機上多客戶端與qga通訊的情況下客戶端間切換過程的狀態同步檢查
比如有兩個客戶端ABqga傳送給A的響應,由於A已經退出,目前B連線到qgasocket,所以這個響應可能被B收到,如果B連線到socket之後,立即傳送該請求給qga,響應中加入了這個同步碼就能區分是A的響應還是B的響應;
qga返回宿主機客戶端傳送的int數字之前,qga返回的所有響應都要忽略。

guest-sync*

與上面相同,只是不在響應中加入0xff字元

guest-ping*

Ping the guest agent, a non-error return implies success

guest-get-time*

獲取虛擬機器時間(返回值為相對於1970-01-01 in UTCTime in nanoseconds.

guest-set-time*

設定虛擬機器時間(輸入為相對於1970-01-01 in UTCTime in nanoseconds.

guest-info*

返回qga支援的所有命令

guest-shutdown*

關閉虛擬機器(支援haltpowerdownreboot,預設動作為powerdown

guest-file-open

開啟虛擬機器內的某個檔案(返回檔案控制程式碼)

guest-file-close

關閉開啟的虛擬機器內的檔案

guest-file-read

根據檔案控制程式碼讀取虛擬機器內的檔案內容(返回base64格式的檔案內容)

guest-file-write

根據檔案控制程式碼寫入檔案內容到虛擬機器內的檔案

……