def _set_lvm_membership(self): if self._is_lvm_member is None: # this is contentious, if a PV is recognized by LVM but has no # VGs, should we consider it as part of LVM? We choose not to # here, because most likely, we need to use VGs from this PV. self._is_lvm_member = False device_to_check = [self.path] device_to_check.extend(self.partitions) # a pv can only be in one vg, so this should be safe # FIXME: While the above assumption holds, sda1 and sda2 # can each host a PV and VG. I think the vg_name property is # actually unused (not 100% sure) and can simply be removed vgs = None if not self.all_devices_vgs: self.all_devices_vgs = lvm.get_all_devices_vgs() for path in device_to_check: for dev_vg in self.all_devices_vgs: if dev_vg.pv_name == path: vgs = [dev_vg] if vgs: self.vgs.extend(vgs) self.vg_name = vgs[0] self._is_lvm_member = True self.lvs.extend(lvm.get_device_lvs(path))
def single_report(self, device): """ Generate a report for a single device. This can be either a logical volume in the form of vg/lv or a device with an absolute path like /dev/sda1 or /dev/sda. Returns '{}' to denote failure. """ lvs = [] if os.path.isabs(device): # we have a block device lvs = api.get_device_lvs(device) if not lvs: # maybe this was a LV path /dev/vg_name/lv_name or /dev/mapper/ lvs = api.get_lvs(filters={'path': device}) else: # vg_name/lv_name was passed vg_name, lv_name = device.split('/') lvs = api.get_lvs(filters={'lv_name': lv_name, 'vg_name': vg_name}) report = self.create_report(lvs) if not report: # check if device is a non-lvm journals or wal/db for dev_type in ['journal', 'wal', 'db']: lvs = api.get_lvs( tags={'ceph.{}_device'.format(dev_type): device}) if lvs: # just taking the first lv here should work lv = lvs[0] phys_dev = self.create_report_non_lv_device(lv) osd_id = lv.tags.get('ceph.osd_id') if osd_id: report[osd_id] = [phys_dev] return report
def get_devices(_sys_block_path='/sys/block'): """ Captures all available block devices as reported by lsblk. Additional interesting metadata like sectors, size, vendor, solid/rotational, etc. is collected from /sys/block/<device> Returns a dictionary, where keys are the full paths to devices. ..note:: loop devices, removable media, and logical volumes are never included. """ device_facts = {} block_devs = get_block_devs_lsblk() for block in block_devs: devname = os.path.basename(block[0]) diskname = block[1] if block[2] not in ['disk', 'mpath']: continue sysdir = os.path.join(_sys_block_path, devname) metadata = {} # If the mapper device is a logical volume it gets excluded if is_mapper_device(diskname): if lvm.get_device_lvs(diskname): continue # all facts that have no defaults # (<name>, <path relative to _sys_block_path>) facts = [('removable', 'removable'), ('ro', 'ro'), ('vendor', 'device/vendor'), ('model', 'device/model'), ('rev', 'device/rev'), ('sas_address', 'device/sas_address'), ('sas_device_handle', 'device/sas_device_handle'), ('support_discard', 'queue/discard_granularity'), ('rotational', 'queue/rotational'), ('nr_requests', 'queue/nr_requests'), ] for key, file_ in facts: metadata[key] = get_file_contents(os.path.join(sysdir, file_)) metadata['scheduler_mode'] = "" scheduler = get_file_contents(sysdir + "/queue/scheduler") if scheduler is not None: m = re.match(r".*?(\[(.*)\])", scheduler) if m: metadata['scheduler_mode'] = m.group(2) metadata['partitions'] = get_partitions_facts(sysdir) size = get_file_contents(os.path.join(sysdir, 'size'), 0) metadata['sectors'] = get_file_contents(os.path.join(sysdir, 'sectors'), 0) fallback_sectorsize = get_file_contents(sysdir + "/queue/hw_sector_size", 512) metadata['sectorsize'] = get_file_contents(sysdir + "/queue/logical_block_size", fallback_sectorsize) metadata['size'] = float(size) * 512 metadata['human_readable_size'] = human_readable_size(metadata['size']) metadata['path'] = diskname metadata['locked'] = is_locked_raw_device(metadata['path']) device_facts[diskname] = metadata return device_facts
def test_get_device_lvs_with_empty_vg(self, patched_output_parser, pcall): patched_output_parser.return_value = [{'lv_name': ''}] pcall.return_value = ('', '', '') vgs = api.get_device_lvs('/dev/foo') assert vgs == []