module: | ave-common |
---|
Modules and packages that are used by several other AVE components. It may also be useful in
- Scheduler implementations
- Service implementations
- Handling of OS specific configuration details
Regular test jobs would not use this package much, but AVE’s own test jobs use them extensively.
Run external commands through a forked pseudoterminal. This is done by using pty.fork() to create new processes. This affects the behavior of the new process:
- Output written to stdout and stderr are mixed into a single stream.
- The process and its children are guaranteed to die when the pseudoterminal is destroyed. This means that the caller does not have to check that the external program is fully terminated afterwards.
- Programs that daemonize survive the destruction of the pseudoterminal, but they have to daemonize correctly to achieve this. I.e. do the double fork and make sure the final child is a new session leader before returning.
- There is no buffering of the program’s output. If the caller is a program that is attached to a pseudoterminal, then the called program’s output will be written immediately on the caller’s pseudoterminal.
Warning
adb does not daemonize correctly and it is not possible to start an ADB server using the ave.cmd functions. Also note that ADB will start a server automatically when executing regular commands if none was running already. This leads to a cascading failure condition where every attemp to run an ADB command results in a new server that is killed as soon as the command returns.
Run a command in a separate process.
Parameters: |
|
---|---|
Returns: | An (integer, string) tuple: The exit code from the process and all its output (stdout and stderr are mixed in the order they are written to, like in a terminal). |
Raises: |
|
Works the same as ave.cmd.run(), except that it is non-blocking.
Returns: | A (PID, file descriptor) tuple. The file descriptor is attached to the new process’ pseudoterminal and will carry all messages written to stdout and stderr. |
---|
Note
The caller must eventually use os.wait() or one of its variations on the PID and os.close() on the file descriptor. Failing to perform these cleanups will lead to defunct processes and/or running out of pseudoterminals.
Functions to read and write system wide configuration details. Used by servers to find all of AVE’s domain specific configuration files. Also used by Debian package installation scripts to create default configuration files.
Create default configuration files under <home>/.ave/config. Will also create the directories if they do not exist. Configuration files that already exist will not be touched.
Parameters: | home – A string containing a path to a directory. Would normally be a user’s home directory, but can be anything where the caller has write and exec permissions. |
---|---|
Returns: | A tuple of two lists. The first contains the paths of the created files. The second contains skipped files. |
Load and return the administrative authentication keys from <home>/ave/config/authkeys.json. The object can be passed as the ault_keys parameter when creating Control instances. Functions marked with the @Control.preauth() decorator can refer to account names found in the file.
Parameters: | home – The base directory to search for AVE configuration files. |
---|---|
Returns: | A dictionary containing account/password pairs in plain text. |
Warning
The use of authentication keys to limit access on API level does not constitute a security system. It is intended to prevent accidental use of features from contexts where they do not make sense to use and could potentially affect system performance severely.
Creates /etc/ave/user – A JSON encoded dictionary. This is done by reading a string on stdin and checking that the value is an existing OS user account. It will write the account name and the path to the account’s home directory to the created file.
Note
The contents of /etc/ave/user is used as a switch board to find all of AVE’s other configuration files. It also determines which user account should be used to run the system when it is started from the init process.
Note
The function will block until it encounters EOF on stdin.
Loads the contents of /etc/ave/user and returns it as a dictionary with the following entries:
- name: The user name or OS account used to run AVE.
- home: The directory under which .ave/config must be found.
The functions in this module are UNIX specific and would need alternative implementations on other OS’es.
Change the current process’ effective UID to that of the given user name. Can only be called by super user 0. This function is only intended for use from the init process during system boot.
Parameters: | name – An OS user name. Must be found in the password database, or a replacement authentication system. |
---|---|
Returns: | The user’s home directory. |
Parameters: | values – A dictionary where all keys are strings. |
---|
Profiles are essentially dict instances that implement __hash__(), so that they can be used as indices into other dictionaries. AVE uses profiles to communicate information about allocatable resources.
Match this profile against another profile or a dictionary: Iterate over the keys in profile and check that self contains the same key with the same value.
Parameters: | profile – A dict or Profile instance. |
---|---|
Returns: | True if the matching succeeded, False otherwise. |
Return a copy of ‘self’ that contains the properties that are mandatory for the Profile subclass, plus the properties specified by profile.
This is the base classs for all AVE processes. It supports daemonization. It also supports synchronized creation so that children can be guaranteed to be fully initialized before the parent’s call to .start() returns. This is sometimes critical to avoid race conditions when the child must install its own signal handlers instead of inheriting those of the parent.
Parameters: |
|
---|
Called by the parent process to start the new process.
Parameters: |
|
---|
Must be implemented by subclasses that accept open file descriptors in their constructors. Append descriptors that should remain open in the new process to the exclude list before passing it to close_fds() on the superclass.
Process.close_fds() is called after the process has forked but before its target function is called.
If no implementation is provided, the default implementation will close all file descriptors except 0, 1 and 2.
Parameters: | exclude – List of integers (file descriptors). |
---|
Send SIGTERM to the process. May be called from the parent process. May also be used on daemonized processes if started with synchonize=True.
Wait for the process to terminate. May only be called by the parent of the process. Must eventually be called by the parent process unless the new process was started with daemonize=True in which case init will wait for the new process. See zombie control in UNIX litterature.
Parameters: | timeout – An integer or float. Raise a Timeout exception if the process does not terminate within timeout seconds. |
---|---|
Returns: | The exit value of the terminated process. |
Check if the child process is still running. Can only be called from the parent process. The parent should call join() on processes that are no longer alive.
Returns: | Boolean. |
---|
Note
The following methods are only available to the new process as methods on self and cannot be called by the parent.
Print a time stamped message to stderr if the process was created with logging=True (see constructor).
Parameters: | message – A string. A timestamp will be added before it is printed. |
---|
Default implementation is empty. Subclasses may implement it to redirect file descriptors that were inherited by the process. Normally used to redirect stderr to log files.
Note: Process.redirect() is called after Process.close_fds().
Set OS specific process controls. Will be called by default during the child’s initialization.
Parameters: | death_signal – An integer matching a valid POSIX signal number. Defaults to 0. If set, the process will receive this signal when its parent process dies. |
---|
Default handler for the SIGTERM signal. Exit the process immediately, without calling Python exit handlers. Should normally not be implemented by subclasses.
Default handler for the SIGUSR1 signal. Creates a trace file for the process in .ave/hickup and sends SIGUSR1 to all children whose process names start with “ave-” (see proc_name parameter on the constructor). This has debugging purposes. Should not be implemented by subclasses.
This is the base class for all RPC capable AVE services. It accepts new connections on a listening TCP socket and polls the resulting sockets for traffic. Incoming JSON encoded messages are treated as remote procedure calls.
Control implements a very limited cookie based authentication mechanism to secure that clients and their sessions are not accidentally mixed up, and a similar system based on persistent cookies to limit and/or expand client capabilities.
Parameters: |
|
---|
Note
None of the Control methods are directly accessible by RPC. Subclasses are expected to expose functions that should be accessible over RPC.
Warning
The use of persistent cookies to limit or expand a client’s access rights does not constitute a security system. It is intended to prevent accidental use of features from contexts where they do not make sense.
Exit the main loop and write a last exit message on all connections before closing them. The exit message will be serialized as an Exit exception.
Defer joining of the process to the control process’ main loop. When the process is joined, Control.joined_process() will be called. Deferred joins are made non-blocking. Any object whose class inherits from ave.network.process.Process may be joined in this way. Errors encountered in the actual attempt to join the process will be printed with Process.log().
May be implemented by classes that inherit from Control. The function will be called whenever a process terminates with a deferred join. See Control.join_later() for more information.
May be used by a subclass to add new open Connection objects to the main event loop.
May be used by a subclass to remove a Connection objects from the main event loop.
May be implemented by classes that inherit directly from Control. The function will be called whenever a new connection is accepted by the Control object.
May be implemented by classes that inherit directly from Control. The function will be called whenever a previously accepted connection, or one added with add_connection(), is lost. The function is called regardless of which peer caused the connection to be lost.
Called periodically as long as there is no other activity in the main loop.
Stop accepting new clients. Close the listening socket.
Use this decorator on a subclass method to make it callable over the network. Clients can only call functions that have been marked this way.
Use this decorator on a subclass RPC method to signal that only clients that have authenticated with the primary authentication key may use the method.
Use this decorator on a subclass RPC method to signal that only clients that have authenticated with an alternate authentication key may use the method.
Class used to connect to Control objects. Creates a Connection object internally to handle socket traffic with the peer.
Parameters: |
|
---|
Find a free IP port by random picking in the selected range. If successful, a bound socket is returned.
Parameters: |
|
---|---|
Returns: | A (socket, port) tuple. |
Raises : | Exception if no free port is found in 20000 attempts. |
A non-blocking TCP/IP socket based message queue.
Parameters: |
|
---|
Returns: | The file descriptor of the underlying socket, if any. |
---|
Sets the underlying socket to a new one that is listening.
Accepts a connection attempt on the underlying socket and returns a new connection object.
Connect to the host/port provided in the constructor.
Raises : | ConnectionInProgress if the attempt could not complete immediately. The caller should poll the underlying socket for writing to determine when connection has been established. |
---|
Shuts down and closes the underlying socket.
Write a string on the underlying socket.
Raises : | ConnectionAgain if the write could not complete immediately and should be retried. The caller should poll the underlying socket for writing to determine when to retry. |
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
Read a string serialized object from the underlying socket.
Parameters: | size – The number of characters to read. |
---|---|
Returns: | A string. |
Raises : | ConnectionAgain if the write could not complete immediately and should be retried. The caller should poll the underlying socket for reading to determine when to retry. |
Raises : | ConnectionClosed if the connection is no longer open. |
Write a payload to the network, prefixed by a 32 bit network order integer that carries the byte size of payload. A reference is kept to the payload internally so that the call may be retried later if writing can not be completed in a single step.
Parameters: | payload – A string. |
---|---|
Raises : | ConnectionAgain if the write could not complete immediately and should be retried. The caller should poll the underlying socket for reading to determine when to retry. |
Raises : | ConnectionClosed if the connection is no longer open. |
Read a message from the network. The message must be composed of a 32 bit network order integer header followed by a payload whose size is encoded in the header. Partially read messages are kept internally until they can be completed or the connection is lost.
Returns: | The payload string, or None if the attempt should be tried again later. |
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
A blocking TCP/IP socket based message queue. Inherits from Connection.
Parameters: |
|
---|
Blocks until the underlying socket satisfies a condition or the wait times out.
Parameters: |
|
---|---|
Returns: | A list of (fd, event) tuples. None if no event was seen before the timeout. |
Connects the underlying socket to a remote peer.
Parameters: |
|
---|---|
Raises : | ConnectionTimeout if the connection could not be established before the timeout. |
Raises : | ConnectionRefused if there is an error condition and the attempt is not made optimistically. |
Write a string on the underlying socket.
Parameters: |
|
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
Raises : | ConnectionTimeout if the attempt could not be completed before the timeout. |
Read a string from the underlying socket.
Parameters: |
|
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
Raises : | ConnectionTimeout if the attempt could not be completed before the timeout. |
Returns: | A string. |
Write a payload to the network, prefixed by a 32 bit network order integer that carries the byte size of payload. A reference is kept to the payload internally so that the call may be retried later if writing can not be completed in a single step.
Parameters: |
|
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
Raises : | ConnectionTimeout if the attempt could not be completed before the timeout. |
Read a message from the network. The message must be composed of a 32 bit network order integer header followed by a payload whose size is encoded in the header. Partially read messages are kept internally until they can be completed or the connection is lost.
Parameters: | timeout – Maximum time in seconds to spend on the attempt. May be None for infinite waiting. |
---|---|
Raises : | ConnectionClosed if the connection is no longer open. |
Raises : | ConnectionTimeout if the attempt could not be completed before the timeout. |
Returns: | The payload string, or None if the attempt should be tried again later. |
Base class for all other AVE exception classes.
Parameters: | details – A dict where all keys are strings. One key must be the "message" key. A "type" key will be automatically set from the name of the exception class, unless provided in the details object. |
---|
Returns: | A pretty printed version of trace information included in the |
---|
exception. An empty string is returned if no trace is available.
Indicates that an operation timed out.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Indicates that an operation could not be performed because the hosting service (e.g the broker) has terminated in a controlled manner.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Used internally in the client/broker, client/session, and other Control based handshakes.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Indicates that an externally called tool has failed.
Parameters: |
|
---|
Indicates that an operation could not be performed because the hosting service (e.g the broker) has restarted and is no longer accepting new calls to the old instance.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Indicates that a background activity has terminated. Background activities are typically long running processes, such as flashing a handset or making a flashable image, that AVE starts in the background and lets the client poll for completion.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Indicates that an handset is offline.
Parameters: | details – A free form text message or a dictionary containing at least a "message" key. |
---|
Indicates that the response code of composition server was not 200.
Parameters: | details – A free form text message. |
---|
Indicates that the request was failed as composition server issue, user should try to request again. Retry HTTP codes:
502, # Bad Gateway 503, # Service (temporarily) unavailable 504 # Gateway timeout
Parameters: | details – A free form text message. |
---|
Indicates that the result of order composition was failed.
Parameters: | details – A free form text message. |
---|
Indicates that the composition was failed when downloading images
Parameters: | details – A free form text message. |
---|
These exceptions are never propagated over the network. They are generated on the client side in response to various network issues. They refer to conditions that can be detected on ave.network.connection.Connection objects.
The connection was closed.
Parameters: | msg – A string. |
---|
The connection timed out. I.e. no traffic could be read from, or written to, the conncetion within the time limit that had been set to govern all functions on the connection.
Parameters: | msg – A string. |
---|
A connection could not be established because the other end refused it.
Parameters: | msg – A string. |
---|
A non-blocking connection attempt is in progress and needs to be monitored with POSIX poll() to check for completeness.
Parameters: | msg – A string. |
---|
A non-blocking read or write operation could not be completed and must be continued later. Use POSIX poll() to determine when the connection is ready for reading or writing.
Parameters: | msg – A string. |
---|
The connection was reset.
Parameters: | msg – A string. |
---|
FdTx is short for File Descriptor Transfer. It is used when restarting brokers in a way that is invisible to clients.
All functionality in this module is UNIX specific. It seems unlikely that a matching feature can be implemented on WIN32, which might mean that service restart on that platform would have to be implemented with some limitations.
The motivation to use file descriptor transfer is based on the following dilemma:
- A session to be transfered may be temporarily unresponsive because it is busy evaluating a lengthy call.
- A broker can not tell if a session is alive and healthy without either actively polling it or at least checking if its TCP connection to the broker is open.
- A broker that is told to take over sessions started by someone else will not be able to reconnect immediately with sessions that are severely busy, and so will not be able to tell by either polling or connection openness if the session is alive.
- If the broker should wait for a busy session to become responsive, how long should it wait?
Instead of trying to solve the dilemma, FdTx allows two processes to pass open file descriptors between each other and so it doesn’t become necessary for the receiver to reconnect with sessions to check their health. The receiver can poll for error conditions on the file descriptor just like the original owner did.
Alternate solutions:
- Drop the requirement on WIN32 that service restarts should be invisible to the clients. I.e. disconnect clients when an AVE service is restarted on a WIN32 host.
- Use at least two processes per broker session: One for communication with resources and one for communication with the broker and client. This might anyway be needed in the long run to support asynchronous manipulation of resources from a threaded or muliprocessed client (if that really is what is wanted).
Implements file descriptor transfer between processes using a special feature of UNIX domain sockets. This feature is not wrapped by Python 2’s standard library, so the implementation resides in a separate C library which is interfaced with the ctypes module.
Parameters: | so_path – None or a file system path to the underlying C library that implements file descriptor transfer. |
---|
Create a UNIX domain socket in the file system and start listening on it for connections.
Parameters: |
|
---|---|
Returns: | The full socket path. |
Raises : | Exception if the file already exists. |
Accept a connection. The caller must have called listen() first.
FdTx only keeps track of one open socket internally. Calling this function more than once has undefined behavior.
Parameters: | timeout – The maximum amount of time to wait, in seconds, for a connection attempt. |
---|---|
Raises : | A Timeout exception if the timeout expires. |
Connect to an accepting peer. The attempt will be retried until it is successful or timeout expires.
Parameters: |
|
---|---|
Raises : | A Timeout exception if the timeout expires. |
Close the underlying domain socket.
Send a message containing a free form text message and an array of file descriptors.
Note
The receiver must have been told beforehand, in a separate message or by convention, how many file descriptors it will receive.
Receive a message containing a free form text message and an array of file descriptors.
Returns: | A tuple containing the message and a list of file descriptors. |
---|