Change in vdsm[master]: sysprep: implement virt-sysprep functionality

mpolednik at redhat.com mpolednik at redhat.com
Tue Sep 30 14:01:17 UTC 2014


Martin Polednik has uploaded a new change for review.

Change subject: sysprep: implement virt-sysprep functionality
......................................................................

sysprep: implement virt-sysprep functionality

Virt-sysprep is a utility to mount qcow2/raw images and remove
host specific data on them. This patch allows virt-sysprep to be called
from within VDSM via sysprepImage verb.

Change-Id: I6815e101bd1f037bf21c9233b18e86f3667cce6e
Signed-off-by: Martin Polednik <mpolednik at redhat.com>
---
M client/vdsClient.py
M lib/vdsm/guestfs.py
M vdsm/API.py
M vdsm/rpc/BindingXMLRPC.py
M vdsm/storage/hsm.py
M vdsm/storage/image.py
M vdsm/storage/sp.py
M vdsm/storage/storage_exception.py
8 files changed, 82 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/45/33545/1

diff --git a/client/vdsClient.py b/client/vdsClient.py
index dafca9e..c52132e 100644
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -1370,6 +1370,13 @@
             return status['status']['code'], status['status']['message']
         return 0, status['uuid']
 
+    def sysprepImage(self, args):
+        (spUUID, sdUUID, imgUUID) = args
+        status = self.s.sysprepImage(spUUID, sdUUID, imgUUID)
+        if status['status']['code']:
+            return status['status']['code'], status['status']['message']
+        return 0, status['uuid']
+
     def cloneImageStructure(self, args):
         spUUID, sdUUID, imgUUID, dstSdUUID = args
         image = self.s.cloneImageStructure(spUUID, sdUUID, imgUUID, dstSdUUID)
@@ -2533,6 +2540,11 @@
                            'free space on image to free space on storage '
                            'domain using virt-sparsify'
                            )),
+        'sysprepImage': (serv.sysprepImage,
+                         ('<spUUID> <sdUUID> <imgUUID>'
+                          'Erase host specific data from image using '
+                          'virt-sparsify'
+                          )),
         'cloneImageStructure': (serv.cloneImageStructure,
                                 ('<spUUID> <sdUUID> <imgUUID> <dstSdUUID>',
                                  'Clone an image structure from a source '
diff --git a/lib/vdsm/guestfs.py b/lib/vdsm/guestfs.py
index dd1cfdd..0c5b361 100644
--- a/lib/vdsm/guestfs.py
+++ b/lib/vdsm/guestfs.py
@@ -25,6 +25,8 @@
 # Fedora, EL6
 _VIRTSPARSIFY = utils.CommandPath("virt-sparsify",
                                   "/usr/bin/virt-sparsify",)
+_VIRTSYSPREP = utils.CommandPath("virt-sysprep",
+                                 "/usr/bin/virt-sysprep",)
 
 
 class Error(Exception):
@@ -61,3 +63,21 @@
 
     if rc != 0:
         raise Error(rc, err)
+
+
+def sysprep(volume, vol_format=None):
+    """
+    Sysprep the 'src_vol' volume (src_format) using libguestfs virt-sysprep
+
+    volume: path of base volume
+    format: format of base volume ('raw' or `qcow2')
+    """
+    cmd = [_VIRTSPARSIFY.cmd, '-a ' + volume]
+
+    if vol_format:
+        cmd.extend(("--format", vol_format))
+
+    rc, _, err = utils.execCmd(cmd, deathSignal=signal.SIGKILL)
+
+    if rc != 0:
+        raise Error(rc, err)
diff --git a/vdsm/API.py b/vdsm/API.py
index a1129b3..767cba2 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -870,6 +870,10 @@
                                        tmpVolUUID, dstSdUUID, dstImgUUID,
                                        dstVolUUID)
 
+    def sysprep(self, volUUID):
+        return self._irs.sysprepImage(self._spUUID, self._sdUUID, self._UUID,
+                                       volUUID)
+
     def cloneStructure(self, dstSdUUID):
         return self._irs.cloneImageStructure(self._spUUID, self._sdUUID,
                                              self._UUID, dstSdUUID)
diff --git a/vdsm/rpc/BindingXMLRPC.py b/vdsm/rpc/BindingXMLRPC.py
index f2dcbdf..df0c899 100644
--- a/vdsm/rpc/BindingXMLRPC.py
+++ b/vdsm/rpc/BindingXMLRPC.py
@@ -690,6 +690,10 @@
         image = API.Image(imgUUID, spUUID, sdUUID)
         return image.sparsify(tmpVolUUID, dstSdUUID, dstImgUUID, dstVolUUID)
 
+    def imageSysprep(self, spUUID, sdUUID, imgUUID):
+        image = API.Image(imgUUID, spUUID, sdUUID)
+        return image.sparsify(imgUUID)
+
     def imageCloneStructure(self, spUUID, sdUUID, imgUUID, dstSdUUID):
         image = API.Image(imgUUID, spUUID, sdUUID)
         return image.cloneStructure(dstSdUUID)
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index cde80ff..a5e8e6f 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -1638,6 +1638,20 @@
                           dstImgUUID, dstVolUUID)
 
     @public
