Esempio n. 1
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, )
Esempio n. 2
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True, rw=True, chainrw=force, setrw=True, force=True)
            try:
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting, int(size),
                                 recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
Esempio n. 3
0
def _postZero(sdUUID, volumes):
    # Assumed that there is no any thread that can deactivate these LVs
    # on this host or change the rw permission on this or any other host.

    lvNames = tuple(vol.volUUID for vol in volumes)
    # Assert volumes are writable. (Don't do this at home.)
    try:
        lvm.changelv(sdUUID, lvNames, ("--permission", "rw"))
    except se.StorageException:
        # Hope this only means that some volumes were already writable.
        pass

    lvm.activateLVs(sdUUID, lvNames)

    for lv in lvm.getLV(sdUUID):
        if lv.name in lvNames:
            # wipe out the whole volume
            try:
                misc.ddWatchCopy(
                    "/dev/zero", lvm.lvPath(sdUUID, lv.name),
                    vars.task.aborting, int(lv.size),
                    recoveryCallback=volume.baseAsyncTasksRollback)
            except utils.ActionStopped:
                raise
            except Exception:
                raise se.VolumesZeroingError(lv.name)
Esempio n. 4
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,)
Esempio n. 5
0
    def create(cls, repoPath, sdUUID, imgUUID, size, volFormat, preallocate,
               diskType, volUUID, desc, srcImgUUID, srcVolUUID):
        """
        Create a new volume with given size or snapshot
            'size' - in sectors
            'volFormat' - volume format COW / RAW
            'preallocate' - Prealocate / Sparse
            'diskType' - string that describes disk type System|Data|Shared|Swap|Temp
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
        """
        if not volUUID:
            volUUID = str(uuid.uuid4())
        if volUUID == volume.BLANK_UUID:
            raise se.InvalidParameterException("volUUID", volUUID)

        # Validate volume parameters should be checked here for all
        # internal flows using volume creation.
        cls.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)

        imageDir = image.Image(repoPath).create(sdUUID, imgUUID)
        vol_path = os.path.join(imageDir, volUUID)
        voltype = "LEAF"
        pvol = None
        # Check if volume already exists
        if oop.getProcessPool(sdUUID).fileUtils.pathExists(vol_path):
            raise se.VolumeAlreadyExists(vol_path)
        # Check if snapshot creation required
        if srcVolUUID != volume.BLANK_UUID:
            if srcImgUUID == volume.BLANK_UUID:
                srcImgUUID = imgUUID
            pvol = FileVolume(repoPath, sdUUID, srcImgUUID, srcVolUUID)
            # Cannot create snapshot for ILLEGAL volume
            if not pvol.isLegal():
                raise se.createIllegalVolumeSnapshotError(pvol.volUUID)

        # create volume rollback
        vars.task.pushRecovery(
            task.Recovery("halfbaked volume rollback", "fileVolume",
                          "FileVolume", "halfbakedVolumeRollback", [vol_path]))
        if preallocate == volume.PREALLOCATED_VOL:
            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)
Esempio n. 6
0
    def create(cls, repoPath, sdUUID, imgUUID, size, volFormat, preallocate, diskType, volUUID, desc, srcImgUUID, srcVolUUID):
        """
        Create a new volume with given size or snapshot
            'size' - in sectors
            'volFormat' - volume format COW / RAW
            'preallocate' - Prealocate / Sparse
            'diskType' - string that describes disk type System|Data|Shared|Swap|Temp
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
        """
        if not volUUID:
            volUUID = str(uuid.uuid4())
        if volUUID == volume.BLANK_UUID:
            raise se.InvalidParameterException("volUUID", volUUID)

        # Validate volume parameters should be checked here for all
        # internal flows using volume creation.
        cls.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)

        imageDir = image.Image(repoPath).create(sdUUID, imgUUID)
        vol_path = os.path.join(imageDir, volUUID)
        voltype = "LEAF"
        pvol = None
        # Check if volume already exists
        if oop.getProcessPool(sdUUID).fileUtils.pathExists(vol_path):
            raise se.VolumeAlreadyExists(vol_path)
        # Check if snapshot creation required
        if srcVolUUID != volume.BLANK_UUID:
            if srcImgUUID == volume.BLANK_UUID:
                srcImgUUID = imgUUID
            pvol = FileVolume(repoPath, sdUUID, srcImgUUID, srcVolUUID)
            # Cannot create snapshot for ILLEGAL volume
            if not pvol.isLegal():
                raise se.createIllegalVolumeSnapshotError(pvol.volUUID)

        # Rollback sentinel, just to mark the start of the task
        vars.task.pushRecovery(task.Recovery(task.ROLLBACK_SENTINEL, "fileVolume", "FileVolume", "startCreateVolumeRollback",
                                             [sdUUID, imgUUID, volUUID]))
        # create volume rollback
        vars.task.pushRecovery(task.Recovery("halfbaked volume rollback", "fileVolume", "FileVolume", "halfbakedVolumeRollback",
                                             [vol_path]))
        if preallocate == volume.PREALLOCATED_VOL:
            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)
