Merge "Fix properties extracting from image with glance api v2"
This commit is contained in:
commit
02b2d31ad7
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'},
|
||||
|
|
Loading…
Reference in New Issue