diff options
| author | Alex Meade <alex.meade@rackspace.com> | 2012-04-30 12:59:21 -0400 |
|---|---|---|
| committer | Alex Meade <alex.meade@rackspace.com> | 2012-05-02 13:33:24 -0400 |
| commit | 718a3f057cee0b1163c40fbcbedda29bd2ef9dfe (patch) | |
| tree | 6d4531db55a152c958ca3e30ff01394de512b190 | |
| parent | 994bba6ae7156a565bd160fc8f0f8e8578c28d1b (diff) | |
| download | nova-718a3f057cee0b1163c40fbcbedda29bd2ef9dfe.tar.gz nova-718a3f057cee0b1163c40fbcbedda29bd2ef9dfe.tar.xz nova-718a3f057cee0b1163c40fbcbedda29bd2ef9dfe.zip | |
Provide better quota error messages.
Refactor the handling of QuotaErrors.
Fixes bug: 990015
Fixes bug: 991994
Change-Id: I722545fad3c0bdff896a8f56f6c53ba47e433b0c
| -rw-r--r-- | nova/api/openstack/compute/contrib/flavorextraspecs.py | 14 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/volumetypes.py | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/server_metadata.py | 23 | ||||
| -rw-r--r-- | nova/api/openstack/compute/servers.py | 33 | ||||
| -rw-r--r-- | nova/compute/api.py | 27 | ||||
| -rw-r--r-- | nova/exception.py | 29 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/test_server_metadata.py | 75 | ||||
| -rw-r--r-- | nova/tests/api/openstack/compute/test_servers.py | 165 | ||||
| -rw-r--r-- | nova/volume/api.py | 2 |
9 files changed, 283 insertions, 91 deletions
diff --git a/nova/api/openstack/compute/contrib/flavorextraspecs.py b/nova/api/openstack/compute/contrib/flavorextraspecs.py index e878e2efb..faae7c40b 100644 --- a/nova/api/openstack/compute/contrib/flavorextraspecs.py +++ b/nova/api/openstack/compute/contrib/flavorextraspecs.py @@ -66,8 +66,8 @@ class FlavorExtraSpecsController(object): db.instance_type_extra_specs_update_or_create(context, flavor_id, specs) - except exception.QuotaError as error: - self._handle_quota_error(error) + except exception.MetadataLimitExceeded as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) return body @wsgi.serializers(xml=ExtraSpecsTemplate) @@ -85,8 +85,8 @@ class FlavorExtraSpecsController(object): db.instance_type_extra_specs_update_or_create(context, flavor_id, body) - except exception.QuotaError as error: - self._handle_quota_error(error) + except exception.MetadataLimitExceeded as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) return body @@ -107,12 +107,6 @@ class FlavorExtraSpecsController(object): authorize(context) db.instance_type_extra_specs_delete(context, flavor_id, id) - def _handle_quota_error(self, error): - """Reraise quota errors as api-specific http exceptions.""" - if error.code == "MetadataLimitExceeded": - raise exc.HTTPBadRequest(explanation=error.message) - raise error - class Flavorextraspecs(extensions.ExtensionDescriptor): """Instance type (flavor) extra specs""" diff --git a/nova/api/openstack/compute/contrib/volumetypes.py b/nova/api/openstack/compute/contrib/volumetypes.py index 4255ac149..2711c45d7 100644 --- a/nova/api/openstack/compute/contrib/volumetypes.py +++ b/nova/api/openstack/compute/contrib/volumetypes.py @@ -114,12 +114,6 @@ class VolumeTypesController(object): except exception.NotFound: raise exc.HTTPNotFound() - def _handle_quota_error(self, error): - """Reraise quota errors as api-specific http exceptions.""" - if error.code == "MetadataLimitExceeded": - raise exc.HTTPBadRequest(explanation=error.message) - raise error - class VolumeTypeExtraSpecsTemplate(xmlutil.TemplateBuilder): def construct(self): diff --git a/nova/api/openstack/compute/server_metadata.py b/nova/api/openstack/compute/server_metadata.py index a2fb53e7e..dfb4b55a8 100644 --- a/nova/api/openstack/compute/server_metadata.py +++ b/nova/api/openstack/compute/server_metadata.py @@ -126,8 +126,12 @@ class Controller(object): msg = _("Malformed request body") raise exc.HTTPBadRequest(explanation=msg) + except exception.InvalidMetadata as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) + except exception.QuotaError as error: - self._handle_quota_error(error) + raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error), + headers={'Retry-After': 0}) @wsgi.serializers(xml=common.MetaItemTemplate) def show(self, req, server_id, id): @@ -159,23 +163,6 @@ class Controller(object): msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) - def _handle_quota_error(self, error): - """Reraise quota errors as api-specific http exceptions.""" - code_mappings = { - "MetadataKeyValueLimitExceeded": - _("Metadata property key or value greater than 255 " - "characters"), - "MetadataKeyUnspecified": - _("Metadata property key blank"), - "MetadataLimitExceeded": - error.message % error.kwargs - } - expl = code_mappings.get(error.kwargs['code']) - if expl: - raise exc.HTTPRequestEntityTooLarge(explanation=expl, - headers={'Retry-After': 0}) - raise error - def create_resource(): return wsgi.Resource(Controller()) diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index af6d9c7d6..ff96ded9b 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -471,32 +471,6 @@ class Controller(wsgi.Controller): except exception.NotFound: raise exc.HTTPNotFound() - def _handle_quota_error(self, error): - """Reraise quota errors as api-specific http exceptions.""" - - code_mappings = { - "OnsetFileLimitExceeded": - _("Personality file limit exceeded"), - "OnsetFilePathLimitExceeded": - _("Personality file path too long"), - "OnsetFileContentLimitExceeded": - _("Personality file content too long"), - "MetadataKeyValueLimitExceeded": - _("Metadata property key or value greater than 255 " - "characters"), - "MetadataKeyUnspecified": - _("Metadata property key blank"), - - # NOTE(bcwaldon): expose the message generated below in order - # to better explain how the quota was exceeded - "InstanceLimitExceeded": error.message, - } - - code = error.kwargs['code'] - expl = code_mappings.get(code, error.message) % error.kwargs - raise exc.HTTPRequestEntityTooLarge(explanation=expl, - headers={'Retry-After': 0}) - def _validate_server_name(self, value): if not isinstance(value, basestring): msg = _("Server name is not a string or unicode") @@ -726,11 +700,14 @@ class Controller(wsgi.Controller): auto_disk_config=auto_disk_config, scheduler_hints=scheduler_hints) except exception.QuotaError as error: - self._handle_quota_error(error) + raise exc.HTTPRequestEntityTooLarge(explanation=unicode(error), + headers={'Retry-After': 0}) except exception.InstanceTypeMemoryTooSmall as error: raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.InstanceTypeDiskTooSmall as error: raise exc.HTTPBadRequest(explanation=unicode(error)) + except exception.InvalidMetadata as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.ImageNotFound as error: msg = _("Can not find requested image") raise exc.HTTPBadRequest(explanation=msg) @@ -1075,6 +1052,8 @@ class Controller(wsgi.Controller): except exception.InstanceNotFound: msg = _("Instance could not be found") raise exc.HTTPNotFound(explanation=msg) + except exception.InvalidMetadata as error: + raise exc.HTTPBadRequest(explanation=unicode(error)) except exception.ImageNotFound: msg = _("Cannot find image for rebuild") raise exc.HTTPBadRequest(explanation=msg) diff --git a/nova/compute/api.py b/nova/compute/api.py index 542782c8b..ad34dd288 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -176,16 +176,15 @@ class API(BaseAPI): return limit = quota.allowed_injected_files(context, len(injected_files)) if len(injected_files) > limit: - raise exception.QuotaError(code="OnsetFileLimitExceeded") + raise exception.OnsetFileLimitExceeded() path_limit = quota.allowed_injected_file_path_bytes(context) for path, content in injected_files: if len(path) > path_limit: - raise exception.QuotaError(code="OnsetFilePathLimitExceeded") + raise exception.OnsetFilePathLimitExceeded() content_limit = quota.allowed_injected_file_content_bytes( context, len(content)) if len(content) > content_limit: - code = "OnsetFileContentLimitExceeded" - raise exception.QuotaError(code=code) + raise exception.OnsetFileContentLimitExceeded() def _check_num_instances_quota(self, context, instance_type, min_count, max_count): @@ -196,12 +195,14 @@ class API(BaseAPI): pid = context.project_id if num_instances <= 0: msg = _("Cannot run any more instances of this type.") + used = max_count else: msg = (_("Can only run %s more instances of this type.") % num_instances) + used = max_count - num_instances LOG.warn(_("Quota exceeded for %(pid)s," " tried to run %(min_count)s instances. %(msg)s"), locals()) - raise exception.QuotaError(code="InstanceLimitExceeded") + raise exception.TooManyInstances(used=used, allowed=max_count) return num_instances @@ -216,7 +217,7 @@ class API(BaseAPI): msg = _("Quota exceeded for %(pid)s, tried to set " "%(num_metadata)s metadata properties") % locals() LOG.warn(msg) - raise exception.QuotaError(code="MetadataLimitExceeded") + raise exception.MetadataLimitExceeded(allowed=quota_metadata) # Because metadata is stored in the DB, we hard-code the size limits # In future, we may support more variable length strings, so we act @@ -225,13 +226,15 @@ class API(BaseAPI): if len(k) == 0: msg = _("Metadata property key blank") LOG.warn(msg) - raise exception.QuotaError(code="MetadataKeyUnspecified") - if len(k) > 255 or len(v) > 255: - msg = _("Metadata property key or value greater than 255 " - "characters") + raise exception.InvalidMetadata(reason=msg) + if len(k) > 255: + msg = _("Metadata property key greater than 255 characters") LOG.warn(msg) - raise exception.QuotaError( - code="MetadataKeyValueLimitExceeded") + raise exception.InvalidMetadata(reason=msg) + if len(v) > 255: + msg = _("Metadata property value greater than 255 characters") + LOG.warn(msg) + raise exception.InvalidMetadata(reason=msg) def _check_requested_networks(self, context, requested_networks): """ Check if the networks requested belongs to the project diff --git a/nova/exception.py b/nova/exception.py index 5fa9e0c87..e40fa0ccf 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -265,6 +265,10 @@ class InvalidVolume(Invalid): message = _("Invalid volume") + ": %(reason)s" +class InvalidMetadata(Invalid): + message = _("Invalid metadata") + ": %(reason)s" + + class InvalidPortRange(Invalid): message = _("Invalid port range %(from_port)s:%(to_port)s. %(msg)s") @@ -962,6 +966,31 @@ class QuotaError(NovaException): message = _("Quota exceeded") + ": code=%(code)s" +class TooManyInstances(QuotaError): + message = _("Quota exceeded: already used %(used)d of %(allowed)d" + " instances") + + +class VolumeSizeTooLarge(QuotaError): + message = _("Maximum volume size exceeded") + + +class MetadataLimitExceeded(QuotaError): + message = _("Maximum number of metadata items exceeds %(allowed)d") + + +class OnsetFileLimitExceeded(QuotaError): + message = _("Personality file limit exceeded") + + +class OnsetFilePathLimitExceeded(QuotaError): + message = _("Personality file path too long") + + +class OnsetFileContentLimitExceeded(QuotaError): + message = _("Personality file content too long") + + class AggregateError(NovaException): message = _("Aggregate %(aggregate_id)s: action '%(action)s' " "caused an error: %(reason)s.") diff --git a/nova/tests/api/openstack/compute/test_server_metadata.py b/nova/tests/api/openstack/compute/test_server_metadata.py index aa4e47706..87fcec57b 100644 --- a/nova/tests/api/openstack/compute/test_server_metadata.py +++ b/nova/tests/api/openstack/compute/test_server_metadata.py @@ -200,6 +200,31 @@ class ServerMetaDataTest(test.TestCase): self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, self.uuid, None) + def test_create_item_empty_key(self): + self.stubs.Set(nova.db, 'instance_metadata_update', + return_create_instance_metadata) + req = fakes.HTTPRequest.blank(self.url + '/key1') + req.method = 'PUT' + body = {"meta": {"": "value1"}} + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, req, self.uuid, body) + + def test_create_item_key_too_long(self): + self.stubs.Set(nova.db, 'instance_metadata_update', + return_create_instance_metadata) + req = fakes.HTTPRequest.blank(self.url + '/key1') + req.method = 'PUT' + body = {"meta": {("a" * 260): "value1"}} + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, + req, self.uuid, body) + def test_create_nonexistant_server(self): self.stubs.Set(nova.db, 'instance_get', return_server_nonexistant) req = fakes.HTTPRequest.blank(self.url) @@ -308,6 +333,44 @@ class ServerMetaDataTest(test.TestCase): self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, req, self.uuid, 'key1', None) + def test_update_item_empty_key(self): + self.stubs.Set(nova.db, 'instance_metadata_update', + return_create_instance_metadata) + req = fakes.HTTPRequest.blank(self.url + '/key1') + req.method = 'PUT' + body = {"meta": {"": "value1"}} + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.update, req, self.uuid, '', body) + + def test_update_item_key_too_long(self): + self.stubs.Set(nova.db, 'instance_metadata_update', + return_create_instance_metadata) + req = fakes.HTTPRequest.blank(self.url + '/key1') + req.method = 'PUT' + body = {"meta": {("a" * 260): "value1"}} + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.update, + req, self.uuid, ("a" * 260), body) + + def test_update_item_value_too_long(self): + self.stubs.Set(nova.db, 'instance_metadata_update', + return_create_instance_metadata) + req = fakes.HTTPRequest.blank(self.url + '/key1') + req.method = 'PUT' + body = {"meta": {"key1": ("a" * 260)}} + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.update, + req, self.uuid, "key1", body) + def test_update_item_too_many_keys(self): self.stubs.Set(nova.db, 'instance_metadata_update', return_create_instance_metadata) @@ -356,19 +419,19 @@ class ServerMetaDataTest(test.TestCase): #test for long key data = {"metadata": {"a" * 260: "value1"}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, self.uuid, data) #test for long value data = {"metadata": {"key": "v" * 260}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, self.uuid, data) #test for empty key. data = {"metadata": {"": "value1"}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, self.uuid, data) def test_too_many_metadata_items_on_update_item(self): @@ -399,17 +462,17 @@ class ServerMetaDataTest(test.TestCase): #test for long key data = {"metadata": {"a" * 260: "value1"}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update_all, req, self.uuid, data) #test for long value data = {"metadata": {"key": "v" * 260}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update_all, req, self.uuid, data) #test for empty key. data = {"metadata": {"": "value1"}} req.body = json.dumps(data) - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update_all, req, self.uuid, data) diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py index 514d7cf84..0004c9fcb 100644 --- a/nova/tests/api/openstack/compute/test_servers.py +++ b/nova/tests/api/openstack/compute/test_servers.py @@ -1003,7 +1003,7 @@ class ServersControllerTest(test.TestCase): req, FAKE_UUID, body) def test_rebuild_instance_with_access_ipv4_bad_format(self): - self.stubs.Set(nova.db, 'instance_get', + self.stubs.Set(nova.db, 'instance_get_by_uuid', fakes.fake_instance_get(vm_state=vm_states.ACTIVE)) # proper local hrefs must start with 'http://localhost/v2/' image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' @@ -1036,6 +1036,108 @@ class ServersControllerTest(test.TestCase): self.assertRaises(webob.exc.HTTPBadRequest, self.controller._action_rebuild, req, FAKE_UUID, body) + def test_rebuild_instance_with_blank_metadata_key(self): + self.stubs.Set(nova.db, 'instance_get_by_uuid', + fakes.fake_instance_get(vm_state=vm_states.ACTIVE)) + # proper local hrefs must start with 'http://localhost/v2/' + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/fake/images/%s' % image_uuid + access_ipv4 = '0.0.0.0' + access_ipv6 = 'fead::1234' + body = { + 'rebuild': { + 'name': 'new_name', + 'imageRef': image_href, + 'accessIPv4': access_ipv4, + 'accessIPv6': access_ipv6, + 'metadata': { + '': 'world', + 'open': 'stack', + }, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + ], + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller._action_rebuild, req, FAKE_UUID, body) + + def test_rebuild_instance_with_metadata_key_too_long(self): + self.stubs.Set(nova.db, 'instance_get_by_uuid', + fakes.fake_instance_get(vm_state=vm_states.ACTIVE)) + # proper local hrefs must start with 'http://localhost/v2/' + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/fake/images/%s' % image_uuid + access_ipv4 = '0.0.0.0' + access_ipv6 = 'fead::1234' + body = { + 'rebuild': { + 'name': 'new_name', + 'imageRef': image_href, + 'accessIPv4': access_ipv4, + 'accessIPv6': access_ipv6, + 'metadata': { + ('a' * 260): 'world', + 'open': 'stack', + }, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + ], + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller._action_rebuild, req, FAKE_UUID, body) + + def test_rebuild_instance_with_metadata_value_too_long(self): + self.stubs.Set(nova.db, 'instance_get_by_uuid', + fakes.fake_instance_get(vm_state=vm_states.ACTIVE)) + # proper local hrefs must start with 'http://localhost/v2/' + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/fake/images/%s' % image_uuid + access_ipv4 = '0.0.0.0' + access_ipv6 = 'fead::1234' + body = { + 'rebuild': { + 'name': 'new_name', + 'imageRef': image_href, + 'accessIPv4': access_ipv4, + 'accessIPv6': access_ipv6, + 'metadata': { + 'key1': ('a' * 260), + 'open': 'stack', + }, + 'personality': [ + { + "path": "/etc/banner.txt", + "contents": "MQ==", + }, + ], + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers/a/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller._action_rebuild, req, FAKE_UUID, body) + def test_rebuild_instance_fails_when_min_ram_too_small(self): # make min_ram larger than our instance ram size def fake_get_image(self, context, image_href): @@ -1845,13 +1947,7 @@ class ServersControllerCreateTest(test.TestCase): 'imageRef': image_href, 'flavorRef': flavor_ref, 'metadata': { - ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' - 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'): '12345', + ('a' * 260): '12345', }, }, } @@ -1861,7 +1957,55 @@ class ServersControllerCreateTest(test.TestCase): req.body = json.dumps(body) req.headers["content-type"] = "application/json" - self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, req, body) + + def test_create_instance_metadata_value_too_long(self): + self.flags(quota_metadata_items=1) + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/images/%s' % image_uuid + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'name': 'server_test', + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': { + 'key1': ('a' * 260), + }, + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, req, body) + + def test_create_instance_metadata_key_blank(self): + self.flags(quota_metadata_items=1) + image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + image_href = 'http://localhost/v2/images/%s' % image_uuid + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'name': 'server_test', + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': { + '': '12345', + }, + }, + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, body) def test_create_instance_invalid_key_name(self): @@ -2193,9 +2337,8 @@ class ServersControllerCreateTest(test.TestCase): server = self.controller.create(req, body).obj['server'] fail('excepted quota to be exceeded') except webob.exc.HTTPRequestEntityTooLarge as e: - code = {'code': 'InstanceLimitExceeded'} self.assertEquals(e.explanation, - _('Quota exceeded: code=%(code)s') % code) + _('Quota exceeded: already used 1 of 1 instances')) class TestServerCreateRequestXMLDeserializer(test.TestCase): diff --git a/nova/volume/api.py b/nova/volume/api.py index c40270ac7..f62d41ea6 100644 --- a/nova/volume/api.py +++ b/nova/volume/api.py @@ -84,7 +84,7 @@ class API(base.Base): pid = context.project_id LOG.warn(_("Quota exceeded for %(pid)s, tried to create" " %(size)sG volume") % locals()) - raise exception.QuotaError(code="VolumeSizeTooLarge") + raise exception.VolumeSizeTooLarge() if availability_zone is None: availability_zone = FLAGS.storage_availability_zone |
