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'])
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'])
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