From e34d5d9e3d416fc40f147a5914f7dceee26f5ba4 Mon Sep 17 00:00:00 2001 From: Rohit Karajgi Date: Fri, 28 Dec 2012 04:43:14 -0800 Subject: Add Compute API validations for block device map This patch adds validations to return 400 BadRequest to Create server(s) with block device mappings where appropriate and related unit tests Fixes bug 1094244 Change-Id: I778d3ed4b0871561774594e950ce98b6a1ecfcb9 --- nova/api/openstack/compute/servers.py | 2 + nova/compute/api.py | 6 ++- nova/tests/api/openstack/compute/test_servers.py | 49 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index d3a6fc8a9..82eae442c 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -890,6 +890,8 @@ class Controller(wsgi.Controller): raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InvalidMetadataSize as error: raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error)) + except exception.InvalidRequest as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) diff --git a/nova/compute/api.py b/nova/compute/api.py index d0a039644..9b51ba13e 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -432,7 +432,11 @@ class API(base.Base): max_count = min_count block_device_mapping = block_device_mapping or [] - + if min_count > 1 or max_count > 1: + if any(map(lambda bdm: 'volume_id' in bdm, block_device_mapping)): + msg = _('Cannot attach one or more volumes to multiple' + ' instances') + raise exception.InvalidRequest(msg) if instance_type['disabled']: raise exception.InstanceTypeNotFound( instance_type_id=instance_type['id']) diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py index 2567558ab..1fa1e67e5 100644 --- a/nova/tests/api/openstack/compute/test_servers.py +++ b/nova/tests/api/openstack/compute/test_servers.py @@ -2002,6 +2002,55 @@ class ServersControllerCreateTest(test.TestCase): self.assertNotEqual(reservation_id, None) self.assertTrue(len(reservation_id) > 1) + def test_create_multiple_instances_with_multiple_volume_bdm(self): + """ + Test that a BadRequest is raised if multiple instances + are requested with a list of block device mappings for volumes. + """ + self.ext_mgr.extensions = {'os-multiple-create': 'fake'} + min_count = 2 + bdm = [{'device_name': 'foo1', 'volume_id': 'vol-xxxx'}, + {'device_name': 'foo2', 'volume_id': 'vol-yyyy'} + ] + params = { + 'block_device_mapping': bdm, + 'min_count': min_count + } + old_create = compute_api.API.create + + def create(*args, **kwargs): + self.assertEqual(kwargs['min_count'], 2) + self.assertEqual(len(kwargs['block_device_mapping']), 2) + return old_create(*args, **kwargs) + + self.stubs.Set(compute_api.API, 'create', create) + self.assertRaises(webob.exc.HTTPBadRequest, + self._test_create_extra, params, no_image=True) + + def test_create_multiple_instances_with_single_volume_bdm(self): + """ + Test that a BadRequest is raised if multiple instances + are requested to boot from a single volume. + """ + self.ext_mgr.extensions = {'os-multiple-create': 'fake'} + min_count = 2 + bdm = [{'device_name': 'foo1', 'volume_id': 'vol-xxxx'}] + params = { + 'block_device_mapping': bdm, + 'min_count': min_count + } + old_create = compute_api.API.create + + def create(*args, **kwargs): + self.assertEqual(kwargs['min_count'], 2) + self.assertEqual(kwargs['block_device_mapping']['volume_id'], + 'vol-xxxx') + return old_create(*args, **kwargs) + + self.stubs.Set(compute_api.API, 'create', create) + self.assertRaises(webob.exc.HTTPBadRequest, + self._test_create_extra, params, no_image=True) + def test_create_instance_image_ref_is_bookmark(self): image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' image_href = 'http://localhost/fake/images/%s' % image_uuid -- cgit