示例#1
0
    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))
示例#2
0
    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
示例#3
0
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
示例#4
0
 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 == []