From d6ffe3828c5fe0cb86a95c046bb54ceb43da8f6b Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 3 Jul 2012 09:55:02 -0700 Subject: [PATCH] Report size of image file in v2 API Size will be None until image data is uploaded. The size attribute will be updated to reflect the actual size. Related to bp api-2. Change-Id: I577d8005b9ce60bf1470cda43413f0cdc034dbe1 --- glance/api/v2/images.py | 8 ++++-- glance/tests/functional/v2/test_images.py | 8 ++++++ glance/tests/functional/v2/test_schemas.py | 1 + glance/tests/unit/v2/test_images_resource.py | 29 ++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/glance/api/v2/images.py b/glance/api/v2/images.py index 6975e63ebc..cb1476c0b7 100644 --- a/glance/api/v2/images.py +++ b/glance/api/v2/images.py @@ -258,8 +258,8 @@ class ResponseSerializer(wsgi.JSONResponseSerializer): def _format_image(self, image): _image = image['properties'] - for key in ['id', 'name', 'created_at', 'updated_at', 'tags', 'owner', - 'checksum']: + for key in ['id', 'name', 'created_at', 'updated_at', 'tags', 'size', + 'owner', 'checksum']: _image[key] = image[key] _image['visibility'] = 'public' if image['is_public'] else 'private' _image = self.schema.filter(_image) @@ -333,6 +333,10 @@ _BASE_PROPERTIES = { 'type': 'string', 'maxLength': 32, }, + 'size': { + 'type': 'integer', + 'description': 'Size of image file in bytes', + }, 'created_at': { 'type': 'string', 'description': 'Date and time of image registration', diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py index 631d534814..289a25c27b 100644 --- a/glance/tests/functional/v2/test_images.py +++ b/glance/tests/functional/v2/test_images.py @@ -85,6 +85,7 @@ class TestImages(functional.FunctionalTest): image = json.loads(response.text)['image'] self.assertEqual(image_id, image['id']) self.assertEqual(None, image['checksum']) + self.assertEqual(None, image['size']) self.assertEqual('bar', image['foo']) self.assertTrue(image['created_at']) self.assertTrue(image['updated_at']) @@ -147,6 +148,13 @@ class TestImages(functional.FunctionalTest): response = requests.put(path, headers=headers, data='XXX') self.assertEqual(409, response.status_code) + # Ensure the size is updated to reflect the data uploaded + path = self._url('/v2/images/%s' % image_id) + headers = self._headers() + response = requests.get(path, headers=headers) + self.assertEqual(200, response.status_code) + self.assertEqual(5, json.loads(response.text)['image']['size']) + # Deletion should work path = self._url('/v2/images/%s' % image_id) response = requests.delete(path, headers=self._headers()) diff --git a/glance/tests/functional/v2/test_schemas.py b/glance/tests/functional/v2/test_schemas.py index 836d4c6430..d686fd7489 100644 --- a/glance/tests/functional/v2/test_schemas.py +++ b/glance/tests/functional/v2/test_schemas.py @@ -55,6 +55,7 @@ class TestSchemas(functional.FunctionalTest): 'created_at', 'updated_at', 'tags', + 'size', 'type', 'format', 'self', diff --git a/glance/tests/unit/v2/test_images_resource.py b/glance/tests/unit/v2/test_images_resource.py index 57daec5d4c..a4e1731b36 100644 --- a/glance/tests/unit/v2/test_images_resource.py +++ b/glance/tests/unit/v2/test_images_resource.py @@ -703,6 +703,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['one', 'two'], + 'size': 1024, }, { 'id': unit_test_utils.UUID2, @@ -714,6 +715,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': None, }, ] expected = { @@ -727,6 +729,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['one', 'two'], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID1, 'file': '/v2/images/%s/file' % unit_test_utils.UUID1, 'access': '/v2/images/%s/access' % unit_test_utils.UUID1, @@ -741,6 +744,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': None, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -768,6 +772,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['one', 'two'], + 'size': 1024, }, { 'id': unit_test_utils.UUID2, @@ -779,6 +784,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': None, }, ] expected = { @@ -792,6 +798,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['one', 'two'], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID1, 'file': '/v2/images/%s/file' % unit_test_utils.UUID1, 'access': '/v2/images/%s/access' % unit_test_utils.UUID1, @@ -806,6 +813,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': None, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -835,6 +843,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['one', 'two'], + 'size': 1024, }, { 'id': unit_test_utils.UUID2, @@ -846,6 +855,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': None, }, ] expected = { @@ -859,6 +869,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['one', 'two'], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID1, 'file': '/v2/images/%s/file' % unit_test_utils.UUID1, 'access': '/v2/images/%s/access' % unit_test_utils.UUID1, @@ -873,6 +884,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': None, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -901,6 +913,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['one', 'two'], + 'size': 1024, }, { 'id': unit_test_utils.UUID2, @@ -912,6 +925,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': None, }, ] expected = { @@ -925,6 +939,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['one', 'two'], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID1, 'file': '/v2/images/%s/file' % unit_test_utils.UUID1, 'access': '/v2/images/%s/access' % unit_test_utils.UUID1, @@ -939,6 +954,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': None, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -969,6 +985,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['three', 'four'], + 'size': 1024, } expected = { 'image': { @@ -980,6 +997,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['three', 'four'], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -1001,6 +1019,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': 1024, } self_link = '/v2/images/%s' % unit_test_utils.UUID2 expected = { @@ -1013,6 +1032,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': 1024, 'self': self_link, 'file': '%s/file' % self_link, 'access': '%s/access' % self_link, @@ -1035,6 +1055,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': ['five'], + 'size': 1024, } self_link = '/v2/images/%s' % unit_test_utils.UUID2 expected = { @@ -1047,6 +1068,7 @@ class TestImagesSerializer(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': ['five'], + 'size': 1024, 'self': self_link, 'file': '%s/file' % self_link, 'access': '%s/access' % self_link, @@ -1082,6 +1104,7 @@ class TestImagesSerializerWithExtendedSchema(test_utils.BaseTestCase): 'created_at': DATETIME, 'updated_at': DATETIME, 'tags': [], + 'size': 1024, 'properties': {'color': 'green', 'mood': 'grouchy'}, } @@ -1096,6 +1119,7 @@ class TestImagesSerializerWithExtendedSchema(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': 1024, 'color': 'green', 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, @@ -1119,6 +1143,7 @@ class TestImagesSerializerWithExtendedSchema(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': 1024, 'color': 'invalid', 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, @@ -1148,6 +1173,7 @@ class TestImagesSerializerWithAdditionalProperties(test_utils.BaseTestCase): 'marx': 'groucho', }, 'tags': [], + 'size': 1024, } def test_show(self): @@ -1163,6 +1189,7 @@ class TestImagesSerializerWithAdditionalProperties(test_utils.BaseTestCase): 'updated_at': ISOTIME, 'marx': 'groucho', 'tags': [], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -1190,6 +1217,7 @@ class TestImagesSerializerWithAdditionalProperties(test_utils.BaseTestCase): 'updated_at': ISOTIME, 'marx': 123, 'tags': [], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2, @@ -1213,6 +1241,7 @@ class TestImagesSerializerWithAdditionalProperties(test_utils.BaseTestCase): 'created_at': ISOTIME, 'updated_at': ISOTIME, 'tags': [], + 'size': 1024, 'self': '/v2/images/%s' % unit_test_utils.UUID2, 'file': '/v2/images/%s/file' % unit_test_utils.UUID2, 'access': '/v2/images/%s/access' % unit_test_utils.UUID2,