跳转到主要内容

可脚本化的KVM/QEMU客户代理(事物的一方)

项目描述

Python包negotiator-hostnegotiator-guestnegotiator-common共同实现了Python中的可脚本化KVM/QEMU客户代理基础设施。这个基础设施支持Linux主机和客户机之间的实时双向通信,允许主机和客户机在“另一方”调用用户定义的命令。

因为用户定义了主机和客户机可以执行的命令,用户控制了主机和客户机相互影响的大小(有一些内置的命令,这些都是只读的)。

状态

需要考虑的一些问题

  • Negotiator项目完成了我期望的事情:基于Linux的KVM/QEMU主机和客户机之间的实时双向通信。

  • 该项目没有自动化的测试套件,尽管在开发过程中其功能已经得到了广泛的测试,并且正在超过100台虚拟机(用于非关键任务)的生产环境中使用。

  • 该项目在安全性方面尚未经过同行评审。我的主要用例是KVM/QEMU主机和客户端机,它们在一定程度上相互信任(考虑私有云,而不是共享托管 :-)。

安装

negotiator软件包及其依赖与Python 2.7及更高版本兼容,并且都是纯Python。这意味着您无需编译器工具链即可安装negotiator软件包。这是一个设计决策,因此不会改变。

在KVM/QEMU主机上

以下是在您的主机上安装negotiator-host软件包的方法

$ sudo pip install negotiator-host

如果您愿意,可以在虚拟环境中安装Python软件包

$ sudo apt-get install --yes python-virtualenv
$ virtualenv /tmp/negotiator-host
$ source /tmp/negotiator-host/bin/activate
$ pip install negotiator-host

安装后,negotiator-host程序可用。使用信息将帮助您入门,尝试使用--help选项。现在您需要找到一种方法以守护进程方式运行negotiator-host命令。我使用supervisord有很好的经验,以下是设置方法:

$ sudo apt-get install --yes supervisor
$ sudo tee /etc/supervisor/conf.d/negotiator-host.conf >/dev/null << EOF
[program:negotiator-host]
command = /usr/local/bin/negotiator-host --daemon
autostart = True
stdout_logfile = /var/log/negotiator-host.log
stderr_logfile = /var/log/negotiator-host.log
EOF
$ sudo supervisorctl update negotiator-host

在KVM/QEMU客户机上

在您的客户端机上安装negotiator-guest软件包

$ sudo pip install negotiator-guest

如果您愿意,可以在虚拟环境中安装Python软件包

$ sudo apt-get install --yes python-virtualenv
$ virtualenv /tmp/negotiator-guest
$ source /tmp/negotiator-guest/bin/activate
$ pip install negotiator-guest

安装后,您需要找到一种方法以守护进程方式运行negotiator-guest命令。我使用supervisord有很好的经验,以下是设置方法:

$ sudo apt-get install --yes supervisor
$ sudo tee /etc/supervisor/conf.d/negotiator-guest.conf >/dev/null << EOF
[program:negotiator-guest]
command = /usr/local/bin/negotiator-guest --daemon
autostart = True
stdout_logfile = /var/log/negotiator-guest.log
stderr_logfile = /var/log/negotiator-guest.log
EOF
$ sudo supervisorctl update negotiator-guest

入门

