summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Yeoh <cyeoh@au1.ibm.com>2013-05-18 12:48:44 +0930
committerChris Yeoh <cyeoh@au1.ibm.com>2013-06-07 10:06:52 +0930
commitd5ae8d5667fee22ba4df4feea53224874a19d167 (patch)
tree8e04a8005d8417460600b43518380854d6653946
parent8b632660aff27582c9b8ced3e0642399f3139f81 (diff)
downloadnova-d5ae8d5667fee22ba4df4feea53224874a19d167.tar.gz
nova-d5ae8d5667fee22ba4df4feea53224874a19d167.tar.xz
nova-d5ae8d5667fee22ba4df4feea53224874a19d167.zip
Adds check that the core V3 API is loaded
Adds infrastructure to be able to check that the core V3 API plugins are present and raise an exception and abort if any are missing. The list is deliberately hard coded though it is not yet complete and will be expanded as the core APIs are ported and it is decided exactly what will be considered to be the core API. Partially implements blueprint v3-api-extension-framework Change-Id: Ic2c1d5cd6836ee18819106558880682cf4cda487
-rw-r--r--nova/api/openstack/__init__.py20
-rw-r--r--nova/exception.py4
-rw-r--r--nova/tests/api/openstack/compute/test_v3_extensions.py69
3 files changed, 93 insertions, 0 deletions
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
index 3687ce111..3455b812d 100644
--- a/nova/api/openstack/__init__.py
+++ b/nova/api/openstack/__init__.py
@@ -28,6 +28,7 @@ import webob.exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
+from nova import exception
from nova import notifications
from nova.openstack.common import log as logging
from nova import utils
@@ -55,6 +56,11 @@ CONF = cfg.CONF
CONF.register_group(api_opts_group)
CONF.register_opts(api_opts, api_opts_group)
+# List of v3 API extensions which are considered to form
+# the core API and so must be present
+# TODO(cyeoh): Expand this list as the core APIs are ported to V3
+API_V3_CORE_EXTENSIONS = set(['servers'])
+
class FaultWrapper(base_wsgi.Middleware):
"""Calls down the middleware stack, making exceptions into faults."""
@@ -306,8 +312,22 @@ class APIRouterV3(base_wsgi.Router):
mapper=mapper)
self.api_extension_manager.map(self._register_controllers)
+ missing_core_extensions = self.get_missing_core_extensions(
+ self.loaded_extension_info.get_extensions().keys())
+ if missing_core_extensions:
+ LOG.critical(_("Missing core API extensions: %s"),
+ missing_core_extensions)
+ raise exception.CoreAPIMissing(
+ missing_apis=missing_core_extensions)
+
super(APIRouterV3, self).__init__(mapper)
+ @staticmethod
+ def get_missing_core_extensions(extensions_loaded):
+ extensions_loaded = set(extensions_loaded)
+ missing_extensions = API_V3_CORE_EXTENSIONS - extensions_loaded
+ return missing_extensions
+
@property
def loaded_extension_info(self):
raise NotImplementedError()
diff --git a/nova/exception.py b/nova/exception.py
index bbe5442f1..62bcf1c76 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -1220,3 +1220,7 @@ class OrphanedObjectError(NovaException):
class IncompatibleObjectVersion(NovaException):
message = _('Version %(objver)s of %(objname)s is not supported')
+
+
+class CoreAPIMissing(NovaException):
+ message = _("Core API extensions are missing: %(missing_apis)s")
diff --git a/nova/tests/api/openstack/compute/test_v3_extensions.py b/nova/tests/api/openstack/compute/test_v3_extensions.py
index f7c1bf39c..97429ca45 100644
--- a/nova/tests/api/openstack/compute/test_v3_extensions.py
+++ b/nova/tests/api/openstack/compute/test_v3_extensions.py
@@ -15,9 +15,12 @@
# under the License.
from oslo.config import cfg
+import stevedore
+from nova.api import openstack
from nova.api.openstack import compute
from nova.api.openstack.compute import plugins
+from nova import exception
from nova import test
CONF = cfg.CONF
@@ -28,8 +31,35 @@ class fake_bad_extension(object):
alias = "fake-bad"
+class fake_stevedore_enabled_extensions(object):
+ def __init__(self, namespace, check_func, invoke_on_load=False,
+ invoke_args=(), invoke_kwds={}):
+ self.extensions = []
+
+ def map(self, func, *args, **kwds):
+ pass
+
+ def __iter__(self):
+ return iter(self.extensions)
+
+
+class fake_loaded_extension_info(object):
+ def __init__(self):
+ self.extensions = {}
+
+ def register_extension(self, ext):
+ self.extensions[ext] = ext
+ return True
+
+ def get_extensions(self):
+ return {'core1': None, 'core2': None, 'noncore1': None}
+
+
class ExtensionLoadingTestCase(test.TestCase):
+ def _set_v3_core(self, core_extensions):
+ openstack.API_V3_CORE_EXTENSIONS = core_extensions
+
def test_extensions_loaded(self):
app = compute.APIRouterV3()
self.assertIn('servers', app._loaded_extension_info.extensions)
@@ -70,3 +100,42 @@ class ExtensionLoadingTestCase(test.TestCase):
self.assertNotIn('os-fixed-ips', app._loaded_extension_info.extensions)
self.assertIn('servers', app._loaded_extension_info.extensions)
self.assertEqual(len(app._loaded_extension_info.extensions), 1)
+
+ def test_get_missing_core_extensions(self):
+ v3_core = openstack.API_V3_CORE_EXTENSIONS
+ openstack.API_V3_CORE_EXTENSIONS = set(['core1', 'core2'])
+ self.addCleanup(self._set_v3_core, v3_core)
+ self.assertEqual(len(compute.APIRouterV3.get_missing_core_extensions(
+ ['core1', 'core2', 'noncore1'])), 0)
+ missing_core = compute.APIRouterV3.get_missing_core_extensions(
+ ['core1'])
+ self.assertEqual(len(missing_core), 1)
+ self.assertIn('core2', missing_core)
+ missing_core = compute.APIRouterV3.get_missing_core_extensions([])
+ self.assertEqual(len(missing_core), 2)
+ self.assertIn('core1', missing_core)
+ self.assertIn('core2', missing_core)
+ missing_core = compute.APIRouterV3.get_missing_core_extensions(
+ ['noncore1'])
+ self.assertEqual(len(missing_core), 2)
+ self.assertIn('core1', missing_core)
+ self.assertIn('core2', missing_core)
+
+ def test_core_extensions_present(self):
+ self.stubs.Set(stevedore.enabled, 'EnabledExtensionManager',
+ fake_stevedore_enabled_extensions)
+ self.stubs.Set(plugins, 'LoadedExtensionInfo',
+ fake_loaded_extension_info)
+ v3_core = openstack.API_V3_CORE_EXTENSIONS
+ openstack.API_V3_CORE_EXTENSIONS = set(['core1', 'core2'])
+ self.addCleanup(self._set_v3_core, v3_core)
+ # if no core API extensions are missing then an exception will
+ # not be raised when creating an instance of compute.APIRouterV3
+ _ = compute.APIRouterV3()
+
+ def test_core_extensions_missing(self):
+ self.stubs.Set(stevedore.enabled, 'EnabledExtensionManager',
+ fake_stevedore_enabled_extensions)
+ self.stubs.Set(plugins, 'LoadedExtensionInfo',
+ fake_loaded_extension_info)
+ self.assertRaises(exception.CoreAPIMissing, compute.APIRouterV3)