经常使用vmWare的同学都知道有vmware-tools这个工具,这个安装在vm内部的工具,可以实现宿主机与虚拟机的通讯,大大增强了虚拟机的性能与功能,

如vmware现在的Unity mode下可以让应用程序无缝地与宿主机交互,更不用提直接复制粘帖文件及内容的小功能了。

对于KVM而言,其实也有一款这样的工具叫做 Qemu Guest Agent(以下称qga).

原理分析:

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

  qga通过读写串口设备与宿主机上的socket通道进行交互,宿主机上可以使用普通的unix socket读写方式对socket文件进行读写,最终实现与qga的交互,交互的协议与qmp(QEMU Monitor 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 \
-chardev socket,id=charchannel0,path=/var/lib/libvirt/qemu/test.agent,server,nowait \
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,\
name=com.163.spice.0

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

也可以通的XML文件来配置这个串口设备:

<channel type='unix'>
<source mode='bind' path='/var/lib/libvirt/qemu/test.agent'/>
<target type='virtio' name='com.163.spice.0'/>
</channel>

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

已有功能

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

Ø guest-sync-delimited*:宿主机发送一个int数字给qga,qga返回这个数字,并且在后续返回字符串响应中加入ascii码为0xff的字符,其作用是检查宿主机与qga通信的同步状态,主要用在宿主机上多客户端与qga通信的情况下客户端间切换过程的状态同步检查,比如有两个客户端A、B,qga发送给A的响应,由于A已经退出,目前B连接到qga的socket,所以这个响应可能被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 UTC,Time in nanoseconds.);

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

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

Ø guest-shutdown*:关闭虚拟机(支持halt、powerdown、reboot,默认动作为powerdown);

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

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

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

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

Ø guest-file-seek:Seek to a position in the file, as with fseek(), and return the current file position afterward. Also encapsulates ftell()'s functionality, just Set offset=0, whence=SEEK_CUR;

Ø guest-file-flush:Write file changes bufferred in userspace to disk/kernel buffers;

Ø guest-fsfreeze-status:Get guest fsfreeze state. error state indicates;

Ø guest-fsfreeze-freeze:Sync and freeze all freezable, local guest filesystems;

Ø guest-fsfreeze-thaw:Unfreeze all frozen guest filesystems;

Ø guest-fstrim:Discard (or "trim") blocks which are not in use by the filesystem;

Ø guest-suspend-disk*:Suspend guest to disk;

Ø guest-suspend-ram*:Suspend guest to ram;

Ø guest-suspend-hybrid:Save guest state to disk and suspend to ram(This command requires the pm-utils package to be installed in the guest.);

Ø guest-network-get-interfaces:Get list of guest IP addresses, MAC addresses and netmasks;

Ø guest-get-vcpus:Retrieve the list of the guest's logical processors;

guest-set-vcpus:Attempt to reconfigure (currently: enable/disable) logical processors inside the guest。

功能扩展方式

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' }
+

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

写到这里,有经验的开发人员已经知道如何用qga开发监控平台,下面是网友的实现思路,供参考:

