Пример #1
0
def get_partitions_facts(sys_block_path):
    partition_metadata = {}
    for folder in os.listdir(sys_block_path):
        folder_path = os.path.join(sys_block_path, folder)
        if os.path.exists(os.path.join(folder_path, 'partition')):
            contents = get_file_contents(os.path.join(folder_path, 'partition'))
            if contents:
                part = {}
                partname = folder
                part_sys_block_path = os.path.join(sys_block_path, partname)

                part['start'] = get_file_contents(part_sys_block_path + "/start", 0)
                part['sectors'] = get_file_contents(part_sys_block_path + "/size", 0)

                part['sectorsize'] = get_file_contents(
                    part_sys_block_path + "/queue/logical_block_size")
                if not part['sectorsize']:
                    part['sectorsize'] = get_file_contents(
                        part_sys_block_path + "/queue/hw_sector_size", 512)
                part['size'] = float(part['sectors']) * 512
                part['human_readable_size'] = human_readable_size(float(part['sectors']) * 512)
                part['holders'] = []
                for holder in os.listdir(part_sys_block_path + '/holders'):
                    part['holders'].append(holder)

                partition_metadata[partname] = part
    return partition_metadata
Пример #2
0
def get_partitions_facts(sys_block_path):
    partition_metadata = {}
    for folder in os.listdir(sys_block_path):
        folder_path = os.path.join(sys_block_path, folder)
        if os.path.exists(os.path.join(folder_path, 'partition')):
            contents = get_file_contents(os.path.join(folder_path, 'partition'))
            if contents:
                part = {}
                partname = folder
                part_sys_block_path = os.path.join(sys_block_path, partname)

                part['start'] = get_file_contents(part_sys_block_path + "/start", 0)
                part['sectors'] = get_file_contents(part_sys_block_path + "/size", 0)

                part['sectorsize'] = get_file_contents(
                    part_sys_block_path + "/queue/logical_block_size")
                if not part['sectorsize']:
                    part['sectorsize'] = get_file_contents(
                        part_sys_block_path + "/queue/hw_sector_size", 512)
                part['size'] = human_readable_size(float(part['sectors']) * 512)
                part['holders'] = []
                for holder in os.listdir(part_sys_block_path + '/holders'):
                    part['holders'].append(holder)

                partition_metadata[partname] = part
    return partition_metadata
Пример #3
0
def get_block_devs_sysfs(_sys_block_path='/sys/block',
                         _sys_dev_block_path='/sys/dev/block'):
    def holder_inner_loop():
        for holder in holders:
            # /sys/block/sdy/holders/dm-8/dm/uuid
            holder_dm_type = get_file_contents(
                os.path.join(
                    _sys_block_path, dev,
                    f'holders/{holder}/dm/uuid')).split('-')[0].lower()
            if holder_dm_type == 'mpath':
                return True

    # First, get devices that are _not_ partitions
    result = list()
    dev_names = os.listdir(_sys_block_path)
    for dev in dev_names:
        name = kname = os.path.join("/dev", dev)
        if not os.path.exists(name):
            continue
        type_ = 'disk'
        holders = os.listdir(os.path.join(_sys_block_path, dev, 'holders'))
        if get_file_contents(os.path.join(_sys_block_path, dev,
                                          'removable')) == "1":
            continue
        if holder_inner_loop():
            continue
        dm_dir_path = os.path.join(_sys_block_path, dev, 'dm')
        if os.path.isdir(dm_dir_path):
            dm_type = get_file_contents(os.path.join(dm_dir_path, 'uuid'))
            type_ = dm_type.split('-')[0].lower()
            basename = get_file_contents(os.path.join(dm_dir_path, 'name'))
            name = os.path.join("/dev/mapper", basename)
        if dev.startswith('loop'):
            if not allow_loop_devices():
                continue
            # Skip loop devices that are not attached
            if not os.path.exists(os.path.join(_sys_block_path, dev, 'loop')):
                continue
            type_ = 'loop'
        result.append([kname, name, type_])
    # Next, look for devices that _are_ partitions
    for item in os.listdir(_sys_dev_block_path):
        is_part = get_file_contents(
            os.path.join(_sys_dev_block_path, item, 'partition')) == "1"
        dev = os.path.basename(
            os.readlink(os.path.join(_sys_dev_block_path, item)))
        if not is_part:
            continue
        name = kname = os.path.join("/dev", dev)
        result.append([name, kname, "part"])
    return sorted(result, key=lambda x: x[0])
