def getAllVolumes(sdUUID): """ Return dict {volUUID: ((imgUUIDs,), parentUUID)} of the domain. imgUUIDs is a list of all images dependant on volUUID. For template based volumes, the first image is the template's image. For other volumes, there is just a single imageUUID. Template self image is the 1st term in template volume entry images. """ vols = _getVolsTree(sdUUID) res = {} for volName in vols.iterkeys(): res[volName] = {'imgs': [], 'parent': None} for volName, vImg, parentVol in vols.itervalues(): res[volName]['parent'] = parentVol if vImg not in res[volName]['imgs']: res[volName]['imgs'].insert(0, vImg) if parentVol != sd.BLANK_UUID: try: imgIsUnknown = vImg not in res[parentVol]['imgs'] except KeyError: log.warning("Found broken image %s, orphan volume %s/%s, " "parent %s", vImg, sdUUID, volName, parentVol) else: if imgIsUnknown: res[parentVol]['imgs'].append(vImg) return dict((k, sd.ImgsPar(tuple(v['imgs']), v['parent'])) for k, v in res.iteritems())
def getAllVolumes(self): """ Return dict {volUUID: ((imgUUIDs,), parentUUID)} of the domain. Template self image is the 1st term in template volume entry images. The parent can't be determined in file domain without reading the metadata. Setting parent = None for compatibility with block version. """ volMetaPattern = os.path.join(self.mountpoint, self.sdUUID, sd.DOMAIN_IMAGES, "*", "*.meta") volMetaPaths = self.oop.glob.glob(volMetaPattern) volumes = {} for metaPath in volMetaPaths: head, tail = os.path.split(metaPath) volUUID, volExt = os.path.splitext(tail) imgUUID = os.path.basename(head) if volUUID in volumes: # Templates have no parents volumes[volUUID]['parent'] = sd.BLANK_UUID # Template volumes are hard linked in every image directory # which is derived from that template, therefore: # 1. a template volume which is in use will appear at least # twice (in the template image dir and in the derived image # dir) # 2. Any volume which appears more than once in the dir tree is # by definition a template volume. # 3. Any image which has more than 1 volume is not a template # image. Therefore if imgUUID appears in more than one path # then it is not a template. if len( tuple(vPath for vPath in volMetaPaths if imgUUID in vPath)) > 1: # Add template additonal image volumes[volUUID]['imgs'].append(imgUUID) else: # Insert at head the template self image volumes[volUUID]['imgs'].insert(0, imgUUID) else: volumes[volUUID] = {'imgs': [imgUUID], 'parent': None} return dict((k, sd.ImgsPar(tuple(v['imgs']), v['parent'])) for k, v in volumes.iteritems())
def getAllVolumesImages(self): """ Return all the images that depend on a volume. Return dicts: vols = {volUUID: ([imgUUID1, imgUUID2], parentUUID)]} for complete images. remnants (same) for broken imgs, orphan volumes, etc. """ vols = {} # The "legal" volumes: not half deleted/removed volumes. remnants = {} # Volumes which are part of failed image deletes. allVols = getAllVolumes(self.sdUUID) for volName, ip in allVols.iteritems(): if (volName.startswith(sd.REMOVED_IMAGE_PREFIX) or ip.imgs[0].startswith(sd.REMOVED_IMAGE_PREFIX)): remnants[volName] = ip else: # Deleted images are not dependencies of valid volumes. images = [img for img in ip.imgs if not img.startswith(sd.REMOVED_IMAGE_PREFIX)] vols[volName] = sd.ImgsPar(images, ip.parent) return vols, remnants
def getAllVolumes(self): """ Return dict {volUUID: ((imgUUIDs,), parentUUID)} of the domain. (imgUUIDs,) is a tuple of all the images that contain a certain volUUID. For non-templates volumes, this tuple consists of a single image. For template volume it consists of all the images that are based on the template volume. In that case, the first imgUUID in the tuple is the self-image of the template. The parent of a non-template volume cannot be determined in file domain without reading the metadata. However, in order to have an output compatible to block domain, we report parent as None. Template volumes have no parent, and thus we report BLANK_UUID as their parentUUID. """ volMetaPattern = os.path.join(self.mountpoint, self.sdUUID, sd.DOMAIN_IMAGES, "*", "*.meta") volMetaPaths = self.oop.glob.glob(volMetaPattern) # First create mapping from images to volumes images = collections.defaultdict(list) for metaPath in volMetaPaths: head, tail = os.path.split(metaPath) volUUID, volExt = os.path.splitext(tail) imgUUID = os.path.basename(head) images[imgUUID].append(volUUID) # Using images to volumes mapping, we can create volumes to images # mapping, detecting template volumes and template images, based on # these rules: # # Template volumes are hard linked in every image directory # which is derived from that template, therefore: # # 1. A template volume which is in use will appear at least twice # (in the template image dir and in the derived image dir) # # 2. Any volume which appears more than once in the dir tree is # by definition a template volume. # # 3. Any image which has more than 1 volume is not a template # image. volumes = {} for imgUUID, volUUIDs in images.iteritems(): for volUUID in volUUIDs: if volUUID in volumes: # This must be a template volume (rule 2) volumes[volUUID]['parent'] = sd.BLANK_UUID if len(volUUIDs) > 1: # This image is not a template (rule 3) volumes[volUUID]['imgs'].append(imgUUID) else: # This image is a template (rule 3) volumes[volUUID]['imgs'].insert(0, imgUUID) else: volumes[volUUID] = {'imgs': [imgUUID], 'parent': None} return dict((k, sd.ImgsPar(tuple(v['imgs']), v['parent'])) for k, v in volumes.iteritems())