Esempio n. 7
0
def qemuConvert(src, dst, src_fmt, dst_fmt, stop, size, dstvolType):
    """
    Convert the 'src' image (or chain of images) into a new single 'dst'
    """
    src_fmt = fmt2str(src_fmt)
    dst_fmt = fmt2str(dst_fmt)
    log.debug('(qemuConvert): COPY %s (%s) to %s (%s) START' %
              (src, src_fmt, dst, dst_fmt))

    if (src_fmt == "raw" and dst_fmt == "raw" and
            dstvolType == PREALLOCATED_VOL):
        (rc, out, err) = misc.ddWatchCopy(
            src=src, dst=dst,
            stop=stop, size=size,
            recoveryCallback=baseAsyncTasksRollback)
    else:
        cmd = [constants.EXT_QEMUIMG, "convert",
               "-t", "none", "-f", src_fmt, src,
               "-O", dst_fmt, dst]
        (rc, out, err) = misc.watchCmd(cmd, stop=stop,
                                       recoveryCallback=baseAsyncTasksRollback,
                                       ioclass=utils.IOCLASS.IDLE,
                                       nice=utils.NICENESS.HIGH)

    log.debug('(qemuConvert): COPY %s to %s DONE' % (src, dst))
    return (rc, out, err)
Esempio n. 8
0
def qemuConvert(src, dst, src_fmt, dst_fmt, stop, size, dstvolType):
    """
    Convert the 'src' image (or chain of images) into a new single 'dst'
    """
    src_fmt = fmt2str(src_fmt)
    dst_fmt = fmt2str(dst_fmt)
    log.debug('(qemuConvert): COPY %s (%s) to %s (%s) START' %
              (src, src_fmt, dst, dst_fmt))

    if (src_fmt == "raw" and dst_fmt == "raw" and
            dstvolType == PREALLOCATED_VOL):
        (rc, out, err) = misc.ddWatchCopy(
            src=src, dst=dst,
            stop=stop, size=size,
            recoveryCallback=baseAsyncTasksRollback)
    else:
        cmd = [constants.EXT_QEMUIMG, "convert",
               "-t", "none", "-f", src_fmt, src,
               "-O", dst_fmt, dst]
        (rc, out, err) = misc.watchCmd(cmd, stop=stop,
                                       recoveryCallback=baseAsyncTasksRollback,
                                       ioclass=utils.IOCLASS.IDLE,
                                       nice=utils.NICENESS.HIGH)

    log.debug('(qemuConvert): COPY %s to %s DONE' % (src, dst))
    return (rc, out, err)
Esempio n. 9
0
    def _interImagesCopy(self, destDom, srcSdUUID, imgUUID, chains):
        srcLeafVol = chains['srcChain'][-1]
        dstLeafVol = chains['dstChain'][-1]
        try:
            # Prepare the whole chains before the copy
            srcLeafVol.prepare(rw=False)
            dstLeafVol.prepare(rw=True, chainrw=True, setrw=True)
        except Exception:
            self.log.error("Unexpected error", exc_info=True)
            # teardown volumes
            self.__cleanupMove(srcLeafVol, dstLeafVol)
            raise

        try:
            for srcVol in chains['srcChain']:
                # Do the actual copy
                try:
                    dstVol = destDom.produceVolume(imgUUID=imgUUID,
                                                   volUUID=srcVol.volUUID)
                    srcFmt = srcVol.getFormat()
                    if srcFmt == volume.RAW_FORMAT:
                        srcFmtStr = volume.fmt2str(srcFmt)
                        dstFmtStr = volume.fmt2str(dstVol.getFormat())
                        self.log.debug("start qemu convert")
                        qemuImg.convert(srcVol.getVolumePath(),
                                        dstVol.getVolumePath(),
                                        vars.task.aborting,
                                        srcFmtStr, dstFmtStr)
                    else:
                        srcSize = srcVol.getVolumeSize(bs=1)
                        misc.ddWatchCopy(srcVol.getVolumePath(),
                                         dstVol.getVolumePath(),
                                         vars.task.aborting,
                                         size=srcSize)
                except ActionStopped:
                    raise
                except se.StorageException:
                    self.log.error("Unexpected error", exc_info=True)
                    raise
                except Exception:
                    self.log.error("Copy image error: image=%s, src domain=%s,"
                                   " dst domain=%s", imgUUID, srcSdUUID,
                                   destDom.sdUUID, exc_info=True)
                    raise se.CopyImageError()
        finally:
            # teardown volumes
            self.__cleanupMove(srcLeafVol, dstLeafVol)
