Marche API

These are the base classes you need to inherit from when implementing a new job or interface.

Base Job class

class marche.jobs.base.ConfigMixin[source]

Mixin for receiving and sending a number of config files, stored as self.config_files, without looking at the service/instance.

Since only the basenames are transferred to the client as identifiers, all configured config files must have different basenames.

configure_config_mixin(config)[source]

To be called from the Job’s configure().

receive_config(service, instance)[source]
send_config(service, instance, filename, contents)[source]
class marche.jobs.base.Job(jobtype, name, config, log, event_callback)[source]

This is the basic job class.

All methods that implement a Marche command should raise marche.jobs.Fault with a nice error message on error. Other exceptions are caught but will cause tracebacks to be written to the logfile.

All methods that start/stop services can also raise marche.jobs.Busy to indicate that the operation cannot be done at the moment, because a job is already starting/stopping.

The job has a thread-lock, which needs to be held for operations where it is not documented that they are safe without locking.

__init__(jobtype, name, config, log, event_callback)[source]

The constructor should not be overridden, rather implement the configure() method.

It sets the following instance attributes:

name
The job name (the name argument).
config
The job config dictionary (the config argument).
log
A logger for the job (a child of the log argument).
all_service_status()[source]

Return a dict with the tuple of status constants of all services/instances.

Used by the poller to get the status of all services faster if possible.

By default, this just loops through the services.

check()[source]

Check if the job can be used at all (on this system).

This is called on daemon initialization for each configured job, and if it returns False, the job is not further used.

If this returns False, it should also do some logging output to inform the user of the reason that the job cannot work.

The default is to return True.

check_permission(level, client)[source]

Ensure that the client has permission to do an action that would normally have level. If not, raises Fault.

Safe to call without the job lock held.

configure(config)[source]

Check and process the configuration in config.

The default implementation does nothing.

determine_permissions(client)[source]

Return which normal levels of actions this client can do.

Safe to call without the job lock held.

get_services()[source]

Return a list of (service, instance) names that this job supports. This should be very cheap, so the list of services should be determined in the constructor and only returned here.

For jobs without sub-instances, return (service, '').

This must be implemented by subclasses.

Must be safe to call without the job lock held.

has_permission(level, client)[source]

Query if the client has permission to do an action that would normally have level.

Safe to call without the job lock held.

init()[source]

Initialize the job.

This can further configure the job after the feasibility check has run.

The default is to start the poller, so the base class method should be normally called by subclasses.

invalidate(service, instance)[source]

Invalidate polled and cached status.

poll_now()[source]

Let the poller poll now, if possible.

polled_service_status(service, instance)[source]

Return the service status, if possible from the poller cache.

Must be called without the job lock held.

receive_config(service, instance)[source]

Return the contents of the config file(s) of the service, if possible.

The return value must be a dict mapping the file name to the decoded string content for each file.

The default is to return no config files.

restart_service(service, instance)[source]

Restart the service with the given name.

The method should not block; instead, if the service takes a while to restart the returned status should be STARTING during that time.

This must be implemented by subclasses.

send_config(service, instance, filename, contents)[source]

Transfer a changed config file to the service, and update it. Usually, this means that the new file is written to disk, but it could also take some further action.

It should not restart the service, even if that is necessary for the config file to take effect.

If receive_config returns files, this must be implemented. The default is to raise an exception that no files are accepted.

service_description(service, instance)[source]

Return a string description of the service with the given name.

Must be safe to call without the job lock held.

service_logs(service, instance)[source]

Return the contents of the logfile(s) of the service, if possible.

The return value must be a dictionary of file names and contents.

The default is to return no logfiles.

service_output(service, instance)[source]

Return the console output of the last attempt to start/stop/restart the service, as a list of strings (lines).

The default is to return no output.

service_status(service, instance)[source]

Return the tuple of status constant and extended status of the service with the given name.

The status should be one of the constants defined in the marche.jobs module:

  • DEAD (not running, for services that should run continuously)
  • NOT_RUNNING (not running, for one-shot services)
  • STARTING (currently starting to run)
  • INITIALIZING (process running, but not started up)
  • RUNNING (running OK)
  • WARNING (running, but not completely/with errors)
  • STOPPING (currently stopping to run)
  • NOT_AVAILABLE (not running, cannot start) – this should only be necessary if the feasibility check cannot already rule it out

Not all states have to be supported; the most basic set of states to return is DEAD or RUNNING.

The extended status is just a string with more information if needed and available.

This must be implemented by subclasses.

shutdown()[source]

Shut the job down.

The default is to stop the poller, so the base class method should be normally called by subclasses.

start_service(service, instance)[source]

Start the service with the given name.

The method should not block; instead, if the service takes a while to start the returned status should be STARTING during that time.

This must be implemented by subclasses.

stop_service(service, instance)[source]

Stop the service with the given name.

The method should not block; instead, if the service takes a while to stop the returned status should be STOPPING during that time.

This must be implemented by subclasses.

class marche.jobs.base.LogfileMixin[source]

Mixin for configuring and sending a number of logfiles, stored as self.log_files, without looking at the service/instance.

configure_logfile_mixin(config)[source]
service_logs(service, instance)[source]

Base Authenticator class

Basic authenticator class.

class marche.auth.base.Authenticator(config, log)[source]
authenticate(user, passwd)[source]

Return a marche.permission.ClientInfo object with the assigned permission level if the user and password are correct.

Otherwise, return None to give other authenticators a chance.

init()[source]

Implement to do something on init.

The constructor has stored the configuration in self.config, and created a logger in self.log.

Base Interface class

Base interface class.

class marche.iface.base.Interface(config, jobhandler, authhandler, log)[source]
emit_event(event)[source]

Emit an event to clients.

This method will be called from various threads; it is the interface’s job to ensure that this is safe.

iface_name = 'iface'

The name of the interface, must be the same as the module name.

init()[source]

Initialize the interface. Called by the constructor.

The following instance attributes are set:

jobhandler
The JobHandler instance.
config
The config dictionary for the interface.
log
The logger for the interface.
needs_events = True

True if the interface can emit or otherwise handle events.

run()[source]

Run the interface. This should start the main loop of the interface in a separate thread and return.

shutdown()[source]

Shutdown the interface. This should stop the main loop of the interface if possible.