示例#1
0
    def rename(self, newUUID, recovery=True):
        """
        Rename volume
        """
        self.log.info("Rename volume %s as %s ", self.volUUID, newUUID)
        if not self.imagePath:
            self.validateImagePath()
        volPath = os.path.join(self.imagePath, newUUID)
        metaPath = self._getMetaVolumePath(volPath)
        prevMetaPath = self._getMetaVolumePath()

        if recovery:
            name = "Rename volume rollback: " + volPath
            vars.task.pushRecovery(
                task.Recovery(name, "fileVolume", "FileVolume",
                              "renameVolumeRollback",
                              [volPath, self.volumePath]))
        self.oop.os.rename(self.volumePath, volPath)
        if recovery:
            name = "Rename meta-volume rollback: " + metaPath
            vars.task.pushRecovery(
                task.Recovery(name, "fileVolume", "FileVolume",
                              "renameVolumeRollback",
                              [metaPath, prevMetaPath]))
        self.oop.os.rename(prevMetaPath, metaPath)
        self.volUUID = newUUID
        self.volumePath = volPath
示例#2
0
文件: volume.py 项目: bronhaim/vdsm
 def clone(self, dstPath, volFormat):
     """
     Clone self volume to the specified dst_image_dir/dst_volUUID
     """
     wasleaf = False
     taskName = "parent volume rollback: " + self.volUUID
     vars.task.pushRecovery(
         task.Recovery(taskName, "volume", "Volume", "parentVolumeRollback",
                       [self.sdUUID, self.imgUUID, self.volUUID]))
     if self.isLeaf():
         wasleaf = True
         self.setInternal()
     try:
         self.prepare(rw=False)
         self.log.debug('cloning volume %s to %s', self.volumePath, dstPath)
         parent = getBackingVolumePath(self.imgUUID, self.volUUID)
         domain = sdCache.produce(self.sdUUID)
         qemuimg.create(dstPath,
                        backing=parent,
                        format=sc.fmt2str(volFormat),
                        qcow2Compat=domain.qcow2_compat(),
                        backingFormat=sc.fmt2str(self.getFormat()))
         self.teardown(self.sdUUID, self.volUUID)
     except Exception as e:
         self.log.exception('cannot clone image %s volume %s to %s',
                            self.imgUUID, self.volUUID, dstPath)
         # FIXME: might race with other clones
         if wasleaf:
             self.setLeaf()
         self.teardown(self.sdUUID, self.volUUID)
         raise se.CannotCloneVolume(self.volumePath, dstPath, str(e))
示例#3
0
文件: volume.py 项目: fancyKai/vdsm
    def rebase(self, backingVol, backingVolPath, backingFormat, unsafe,
               rollback):
        """
        Rebase volume on top of new backing volume
        """
        if rollback:
            pvol = self.getParentVolume()
            if not pvol:
                self.log.warn("Can't rebase volume %s, parent missing",
                              self.volUUID)
                return

            name = "Merge volume: " + self.volUUID
            vars.task.pushRecovery(
                task.Recovery(name, "volume", "Volume", "rebaseVolumeRollback",
                              [
                                  self.sdUUID,
                                  self.getImage(), self.volUUID,
                                  str(pvol.getFormat()), pvol.volUUID,
                                  str(True)
                              ]))

        volumePath = self.getVolumePath()

        try:
            qemuimg.rebase(volumePath,
                           backingVolPath, fmt2str(self.getFormat()),
                           fmt2str(backingFormat), unsafe, vars.task.aborting)
        except qemuimg.QImgError:
            self.log.exception('cannot rebase volume %s on %s', volumePath,
                               backingVolPath)
            raise se.MergeSnapshotsError(self.volUUID)

        self.setParent(backingVol)
        self.recheckIfLeaf()
