summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nova/api/openstack/compute/server_metadata.py14
-rw-r--r--nova/api/openstack/compute/servers.py5
-rw-r--r--nova/compute/api.py12
-rw-r--r--nova/tests/api/openstack/compute/test_server_metadata.py54
4 files changed, 79 insertions, 6 deletions
diff --git a/nova/api/openstack/compute/server_metadata.py b/nova/api/openstack/compute/server_metadata.py
index bdef6fbf46..a2fb53e7e4 100644
--- a/nova/api/openstack/compute/server_metadata.py
+++ b/nova/api/openstack/compute/server_metadata.py
@@ -161,8 +161,18 @@ class Controller(object):
def _handle_quota_error(self, error):
"""Reraise quota errors as api-specific http exceptions."""
- if error.kwargs['code'] == "MetadataLimitExceeded":
- raise exc.HTTPRequestEntityTooLarge(explanation=error.message,
+ 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
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 2e7b184c48..08b6954770 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -478,6 +478,11 @@ class Controller(wsgi.Controller):
_("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
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 15946d1167..70f8f69679 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -222,12 +222,16 @@ class API(BaseAPI):
# In future, we may support more variable length strings, so we act
# as if this is quota-controlled for forwards compatibility
for k, v in metadata.iteritems():
+ 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:
- pid = context.project_id
- msg = _("Quota exceeded for %(pid)s, metadata property "
- "key or value too long") % locals()
+ msg = _("Metadata property key or value greater than 255 "
+ "characters")
LOG.warn(msg)
- raise exception.QuotaError(code="MetadataLimitExceeded")
+ raise exception.QuotaError(
+ code="MetadataKeyValueLimitExceeded")
def _check_requested_networks(self, context, requested_networks):
""" Check if the networks requested belongs to the project
diff --git a/nova/tests/api/openstack/compute/test_server_metadata.py b/nova/tests/api/openstack/compute/test_server_metadata.py
index 61bf4fc479..aa4e477068 100644
--- a/nova/tests/api/openstack/compute/test_server_metadata.py
+++ b/nova/tests/api/openstack/compute/test_server_metadata.py
@@ -346,6 +346,31 @@ class ServerMetaDataTest(test.TestCase):
self.assertRaises(webob.exc.HTTPRequestEntityTooLarge,
self.controller.create, req, self.uuid, data)
+ def test_invalid_metadata_items_on_create(self):
+ self.stubs.Set(nova.db, 'instance_metadata_update',
+ return_create_instance_metadata)
+ req = fakes.HTTPRequest.blank(self.url)
+ req.method = 'POST'
+ req.headers["content-type"] = "application/json"
+
+ #test for long key
+ data = {"metadata": {"a" * 260: "value1"}}
+ req.body = json.dumps(data)
+ self.assertRaises(webob.exc.HTTPRequestEntityTooLarge,
+ 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.controller.create, req, self.uuid, data)
+
+ #test for empty key.
+ data = {"metadata": {"": "value1"}}
+ req.body = json.dumps(data)
+ self.assertRaises(webob.exc.HTTPRequestEntityTooLarge,
+ self.controller.create, req, self.uuid, data)
+
def test_too_many_metadata_items_on_update_item(self):
self.stubs.Set(nova.db, 'instance_metadata_update',
return_create_instance_metadata)
@@ -359,3 +384,32 @@ class ServerMetaDataTest(test.TestCase):
self.assertRaises(webob.exc.HTTPRequestEntityTooLarge,
self.controller.update_all, req, self.uuid, data)
+
+ def test_invalid_metadata_items_on_update_item(self):
+ self.stubs.Set(nova.db, 'instance_metadata_update',
+ return_create_instance_metadata)
+ data = {"metadata": {}}
+ for num in range(FLAGS.quota_metadata_items + 1):
+ data['metadata']['key%i' % num] = "blah"
+ req = fakes.HTTPRequest.blank(self.url)
+ req.method = 'PUT'
+ req.body = json.dumps(data)
+ req.headers["content-type"] = "application/json"
+
+ #test for long key
+ data = {"metadata": {"a" * 260: "value1"}}
+ req.body = json.dumps(data)
+ self.assertRaises(webob.exc.HTTPRequestEntityTooLarge,
+ 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.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.controller.update_all, req, self.uuid, data)