Only get image location attributes if including locations
Commit 155eeabbfa added 'direct_url' and
'locations' to the list of attributes to get from an image which makes a
call back to glance if the attributes aren't on the image, and can
result in a 404 if they aren't available, which would be in the glance
v1 API case.
This change simply passes the new include_locations parameter down to
_extract_attributes so we can do the proper filtering.
Change-Id: I903fa5c781fed52183b340dc3d9bc4b6598b21ce
Partial-Bug: #1351333
			
			
This commit is contained in:
		@@ -307,16 +307,14 @@ class GlanceImageService(object):
 | 
			
		||||
        if not _is_image_available(context, image):
 | 
			
		||||
            raise exception.ImageNotFound(image_id=image_id)
 | 
			
		||||
 | 
			
		||||
        image = _translate_from_glance(image)
 | 
			
		||||
        image = _translate_from_glance(image,
 | 
			
		||||
                                       include_locations=include_locations)
 | 
			
		||||
        if include_locations:
 | 
			
		||||
            locations = image.get('locations', None) or []
 | 
			
		||||
            du = image.get('direct_url', None)
 | 
			
		||||
            if du:
 | 
			
		||||
                locations.append({'url': du, 'metadata': {}})
 | 
			
		||||
            image['locations'] = locations
 | 
			
		||||
        else:
 | 
			
		||||
            image.pop('locations', None)
 | 
			
		||||
            image.pop('direct_url', None)
 | 
			
		||||
 | 
			
		||||
        return image
 | 
			
		||||
 | 
			
		||||
@@ -482,8 +480,9 @@ def _translate_to_glance(image_meta):
 | 
			
		||||
    return image_meta
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _translate_from_glance(image):
 | 
			
		||||
    image_meta = _extract_attributes(image)
 | 
			
		||||
def _translate_from_glance(image, include_locations=False):
 | 
			
		||||
    image_meta = _extract_attributes(image,
 | 
			
		||||
                                     include_locations=include_locations)
 | 
			
		||||
    image_meta = _convert_timestamps_to_datetimes(image_meta)
 | 
			
		||||
    image_meta = _convert_from_string(image_meta)
 | 
			
		||||
    return image_meta
 | 
			
		||||
@@ -532,7 +531,7 @@ def _convert_to_string(metadata):
 | 
			
		||||
    return _convert(_json_dumps, metadata)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _extract_attributes(image):
 | 
			
		||||
def _extract_attributes(image, include_locations=False):
 | 
			
		||||
    # NOTE(hdd): If a key is not found, base.Resource.__getattr__() may perform
 | 
			
		||||
    # a get(), resulting in a useless request back to glance. This list is
 | 
			
		||||
    # therefore sorted, with dependent attributes as the end
 | 
			
		||||
@@ -547,6 +546,7 @@ def _extract_attributes(image):
 | 
			
		||||
 | 
			
		||||
    queued = getattr(image, 'status') == 'queued'
 | 
			
		||||
    queued_exclude_attrs = ['disk_format', 'container_format']
 | 
			
		||||
    include_locations_attrs = ['direct_url', 'locations']
 | 
			
		||||
    output = {}
 | 
			
		||||
 | 
			
		||||
    for attr in IMAGE_ATTRIBUTES:
 | 
			
		||||
@@ -560,6 +560,10 @@ def _extract_attributes(image):
 | 
			
		||||
        # NOTE(liusheng): queued image may not have these attributes and 'name'
 | 
			
		||||
        elif queued and attr in queued_exclude_attrs:
 | 
			
		||||
            output[attr] = getattr(image, attr, None)
 | 
			
		||||
        # NOTE(mriedem): Only get location attrs if including locations.
 | 
			
		||||
        elif attr in include_locations_attrs:
 | 
			
		||||
            if include_locations:
 | 
			
		||||
                output[attr] = getattr(image, attr, None)
 | 
			
		||||
        else:
 | 
			
		||||
            # NOTE(xarses): Anything that is caught with the default value
 | 
			
		||||
            # will result in a additional lookup to glance for said attr.
 | 
			
		||||
 
 | 
			
		||||
