From 8e9e0cadaf8ce246861cf661cd4927ba7480484a Mon Sep 17 00:00:00 2001 From: Eoghan Glynn Date: Tue, 3 Apr 2012 11:22:07 +0100 Subject: [PATCH] Defaulted amazon disk & container formats Fixes bug 972014 Default unset disk/container format to the corresponding container/disk format, where the latter is an amazon format requiring a strict match. Change-Id: I147df146940a21c368e95901343f36e1e3b7495b --- glance/registry/db/api.py | 44 ++++++++++++++++++++++++-------- glance/tests/unit/v1/test_api.py | 22 ++++++++++++++++ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/glance/registry/db/api.py b/glance/registry/db/api.py index 04fe2e598f..acbdfeefa6 100644 --- a/glance/registry/db/api.py +++ b/glance/registry/db/api.py @@ -463,6 +463,30 @@ def validate_image(values): msg = "Invalid image status '%s' for image." % status raise exception.Invalid(msg) + def _amazon_format(disk, container): + amazon_formats = ('aki', 'ari', 'ami') + return ((disk in amazon_formats and + (container in CONTAINER_FORMATS or container is None)) or + (container in amazon_formats and + (disk in DISK_FORMATS or disk is None))) + + def _only_one_of(a, b): + return (a and b is None) or (b and a is None) + + if _amazon_format(disk_format, container_format): + if _only_one_of(container_format, disk_format): + container_format = (container_format if disk_format is None + else disk_format) + values['container_format'] = container_format + disk_format = container_format + values['disk_format'] = disk_format + elif container_format != disk_format: + msg = ("Invalid mix of disk and container formats. " + "When setting a disk or container format to " + "one of 'aki', 'ari', or 'ami', the container " + "and disk formats must match.") + raise exception.Invalid(msg) + def _required_format_absent(format, formats): activating = status == 'active' unrecognized = format not in formats @@ -481,20 +505,19 @@ def _required_format_absent(format, formats): msg = "Invalid container format '%s' for image." % container_format raise exception.Invalid(msg) - if disk_format in ('aki', 'ari', 'ami') or\ - container_format in ('aki', 'ari', 'ami'): - if container_format != disk_format: - msg = ("Invalid mix of disk and container formats. " - "When setting a disk or container format to " - "one of 'ami', 'ari', or 'ami', the container " - "and disk formats must match.") - raise exception.Invalid(msg) - name = values.get('name') if name and len(name) > 255: msg = _('Image name too long: %d') % len(name) raise exception.Invalid(msg) + return values + + +def _update_values(image_ref, values): + for k in values.keys(): + if getattr(image_ref, k) != values[k]: + setattr(image_ref, k, values[k]) + def _image_update(context, values, image_id, purge_props=False): """ @@ -547,7 +570,8 @@ def _image_update(context, values, image_id, purge_props=False): # investigation, the @validates decorator does not validate # on new records, only on existing records, which is, well, # idiotic. - validate_image(image_ref.to_dict()) + values = validate_image(image_ref.to_dict()) + _update_values(image_ref, values) try: image_ref.save(session=session) diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py index 8cfdaf8395..b27b14dc28 100644 --- a/glance/tests/unit/v1/test_api.py +++ b/glance/tests/unit/v1/test_api.py @@ -2012,6 +2012,28 @@ def destroy_fixtures(self): db_models.unregister_models(db_api._ENGINE) db_models.register_models(db_api._ENGINE) + def _do_test_defaulted_format(self, format_key, format_value): + fixture_headers = {'x-image-meta-name': 'defaulted', + 'x-image-meta-location': 'http://foo.com/image', + format_key: format_value} + + 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.assertEquals(res.status_int, 201) + res_body = json.loads(res.body)['image'] + self.assertEquals(format_value, res_body['disk_format']) + self.assertEquals(format_value, res_body['container_format']) + + def test_defaulted_amazon_format(self): + for key in ('x-image-meta-disk-format', + 'x-image-meta-container-format'): + for value in ('aki', 'ari', 'ami'): + self._do_test_defaulted_format(key, value) + def test_bad_disk_format(self): fixture_headers = {'x-image-meta-store': 'bad', 'x-image-meta-name': 'bogus',