Пример #4
0
 def holder_inner_loop():
     for holder in holders:
         # /sys/block/sdy/holders/dm-8/dm/uuid
         holder_dm_type = get_file_contents(
             os.path.join(
                 _sys_block_path, dev,
                 f'holders/{holder}/dm/uuid')).split('-')[0].lower()
         if holder_dm_type == 'mpath':
             return True
Пример #5
0
 def test_exception_returns_default(self):
     with patch('builtins.open') as mocked_open:
         mocked_open.side_effect = Exception()
         result = system.get_file_contents('/tmp/fake-file')
     assert result == ''
Пример #6
0
 def test_path_has_multiline_contents(self, fake_filesystem):
     interesting_file = fake_filesystem.create_file('/tmp/fake-file',
                                                    contents="0\n1")
     result = system.get_file_contents(interesting_file.path)
     assert result == "0\n1"
Пример #7
0
 def test_path_does_not_exist(self, tmpdir):
     filepath = os.path.join(str(tmpdir), 'doesnotexist')
     assert system.get_file_contents(filepath, 'default') == 'default'
Пример #8
0
 def test_exception_returns_default(self, tmpfile):
     interesting_file = tmpfile(contents="0")
     # remove read, causes IOError
     os.chmod(interesting_file, 0o000)
     result = system.get_file_contents(interesting_file)
     assert result == ''
Пример #9
0
 def test_path_has_multiline_contents(self, tmpfile):
     interesting_file = tmpfile(contents="0\n1")
     result = system.get_file_contents(interesting_file)
     assert result == "0\n1"
Пример #10
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
Пример #11
0
def get_devices(_sys_block_path='/sys/block',
                _dev_path='/dev',
                _mapper_path='/dev/mapper'):
    """
    Captures all available devices from /sys/block/, including its partitions,
    along with interesting metadata like sectors, size, vendor,
    solid/rotational, etc...

    Returns a dictionary, where keys are the full paths to devices.

    ..note:: dmapper devices get their path updated to what they link from, if
            /dev/dm-0 is linked by /dev/mapper/ceph-data, then the latter gets
            used as the key.

    ..note:: loop devices, removable media, and logical volumes are never included.
    """
    # Portions of this detection process are inspired by some of the fact
    # gathering done by Ansible in module_utils/facts/hardware/linux.py. The
    # processing of metadata and final outcome *is very different* and fully
    # imcompatible. There are ignored devices, and paths get resolved depending
    # on dm devices, loop, and removable media

    device_facts = {}

    block_devs = get_block_devs(_sys_block_path)
    dev_devs = get_dev_devs(_dev_path)
    mapper_devs = get_mapper_devs(_mapper_path)

    for block in block_devs:
        sysdir = os.path.join(_sys_block_path, block)
        metadata = {}

        # Ensure that the diskname is an absolute path and that it never points
        # to a /dev/dm-* device
        diskname = mapper_devs.get(block) or dev_devs.get(block)
        if not diskname:
            continue

        # If the mapper device is a logical volume it gets excluded
        if is_mapper_device(diskname):
            if lvm.is_lv(diskname):
                continue

        metadata['removable'] = get_file_contents(
            os.path.join(sysdir, 'removable'))
        # Is the device read-only ?
        metadata['ro'] = get_file_contents(os.path.join(sysdir, 'ro'))

        for key in [
                'vendor', 'model', 'rev', 'sas_address', 'sas_device_handle'
        ]:
            metadata[key] = get_file_contents(sysdir + "/device/" + key)

        for key in ['sectors', 'size']:
            metadata[key] = get_file_contents(os.path.join(sysdir, key), 0)

        for key, _file in [('support_discard', '/queue/discard_granularity')]:
            metadata[key] = get_file_contents(os.path.join(sysdir, _file))

        metadata['partitions'] = get_partitions_facts(sysdir)

        for key in ['rotational', 'nr_requests']:
            metadata[key] = get_file_contents(sysdir + "/queue/" + key)

        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)

        if not metadata['sectors']:
            metadata['sectors'] = 0
        size = metadata['sectors'] or metadata['size']
        metadata['sectorsize'] = get_file_contents(sysdir +
                                                   "/queue/logical_block_size")
        if not metadata['sectorsize']:
            metadata['sectorsize'] = get_file_contents(
                sysdir + "/queue/hw_sector_size", 512)
        metadata['human_readable_size'] = human_readable_size(
            float(size) * 512)
        metadata['size'] = float(size) * 512
        metadata['path'] = diskname
        metadata['locked'] = is_locked_raw_device(metadata['path'])

        device_facts[diskname] = metadata
    return device_facts