示例#4
0
 def share(self, dst_image_dir, hard=True):
     """
     Share this volume to dst_image_dir
     'hard' - link type: file volumes should use hardlinks (default behaviour)
                         block volumes should use softlinks (explicitly hard=False)
     """
     self.log.debug("Volume.share)share  %s to %s hard %s" % (self.volUUID, dst_image_dir, hard))
     if not self.isShared():
         raise se.VolumeNonShareable(self)
     if os.path.basename(dst_image_dir) == os.path.basename(self.imagePath):
         raise se.VolumeOwnershipError(self)
     try:
         src = self.getDevPath()
         dst = os.path.join(dst_image_dir, self.volUUID)
         taskName = "share volume rollback: " + dst
         vars.task.pushRecovery(task.Recovery(taskName, "volume", "Volume", "shareVolumeRollback",
                                              [dst]))
         if os.path.lexists(dst):
             os.unlink(dst)
         if hard:
             os.link(src, dst)
         else:
             os.symlink(src, dst)
     except Exception, e:
         raise se.CannotShareVolume(src, dst, str(e))
示例#5
0
 def clone(self, dst_image_dir, dst_volUUID, volFormat, preallocate):
     """
     Clone self volume to the specified dst_image_dir/dst_volUUID
     """
     wasleaf = False
     dst_path = None
     taskName = "parent volume rollback: " + self.volUUID
     vars.task.pushRecovery(task.Recovery(taskName, "volume", "Volume", "parentVolumeRollback",
                                          [self.sdUUID, self.imgUUID, self.volUUID]))
     if self.isLeaf():
         wasleaf = True
         self.setInternal()
     try:
         self.prepare(rw=False)
         dst_path = os.path.join(dst_image_dir, dst_volUUID)
         self.log.debug("Volume.clone: %s to %s" % (self.volumePath, dst_path))
         size = int(self.getMetaParam(SIZE))
         parent = self.getVolumePath()
         parent_format = fmt2str(self.getFormat())
         # We should use parent's relative path instead of full path
         parent = os.path.join(os.path.basename(os.path.dirname(parent)),
                                                os.path.basename(parent))
         createVolume(parent, parent_format, dst_path, size, volFormat, preallocate)
         self.teardown(self.sdUUID, self.volUUID)
     except Exception, e:
         # FIXME: might race with other clones
         if wasleaf:
             self.setLeaf()
         self.teardown(self.sdUUID, self.volUUID)
         self.log.error("Volume.clone: can't clone: %s to %s" % (self.volumePath, dst_path))
         raise se.CannotCloneVolume(self.volumePath, dst_path, str(e))
示例#6
0
    def share(self, dstImgPath):
        """
        Share this volume to dstImgPath
        """
        self.log.debug("Share volume %s to %s", self.volUUID, dstImgPath)

        if not self.isShared():
            raise se.VolumeNonShareable(self)

        if os.path.basename(dstImgPath) == os.path.basename(self.imagePath):
            raise se.VolumeOwnershipError(self)

        dstPath = os.path.join(dstImgPath, self.volUUID)
        clsModule, clsName = self._getModuleAndClass()

        try:
            vars.task.pushRecovery(
                task.Recovery("Share volume rollback: %s" % dstPath, clsModule,
                              clsName, "shareVolumeRollback", [dstPath])
            )

            self._share(dstImgPath)

        except Exception as e:
            raise se.CannotShareVolume(self.getVolumePath(), dstPath, str(e))
示例#7
0
    def rebase(self, backingVol, backingVolPath,
               backingFormat, unsafe, rollback):
        """
        Rebase volume on top of new backing volume
        """
        if rollback:
            pvol = self.getParentVolume()
            if not pvol:
                self.log.warn("Can't rebase volume %s, parent missing",
                              self.volUUID)
                return

            name = "Merge volume: " + self.volUUID
            vars.task.pushRecovery(
                task.Recovery(name, "volume", "Volume",
                              "rebaseVolumeRollback",
                              [self.sdUUID, self.getImage(),
                                  self.volUUID, str(pvol.getFormat()),
                                  pvol.volUUID, str(True)]))

        (rc, out, err) = qemuRebase(self.getVolumePath(), self.getFormat(),
                                    backingVolPath, backingFormat, unsafe,
                                    vars.task.aborting, rollback)
        if rc:
            raise se.MergeSnapshotsError(self.volUUID)
        self.setParent(backingVol)
        self.recheckIfLeaf()
