Exemplo n.º 1
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)

        mysd = sdCache.produce(sdUUID=sdUUID)
        try:
            lvm.getLV(sdUUID, volUUID)
        except se.LogicalVolumeDoesNotExistError:
            pass  #OK, this is a new volume
        else:
            raise se.VolumeAlreadyExists(volUUID)

        imageDir = image.Image(repoPath).create(sdUUID, imgUUID)
        vol_path = os.path.join(imageDir, volUUID)
        pvol = None
        voltype = "LEAF"

        try:
            if srcVolUUID != volume.BLANK_UUID:
                # We have a parent
                if srcImgUUID == volume.BLANK_UUID:
                    srcImgUUID = imgUUID
                pvol = BlockVolume(repoPath, sdUUID, srcImgUUID, srcVolUUID)
                # Cannot create snapshot for ILLEGAL volume
                if not pvol.isLegal():
                    raise se.createIllegalVolumeSnapshotError(pvol.volUUID)

                if imgUUID != srcImgUUID:
                    pvol.share(imageDir, hard=False)
                    pvol = BlockVolume(repoPath, sdUUID, imgUUID, srcVolUUID)

                # override size param by parent's size
                size = pvol.getSize()
        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.VolumeCannotGetParent(
                "blockVolume can't get parent %s for volume %s: %s" %
                (srcVolUUID, volUUID, str(e)))
Exemplo n.º 2
0
    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 = type2name(LEAF_VOL)

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

        try:
            if srcVolUUID != BLANK_UUID:
                # When the srcImgUUID isn't specified we assume it's the same
                # as the imgUUID
                if srcImgUUID == 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 == RAW_FORMAT:
                apparentSize = int(dom.getVSize(imgUUID, volUUID) / 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,
                            type2name(volFormat), type2name(preallocate),
                            volType, diskType, desc, 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