def validateVolumeChain(self, sdUUID, imgUUID): """ Check correctness of the whole chain (including template if exists) """ if not self.isLegal(sdUUID, imgUUID): raise se.ImageIsNotLegalChain(imgUUID) chain = self.getChain(sdUUID, imgUUID) log_str = logutils.volume_chain_to_str(vol.volUUID for vol in chain) self.log.info("Current chain=%s ", log_str) # check if the chain is build above a template, or it is a standalone pvol = chain[0].getParentVolume() if pvol: if not pvol.isLegal() or pvol.isFake(): raise se.ImageIsNotLegalChain(imgUUID)
def syncData(self, sdUUID, imgUUID, dstSdUUID, syncType): srcChain = self.getChain(sdUUID, imgUUID) log_str = logutils.volume_chain_to_str(vol.volUUID for vol in srcChain) self.log.info("Source chain=%s ", log_str) dstChain = self.getChain(dstSdUUID, imgUUID) log_str = logutils.volume_chain_to_str(vol.volUUID for vol in dstChain) self.log.info("Dest chain=%s ", log_str) if syncType == SYNC_VOLUMES_INTERNAL: try: # Removing the leaf volumes del srcChain[-1], dstChain[-1] except IndexError: raise se.ImageIsNotLegalChain() elif syncType == SYNC_VOLUMES_LEAF: try: # Removing all the internal volumes del srcChain[:-1], dstChain[:-1] except IndexError: raise se.ImageIsNotLegalChain() elif syncType != SYNC_VOLUMES_ALL: raise se.MiscNotImplementedException() if len(srcChain) != len(dstChain): raise se.DestImageActionError(imgUUID, dstSdUUID) # Checking the volume uuids (after removing the leaves to allow # different uuids for the current top layer, see previous check). for i, v in enumerate(srcChain): if v.volUUID != dstChain[i].volUUID: raise se.DestImageActionError(imgUUID, dstSdUUID) dstDom = sdCache.produce(dstSdUUID) self._interImagesCopy(dstDom, sdUUID, imgUUID, { 'srcChain': srcChain, 'dstChain': dstChain }) self._finalizeDestinationImage(dstDom, imgUUID, { 'srcChain': srcChain, 'dstChain': dstChain }, False)
def getChain(self, sdUUID, imgUUID, volUUID=None): """ Return the chain of volumes of image as a sorted list (not including a shared base (template) if any) """ chain = [] volclass = sdCache.produce(sdUUID).getVolumeClass() # Use volUUID when provided if volUUID: srcVol = volclass(self.repoPath, sdUUID, imgUUID, volUUID) # For template images include only one volume (the template itself) # NOTE: this relies on the fact that in a template there is only # one volume if srcVol.isShared(): return [srcVol] # Find all the volumes when volUUID is not provided else: # Find all volumes of image uuidlist = volclass.getImageVolumes(sdUUID, imgUUID) if not uuidlist: raise se.ImageDoesNotExistInSD(imgUUID, sdUUID) srcVol = volclass(self.repoPath, sdUUID, imgUUID, uuidlist[0]) # For template images include only one volume (the template itself) if len(uuidlist) == 1 and srcVol.isShared(): return [srcVol] # Searching for the leaf for vol in uuidlist: srcVol = volclass(self.repoPath, sdUUID, imgUUID, vol) if srcVol.isLeaf(): break srcVol = None if not srcVol: self.log.error("There is no leaf in the image %s", imgUUID) raise se.ImageIsNotLegalChain(imgUUID) # We have seen corrupted chains that cause endless loops here. # https://bugzilla.redhat.com/1125197 seen = set() # Build up the sorted parent -> child chain while not srcVol.isShared(): chain.insert(0, srcVol) seen.add(srcVol.volUUID) parentUUID = srcVol.getParent() if parentUUID == sc.BLANK_UUID: break if parentUUID in seen: self.log.error("Image %s volume %s has invalid parent UUID %s", imgUUID, srcVol.volUUID, parentUUID) raise se.ImageIsNotLegalChain(imgUUID) srcVol = srcVol.getParentVolume() return chain