在虚拟化中,必然存在宿主机与虚拟机通信的需要。一般来说,可以通过网桥的方式与虚拟机建立通信通道,通过网络传输数据,适用性比较强。但是,这种方式依赖于网络通畅,当虚拟机发生某些故障,网络已经发生问题,宿主机就需要另外一种方式与虚拟机建立通信通道了。经常使用VMWare的同学都知道Mware Tools,这个工具安装在虚拟机内部,可以实现宿主机与虚拟机的通信。
什么是QEMU Guest Agent
对于QEMU/KVM 来说,也有这么一款工具叫做QEMU Guest Agent。
QEMU Guest Agent(下简称:QGA)是一个运行在虚拟机内部的普通应用程序(可执行文件名称默认为qemu-ga,服务名称默认为qemu-guest-agent),是一种宿主机与虚拟机的交互方式。QGA依赖于virtio-serial或者isa-serial,不依赖于网络,在虚拟机内部是一个串口设备,在宿主机上是一个unix socket文件,在宿主机上使用普通的unix socket读写方式写入命令,虚拟机里读写串口设备与宿主机交互(qemu-ga监听改设备,有命令进来,就开始分析、执行)。QGA的交互协议是qmp(qemu monitor protocol)协议,其实就是使用json格式交换数据。串口设备的速率通常比较低,所以比较适合小数据量的交换。
QGA的使用方法
环境如下:
宿主机:
系统版本:CentOS Linux release 7.1.1503
virsh版本:libvirt 1.2.17、QEMU 2.6.0
虚拟机:
系统版本:CentOS Linux release 7.1.1503
QGA版本(QEMU版本):2.7.1 release
准备虚拟机:
具体请参考前期文章:
《江博士带你轻松搞定KVM虚拟化》http://mp.weixin.qq.com/s/auW_c4Z_-mgoiZl7EmhAZg
使用virsh命令创建虚拟机。简单步骤如下:
创建虚拟机配置文件centos.xml,并在<devices>下添加QGA配置项:
<devices> … <channel type='unix'> <source mode='bind' path='/var/centos7-1.0'/> <target type='virtio' name='org.qemu.guest_agent.0'/> <address type='virtio-serial' controller='0' bus='0' port='1'/> </channel> … </devices>
其中,source -> path可以自己指定路径及名称,这个就是宿主机上的unix socket文件;target -> name 要与虚拟机内QGA设备相同,默认是org.qemu.guest_agent.0。
创建虚拟机
virsh create centos.xml
在source -> path 目录下可以看到对应的socket文件。
在虚拟机内安装QGA
使用yum安装QGA
如果只使用QGA默认功能,不进行扩展的话,可以直接使用yum安装:
yum install qemu-guest-agent
由于本机yum源没有最新版的QGA,安装的是2.5.0版本,如果需要最新版或者需要扩展功能请参考本文2.2.2 编译安装内容。
使用源码编译安装QGA
下载QGA源文件
如果需要扩展QGA,需要下载源码,修改后编译安装:
下载QGA源码并解压到/home/qemu-2.7.1 (不要纠结这个路径…)。
git clone git://git.qemu-project.org/qemu.git git克隆代码。 或 http://wiki.qemu-project.org/download/qemu-2.7.1.tar.bz2 下载tar.bz2源码包。
说明:
QGA是QEMU的一个模块,官方没有单独的QGA源码,下载QEMU源码,可以单独编译QGA模块。如果只是用QGA的话,可自行精简源码。
编译安装:
# 进入qemu目录 cd /home/qemu-2.7.1 # 在configure阶段可能出现缺少依赖项问题,根据提示安装对应的依赖项即可。 ./configure
# 只编译 安装 qemu-ga make qemu-ga make install qemu-ga
运行及使用QGA:
宿主机使用socat建立连接:
socat /var/centos7-1.0 readline
通过qemu-ga命令打开虚拟机上的串口设备:
qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0
前文说过QGA在虚拟机里是一个设备,宿主机发送的命令会自动写入到该设备中缓存,linux中设备也是个文件,所以这个org.qemu.guest_agent.0也可以用vim打开,查看宿主机命令是否写入。另外,虚拟机里的QGA设备的文件名org.qemu.guest_agent.0是在配置文件xml中devices -> target -> name定义的。具体的qga路径信息可以使用命令qemu-ga –D 查看。
在宿主机上发送命令给虚拟机执行:
使用json格式给虚拟机发送命令。
下图是发送了两个QGA默认提供的两条命令,及返回内容的截图。
扩展QGA功能
本文第2章介绍了如何安装使用QGA,实际上,QGA默认提供的功能(命令)并不能满足我们,这时我们就需要根据需求修改QGA源码,添加相应的功能,然后重新编译运行。
QGA功能扩展比较方便,共需要操作三个文件:
/qemu-2.7.1/qga/qapi-schema.json /qemu-2.7.1/qga/ qapi-generated/qga-qmp-commands.h /qemu-2.7.1/qga/ commands-posix.c
在qapi-schema.json文件中,定义功能(命令)名称、输入输出数据类型即可,格式参考自带功能(命令);在qga-qmp-commands.h文件中,添加对应的函数声明;在commands-posix.c文件中,添加对应的功能函数即可。
下面的示例添加一个功能(命令),宿主机使用QGA方式将字符串写入虚拟机中的文件中。具体步骤,咱们一步一步的来!
首先,在qapi-schema.json文件中,定义功能(命令)名称、输入输出数据类型即可,格式参考自带功能(命令):
如下图所示:
参考自带的命令格式,添加我们自定义的功能(命令)。
先定义返回值类型。
本文使用QGA版本已经不允许使用內建数据类型作为返回值类型了,所以我们先定义一个返回值的数据结构。
{ 'struct': 'TestRE', 'data': { 'code': 'int'} } 结构的名字是:TestRE 内容的key是code,值是int型。
再定义功能(命令)的输入输出。
{ 'command': 'guest-test', 'data': {'content':'str'}, 'returns': 'TestRE'} 命令的名字是:guest-test 输入数据的key是content,值是一个字符串。 输出数据是一个TestRE的结构,刚刚我们自己定义的。
然后,在qga-qmp-commands.h文件中,添加对应的函数声明,并在commands-posix.c文件中,添加对应的功能函数。
先在qga-qmp-commands.h添加函数声明。如下图:
TestRE *qmp_guest_test(const char *content, Error **errp);
为什么是这个名字,看下文!
在commands-posix.c添加函数体。如下图:
在文件尾添加:
TestRE *qmp_guest_test(const char *content, Error **errp) { FILE *fd; int ret = 0; fd = fopen("/var/test.txt", "a+"); printf("%s",content); if (fd){ ret = fprintf(fd, "%s\n", content ); } fclose(fd); TestRE *ge = NULL; // get 100 byte malloc ge = g_new0(TestRE, 100); ge->code = ret; return ge; }
说明:
定义指针函数,函数名与qapi-schema.json定义的功能(命令)名对应。以qmp_ 开头,把横线–改为下划线_,返回我们定义的返回类型即可。函数实现了一个简单的功能,把输入的字符串存到/var/test.txt中,返回存入文件的字符数。
好了,修改完毕!
保存后,重新编译:
make qemu-ga make install qemu-ga
运行(参考2.3):
宿主机使用socat建立连接:
socat /var/centos7-1.0 readline
通过qemu-ga命令打开虚拟机上的串口设备:
qemu-ga -m virtio-serial -p /dev/virtio-ports/org.qemu.guest_agent.0
结果如图:
在宿主机上发动了三条写字符串到虚拟机文件的命令,可以看到,虚拟机执行命令正确(写入了文件),返回值正确(返回写入文件的字符数)。
扩展成功!
qga通道
如图所示:
在宿主机中,将命令写入unix socket文件。
在虚拟机中,可以在QGA设备文件中读取到。
这就组成了宿主机到虚拟机间的QGA通道。
结语
本文简单介绍了QEMU Guest Agent的使用及扩展方法。通过在虚拟机内部预装qemu-ga,云平台对虚拟机的控制能力显著加强。但是,串口方式,速率较低,仅能进行小数据量的交换。各位看官,自取所需。在qga-qmp-commands.h文件中
如果您需要了解更多内容,可以
加入QQ群:570982169
直接询问:010-68438880