Change in vdsm[ovirt-3.5]: qemuimg: Create qcow2 compat 0.10 images

nsoffer at redhat.com nsoffer at redhat.com
Wed Sep 17 18:36:12 UTC 2014


Hello Federico Simoncelli, Allon Mureinik,

I'd like you to do a code review.  Please visit

    http://gerrit.ovirt.org/33020

to review the following change.

Change subject: qemuimg: Create qcow2 compat 0.10 images
......................................................................

qemuimg: Create qcow2 compat 0.10 images

Recent qemu versions introduced a new default qcow2 format (1.1), which
is not compatible with older versions of qemu. For example, EL6 host
cannot create snapshots if an image was created on EL7 host.

This patch uses the "compat" option to create images in the older format
(0.10), which are are compatible with different versions of qemu.

The "compat" option is not available on older qemu-img, so we have to
use the "-o ?" option to detect the availability of the "compat" option
before creating an image. This is the same method used by libvirt.

When all supported platforms provide the "compat" option, we can remove
the "compat" detection code. Chanding the compat version will require
a new storage domain format.

Change-Id: Iffd45b394c49e8b12fb7a4cbaa5c7a3519a2cc1c
Bug-Url: https://bugzilla.redhat.com/1139707
Signed-off-by: Nir Soffer <nsoffer at redhat.com>
Reviewed-on: http://gerrit.ovirt.org/32836
Reviewed-by: Allon Mureinik <amureini at redhat.com>
Reviewed-by: Federico Simoncelli <fsimonce at redhat.com>
---
M lib/vdsm/qemuimg.py
M tests/qemuimgTests.py
2 files changed, 86 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/20/33020/1

diff --git a/lib/vdsm/qemuimg.py b/lib/vdsm/qemuimg.py
index 3cdec8d..c36bc26 100644
--- a/lib/vdsm/qemuimg.py
+++ b/lib/vdsm/qemuimg.py
@@ -35,6 +35,12 @@
     RAW = "raw"
     VMDK = "vmdk"
 
+
+# Recent qemu-img supports two incompatible qcow2 versions. We use 0.10 format
+# so hosts with older qemu can consume images created by newer versions.
+# See https://bugzilla.redhat.com/1139707
+QCOW2_COMPAT = '0.10'
+
 __iregex = {
     'format': re.compile("^file format: (?P<value>\w+)$"),
     'virtualsize': re.compile("^virtual size: "
@@ -109,6 +115,8 @@
 
     if format:
         cmd.extend(("-f", format))
+        if format == FORMAT.QCOW2 and _supports_qcow2_compat():
+            cmd.extend(('-o', 'compat=' + QCOW2_COMPAT))
 
     if backing:
         if not os.path.isabs(backing):
@@ -129,6 +137,24 @@
         raise QImgError(rc, out, err)
 
 
+def _supports_qcow2_compat():
+    """
+    TODO: Remove this when qemu versions providing the "compat" option are
+    available on all platforms.
+    """
+    cmd = [_qemuimg.cmd, "create", "-f", FORMAT.QCOW2, "-o", "?", "/dev/null"]
+
+    rc, out, err = utils.execCmd(cmd, raw=True)
+
+    if rc != 0:
+        raise QImgError(rc, out, err)
+
+    # Supported options:
+    # compat           Compatibility level (0.10 or 1.1)
+
+    return '\ncompat ' in out
+
+
 def check(image, format=None):
     cmd = [_qemuimg.cmd, "check"]
 
diff --git a/tests/qemuimgTests.py b/tests/qemuimgTests.py
index 4a35694..ce7cb76 100644
--- a/tests/qemuimgTests.py
+++ b/tests/qemuimgTests.py
@@ -114,3 +114,63 @@
     def testQemu2BackingNoCluster(self):
         info = qemuimg.info('unused')
         self.assertEquals('base.img', info['backingfile'])
+
+
+class FakeExecCmd(object):
+
+    def __init__(self, *calls):
+        self.calls = list(calls)
+        self.saved = None
+
+    def __call__(self, cmd, **kw):
+        call = self.calls.pop(0)
+        return call(cmd, **kw)
+
+    def __enter__(self):
+        self.saved = utils.execCmd
+        utils.execCmd = self
+
+    def __exit__(self, t=None, v=None, tb=None):
+        utils.execCmd = self.saved
+
+
+class QemuimgCreateTests(TestCaseBase):
+
+    def test_no_format(self):
+
+        def create_no_format(cmd, **kw):
+            assert cmd == [qemuimg._qemuimg.cmd, 'create', 'image']
+            return 0, '', ''
+
+        with FakeExecCmd(create_no_format):
+            qemuimg.create('image')
+
+    def test_qcow2_compat_not_supported(self):
+
+        def qcow2_compat_not_supported(cmd, **kw):
+            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2', '-o',
+                           '?', '/dev/null']
+            return 0, 'Supported options:\nsize ...\n', ''
+
+        def create_qcow2_no_compat(cmd, **kw):
+            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2',
+                           'image']
+            return 0, '', ''
+
+        with FakeExecCmd(qcow2_compat_not_supported, create_qcow2_no_compat):
+            qemuimg.create('image', format='qcow2')
+
+    def test_qcow2_compat_supported(self):
+
+        def qcow2_compat_supported(cmd, **kw):
+            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2', '-o',
+                           '?', '/dev/null']
+            return 0, 'Supported options:\ncompat ...\n', ''
+
+        def create_qcow2_compat(cmd, **kw):
+            assert cmd == [qemuimg._qemuimg.cmd, 'create', '-f', 'qcow2', '-o',
+                           'compat=0.10', 'image']
+            return 0, '', ''
+
+        with FakeExecCmd(qcow2_compat_supported, create_qcow2_compat):
+            qemuimg.create('image', format='qcow2')


-- 
To view, visit http://gerrit.ovirt.org/33020
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iffd45b394c49e8b12fb7a4cbaa5c7a3519a2cc1c
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: ovirt-3.5
Gerrit-Owner: Nir Soffer <nsoffer at redhat.com>
Gerrit-Reviewer: Allon Mureinik <amureini at redhat.com>
Gerrit-Reviewer: Federico Simoncelli <fsimonce at redhat.com>


More information about the vdsm-patches mailing list