From 3c5efdb74eae49e779f59debfc3807c913e4f699 Mon Sep 17 00:00:00 2001 From: David Koo Date: Fri, 20 Dec 2013 10:49:20 +0800 Subject: [PATCH] Allow updating empty created v2 images from v1 When an empty image is created through python-glanceclient using v2 APIs but updated using v1 APIs, python-glanceclient crashes with a "int() argument must be a string or a number, not 'NoneType'" message. This is because v1.images.ImageManager._format_image_meta_for_user expects the 'size' (and 'min_ram' and 'min_disk') field of an image to be convertible to 'int' but the server-side v2 APIs set it to 'None' for an empty image. Therefore the conversion to int fails with the message above. This fix modifies _format_image_meta_for_user to check whether or not a field can be converted to 'int' and, if not, returns 0 (zero) as the value instead. Tests have also been added. Change-Id: I86680bc06c8ce3ee492efeb3f32071da4f293bcd Closes-bug: #1258160 --- glanceclient/v1/images.py | 2 +- tests/v1/test_images.py | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/glanceclient/v1/images.py b/glanceclient/v1/images.py index 51caa010..ea1a9862 100644 --- a/glanceclient/v1/images.py +++ b/glanceclient/v1/images.py @@ -98,7 +98,7 @@ class ImageManager(base.Manager): for key in ['size', 'min_ram', 'min_disk']: if key in meta: try: - meta[key] = int(meta[key]) + meta[key] = int(meta[key]) if meta[key] else 0 except ValueError: pass return meta diff --git a/tests/v1/test_images.py b/tests/v1/test_images.py index 0f4d35e2..4f2f556f 100644 --- a/tests/v1/test_images.py +++ b/tests/v1/test_images.py @@ -358,6 +358,32 @@ fixtures = { 'ZZZ', ), }, + '/v1/images/v2_created_img': { + 'PUT': ( + {}, + json.dumps({ + "image": { + "status": "queued", + "deleted": False, + "container_format": "bare", + "min_ram": 0, + "updated_at": "2013-12-20T01:51:45", + "owner": "foo", + "min_disk": 0, + "is_public": False, + "deleted_at": None, + "id": "v2_created_img", + "size": None, + "name": "bar", + "checksum": None, + "created_at": "2013-12-20T01:50:38", + "disk_format": "qcow2", + "properties": {}, + "protected": False + } + }) + ), + }, } @@ -651,6 +677,26 @@ class ImageManagerTest(testtools.TestCase): self.assertEqual(image_list[3].id, 'c') self.assertEqual(len(image_list), 4) + def test_update_v2_created_image_using_v1(self): + fields_to_update = { + 'name': 'bar', + 'container_format': 'bare', + 'disk_format': 'qcow2', + } + image = self.mgr.update('v2_created_img', **fields_to_update) + expect_hdrs = { + 'x-image-meta-name': 'bar', + 'x-image-meta-container_format': 'bare', + 'x-image-meta-disk_format': 'qcow2', + } + expect = [('PUT', '/v1/images/v2_created_img', expect_hdrs, None)] + self.assertEqual(self.api.calls, expect) + self.assertEqual(image.id, 'v2_created_img') + self.assertEqual(image.name, 'bar') + self.assertEqual(image.size, 0) + self.assertEqual(image.container_format, 'bare') + self.assertEqual(image.disk_format, 'qcow2') + class ImageTest(testtools.TestCase): def setUp(self):