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,
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"
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."""
_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
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):
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):
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.
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.
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):
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
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
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,
'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,
'container_format': None,
'checksum': None,
'deleted': None,
- 'deleted_at': None,
'status': None,
'properties': {'kernel_id': 'foo',
'ramdisk_id': 'bar'},