]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add check for qemu-img to image_utils fetch_to_raw
authorJay S. Bryant <jsbryant@us.ibm.com>
Mon, 12 Aug 2013 17:55:48 +0000 (12:55 -0500)
committerJay S. Bryant <jsbryant@us.ibm.com>
Tue, 10 Sep 2013 19:04:46 +0000 (14:04 -0500)
Some platforms, particularly PowerPC systems running RHEL,
do not have qemu-img installed by default and do not
support image formats other than RAW.  For these systems,
functions/drivers that use fetch_to_raw() currently fail
because it is assumed that qemu-img will always be installed.

This change updates fetch_to_raw() to function more like the
upload_volume() function which checks the image format and skips
any conversion if the image is already in the RAW format. To
minimize the impact upon platforms that have qemu-img installed
this is being implemented by checking to see if qemu-img is
installed.  If it is installed, no changes are made to the flow
through fetch_to_raw.  If qemu-img is not available and the image
format is not already RAW, an exception is thrown.  Otherwise,
the image is downloaded and we do not progress to the portions of
fetch_to_raw that require qemu-img to be installed.

This commit also updates the test cases that touch this code.

Closes-bug: 1200800

Change-Id: I34540dfa238a8b8e61ff5c30c7e121130bad39b4

cinder/image/image_utils.py
cinder/tests/test_image_utils.py

index 032919595f6ed0d6a83ddd6e79307c48f2cb024d..dbfb7232c809505dddbb24c1bb9410181e4d30a2 100644 (file)
@@ -36,9 +36,10 @@ from oslo.config import cfg
 from cinder import exception
 from cinder.openstack.common import fileutils
 from cinder.openstack.common import log as logging
+from cinder.openstack.common import processutils
 from cinder.openstack.common import strutils
 from cinder import utils
-
+from cinder.volume import utils as volume_utils
 
 LOG = logging.getLogger(__name__)
 
@@ -254,16 +255,55 @@ def fetch_to_volume_format(context, image_service,
             os.path.exists(CONF.image_conversion_dir)):
         os.makedirs(CONF.image_conversion_dir)
 
+    no_qemu_img = False
+    image_meta = image_service.show(context, image_id)
+
     # NOTE(avishay): I'm not crazy about creating temp files which may be
     # large and cause disk full errors which would confuse users.
     # Unfortunately it seems that you can't pipe to 'qemu-img convert' because
     # it seeks. Maybe we can think of something for a future version.
     with temporary_file() as tmp:
+        # We may be on a system that doesn't have qemu-img installed.  That
+        # is ok if we are working with a RAW image.  This logic checks to see
+        # if qemu-img is installed.  If not we make sure the image is RAW and
+        # throw an exception if not.  Otherwise we stop before needing
+        # qemu-img.  Systems with qemu-img will always progress through the
+        # whole function.
+        try:
+            # Use the empty tmp file to make sure qemu_img_info works.
+            qemu_img_info(tmp)
+        except processutils.ProcessExecutionError:
+            no_qemu_img = True
+            if image_meta:
+                if image_meta['disk_format'] != 'raw':
+                    raise exception.ImageUnacceptable(
+                        reason=_("qemu-img is not installed and image is of "
+                                 "type %s.  Only RAW images can be used if "
+                                 "qemu-img is not installed.") %
+                        image_meta['disk_format'],
+                        image_id=image_id)
+            else:
+                raise exception.ImageUnacceptable(
+                    reason=_("qemu-img is not installed and the disk "
+                             "format is not specified.  Only RAW images "
+                             "can be used if qemu-img is not installed."),
+                    image_id=image_id)
+
         fetch(context, image_service, image_id, tmp, user_id, project_id)
 
         if is_xenserver_image(context, image_service, image_id):
             replace_xenserver_image_with_coalesced_vhd(tmp)
 
+        if no_qemu_img:
+            # qemu-img is not installed but we do have a RAW image.  As a
+            # result we only need to copy the image to the destination and then
+            # return.
+            LOG.debug(_('Copying image from %(tmp)s to volume %(dest)s - '
+                        'size: %(size)s') % {'tmp': tmp, 'dest': dest,
+                                             'size': image_meta['size']})
+            volume_utils.copy_volume(tmp, dest, image_meta['size'])
+            return
+
         data = qemu_img_info(tmp)
         fmt = data.file_format
         if fmt is None:
index a6f7a11e3e985785ae5b8fb1ad23e1a5c4f20ab4..fd1d29b9c4c9e7df3776565fc97fd3d5789628c1 100644 (file)
@@ -165,6 +165,12 @@ class TestUtils(test.TestCase):
                 (TEST_RET, 'ignored')
             )
 
+        utils.execute(
+            'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+            self.TEST_DEV_PATH, run_as_root=True).AndReturn(
+                (TEST_RET, 'ignored')
+            )
+
         utils.execute('qemu-img', 'convert', '-O', 'raw',
                       self.TEST_DEV_PATH, self.TEST_DEV_PATH, run_as_root=True)
 
@@ -203,6 +209,12 @@ class TestUtils(test.TestCase):
                 (TEST_RET, 'ignored')
             )
 
+        utils.execute(
+            'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+            self.TEST_DEV_PATH, run_as_root=True).AndReturn(
+                (TEST_RET, 'ignored')
+            )
+
         mox.ReplayAll()
 
         self.assertRaises(exception.ImageUnacceptable,
@@ -235,6 +247,12 @@ class TestUtils(test.TestCase):
                 (TEST_RET, 'ignored')
             )
 
+        utils.execute(
+            'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+            self.TEST_DEV_PATH, run_as_root=True).AndReturn(
+                (TEST_RET, 'ignored')
+            )
+
         mox.ReplayAll()
         self.assertRaises(exception.ImageUnacceptable,
                           image_utils.fetch_to_raw,
@@ -265,6 +283,12 @@ class TestUtils(test.TestCase):
                 (TEST_RET, 'ignored')
             )
 
+        utils.execute(
+            'env', 'LC_ALL=C', 'LANG=C', 'qemu-img', 'info',
+            self.TEST_DEV_PATH, run_as_root=True).AndReturn(
+                (TEST_RET, 'ignored')
+            )
+
         utils.execute('qemu-img', 'convert', '-O', 'raw',
                       self.TEST_DEV_PATH, self.TEST_DEV_PATH, run_as_root=True)