Пример #12
0
def get_devices(_sys_block_path='/sys/block', _dev_path='/dev', _mapper_path='/dev/mapper'):
    """
    Captures all available devices from /sys/block/, including its partitions,
    along with interesting metadata like sectors, size, vendor,
    solid/rotational, etc...

    Returns a dictionary, where keys are the full paths to devices.

    ..note:: dmapper devices get their path updated to what they link from, if
            /dev/dm-0 is linked by /dev/mapper/ceph-data, then the latter gets
            used as the key.

    ..note:: loop devices, removable media, and logical volumes are never included.
    """
    # Portions of this detection process are inspired by some of the fact
    # gathering done by Ansible in module_utils/facts/hardware/linux.py. The
    # processing of metadata and final outcome *is very different* and fully
    # imcompatible. There are ignored devices, and paths get resolved depending
    # on dm devices, loop, and removable media

    device_facts = {}

    block_devs = get_block_devs(_sys_block_path)
    dev_devs = get_dev_devs(_dev_path)
    mapper_devs = get_mapper_devs(_mapper_path)

    for block in block_devs:
        sysdir = os.path.join(_sys_block_path, block)
        metadata = {}

        # Ensure that the diskname is an absolute path and that it never points
        # to a /dev/dm-* device
        diskname = mapper_devs.get(block) or dev_devs.get(block)
        if not diskname:
            continue

        # If the mapper device is a logical volume it gets excluded
        if is_mapper_device(diskname):
            if lvm.is_lv(diskname):
                continue

        metadata['removable'] = get_file_contents(os.path.join(sysdir, 'removable'))
        # Is the device read-only ?
        metadata['ro'] = get_file_contents(os.path.join(sysdir, 'ro'))


        for key in ['vendor', 'model', 'rev', 'sas_address', 'sas_device_handle']:
            metadata[key] = get_file_contents(sysdir + "/device/" + key)

        for key in ['sectors', 'size']:
            metadata[key] = get_file_contents(os.path.join(sysdir, key), 0)

        for key, _file in [('support_discard', '/queue/discard_granularity')]:
            metadata[key] = get_file_contents(os.path.join(sysdir, _file))

        metadata['partitions'] = get_partitions_facts(sysdir)

        for key in ['rotational', 'nr_requests']:
            metadata[key] = get_file_contents(sysdir + "/queue/" + key)

        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)

        if not metadata['sectors']:
            metadata['sectors'] = 0
        size = metadata['sectors'] or metadata['size']
        metadata['sectorsize'] = get_file_contents(sysdir + "/queue/logical_block_size")
        if not metadata['sectorsize']:
            metadata['sectorsize'] = get_file_contents(sysdir + "/queue/hw_sector_size", 512)
        metadata['human_readable_size'] = human_readable_size(float(size) * 512)
        metadata['size'] = float(size) * 512
        metadata['path'] = diskname
        metadata['locked'] = is_locked_raw_device(metadata['path'])

        for part_name, part_metadata in metadata['partitions'].items():
            part_abspath = '/dev/%s' % part_name
            device_facts[part_abspath] = part_metadata

        device_facts[diskname] = metadata
    return device_facts