Beispiel #1
0
    def __init__(self, volumeData, newSize, callbackFunction=None):

        if (not 'poolID' in volumeData) or \
           (not 'domainID' in volumeData) or \
           (not 'volumeID' in volumeData):
                self.log.error('create extend msg failed for volume: %s, size: %d', '-'.join(volumeData.values()), newSize)
                raise InvalidParameterException('volumeData dictionary', volumeData)
        if (newSize < 0) or (newSize > VOLUME_MAX_SIZE):
                raise InvalidParameterException('volumeSize', newSize)
        misc.validateUUID(volumeData['domainID'], 'domainID')
        misc.validateUUID(volumeData['volumeID'], 'volumeID')

        self.pool = volumeData['poolID']
        self.volumeData = volumeData
        self.newSize = str(dec2hex(newSize))
        self.callback = callbackFunction

        # Message structure is rigid (order must be kept and is relied upon):
        # Version (1 byte), OpCode (4 bytes), Domain UUID (16 bytes), Volume UUID (16 bytes), Requested size (16 bytes), Padding to 64 bytes (14 bytes)
        domain = misc.packUuid(volumeData['domainID'])
        volume = misc.packUuid(volumeData['volumeID'])
        # Build base payload
        payload = MESSAGE_VERSION + EXTEND_CODE + domain + volume + self.newSize.rjust(SIZE_CHARS,"0")
        # Pad payload with zeros
        self.payload = payload.ljust(MESSAGE_SIZE,"0")

        self.log.debug('new extend msg created: domain: %s, volume: %s', volumeData['domainID'], volumeData['volumeID'])
Beispiel #2
0
    def __init__(self, volumeData, newSize, callbackFunction=None):

        if ('poolID' not in volumeData) or \
           ('domainID' not in volumeData) or \
           ('volumeID' not in volumeData):
            self.log.error(
                'create extend msg failed for volume: %s, size:'
                ' %d', '-'.join(volumeData.values()), newSize)
            raise InvalidParameterException('volumeData dictionary',
                                            volumeData)
        if (newSize < 0) or (newSize > VOLUME_MAX_SIZE):
            raise InvalidParameterException('volumeSize', newSize)
        misc.validateUUID(volumeData['domainID'], 'domainID')
        misc.validateUUID(volumeData['volumeID'], 'volumeID')

        self.pool = volumeData['poolID']
        self.volumeData = volumeData
        self.newSize = str(dec2hex(newSize))
        self.callback = callbackFunction

        # Message structure is rigid (order must be kept and is relied upon):
        # Version (1 byte), OpCode (4 bytes), Domain UUID (16 bytes), Volume
        # UUID (16 bytes), Requested size (16 bytes), Padding to 64 bytes (14
        # bytes)
        domain = misc.packUuid(volumeData['domainID'])
        volume = misc.packUuid(volumeData['volumeID'])
        # Build base payload
        payload = MESSAGE_VERSION + EXTEND_CODE + domain + volume + \
            self.newSize.rjust(SIZE_CHARS, "0")
        # Pad payload with zeros
        self.payload = payload.ljust(MESSAGE_SIZE, "0")

        self.log.debug('new extend msg created: domain: %s, volume: %s',
                       volumeData['domainID'], volumeData['volumeID'])
Beispiel #3
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' - Preallocate / Sparse
            'diskType' - enum (API.Image.DiskTypes)
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
        """
        # Validate volume parameters should be checked here for all
        # internal flows using volume creation.
        misc.validateUUID(sdUUID, "sdUUID", False)
        misc.validateUUID(imgUUID, "imgUUID", False)
        misc.validateUUID(srcImgUUID, "srcImgUUID", True)
        misc.validateUUID(srcVolUUID, "srcVolUUID", True)
        cls.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)

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

        if dom.volumeExists(imgPath, volUUID):
            raise se.VolumeAlreadyExists(volUUID)

        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...)
            metaId = cls._create(dom, imgUUID, volUUID, size, volFormat,
                                 preallocate, volParent, srcImgUUID,
                                 srcVolUUID, imgPath, volPath)

            # 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 = cls.getVSize(dom, imgUUID, volUUID)
                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
Beispiel #4
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' - Preallocate / Sparse
            'diskType' - enum (API.Image.DiskTypes)
            'srcImgUUID' - source image UUID
            'srcVolUUID' - source volume UUID
        """
        # Validate volume parameters should be checked here for all
        # internal flows using volume creation.
        misc.validateUUID(sdUUID, "sdUUID", False)
        misc.validateUUID(imgUUID, "imgUUID", False)
        misc.validateUUID(srcImgUUID, "srcImgUUID", True)
        misc.validateUUID(srcVolUUID, "srcVolUUID", True)
        cls.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID)

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

        if dom.volumeExists(imgPath, volUUID):
            raise se.VolumeAlreadyExists(volUUID)

        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...)
            metaId = cls._create(dom, imgUUID, volUUID, size, volFormat,
                                 preallocate, volParent, srcImgUUID,
                                 srcVolUUID, imgPath, volPath)

            # 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 = cls.getVSize(dom, imgUUID, volUUID)
                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