1.原理分析

qga是一个运行在虚拟机内部的普通应用程序(可执行文件名称默认为qemu-ga,服务名称默认为qemu-guest-agent),其目的是实现一种宿主机和虚拟机进行交互的方式,这种方式不依赖于网络,而是依赖于virtio-serial(默认首选方式)或者isa-serial,而QEMU则提供了串口设备的模拟及数据交换的通道,最终呈现出来的是一个串口设备(虚拟机内部)和一个unixsocket文件(宿主机上)。

qga通过读写串口设备与宿主机上的socket通道进行交互,宿主机上可以使用普通的unixsocket读写方式对socket文件进行读写,最终实现与qga的交互,交互的协议与qmp(QEMUMonitor Protocol)相同(简单来说就是使用JSON格式进行数据交换),串口设备的速率通常都较低,所以比较适合小数据量的交换。

QEMU virtio串口设备模拟参数:

/usr/bin/kvm(QEMU) \

……\

-device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \

-device isa-serial,chardev=charserial1,id=serial1 \

-chardevsocket,id=charchannel0,path=/var/lib/libvirt/qemu/test.agent,server,nowait\

-devicevirtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,\

name=com.163.spice.0

通过上面的参数就可以在宿主机上生成一个unixsocket文件,路径为:/var/lib/libvirt/qemu/test.agent,同时在虚拟机内部生成一个serial设备,名字为com.163.spice.0,设备路径为:/dev/vport0p1,映射出来的可读性比较好的路径为:/dev/virtio-ports/com.163.spice.0,可以在运行qga的时候通过-p参数指定读写这个设备。

Libvirt支持QEMU串口相关配置,所以上述参数已经可以通过libvirt进行配置,且更简单直观,配置方式如下:

<channeltype='unix'>

<sourcemode='bind' path='/var/lib/libvirt/qemu/test.agent'/>

<targettype='virtio' name='com.163.spice.0'/>

</channel>

需要注意的是libvirt-qemu:kvm用户要有权限读写'/var/lib/libvirt/qemu/test.agent'。

2.实现程度

2.1已有功能

目前qga最新版本为1.5.50,linux已经实现下面的所有功能,windows仅支持加*的那些功能:

  • 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*Pingthe guest agent, a non-error return implies success

  • guest-get-time*:获取虚拟机时间(返回值为相对于1970-01-01in UTCTimein nanoseconds.);

  • guest-set-time*:设置虚拟机时间(输入为相对于1970-01-01in UTCTimein nanoseconds.);

  • guest-info*:返回qga支持的所有命令;

  • guest-shutdown*:关闭虚拟机(支持haltpowerdownreboot,默认动作为powerdown);

  • guest-file-open:打开虚拟机内的某个文件(返回文件句柄);

  • guest-file-close:关闭打开的虚拟机内的文件;

  • guest-file-read:根据文件句柄读取虚拟机内的文件内容(返回base64格式的文件内容);

  • guest-file-write:根据文件句柄写入文件内容到虚拟机内的文件;

  • guest-file-seekSeekto a position in the file, as with fseek(), and return the currentfile position afterward. Also encapsulates ftell()'s functionality,just Set offset=0, whence=SEEK_CUR

  • guest-file-flushWritefile changes bufferred in userspace to disk/kernel buffers

  • guest-fsfreeze-statusGetguest fsfreeze state. error state indicates

  • guest-fsfreeze-freezeSyncand freeze all freezable, local guest filesystems

  • guest-fsfreeze-thawUnfreezeall frozen guest filesystems

  • guest-fstrimDiscard(or "trim") blocks which are not in use by the filesystem

  • guest-suspend-disk*Suspendguest to disk

  • guest-suspend-ram*Suspendguest to ram

  • guest-suspend-hybridSaveguest state to disk and suspend to ramThiscommand requires the pm-utils package to be installed in theguest.);

  • guest-network-get-interfacesGetlist of guest IP addresses, MAC addresses and netmasks

  • guest-get-vcpusRetrievethe list of the guest's logical processors

  • guest-set-vcpus:Attemptto reconfigure (currently: enable/disable) logical processors insidethe guest。

