]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Include boot properties from glance v2 images
authorJon Bernard <jobernar@redhat.com>
Tue, 7 Apr 2015 17:57:36 +0000 (13:57 -0400)
committerJon Bernard <jobernar@redhat.com>
Thu, 9 Apr 2015 18:13:04 +0000 (14:13 -0400)
In order for users to take advantage of COW volumes created from
a glance image, Cinder must be configured to use Glance API version
2 (default is 1). In version 2, the required boot metadata (kernel_id
and ramdisk_id) are no long stored in the 'properties' dict, but as
standalone fields in the GET response from glance. The existing cinder
parser for the glance request is not aware of this and the volume
created form a v2 image will lack this required metadata.

This was causing the recent Ceph CI gate failures for
test_volume_boot_pattern.

Change-Id: I688898b3841691369d73887f7eabdceb05155db1
Closes-Bug: #1439371

cinder/image/glance.py
cinder/tests/image/test_glance.py

index 5b9c85ed18b898c30abe47df56fb8d14ce661b00..9bef05bf7ab70461f6ca579c9690380e78d6385c 100644 (file)
@@ -449,6 +449,17 @@ def _extract_attributes(image):
 
     output['properties'] = getattr(image, 'properties', {})
 
+    # NOTE(jbernard): Update image properties for API version 2.  For UEC
+    # images stored in glance, the necessary boot information is stored in the
+    # properties dict in version 1 so there is nothing more to do.  However, in
+    # version 2 these are standalone fields in the GET response.  This bit of
+    # code moves them back into the properties dict as the caller expects, thus
+    # producing a volume with correct metadata for booting.
+    for attr in ('kernel_id', 'ramdisk_id'):
+        value = getattr(image, attr, None)
+        if value:
+            output['properties'][attr] = value
+
     return output
 
 
index f4f9ee150e2f65575c86da6408fa251d78ae102f..1fa518ff98a53854a0cf62a619c3b3e8e38a86e5 100644 (file)
@@ -584,6 +584,63 @@ class TestGlanceImageService(test.TestCase):
         }
         self.assertEqual(actual, expected)
 
+    @mock.patch('cinder.image.glance.CONF')
+    def test_extracting_v2_boot_properties(self, config):
+
+        config.glance_api_version = 2
+
+        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,
+            'min_disk': 2,
+            'min_ram': 2,
+            'kernel_id': 'foo',
+            '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)
+        expected = {
+            'id': 1,
+            'name': None,
+            'is_public': None,
+            'size': 2,
+            'min_disk': 2,
+            'min_ram': 2,
+            'disk_format': None,
+            'container_format': None,
+            'checksum': None,
+            'deleted': None,
+            'deleted_at': None,
+            'status': None,
+            'properties': {'kernel_id': 'foo',
+                           'ramdisk_id': 'bar'},
+            'owner': None,
+            'created_at': None,
+            'updated_at': None
+        }
+
+        self.assertEqual(expected, actual)
+
 
 class TestGlanceClientVersion(test.TestCase):
     """Tests the version of the glance client generated."""