summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Prince <dan.prince@rackspace.com>2011-08-09 16:33:13 +0000
committerTarmac <>2011-08-09 16:33:13 +0000
commit5afb04d2fbeccf31a83681ef6b58cb9a7674993b (patch)
tree687aae0af27b6a9c504c8254687bb2d3b476aa43
parent78d086b62cb7f1bf043d368e7d2b9e304d4c764f (diff)
parente24e031b453f90bb1d26616ec8d3975048d46220 (diff)
Update the OSAPI v1.1 server 'createImage' and 'createBackup' actions to limit the number of image metadata items based on the configured quota.allowed_metadata_items that is set.
-rw-r--r--nova/api/openstack/common.py11
-rw-r--r--nova/api/openstack/image_metadata.py16
-rw-r--r--nova/api/openstack/servers.py6
-rw-r--r--nova/tests/api/openstack/test_server_actions.py40
4 files changed, 58 insertions, 15 deletions
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index ac2104a5f..b916372d6 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -25,6 +25,7 @@ import webob
from nova import exception
from nova import flags
from nova import log as logging
+from nova import quota
from nova.api.openstack import wsgi
@@ -193,6 +194,16 @@ def get_version_from_href(href):
return version
+def check_img_metadata_quota_limit(context, metadata):
+ if metadata is None:
+ return
+ num_metadata = len(metadata)
+ quota_metadata = quota.allowed_metadata_items(context, num_metadata)
+ if quota_metadata < num_metadata:
+ expl = _("Image metadata limit exceeded")
+ raise webob.exc.HTTPBadRequest(explanation=expl)
+
+
class MetadataXMLDeserializer(wsgi.XMLDeserializer):
def extract_metadata(self, metadata_node):
diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/image_metadata.py
index aaf64a123..4d615ea96 100644
--- a/nova/api/openstack/image_metadata.py
+++ b/nova/api/openstack/image_metadata.py
@@ -19,7 +19,6 @@ from webob import exc
from nova import flags
from nova import image
-from nova import quota
from nova import utils
from nova.api.openstack import common
from nova.api.openstack import wsgi
@@ -40,15 +39,6 @@ class Controller(object):
metadata = image.get('properties', {})
return metadata
- def _check_quota_limit(self, context, metadata):
- if metadata is None:
- return
- num_metadata = len(metadata)
- quota_metadata = quota.allowed_metadata_items(context, num_metadata)
- if quota_metadata < num_metadata:
- expl = _("Image metadata limit exceeded")
- raise exc.HTTPBadRequest(explanation=expl)
-
def index(self, req, image_id):
"""Returns the list of metadata for a given instance"""
context = req.environ['nova.context']
@@ -70,7 +60,7 @@ class Controller(object):
if 'metadata' in body:
for key, value in body['metadata'].iteritems():
metadata[key] = value
- self._check_quota_limit(context, metadata)
+ common.check_img_metadata_quota_limit(context, metadata)
img['properties'] = metadata
self.image_service.update(context, image_id, img, None)
return dict(metadata=metadata)
@@ -93,7 +83,7 @@ class Controller(object):
img = self.image_service.show(context, image_id)
metadata = self._get_metadata(context, image_id, img)
metadata[id] = meta[id]
- self._check_quota_limit(context, metadata)
+ common.check_img_metadata_quota_limit(context, metadata)
img['properties'] = metadata
self.image_service.update(context, image_id, img, None)
return dict(meta=meta)
@@ -102,7 +92,7 @@ class Controller(object):
context = req.environ['nova.context']
img = self.image_service.show(context, image_id)
metadata = body.get('metadata', {})
- self._check_quota_limit(context, metadata)
+ common.check_img_metadata_quota_limit(context, metadata)
img['properties'] = metadata
self.image_service.update(context, image_id, img, None)
return dict(metadata=metadata)
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 63e71b3eb..4f34d63c9 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -218,13 +218,14 @@ class Controller(object):
props = {'instance_ref': server_ref}
metadata = entity.get('metadata', {})
+ context = req.environ["nova.context"]
+ common.check_img_metadata_quota_limit(context, metadata)
try:
props.update(metadata)
except ValueError:
msg = _("Invalid metadata")
raise webob.exc.HTTPBadRequest(explanation=msg)
- context = req.environ["nova.context"]
image = self.compute_api.backup(context,
instance_id,
image_name,
@@ -713,13 +714,14 @@ class ControllerV11(Controller):
props = {'instance_ref': server_ref}
metadata = entity.get('metadata', {})
+ context = req.environ['nova.context']
+ common.check_img_metadata_quota_limit(context, metadata)
try:
props.update(metadata)
except ValueError:
msg = _("Invalid metadata")
raise webob.exc.HTTPBadRequest(explanation=msg)
- context = req.environ['nova.context']
image = self.compute_api.snapshot(context,
instance_id,
image_name,
diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py
index 311db3f42..717e11c00 100644
--- a/nova/tests/api/openstack/test_server_actions.py
+++ b/nova/tests/api/openstack/test_server_actions.py
@@ -9,6 +9,7 @@ import webob
from nova import context
from nova import db
from nova import utils
+from nova import flags
from nova.api.openstack import create_instance_helper
from nova.compute import instance_types
from nova.compute import power_state
@@ -18,6 +19,9 @@ from nova.tests.api.openstack import common
from nova.tests.api.openstack import fakes
+FLAGS = flags.FLAGS
+
+
def return_server_by_id(context, id):
return _get_instance()
@@ -370,6 +374,26 @@ class ServerActionsTest(test.TestCase):
self.assertEqual(202, response.status_int)
self.assertTrue(response.headers['Location'])
+ def test_create_backup_with_too_much_metadata(self):
+ self.flags(allow_admin_api=True)
+
+ body = {
+ 'createBackup': {
+ 'name': 'Backup 1',
+ 'backup_type': 'daily',
+ 'rotation': 1,
+ 'metadata': {'123': 'asdf'},
+ },
+ }
+ for num in range(FLAGS.quota_metadata_items + 1):
+ body['createBackup']['metadata']['foo%i' % num] = "bar"
+ req = webob.Request.blank('/v1.0/servers/1/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
def test_create_backup_no_name(self):
"""Name is required for backups"""
self.flags(allow_admin_api=True)
@@ -809,6 +833,22 @@ class ServerActionsTestV11(test.TestCase):
location = response.headers['Location']
self.assertEqual('http://localhost/v1.1/images/123', location)
+ def test_create_image_with_too_much_metadata(self):
+ body = {
+ 'createImage': {
+ 'name': 'Snapshot 1',
+ 'metadata': {},
+ },
+ }
+ for num in range(FLAGS.quota_metadata_items + 1):
+ body['createImage']['metadata']['foo%i' % num] = "bar"
+ req = webob.Request.blank('/v1.1/servers/1/action')
+ req.method = 'POST'
+ req.body = json.dumps(body)
+ req.headers["content-type"] = "application/json"
+ response = req.get_response(fakes.wsgi_app())
+ self.assertEqual(400, response.status_int)
+
def test_create_image_no_name(self):
body = {
'createImage': {},