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
GuestChannel
that puts it in a separate process.Uses
multiprocessing.Process
to isolate guest channels in separate processes.-
__init__
(guest_name, unix_socket)¶ Initialize a
GuestChannel
in 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
AutomaticGuestChannel
which wrapsGuestChannel
and 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
GuestChannel
when socket initialization fails.
-
exception
negotiator_host.
GuestDiscoveryError
¶ Exception raised by
find_running_guests()
whenvirsh list
fails.
-
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 dumpxml
and 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 list
command 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.py
script of Negotiator.
Returns: A generator of strings. Raises: GuestDiscoveryError
whenvirsh list
fails.
-
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-host
program.
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_ASYNC
andsignal.SIGIO
(see alsoWaitForRead
).Returns: The data read from the remote side (a string).
-
retry_open
(character_device, mode)¶ Open the character device and retry
EBUSY
errors.
-
-
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
SIGIO
signals to arrive.
-
signal_handler
(signal_number, frame)¶ Signal handler for
SIGIO
signals 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-guest
program.
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
command
key with a string value (the name of the method to invoke). - The value of the optional
arguments
key gives a list of positional arguments to pass to the method. - The value of the optional
keyword-arguments
key 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
success
key with a boolean value. - If
success=True
the keyresult
gives the return value of the method. - If
success=False
the keyerror
gives a string explaining what went wrong.
Raises: ProtocolError
when 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
None
if 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: ProtocolError
when 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/latest/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_NAME
andHOST_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
) intoTerminationError
exceptions.-
__enter__
()¶ Start intercepting termination signals.
-
__exit__
(exc_type, exc_value, traceback)¶ Stop intercepting termination signals.
-
signal_handler
(signum, frame)¶ Raise
TerminationError
when the timeout elapses.
-
-
exception
negotiator_common.utils.
TerminationError
¶ Exception that is raised when
SIGTERM
is 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
TimeOutError
when 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).