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: return # Nothing to do elif curSizeBytes <= 0: raise se.StorageException("Volume size is impossible: %s" % curSizeBytes) elif newSizeBytes < curSizeBytes: raise se.VolumeResizeValueError(newSize) if self.getType() == sc.PREALLOCATED_VOL: self.log.info("Preallocating volume %s to %s bytes", volPath, newSizeBytes) operation = fallocate.allocate(volPath, newSizeBytes - curSizeBytes, curSizeBytes) with vars.task.abort_callback(operation.abort): with utils.stopwatch("Preallocating volume %s" % volPath): operation.run() else: # for sparse files we can just truncate to the correct size # also good fallback for failed preallocation self.log.info("Truncating volume %s to %s bytes", volPath, newSizeBytes) self.oop.truncateFile(volPath, newSizeBytes)
def _extendSizeRaw(self, new_capacity): volPath = self.getVolumePath() cur_capacity = self.oop.os.stat(volPath).st_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 new_capacity == cur_capacity: return # Nothing to do elif cur_capacity <= 0: raise se.StorageException("Volume capacity is impossible: %s" % cur_capacity) elif new_capacity < cur_capacity: raise se.VolumeResizeValueError(new_capacity) if self.getType() == sc.PREALLOCATED_VOL: self.log.info("Preallocating volume %s to %s", volPath, new_capacity) op = fallocate.allocate(volPath, new_capacity - cur_capacity, offset=cur_capacity) with vars.task.abort_callback(op.abort): with utils.stopwatch("Preallocating volume {}".format(volPath), level=logging.INFO, log=self.log): op.run() else: # for sparse files we can just truncate to the correct size # also good fallback for failed preallocation self.log.info("Truncating volume %s to %s", volPath, new_capacity) self.oop.truncateFile(volPath, new_capacity)
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
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: return # Nothing to do elif curSizeBytes <= 0: raise se.StorageException("Volume size is impossible: %s" % curSizeBytes) elif newSizeBytes < curSizeBytes: raise se.VolumeResizeValueError(newSize) if self.getType() == sc.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)