From d8673cb256e17fec05788907fce66898a36ddcf2 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Wed, 8 Jun 2016 15:27:19 -0400 Subject: [PATCH] remove processing of blacklist/whitelist/corelist extensions This removes the facility in the API router to have limited lists of extensions. From this point forward, what is in Nova is loaded, no exceptions. A number of unit tests and fakes have to be updated to pass after this, as many unit tests were sending small lists of extensions to the API router to simplify the responses they were getting back. This also required stubbing out the request db cache in some cases, because extensions later get content from there to avoid additional db hits. As well as adjusting a few samples tests which now return more data because all the extensions are always loaded. There is much cleanup to happen after this, but this is the smallest unit to get us over this boundary which will start letting us to refold extensions back into the base views (and massively simplify the API code). This does not yet remove the config options because there is another place those get used in servers.py and the testing fallout of that is much bigger. The reno will come with that patch. Change-Id: I3e72f5e23ce39148f31dfdb76d18f403c6d04842 --- .../availability-zone-post-resp.json | 6 +++ nova/api/openstack/__init__.py | 46 +------------------ .../availability-zone-post-resp.json.tpl | 6 +++ .../openstack/compute/test_config_drive.py | 6 +++ .../api/openstack/compute/test_extensions.py | 44 ------------------ .../openstack/compute/test_flavor_disabled.py | 10 ++++ .../api/openstack/compute/test_flavor_rxtx.py | 2 + .../api/openstack/compute/test_flavor_swap.py | 4 ++ .../openstack/compute/test_flavorextradata.py | 6 +++ .../api/openstack/compute/test_keypairs.py | 7 +++ nova/tests/unit/api/openstack/fakes.py | 2 +- 11 files changed, 49 insertions(+), 90 deletions(-) diff --git a/doc/api_samples/os-availability-zone/availability-zone-post-resp.json b/doc/api_samples/os-availability-zone/availability-zone-post-resp.json index d5821b679c9b..a13b8b9a5b38 100644 --- a/doc/api_samples/os-availability-zone/availability-zone-post-resp.json +++ b/doc/api_samples/os-availability-zone/availability-zone-post-resp.json @@ -11,6 +11,12 @@ "href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/3e45fa2a-5204-466f-a684-c2a8e1c82d7f", "rel": "bookmark" } + ], + "OS-DCF:diskConfig": "AUTO", + "security_groups": [ + { + "name": "default" + } ] } } \ No newline at end of file diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 60190f94005d..0f2aee7bc556 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -25,11 +25,8 @@ import stevedore import webob.dec import webob.exc -from nova.api.openstack import extensions from nova.api.openstack import wsgi import nova.conf -from nova import exception -from nova.i18n import _LC from nova.i18n import _LE from nova.i18n import _LI from nova.i18n import _LW @@ -245,40 +242,7 @@ class APIRouterV21(base_wsgi.Router): # all extensions but eventually should be able to exclude # based on a config file def _check_load_extension(ext): - if (self.init_only is None or ext.obj.alias in - self.init_only) and isinstance(ext.obj, - extensions.V21APIExtensionBase): - - # Check whitelist is either empty or if not then the extension - # is in the whitelist - if (not CONF.osapi_v21.extensions_whitelist or - ext.obj.alias in CONF.osapi_v21.extensions_whitelist): - - # Check the extension is not in the blacklist - blacklist = CONF.osapi_v21.extensions_blacklist - if ext.obj.alias not in blacklist: - return self._register_extension(ext) - return False - - if (CONF.osapi_v21.extensions_blacklist or - CONF.osapi_v21.extensions_whitelist): - LOG.warning( - _LW('In the M release you must run all of the API. ' - 'The concept of API extensions will be removed from ' - 'the codebase to ensure there is a single Compute API.')) - - self.init_only = init_only - LOG.debug("v21 API Extension Blacklist: %s", - CONF.osapi_v21.extensions_blacklist) - LOG.debug("v21 API Extension Whitelist: %s", - CONF.osapi_v21.extensions_whitelist) - - in_blacklist_and_whitelist = set( - CONF.osapi_v21.extensions_whitelist).intersection( - CONF.osapi_v21.extensions_blacklist) - if len(in_blacklist_and_whitelist) != 0: - LOG.warning(_LW("Extensions in both blacklist and whitelist: %s"), - list(in_blacklist_and_whitelist)) + return self._register_extension(ext) self.api_extension_manager = stevedore.enabled.EnabledExtensionManager( namespace=self.api_extension_namespace(), @@ -298,14 +262,6 @@ class APIRouterV21(base_wsgi.Router): self._register_resources_check_inherits(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 not self.init_only and missing_core_extensions: - LOG.critical(_LC("Missing core API extensions: %s"), - missing_core_extensions) - raise exception.CoreAPIMissing( - missing_apis=missing_core_extensions) - LOG.info(_LI("Loaded extensions: %s"), sorted(self.loaded_extension_info.get_extensions().keys())) super(APIRouterV21, self).__init__(mapper) diff --git a/nova/tests/functional/api_sample_tests/api_samples/os-availability-zone/availability-zone-post-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/os-availability-zone/availability-zone-post-resp.json.tpl index 5358868400cd..c971df42ab28 100644 --- a/nova/tests/functional/api_sample_tests/api_samples/os-availability-zone/availability-zone-post-resp.json.tpl +++ b/nova/tests/functional/api_sample_tests/api_samples/os-availability-zone/availability-zone-post-resp.json.tpl @@ -11,6 +11,12 @@ "href": "%(compute_endpoint)s/servers/%(uuid)s", "rel": "bookmark" } + ], + "OS-DCF:diskConfig": "AUTO", + "security_groups": [ + { + "name": "default" + } ] } } diff --git a/nova/tests/unit/api/openstack/compute/test_config_drive.py b/nova/tests/unit/api/openstack/compute/test_config_drive.py index 652cf2409e70..622d98e139bb 100644 --- a/nova/tests/unit/api/openstack/compute/test_config_drive.py +++ b/nova/tests/unit/api/openstack/compute/test_config_drive.py @@ -52,6 +52,12 @@ class ConfigDriveTestV21(test.TestCase): fakes.fake_instance_get()) self.stub_out('nova.db.instance_get_by_uuid', fakes.fake_instance_get()) + # NOTE(sdague): because of the way extensions work, we have to + # also stub out the Request compute cache with a real compute + # object. Delete this once we remove all the gorp of + # extensions modifying the server objects. + self.stub_out('nova.api.openstack.wsgi.Request.get_db_instance', + fakes.fake_compute_get()) req = webob.Request.blank(self.base_url + uuids.sentinel) req.headers['Content-Type'] = 'application/json' response = req.get_response(self.app) diff --git a/nova/tests/unit/api/openstack/compute/test_extensions.py b/nova/tests/unit/api/openstack/compute/test_extensions.py index 206fbae60543..c5a7f8c24b87 100644 --- a/nova/tests/unit/api/openstack/compute/test_extensions.py +++ b/nova/tests/unit/api/openstack/compute/test_extensions.py @@ -70,13 +70,6 @@ class ExtensionLoadingTestCase(test.NoDBTestCase): loaded_ext_info = extension_info.LoadedExtensionInfo() self.assertFalse(loaded_ext_info._check_extension(fake_bad_extension)) - def test_extensions_blacklist(self): - app = compute.APIRouterV21() - self.assertIn('os-hosts', app._loaded_extension_info.extensions) - CONF.set_override('extensions_blacklist', ['os-hosts'], 'osapi_v21') - app = compute.APIRouterV21() - self.assertNotIn('os-hosts', app._loaded_extension_info.extensions) - @mock.patch('nova.api.openstack.APIRouterV21._register_resources_list') def test_extensions_inherit(self, mock_register): app = compute.APIRouterV21() @@ -106,36 +99,6 @@ class ExtensionLoadingTestCase(test.NoDBTestCase): app = compute.APIRouterV21() self.assertIn('os-hosts', app._loaded_extension_info.extensions) - def test_extensions_whitelist_block(self): - # NOTE(maurosr): just to avoid to get an exception raised for not - # loading all core api. - v21_core = openstack.API_V21_CORE_EXTENSIONS - openstack.API_V21_CORE_EXTENSIONS = set(['servers']) - self.addCleanup(self._set_v21_core, v21_core) - - app = compute.APIRouterV21() - self.assertIn('os-hosts', app._loaded_extension_info.extensions) - CONF.set_override('extensions_whitelist', ['servers'], 'osapi_v21') - app = compute.APIRouterV21() - self.assertNotIn('os-hosts', app._loaded_extension_info.extensions) - - def test_blacklist_overrides_whitelist(self): - # NOTE(maurosr): just to avoid to get an exception raised for not - # loading all core api. - v21_core = openstack.API_V21_CORE_EXTENSIONS - openstack.API_V21_CORE_EXTENSIONS = set(['servers']) - self.addCleanup(self._set_v21_core, v21_core) - - app = compute.APIRouterV21() - self.assertIn('os-hosts', app._loaded_extension_info.extensions) - CONF.set_override('extensions_whitelist', ['servers', 'os-hosts'], - 'osapi_v21') - CONF.set_override('extensions_blacklist', ['os-hosts'], 'osapi_v21') - app = compute.APIRouterV21() - self.assertNotIn('os-hosts', app._loaded_extension_info.extensions) - self.assertIn('servers', app._loaded_extension_info.extensions) - self.assertEqual(1, len(app._loaded_extension_info.extensions)) - def test_get_missing_core_extensions(self): v21_core = openstack.API_V21_CORE_EXTENSIONS openstack.API_V21_CORE_EXTENSIONS = set(['core1', 'core2']) @@ -169,13 +132,6 @@ class ExtensionLoadingTestCase(test.NoDBTestCase): # not be raised when creating an instance of compute.APIRouterV21 compute.APIRouterV21() - def test_core_extensions_missing(self): - self.stubs.Set(stevedore.enabled, 'EnabledExtensionManager', - fake_stevedore_enabled_extensions) - self.stubs.Set(extension_info, 'LoadedExtensionInfo', - fake_loaded_extension_info) - self.assertRaises(exception.CoreAPIMissing, compute.APIRouterV21) - def test_extensions_expected_error(self): @extensions.expected_errors(404) def fake_func(): diff --git a/nova/tests/unit/api/openstack/compute/test_flavor_disabled.py b/nova/tests/unit/api/openstack/compute/test_flavor_disabled.py index 062e99225b5b..b52843ef847c 100644 --- a/nova/tests/unit/api/openstack/compute/test_flavor_disabled.py +++ b/nova/tests/unit/api/openstack/compute/test_flavor_disabled.py @@ -29,6 +29,8 @@ FAKE_FLAVORS = { "vcpus": 1, "ephemeral_gb": 1, "disabled": False, + "is_public": True, + "rxtx_factor": 1.0, }, 'flavor 2': { "flavorid": '2', @@ -39,10 +41,16 @@ FAKE_FLAVORS = { "vcpus": 1, "ephemeral_gb": 1, "disabled": True, + "is_public": True, + "rxtx_factor": 1.0, }, } +def fake_get_db_flavor(req, flavorid): + return fake_flavor_get_by_flavor_id(flavorid) + + def fake_flavor_get_by_flavor_id(flavorid, ctxt=None): return FAKE_FLAVORS['flavor %s' % flavorid] @@ -72,6 +80,8 @@ class FlavorDisabledTestV21(test.NoDBTestCase): self.stubs.Set(flavors, "get_flavor_by_flavor_id", fake_flavor_get_by_flavor_id) + self.stub_out('nova.api.openstack.wsgi.Request.get_db_flavor', + fake_get_db_flavor) def _make_request(self, url): req = webob.Request.blank(url) diff --git a/nova/tests/unit/api/openstack/compute/test_flavor_rxtx.py b/nova/tests/unit/api/openstack/compute/test_flavor_rxtx.py index c987fb2d10f2..da008d470687 100644 --- a/nova/tests/unit/api/openstack/compute/test_flavor_rxtx.py +++ b/nova/tests/unit/api/openstack/compute/test_flavor_rxtx.py @@ -29,6 +29,7 @@ FAKE_FLAVORS = { "disabled": False, "ephemeral_gb": '20', "rxtx_factor": '1.0', + "is_public": True, "vcpus": 1, }, 'flavor 2': { @@ -40,6 +41,7 @@ FAKE_FLAVORS = { "ephemeral_gb": '25', "rxtx_factor": None, "disabled": False, + "is_public": True, "vcpus": 1, }, } diff --git a/nova/tests/unit/api/openstack/compute/test_flavor_swap.py b/nova/tests/unit/api/openstack/compute/test_flavor_swap.py index b2ea13687d29..153683e8f79c 100644 --- a/nova/tests/unit/api/openstack/compute/test_flavor_swap.py +++ b/nova/tests/unit/api/openstack/compute/test_flavor_swap.py @@ -29,6 +29,8 @@ FAKE_FLAVORS = { "vcpus": 1, "ephemeral_gb": 1, "disabled": False, + "is_public": True, + "rxtx_factor": 1.0, }, 'flavor 2': { "flavorid": '2', @@ -39,6 +41,8 @@ FAKE_FLAVORS = { "vcpus": 1, "ephemeral_gb": 1, "disabled": False, + "is_public": True, + "rxtx_factor": 1.0, }, } diff --git a/nova/tests/unit/api/openstack/compute/test_flavorextradata.py b/nova/tests/unit/api/openstack/compute/test_flavorextradata.py index 33f7a4cfb2b2..e77825d6d9ce 100644 --- a/nova/tests/unit/api/openstack/compute/test_flavorextradata.py +++ b/nova/tests/unit/api/openstack/compute/test_flavorextradata.py @@ -39,7 +39,9 @@ def fake_get_flavor_by_flavor_id(flavorid, ctxt=None): 'deleted_at': None, 'vcpu_weight': None, 'swap': 0, + 'is_public': True, 'disabled': False, + 'rxtx_factor': 1.0, } @@ -101,6 +103,8 @@ class FlavorExtraDataTestV21(test.NoDBTestCase): 'vcpus': 1, 'disk': 1, 'OS-FLV-EXT-DATA:ephemeral': 1, + 'rxtx_factor': 1.0, + 'os-flavor-access:is_public': True, }, { 'id': '2', @@ -109,6 +113,8 @@ class FlavorExtraDataTestV21(test.NoDBTestCase): 'vcpus': 1, 'disk': 1, 'OS-FLV-EXT-DATA:ephemeral': 1, + 'rxtx_factor': 1.0, + 'os-flavor-access:is_public': True, }, ] diff --git a/nova/tests/unit/api/openstack/compute/test_keypairs.py b/nova/tests/unit/api/openstack/compute/test_keypairs.py index dcd1e441b946..41ad763bee04 100644 --- a/nova/tests/unit/api/openstack/compute/test_keypairs.py +++ b/nova/tests/unit/api/openstack/compute/test_keypairs.py @@ -285,6 +285,13 @@ class KeypairsTestV21(test.TestCase): fakes.fake_instance_get()) self.stub_out('nova.db.instance_get_by_uuid', fakes.fake_instance_get()) + # NOTE(sdague): because of the way extensions work, we have to + # also stub out the Request compute cache with a real compute + # object. Delete this once we remove all the gorp of + # extensions modifying the server objects. + self.stub_out('nova.api.openstack.wsgi.Request.get_db_instance', + fakes.fake_compute_get()) + req = webob.Request.blank(self.base_url + '/servers/' + uuids.server) req.headers['Content-Type'] = 'application/json' response = req.get_response(self.app_server) diff --git a/nova/tests/unit/api/openstack/fakes.py b/nova/tests/unit/api/openstack/fakes.py index 22c84da65774..dff36394bc7b 100644 --- a/nova/tests/unit/api/openstack/fakes.py +++ b/nova/tests/unit/api/openstack/fakes.py @@ -65,7 +65,7 @@ def fake_wsgi(self, req): def wsgi_app_v21(fake_auth_context=None, init_only=None, v2_compatible=False): - inner_app_v21 = compute.APIRouterV21(init_only) + inner_app_v21 = compute.APIRouterV21() if v2_compatible: inner_app_v21 = openstack_api.LegacyV2CompatibleWrapper(inner_app_v21)