From 171a57a6879683dac5f219a0e8f1080ea687105d Mon Sep 17 00:00:00 2001 From: Josh Durgin Date: Tue, 14 Aug 2012 12:26:19 -0700 Subject: [PATCH] add get_location method for images This is useful for determining whether the backend storage for the image in Glance is the same as the storage used in a volume driver. The direct_url is only available in the v2 images API, so add a version parameter to each request. As more parts of the v2 API are used, this parameter will become more useful. Change-Id: I5ca06b6d80ffe4118f8dd381ed11283573bce71f Signed-off-by: Josh Durgin --- cinder/image/glance.py | 51 ++++++++++++++++++++++++++------------ cinder/tests/image/fake.py | 4 +++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/cinder/image/glance.py b/cinder/image/glance.py index 2d24c90ad..32a9b9bf3 100644 --- a/cinder/image/glance.py +++ b/cinder/image/glance.py @@ -55,13 +55,14 @@ def _parse_image_ref(image_href): return (image_id, host, port) -def _create_glance_client(context, host, port): +def _create_glance_client(context, host, port, version=1): """Instantiate a new glanceclient.Client object""" params = {} if FLAGS.auth_strategy == 'keystone': params['token'] = context.auth_token endpoint = 'http://%s:%s' % (host, port) - return glanceclient.Client('1', endpoint, **params) + + return glanceclient.Client(str(version), endpoint, **params) def get_api_servers(): @@ -81,27 +82,30 @@ def get_api_servers(): class GlanceClientWrapper(object): """Glance client wrapper class that implements retries.""" - def __init__(self, context=None, host=None, port=None): + def __init__(self, context=None, host=None, port=None, version=None): if host is not None: - self.client = self._create_static_client(context, host, port) + self.client = self._create_static_client(context, host, port, + version) else: self.client = None self.api_servers = None - def _create_static_client(self, context, host, port): + def _create_static_client(self, context, host, port, version): """Create a client that we'll use for every call.""" self.host = host self.port = port - return _create_glance_client(context, self.host, self.port) + self.version = version + return _create_glance_client(context, self.host, self.port, + self.version) - def _create_onetime_client(self, context): + def _create_onetime_client(self, context, version): """Create a client that will be used for one call.""" if self.api_servers is None: self.api_servers = get_api_servers() self.host, self.port = self.api_servers.next() - return _create_glance_client(context, self.host, self.port) + return _create_glance_client(context, self.host, self.port, version) - def call(self, context, method, *args, **kwargs): + def call(self, context, version, method, *args, **kwargs): """ Call a glance client method. If we get a connection error, retry the request according to FLAGS.glance_num_retries. @@ -112,7 +116,8 @@ class GlanceClientWrapper(object): num_attempts = 1 + FLAGS.glance_num_retries for attempt in xrange(1, num_attempts + 1): - client = self.client or self._create_onetime_client(context) + client = self.client or self._create_onetime_client(context, + version) try: return getattr(client.images, method)(*args, **kwargs) except retry_excs as e: @@ -140,7 +145,7 @@ class GlanceImageService(object): """Calls out to Glance for a list of detailed image information.""" params = self._extract_query_params(kwargs) try: - images = self._client.call(context, 'list', **params) + images = self._client.call(context, 1, 'list', **params) except Exception: _reraise_translated_exception() @@ -169,7 +174,7 @@ class GlanceImageService(object): def show(self, context, image_id): """Returns a dict with image data for the given opaque image id.""" try: - image = self._client.call(context, 'get', image_id) + image = self._client.call(context, 1, 'get', image_id) except Exception: _reraise_translated_image_exception(image_id) @@ -179,10 +184,24 @@ class GlanceImageService(object): base_image_meta = self._translate_from_glance(image) return base_image_meta + def get_location(self, context, image_id): + """Returns the direct url representing the backend storage location, + or None if this attribute is not shown by Glance.""" + try: + client = GlanceClientWrapper() + image_meta = client.call(context, 2, 'get', image_id) + except Exception: + _reraise_translated_image_exception(image_id) + + if not self._is_image_available(context, image_meta): + raise exception.ImageNotFound(image_id=image_id) + + return getattr(image_meta, 'direct_url', None) + def download(self, context, image_id, data): """Calls out to Glance for metadata and data and writes data.""" try: - image_chunks = self._client.call(context, 'data', image_id) + image_chunks = self._client.call(context, 1, 'data', image_id) except Exception: _reraise_translated_image_exception(image_id) @@ -196,7 +215,7 @@ class GlanceImageService(object): if data: sent_service_image_meta['data'] = data - recv_service_image_meta = self._client.call(context, 'create', + recv_service_image_meta = self._client.call(context, 1, 'create', **sent_service_image_meta) return self._translate_from_glance(recv_service_image_meta) @@ -212,7 +231,7 @@ class GlanceImageService(object): if data: image_meta['data'] = data try: - image_meta = self._client.call(context, 'update', + image_meta = self._client.call(context, 1, 'update', image_id, **image_meta) except Exception: _reraise_translated_image_exception(image_id) @@ -227,7 +246,7 @@ class GlanceImageService(object): """ try: - self._client.call(context, 'delete', image_id) + self._client.call(context, 1, 'delete', image_id) except glanceclient.exc.NotFound: raise exception.ImageNotFound(image_id=image_id) return True diff --git a/cinder/tests/image/fake.py b/cinder/tests/image/fake.py index 602815eca..8e7d172cd 100644 --- a/cinder/tests/image/fake.py +++ b/cinder/tests/image/fake.py @@ -217,6 +217,10 @@ class _FakeImageService(object): if not removed: raise exception.ImageNotFound(image_id=image_id) + def get_location(self, context, image_id): + if image_id in self.images: + return 'fake_location' + return None _fakeImageService = _FakeImageService() -- 2.45.2