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@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 #################################################
oVirt Jenkins CI Server has posted comments on this change.
Change subject: sysprep: implement virt-sysprep functionality ......................................................................
Patch Set 1: Code-Review-1 Verified-1
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/11739/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/12683/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/12528/ : UNSTABLE
oVirt Jenkins CI Server has posted comments on this change.
Change subject: sysprep: implement virt-sysprep functionality ......................................................................
Patch Set 2: Code-Review-1 Verified-1
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/11740/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/12684/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/12529/ : UNSTABLE
oVirt Jenkins CI Server has posted comments on this change.
Change subject: sysprep: implement virt-sysprep functionality ......................................................................
Patch Set 3: Code-Review-1 Verified-1
Build Failed
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/11741/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/12685/ : FAILURE
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/12530/ : UNSTABLE
oVirt Jenkins CI Server has posted comments on this change.
Change subject: sysprep: implement virt-sysprep functionality ......................................................................
Patch Set 4:
Build Successful
http://jenkins.ovirt.org/job/vdsm_master_unit_tests_gerrit_el/11743/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_unit-tests_created/12687/ : SUCCESS
http://jenkins.ovirt.org/job/vdsm_master_pep8_gerrit/12532/ : SUCCESS
vdsm-patches@lists.fedorahosted.org