QGA是一个运行在虚拟机内部的普通应用程序(可执行文件名称默认为qemu-ga,服务名称默认为qemu-guest-agent),其目的是实现一种宿主机和虚拟机进行交互的方式,这种方式不依赖于网络,而是依赖于virtio-serial(默认首选方式)或者isa-serial,而qemu则提供了串口设备的模拟及数据交换的通道,最终呈现出来的是一个串口设备(虚拟机内部)和一个unix socket文件(宿主机上)
QGA通过读写串口设备与宿主机上的socket通道进行交互,宿主机上可以使用普通的unix socket读写方式对socket文件进行读写,最终实现与qga的交互,交互的协议与qmp(qemu monitor protocol)相同(简单来说就是使用json格式进行数据交换),串口设备的速率通常比较低,所以比较适合小数据量的交换。
下面介绍如何利用libvirt的xml文件在虚拟机内增加virtio-serial的串口设备
1)在虚机的配置文件中增加以下内容:
<channel type='unix'>
<source mode='bind' path='/var/lib/libvirt/qemu/test.agent'/>
<target type='virtio' name='org.qemu.guest_agent_test.0'/>
</channel>
重新定义并启动虚拟机,这样会在host上创建一个/var/lib/libvirt/qemu/test.agent的socket文件,而在guest上会在/dev/virtio-ports目录下创建一个名字为org.qemu.guest_agent_test.0的窗口设备
2)guest上安装qemu-guest-agent:
yum install qemu-guest-agent
3)通过qemu-ga命令打开虚拟机上的串口设备:
qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent_test.0
4)宿主机使用socat建立连接:
socat /var/lib/libvirt/qemu/test.agent readline
5)此时就可以在host上发送命令给guest,并让guest按照定义去响应相应的函数:
{"execute": "guest-get-vcpus"}
{"return": [{"online": true, "can-offline": false, "logical-id": 0}, {"online": true, "can-offline": true, "logical-id": 1}]}
我再执行: virsh setvpuc test 4 --live之后重新执行
{"execute": "guest-get-vcpus"}
{"return": [{"online": true, "can-offline": false, "logical-id": 0}, {"online": true, "can-offline": true, "logical-id": 1}, {"online": false, "can-offline": true, "logical-id": 2}, {"online": false, "can-offline": true, "logical-id": 3}]}
可以看到通过在host上执行qga的命令就可以得到guest的信息
6)功能扩展方式:
qga功能扩展十分方便,只需要在qapi-schema.json文件中定义好功能名称、输入输出数据类型,然后在commands-posix.c里面增加对应的功能函数即可,下面的补丁即在qga中增加一個通过statvfs获取虚拟机磁盘空间信息的功能:
diff --git a/qga/commands-posix.c b/qga/commands-posix.c index e199738..2f42a2f 100644 a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -21,6 +21,7 @@ #include <stdio.h> #include <string.h> #include <sys/stat.h> +#include <sys/statvfs.h> #include <inttypes.h> #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" @@ -1467,6 +1468,36 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) } #endif +GuestFileSystemStatistics *qmp_guest_get_statvfs(const char *path, Error **errp) +{ + int ret; + GuestFileSystemStatistics *fs_stat; + struct statvfs *buf; + buf = g_malloc0(sizeof(struct statvfs)); + + + ret = statvfs(path, buf); + if (ret < 0) { + error_setg_errno(errp, errno, "Failed to get statvfs"); + return NULL; + } + + fs_stat = g_malloc0(sizeof(GuestFileSystemStatistics)); + fs_stat->f_bsize = buf->f_bsize; + fs_stat->f_frsize = buf->f_frsize; + fs_stat->f_blocks = buf->f_blocks; + fs_stat->f_bfree = buf->f_bfree; + fs_stat->f_bavail = buf->f_bavail; + fs_stat->f_files = buf->f_files; + fs_stat->f_ffree = buf->f_ffree; + fs_stat->f_favail = buf->f_favail; + fs_stat->f_fsid = buf->f_fsid; + fs_stat->f_flag = buf->f_flag; + fs_stat->f_namemax = buf->f_namemax; + + return fs_stat; +} + /* register init/cleanup routines for stateful command groups */ void ga_command_state_init(GAState *s, GACommandState *cs) { diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 7155b7a..a071c3f 100644 a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -638,3 +638,52 @@ { 'command': 'guest-set-vcpus', 'data': {'vcpus': ['GuestLogicalProcessor'] }, 'returns': 'int' } + +## +# @GuestFileSystemStatistics: +# +# Information about guest file system statistics. +# +# @f_bsize: file system block size. +# +# @f_frsize: fragment size. +# +# @f_blocks: size of fs in f_frsize units. +# +# @f_bfree: free blocks. +# +# @f_bavail: free blocks for non-root. +# +# @f_files: inodes. +# +# @f_ffree: free inodes. +# +# @f_favail: free inodes for non-root. +# +# @f_fsid: file system id. +# +# @f_flag: mount flags +# +# @f_namemax: maximum filename length. +# +# Since 1.5.10(NetEase) +## +{ 'type': 'GuestFileSystemStatistics', + 'data': { 'f_bsize': 'int', 'f_frsize': 'int', 'f_blocks': 'int', + 'f_bfree': 'int', 'f_bavail': 'int', 'f_files': 'int', + 'f_ffree': 'int', 'f_favail': 'int', 'f_fsid': 'int', + 'f_flag': 'int', 'f_namemax': 'int'} } + +## +# @guest-get-statvfs: +# +# Get the information about guest file system statistics by statvfs. +# +# Returns: @GuestFileSystemStatistics. +# +# Since 1.5.10(NetEase) +## +{ 'command': 'guest-get-statvfs', + 'data': { 'path': 'str' }, + 'returns': 'GuestFileSystemStatistics' } +
参考文章:
http://www.xlgps.com/article/420153.html