1
from logging import info, exception
3
from landscape.lib.bpickle import loads
4
from landscape.lib.dbus_util import Object, array_to_string
5
from landscape.log import format_object
8
class HandlerNotFoundError(Exception):
9
"""A handler for the given message type was not found."""
12
class PluginConfigError(Exception):
13
"""There was an error registering or configuring a plugin."""
16
class PluginRegistry(object):
17
"""A central integration point for plugins."""
21
self._plugin_names = {}
22
self._registered_messages = {}
24
def add(self, plugin):
27
The plugin's C{register} method will be called with this registry as
30
If the plugin has a C{plugin_name} attribute, it will be possible to
31
look up the plugin later with L{get_plugin}.
33
info("Registering plugin %s.", format_object(plugin))
34
self._plugins.append(plugin)
35
if hasattr(plugin, 'plugin_name'):
36
self._plugin_names[plugin.plugin_name] = plugin
39
def get_plugins(self):
40
"""Get the list of plugins."""
43
def get_plugin(self, name):
44
"""Get a particular plugin by name."""
45
return self._plugin_names[name]
47
def register_message(self, type, handler):
49
Register interest in a particular type of Landscape server->client
52
self._registered_messages[type] = handler
54
def dispatch_message(self, message):
55
type = message["type"]
56
handler = self._registered_messages.get(type)
57
if handler is not None:
59
return handler(message)
61
exception("Error running message handler for type %r: %r"
64
raise HandlerNotFoundError(type)
68
"""A convenience for writing plugins.
70
This provides a register method which will set up a bunch of
71
reactor handlers in the idiomatic way.
73
If C{run} is defined on subclasses, it will be called every C{run_interval}
74
seconds after being registered.
76
@cvar run_interval: The interval, in seconds, to execute the
77
C{run} method. If set to C{None}, then C{run} will not be
83
def register(self, registry):
84
self.registry = registry
85
if hasattr(self, "run") and self.run_interval is not None:
86
registry.reactor.call_every(self.run_interval, self.run)
90
class BrokerPlugin(Object):
92
A DBus object which exposes the 'plugin' interface that the Broker expects
95
def __init__(self, bus, registry):
96
Object.__init__(self, bus)
97
self.registry = registry
103
from twisted.internet import reactor
104
reactor.callLater(0.1, reactor.stop)
106
def dispatch_message(self, blob):
108
Call the L{PluginRegistry}'s C{dispatch_message} method and return True
109
if a message handler was found and False otherwise.
111
message = loads(array_to_string(blob))
113
self.registry.dispatch_message(message)
115
except HandlerNotFoundError:
118
def message(self, blob):
120
Call L{dispatch_message} with C{blob} and return the result.
122
return self.dispatch_message(blob)