@@ -454,7 +454,7 @@ class TestGlanceImageService(test.NoDBTestCase):
 | 
			
		||||
        self.assertEqual(same_id, image_id)
 | 
			
		||||
        self.assertEqual(service._client.host, 'something-less-likely')
 | 
			
		||||
 | 
			
		||||
    def test_extracting_missing_attributes(self):
 | 
			
		||||
    def _test_extracting_missing_attributes(self, include_locations):
 | 
			
		||||
        """Verify behavior from glance objects that are missing attributes
 | 
			
		||||
 | 
			
		||||
        This fakes the image class and is missing attribute as the client can
 | 
			
		||||
@@ -475,7 +475,8 @@ class TestGlanceImageService(test.NoDBTestCase):
 | 
			
		||||
            'updated_at': self.NOW_DATETIME,
 | 
			
		||||
        }
 | 
			
		||||
        image = MyFakeGlanceImage(metadata)
 | 
			
		||||
        observed = glance._extract_attributes(image)
 | 
			
		||||
        observed = glance._extract_attributes(
 | 
			
		||||
            image, include_locations=include_locations)
 | 
			
		||||
        expected = {
 | 
			
		||||
            'id': 1,
 | 
			
		||||
            'name': None,
 | 
			
		||||
@@ -492,12 +493,19 @@ class TestGlanceImageService(test.NoDBTestCase):
 | 
			
		||||
            'deleted': None,
 | 
			
		||||
            'status': None,
 | 
			
		||||
            'properties': {},
 | 
			
		||||
            'owner': None,
 | 
			
		||||
            'locations': None,
 | 
			
		||||
            'direct_url': None
 | 
			
		||||
            'owner': None
 | 
			
		||||
        }
 | 
			
		||||
        if include_locations:
 | 
			
		||||
            expected['locations'] = None
 | 
			
		||||
            expected['direct_url'] = None
 | 
			
		||||
        self.assertEqual(expected, observed)
 | 
			
		||||
 | 
			
		||||
    def test_extracting_missing_attributes_include_locations(self):
 | 
			
		||||
        self._test_extracting_missing_attributes(include_locations=True)
 | 
			
		||||
 | 
			
		||||
    def test_extracting_missing_attributes_exclude_locations(self):
 | 
			
		||||
        self._test_extracting_missing_attributes(include_locations=False)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _create_failing_glance_client(info):
 | 
			
		||||
    class MyGlanceStubClient(glance_stubs.StubGlanceClient):
 | 
			
		||||
@@ -652,7 +660,7 @@ class TestShow(test.NoDBTestCase):
 | 
			
		||||
        client.call.assert_called_once_with(ctx, 1, 'get',
 | 
			
		||||
                                            mock.sentinel.image_id)
 | 
			
		||||
        is_avail_mock.assert_called_once_with(ctx, {})
 | 
			
		||||
        trans_from_mock.assert_called_once_with({})
 | 
			
		||||
        trans_from_mock.assert_called_once_with({}, include_locations=False)
 | 
			
		||||
        self.assertIn('mock', info)
 | 
			
		||||
        self.assertEqual(mock.sentinel.trans_from, info['mock'])
 | 
			
		||||
 | 
			
		||||
@@ -743,7 +751,8 @@ class TestShow(test.NoDBTestCase):
 | 
			
		||||
 | 
			
		||||
        client.call.assert_called_once_with(ctx, 2, 'get', image_id)
 | 
			
		||||
        avail_mock.assert_called_once_with(ctx, mock.sentinel.image)
 | 
			
		||||
        trans_from_mock.assert_called_once_with(mock.sentinel.image)
 | 
			
		||||
        trans_from_mock.assert_called_once_with(mock.sentinel.image,
 | 
			
		||||
                                                include_locations=True)
 | 
			
		||||
        self.assertIn('locations', info)
 | 
			
		||||
        self.assertEqual(locations, info['locations'])
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user