Beispiel #1
0
    def validateCreateVolumeParams(self, volFormat, srcVolUUID,
                                   preallocate=None):
        """
        Validate create volume parameters
        """
        if volFormat not in volume.VOL_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))

        # Volumes with a parent must be cow
        if srcVolUUID != volume.BLANK_UUID and volFormat != volume.COW_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))

        if preallocate is not None and preallocate not in volume.VOL_TYPE:
            raise se.IncorrectType(volume.type2name(preallocate))
Beispiel #2
0
 def validateCreateVolumeParams(self, volFormat, srcVolUUID,
                                preallocate=None):
     super(BlockStorageDomain, self).validateCreateVolumeParams(
         volFormat, srcVolUUID, preallocate=preallocate)
     # Sparse-Raw not supported for block volumes
     if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
         raise se.IncorrectFormat(volume.type2name(volFormat))
Beispiel #3
0
    def _create(cls,
                dom,
                imgUUID,
                volUUID,
                size,
                volFormat,
                preallocate,
                volParent,
                srcImgUUID,
                srcVolUUID,
                volPath,
                initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """
        if initialSize:
            cls.log.error("initialSize is not supported for file-based "
                          "volumes")
            raise se.InvalidParameterException("initial size", initialSize)

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(
                volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                                 sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS)

        return (volPath, )
Beispiel #4
0
    def validateCreateVolumeParams(self,
                                   volFormat,
                                   srcVolUUID,
                                   preallocate=None):
        """
        Validate create volume parameters
        """
        if volFormat not in volume.VOL_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))

        # Volumes with a parent must be cow
        if srcVolUUID != volume.BLANK_UUID and volFormat != volume.COW_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))

        if preallocate is not None and preallocate not in volume.VOL_TYPE:
            raise se.IncorrectType(volume.type2name(preallocate))
Beispiel #5
0
 def validateCreateVolumeParams(self, volFormat, srcVolUUID,
                                preallocate=None):
     super(BlockStorageDomain, self).validateCreateVolumeParams(
         volFormat, srcVolUUID, preallocate=preallocate)
     # Sparse-Raw not supported for block volumes
     if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
         raise se.IncorrectFormat(volume.type2name(volFormat))
Beispiel #6
0
    def _create(
        cls,
        dom,
        imgUUID,
        volUUID,
        size,
        volFormat,
        preallocate,
        volParent,
        srcImgUUID,
        srcVolUUID,
        volPath,
        initialSize=None,
    ):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """
        if initialSize:
            cls.log.error("initialSize is not supported for file-based " "volumes")
            raise se.InvalidParameterException("initial size", initialSize)

        sizeBytes = size * BLOCK_SIZE
        truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise

        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting, sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size
            )
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        # Forcing the volume permissions in case one of the tools we use
        # (dd, qemu-img, etc.) will mistakenly change the file permissiosn.
        dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS)

        return (volPath,)
Beispiel #7
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        if preallocate == volume.SPARSE_VOL:
            volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb")
        else:
            volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB)

        lvm.createLV(dom.sdUUID,
                     volUUID,
                     volSize,
                     activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, size * BLOCK_SIZE,
                               volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with cls._tagCreateLock:
            mdSlot = dom.getVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS)
            mdTags = [
                "%s%s" % (TAG_PREFIX_MD, mdSlot),
                "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)
            ]
            lvm.changeLVTags(dom.sdUUID,
                             volUUID,
                             delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID,
                         volUUID,
                         exc_info=True)

        return (dom.sdUUID, mdSlot)
Beispiel #8
0
    def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
        """
        Validate create volume parameters.
        'srcVolUUID' - backing volume UUID
        'volFormat' - volume format RAW/QCOW2
        'preallocate' - sparse/preallocate
        """
        volume.Volume.validateCreateVolumeParams(volFormat, preallocate,
                                                 srcVolUUID)

        # Sparse-Raw not supported for block volumes
        if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))