如果以下说明不足以让您入门,请参阅下方的调试部分,了解当事情没有按预期工作时应做什么。

  1. 首先,您必须向QEMU客户端机添加两个虚拟设备。您可以通过编辑客户端机的XML定义文件来完成此操作。在Ubuntu Linux KVM/QEMU主机上,这些文件位于目录/etc/libvirt/qemu中。使用您喜欢的文本编辑器(Vim? :-))打开文件,并在<devices>部分中添加以下XML片段:

    <channel type='unix'>
       <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/GUEST_NAME.negotiator-host-to-guest.0' />
       <target type='virtio' name='negotiator-host-to-guest.0' />
    </channel>
    
    <channel type='unix'>
       <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/GUEST_NAME.negotiator-guest-to-host.0' />
       <target type='virtio' name='negotiator-guest-to-host.0' />
    </channel>

    GUEST_NAME替换为客户端机的名称。如果您使用libvirt 1.0.6或更高版本(您可以使用virsh --version进行检查),则可以省略path='...'属性,因为libvirt将在重新加载客户端机的XML定义文件时自动填充它(在步骤2中)。

  2. 添加配置片段后,您需要激活它

    $ sudo virsh define /etc/libvirt/qemu/GUEST_NAME.xml
  3. 现在,您需要关闭客户端机,然后重新启动它

    $ sudo virsh shutdown --mode acpi GUEST_NAME
    $ sudo virsh start GUEST_NAME

    请注意,仅仅重新启动客户端机不会添加新的虚拟设备,您必须实际上停止客户端机,然后重新启动它!

  4. 现在,请前往/usr/lib/negotiator/commands创建一些脚本,并尝试从另一端执行它们!一旦您开始编写自己的命令,了解KVM/QEMU主机端的命令可以访问一些环境变量会有所帮助。

使用

本节记录了在主机和客户端机上运行的程序的命令行界面。有关Python API的信息,请参阅Read the Docs上的在线文档。

negotiator-host程序

用法: negotiator-host [OPTIONS] GUEST_NAME

使用运行在客户端机内部的客户端代理守护进程,与运行在KVM/QEMU主机系统上的客户端机进行通信。

支持选项

选项

描述

-g--list-guests

列出具有适当通道的客人名称。

-c--list-commands

列出客人向其主机暴露的命令。

-e--execute=COMMAND

在GUEST_NAME内部执行给定的命令。客人内部命令的标准输出流被拦截并复制到主机上的标准输出流。如果命令以非零状态码退出,negotiator-host程序也将以非零状态码退出。

-t--timeout=SECONDS

设置远程调用在没有响应之前超时的秒数。零值禁用超时(在这种情况下,命令可以无限期地挂起)。默认为10秒。

-d--daemon

启动主机守护进程,以响应客人的实时请求。

-v--verbose

增加日志详细程度(可重复)。

-q--quiet

减少日志详细程度(可重复)。

-h--help

显示此信息并退出。

negotiator-guest程序

用法: negotiator-guest [OPTIONS]

从KVM/QEMU客人系统与其主机通信或启动客人守护进程以允许主机在其客人上执行命令。

支持选项

选项

描述

-l--list-commands

列出主机向其客人暴露的命令。

-e--execute=COMMAND

在KVM/QEMU主机上执行给定的命令。主机上命令的标准输出流被拦截并复制到客人上的标准输出流。如果命令以非零状态码退出,negotiator-guest程序也将以非零状态码退出。

-d--daemon

启动客人守护进程。当使用此命令行选项时,“negotiator-guest”程序永远不会返回(除非发生意外错误条件)。

-t--timeout=SECONDS

设置远程调用在没有响应之前超时的秒数。零值禁用超时(在这种情况下,命令可以无限期地挂起)。默认为10秒。

-c--character-device=PATH