示例#8
0
    def rename(self, newUUID, recovery=True):
        """
        Rename volume
        """
        self.log.info("Rename volume %s as %s ", self.volUUID, newUUID)
        if not self.imagePath:
            self._manifest.validateImagePath()
        volPath = os.path.join(self.imagePath, newUUID)
        metaPath = self._getMetaVolumePath(volPath)
        prevMetaPath = self._getMetaVolumePath()
        leasePath = self._getLeaseVolumePath(volPath)
        prevLeasePath = self._getLeaseVolumePath()

        if recovery:
            name = "Rename volume rollback: " + volPath
            vars.task.pushRecovery(
                task.Recovery(name, "fileVolume", "FileVolume",
                              "renameVolumeRollback",
                              [volPath, self.volumePath]))
        self.log.debug("Renaming %s to %s", self.volumePath, volPath)
        self.oop.os.rename(self.volumePath, volPath)
        if recovery:
            name = "Rename meta-volume rollback: " + metaPath
            vars.task.pushRecovery(
                task.Recovery(name, "fileVolume", "FileVolume",
                              "renameVolumeRollback",
                              [metaPath, prevMetaPath]))
        self.log.debug("Renaming %s to %s", prevMetaPath, metaPath)
        self.oop.os.rename(prevMetaPath, metaPath)
        if recovery:
            name = "Rename lease-volume rollback: " + leasePath
            vars.task.pushRecovery(
                task.Recovery(name, "fileVolume", "FileVolume",
                              "renameVolumeRollback",
                              [leasePath, prevLeasePath]))
        self.log.debug("Renaming %s to %s", prevLeasePath, leasePath)
        try:
            self.oop.os.rename(prevLeasePath, leasePath)
        except OSError as e:
            if e.errno != os.errno.ENOENT:
                raise
        self._manifest.volUUID = newUUID
        self._manifest.volumePath = volPath
示例#9
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)
示例#10
0
文件: volume.py 项目: bronhaim/vdsm
    def extendSize(self, newSize):
        """
        Extend the size (virtual disk size seen by the guest) of the volume.
        """
        if self.isShared():
            raise se.VolumeNonWritable(self.volUUID)

        volFormat = self.getFormat()
        if volFormat == sc.COW_FORMAT:
            self.log.debug(
                "skipping cow size extension for volume %s to "
                "size %s", self.volUUID, newSize)
            return
        elif volFormat != sc.RAW_FORMAT:
            raise se.IncorrectFormat(self.volUUID)

        # Note: This function previously prohibited extending non-leaf volumes.
        # If a disk is enlarged a volume may become larger than its parent.  In
        # order to support live merge of a larger volume into its raw parent we
        # must permit extension of this raw volume prior to starting the merge.
        isBase = self.getParent() == sc.BLANK_UUID
        if not (isBase or self.isLeaf()):
            raise se.VolumeNonWritable(self.volUUID)

        curRawSize = self.getVolumeSize()

        if (newSize < curRawSize):
            self.log.error(
                "current size of volume %s is larger than the "
                "size requested in the extension (%s > %s)", self.volUUID,
                curRawSize, newSize)
            raise se.VolumeResizeValueError(newSize)

        if (newSize == curRawSize):
            self.log.debug(
                "the requested size %s is equal to the current "
                "size %s, skipping extension", newSize, curRawSize)
        else:
            self.log.info(
                "executing a raw size extension for volume %s "
                "from size %s to size %s", self.volUUID, curRawSize, newSize)
            vars.task.pushRecovery(
                task.Recovery("Extend size for volume: " + self.volUUID,
                              "volume", "Volume", "extendSizeFinalize",
                              [self.sdUUID, self.imgUUID, self.volUUID]))
            self._extendSizeRaw(newSize)

        self.syncMetadata()  # update the metadata
示例#11
0
    def rename(self, newUUID, recovery=True):
        """
        Rename volume
        """
        self.log.info("Rename volume %s as %s ", self.volUUID, newUUID)
        if not self.imagePath:
            self.validateImagePath()

        if os.path.lexists(self.getVolumePath()):
            os.unlink(self.getVolumePath())

        if recovery:
            name = "Rename volume rollback: " + newUUID
            vars.task.pushRecovery(
                task.Recovery(name, "blockVolume", "BlockVolume",
                              "renameVolumeRollback",
                              [self.sdUUID, newUUID, self.volUUID]))
        lvm.renameLV(self.sdUUID, self.volUUID, newUUID)
        self.volUUID = newUUID
        self.volumePath = os.path.join(self.imagePath, newUUID)
