From 856503b064e79bc0daf1d27bf2ce1fa4ecd62160 Mon Sep 17 00:00:00 2001 From: Andrew Bogott Date: Wed, 13 Jun 2012 11:51:32 -0500 Subject: Add common plugin framework. For blueprint novaplugins. It turns out that most of the plugin framework applies equally well to other projects, so it's going into Nova via common so that other projects can pull it in with a minimum of fuss. Change-Id: Ia4455a8ca0b8c1c3e4b0b9647e8cacaf0a47c914 --- openstack/common/plugin/pluginmanager.py | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 openstack/common/plugin/pluginmanager.py (limited to 'openstack/common/plugin/pluginmanager.py') diff --git a/openstack/common/plugin/pluginmanager.py b/openstack/common/plugin/pluginmanager.py new file mode 100644 index 0000000..0095135 --- /dev/null +++ b/openstack/common/plugin/pluginmanager.py @@ -0,0 +1,86 @@ +# Copyright 2012 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import imp +import os +import pkg_resources + +from openstack.common import cfg +from openstack.common import log as logging +from openstack.common.notifier import list_notifier + + +CONF = cfg.CONF +LOG = logging.getLogger(__name__) + + +class PluginManager(object): + """Manages plugin entrypoints and loading. + + For a service to implement this plugin interface for callback purposes: + + - Make use of the openstack-common notifier system + - Instantiate this manager in each process (passing in + project and service name) + + For an API service to extend itself using this plugin interface, + it needs to query the plugin_extension_factory provided by + the already-instantiated PluginManager. + """ + + def __init__(self, project_name, service_name): + """ Construct Plugin Manager; load and initialize plugins. + + project_name (e.g. 'nova' or 'glance') is used + to construct the entry point that identifies plugins. + + The service_name (e.g. 'compute') is passed on to + each plugin as a raw string for it to do what it will. + """ + self._project_name = project_name + self._service_name = service_name + self.plugins = [] + + # Make sure we're using the list_notifier. + if not hasattr(CONF, "list_notifier_drivers"): + CONF.list_notifier_drivers = [] + old_notifier = CONF.notification_driver + CONF.notification_driver = 'openstack.common.notifier.list_notifier' + if (old_notifier and + old_notifier != 'openstack.common.notifier.list_notifier'): + list_notifier.add_driver(old_notifier) + + def load_plugins(self): + self.plugins = [] + + for entrypoint in pkg_resources.iter_entry_points('%s.plugin' % + self._project_name): + try: + pluginclass = entrypoint.load() + plugin = pluginclass(self._service_name) + self.plugins.append(plugin) + except Exception, exc: + LOG.error(_("Failed to load plugin %(plug)s: %(exc)s") % + {'plug': entrypoint, 'exc': exc}) + + for plugin in self.plugins: + for notifier in plugin.notifiers: + list_notifier.add_driver(notifier) + + def plugin_extension_factory(self, ext_mgr): + for plugin in self.plugins: + descriptors = plugin.api_extension_descriptors + for descriptor in descriptors: + ext_mgr.load_extension(descriptor) -- cgit