默认情况下,将根据/sys/class/virtio-ports/*/name自动选择适当的字符设备。如果自动选择不起作用,您可以设置与运行在KVM/QEMU主机上的negotiator-host守护进程通信的字符设备的绝对路径名。

-v--verbose

增加日志详细程度(可重复)。

-q--quiet

减少日志详细程度(可重复)。

-h--help

显示此信息并退出。

调试

本节包含有关在预期情况不正常时的操作提示。

KVM/QEMU主机上的损坏通道

无论您是想获取官方QEMU客人代理还是运行Negotiator项目,您都需要一个正常工作的双向通道。我在Ubuntu 14.04 KVM/QEMU主机上测试Negotiator,并需要几个更改才能使一切正常运行

$ CHANNELS_DIRECTORY=/var/lib/libvirt/qemu/channel/target
$ sudo mkdir -p $CHANNELS_DIRECTORY
$ sudo chown libvirt-qemu:kvm $CHANNELS_DIRECTORY

如果您问我,上述操作应由KVM/QEMU系统软件包完成,但无论如何。此外,如果您正在运行启用AppArmor的Ubuntu(默认设置),您可能需要应用以下补丁

$ diff -u /etc/apparmor.d/abstractions/libvirt-qemu.orig /etc/apparmor.d/abstractions/libvirt-qemu
--- /etc/apparmor.d/abstractions/libvirt-qemu.orig      2015-09-19 12:46:54.316593334 +0200
+++ /etc/apparmor.d/abstractions/libvirt-qemu   2015-09-24 14:43:43.642064576 +0200
@@ -49,6 +49,9 @@
   /run/shm/ r,
   owner /run/shm/spice.* rw,

+  # Local modification to enable the QEMU guest agent.
+  owner /var/lib/libvirt/qemu/channel/target/* rw,
+
   # 'kill' is not required for sound and is a security risk. Do not enable
   # unless you absolutely need it.
   deny capability kill,

这应该只是KVM/QEMU系统软件包的一部分,但无论如何。Negotiator项目正在玩一些新功能,所以我基本上知道要期待锋利的边缘 :-)

字符设备检测失败

当negotiator-guest程序无法检测到正确的字符设备时,它会大声抱怨并指向这里。以下是我遇到的一些可能引起这种情况的问题

  • 虚拟通道(s)尚未正确配置,或者正确的配置尚未应用。请仔细阅读上面《入门》部分中的说明。

  • 内核模块 virtio_console 未加载,因为您的内核中没有提供。您可以使用 lsmod 命令来检查。如果没有加载该模块,您需要安装并引导到一个包含该模块的内核。

为什么还需要另一个客户代理?

QEMU 项目提供了一个 官方的虚拟机代理,这个代理对于增强 QEMU 主机和虚拟机之间的集成非常有用。然而,官方的 QEMU 虚拟机代理有两个显著的不足(至少对我来说是这样的)

可扩展性

官方的 QEMU 虚拟机代理有一些通用的机制,例如能够在虚拟机内部写入文件,但这与一个通用的、可扩展的架构相去甚远。理想情况下,如果我们有主机和虚拟机的权限,我们应能够在双方传输任意数据并执行用户定义的逻辑。

平台支持

尽管我付出了相当大的努力,但我还没有能够在较老的 Linux 发行版(例如 Ubuntu Linux 10.04)上运行 QEMU 虚拟机代理的最新版本。虽然旧版本的虚拟机代理可以成功编译为这样的发行版,但不支持我所需的功能。通过创建自己的虚拟机代理,我可以在平台支持方面拥有更多的控制权(考虑到通信所需的原始功能)。

注意,我的项目绝对没有试图取代官方的 QEMU 虚拟机代理。例如,我没有打算实现文件系统的冻结和解冻,因为官方代理已经做得很好了 :-). 换句话说,这两个项目有很多共同的想法,但目标非常不同。

它是如何工作的?

可脚本化虚拟机代理基础设施使用了官方 QEMU 虚拟机代理使用的相同机制

  • 在虚拟机内部创建了特殊字符设备,允许读写操作。这些字符设备是 /dev/vport[0-9]p[0-9]

  • 在主机上创建了 UNIX 域套接字,这些套接字连接到虚拟机内部的字符设备。在 Ubuntu Linux KVM/QEMU 主机上,这些 UNIX 域套接字在目录 /var/lib/libvirt/qemu/channel/target 中创建。

联系方式

最新版本的 negotiator 可在 PyPIGitHub 上找到。您可以在 Read The Docs 上找到文档。有关错误报告,请在 GitHub 上创建问题。如果您有任何问题、建议等,请随时通过电子邮件发送给我,地址是 peter@peterodding.com

许可证

本软件受 MIT 许可证 许可。

© 2019 Peter Odding。

项目详情


下载文件

下载适合您平台的项目。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源代码发行版

negotiator-guest-0.12.2.tar.gz (13.9 kB 查看哈希值)

上传于 源代码

构建分发版

negotiator_guest-0.12.2-py3-none-any.whl (12.7 kB 查看哈希值)

上传于 Python 3

由以下支持