diff --git a/quantum/common/extensions.py b/quantum/common/extensions.py index 7ad802fa96..2682aa9299 100644 --- a/quantum/common/extensions.py +++ b/quantum/common/extensions.py @@ -24,6 +24,7 @@ import logging import webob.dec import webob.exc +from quantum.manager import QuantumManager from quantum.common import exceptions from quantum.common import wsgi from gettext import gettext as _ @@ -231,8 +232,9 @@ class ExtensionMiddleware(wsgi.Middleware): ext_mgr=None): self.ext_mgr = (ext_mgr - or ExtensionManager(config_params.get('api_extensions_path', - ''))) + or ExtensionManager( + config_params.get('api_extensions_path', + ''), QuantumManager().plugin)) mapper = routes.Mapper() @@ -296,11 +298,11 @@ class ExtensionManager(object): example extension implementation. """ - - def __init__(self, path): + def __init__(self, path, plugin): LOG.info(_('Initializing extension manager.')) self.path = path + self.plugin = plugin self.extensions = {} self._load_all_extensions() @@ -350,10 +352,10 @@ class ExtensionManager(object): LOG.debug(_('Ext description: %s'), extension.get_description()) LOG.debug(_('Ext namespace: %s'), extension.get_namespace()) LOG.debug(_('Ext updated: %s'), extension.get_updated()) + return self.plugin.supports_extension(extension) except AttributeError as ex: LOG.exception(_("Exception loading extension: %s"), unicode(ex)) return False - return True def _load_all_extensions(self): """Load extensions from the configured path. @@ -392,7 +394,6 @@ class ExtensionManager(object): 'file': ext_path}) continue new_ext = new_ext_class() - self._check_extension(new_ext) self.add_extension(new_ext) def add_extension(self, ext): diff --git a/quantum/manager.py b/quantum/manager.py index a9662d8eb6..00aefc6987 100644 --- a/quantum/manager.py +++ b/quantum/manager.py @@ -26,6 +26,7 @@ The caller should make sure that QuantumManager is a singleton. """ import gettext import os +import logging gettext.install('quantum', unicode=1) import os @@ -33,6 +34,7 @@ import os from common import utils from quantum_plugin_base import QuantumPluginBase +LOG = logging.getLogger('quantum.manager') CONFIG_FILE = "plugins.ini" @@ -51,13 +53,13 @@ class QuantumManager(object): else: self.configuration_file = config plugin_location = utils.getPluginFromConfig(self.configuration_file) - print "PLUGIN LOCATION:%s" % plugin_location + LOG.debug("PLUGIN LOCATION:%s" % plugin_location) plugin_klass = utils.import_class(plugin_location) if not issubclass(plugin_klass, QuantumPluginBase): raise Exception("Configured Quantum plug-in " \ "didn't pass compatibility test") else: - print("Successfully imported Quantum plug-in." \ + LOG.debug("Successfully imported Quantum plug-in." \ "All compatibility tests passed\n") self.plugin = plugin_klass() diff --git a/quantum/plugins/SamplePlugin.py b/quantum/plugins/SamplePlugin.py index 376456a6c8..fa8da29d95 100644 --- a/quantum/plugins/SamplePlugin.py +++ b/quantum/plugins/SamplePlugin.py @@ -434,3 +434,6 @@ class FakePlugin(object): # TODO(salvatore-orlando): # Should unplug on port without attachment raise an Error? port['attachment'] = None + + def supports_extension(self, extension): + return True diff --git a/quantum/quantum_plugin_base.py b/quantum/quantum_plugin_base.py index 8e3f1f8e15..52947aa7ec 100644 --- a/quantum/quantum_plugin_base.py +++ b/quantum/quantum_plugin_base.py @@ -230,6 +230,15 @@ class QuantumPluginBase(object): """ pass + @abstractmethod + def supports_extension(self, extension): + """ + Returns if the extension is suppoorted + + :returns: True or False + """ + pass + @classmethod def __subclasshook__(cls, klass): """ diff --git a/tests/unit/test_extensions.py b/tests/unit/test_extensions.py index 9579a0d720..7a02cdeb47 100644 --- a/tests/unit/test_extensions.py +++ b/tests/unit/test_extensions.py @@ -23,7 +23,7 @@ from webtest import TestApp from quantum.common import extensions from quantum.common import wsgi from quantum.common import config - +from quantum.common.extensions import ExtensionManager extension_index_response = "Try to say this Mr. Knox, sir..." test_conf_file = os.path.join(os.path.dirname(__file__), os.pardir, @@ -71,38 +71,63 @@ class ResourceExtensionTest(unittest.TestCase): self.assertEqual(404, response.status_int) +class StubExtension(object): + + def __init__(self, alias="stub_extension"): + self.alias = alias + + def get_name(self): + return "Stub Extension" + + def get_alias(self): + return self.alias + + def get_description(self): + return "" + + def get_namespace(self): + return "" + + def get_updated(self): + return "" + + +class StubPlugin(object): + + def __init__(self, supported_extensions=[]): + self.supported_extensions = supported_extensions + + def supports_extension(self, extension): + return extension.get_alias() in self.supported_extensions + + class ExtensionManagerTest(unittest.TestCase): def test_invalid_extensions_are_not_registered(self): - class ValidExtension(object): - - def get_name(self): - return "Valid Extension" - - def get_alias(self): - return "valid_extension" - - def get_description(self): - return "" - - def get_namespace(self): - return "" - - def get_updated(self): - return "" - class InvalidExtension(object): def get_alias(self): return "invalid_extension" - extended_app = setup_extensions_middleware() - ext_mgr = extended_app.ext_mgr + ext_mgr = setup_extensions_middleware().ext_mgr ext_mgr.add_extension(InvalidExtension()) - ext_mgr.add_extension(ValidExtension()) + ext_mgr.add_extension(StubExtension("valid_extension")) + self.assertTrue('valid_extension' in ext_mgr.extensions) self.assertFalse('invalid_extension' in ext_mgr.extensions) + def test_unsupported_extensions_are_not_loaded(self): + ext_mgr = setup_extensions_middleware().ext_mgr + ext_mgr.plugin = StubPlugin(supported_extensions=["e1", "e3"]) + + ext_mgr.add_extension(StubExtension("e1")) + ext_mgr.add_extension(StubExtension("e2")) + ext_mgr.add_extension(StubExtension("e3")) + + self.assertTrue("e1" in ext_mgr.extensions) + self.assertFalse("e2" in ext_mgr.extensions) + self.assertTrue("e3" in ext_mgr.extensions) + class ActionExtensionTest(unittest.TestCase):