From ef3f158a5aa1988be8ab2f295252373f3ee85809 Mon Sep 17 00:00:00 2001 From: Andrew Woodward Date: Wed, 14 May 2014 19:22:48 -0700 Subject: [PATCH] Catch missing Glance image attrs with None Glance is known to drop values from its response if they don't resolve to true. Previously in I67b7dd16a94fe60d873c012f6bd246ab24500d5a the None catch was removed as this WILL cause a call to glance for missing value and optimizations where made to attempt to pre-cache values that can be missing in expected ways. However there are still situations that can't be optimized. Notably this can occur with disk_format, container_format, name, deleted, and checksum. Test adapted from I85c42f8351763da201021a22f5ff0ebd62c6b2db by Mike Perez Closes-bug #1308058 Co-Author: Mike Perez Change-Id: Icddead6f746d4d3ba652858eaae425acce8c177d --- nova/image/glance.py | 6 ++++- nova/tests/image/test_glance.py | 42 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/nova/image/glance.py b/nova/image/glance.py index 1245a5c64477..a24effc10dbd 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -527,7 +527,11 @@ def _extract_attributes(image): elif attr == 'checksum' and output['status'] != 'active': output[attr] = None else: - output[attr] = getattr(image, attr) + # NOTE(xarses): Anything that is caught with the default value + # will result in a additional lookup to glance for said attr. + # Notable attributes that could have this issue: + # disk_format, container_format, name, deleted, checksum + output[attr] = getattr(image, attr, None) output['properties'] = getattr(image, 'properties', {}) diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 556af3dfec89..2d1c470ac25e 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -453,6 +453,48 @@ class TestGlanceImageService(test.NoDBTestCase): self.assertEqual(same_id, image_id) self.assertEqual(service._client.host, 'something-less-likely') + def test_extracting_missing_attributes(self): + """Verify behavior from glance objects that are missing attributes + + This fakes the image class and is missing attribute as the client can + return if they're not set in the database. + """ + class MyFakeGlanceImage(glance_stubs.FakeImage): + def __init__(self, metadata): + IMAGE_ATTRIBUTES = ['size', 'owner', 'id', 'created_at', + 'updated_at', 'status', 'min_disk', + 'min_ram', 'is_public'] + raw = dict.fromkeys(IMAGE_ATTRIBUTES) + raw.update(metadata) + self.__dict__['raw'] = raw + + metadata = { + 'id': 1, + 'created_at': self.NOW_DATETIME, + 'updated_at': self.NOW_DATETIME, + } + image = MyFakeGlanceImage(metadata) + observed = glance._extract_attributes(image) + expected = { + 'id': 1, + 'name': None, + 'is_public': None, + 'size': None, + 'min_disk': None, + 'min_ram': None, + 'disk_format': None, + 'container_format': None, + 'checksum': None, + 'created_at': self.NOW_DATETIME, + 'updated_at': self.NOW_DATETIME, + 'deleted_at': None, + 'deleted': None, + 'status': None, + 'properties': {}, + 'owner': None, + } + self.assertEqual(expected, observed) + def _create_failing_glance_client(info): class MyGlanceStubClient(glance_stubs.StubGlanceClient):