示例#12
0
    def extendSize(self, newSize):
        """
        Extend the size (virtual disk size seen by the guest) of the volume.
        """
        if not self.isLeaf() or self.isShared():
            raise se.VolumeNonWritable(self.volUUID)

        volFormat = self.getFormat()

        if volFormat == COW_FORMAT:
            self.log.debug(
                "skipping cow size extension for volume %s to "
                "size %s", self.volUUID, newSize)
            return
        elif volFormat != RAW_FORMAT:
            raise se.IncorrectFormat(self.volUUID)

        curRawSize = self.getVolumeSize()

        if (newSize < curRawSize):
            self.log.error(
                "current size of volume %s is larger than the "
                "size requested in the extension (%s > %s)", self.volUUID,
                curRawSize, newSize)
            raise se.VolumeResizeValueError(newSize)

        if (newSize == curRawSize):
            self.log.debug(
                "the requested size %s is equal to the current "
                "size %s, skipping extension", newSize, curRawSize)
        else:
            self.log.info(
                "executing a raw size extension for volume %s "
                "from size %s to size %s", self.volUUID, curRawSize, newSize)
            vars.task.pushRecovery(
                task.Recovery("Extend size for volume: " + self.volUUID,
                              "volume", "Volume", "extendSizeFinalize",
                              [self.sdUUID, self.imgUUID, self.volUUID]))
            self._extendSizeRaw(newSize)

        self.syncMetadata()  # update the metadata
示例#13
0
文件: volume.py 项目: bronhaim/vdsm
    def create(cls,
               repoPath,
               sdUUID,
               imgUUID,
               size,
               volFormat,
               preallocate,
               diskType,
               volUUID,
               desc,
               srcImgUUID,
               srcVolUUID,
               initialSize=None):
        """
        Create a new volume with given size or snapshot
            'size' - in sectors
            'volFormat' - volume format COW / RAW
            'preallocate' - Preallocate / Sparse
            'diskType' - enum (API.Image.DiskTypes)
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
            'initialSize' - initial volume size in sectors,
                            in case of thin provisioning
        """
        dom = sdCache.produce(sdUUID)
        dom.validateCreateVolumeParams(volFormat,
                                       srcVolUUID,
                                       preallocate=preallocate)

        imgPath = image.Image(repoPath).create(sdUUID, imgUUID)

        volPath = os.path.join(imgPath, volUUID)
        volParent = None
        volType = sc.type2name(sc.LEAF_VOL)

        # Get the specific class name and class module to be used in the
        # Recovery tasks.
        clsModule, clsName = cls._getModuleAndClass()

        try:
            if srcVolUUID != sc.BLANK_UUID:
                # When the srcImgUUID isn't specified we assume it's the same
                # as the imgUUID
                if srcImgUUID == sc.BLANK_UUID:
                    srcImgUUID = imgUUID

                volParent = cls(repoPath, sdUUID, srcImgUUID, srcVolUUID)

                if not volParent.isLegal():
                    raise se.createIllegalVolumeSnapshotError(
                        volParent.volUUID)

                if imgUUID != srcImgUUID:
                    volParent.share(imgPath)
                    volParent = cls(repoPath, sdUUID, imgUUID, srcVolUUID)

                # Override the size with the size of the parent
                size = volParent.getSize()

        except se.StorageException:
            cls.log.error("Unexpected error", exc_info=True)
            raise
        except Exception as e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCannotGetParent(
                "Couldn't get parent %s for volume %s: %s" %
                (srcVolUUID, volUUID, e))

        try:
            cls.log.info("Creating volume %s", volUUID)

            # Rollback sentinel to mark the start of the task
            vars.task.pushRecovery(
                task.Recovery(task.ROLLBACK_SENTINEL, clsModule, clsName,
                              "startCreateVolumeRollback",
                              [sdUUID, imgUUID, volUUID]))

            # Create volume rollback
            vars.task.pushRecovery(
                task.Recovery("Halfbaked volume rollback", clsModule, clsName,
                              "halfbakedVolumeRollback",
                              [sdUUID, volUUID, volPath]))

            # Specific volume creation (block, file, etc...)
            try:
                metaId = cls._create(dom,
                                     imgUUID,
                                     volUUID,
                                     size,
                                     volFormat,
                                     preallocate,
                                     volParent,
                                     srcImgUUID,
                                     srcVolUUID,
                                     volPath,
                                     initialSize=initialSize)
            except (se.VolumeAlreadyExists, se.CannotCreateLogicalVolume,
                    se.VolumeCreationError, se.InvalidParameterException) as e:
                cls.log.error("Failed to create volume %s: %s", volPath, e)
                vars.task.popRecovery()
                raise
            # When the volume format is raw what the guest sees is the apparent
            # size of the file/device therefore if the requested size doesn't
            # match the apparent size (eg: physical extent granularity in LVM)
            # we need to update the size value so that the metadata reflects
            # the correct state.
            if volFormat == sc.RAW_FORMAT:
                apparentSize = int(
                    dom.getVSize(imgUUID, volUUID) / sc.BLOCK_SIZE)
                if apparentSize < size:
                    cls.log.error(
                        "The volume %s apparent size %s is smaller "
                        "than the requested size %s", volUUID, apparentSize,
                        size)
                    raise se.VolumeCreationError()
                if apparentSize > size:
                    cls.log.info(
                        "The requested size for volume %s doesn't "
                        "match the granularity on domain %s, "
                        "updating the volume size from %s to %s", volUUID,
                        sdUUID, size, apparentSize)
                    size = apparentSize

            vars.task.pushRecovery(
                task.Recovery("Create volume metadata rollback", clsModule,
                              clsName, "createVolumeMetadataRollback",
                              map(str, metaId)))

            cls.newMetadata(metaId, sdUUID, imgUUID, srcVolUUID, size,
                            sc.type2name(volFormat), sc.type2name(preallocate),
                            volType, diskType, desc, sc.LEGAL_VOL)

            if dom.hasVolumeLeases():
                cls.newVolumeLease(metaId, sdUUID, volUUID)

        except se.StorageException:
            cls.log.error("Unexpected error", exc_info=True)
            raise
        except Exception as e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCreationError("Volume creation %s failed: %s" %
                                         (volUUID, e))

        # Remove the rollback for the halfbaked volume
        vars.task.replaceRecoveries(
            task.Recovery("Create volume rollback", clsModule, clsName,
                          "createVolumeRollback",
                          [repoPath, sdUUID, imgUUID, volUUID, imgPath]))

        return volUUID