2.2功能扩展方式

qga功能扩展十分方便,只需要在qapi-schema.json文件中定义好功能名称、输入输出数据类型,然后在commands-posix.c里面增加对应的功能函数即可,下面的补丁即在qga中增加一个通过statvfs获取虚拟机磁盘空间信息的功能:

diff--git a/qga/commands-posix.c b/qga/commands-posix.c

indexe199738..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_tminimum, 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 */

voidga_command_state_init(GAState *s, GACommandState *cs)

{

diff--git a/qga/qapi-schema.json b/qga/qapi-schema.json

index7155b7a..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' }

+

中间复杂的类型定义代码,以及头文件包含关系处理都由一个python脚本在编译的时候动态生成出来,这对开发人员来说是非常方便的,开发人员在扩展功能的时候只需要关注输入、输出的数据类型,以及功能的函数内容即可。

3.社区活跃度

QEMU社区从2011年7月20号开始在QEMU代码仓库中增加qga功能,代码维护人员主要来自redhat和IBM,社区的活跃度不高,但是QEMU本身的提交记录从2003年至今已有27200多条,还是比较活跃的,qga的功能及代码都比较简单,也是活跃度不高的一个重要原因。

QEMU代码仓库地址:gitclone git://git.qemu-project.org/qemu.git

qga代码位于QEMU代码的根目录下的qga目录中。

4.利用qemu-guest-agent实现监控方案

4.1监控方案现状

目前云主机监控的实现方法是,在创建云主机的过程中,增加监控脚本及其配置文件、定时任务及监控信息推送配置文件的注入过程,包括四个文件,其中监控信息推送配置文件(/etc/vm_monitor/info)由管理平台根据云主机所属用户的注册信息以及监控平台相关配置生成,并传入创建云主机的API来实现文件的注入,监控脚本(/etc/vm_monitor/send_monitor_data.py)及其配置文件(/etc/vm_monitor/monitor_settings.xml)、定时任务文件(/etc/cron.d/inject_cron_job)是包含在NVS经过base64编码后的监控脚本文件inject_files.json中。

工作模式为,在root账户增加定时任务inject_cron_job,其中有一条任务为:rootsu -c 'python /etc/vm_monitor/send_monitor_data.py' > /dev/null2>&1,也即每60s收集并推送一次监控信息给监控平台。

4.2当前方案存在的问题

  • 依赖云主机内部的python解释器

  • 云主机必须存在root账户

  • 依赖NVS文件注入功能;并且为了注入这些监控文件对nova的改动也比较大,也无法与社区同步;windows镜像也会注入这些无用的文件,可能导致一些意想不到的问题;另外如果有的镜像的操作系统不在第一个分区上,则注入的监控文件会失效

  • 已经运行的云主机内部的监控相关文件更新困难,导致新监控项的添加、推送周期、推送地址等的修改也比较困难,灵活性较差

  • Nova中base64编码的注入脚本的代码可读性很差,代码更新及维护困难

  • 定位问题一般都需要登录到云主机内部进行,对于采用密钥对登录的云主机来说定位问题比较困难

4.3采用qga方式的监控方案

首先为每个云主机增加virtio-serial的配置,这个只需要修改生成libvirt配置文件的代码即可,并且应该可以提交给社区;其次需要在虚拟机内部安装qga服务;最后需要在宿主机上新增一个服务进程(这里暂定为monitor服务),用来通过与qga交互从云主机内部获取监控信息;总的模块交互流程如下:

云主机创建流程中的监控相关操作流程图

monitor服务单次监控信息获取及推送流程如下:

单次监控数据获取及推送流程图

4.4采用qga方式需要做的工作

  • 需要扩展qga的功能,增加获取文件系统信息的功能

  • 为qga打包的相关工作

  • 需要重构监控信息获取脚本,把读本地/proc目录相关文件改为通过qga读文件

  • 计算节点新增monitor服务

  • nova代码修改,包括新增virtio-serial配置生成流程以及去掉原有的监控文件注入流程

  • 已有镜像需要更新,安装qga

4.5qga方式存在的问题

  • 与当前方案的兼容性问题:已创建的云主机仍然采用原有的监控方式进行数据推送,新创建的云主机则采用qga方式进行监控数据的推送(可以通过检查宿主机上没有socket文件来区分新创建还是已有云主机);监控项保持不变;

  • qga升级问题:除非需要增加读取云主机内部相关文件不能获取到相关信息的监控项,否则不需要特别对qga进行升级;如果确实需要升级,可以在云主机内部配置包含新版本qga的apt相关源,通过apt方式进行升级;

  • 监控项扩展问题:在不需要对qga进行升级的情况下,只需要升级monitor服务即可(已有云主机也不需要改动);如果需要同时升级qga(这种情况比较麻烦,如果不升级qga则新的监控项无法推送);

  • 安全问题:主要包括暴露在计算节点的socket文件以及暴露在云主机内部的virtio-serial,这两个文件或设备的安全性问题;外部的socket文件与云主机镜像文件类似,都是有权限控制的,普通用户无法访问;云主机内部的virtio-serial设备可能会被用户攻击,但由于其速率较低,所以对宿主机影响不大,主要的问题可能是用户会伪造监控文件,然后通过virtio-serial设备返回给monitor服务,导致报警异常,之前的监控文件注入方式比qga方式在这一问题上更严重,因为监控完全是通过注入的脚本在云主机内部获取并推送的,用户可以做任何修改,所以这个问题也应该不是问题;

  • 用户隐私保护问题:用户可能会担心我们使用qga获取云主机内部的某些敏感文件,但这个问题其实在云计算环境是无法完全避免的,即使不通过qga,我们也可以通过拷贝云主机镜像并重新创建新的云主机的方式获取云主机内部的任意文件,所以这应该也不是问题;

4.6类似agent比较

ovirt-guest-agent

该agent的原理与qga完全相同,是redhat公司为自己的OVirt虚拟化管理平台开发的与虚拟机交互的方案,与qga不同之处在于redhat采用了python作为其guestagent的开发语言,其支持的协议也是基于JSON格式的,并且它支持部分windows系统。其支持的功能列表可以在其主页查看到:http://www.ovirt.org/Guest_Agent。

参考:http://git.qemu.org/?p=qemu.git;a=blob;f=qga/qapi-schema.json;h=7155b7ab55fc4ef5336fd771ca06905c485fad62;hb=refs/heads/master

http://git.qemu.org/?p=qemu.git;a=commitdiff;h=6912e6a94cb0a1d650271103efbc3ac2299e4fd0

http://wiki.qemu.org/Features/QAPI/GuestAgent

http://wiki.libvirt.org/page/Qemu_guest_agent

http://www.cnblogs.com/biangbiang/p/3222458.html

qemu-guest-agent调研相关推荐

  1. QEMU — Guest Agent

    目录 文章目录 目录 QEMU Guest Agent 安装 QGA QGA 接口 利用 QGA 的 OpenStack 云主机监控方案 QEMU Guest Agent QEMU Guest Age ...

  2. Qemu Guest Agent方式实现libvirt与虚机交互

    一.qga简介 1.qga工具 qemu guest agent,简称qga,是一个运行在虚拟机内部的普通应用程序,可实现宿主机libvirt和虚拟机的通信,宿主机可通过向虚机中的qga发送命令控制虚 ...

  3. 虚拟化kvm - 创建虚拟机、virtio、QEMU Guest Agent

    文章目录 写在开头的话 创建虚拟机.virtio.QEMU Guest Agent 00. 使用virt-manager创建虚拟机 0.1 实验的环境准备 01. 使用virt-install创建虚拟 ...

  4. QEMU Guest Agent安装(内网环境)

    1.在pve管理界面配置虚拟机 - 2.配置PVE后,并确保网卡配置为virtio:开始安装qemu-guest-agent qemu-guest-agent下载地址: rpm -ivh qemu-g ...

  5. qeum guest agent详解

    qemu guest agent简称qga, 是运行在虚拟机内部的一个守护程序(qemu-guest-agent.service),他可以管理应用程序,执行宿主机发出的命令. QEMU为宿主机和虚拟机 ...

  6. ovirt guest agent 安装

    ovirt guest agent 安装 CentOS 如何在CentOS中安装guest代理(CentOS7) # 通过终端使用YUM来安装oVirt Guest Tools sudo yum in ...

  7. QEMU guest与host通过网络通信——bridge/hostfwd/guestfwd

    一.开篇大前提 qemu虚拟机器默认是使用nat来上网的--By default(默认qemu就帮你做了), QEMU invokes the -nic and -user options to ad ...

  8. qemu monitor和qemu agent的实现

    虚拟机配置中: <channel type='unix'> <target type='virtio' name='org.qemu.guest_agent.0'/> < ...

  9. 【翻译】QEMU内部机制:顶层概览

    系列文章: [翻译]QEMU内部机制:宏观架构和线程模型 [翻译]QEMU内部机制:vhost的架构 [翻译]QEMU内部机制:顶层概览(本文) [翻译]QEMU内部机制:内存 原文地址:http:/ ...

  10. KVM 介绍(7):使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照 (Nova Instances Snapshot Libvirt)...

    学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...

最新文章

  1. 七招从办公室政治中取胜 发表于 09 May 2008 ? 领导力培养
  2. MySQL的单表索引优化案例
  3. 医疗卫生信息化 医学信息 医院管理 医疗信息化 资源下载
  4. python3的fft_科学网—用Python、Matlab、C实现傅立叶变换FFT() - 康建的博文
  5. C#中使用WeiFenLuo.WinFormsUI.Docking.dll实现窗口停靠效果
  6. php删除一张表数据的时候 把另一张表的数据也删除,剔除第一张表的数据时,修改第二张表的相关字段的数值...
  7. 微服务升级_SpringCloud Alibaba工作笔记0016---Nacos之服务提供者注册
  8. python爬虫有几种方法_python爬虫-----Python访问http的几种方式
  9. ins信息服务器,ins怎么登录服务器
  10. 简单C语言程序的编写,c语言编写简单程序.doc
  11. 单片机应用系统设计技术——多功能出租车计费器
  12. vue2项目封装百度地图3.0拾取坐标控件
  13. 计算机写字板英语,写字板的英文是什么
  14. 什么情况下,英文单词中的k发音变g,t发音变d,p发音变b
  15. 360与腾讯之争——顾客有可能成为上帝
  16. 计算机删除默认共享怎样操作,清除windows默认共享方法
  17. linux网络编程常用头文件总结
  18. 【一文读懂】python 中的 numpy.reshape(a, newshape, order=‘C‘) 详细说明及实例讲解
  19. 2020年wordpress主题开发视频教程、WP主题WP模板开发视频教程
  20. Python基础:第015课——弹跳的小球(优化版),条件语句和常量

热门文章

  1. ThinkPad笔记本电脑网络重置之后wifi没有了
  2. 依行科技日常实习面经
  3. 鲤——processing动画交互应用
  4. 网络信息检索(一)检索模型:布尔,向量,概率检索
  5. [转载]NFC问题分析
  6. 老哥,Java 中 final 和 effectively final 到底有什么区别?
  7. 达梦数据库基础篇--数据库管理工具
  8. 不是计算机布尔检索命令的是,在计算机信息检索中,用于组配检索词和限字检索范围的布尔逻辑运算符包括哪些?...
  9. 旅夜书怀,月夜忆舍弟,天末怀李白,春望,旅宿,与诸子登岘山,宴梅道士山房,章台夜思,淮上喜会梁州故人,赋得暮雨送李曹
  10. bootstrap案例解析