def validateCreateVolumeParams(self, volFormat, srcVolUUID, preallocate=None): """ Validate create volume parameters """ if volFormat not in volume.VOL_FORMAT: raise se.IncorrectFormat(volume.type2name(volFormat)) # Volumes with a parent must be cow if srcVolUUID != volume.BLANK_UUID and volFormat != volume.COW_FORMAT: raise se.IncorrectFormat(volume.type2name(volFormat)) if preallocate is not None and preallocate not in volume.VOL_TYPE: raise se.IncorrectType(volume.type2name(preallocate))
def validateCreateVolumeParams(self, volFormat, srcVolUUID, preallocate=None): super(BlockStorageDomain, self).validateCreateVolumeParams( volFormat, srcVolUUID, preallocate=preallocate) # Sparse-Raw not supported for block volumes if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT: raise se.IncorrectFormat(volume.type2name(volFormat))
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ if initialSize: cls.log.error("initialSize is not supported for file-based " "volumes") raise se.InvalidParameterException("initial size", initialSize) sizeBytes = size * BLOCK_SIZE truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0 try: oop.getProcessPool(dom.sdUUID).truncateFile( volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True) except OSError as e: if e.errno == errno.EEXIST: raise se.VolumeAlreadyExists(volUUID) raise if preallocate == volume.PREALLOCATED_VOL: try: # ddWatchCopy expects size to be in bytes misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting, sizeBytes) except ActionStopped: raise except Exception: cls.log.error("Unexpected error", exc_info=True) raise se.VolumesZeroingError(volPath) if not volParent: cls.log.info( "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat)) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) # Forcing the volume permissions in case one of the tools we use # (dd, qemu-img, etc.) will mistakenly change the file permissiosn. dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS) return (volPath, )
def _create( cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None, ): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ if initialSize: cls.log.error("initialSize is not supported for file-based " "volumes") raise se.InvalidParameterException("initial size", initialSize) sizeBytes = size * BLOCK_SIZE truncSize = sizeBytes if volFormat == volume.RAW_FORMAT else 0 try: oop.getProcessPool(dom.sdUUID).truncateFile(volPath, truncSize, mode=VOLUME_PERMISSIONS, creatExcl=True) except OSError as e: if e.errno == errno.EEXIST: raise se.VolumeAlreadyExists(volUUID) raise if preallocate == volume.PREALLOCATED_VOL: try: # ddWatchCopy expects size to be in bytes misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting, sizeBytes) except ActionStopped: raise except Exception: cls.log.error("Unexpected error", exc_info=True) raise se.VolumesZeroingError(volPath) if not volParent: cls.log.info( "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size ) if volFormat == volume.COW_FORMAT: qemuimg.create(volPath, sizeBytes, volume.fmt2str(volFormat)) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) # Forcing the volume permissions in case one of the tools we use # (dd, qemu-img, etc.) will mistakenly change the file permissiosn. dom.oop.os.chmod(volPath, VOLUME_PERMISSIONS) return (volPath,)
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ if preallocate == volume.SPARSE_VOL: volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb") else: volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB) lvm.createLV(dom.sdUUID, volUUID, volSize, activate=True, initialTag=TAG_VOL_UNINIT) utils.rmFile(volPath) os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath) if not volParent: cls.log.info( "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: qemuimg.create(volPath, size * BLOCK_SIZE, volume.fmt2str(volFormat)) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) with cls._tagCreateLock: mdSlot = dom.getVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS) mdTags = [ "%s%s" % (TAG_PREFIX_MD, mdSlot), "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (TAG_PREFIX_IMAGE, imgUUID) ] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, volUUID) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, mdSlot)
def validateCreateVolumeParams(cls, volFormat, preallocate, srcVolUUID): """ Validate create volume parameters. 'srcVolUUID' - backing volume UUID 'volFormat' - volume format RAW/QCOW2 'preallocate' - sparse/preallocate """ volume.Volume.validateCreateVolumeParams(volFormat, preallocate, srcVolUUID) # Sparse-Raw not supported for block volumes if preallocate == volume.SPARSE_VOL and volFormat == volume.RAW_FORMAT: raise se.IncorrectFormat(volume.type2name(volFormat))
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, imgPath, volPath): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ if preallocate == volume.SPARSE_VOL: volSize = "%s" % config.get("irs", "volume_utilization_chunk_mb") else: volSize = "%s" % ((size + SECTORS_TO_MB - 1) / SECTORS_TO_MB) lvm.createLV(dom.sdUUID, volUUID, volSize, activate=True, initialTag=TAG_VOL_UNINIT) utils.rmFile(volPath) os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath) if not volParent: cls.log.info("Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: volume.createVolume(None, None, volPath, size, volFormat, preallocate) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(imgPath, volUUID, volFormat, preallocate) with cls._tagCreateLock: mdSlot = dom.mapMetaOffset(volUUID, VOLUME_MDNUMBLKS) mdTags = ["%s%s" % (TAG_PREFIX_MD, mdSlot), "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, volUUID) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, mdSlot)
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, imgPath, volPath): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ sizeBytes = int(size) * BLOCK_SIZE try: oop.getProcessPool(dom.sdUUID).truncateFile(volPath, sizeBytes, creatExcl=True) except OSError as e: if e.errno == errno.EEXIST: raise se.VolumeAlreadyExists(volUUID) raise if preallocate == volume.PREALLOCATED_VOL: try: # ddWatchCopy expects size to be in bytes misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting, sizeBytes) except ActionStopped: raise except Exception: cls.log.error("Unexpected error", exc_info=True) raise se.VolumesZeroingError(volPath) if not volParent: cls.log.info("Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: volume.createVolume(None, None, volPath, size, volFormat, preallocate) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(imgPath, volUUID, volFormat, preallocate) # By definition the volume is a leaf cls.file_setrw(volPath, rw=True) return (volPath,)
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ lvSize = cls._calculate_volume_alloc_size(preallocate, size, initialSize) lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True, initialTag=TAG_VOL_UNINIT) utils.rmFile(volPath) os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath) if not volParent: cls.log.info("Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: qemuimg.create( volPath, size * BLOCK_SIZE, volume.fmt2str(volFormat)) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) with dom.acquireVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS) as slot: mdTags = ["%s%s" % (TAG_PREFIX_MD, slot), "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (TAG_PREFIX_IMAGE, imgUUID)] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, volUUID) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, slot)
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, imgPath, volPath): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ sizeBytes = int(size) * BLOCK_SIZE if preallocate == volume.SPARSE_VOL: # Sparse = regular file oop.getProcessPool(dom.sdUUID).truncateFile(volPath, sizeBytes) else: try: # ddWatchCopy expects size to be in bytes misc.ddWatchCopy("/dev/zero", volPath, vars.task.aborting, sizeBytes) except ActionStopped: raise except Exception: cls.log.error("Unexpected error", exc_info=True) raise se.VolumesZeroingError(volPath) if not volParent: cls.log.info( "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: volume.createVolume(None, None, volPath, size, volFormat, preallocate) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(imgPath, volUUID, volFormat, preallocate) # By definition the volume is a leaf cls.file_setrw(volPath, rw=True) return (volPath, )
def _create(cls, dom, imgUUID, volUUID, size, volFormat, preallocate, volParent, srcImgUUID, srcVolUUID, volPath, initialSize=None): """ Class specific implementation of volumeCreate. All the exceptions are properly handled and logged in volume.create() """ lvSize = cls._calculate_volume_alloc_size(preallocate, size, initialSize) lvm.createLV(dom.sdUUID, volUUID, "%s" % lvSize, activate=True, initialTag=TAG_VOL_UNINIT) utils.rmFile(volPath) os.symlink(lvm.lvPath(dom.sdUUID, volUUID), volPath) if not volParent: cls.log.info( "Request to create %s volume %s with size = %s " "sectors", volume.type2name(volFormat), volPath, size) if volFormat == volume.COW_FORMAT: qemuimg.create(volPath, size * BLOCK_SIZE, volume.fmt2str(volFormat)) else: # Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) volParent.clone(volPath, volFormat) with dom.acquireVolumeMetadataSlot(volUUID, VOLUME_MDNUMBLKS) as slot: mdTags = [ "%s%s" % (TAG_PREFIX_MD, slot), "%s%s" % (TAG_PREFIX_PARENT, srcVolUUID), "%s%s" % (TAG_PREFIX_IMAGE, imgUUID) ] lvm.changeLVTags(dom.sdUUID, volUUID, delTags=[TAG_VOL_UNINIT], addTags=mdTags) try: lvm.deactivateLVs(dom.sdUUID, volUUID) except se.CannotDeactivateLogicalVolume: cls.log.warn("Cannot deactivate new created volume %s/%s", dom.sdUUID, volUUID, exc_info=True) return (dom.sdUUID, slot)
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. try: cls.log.info("blockVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID)) if not pvol: cls.log.info( "Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size ) # Create 'raw' volume via qemu-img actually redundant if volFormat == volume.COW_FORMAT: volume.createVolume(None, None, vol_path, size, volFormat, preallocate) else: ## Create hardlink to template and its meta file cls.log.info( "Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID ) pvol.clone(imageDir, volUUID, volFormat, preallocate) except Exception: cls.log.error("Unexpected error", exc_info=True) raise try:
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) else: # Sparse = Normal file oop.getProcessPool(sdUUID).createSparseFile(vol_path, 0) cls.log.info("fileVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID)) if not pvol: cls.log.info("Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size) # Create preallocate/raw volume via qemu-img actually redundant 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]))
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. try: cls.log.info("blockVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID)) if not pvol: cls.log.info("Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size) # Create 'raw' volume via qemu-img actually redundant if volFormat == volume.COW_FORMAT: volume.createVolume(None, None, vol_path, size, volFormat, preallocate) else: ## Create hardlink to template and its meta file cls.log.info("Request to create snapshot %s/%s of volume %s/%s", imgUUID, volUUID, srcImgUUID, srcVolUUID) pvol.clone(imageDir, volUUID, volFormat, preallocate) except Exception: cls.log.error("Unexpected error", exc_info=True) raise try: with cls._tagCreateLock: offs = mysd.mapMetaOffset(volUUID, VOLUME_MDNUMBLKS) lvm.addLVTags(sdUUID, volUUID, ("%s%s" % (TAG_PREFIX_MD, offs),
(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) else: # Sparse = Normal file oop.getProcessPool(sdUUID).createSparseFile(vol_path, 0) cls.log.info("fileVolume: create: volUUID %s srcImg %s srvVol %s" % (volUUID, srcImgUUID, srcVolUUID)) if not pvol: cls.log.info( "Request to create %s volume %s with size = %s sectors", volume.type2name(volFormat), vol_path, size) # Create preallocate/raw volume via qemu-img actually redundant 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(
def copy(self, sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID, dstVolUUID, descr, dstSdUUID, volType, volFormat, preallocate, postZero, force): """ Create new template/volume from VM. Do it by collapse and copy the whole chain (baseVolUUID->srcVolUUID) """ self.log.info("sdUUID=%s vmUUID=%s srcImgUUID=%s srcVolUUID=%s " "dstImgUUID=%s dstVolUUID=%s dstSdUUID=%s volType=%s " "volFormat=%s preallocate=%s force=%s postZero=%s", sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID, dstVolUUID, dstSdUUID, volType, volume.type2name(volFormat), volume.type2name(preallocate), str(force), str(postZero)) try: srcVol = dstVol = None # Find out dest sdUUID if dstSdUUID == sd.BLANK_UUID: dstSdUUID = sdUUID volclass = sdCache.produce(sdUUID).getVolumeClass() destDom = sdCache.produce(dstSdUUID) # find src volume try: srcVol = volclass(self.repoPath, sdUUID, srcImgUUID, srcVolUUID) except se.StorageException: raise except Exception as e: self.log.error(e, exc_info=True) raise se.SourceImageActionError(srcImgUUID, sdUUID, str(e)) # Create dst volume try: # find out src volume parameters volParams = srcVol.getVolumeParams() if volParams['parent'] and \ volParams['parent'] != volume.BLANK_UUID: # Volume has parent and therefore is a part of a chain # in that case we can not know what is the exact size of # the space target file (chain ==> cow ==> sparse). # Therefore compute an estimate of the target volume size # using the sum of the actual size of the chain's volumes if volParams['volFormat'] != volume.COW_FORMAT or \ volParams['prealloc'] != volume.SPARSE_VOL: raise se.IncorrectFormat(self) volParams['apparentsize'] = self.__chainSizeCalc( sdUUID, srcImgUUID, srcVolUUID, volParams['size']) # Find out dest volume parameters if preallocate in [volume.PREALLOCATED_VOL, volume.SPARSE_VOL]: volParams['prealloc'] = preallocate if volFormat in [volume.COW_FORMAT, volume.RAW_FORMAT]: dstVolFormat = volFormat else: dstVolFormat = volParams['volFormat'] self.log.info("copy source %s:%s:%s vol size %s destination " "%s:%s:%s apparentsize %s" % (sdUUID, srcImgUUID, srcVolUUID, volParams['size'], dstSdUUID, dstImgUUID, dstVolUUID, volParams['apparentsize'])) # If image already exists check whether it illegal/fake, # overwrite it if not self.isLegal(dstSdUUID, dstImgUUID): force = True # We must first remove the previous instance of image (if # exists) in destination domain, if we got the overwrite # command if force: self.log.info("delete image %s on domain %s before " "overwriting", dstImgUUID, dstSdUUID) _deleteImage(destDom, dstImgUUID, postZero) # To avoid 'prezeroing' preallocated volume on NFS domain, # we create the target volume with minimal size and after that # we'll change its metadata back to the original size. tmpSize = TEMPORARY_VOLUME_SIZE # in sectors (10M) destDom.createVolume( imgUUID=dstImgUUID, size=tmpSize, volFormat=dstVolFormat, preallocate=volParams['prealloc'], diskType=volParams['disktype'], volUUID=dstVolUUID, desc=descr, srcImgUUID=volume.BLANK_UUID, srcVolUUID=volume.BLANK_UUID) dstVol = sdCache.produce(dstSdUUID).produceVolume( imgUUID=dstImgUUID, volUUID=dstVolUUID) # For convert to 'raw' we need use the virtual disk size # instead of apparent size if dstVolFormat == volume.RAW_FORMAT: newsize = volParams['size'] else: newsize = volParams['apparentsize'] dstVol.extend(newsize) dstPath = dstVol.getVolumePath() # Change destination volume metadata back to the original size. dstVol.setSize(volParams['size']) except se.StorageException: self.log.error("Unexpected error", exc_info=True) raise except Exception as e: self.log.error("Unexpected error", exc_info=True) raise se.CopyImageError("Destination volume %s error: %s" % (dstVolUUID, str(e))) try: # Start the actual copy image procedure srcVol.prepare(rw=False) dstVol.prepare(rw=True, setrw=True) try: (rc, out, err) = volume.qemuConvert( volParams['path'], dstPath, volParams['volFormat'], dstVolFormat, vars.task.aborting, size=srcVol.getVolumeSize(bs=1), dstvolType=dstVol.getType()) if rc: raise se.StorageException("rc: %s, err: %s" % (rc, err)) except ActionStopped: raise except se.StorageException as e: raise se.CopyImageError(str(e)) # Mark volume as SHARED if volType == volume.SHARED_VOL: dstVol.setShared() dstVol.setLegality(volume.LEGAL_VOL) if force: # Now we should re-link all deleted hardlinks, if exists destDom.templateRelink(dstImgUUID, dstVolUUID) except se.StorageException: self.log.error("Unexpected error", exc_info=True) raise except Exception as e: self.log.error("Unexpected error", exc_info=True) raise se.CopyImageError("src image=%s, dst image=%s: msg=%s" % (srcImgUUID, dstImgUUID, str(e))) self.log.info("Finished copying %s:%s -> %s:%s", sdUUID, srcVolUUID, dstSdUUID, dstVolUUID) #TODO: handle return status return dstVolUUID finally: self.__cleanupCopy(srcVol=srcVol, dstVol=dstVol)