+    def sysprepImage(self, spUUID, sdUUID, imgUUID, volUUID):
+        """
+        Reduce sparse image size by converting free space on image to free
+        space on storage domain using virt-sparsify.
+        """
+
+        pool = self.getPool(spUUID)
+
+        vars.task.getSharedLock(STORAGE, sdUUID)
+
+        self._spmSchedule(spUUID, "sysprepImage", pool.sparsifyImage,
+                          sdUUID, imgUUID, volUUID)
+
+    @public
     def cloneImageStructure(self, spUUID, sdUUID, imgUUID, dstSdUUID):
         """
         Clone an image structure (volume chain) to a destination domain within
diff --git a/vdsm/storage/image.py b/vdsm/storage/image.py
index 974ba66..d337341 100644
--- a/vdsm/storage/image.py
+++ b/vdsm/storage/image.py
@@ -591,6 +591,26 @@
         tmpVolume.shrinkToOptimalSize()
         dstVolume.shrinkToOptimalSize()
 
+    def sysprep(self, sdUUID, imgUUID, volUUID):
+        """
+        Erase host-specific data from image using libguestfs virt-sysprep
+        """
+        self.log.info("dstSdUUID=%s, dstImgUUID=%s, dstVolUUID=%s",
+                      sdUUID, imgUUID, volUUID)
+
+        volume = self._getSparsifyVolume(sdUUID, imgUUID, volUUID)
+
+        volume.prepare()
+        try:
+            volume_format = volume.fmt2str(volume.getFormat())
+
+            guestfs.sysprep(volume.getVolumePath(), vol_format=volume_format)
+        except Exception:
+            self.log.exception('Unexpected error sysprepping %s', volUUID)
+            raise se.CannotSysprepVolume(volUUID)
+        finally:
+            volume.teardown(sdUUID=sdUUID, volUUID=volUUID)
+
     def cloneStructure(self, sdUUID, imgUUID, dstSdUUID):
         self._createTargetImage(sdCache.produce(dstSdUUID), sdUUID, imgUUID)
 
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index 34a8fbf..65f9238 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -1588,6 +1588,9 @@
                 tmpSdUUID, tmpImgUUID, tmpVolUUID, dstSdUUID, dstImgUUID,
                 dstVolUUID)
 
+    def sysprepImage(self):
+        pass
+
     def cloneImageStructure(self, sdUUID, imgUUID, dstSdUUID):
         """
         Clone an image structure from a source domain to a destination domain
diff --git a/vdsm/storage/storage_exception.py b/vdsm/storage/storage_exception.py
index 4e2e2e0..8da1d2c 100644
--- a/vdsm/storage/storage_exception.py
+++ b/vdsm/storage/storage_exception.py
@@ -339,6 +339,11 @@
     message = "Cannot sparsify volume"
 
 
+class CannotSysprepVolume(StorageException):
+    code = 235
+    message = "Cannot sysprep volume"
+
+
 #################################################
 #  Images Exceptions
 #################################################


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6815e101bd1f037bf21c9233b18e86f3667cce6e
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Martin Polednik <mpolednik at redhat.com>


More information about the vdsm-patches mailing list