def _activateVolumeForImportExport(self, domain, imgUUID, volUUID=None): chain = self.getChain(domain.sdUUID, imgUUID, volUUID) log_str = logutils.volume_chain_to_str(vol.volUUID for vol in chain) self.log.info("chain=%s ", log_str) template = chain[0].getParentVolume() if template or len(chain) > 1: self.log.error("Importing and exporting an image with more " "than one volume is not supported") raise se.CopyImageError() domain.activateVolumes(imgUUID, volUUIDs=[chain[0].volUUID]) return chain[0]
def _interImagesCopy(self, destDom, srcSdUUID, imgUUID, chains): srcLeafVol = chains['srcChain'][-1] dstLeafVol = chains['dstChain'][-1] try: # Prepare the whole chains before the copy srcLeafVol.prepare(rw=False) dstLeafVol.prepare(rw=True, chainrw=True, setrw=True) except Exception: self.log.error("Unexpected error", exc_info=True) # teardown volumes self.__cleanupMove(srcLeafVol, dstLeafVol) raise try: for srcVol in chains['srcChain']: # Do the actual copy try: dstVol = destDom.produceVolume(imgUUID=imgUUID, volUUID=srcVol.volUUID) if workarounds.invalid_vm_conf_disk(srcVol): srcFormat = dstFormat = qemuimg.FORMAT.RAW else: srcFormat = sc.fmt2str(srcVol.getFormat()) dstFormat = sc.fmt2str(dstVol.getFormat()) parentVol = dstVol.getParentVolume() if parentVol is not None: backing = volume.getBackingVolumePath( imgUUID, parentVol.volUUID) backingFormat = sc.fmt2str(parentVol.getFormat()) else: backing = None backingFormat = None if (destDom.supportsSparseness and dstVol.getType() == sc.PREALLOCATED_VOL): preallocation = qemuimg.PREALLOCATION.FALLOC else: preallocation = None operation = qemuimg.convert( srcVol.getVolumePath(), dstVol.getVolumePath(), srcFormat=srcFormat, dstFormat=dstFormat, dstQcow2Compat=destDom.qcow2_compat(), backing=backing, backingFormat=backingFormat, preallocation=preallocation, unordered_writes=destDom.recommends_unordered_writes( dstVol.getFormat()), create=not destDom.is_block(), ) with utils.stopwatch("Copy volume %s" % srcVol.volUUID): self._run_qemuimg_operation(operation) except ActionStopped: raise except se.StorageException: self.log.error("Unexpected error", exc_info=True) raise except Exception: self.log.error( "Copy image error: image=%s, src domain=%s," " dst domain=%s", imgUUID, srcSdUUID, destDom.sdUUID, exc_info=True) raise se.CopyImageError() finally: # teardown volumes self.__cleanupMove(srcLeafVol, dstLeafVol)
def copyCollapsed(self, sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID, dstVolUUID, descr, dstSdUUID, volType, volFormat, preallocate, postZero, force, discard): """ 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 " "discard=%s", sdUUID, vmUUID, srcImgUUID, srcVolUUID, dstImgUUID, dstVolUUID, dstSdUUID, volType, sc.type2name(volFormat), sc.type2name(preallocate), str(force), str(postZero), discard) 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: # Before reading source volume parameters from volume metadata, # prepare the volume. This ensure that the volume capacity will # match the actual virtual size, see # https://bugzilla.redhat.com/1700623. srcVol.prepare(rw=False) volParams = srcVol.getVolumeParams() if volFormat in [sc.COW_FORMAT, sc.RAW_FORMAT]: dstVolFormat = volFormat else: dstVolFormat = volParams['volFormat'] # TODO: This is needed only when copying to qcow2-thin volume # on block storage. Move into calculate_initial_size. dst_vol_allocation = self.calculate_vol_alloc( sdUUID, volParams, dstSdUUID, dstVolFormat) # Find out dest volume parameters if preallocate in [sc.PREALLOCATED_VOL, sc.SPARSE_VOL]: volParams['prealloc'] = preallocate initial_size = self.calculate_initial_size( destDom.supportsSparseness, dstVolFormat, volParams['prealloc'], dst_vol_allocation) self.log.info( "Copy source %s:%s:%s to destination %s:%s:%s " "capacity=%s, initial size=%s", sdUUID, srcImgUUID, srcVolUUID, dstSdUUID, dstImgUUID, dstVolUUID, volParams['capacity'], initial_size) # 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, discard) destDom.createVolume(imgUUID=dstImgUUID, capacity=volParams['capacity'], volFormat=dstVolFormat, preallocate=volParams['prealloc'], diskType=volParams['disktype'], volUUID=dstVolUUID, desc=descr, srcImgUUID=sc.BLANK_UUID, srcVolUUID=sc.BLANK_UUID, initial_size=initial_size) dstVol = sdCache.produce(dstSdUUID).produceVolume( imgUUID=dstImgUUID, volUUID=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("Destination volume %s error: %s" % (dstVolUUID, str(e))) try: # Start the actual copy image procedure dstVol.prepare(rw=True, setrw=True) if (destDom.supportsSparseness and dstVol.getType() == sc.PREALLOCATED_VOL): preallocation = qemuimg.PREALLOCATION.FALLOC else: preallocation = None try: operation = qemuimg.convert( volParams['path'], dstVol.getVolumePath(), srcFormat=sc.fmt2str(volParams['volFormat']), dstFormat=sc.fmt2str(dstVolFormat), dstQcow2Compat=destDom.qcow2_compat(), preallocation=preallocation, unordered_writes=destDom.recommends_unordered_writes( dstVolFormat), create=not destDom.is_block(), ) with utils.stopwatch("Copy volume %s" % srcVol.volUUID): self._run_qemuimg_operation(operation) except ActionStopped: raise except cmdutils.Error as e: self.log.exception('conversion failure for volume %s', srcVol.volUUID) raise se.CopyImageError(str(e)) # Mark volume as SHARED if volType == sc.SHARED_VOL: dstVol.setShared() dstVol.setLegality(sc.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)
def _interImagesCopy(self, destDom, srcSdUUID, imgUUID, chains): srcLeafVol = chains['srcChain'][-1] dstLeafVol = chains['dstChain'][-1] try: # Prepare the whole chains before the copy srcLeafVol.prepare(rw=False) dstLeafVol.prepare(rw=True, chainrw=True, setrw=True) except Exception: self.log.error("Unexpected error", exc_info=True) # teardown volumes self.__cleanupMove(srcLeafVol, dstLeafVol) raise try: for srcVol in chains['srcChain']: # Do the actual copy try: dstVol = destDom.produceVolume(imgUUID=imgUUID, volUUID=srcVol.volUUID) if workarounds.invalid_vm_conf_disk(srcVol): srcFormat = dstFormat = qemuimg.FORMAT.RAW else: srcFormat = sc.fmt2str(srcVol.getFormat()) dstFormat = sc.fmt2str(dstVol.getFormat()) parentVol = dstVol.getParentVolume() if parentVol is not None: backing = volume.getBackingVolumePath( imgUUID, parentVol.volUUID) backingFormat = sc.fmt2str(parentVol.getFormat()) else: backing = None backingFormat = None operation = qemuimg.convert( srcVol.getVolumePath(), dstVol.getVolumePath(), srcFormat=srcFormat, dstFormat=dstFormat, dstQcow2Compat=destDom.qcow2_compat(), backing=backing, backingFormat=backingFormat, unordered_writes=destDom.recommends_unordered_writes( dstVol.getFormat()), create=dstVol.requires_create(), target_is_zero=dstVol.zero_initialized(), ) with utils.stopwatch("Copy volume {}".format( srcVol.volUUID), level=logging.INFO, log=self.log): self._run_qemuimg_operation(operation) except ActionStopped: raise except se.StorageException: self.log.error("Unexpected error", exc_info=True) raise except Exception: self.log.error( "Copy image error: image=%s, src domain=%s," " dst domain=%s", imgUUID, srcSdUUID, destDom.sdUUID, exc_info=True) raise se.CopyImageError() finally: # teardown volumes self.__cleanupMove(srcLeafVol, dstLeafVol)