From e2fd04e281bbbd5a352f9e31bdc0d215463dccfe Mon Sep 17 00:00:00 2001 From: He Jie Xu Date: Tue, 19 Aug 2014 12:43:59 +0800 Subject: [PATCH] Changes block_device_mapping extension into v2.1 This patch changes v3 block_device_mapping API to v2.1 and make unittest share between v2 and v2.1 The differences between v2 and v3 are described on the wiki page https://wiki.openstack.org/wiki/NovaAPIv2tov3. Partially implements blueprint v2-on-v3-api Change-Id: I935b336523241a32dbd2bb8b154ce72afefd3aa9 --- .../plugins/v3/block_device_mapping.py | 2 +- .../openstack/compute/plugins/v3/servers.py | 3 +- .../test_block_device_mapping.py | 64 +++++++---- .../api/openstack/compute/test_servers.py | 106 +----------------- 4 files changed, 49 insertions(+), 126 deletions(-) rename nova/tests/api/openstack/compute/{plugins/v3 => contrib}/test_block_device_mapping.py (83%) diff --git a/nova/api/openstack/compute/plugins/v3/block_device_mapping.py b/nova/api/openstack/compute/plugins/v3/block_device_mapping.py index 0ee6c8340b..84d87b4c58 100644 --- a/nova/api/openstack/compute/plugins/v3/block_device_mapping.py +++ b/nova/api/openstack/compute/plugins/v3/block_device_mapping.py @@ -22,7 +22,7 @@ from nova import block_device from nova import exception ALIAS = "os-block-device-mapping" -ATTRIBUTE_NAME = "%s:block_device_mapping" % ALIAS +ATTRIBUTE_NAME = "block_device_mapping_v2" class BlockDeviceMapping(extensions.V3APIExtensionBase): diff --git a/nova/api/openstack/compute/plugins/v3/servers.py b/nova/api/openstack/compute/plugins/v3/servers.py index ce70cc8473..df0b0ef574 100644 --- a/nova/api/openstack/compute/plugins/v3/servers.py +++ b/nova/api/openstack/compute/plugins/v3/servers.py @@ -545,7 +545,8 @@ class ServersController(wsgi.Controller): exception.SecurityGroupNotFound, exception.PortRequiresFixedIP, exception.NetworkRequiresSubnet, - exception.NetworkNotFound) as error: + exception.NetworkNotFound, + exception.InvalidBDMVolumeNotBootable) as error: raise exc.HTTPBadRequest(explanation=error.format_message()) except (exception.PortInUse, exception.NetworkAmbiguous, diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_block_device_mapping.py b/nova/tests/api/openstack/compute/contrib/test_block_device_mapping.py similarity index 83% rename from nova/tests/api/openstack/compute/plugins/v3/test_block_device_mapping.py rename to nova/tests/api/openstack/compute/contrib/test_block_device_mapping.py index 639b808f0d..64d95c4769 100644 --- a/nova/tests/api/openstack/compute/plugins/v3/test_block_device_mapping.py +++ b/nova/tests/api/openstack/compute/contrib/test_block_device_mapping.py @@ -18,9 +18,11 @@ import mox from oslo.config import cfg from webob import exc +from nova.api.openstack.compute import extensions from nova.api.openstack.compute import plugins from nova.api.openstack.compute.plugins.v3 import block_device_mapping -from nova.api.openstack.compute.plugins.v3 import servers +from nova.api.openstack.compute.plugins.v3 import servers as servers_v3 +from nova.api.openstack.compute import servers as servers_v2 from nova import block_device from nova.compute import api as compute_api from nova import exception @@ -33,19 +35,20 @@ from nova.tests import matchers CONF = cfg.CONF -class BlockDeviceMappingTest(test.TestCase): - def setUp(self): - super(BlockDeviceMappingTest, self).setUp() +class BlockDeviceMappingTestV21(test.TestCase): + def _setup_controller(self): ext_info = plugins.LoadedExtensionInfo() - self.controller = servers.ServersController(extension_info=ext_info) - + self.controller = servers_v3.ServersController(extension_info=ext_info) CONF.set_override('extensions_blacklist', 'os-block-device-mapping', 'osapi_v3') - self.no_volumes_controller = servers.ServersController( - extension_info=ext_info) + self.no_bdm_v2_controller = servers_v3.ServersController( + extension_info=ext_info) CONF.set_override('extensions_blacklist', '', 'osapi_v3') + def setUp(self): + super(BlockDeviceMappingTestV21, self).setUp() + self._setup_controller() fake.stub_out_image_service(self.stubs) self.bdm = [{ @@ -57,7 +60,7 @@ class BlockDeviceMappingTest(test.TestCase): 'delete_on_termination': False, }] - def _test_create(self, params, no_image=False, override_controller=None): + def _get_servers_body(self, no_image=False): body = { 'server': { 'min_count': 2, @@ -70,10 +73,12 @@ class BlockDeviceMappingTest(test.TestCase): }, }, } - if no_image: del body['server']['imageRef'] + return body + def _test_create(self, params, no_image=False, override_controller=None): + body = self._get_servers_body(no_image) body['server'].update(params) req = fakes.HTTPRequestV3.blank('/servers') @@ -100,7 +105,7 @@ class BlockDeviceMappingTest(test.TestCase): params = {block_device_mapping.ATTRIBUTE_NAME: bdm} self._test_create(params, - override_controller=self.no_volumes_controller) + override_controller=self.no_bdm_v2_controller) def test_create_instance_with_volumes_enabled_no_image(self): """Test that the create will fail if there is no image @@ -281,14 +286,35 @@ class BlockDeviceMappingTest(test.TestCase): @mock.patch('nova.compute.api.API._get_bdm_image_metadata') def test_create_instance_non_bootable_volume_fails(self, fake_bdm_meta): - bdm = [{ - 'id': 1, - 'bootable': False, - 'volume_id': '1', - 'status': 'active', - 'device_name': 'vda', - }] - params = {'block_device_mapping': bdm} + params = {block_device_mapping.ATTRIBUTE_NAME: self.bdm} fake_bdm_meta.side_effect = exception.InvalidBDMVolumeNotBootable(id=1) self.assertRaises(exc.HTTPBadRequest, self._test_create, params, no_image=True) + + +class BlockDeviceMappingTestV2(BlockDeviceMappingTestV21): + + def _setup_controller(self): + self.ext_mgr = extensions.ExtensionManager() + self.ext_mgr.extensions = {'os-volumes': 'fake', + 'os-block-device-mapping-v2-boot': 'fake'} + self.controller = servers_v2.Controller(self.ext_mgr) + self.ext_mgr_bdm_v2 = extensions.ExtensionManager() + self.ext_mgr_bdm_v2.extensions = {'os-volumes': 'fake'} + self.no_bdm_v2_controller = servers_v2.Controller( + self.ext_mgr_bdm_v2) + + def test_create_instance_with_block_device_mapping_disabled(self): + bdm = [{'device_name': 'foo'}] + + old_create = compute_api.API.create + + def create(*args, **kwargs): + self.assertIsNone(kwargs['block_device_mapping'], None) + return old_create(*args, **kwargs) + + self.stubs.Set(compute_api.API, 'create', create) + + params = {block_device_mapping.ATTRIBUTE_NAME: bdm} + self._test_create(params, + override_controller=self.no_bdm_v2_controller) diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py index b491e4394f..0e3289b4c4 100644 --- a/nova/tests/api/openstack/compute/test_servers.py +++ b/nova/tests/api/openstack/compute/test_servers.py @@ -35,7 +35,6 @@ from nova.api.openstack.compute import servers from nova.api.openstack.compute import views from nova.api.openstack import extensions from nova.api.openstack import xmlutil -from nova import block_device from nova.compute import api as compute_api from nova.compute import flavors from nova.compute import task_states @@ -2680,41 +2679,6 @@ class ServersControllerCreateTest(test.TestCase): self.mox.ReplayAll() self._test_create_extra(params, no_image=True) - def test_create_instance_with_bdm_v2_enabled_and_bdms_no_image(self): - self.ext_mgr.extensions = { - 'os-volumes': 'fake', - 'os-block-device-mapping-v2-boot': 'fake'} - bdm_v2 = [{ - 'no_device': None, - 'source_type': 'volume', - 'destination_type': 'volume', - 'uuid': self.volume_id, - 'device_name': 'vda', - 'delete_on_termination': False, - }] - params = {'block_device_mapping_v2': bdm_v2} - old_create = compute_api.API.create - - def create(*args, **kwargs): - self.assertThat(block_device.BlockDeviceDict(bdm_v2[0]), - matchers.DictMatches( - kwargs['block_device_mapping'][0])) - self.assertNotIn('imageRef', kwargs) - return old_create(*args, **kwargs) - - self.mox.StubOutWithMock(compute_api.API, '_validate_bdm') - self.mox.StubOutWithMock(compute_api.API, '_get_bdm_image_metadata') - - compute_api.API._validate_bdm( - mox.IgnoreArg(), mox.IgnoreArg(), - mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(True) - compute_api.API._get_bdm_image_metadata( - mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn({}) - self.mox.ReplayAll() - self.stubs.Set(compute_api.API, 'create', create) - - self._test_create_extra(params, no_image=True) - def test_create_instance_with_volumes_disabled(self): bdm = [{'device_name': 'foo'}] params = {'block_device_mapping': bdm} @@ -2817,7 +2781,7 @@ class ServersControllerCreateTest(test.TestCase): def test_create_instance_bdm_api_validation_fails(self): self.ext_mgr.extensions = {'os-volumes': 'fake', - 'os-block-device-mapping-v2-boot': 'fake'} + 'os-block-devic-emapping-v2-boot': 'fake'} bdm = {'delete_on_termination': 1, 'device_name': 'vda', 'source_type': 'volume', @@ -2893,33 +2857,6 @@ class ServersControllerCreateTest(test.TestCase): self.stubs.Set(compute_api.API, '_validate_bdm', _validate_bdm) self._test_create_extra(params) - def test_create_instance_bdm_v2(self): - self.ext_mgr.extensions = {'os-volumes': 'fake', - 'os-block-device-mapping-v2-boot': 'fake'} - bdm_v2 = [{'source_type': 'volume', - 'device_name': 'fake_dev', - 'uuid': 'fake_vol'}] - bdm_v2_expected = [{'source_type': 'volume', - 'device_name': 'fake_dev', - 'volume_id': 'fake_vol'}] - params = {'block_device_mapping_v2': bdm_v2} - old_create = compute_api.API.create - - def create(*args, **kwargs): - self.assertFalse(kwargs['legacy_bdm']) - for expected, received in zip(bdm_v2_expected, - kwargs['block_device_mapping']): - self.assertThat(block_device.BlockDeviceDict(expected), - matchers.DictMatches(received)) - return old_create(*args, **kwargs) - - def _validate_bdm(*args, **kwargs): - pass - - self.stubs.Set(compute_api.API, 'create', create) - self.stubs.Set(compute_api.API, '_validate_bdm', _validate_bdm) - self._test_create_extra(params) - def test_create_instance_decide_format_legacy(self): self.ext_mgr.extensions = {'os-volumes': 'fake', 'os-block-device-mapping-v2-boot': 'fake'} @@ -2947,32 +2884,6 @@ class ServersControllerCreateTest(test.TestCase): params = {'block_device_mapping': bdm} self._test_create_extra(params) - def test_create_instance_decide_format_new(self): - self.ext_mgr.extensions = {'os-volumes': 'fake', - 'os-block-device-mapping-v2-boot': 'fake'} - - bdm_v2 = [{'source_type': 'volume', - 'device_name': 'fake_dev', - 'uuid': 'fake_vol'}] - - old_create = compute_api.API.create - - expected_legacy_flag = False - - def create(*args, **kwargs): - self.assertEqual(kwargs['legacy_bdm'], expected_legacy_flag) - return old_create(*args, **kwargs) - - def _validate_bdm(*args, **kwargs): - pass - - self.stubs.Set(compute_api.API, 'create', create) - self.stubs.Set(compute_api.API, '_validate_bdm', - _validate_bdm) - - params = {'block_device_mapping_v2': bdm_v2} - self._test_create_extra(params) - def test_create_instance_both_bdm_formats(self): self.ext_mgr.extensions = {'os-volumes': 'fake', 'os-block-device-mapping-v2-boot': 'fake'} @@ -2985,21 +2896,6 @@ class ServersControllerCreateTest(test.TestCase): self.assertRaises(webob.exc.HTTPBadRequest, self._test_create_extra, params) - def test_create_instance_bdm_v2_validation_error(self): - self.ext_mgr.extensions = {'os-volumes': 'fake', - 'os-block-device-mapping-v2-boot': 'fake'} - bdm_v2 = [{'device_name': 'bogus device'}] - params = {'block_device_mapping_v2': bdm_v2} - - def _validate(*args, **kwargs): - raise exception.InvalidBDMFormat() - - self.stubs.Set(block_device.BlockDeviceDict, - '_validate', _validate) - - self.assertRaises(webob.exc.HTTPBadRequest, - self._test_create_extra, params) - def test_create_instance_with_user_data_enabled(self): self.ext_mgr.extensions = {'os-user-data': 'fake'} user_data = 'fake'