]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
add get_location method for images
authorJosh Durgin <josh.durgin@inktank.com>
Tue, 14 Aug 2012 19:26:19 +0000 (12:26 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Tue, 14 Aug 2012 20:33:10 +0000 (13:33 -0700)
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 <josh.durgin@inktank.com>
cinder/image/glance.py
cinder/tests/image/fake.py

index 2d24c90adf2b7d371554a4a567960f43adcdc9ae..32a9b9bf30e8fcf38eb29ad9bee0f3e6e2d7c7a8 100644 (file)
@@ -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
index 602815ecaabae503a5dd54a87b0621ae92c1c76f..8e7d172cd4d85df9db7ab4e5ff62bf7e53304544 100644 (file)
@@ -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()