示例#14
0
def baseAsyncTasksRollback(proc):
    name = "Kill-" + str(proc.pid)
    vars.task.pushRecovery(task.Recovery(name, "volume", "Volume", "killProcRollback",
                                         [str(proc.pid), str(misc.getProcCtime(proc.pid))]))
示例#15
0
            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]))
            # By definition volume is now a leaf
            cls.file_setrw(vol_path, rw=True)
            # Set metadata and mark volume as legal.\
            cls.newMetadata(vol_path, sdUUID, imgUUID, srcVolUUID, size,
                            volume.type2name(volFormat),
                            volume.type2name(preallocate), voltype, diskType,
                            desc, volume.LEGAL_VOL)
        except Exception, e:
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeMetadataWriteError(vol_path + ":" + str(e))

        # Remove all previous rollbacks for 'halfbaked' volume and add rollback for 'real' volume creation
        vars.task.replaceRecoveries(
            task.Recovery("create file volume rollback", "fileVolume",
示例#16
0
            cls.log.error("Unexpected error", exc_info=True)
            raise se.VolumeCannotGetParent(
                "blockVolume can't get parent %s for volume %s: %s" %
                (srcVolUUID, volUUID, str(e)))

        try:
            cls.log.info("blockVolume: creating LV: volUUID %s" % (volUUID))
            if preallocate == volume.SPARSE_VOL:
                volsize = "%s" % config.get("irs",
                                            "volume_utilization_chunk_mb")
            else:
                # should stay %d and size should be int(size)
                volsize = "%s" % (size / 2 / 1024)
            vars.task.pushRecovery(
                task.Recovery("halfbaked volume rollback", "blockVolume",
                              "BlockVolume", "halfbakedVolumeRollback",
                              [sdUUID, volUUID, vol_path]))
            lvm.createLV(sdUUID, volUUID, volsize, activate=True)
            if os.path.exists(vol_path):
                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.