跳转到主要内容

可脚本化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主机上

以下是如何在您的主机(s)上安装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虚拟机上

在您的虚拟机(s)上安装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 [选项] 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 主机上运行的协商器-主机守护进程通信的字符设备的绝对路径名。

-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 程序无法检测到正确的字符设备时,它会大声抱怨并指向这里。以下是我遇到的一些可能导致此情况的问题:

  • 虚拟通道配置不正确或尚未应用正确的配置。请仔细遵循上面 入门 部分的说明。

  • 内核模块 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-common-0.12.2.tar.gz (13.6 kB 查看哈希)

上传时间 源代码

构建的分发

negotiator_common-0.12.2-py3-none-any.whl (14.7 kB 查看哈希值)

上传时间: Python 3

由以下支持