Esempio n. 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()
        """

        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,)
Esempio n. 11
0
    def _extendSizeRaw(self, newSize):
        volPath = self.getVolumePath()
        curSizeBytes = self.oop.os.stat(volPath).st_size
        newSizeBytes = newSize * BLOCK_SIZE

        # No real sanity checks here, they should be included in the calling
        # function/method. We just validate the sizes to be consistent since
        # they're computed and used in the pre-allocated case.
        if (newSizeBytes <= curSizeBytes):
            raise se.VolumeResizeValueError(newSize)

        if self.getVolType() == volume.PREALLOCATED_VOL:
            # for pre-allocated we need to zero to the file size
            misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                             newSizeBytes - curSizeBytes, curSizeBytes)
        else:
            # for sparse files we can just truncate to the correct size
            self.oop.truncateFile(volPath, newSizeBytes)
Esempio n. 12
0
    def _extendSizeRaw(self, newSize):
        volPath = self.getVolumePath()
        curSizeBytes = self.oop.os.stat(volPath).st_size
        newSizeBytes = newSize * BLOCK_SIZE

        # No real sanity checks here, they should be included in the calling
        # function/method. We just validate the sizes to be consistent since
        # they're computed and used in the pre-allocated case.
        if (newSizeBytes <= curSizeBytes):
            raise se.VolumeResizeValueError(newSize)

        if self.getVolType() == volume.PREALLOCATED_VOL:
            # for pre-allocated we need to zero to the file size
            misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting,
                             newSizeBytes - curSizeBytes, curSizeBytes)
        else:
            # for sparse files we can just truncate to the correct size
            self.oop.truncateFile(volPath, newSizeBytes)
Esempio n. 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, )
Esempio n. 14
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy(
                    "/dev/zero",
                    vol_path,
                    vars.task.aborting,
                    int(size),
                    recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
Esempio n. 15
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        # On block storage domains we store a volume's parent UUID in two
        # places: 1) in the domain's metadata LV, and 2) in a LV tag attached
        # to the volume LV itself.  The LV tag is more efficient to access
        # than the domain metadata but it may only be updated by the SPM.
        #
        # This means that after a live merge completes the domain metadata LV
        # will be updated but the LV tag will not.  We can detect this case
        # here and fix the LV tag since this is an SPM verb.
        #
        # File domains do not have this complexity because the metadata is
        # stored in only one place and that metadata is updated by the HSM
        # host when the live merge finishes.
        sync = False
        for childID in self.getChildren():
            child = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                childID)
            metaParent = child.getParentMeta()
            tagParent = child.getParentTag()
            if metaParent != tagParent:
                self.log.debug(
                    "Updating stale PUUID LV tag from %s to %s for "
                    "volume %s", tagParent, metaParent, child.volUUID)
                child.setParentTag(metaParent)
                sync = True
        if sync:
            self.recheckIfLeaf()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting,
                                 int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s",
                             puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s",
                           self.sdUUID,
                           self.volUUID,
                           exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID,
                           self.volUUID,
                           vol_path,
                           exc_info=True)

        raise eFound
Esempio n. 16
0
    #To activate all the volumes of an image at once get its resource.
    #See http://gerrit.usersys.redhat.com/771
    #Assert volumes are writable. (Don't do this at home.)
    lvNames = (vol.volUUID for vol in volumes)
    try:
        lvm.changelv(sdUUID, lvNames, "--permission", "rw")
    except se.StorageException, e:
        #Hope this only means that some volumes were already writable
        pass
    for lv in lvm.getLV(sdUUID):
        if lv.name in lvNames:
            # wipe out the whole volume
            try:
                misc.ddWatchCopy(
                    "/dev/zero",
                    lvm.lvPath(sdUUID, lv.name),
                    vars.task.aborting,
                    int(lv.size),
                    recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                raise se.VolumesZeroingError(lv.name)


def deleteMultipleVolumes(sdUUID, volumes, postZero):
    "Delete multiple volumes (LVs) in the same domain (VG)." ""
    if postZero:
        _postZero(sdUUID, volumes)
    lvNames = [vol.volUUID for vol in volumes]
    lvm.removeLVs(sdUUID, lvNames)
Esempio n. 17
0
def _postZero(sdUUID, volumes):
    #Assumed here that the volume is active.
    #To activate all the volumes of an image at once get its resource.
    #See http://gerrit.usersys.redhat.com/771
    #Assert volumes are writable. (Don't do this at home.)
    lvNames = (vol.volUUID for vol in volumes)
    try:
        lvm.changelv(sdUUID, lvNames, "--permission", "rw")
    except se.StorageException, e:
        #Hope this only means that some volumes were already writable
        pass
    for lv in lvm.getLV(sdUUID):
        if lv.name in lvNames:
        # wipe out the whole volume
            try:
                misc.ddWatchCopy("/dev/zero", lvm.lvPath(sdUUID, lv.name), vars.task.aborting, int(lv.size),
                                 recoveryCallback=volume.baseAsyncTasksRollback)
            except se.ActionStopped, e:
                raise e
            except Exception, e:
                raise se.VolumesZeroingError(lv.name)

def deleteMultipleVolumes(sdUUID, volumes, postZero):
    "Delete multiple volumes (LVs) in the same domain (VG)."""
    if postZero:
        _postZero(sdUUID, volumes)
    lvNames = [vol.volUUID for vol in volumes]
    lvm.removeLVs(sdUUID, lvNames)

