Package: negotiator-common
The Python packagesnegotiator-host,negotiator-guestandnegotiator-commontogether implement a scriptableKVM/QEMUguest agent infrastructure in
Python. This infrastructure supports realtime bidirectional communication
betweenLinuxhosts and guests which allows the hosts and guests to invoke
user defined commands on ‘the other side’.Because the user defines the commands that hosts and guests can execute, the
user controls the amount of influence that hosts and guests have over each
other (there are several built-in commands, these are all read only).ContentsStatusInstallationOn KVM/QEMU hostsOn KVM/QEMU guestsGetting startedUsageThe negotiator-host programThe negotiator-guest programDebuggingBroken channels on KVM/QEMU hostsCharacter device detection failsWhy another guest agent?How does it work?ContactLicenseStatusSome points to consider:The Negotiator project does what I expect from it: realtime bidirectional
communication between Linux based KVM/QEMU hosts and guests.The project doesn’t have an automated test suite, although its functionality
has been extensively tested during development and is being used in a
production environment on more than 100 virtual machines (for non-critical
tasks).The project has not been peer reviewed with regards to security. My primary
use case is KVM/QEMU hosts and guests that trust each other to some extent
(think private clouds, not shared hosting :-).InstallationThenegotiatorpackages and their dependencies are compatible with Python 2.7
and newer and are all pure Python. This means you don’t need a compiler
toolchain to install thenegotiatorpackages. This is a design decision and
so won’t be changed.On KVM/QEMU hostsOn KVM/QEMU guestsOn KVM/QEMU hostsHere’s how to install thenegotiator-hostpackage on your host(s):$sudopipinstallnegotiator-hostIf you prefer you can install the Python package in a virtual environment:$sudoapt-getinstall--yespython-virtualenv$virtualenv/tmp/negotiator-host$source/tmp/negotiator-host/bin/activate$pipinstallnegotiator-hostAfter installation thenegotiator-hostprogram is available. The usage
message will help you get started, try the--helpoption. Now you need to
find a way to run thenegotiator-hostcommand as a daemon. I have good
experiences withsupervisord, here’s how to set that up:$sudoapt-getinstall--yessupervisor$sudotee/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$sudosupervisorctlupdatenegotiator-hostOn KVM/QEMU guestsInstall thenegotiator-guestpackage on your guest(s):$sudopipinstallnegotiator-guestIf you prefer you can install the Python package in a virtual environment:$sudoapt-getinstall--yespython-virtualenv$virtualenv/tmp/negotiator-guest$source/tmp/negotiator-guest/bin/activate$pipinstallnegotiator-guestAfter installation you need to find a way to run thenegotiator-guestcommand as a daemon. I have good experiences withsupervisord, here’s how
to set that up:$sudoapt-getinstall--yessupervisor$sudotee/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$sudosupervisorctlupdatenegotiator-guestGetting startedIf the instructions below are not enough to get you started, take a look at theDebuggingsection below for hints about what to do when things don’t work as
expected.First you have to add two virtual devices to your QEMU guest. You can do so
by editing the guest’s XML definition file. On Ubuntu Linux KVM/QEMU hosts
these files are found in the directory/etc/libvirt/qemu. Open the file
in your favorite text editor (Vim? :-) and add the the following XML snippet
inside the<devices>section:<channeltype='unix'><sourcemode='bind'path='/var/lib/libvirt/qemu/channel/target/GUEST_NAME.negotiator-host-to-guest.0'/><targettype='virtio'name='negotiator-host-to-guest.0'/></channel><channeltype='unix'><sourcemode='bind'path='/var/lib/libvirt/qemu/channel/target/GUEST_NAME.negotiator-guest-to-host.0'/><targettype='virtio'name='negotiator-guest-to-host.0'/></channel>ReplaceGUEST_NAMEwith the name of your guest in both places. If you
use libvirt 1.0.6 or newer (you can check withvirsh--version) you can
omit thepath='...'attribute because libvirt will fill it in
automatically when it reloads the guest’s XML definition file (in step 2).After adding the configuration snippet you have to activate it:$sudovirshdefine/etc/libvirt/qemu/GUEST_NAME.xmlNow you need to shut down the guest and then start it again:$sudovirshshutdown--modeacpiGUEST_NAME$sudovirshstartGUEST_NAMENote that just rebooting the guest will not add the new virtual devices, you
have to actually stop the guest and then start it again!Now go and create some scripts in/usr/lib/negotiator/commandsand try
to execute them from the other side! Once you start writing your own
commands it’s useful to know that commands on the KVM/QEMU host side have
access to someenvironment variables.UsageThis section documents the command line interfaces of the programs running on
hosts and guests. For information on the Python API please refer to the online
documentation onRead the Docs.The negotiator-host programThe negotiator-guest programThe negotiator-host programUsage:negotiator-host [OPTIONS] GUEST_NAMECommunicate from a KVM/QEMU host system with running guest systems using a
guest agent daemon running inside the guests.Supported options:OptionDescription-g,--list-guestsList the names of the guests that have the appropriate channel.-c,--list-commandsList the commands that the guest exposes to its host.-e,--execute=COMMANDExecute the given command inside GUEST_NAME. The standard output stream of
the command inside the guest is intercepted and copied to the standard
output stream on the host. If the command exits with a nonzero status code
the negotiator-host program will also exit with a nonzero status code.-t,--timeout=SECONDSSet the number of seconds before a remote call without a response times
out. A value of zero disables the timeout (in this case the command can
hang indefinitely). The default is 10 seconds.-d,--daemonStart the host daemon that answers real time requests from guests.-v,--verboseIncrease logging verbosity (can be repeated).-q,--quietDecrease logging verbosity (can be repeated).-h,--helpShow this message and exit.The negotiator-guest programUsage:negotiator-guest [OPTIONS]Communicate from a KVM/QEMU guest system to its host or start the
guest daemon to allow the host to execute commands on its guests.Supported options:OptionDescription-l,--list-commandsList the commands that the host exposes to its guests.-e,--execute=COMMANDExecute the given command on the KVM/QEMU host. The standard output stream
of the command on the host is intercepted and copied to the standard output
stream on the guest. If the command exits with a nonzero status code the
negotiator-guest program will also exit with a nonzero status code.-d,--daemonStart the guest daemon. When using this command line option the
“negotiator-guest” program never returns (unless an unexpected error
condition occurs).-t,--timeout=SECONDSSet the number of seconds before a remote call without a response times
out. A value of zero disables the timeout (in this case the command can
hang indefinitely). The default is 10 seconds.-c,--character-device=PATHBy default the appropriate character device is automatically selected based
on /sys/class/virtio-ports/*/name. If the automatic selection doesn’t work,
you can set the absolute pathname of the character device that’s used to
communicate with the negotiator-host daemon running on the KVM/QEMU host.-v,--verboseIncrease logging verbosity (can be repeated).-q,--quietDecrease logging verbosity (can be repeated).-h,--helpShow this message and exit.DebuggingThis section contains hints about what to do when things don’t work as
expected.Broken channels on KVM/QEMU hostsCharacter device detection failsBroken channels on KVM/QEMU hostsWhether you want to get the official QEMU guest agent or the Negotiator project
running, you will need a working bidirectional channel. I’m testing Negotiator
on an Ubuntu 14.04 KVM/QEMU host and I needed several changes to get things
working properly:$CHANNELS_DIRECTORY=/var/lib/libvirt/qemu/channel/target$sudomkdir-p$CHANNELS_DIRECTORY$sudochownlibvirt-qemu:kvm$CHANNELS_DIRECTORYThe above should be done by the KVM/QEMU system packages if you ask me, but
anyway. On top of this if you are running Ubuntu with AppArmor enabled (the
default) you may need to apply the following patch:$diff-u/etc/apparmor.d/abstractions/libvirt-qemu.orig/etc/apparmor.d/abstractions/libvirt-qemu---/etc/apparmor.d/abstractions/libvirt-qemu.orig2015-09-1912:46:54.316593334+0200+++/etc/apparmor.d/abstractions/libvirt-qemu2015-09-2414: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.denycapabilitykill,Again this should just be part of the KVM/QEMU system packages, but whatever.
The Negotiator project is playing with new-ish functionality so I pretty much
know to expect sharp edges :-)Character device detection failsWhen thenegotiator-guestprogram fails to detect the correct character
devices it will complain loudly and point you here. Here are some of things
I’ve run into that can cause this:The virtual channel(s) have not been correctly configured or the correct
configuration hasn’t been applied yet. Please carefully follow the
instructions in theGetting startedsection above.The kernel modulevirtio_consoleis not loaded because it is not
available in your kernel. You can check by using thelsmodcommand. If
the module is not loaded you’ll need to install and boot to a kernel that
does have the module.Why another guest agent?The QEMU project provides anofficial guest agentand this agent is very
useful to increase integration between QEMU hosts and guests. However the
official QEMU guest agent has two notable shortcomings (for me at least):ExtensibilityThe official QEMU guest agent has some generic mechanisms like being able to
write files inside guests, but this is a far cry from a generic, extensible
architecture. Ideally given the host and guest’s permission we should be able
to transfer arbitrary data and execute user defined logic on both sides.Platform supportDespite considerable effort I haven’t been able to get a recent version of
the QEMU guest agent running on older Linux distributions (e.g. Ubuntu Linux
10.04). Older versions of the guest agent can be succesfully compiled for
such distributions but don’t support the features I require. By creating my
own guest agent I have more control over platform support (given the
primitives required for communication).Note that my project in no way tries to replace the official QEMU guest agent.
For example I have no intention of implementing freezing and thawing of file
systems because the official agent already does that just fine :-). In other
words the two projects share a lot of ideas but have very different goals.How does it work?The scriptable guest agent infrastructure usesthe same mechanismthat the
official QEMU guest agent does:Inside the guest special character devices are created that allow reading and
writing. These character devices are/dev/vport[0-9]p[0-9].On the host UNIX domain sockets are created that are connected to the
character devices inside the guest. On Ubuntu Linux KVM/QEMU hosts,
these UNIX domain sockets are created in the directory/var/lib/libvirt/qemu/channel/target.ContactThe latest version ofnegotiatoris available onPyPIandGitHub. You can
find the documentation onRead The Docs. For bug reports please create an
issue onGitHub. If you have questions, suggestions, etc. feel free to send me
an e-mail atpeter@peterodding.com.LicenseThis software is licensed under theMIT license.© 2019 Peter Odding.