Beispiel #9
0
    def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID):
        """
        Validate create volume parameters.
        'srcVolUUID' - backing volume UUID
        'volFormat' - volume format RAW/QCOW2
        'preallocate' - sparse/preallocate
        """
        volume.Volume.validateCreateVolumeParams(volFormat, preallocate,
                                                 srcVolUUID)

        # Sparse-Raw not supported for block volumes
        if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT:
            raise se.IncorrectFormat(volume.type2name(volFormat))
Beispiel #10
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, imgPath, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        if preallocate == volume.SPARSE_VOL:
            volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb")
        else:
            volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB)

        lvm.createLV(dom.sdUUID, volUUID, volSize, activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", volume.type2name(volFormat), volPath,
                         size)

            if volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, volPath, size, volFormat,
                                    preallocate)
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(imgPath, volUUID, volFormat, preallocate)

        with cls._tagCreateLock:
            mdSlot = dom.mapMetaOffset(volUUID, VOLUME_MDNUMBLKS)
            mdTags = ["%s%s" % (TAG_PREFIX_MD, mdSlot),
                      "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                      "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)]
            lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID, volUUID, exc_info=True)

        return (dom.sdUUID, mdSlot)
Beispiel #11
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, imgPath, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        sizeBytes = int(size) * BLOCK_SIZE

        try:
            oop.getProcessPool(dom.sdUUID).truncateFile(volPath, sizeBytes,
                                                        creatExcl=True)
        except OSError as e:
            if e.errno == errno.EEXIST:
                raise se.VolumeAlreadyExists(volUUID)
            raise
        if preallocate == volume.PREALLOCATED_VOL:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath,
                                 vars.task.aborting, sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", volume.type2name(volFormat), volPath,
                         size)

            if volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, volPath, size, volFormat,
                                    preallocate)
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(imgPath, volUUID, volFormat, preallocate)

        # By definition the volume is a leaf
        cls.file_setrw(volPath, rw=True)

        return (volPath,)
Beispiel #12
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        lvSize = cls._calculate_volume_alloc_size(preallocate,
                                                  size, initialSize)

        lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info("Request to create %s volume %s with size = %s "
                         "sectors", volume.type2name(volFormat), volPath,
                         size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(
                    volPath, size * BLOCK_SIZE, volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with dom.acquireVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS) as slot:
            mdTags = ["%s%s" % (TAG_PREFIX_MD, slot),
                      "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                      "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)]
            lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID, volUUID, exc_info=True)

        return (dom.sdUUID, slot)
Beispiel #13
0
    def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate,
                volParent, srcImgUUID, srcVolUUID, imgPath, volPath):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        sizeBytes = int(size) * BLOCK_SIZE

        if preallocate == volume.SPARSE_VOL:
            # Sparse = regular file
            oop.getProcessPool(dom.sdUUID).truncateFile(volPath, sizeBytes)
        else:
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                                 sizeBytes)
            except ActionStopped:
                raise
            except Exception:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)

            if volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, volPath, size, volFormat,
                                    preallocate)
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(imgPath, volUUID, volFormat, preallocate)

        # By definition the volume is a leaf
        cls.file_setrw(volPath, rw=True)

        return (volPath, )
