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,
|
If we get a connection error,
|
||||||
retry the request according to CONF.glance_num_retries.
|
retry the request according to CONF.glance_num_retries.
|
||||||
"""
|
"""
|
||||||
version = self.version
|
version = kwargs.pop('version', self.version)
|
||||||
if 'version' in kwargs:
|
|
||||||
version = kwargs['version']
|
|
||||||
|
|
||||||
retry_excs = (glanceclient.exc.ServiceUnavailable,
|
retry_excs = (glanceclient.exc.ServiceUnavailable,
|
||||||
glanceclient.exc.InvalidEndpoint,
|
glanceclient.exc.InvalidEndpoint,
|
||||||
|
@ -174,7 +172,9 @@ class GlanceClientWrapper(object):
|
||||||
client = self.client or self._create_onetime_client(context,
|
client = self.client or self._create_onetime_client(context,
|
||||||
version)
|
version)
|
||||||
try:
|
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:
|
except retry_excs as e:
|
||||||
netloc = self.netloc
|
netloc = self.netloc
|
||||||
extra = "retrying"
|
extra = "retrying"
|
||||||
|
@ -199,6 +199,7 @@ class GlanceImageService(object):
|
||||||
|
|
||||||
def __init__(self, client=None):
|
def __init__(self, client=None):
|
||||||
self._client = client or GlanceClientWrapper()
|
self._client = client or GlanceClientWrapper()
|
||||||
|
self._image_schema = None
|
||||||
|
|
||||||
def detail(self, context, **kwargs):
|
def detail(self, context, **kwargs):
|
||||||
"""Calls out to Glance for a list of detailed image information."""
|
"""Calls out to Glance for a list of detailed image information."""
|
||||||
|
@ -211,7 +212,7 @@ class GlanceImageService(object):
|
||||||
_images = []
|
_images = []
|
||||||
for image in images:
|
for image in images:
|
||||||
if self._is_image_available(context, image):
|
if self._is_image_available(context, image):
|
||||||
_images.append(self._translate_from_glance(image))
|
_images.append(self._translate_from_glance(context, image))
|
||||||
|
|
||||||
return _images
|
return _images
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ class GlanceImageService(object):
|
||||||
if not self._is_image_available(context, image):
|
if not self._is_image_available(context, image):
|
||||||
raise exception.ImageNotFound(image_id=image_id)
|
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
|
return base_image_meta
|
||||||
|
|
||||||
def get_location(self, context, image_id):
|
def get_location(self, context, image_id):
|
||||||
|
@ -305,7 +306,7 @@ class GlanceImageService(object):
|
||||||
recv_service_image_meta = self._client.call(context, 'create',
|
recv_service_image_meta = self._client.call(context, 'create',
|
||||||
**sent_service_image_meta)
|
**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,
|
def update(self, context, image_id,
|
||||||
image_meta, data=None, purge_props=True):
|
image_meta, data=None, purge_props=True):
|
||||||
|
@ -330,7 +331,7 @@ class GlanceImageService(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
_reraise_translated_image_exception(image_id)
|
_reraise_translated_image_exception(image_id)
|
||||||
else:
|
else:
|
||||||
return self._translate_from_glance(image_meta)
|
return self._translate_from_glance(context, image_meta)
|
||||||
|
|
||||||
def delete(self, context, image_id):
|
def delete(self, context, image_id):
|
||||||
"""Delete the given image.
|
"""Delete the given image.
|
||||||
|
@ -345,19 +346,47 @@ class GlanceImageService(object):
|
||||||
raise exception.ImageNotFound(image_id=image_id)
|
raise exception.ImageNotFound(image_id=image_id)
|
||||||
return True
|
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
|
@staticmethod
|
||||||
def _translate_to_glance(image_meta):
|
def _translate_to_glance(image_meta):
|
||||||
image_meta = _convert_to_string(image_meta)
|
image_meta = _convert_to_string(image_meta)
|
||||||
image_meta = _remove_read_only(image_meta)
|
image_meta = _remove_read_only(image_meta)
|
||||||
return 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
|
@staticmethod
|
||||||
def _is_image_available(context, image):
|
def _is_image_available(context, image):
|
||||||
"""Check image availability.
|
"""Check image availability.
|
||||||
|
|
|
@ -18,6 +18,13 @@ import glanceclient.exc
|
||||||
NOW_GLANCE_FORMAT = "2010-10-11T10:30:22"
|
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):
|
class StubGlanceClient(object):
|
||||||
|
|
||||||
def __init__(self, images=None):
|
def __init__(self, images=None):
|
||||||
|
@ -88,11 +95,6 @@ class StubGlanceClient(object):
|
||||||
|
|
||||||
class FakeImage(object):
|
class FakeImage(object):
|
||||||
def __init__(self, metadata):
|
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 = dict.fromkeys(IMAGE_ATTRIBUTES)
|
||||||
raw.update(metadata)
|
raw.update(metadata)
|
||||||
self.__dict__['raw'] = raw
|
self.__dict__['raw'] = raw
|
||||||
|
@ -108,3 +110,14 @@ class FakeImage(object):
|
||||||
self.__dict__['raw'][key] = value
|
self.__dict__['raw'][key] = value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError(key)
|
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_api_version = 2
|
||||||
config.glance_num_retries = 0
|
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 = {
|
metadata = {
|
||||||
'id': 1,
|
'id': 1,
|
||||||
'size': 2,
|
'size': 2,
|
||||||
|
@ -623,23 +619,13 @@ class TestGlanceImageService(test.TestCase):
|
||||||
'ramdisk_id': 'bar',
|
'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)
|
image = glance_stubs.FakeImage(metadata)
|
||||||
client = glance_stubs.StubGlanceClient()
|
client = glance_stubs.StubGlanceClient()
|
||||||
|
|
||||||
service = self._create_image_service(client)
|
service = self._create_image_service(client)
|
||||||
service._image_schema = FakeSchema(attributes)
|
service._image_schema = glance_stubs.FakeSchema()
|
||||||
actual = service._translate_from_glance(image)
|
|
||||||
|
actual = service._translate_from_glance('fake_context', image)
|
||||||
expected = {
|
expected = {
|
||||||
'id': 1,
|
'id': 1,
|
||||||
'name': None,
|
'name': None,
|
||||||
|
@ -651,7 +637,6 @@ class TestGlanceImageService(test.TestCase):
|
||||||
'container_format': None,
|
'container_format': None,
|
||||||
'checksum': None,
|
'checksum': None,
|
||||||
'deleted': None,
|
'deleted': None,
|
||||||
'deleted_at': None,
|
|
||||||
'status': None,
|
'status': None,
|
||||||
'properties': {'kernel_id': 'foo',
|
'properties': {'kernel_id': 'foo',
|
||||||
'ramdisk_id': 'bar'},
|
'ramdisk_id': 'bar'},
|
||||||
|
|
Loading…
Reference in New Issue