qemu-guest-agent简介的更多相关文章

  1. QEMU Guest Agent

    QEMU Guest Agent It is a daemon program running inside the domain which is supposed to help manageme ...

  2. 利用Qemu Guest Agent (Qemu-ga) 实现 Openstack 监控平台

    经常使用vmWare的同学都知道有vmware-tools这个工具,这个安装在vm内部的工具,可以实现宿主机与虚拟机的通讯,大大增强了虚拟机的性能与功能, 如vmware现在的Unity mode下可 ...

  3. java agent简介

    java agent简介 主要就是两种,一种的方法是premain,一种是agentmain.这两种的区别是: premain是在jvm启动的时候类加载到虚拟机之前执行的 agentmain是可以在j ...

  4. Salesforce Live Agent 简介

    Live Agent Salesforce 内置了即时聊天功能--Live Agent,可以用来作为客服工具. 本文简单介绍了使用 Live Agent 的步骤,主要包含: 启用 Live Agent ...

  5. Qemu事件处理机制简介

    Qmeu 采用了基于事件驱动的架构,所有的事件都在一个事件循环(event loop)中被处理,系统中默认的事件循环是在main-loop.c 中的主循环(main loop).我们也可以使用 –ob ...

  6. 11gR2 Agent 简介

    目的:本文会对oracle 11gR2 集群件(Grid Infrastructure,以下简称GI) 新特性 agent进行介绍,包括 agent的功能,常见的agent介绍,以及基本的诊断方法. ...

  7. 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设备直接分 ...

  8. 使用QEMU创建虚拟机

    下载安装: wget http://wiki.qemu-project.org/download/qemu-2.0.0.tar.bz2 tar xjvf qemu- ./configure --ena ...

  9. KVM(七)使用 libvirt 做 QEMU/KVM 快照和 Nova 实例的快照

    本文将梳理 QEMU/KVM 快照相关的知识,以及在 OpenStack Nova 中使用 libvirt 来对 QEMU/KVM 虚机做快照的过程. 1. QEMU/KVM 快照 1.1 概念 QE ...

随机推荐

  1. Linux 上安装 Node.js

    Linux 上安装 Node.js 直接使用已编译好的包(在个人阿里云服务器47.100.6.106上安装) Node 官网已经把 linux 下载版本更改为已编译好的版本了,我们可以直接下载解压后使 ...

  2. [App Store Connect帮助]五、管理构建版本(2)查看构建版本和文件大小

    您可以查看您为某个 App 上传的所有构建版本,和由 App Store 创建的变体版本的大小.一些构建版本在该 App 发布到 App Store 上后可能不会显示. 必要职能:“帐户持有人”职能. ...

  3. WPF-CheckBox(复选框、功能开关)美化

    老规矩,先放图 按钮美化背景: 由于特殊需求,复选框样式单一,所以我们需要将其按钮重构和美化达到我们的需求 复选框美化思维引导: 图中1为背景色 图中2为边框 图中3为句柄控件组成(Path+Rect ...

  4. jenkins手把手教你从入门到放弃02-jenkins在Windows系统安装与配置(详解)

    简介 上一篇对jenkins有了大致了解之后,那么我们就开始来安装一下jenkins. Jenkins安装 一.安装Java环境 1.你需要做的第一件事情就是在你的机器上安装Java环境.Jenkin ...

  5. Proteus中的 PIC10/12/16 MCUs编译器无法下载的问题

    当你打开网站时,点击该软件下载会发现如下页面: google一下会出现这个界面,大意是这个版本的编译器太老了,已经被某些更加高级的编译器给取代了(qaq心痛) 然后我就开始FQ到处google,Sou ...

  6. 278 First Bad Version 第一个错误的版本

    你是产品经理,目前正在领导一个团队开发一个新产品.不幸的是,您的产品的最新版本没有通过质量检查.由于每个版本都是基于之前的版本开发的,所以错误版本之后的所有版本都是不好的.假设你有 n 个版本 [1, ...

  7. .Net MVC 与WebApi ActionFilterAttribute 区别

    首先我们来看下 这两个ActionFilterAttribute 的命名空间区别的: 可以看出mvc 引用的是System.Web.Mvc,webapi 引用的是System.Web.Http.Fil ...

  8. JavaScript Json与Map互转以及Map对象的取值方式

    Json格式(Json字符串) : var json='{"name": "lily","age":"15"}' Map ...

  9. ajax怎么理解?

    Ajix是创建交互式网页的前端网页开发技术,不是一种语言,ajax是基于http来传输数据的,他是利用浏览器提供操作http的接口(XMLHttpRequest或者activeXobject),来操作 ...

  10. oa系统部署

    1.配置java环境变量 新建:JAVA_HOME C:\Program Files\Java\jdk1.6.0_45 path添加   C:\Program Files\Java\jdk1.6.0_ ...