def get_devices(ns, devices=None): """ Returns list of block devices. If no devices are given, all block devices on the system are returned. This functions just converts list of strings to list of appropriate LMIInstances. :type devices: list of LMIInstance/CIM_StorageExtent or list of strings :param devices: Devices to list. :rtype: list of LMIInstance/CIM_StorageExtent. """ if devices: LOG().debug("get_devices: Loading list of selected devices.") for dev in devices: yield str2device(ns, dev) else: LOG().debug("get_devices: Loading list of all devices.") for dev in ns.CIM_StorageExtent.instances(): if lmi_isinstance(dev, ns.CIM_Memory): # Skip memory devices, they inherit from CIM_StorageExtent too LOG().debug("get_devices: Skipping memory device %s" % dev.DeviceID) continue yield dev
def get_obj_id(self, ns, obj): """ Return unique ID of a device or a Volume group. """ if lmi_isinstance(obj, ns.CIM_StorageExtent): return obj.DeviceID else: return obj.InstanceID
def get_obj_info(ns, obj, human_friendly): """ Return detailed information of the device or VG to show. """ if lmi_isinstance(obj, ns.CIM_StorageExtent): return get_device_info(ns, obj, human_friendly) else: return get_pool_info(ns, obj, human_friendly)
def execute(self, ns, device=None): """ Implementation of 'device tree' command. """ # Note, this is high-speed version of the device tree. # Walking through associations using get_children() functions # was kind of slow, even for small number of devices (~5). # devices = dict devid -> LMIInstance devices = {} # Load *all* CIM_StorageExtents to speed things up. for dev in get_devices(ns): devices[self.get_obj_id(ns, dev)] = dev # Add *all* LMI_VGStoragePools. for vg in lvm.get_vgs(ns): devices[self.get_obj_id(ns, vg)] = vg for tp in lvm.get_tps(ns): devices[self.get_obj_id(ns, tp)] = tp # deps = array of tuples (parent devid, child devid) # Load all dependencies, calling get_children iteratively is slow # Add CIM_BasedOn dependencies (and omit LMI_LVBasedOn, we need # LMI_LVAllocatedFromStoragePool instead) LOG().debug("Loading list of CIM_BasedOn associations.") deps = [ (self.get_obj_id(ns, i.Antecedent), self.get_obj_id(ns, i.Dependent)) for i in ns.CIM_BasedOn.instances() if not lmi_isinstance(i, ns.LMI_LVBasedOn) ] # Be careful with logical partitions - they are BasedOn on appropriate # extended partition, but we want to draw them as children of # appropriate disk. LOG().debug("Reworking BasedOn associations for logical partitions.") logical = ns.LMI_DiskPartition.PartitionTypeValues.Logical extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended for i in xrange(len(deps)): dev = devices[deps[i][0]] child = devices[deps[i][1]] LOG().debug("Inspecting %s - %s" % deps[i]) if ( "PartitionType" in dev.properties() and "PartitionType" in child.properties() and dev.PartitionType == extended and child.PartitionType == logical ): # We found ext. partition - logical partition dependency # Find the disk disk_id = None for (d, c) in deps: if c == deps[i][0]: disk_id = d # Replace the extended->logical dependency with disk->logical deps[i] = (disk_id, deps[i][1]) LOG().debug("--- Replaced with %s - %s" % deps[i]) # Add VG-LV dependencies from LMI_LVAllocatedFromStoragePool association LOG().debug("Loading LVAllocatedFromStoragePool associations.") deps += [ (self.get_obj_id(ns, i.Antecedent), self.get_obj_id(ns, i.Dependent)) for i in ns.LMI_LVAllocatedFromStoragePool.instances() ] # Add PV-VG dependencies from LMI_VGAssociatedComponentExtent LOG().debug("Loading VGAssociatedComponentExtent associations.") deps += [ (self.get_obj_id(ns, i.PartComponent), self.get_obj_id(ns, i.GroupComponent)) for i in ns.LMI_VGAssociatedComponentExtent.instances() ] # Add VG-ThinPool dependencies from LMI_VGAllocatedFromStoragePool if "LMI_VGAllocatedFromStoragePool" in ns.classes(): LOG().debug("Loading VGAllocatedFromStoragePool associations.") deps += [ (self.get_obj_id(ns, i.Antecedent), self.get_obj_id(ns, i.Dependent)) for i in ns.LMI_VGAllocatedFromStoragePool.instances() ] # queue = array of tuples (devid, level), queue of items to inspect # and display queue = [] if device: device = str2device(ns, device[0]) queue = [(self.get_obj_id(ns, device), 0)] else: for (devid, device) in devices.iteritems(): if device.Primordial: queue.append((devid, 0)) shown = set() while queue: (devid, level) = queue.pop() device = devices[devid] info = get_obj_info(ns, device, self.app.config.human_friendly) if devid in shown: # If the device was already displayed, just show reference to it yield (self.prepare_tree_line(level, info[0], queue), "***") # Don't show children of already displayed elements continue # Display the device yield (self.prepare_tree_line(level, info[0], queue),) + info[1:] shown.add(devid) # And inspect all children children = [dep[1] for dep in deps if dep[0] == devid] for child in reversed(children): queue.append((child, level + 1))
def execute(self, ns, device=None): """ Implementation of 'device tree' command. """ # Note, this is high-speed version of the device tree. # Walking through associations using get_children() functions # was kind of slow, even for small number of devices (~5). # devices = dict devid -> LMIInstance devices = {} # Load *all* CIM_StorageExtents to speed things up. for dev in get_devices(ns): devices[self.get_obj_id(ns, dev)] = dev # Add *all* LMI_VGStoragePools. for vg in get_vgs(ns): devices[self.get_obj_id(ns, vg)] = vg # deps = array of tuples (parent devid, child devid) # Load all dependencies, calling get_children iteratively is slow # Add CIM_BasedOn dependencies (and omit LMI_LVBasedOn, we need # LMI_LVAllocatedFromStoragePool instead) LOG().debug("Loading list of CIM_BasedOn associations.") deps = [(self.get_obj_id(ns, i.Antecedent), self.get_obj_id(ns, i.Dependent)) for i in ns.CIM_BasedOn.instances() if not lmi_isinstance(i, ns.LMI_LVBasedOn)] # Be careful with logical partitions - they are BasedOn on appropriate # extended partition, but we want to draw them as children of # appropriate disk. LOG().debug("Reworking BasedOn associations for logical partitions.") logical = ns.LMI_DiskPartition.PartitionTypeValues.Logical extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended for i in xrange(len(deps)): dev = devices[deps[i][0]] child = devices[deps[i][1]] LOG().debug("Inspecting %s - %s" % deps[i]) if ("PartitionType" in dev.properties() and "PartitionType" in child.properties() and dev.PartitionType == extended and child.PartitionType == logical): # We found ext. partition - logical partition dependency # Find the disk disk_id = None for (d, c) in deps: if c == deps[i][0]: disk_id = d # Replace the extended->logical dependency with disk->logical deps[i] = (disk_id, deps[i][1]) LOG().debug("--- Replaced with %s - %s" % deps[i]) # Add VG-LV dependencies from LMI_LVAllocatedFromStoragePool association LOG().debug("Loading LVAllocatedFromStoragePool associations.") deps += [(self.get_obj_id(ns, i.Antecedent), self.get_obj_id(ns, i.Dependent)) for i in ns.LMI_LVAllocatedFromStoragePool.instances()] # Add PV-VG dependencies from LMI_VGAssociatedComponentExtent LOG().debug("Loading VGAssociatedComponentExtent associations.") deps += [(self.get_obj_id(ns, i.PartComponent), self.get_obj_id(ns, i.GroupComponent)) for i in ns.LMI_VGAssociatedComponentExtent.instances()] # queue = array of tuples (devid, level), queue of items to inspect # and display queue = [] if device: device = str2device(ns, device[0]) queue = [ (self.get_obj_id(ns, device), 0), ] else: for (devid, device) in devices.iteritems(): if device.Primordial: queue.append((devid, 0)) shown = set() while queue: (devid, level) = queue.pop() device = devices[devid] info = get_obj_info(ns, device, self.app.config.human_friendly) if devid in shown: # If the device was already displayed, just show reference to it yield (self.prepare_tree_line(level, info[0], queue), "***") # Don't show children of already displayed elements continue # Display the device yield (self.prepare_tree_line(level, info[0], queue), ) + info[1:] shown.add(devid) # And inspect all children children = [dep[1] for dep in deps if dep[0] == devid] for child in reversed(children): queue.append((child, level + 1))
def get_children(ns, obj, deep=False): """ Return list of all children of given LMIInstance. For example: * If ``obj`` is LMIInstance/LMI_VGStoragePool (=Volume Group), it returns all its Logical Volumes (=LMIInstance/LMI_LVStorageExtent). * If ``obj`` is LMIInstance/LMI_StorageExtent of a disk, it returns all its partitions (=LMIInstance/CIM_GenericDiskPartition). * If ``obj`` is LMIInstance/LMI_DiskPartition and the partition is Physical Volume of a Volume Group,, it returns the pool (LMIInstance/LMI_VGStoragePool). :type obj: LMIInstance/CIM_StorageExtent or LMIInstance/LMI_VGStoragePool or string :param obj: Object to find children of. :type deep: Boolean :param deep: Whether all children of the object should be returned or only immediate ones. """ obj = str2obj(ns, obj) if deep: # use loop of get_children(ns, xxx, deep=False) known_children = set() todo = [obj, ] # a TO-DO list while todo: obj = todo.pop() new_children = get_children(ns, obj, False) for child in new_children: if "DeviceID" in child.properties(): devid = child.DeviceID else: devid = child.InstanceID if devid not in known_children: known_children.add(devid) todo.append(child) yield child return # only direct children requested if lmi_isinstance(obj, ns.CIM_StorageExtent): # try to find children VG first children = obj.associators( AssocClass="LMI_VGAssociatedComponentExtent", Role="PartComponent") if children: for child in children: yield child return # Extended partition don't have children extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended if (lmi_isinstance(obj, ns.CIM_DiskPartition) and obj.PartitionType == extended): return # try usual BasedOn next children = obj.associators(AssocClass="CIM_BasedOn", Role="Antecedent") for child in children: yield child # Be careful with logical partitions - they are BasedOn extended # partition, but we want to have them as children of appropriate # disk instead. if (lmi_isinstance(child, ns.CIM_DiskPartition) and child.PartitionType == extended): LOG().debug("Looking for logical partitions on %s" % (child.DeviceID)) for c in child.associators(AssocClass="CIM_BasedOn", Role="Antecedent"): yield c elif lmi_isinstance(obj, ns.CIM_StoragePool): # find LVs allocated from the VG children = obj.associators( AssocClass="LMI_LVAllocatedFromStoragePool", Role="Antecedent") for child in children: yield child else: raise LmiFailed("CIM_StorageExtent or LMI_VGStragePool expected: %s" % obj.classname)
def get_parents(ns, obj, deep=False): """ Return list of all parents of given LMIInstance. For example: * If ``obj`` is LMIInstance/LMI_LVStorageExtent (=Logical Volume), it returns LMIInstance/LMI_VGStoragePool (=Volume Group). * If ``obj`` is LMIInstance/LMI_VGStoragePool (=Volume Group), it returns all its Physical Volumes (=LMIInstance/CIM_StorageExtent). :type obj: LMIInstance/CIM_StorageExtent or LMIInstance/LMI_VGStoragePool or string :param obj: Object to find parents of. :type deep: Boolean :param deep: Whether all parents of the object should be returned or only immediate ones. """ obj = str2obj(ns, obj) if deep: # use loop of get_parents(ns, xxx, deep=False) known_parents = set() todo = [obj, ] # a TO-DO list while todo: obj = todo.pop() new_parents = get_parents(ns, obj, False) for parent in new_parents: if "DeviceID" in parent.properties(): devid = parent.DeviceID else: devid = parent.InstanceID if devid not in known_parents: known_parents.add(devid) todo.append(parent) yield parent return # only direct parents requested if lmi_isinstance(obj, ns.CIM_StorageExtent): # Try to get parent VG first parents = obj.associators( AssocClass="LMI_LVAllocatedFromStoragePool", Role="Dependent") if parents: for parent in parents: yield parent return # Try usual BasedOn next parents = obj.associators(AssocClass="CIM_BasedOn", Role="Dependent") for parent in parents: # Be careful with logical partitions - they are BasedOn extended # partition, but we want to return appropriate disk instead. logical = ns.LMI_DiskPartition.PartitionTypeValues.Logical extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended if (lmi_isinstance(parent, ns.CIM_DiskPartition) and lmi_isinstance(obj, ns.CIM_DiskPartition) and obj.PartitionType == logical and parent.PartitionType == extended): LOG().debug("Looking for disk instead of extended partition %s" % (parent.DeviceID)) for p in get_parents(ns, parent, False): yield p else: # It is not logical partition yield parent elif lmi_isinstance(obj, ns.CIM_StoragePool): # find physical volumes of the VG parents = obj.associators( AssocClass="LMI_VGAssociatedComponentExtent", Role="GroupComponent") for parent in parents: yield parent else: raise LmiFailed("CIM_StorageExtent or LMI_VGStragePool expected: %s", obj.classname)
def get_children(ns, obj, deep=False): """ Return list of all children of given LMIInstance. For example: * If ``obj`` is LMIInstance/LMI_VGStoragePool (=Volume Group), it returns all its Logical Volumes (=LMIInstance/LMI_LVStorageExtent). * If ``obj`` is LMIInstance/LMI_StorageExtent of a disk, it returns all its partitions (=LMIInstance/CIM_GenericDiskPartition). * If ``obj`` is LMIInstance/LMI_DiskPartition and the partition is Physical Volume of a Volume Group,, it returns the pool (LMIInstance/LMI_VGStoragePool). :type obj: LMIInstance/CIM_StorageExtent or LMIInstance/LMI_VGStoragePool or string :param obj: Object to find children of. :type deep: Boolean :param deep: Whether all children of the object should be returned or only immediate ones. """ obj = str2obj(ns, obj) if deep: # use loop of get_children(ns, xxx, deep=False) known_children = set() todo = [ obj, ] # a TO-DO list while todo: obj = todo.pop() new_children = get_children(ns, obj, False) for child in new_children: if "DeviceID" in child.properties(): devid = child.DeviceID else: devid = child.InstanceID if devid not in known_children: known_children.add(devid) todo.append(child) yield child return # only direct children requested if lmi_isinstance(obj, ns.CIM_StorageExtent): # try to find children VG first children = obj.associators( AssocClass="LMI_VGAssociatedComponentExtent", Role="PartComponent") if children: for child in children: yield child return # Extended partition don't have children extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended if (lmi_isinstance(obj, ns.CIM_DiskPartition) and obj.PartitionType == extended): return # try usual BasedOn next children = obj.associators(AssocClass="CIM_BasedOn", Role="Antecedent") for child in children: yield child # Be careful with logical partitions - they are BasedOn extended # partition, but we want to have them as children of appropriate # disk instead. if (lmi_isinstance(child, ns.CIM_DiskPartition) and child.PartitionType == extended): LOG().debug("Looking for logical partitions on %s" % (child.DeviceID)) for c in child.associators(AssocClass="CIM_BasedOn", Role="Antecedent"): yield c elif lmi_isinstance(obj, ns.CIM_StoragePool): # find thin pools from the VG assoc_class = "LMI_VGAllocatedFromStoragePool" if assoc_class in ns.classes(): children = obj.associators(AssocClass=assoc_class, Role="Antecedent") for child in children: yield child # find LVs allocated from the VG children = obj.associators(AssocClass="LMI_LVAllocatedFromStoragePool", Role="Antecedent") for child in children: yield child else: raise LmiFailed("CIM_StorageExtent or LMI_VGStragePool expected: %s" % obj.classname)
def get_parents(ns, obj, deep=False): """ Return list of all parents of given LMIInstance. For example: * If ``obj`` is LMIInstance/LMI_LVStorageExtent (=Logical Volume), it returns LMIInstance/LMI_VGStoragePool (=Volume Group). * If ``obj`` is LMIInstance/LMI_VGStoragePool (=Volume Group), it returns all its Physical Volumes (=LMIInstance/CIM_StorageExtent). :type obj: LMIInstance/CIM_StorageExtent or LMIInstance/LMI_VGStoragePool or string :param obj: Object to find parents of. :type deep: Boolean :param deep: Whether all parents of the object should be returned or only immediate ones. """ obj = str2obj(ns, obj) if deep: # use loop of get_parents(ns, xxx, deep=False) known_parents = set() todo = [ obj, ] # a TO-DO list while todo: obj = todo.pop() new_parents = get_parents(ns, obj, False) for parent in new_parents: if "DeviceID" in parent.properties(): devid = parent.DeviceID else: devid = parent.InstanceID if devid not in known_parents: known_parents.add(devid) todo.append(parent) yield parent return # only direct parents requested if lmi_isinstance(obj, ns.CIM_StorageExtent): # Try to get parent VG first parents = obj.associators(AssocClass="LMI_LVAllocatedFromStoragePool", Role="Dependent") if parents: for parent in parents: yield parent return # Try usual BasedOn next parents = obj.associators(AssocClass="CIM_BasedOn", Role="Dependent") for parent in parents: # Be careful with logical partitions - they are BasedOn extended # partition, but we want to return appropriate disk instead. logical = ns.LMI_DiskPartition.PartitionTypeValues.Logical extended = ns.LMI_DiskPartition.PartitionTypeValues.Extended if (lmi_isinstance(parent, ns.CIM_DiskPartition) and lmi_isinstance(obj, ns.CIM_DiskPartition) and obj.PartitionType == logical and parent.PartitionType == extended): LOG().debug( "Looking for disk instead of extended partition %s" % (parent.DeviceID)) for p in get_parents(ns, parent, False): yield p else: # It is not logical partition yield parent elif lmi_isinstance(obj, ns.CIM_StoragePool): # find VGs of the thin pool assoc_class = "LMI_VGAllocatedFromStoragePool" if assoc_class in ns.classes(): parents = obj.associators(AssocClass=assoc_class, Role="Dependent") for parent in parents: yield parent # find physical volumes of the VG parents = obj.associators(AssocClass="LMI_VGAssociatedComponentExtent", Role="GroupComponent") for parent in parents: yield parent else: raise LmiFailed("CIM_StorageExtent or LMI_VGStragePool expected: %s", obj.classname)