Beispiel #14
0
    def _create(cls,
                dom,
                imgUUID,
                volUUID,
                size,
                volFormat,
                preallocate,
                volParent,
                srcImgUUID,
                srcVolUUID,
                volPath,
                initialSize=None):
        """
        Class specific implementation of volumeCreate. All the exceptions are
        properly handled and logged in volume.create()
        """

        lvSize = cls._calculate_volume_alloc_size(preallocate, size,
                                                  initialSize)

        lvm.createLV(dom.sdUUID,
                     volUUID,
                     "%s" % lvSize,
                     activate=True,
                     initialTag=TAG_VOL_UNINIT)

        utils.rmFile(volPath)
        os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath)

        if not volParent:
            cls.log.info(
                "Request to create %s volume %s with size = %s "
                "sectors", volume.type2name(volFormat), volPath, size)
            if volFormat == volume.COW_FORMAT:
                qemuimg.create(volPath, size * BLOCK_SIZE,
                               volume.fmt2str(volFormat))
        else:
            # Create hardlink to template and its meta file
            cls.log.info("Request to create snapshot %s/%s of volume %s/%s",
                         imgUUID, volUUID, srcImgUUID, srcVolUUID)
            volParent.clone(volPath, volFormat)

        with dom.acquireVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS) as slot:
            mdTags = [
                "%s%s" % (TAG_PREFIX_MD, slot),
                "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID),
                "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)
            ]
            lvm.changeLVTags(dom.sdUUID,
                             volUUID,
                             delTags=[TAG_VOL_UNINIT],
                             addTags=mdTags)

        try:
            lvm.deactivateLVs(dom.sdUUID, volUUID)
        except se.CannotDeactivateLogicalVolume:
            cls.log.warn("Cannot deactivate new created volume %s/%s",
                         dom.sdUUID,
                         volUUID,
                         exc_info=True)

        return (dom.sdUUID, slot)
Beispiel #15
0
            os.symlink(lvm.lvPath(sdUUID, volUUID), vol_path)
        except se.StorageException:
            cls.log.error("Unexpected error", exc_info=True)
            raise
        except Exception, e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCreationError("blockVolume create/link lv %s failed: %s" % (volUUID, str(e)))

        # By definition volume is now a leaf and should be writeable.
        # Default permission for lvcreate is read and write. No need to set permission.

        try:
            cls.log.info("blockVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID))
            if not pvol:
                cls.log.info(
                    "Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size
                )
                # Create 'raw' volume via qemu-img actually redundant
                if volFormat == volume.COW_FORMAT:
                    volume.createVolume(None, None, vol_path, size, volFormat, preallocate)
            else:
                ## Create hardlink to template and its meta file
                cls.log.info(
                    "Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID
                )
                pvol.clone(imageDir, volUUID, volFormat, preallocate)
        except Exception:
            cls.log.error("Unexpected error", exc_info=True)
            raise

        try:
Beispiel #16
0
            try:
                # ddWatchCopy expects size to be in bytes
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting, (int(size) * 512))
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
        else:
            # Sparse = Normal file
            oop.getProcessPool(sdUUID).createSparseFile(vol_path, 0)

        cls.log.info("fileVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID))
        if not pvol:
            cls.log.info("Request to create %s volume %s with size = %s sectors",
                     volume.type2name(volFormat), vol_path, size)
            # Create preallocate/raw volume via qemu-img actually redundant
            if preallocate == volume.SPARSE_VOL or volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, vol_path, size, volFormat, preallocate)
        else:
            # Create hardlink to template and its meta file
            if imgUUID != srcImgUUID:
                pvol.share(imageDir, hard=True)
                # Make clone to link the new volume against the local shared volume
                pvol = FileVolume(repoPath, sdUUID, imgUUID, srcVolUUID)
            pvol.clone(imageDir, volUUID, volFormat, preallocate)
            size = pvol.getMetaParam(volume.SIZE)

        try:
            vars.task.pushRecovery(task.Recovery("create file volume metadata rollback", "fileVolume", "FileVolume", "createVolumeMetadataRollback",
                                                 [vol_path]))
