Merge "Fix properties extracting from image with glance api v2"

This commit is contained in:
Jenkins 2015-07-24 00:48:50 +00:00 committed by Gerrit Code Review
commit 02b2d31ad7
3 changed files with 65 additions and 38 deletions

View File

@ -161,9 +161,7 @@ class GlanceClientWrapper(object):
If we get a connection error,
retry the request according to CONF.glance_num_retries.
"""
version = self.version
if 'version' in kwargs:
version = kwargs['version']
version = kwargs.pop('version', self.version)
retry_excs = (glanceclient.exc.ServiceUnavailable,
glanceclient.exc.InvalidEndpoint,
@ -174,7 +172,9 @@ class GlanceClientWrapper(object):
client = self.client or self._create_onetime_client(context,
version)
try:
return getattr(client.images, method)(*args, **kwargs)
controller = getattr(client,
kwargs.pop('controller', 'images'))
return getattr(controller, method)(*args, **kwargs)
except retry_excs as e:
netloc = self.netloc
extra = "retrying"
@ -199,6 +199,7 @@ class GlanceImageService(object):
def __init__(self, client=None):
self._client = client or GlanceClientWrapper()
self._image_schema = None
def detail(self, context, **kwargs):
"""Calls out to Glance for a list of detailed image information."""
@ -211,7 +212,7 @@ class GlanceImageService(object):
_images = []
for image in images:
if self._is_image_available(context, image):
_images.append(self._translate_from_glance(image))
_images.append(self._translate_from_glance(context, image))
return _images
@ -240,7 +241,7 @@ class GlanceImageService(object):
if not self._is_image_available(context, image):
raise exception.ImageNotFound(image_id=image_id)
base_image_meta = self._translate_from_glance(image)
base_image_meta = self._translate_from_glance(context, image)
return base_image_meta
def get_location(self, context, image_id):
@ -305,7 +306,7 @@ class GlanceImageService(object):
recv_service_image_meta = self._client.call(context, 'create',
**sent_service_image_meta)
return self._translate_from_glance(recv_service_image_meta)
return self._translate_from_glance(context, recv_service_image_meta)
def update(self, context, image_id,
image_meta, data=None, purge_props=True):
@ -330,7 +331,7 @@ class GlanceImageService(object):
except Exception:
_reraise_translated_image_exception(image_id)
else:
return self._translate_from_glance(image_meta)
return self._translate_from_glance(context, image_meta)
def delete(self, context, image_id):
"""Delete the given image.
@ -345,19 +346,47 @@ class GlanceImageService(object):
raise exception.ImageNotFound(image_id=image_id)
return True
def _translate_from_glance(self, context, image):
"""Get image metadata from glance image.
Extract metadata from image and convert it's properties
to type cinder expected.
:param image: glance image object
:return: image metadata dictionary
"""
if CONF.glance_api_version == 2:
if self._image_schema is None:
self._image_schema = self._client.call(context, 'get',
controller='schemas',
schema_name='image',
version=2)
# NOTE(aarefiev): get base image property, store image 'schema'
# is redundant, so ignore it.
image_meta = {key: getattr(image, key)
for key in image.keys()
if self._image_schema.is_base_property(key) is True
and key != 'schema'}
# NOTE(aarefiev): nova is expected that all image properties
# (custom or defined in schema-image.json) stores in
# 'properties' key.
image_meta['properties'] = {
key: getattr(image, key) for key in image.keys()
if self._image_schema.is_base_property(key) is False}
else:
image_meta = _extract_attributes(image)
image_meta = _convert_timestamps_to_datetimes(image_meta)
image_meta = _convert_from_string(image_meta)
return image_meta
@staticmethod
def _translate_to_glance(image_meta):
image_meta = _convert_to_string(image_meta)
image_meta = _remove_read_only(image_meta)
return image_meta
@staticmethod
def _translate_from_glance(image):
image_meta = _extract_attributes(image)
image_meta = _convert_timestamps_to_datetimes(image_meta)
image_meta = _convert_from_string(image_meta)
return image_meta
@staticmethod
def _is_image_available(context, image):
"""Check image availability.

View File

@ -18,6 +18,13 @@ import glanceclient.exc
NOW_GLANCE_FORMAT = "2010-10-11T10:30:22"
IMAGE_ATTRIBUTES = ['size', 'disk_format', 'owner',
'container_format', 'checksum', 'id',
'name', 'created_at', 'updated_at',
'deleted', 'status',
'min_disk', 'min_ram', 'is_public']
class StubGlanceClient(object):
def __init__(self, images=None):
@ -88,11 +95,6 @@ class StubGlanceClient(object):
class FakeImage(object):
def __init__(self, metadata):
IMAGE_ATTRIBUTES = ['size', 'disk_format', 'owner',
'container_format', 'checksum', 'id',
'name', 'created_at', 'updated_at',
'deleted', 'status',
'min_disk', 'min_ram', 'is_public']
raw = dict.fromkeys(IMAGE_ATTRIBUTES)
raw.update(metadata)
self.__dict__['raw'] = raw
@ -108,3 +110,14 @@ class FakeImage(object):
self.__dict__['raw'][key] = value
except KeyError:
raise AttributeError(key)
def keys(self):
return self.__dict__['raw'].keys()
class FakeSchema(object):
def is_base_property(self, key):
if key in IMAGE_ATTRIBUTES:
return True
else:
return False

View File

@ -610,10 +610,6 @@ class TestGlanceImageService(test.TestCase):
config.glance_api_version = 2
config.glance_num_retries = 0
attributes = ['size', 'disk_format', 'owner', 'container_format',
'checksum', 'id', 'name', 'created_at', 'updated_at',
'deleted', 'status', 'min_disk', 'min_ram', 'is_public']
metadata = {
'id': 1,
'size': 2,
@ -623,23 +619,13 @@ class TestGlanceImageService(test.TestCase):
'ramdisk_id': 'bar',
}
class FakeSchema(object):
def __init__(self, base):
self.base = base
def is_base_property(self, key):
if key in self.base:
return True
else:
return False
image = glance_stubs.FakeImage(metadata)
client = glance_stubs.StubGlanceClient()
service = self._create_image_service(client)
service._image_schema = FakeSchema(attributes)
actual = service._translate_from_glance(image)
service._image_schema = glance_stubs.FakeSchema()
actual = service._translate_from_glance('fake_context', image)
expected = {
'id': 1,
'name': None,
@ -651,7 +637,6 @@ class TestGlanceImageService(test.TestCase):
'container_format': None,
'checksum': None,
'deleted': None,
'deleted_at': None,
'status': None,
'properties': {'kernel_id': 'foo',
'ramdisk_id': 'bar'},