跳转到主要内容

可脚本化的KVM/QEMU客户代理(主机端)

项目描述

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

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

状态

一些需要考虑的点

  • “谈判者”项目做到了我预期的功能:基于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

通过在虚拟机内部运行的代理守护进程,与正在运行的虚拟机系统进行通信。

支持选项

选项

描述

-g--list-guests

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

-c--list-commands

列出访客对其宿主公开的命令。

-e--execute=COMMAND

在GUEST_NAME内部执行指定的命令。访客内部命令的标准输出流被截获并复制到宿主的标准输出流。如果命令以非零状态码退出,协商宿主程序也将以非零状态码退出。

-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宿主上执行指定的命令。宿主上命令的标准输出流被截获并复制到访客的标准输出流。如果命令以非零状态码退出,协商访客程序也将以非零状态码退出。

-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访客代理还是运行协商者项目,您都需要一个正常工作的双向通道。我在Ubuntu 14.04 KVM/QEMU宿主上测试协商者,需要做几个更改才能正常工作。

$ 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-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-host-0.12.2.tar.gz (13.2 kB 查看哈希值)

上传时间 源代码

构建发行版

negotiator_host-0.12.2-py3-none-any.whl (13.3 kB 查看哈希值)

上传时间 Python 3

由以下机构支持