Beispiel #17
0
                os.unlink(vol_path)
            os.symlink(lvm.lvPath(sdUUID, volUUID), vol_path)
        except se.StorageException:
            cls.log.error("Unexpected error", exc_info=True)
            raise
        except Exception, e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCreationError("blockVolume create/link lv %s failed: %s" % (volUUID, str(e)))

        # By definition volume is now a leaf and should be writeable.
        # Default permission for lvcreate is read and write. No need to set permission.

        try:
            cls.log.info("blockVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID))
            if not pvol:
                cls.log.info("Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size)
                # Create 'raw' volume via qemu-img actually redundant
                if volFormat == volume.COW_FORMAT:
                    volume.createVolume(None, None, vol_path, size, volFormat, preallocate)
            else:
                ## Create hardlink to template and its meta file
                cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID)
                pvol.clone(imageDir, volUUID, volFormat, preallocate)
        except Exception:
            cls.log.error("Unexpected error", exc_info=True)
            raise

        try:
            with cls._tagCreateLock:
                offs = mysd.mapMetaOffset(volUUID, VOLUME_MDNUMBLKS)
                lvm.addLVTags(sdUUID, volUUID, ("%s%s" % (TAG_PREFIX_MD, offs),
Beispiel #18
0
                                 (int(size) * 512))
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                cls.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
        else:
            # Sparse = Normal file
            oop.getProcessPool(sdUUID).createSparseFile(vol_path, 0)

        cls.log.info("fileVolume: create: volUUID %s srcImg %s srvVol %s" %
                     (volUUID, srcImgUUID, srcVolUUID))
        if not pvol:
            cls.log.info(
                "Request to create %s volume %s with size = %s sectors",
                volume.type2name(volFormat), vol_path, size)
            # Create preallocate/raw volume via qemu-img actually redundant
            if preallocate == volume.SPARSE_VOL or volFormat == volume.COW_FORMAT:
                volume.createVolume(None, None, vol_path, size, volFormat,
                                    preallocate)
        else:
            # Create hardlink to template and its meta file
            if imgUUID != srcImgUUID:
                pvol.share(imageDir, hard=True)
                # Make clone to link the new volume against the local shared volume
                pvol = FileVolume(repoPath, sdUUID, imgUUID, srcVolUUID)
            pvol.clone(imageDir, volUUID, volFormat, preallocate)
            size = pvol.getMetaParam(volume.SIZE)

        try:
            vars.task.pushRecovery(
Beispiel #19
0
    def copy(self, sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID,
             dstVolUUID, descr, dstSdUUID, volType, volFormat, preallocate,
             postZero, force):
        """
        Create new template/volume from VM.
        Do it by collapse and copy the whole chain (baseVolUUID->srcVolUUID)
        """
        self.log.info("sdUUID=%s vmUUID=%s srcImgUUID=%s srcVolUUID=%s "
                      "dstImgUUID=%s dstVolUUID=%s dstSdUUID=%s volType=%s "
                      "volFormat=%s preallocate=%s force=%s postZero=%s",
                      sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID,
                      dstVolUUID, dstSdUUID, volType,
                      volume.type2name(volFormat),
                      volume.type2name(preallocate), str(force), str(postZero))
        try:
            srcVol = dstVol = None

            # Find out dest sdUUID
            if dstSdUUID == sd.BLANK_UUID:
                dstSdUUID = sdUUID
            volclass = sdCache.produce(sdUUID).getVolumeClass()
            destDom = sdCache.produce(dstSdUUID)

            # find src volume
            try:
                srcVol = volclass(self.repoPath, sdUUID, srcImgUUID,
                                  srcVolUUID)
            except se.StorageException:
                raise
            except Exception as e:
                self.log.error(e, exc_info=True)
                raise se.SourceImageActionError(srcImgUUID, sdUUID, str(e))

            # Create dst volume
            try:
                # find out src volume parameters
                volParams = srcVol.getVolumeParams()

                if volParams['parent'] and \
                        volParams['parent'] != volume.BLANK_UUID:
                    # Volume has parent and therefore is a part of a chain
                    # in that case we can not know what is the exact size of
                    # the space target file (chain ==> cow ==> sparse).
                    # Therefore compute an estimate of the target volume size
                    # using the sum of the actual size of the chain's volumes
                    if volParams['volFormat'] != volume.COW_FORMAT or \
                            volParams['prealloc'] != volume.SPARSE_VOL:
                        raise se.IncorrectFormat(self)
                    volParams['apparentsize'] = self.__chainSizeCalc(
                        sdUUID, srcImgUUID, srcVolUUID, volParams['size'])

                # Find out dest volume parameters
                if preallocate in [volume.PREALLOCATED_VOL, volume.SPARSE_VOL]:
                    volParams['prealloc'] = preallocate
                if volFormat in [volume.COW_FORMAT, volume.RAW_FORMAT]:
                    dstVolFormat = volFormat
                else:
                    dstVolFormat = volParams['volFormat']

                self.log.info("copy source %s:%s:%s vol size %s destination "
                              "%s:%s:%s apparentsize %s" %
                              (sdUUID, srcImgUUID, srcVolUUID,
                               volParams['size'], dstSdUUID, dstImgUUID,
                               dstVolUUID, volParams['apparentsize']))

                # If image already exists check whether it illegal/fake,
                # overwrite it
                if not self.isLegal(dstSdUUID, dstImgUUID):
                    force = True

                # We must first remove the previous instance of image (if
                # exists) in destination domain, if we got the overwrite
                # command
                if force:
                    self.log.info("delete image %s on domain %s before "
                                  "overwriting", dstImgUUID, dstSdUUID)
                    _deleteImage(destDom, dstImgUUID, postZero)

                # To avoid 'prezeroing' preallocated volume on NFS domain,
                # we create the target volume with minimal size and after that
                # we'll change its metadata back to the original size.
                tmpSize = TEMPORARY_VOLUME_SIZE  # in sectors (10M)
                destDom.createVolume(
                    imgUUID=dstImgUUID, size=tmpSize, volFormat=dstVolFormat,
                    preallocate=volParams['prealloc'],
                    diskType=volParams['disktype'], volUUID=dstVolUUID,
                    desc=descr, srcImgUUID=volume.BLANK_UUID,
                    srcVolUUID=volume.BLANK_UUID)

                dstVol = sdCache.produce(dstSdUUID).produceVolume(
                    imgUUID=dstImgUUID, volUUID=dstVolUUID)
                # For convert to 'raw' we need use the virtual disk size
                # instead of apparent size
                if dstVolFormat == volume.RAW_FORMAT:
                    newsize = volParams['size']
                else:
                    newsize = volParams['apparentsize']
                dstVol.extend(newsize)
                dstPath = dstVol.getVolumePath()
                # Change destination volume metadata back to the original size.
                dstVol.setSize(volParams['size'])
            except se.StorageException:
                self.log.error("Unexpected error", exc_info=True)
                raise
            except Exception as e:
                self.log.error("Unexpected error", exc_info=True)
                raise se.CopyImageError("Destination volume %s error: %s" %
                                        (dstVolUUID, str(e)))

            try:
                # Start the actual copy image procedure
                srcVol.prepare(rw=False)
                dstVol.prepare(rw=True, setrw=True)

                try:
                    (rc, out, err) = volume.qemuConvert(
                        volParams['path'], dstPath, volParams['volFormat'],
                        dstVolFormat, vars.task.aborting,
                        size=srcVol.getVolumeSize(bs=1),
                        dstvolType=dstVol.getType())
                    if rc:
                        raise se.StorageException("rc: %s, err: %s" %
                                                  (rc, err))
                except ActionStopped:
                    raise
                except se.StorageException as e:
                    raise se.CopyImageError(str(e))

                # Mark volume as SHARED
                if volType == volume.SHARED_VOL:
                    dstVol.setShared()

                dstVol.setLegality(volume.LEGAL_VOL)

                if force:
                    # Now we should re-link all deleted hardlinks, if exists
                    destDom.templateRelink(dstImgUUID, dstVolUUID)
            except se.StorageException:
                self.log.error("Unexpected error", exc_info=True)
                raise
            except Exception as e:
                self.log.error("Unexpected error", exc_info=True)
                raise se.CopyImageError("src image=%s, dst image=%s: msg=%s" %
                                        (srcImgUUID, dstImgUUID, str(e)))

            self.log.info("Finished copying %s:%s -> %s:%s", sdUUID,
                          srcVolUUID, dstSdUUID, dstVolUUID)
            #TODO: handle return status
            return dstVolUUID
        finally:
            self.__cleanupCopy(srcVol=srcVol, dstVol=dstVol)