Prevent min_disk and min_ram from being negative

At the moment, in both api versions, min_disk and min_ram can be set to
negative value - which doesn't make sense. This commit fixes this behavior
in the two versions of the glance api.

Change-Id: Ib7855c1d928ab8262dd2a109619a4e3d2299ff9e
Closes-bug: #1265711
This commit is contained in:
Yanis Guenane 2014-01-07 19:45:26 +00:00
parent f19bfe2364
commit a5b78ae0b5
5 changed files with 154 additions and 15 deletions

View File

@ -61,6 +61,8 @@ class ImagesController(object):
raise webob.exc.HTTPBadRequest(explanation=unicode(dup))
except exception.Forbidden as e:
raise webob.exc.HTTPForbidden(explanation=unicode(e))
except exception.InvalidParameterValue as e:
raise webob.exc.HTTPBadRequest(explanation=unicode(e))
except exception.LimitExceeded as e:
LOG.info(unicode(e))
raise webob.exc.HTTPRequestEntityTooLarge(
@ -126,6 +128,8 @@ class ImagesController(object):
raise webob.exc.HTTPNotFound(explanation=msg)
except exception.Forbidden as e:
raise webob.exc.HTTPForbidden(explanation=unicode(e))
except exception.InvalidParameterValue as e:
raise webob.exc.HTTPBadRequest(explanation=unicode(e))
except exception.StorageQuotaFull as e:
msg = (_("Denying attempt to upload image because it exceeds the ."
"quota: %s") % e)

View File

@ -254,21 +254,26 @@ def get_image_meta_from_headers(response):
raise exc.HTTPBadRequest(msg, content_type="text/plain")
result[field_name] = value or None
result['properties'] = properties
if 'size' in result:
try:
result['size'] = int(result['size'])
except ValueError:
extra = (_("Cannot convert image size '%s' to an integer.") %
result['size'])
raise exception.InvalidParameterValue(value=result['size'],
param='size',
extra_msg=extra)
if result['size'] < 0:
extra = (_("Image size must be >= 0 ('%s' specified).") %
result['size'])
raise exception.InvalidParameterValue(value=result['size'],
param='size',
extra_msg=extra)
for key in ('size', 'min_disk', 'min_ram'):
if key in result:
try:
result[key] = int(result[key])
except ValueError:
extra = (_("Cannot convert image %(key)s '%(value)s' "
"to an integer.")
% {'key': key, 'value': result[key]})
raise exception.InvalidParameterValue(value=result[key],
param=key,
extra_msg=extra)
if result[key] < 0:
extra = (_("Image %(key)s must be >= 0 "
"('%(value)s' specified).")
% {'key': key, 'value': result[key]})
raise exception.InvalidParameterValue(value=result[key],
param=key,
extra_msg=extra)
for key in ('is_public', 'deleted', 'protected'):
if key in result:
result[key] = strutils.bool_from_string(result[key])

View File

@ -181,6 +181,32 @@ class Image(object):
raise exception.Forbidden(message=msg)
self._disk_format = value
@property
def min_disk(self):
return self._min_disk
@min_disk.setter
def min_disk(self, value):
if value and value < 0:
extra_msg = 'Cannot be a negative value'
raise exception.InvalidParameterValue(value=value,
param='min_disk',
extra_msg=extra_msg)
self._min_disk = value
@property
def min_ram(self):
return self._min_ram
@min_ram.setter
def min_ram(self, value):
if value and value < 0:
extra_msg = 'Cannot be a negative value'
raise exception.InvalidParameterValue(value=value,
param='min_ram',
extra_msg=extra_msg)
self._min_ram = value
def delete(self):
if self.protected:
raise exception.ProtectedImageDelete(image_id=self.image_id)

View File

@ -134,6 +134,80 @@ class TestGlanceAPI(base.IsolatedUnitTest):
for value in ('aki', 'ari', 'ami'):
self._do_test_defaulted_format(key, value)
def test_bad_min_disk_size_create(self):
fixture_headers = {'x-image-meta-store': 'file',
'x-image-meta-disk-format': 'vhd',
'x-image-meta-container-format': 'ovf',
'x-image-meta-min-disk': '-42',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(res.status_int, 400)
self.assertTrue('Invalid value' in res.body, res.body)
def test_bad_min_disk_size_update(self):
fixture_headers = {'x-image-meta-disk-format': 'vhd',
'x-image-meta-container-format': 'ovf',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(res.status_int, 201)
res_body = jsonutils.loads(res.body)['image']
self.assertEqual('queued', res_body['status'])
image_id = res_body['id']
req = webob.Request.blank("/images/%s" % image_id)
req.method = 'PUT'
req.headers['x-image-meta-min-disk'] = '-42'
res = req.get_response(self.api)
self.assertEqual(res.status_int, 400)
self.assertTrue('Invalid value' in res.body, res.body)
def test_bad_min_ram_size_create(self):
fixture_headers = {'x-image-meta-store': 'file',
'x-image-meta-disk-format': 'vhd',
'x-image-meta-container-format': 'ovf',
'x-image-meta-min-ram': '-42',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(res.status_int, 400)
self.assertTrue('Invalid value' in res.body, res.body)
def test_bad_min_ram_size_update(self):
fixture_headers = {'x-image-meta-disk-format': 'vhd',
'x-image-meta-container-format': 'ovf',
'x-image-meta-name': 'fake image #3'}
req = webob.Request.blank("/images")
req.method = 'POST'
for k, v in fixture_headers.iteritems():
req.headers[k] = v
res = req.get_response(self.api)
self.assertEqual(res.status_int, 201)
res_body = jsonutils.loads(res.body)['image']
self.assertEqual('queued', res_body['status'])
image_id = res_body['id']
req = webob.Request.blank("/images/%s" % image_id)
req.method = 'PUT'
req.headers['x-image-meta-min-ram'] = '-42'
res = req.get_response(self.api)
self.assertEqual(res.status_int, 400)
self.assertTrue('Invalid value' in res.body, res.body)
def test_bad_disk_format(self):
fixture_headers = {
'x-image-meta-store': 'bad',

View File

@ -573,6 +573,24 @@ class TestImagesController(base.IsolatedUnitTest):
extra_properties=image_properties,
tags=[])
def test_create_with_bad_min_disk_size(self):
request = unit_test_utils.get_fake_request()
image = {'min_disk': -42, 'name': 'image-1'}
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, request,
image=image,
extra_properties={},
tags=[])
def test_create_with_bad_min_ram_size(self):
request = unit_test_utils.get_fake_request()
image = {'min_ram': -42, 'name': 'image-1'}
self.assertRaises(webob.exc.HTTPBadRequest,
self.controller.create, request,
image=image,
extra_properties={},
tags=[])
def test_create_public_image_as_admin(self):
request = unit_test_utils.get_fake_request()
image = {'name': 'image-1', 'visibility': 'public'}
@ -620,6 +638,18 @@ class TestImagesController(base.IsolatedUnitTest):
#NOTE(markwash): don't send a notification if nothing is updated
self.assertTrue(len(output_logs) == 0)
def test_update_with_bad_min_disk(self):
request = unit_test_utils.get_fake_request()
changes = [{'op': 'replace', 'path': ['min_disk'], 'value': -42}]
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
request, UUID1, changes=changes)
def test_update_with_bad_min_ram(self):
request = unit_test_utils.get_fake_request()
changes = [{'op': 'replace', 'path': ['min_ram'], 'value': -42}]
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update,
request, UUID1, changes=changes)
def test_update_image_doesnt_exist(self):
request = unit_test_utils.get_fake_request()
self.assertRaises(webob.exc.HTTPNotFound, self.controller.update,