From 718a3f057cee0b1163c40fbcbedda29bd2ef9dfe Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Mon, 30 Apr 2012 12:59:21 -0400 Subject: Provide better quota error messages. Refactor the handling of QuotaErrors. Fixes bug: 990015 Fixes bug: 991994 Change-Id: I722545fad3c0bdff896a8f56f6c53ba47e433b0c --- .../api/openstack/compute/test_server_metadata.py | 75 +++++++++- nova/tests/api/openstack/compute/test_servers.py | 165 +++++++++++++++++++-- 2 files changed, 223 insertions(+), 17 deletions(-) (limited to 'nova/tests') 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): -- cgit