Esempio n. 18
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True, rw=True, chainrw=force, setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy(
                    "/dev/zero", vol_path, vars.task.aborting, int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s", puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s", self.sdUUID,
                           self.volUUID, exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID, self.volUUID, vol_path, exc_info=True)

        raise eFound
Esempio n. 19
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        # On block storage domains we store a volume's parent UUID in two
        # places: 1) in the domain's metadata LV, and 2) in a LV tag attached
        # to the volume LV itself.  The LV tag is more efficient to access
        # than the domain metadata but it may only be updated by the SPM.
        #
        # This means that after a live merge completes the domain metadata LV
        # will be updated but the LV tag will not.  We can detect this case
        # here and fix the LV tag since this is an SPM verb.
        #
        # File domains do not have this complexity because the metadata is
        # stored in only one place and that metadata is updated by the HSM
        # host when the live merge finishes.
        sync = False
        for childID in self.getChildren():
            child = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                childID)
            metaParent = child.getParentMeta()
            tagParent = child.getParentTag()
            if metaParent != tagParent:
                self.log.debug("Updating stale PUUID LV tag from %s to %s for "
                               "volume %s", tagParent, metaParent,
                               child.volUUID)
                child.setParentTag(metaParent)
                sync = True
        if sync:
            self.recheckIfLeaf()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True, rw=True, chainrw=force, setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy(
                    "/dev/zero", vol_path, vars.task.aborting, int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s", puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s", self.sdUUID,
                           self.volUUID, exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID, self.volUUID, vol_path, exc_info=True)

        raise eFound
Esempio n. 20
0
    def delete(self, postZero, force):
        """ Delete volume
            'postZero' - zeroing file before deletion
            'force' is required to remove shared and internal volumes
        """
        self.log.info("Request to delete LV %s of image %s in VG %s ",
                      self.volUUID, self.imgUUID, self.sdUUID)

        vol_path = self.getVolumePath()
        size = self.getVolumeSize(bs=1)
        offs = self.getMetaOffset()

        if not force:
            self.validateDelete()

        # Mark volume as illegal before deleting
        self.setLegality(volume.ILLEGAL_VOL)

        if postZero:
            self.prepare(justme=True,
                         rw=True,
                         chainrw=force,
                         setrw=True,
                         force=True)
            try:
                misc.ddWatchCopy("/dev/zero", vol_path, vars.task.aborting,
                                 int(size))
            except utils.ActionStopped:
                raise
            except Exception:
                self.log.error("Unexpected error", exc_info=True)
                raise se.VolumesZeroingError(vol_path)
            finally:
                self.teardown(self.sdUUID, self.volUUID, justme=True)

        # try to cleanup as much as possible
        eFound = se.CannotDeleteVolume(self.volUUID)
        puuid = None
        try:
            # We need to blank parent record in our metadata
            # for parent to become leaf successfully.
            puuid = self.getParent()
            self.setParent(volume.BLANK_UUID)
            if puuid and puuid != volume.BLANK_UUID:
                pvol = BlockVolume(self.repoPath, self.sdUUID, self.imgUUID,
                                   puuid)
                pvol.recheckIfLeaf()
        except Exception as e:
            eFound = e
            self.log.warning("cannot finalize parent volume %s",
                             puuid,
                             exc_info=True)

        try:
            try:
                lvm.removeLVs(self.sdUUID, self.volUUID)
            except se.CannotRemoveLogicalVolume:
                # At this point LV is already marked as illegal, we will
                # try to cleanup whatever we can...
                pass

            self.removeMetadata([self.sdUUID, offs])
        except Exception as e:
            eFound = e
            self.log.error("cannot remove volume %s/%s",
                           self.sdUUID,
                           self.volUUID,
                           exc_info=True)

        try:
            self.log.debug("Unlinking %s", vol_path)
            os.unlink(vol_path)
            return True
        except Exception as e:
            eFound = e
            self.log.error("cannot delete volume's %s/%s link path: %s",
                           self.sdUUID,
                           self.volUUID,
                           vol_path,
                           exc_info=True)

        raise eFound