API documentation¶
The following documentation is based on the source code of version 0.12.2 of the negotiator project:
negotiator_host¶
Channel for communication with guests.
This module implements the GuestChannel class which provides the
host side of the channel between QEMU hosts and guests. Channel objects can be
used to query and command running guests.
-
class
negotiator_host.AutomaticGuestChannel(guest_name, unix_socket)¶ Thin wrapper for
GuestChannelthat puts it in a separate process.Uses
multiprocessing.Processto isolate guest channels in separate processes.-
__init__(guest_name, unix_socket)¶ Initialize a
GuestChannelin a separate process.Parameters: - guest_name – The name of the guest to connect to (a string).
- unix_socket – The absolute pathname of the UNIX socket that we should connect to (a string).
-
run()¶ Start the main loop of the common negotiator interface.
-
-
class
negotiator_host.GuestChannel(guest_name, unix_socket=None)¶ The host side of the channel connecting KVM/QEMU hosts and guests.
See also
AutomaticGuestChannelwhich wrapsGuestChanneland puts it in its own process.-
__init__(guest_name, unix_socket=None)¶ Initialize a negotiator host agent.
Parameters: - guest_name – The name of the guest to connect to (a string).
- unix_socket – The absolute pathname of the UNIX socket that we should connect to (a string, optional).
-
prepare_environment()¶ Prepare environment variables for command execution on KVM/QEMU hosts.
The following environment variables are currently exposed to commands:
$NEGOTIATOR_GUEST- The name of the KVM/QEMU guest that invoked the command.
-
-
exception
negotiator_host.GuestChannelInitializationError¶ Exception raised by
GuestChannelwhen socket initialization fails.
-
exception
negotiator_host.GuestDiscoveryError¶ Exception raised by
find_running_guests()whenvirsh listfails.
-
class
negotiator_host.HostDaemon¶ The host daemon automatically manages a group of processes that handle “guest to host” calls.
-
__init__()¶ Initialize the host daemon.
-
cleanup_workers(running_guests)¶ Cleanup crashed workers and workers for guests that are no longer running.
-
enter_main_loop()¶ Create and maintain active channels for all running guests.
-
spawn_workers(running_guests)¶ Spawn new workers on demand (ignoring guests known not to support negotiator).
-
update_workers()¶ Automatically spawn subprocesses (workers) to maintain connections to all guests.
-
-
negotiator_host.find_channels_of_guest(guest_name)¶ Find the pathnames of the channels associated to a guest.
Parameters: guest_name – The name of the guest (a string). Returns: A dictionary with channel names (strings) as keys and pathnames of UNIX socket files (strings) as values. If no channels are detected an empty dictionary will be returned. This function uses
virsh dumpxmland parses the XML output to determine the pathnames of the channels associated to the guest.
-
negotiator_host.find_running_guests()¶ Find the names of the guests running on the current host.
This function parses the output of the
virsh listcommand instead of using the libvirt API because of two reasons:- I’m under the impression that the libvirt API is still very much in flux and large changes are still being made, so it’s not the most stable foundation for Negotiator to find running guests.
- The Python libvirt API needs to match the version of the libvirt API on
the host system and there is AFAIK no obvious way to express this in the
setup.pyscript of Negotiator.
Returns: A generator of strings. Raises: GuestDiscoveryErrorwhenvirsh listfails.
-
negotiator_host.find_supported_guests()¶ Find guests supporting the negotiator interface.
Returns: A generator of strings with guest names. This function uses
find_running_guests()to determine which guests are currently running and then usesfind_channels_of_guest()to determine which guests support the negotiator interface.
negotiator_host.cli¶
Usage: negotiator-host [OPTIONS] GUEST_NAME
Communicate from a KVM/QEMU host system with running guest systems using a guest agent daemon running inside the guests.
Supported options:
| Option | Description |
|---|---|
-g, --list-guests |
List the names of the guests that have the appropriate channel. |
-c, --list-commands |
List the commands that the guest exposes to its host. |
-e, --execute=COMMAND |
Execute 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=SECONDS |
Set 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, --daemon |
Start the host daemon that answers real time requests from guests. |
-v, --verbose |
Increase logging verbosity (can be repeated). |
-q, --quiet |
Decrease logging verbosity (can be repeated). |
-h, --help |
Show this message and exit. |
-
class
negotiator_host.cli.Context¶ Enables
main()to inject a custom timeout into partially applied actions.-
__init__()¶ Initialize a context for executing commands on the host.
-
execute_command(guest_name, command_line)¶ Execute a command inside the named guest.
-
print_commands(guest_name)¶ Print the commands supported by the guest.
-
print_guest_names()¶ Print the names of the guests that Negotiator can connect with.
-
-
negotiator_host.cli.main()¶ Command line interface for the
negotiator-hostprogram.
negotiator_guest¶
The guest agent daemon and client.
This module implements the guest agent, the Python daemon process that’s always running inside KVM/QEMU guests.
-
class
negotiator_guest.GuestAgent(character_device, retry=False)¶ Implementation of the daemon running inside KVM/QEMU guests.
-
__init__(character_device, retry=False)¶ Initialize a negotiator guest agent.
Parameters:
-
raw_readline()¶ Read a newline terminated string from the remote side.
This method overrides the
raw_readline()method of theNegotiatorInterface()class to implement blocking reads based onos.O_ASYNCandsignal.SIGIO(see alsoWaitForRead).Returns: The data read from the remote side (a string).
-
retry_open(character_device, mode)¶ Open the character device and retry
EBUSYerrors.
-
-
class
negotiator_guest.WaitForRead(group=None, target=None, name=None, args=(), kwargs={})¶ Used by
GuestAgent.raw_readline()to implement blocking reads.-
run()¶ Endless loop that waits for one or more
SIGIOsignals to arrive.
-
signal_handler(signal_number, frame)¶ Signal handler for
SIGIOsignals that immediately exits the process.
-
negotiator_guest.cli¶
Usage: 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:
| Option | Description |
|---|---|
-l, --list-commands |
List the commands that the host exposes to its guests. |
-e, --execute=COMMAND |
Execute 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, --daemon |
Start the guest daemon. When using this command line option the “negotiator-guest” program never returns (unless an unexpected error condition occurs). |
-t, --timeout=SECONDS |
Set 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=PATH |
By 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, --verbose |
Increase logging verbosity (can be repeated). |
-q, --quiet |
Decrease logging verbosity (can be repeated). |
-h, --help |
Show this message and exit. |
-
negotiator_guest.cli.main()¶ Command line interface for the
negotiator-guestprogram.
negotiator_common¶
Common shared functionality between the negotiator host and guest.
This Python module contains the functionality that is shared between the negotiator-host and negotiator-guest packages. By moving all of the shared functionality to a separate Python package and using Python package dependencies to pull in the negotiator-common package we stimulate code reuse while avoiding code duplication.
-
class
negotiator_common.NegotiatorInterface(handle, label)¶ Common logic shared between the host/guest components.
This class defines the protocol that’s used to communicate between the Python programs running on the hosts and guests.
-
__init__(handle, label)¶ Initialize a negotiator host or guest agent.
Parameters: - handle – A file like object connected to the other side.
- label – A string describing the file like object (used in logging).
This constructor is intended to be called by sub classes to provide the base class with the context it needs to set up bidirectional communication between the host and guest agents.
-
call_remote_method(method, *args, **kw)¶ Call a method on the remote object.
Parameters: - method – The name of the method to call (a string).
- args – The positional arguments for the method.
- kw – The keyword arguments for the method.
Returns: The return value of the remote method.
-
enter_main_loop()¶ Wait for requests from the other side.
The communication protocol for remote procedure calls is as follows:
- Every request is a dictionary containing at least a
commandkey with a string value (the name of the method to invoke). - The value of the optional
argumentskey gives a list of positional arguments to pass to the method. - The value of the optional
keyword-argumentskey gives a dictionary of keyword arguments to pass to the method.
Responses are structured as follows:
- Every response is a dictionary containing at least a
successkey with a boolean value. - If
success=Truethe keyresultgives the return value of the method. - If
success=Falsethe keyerrorgives a string explaining what went wrong.
Raises: ProtocolErrorwhen the remote side violates the defined protocol.- Every request is a dictionary containing at least a
-
execute(*command, **options)¶ Execute a user defined or built-in command.
Parameters: - command – The command name and any arguments (one or more strings).
- input – The input to feed to the command on its standard input
stream (a string or
None).
Returns: The output of the command (a string) or
Noneif the command exited with a nonzero exit code.
-
list_commands()¶ Find the names of the user defined commands.
Returns: A list of executable names (strings).
-
prepare_environment()¶ Prepare environment variables for command execution.
This method can be overridden by sub classes to prepare environment variables for external command execution.
-
raw_read(num_bytes)¶ Read the given number of bytes from the remote side.
Parameters: num_bytes – The number of bytes to read (an integer). Returns: The data read from the remote side (a string).
-
raw_readline()¶ Read a newline terminated string from the remote side.
Returns: The data read from the remote side (a string).
-
raw_write(data)¶ Write a string of data to the remote side.
Parameters: data – The data to write tot the remote side (a string).
-
read()¶ Wait for a JSON encoded message from the remote side.
The basic communication protocol is really simple:
- First an ASCII encoded integer number is received, terminated by a newline.
- Second the number of bytes given by step 1 is read and interpreted as a JSON encoded value. This step is not terminated by a newline.
That’s it :-).
Returns: The JSON value decoded to a Python value. Raises: ProtocolErrorwhen the remote side violates the defined protocol.
-
write(value)¶ Send a Python value to the other side.
Parameters: value – Any Python value that can be encoded as JSON.
-
-
exception
negotiator_common.ProtocolError¶ Exception that is raised when the communication protocol is violated.
-
exception
negotiator_common.RemoteMethodFailed¶ Exception that is raised when a remote method call failed.
negotiator_common.config¶
Configuration defaults for the negotiator project.
-
negotiator_common.config.BUILTIN_COMMANDS_DIRECTORY= '/home/docs/checkouts/readthedocs.org/user_builds/negotiator/checkouts/stable/common/negotiator_common/scripts'¶ The directory with built-in commands (a string).
-
negotiator_common.config.DEFAULT_TIMEOUT= 10¶ The number of seconds to wait for a reply from the other side (an integer).
If more time elapses an exception is raised causing the process to exit with a nonzero status code.
-
negotiator_common.config.GUEST_TO_HOST_CHANNEL_NAME= 'negotiator-guest-to-host.0'¶ The name of the channel that’s used for communication initiated by the guest (a string).
-
negotiator_common.config.HOST_TO_GUEST_CHANNEL_NAME= 'negotiator-host-to-guest.0'¶ The name of the channel that’s used for communication initiated by the host (a string).
-
negotiator_common.config.SUPPORTED_CHANNEL_NAMES= ('negotiator-guest-to-host.0', 'negotiator-host-to-guest.0')¶ A tuple of strings with supported channel names (containing
GUEST_TO_HOST_CHANNEL_NAMEandHOST_TO_GUEST_CHANNEL_NAME).
-
negotiator_common.config.USER_COMMANDS_DIRECTORY= '/usr/lib/negotiator/commands'¶ The pathname of the directory containing user defined commands that ‘the other side’ can invoke through negotiator.
negotiator_common.utils¶
Miscellaneous functionality.
-
class
negotiator_common.utils.GracefulShutdown¶ Context manager to enable graceful handling of
SIGTERM.This context manager translates termination signals (
SIGTERM) intoTerminationErrorexceptions.-
__enter__()¶ Start intercepting termination signals.
-
__exit__(exc_type, exc_value, traceback)¶ Stop intercepting termination signals.
-
signal_handler(signum, frame)¶ Raise
TerminationErrorwhen the timeout elapses.
-
-
exception
negotiator_common.utils.TerminationError¶ Exception that is raised when
SIGTERMis received.
-
class
negotiator_common.utils.TimeOut(num_seconds)¶ Context manager that enforces timeouts using UNIX alarm signals.
-
__enter__()¶ Schedule the timeout.
-
__exit__(exc_type, exc_value, traceback)¶ Clear the timeout and restore the previous signal handler.
-
__init__(num_seconds)¶ Initialize the context manager.
Parameters: num_seconds – The number of seconds after which to interrupt the running operation (an integer).
-
signal_handler(signum, frame)¶ Raise
TimeOutErrorwhen the timeout elapses.
-
-
negotiator_common.utils.format_call(function, *args, **kw)¶ Format a Python function call into a human readable string.
Parameters: - function – The name of the function that’s called (a string).
- args – The positional arguments to the function (if any).
- kw – The keyword arguments to the function (if any).