Loading cloudcontrol/node/host/plugins.py 0 → 100644 +93 −0 Changes for cloudcontrol/node/host/plugins.py: 93 added lines, 0 removed lines. Original line number Diff line number Diff line import imp import logging from collections import defaultdict from cloudcontrol.common.client.tags import Tag from cloudcontrol.common.jobs import Job from cloudcontrol.common.tql.db.helpers import taggify logger = logging.getLogger(__name__) def _tag_direct_use_error(*args, **kwargs): raise RuntimeError('Plugins tags can\'t be called directly') class Plugin(object): """ Represent a loaded cloudcontrol plugin. """ def __init__(self, logger, tag_db, name, sha1, plugin_body): self.logger = logger self.name = name self.sha1 = sha1 self.tag_db = tag_db self.methods = {} self.events = defaultdict(lambda: []) self._load_module(plugin_body) self.trigger('install', self) def _load_module(self, plugin_body): # load the code into a module: module = imp.new_module(self.name) module.logger = self.logger module.tag = self._decorator_tag module.method = self._decorator_method module.on = self._decorator_event try: exec plugin_body in module.__dict__ except Exception: err_msg = 'Error during plugin installation (%s)' % self.name logger.exception(err_msg) raise RuntimeError(err_msg) else: # prevents module from being garbage collected self.module = module def _decorator_tag(self, ttl=-1, refresh=None, name=None): def decorator(func): tag = Tag(func.__name__ if name is None else name, lambda: taggify(func()), ttl=ttl, refresh=refresh) self.tag_db.add_tag(tag) return _tag_direct_use_error return decorator def _decorator_method(self, name=None): def decorator(func): self.methods[func.__name__ if name is None else name] = func return func return decorator def _decorator_event(self, event): def decorator(func): self.events[event].append(func) return func return decorator def trigger(self, event, *args, **kwargs): """Trigger an event.""" for func in self.events[event]: func(*args, **kwargs) def uninstall(self): self.trigger('uninstall') # shutdown the tags database: self.tag_db.set_parent(None) class PluginMethodJob(Job): """Job that run a plugin method.""" def job(self, plugin_name, method_name, method, method_kwargs): kwargs_str = ', '.join(('%s=%s' % (k, v) for k, v in method_kwargs.iteritems())) self.title = 'Plugin: %s.%s(%s)' % (plugin_name, method_name, kwargs_str) try: returned = method(self, **method_kwargs) except Exception: self.logger.exception('Error while executing method') raise if returned is not None: self.attachment('output').write(returned) Loading
cloudcontrol/node/host/plugins.py 0 → 100644 +93 −0 Changes for cloudcontrol/node/host/plugins.py: 93 added lines, 0 removed lines. Original line number Diff line number Diff line import imp import logging from collections import defaultdict from cloudcontrol.common.client.tags import Tag from cloudcontrol.common.jobs import Job from cloudcontrol.common.tql.db.helpers import taggify logger = logging.getLogger(__name__) def _tag_direct_use_error(*args, **kwargs): raise RuntimeError('Plugins tags can\'t be called directly') class Plugin(object): """ Represent a loaded cloudcontrol plugin. """ def __init__(self, logger, tag_db, name, sha1, plugin_body): self.logger = logger self.name = name self.sha1 = sha1 self.tag_db = tag_db self.methods = {} self.events = defaultdict(lambda: []) self._load_module(plugin_body) self.trigger('install', self) def _load_module(self, plugin_body): # load the code into a module: module = imp.new_module(self.name) module.logger = self.logger module.tag = self._decorator_tag module.method = self._decorator_method module.on = self._decorator_event try: exec plugin_body in module.__dict__ except Exception: err_msg = 'Error during plugin installation (%s)' % self.name logger.exception(err_msg) raise RuntimeError(err_msg) else: # prevents module from being garbage collected self.module = module def _decorator_tag(self, ttl=-1, refresh=None, name=None): def decorator(func): tag = Tag(func.__name__ if name is None else name, lambda: taggify(func()), ttl=ttl, refresh=refresh) self.tag_db.add_tag(tag) return _tag_direct_use_error return decorator def _decorator_method(self, name=None): def decorator(func): self.methods[func.__name__ if name is None else name] = func return func return decorator def _decorator_event(self, event): def decorator(func): self.events[event].append(func) return func return decorator def trigger(self, event, *args, **kwargs): """Trigger an event.""" for func in self.events[event]: func(*args, **kwargs) def uninstall(self): self.trigger('uninstall') # shutdown the tags database: self.tag_db.set_parent(None) class PluginMethodJob(Job): """Job that run a plugin method.""" def job(self, plugin_name, method_name, method, method_kwargs): kwargs_str = ', '.join(('%s=%s' % (k, v) for k, v in method_kwargs.iteritems())) self.title = 'Plugin: %s.%s(%s)' % (plugin_name, method_name, kwargs_str) try: returned = method(self, **method_kwargs) except Exception: self.logger.exception('Error while executing method') raise if returned is not None: self.attachment('output').write(returned)