def test_check_xfs_systemdmount(monkeypatch): systemdmount_data_no_xfs = { "node": "/dev/sda1", "path": "pci-0000:00:17.0-ata-2", "model": "TOSHIBA_THNSNJ512GDNU_A", "wwn": "0x500080d9108e8753", "fs_type": "ext4", "label": "n/a", "uuid": "5675d309-eff7-4eb1-9c27-58bc5880ec72" } mountpoints = library.check_xfs_systemdmount( [SystemdMountEntry(**systemdmount_data_no_xfs)]) assert len(mountpoints) == 0 systemdmount_data_xfs = { "node": "/dev/sda1", "path": "/var", "model": "n/a", "wwn": "n/a", "fs_type": "xfs", "label": "n/a", "uuid": "n/a" } mountpoints = library.check_xfs_systemdmount( [SystemdMountEntry(**systemdmount_data_xfs)]) assert mountpoints == {"/var"}
def test_get_systemd_mount_info(monkeypatch): def get_cmd_output_mocked(cmd, delim, expected_len): return [ ['/dev/dm-1', 'n/a', 'n/a', 'n/a', 'ext4', 'n/a', 'bec30ca5-5403-4c23-ae6e-cb2a911bc076'], ['/dev/dm-3', 'n/a', 'n/a', 'n/a', 'ext4', 'n/a', 'd6eaf17d-e2a9-4e8d-bb54-a89c18923ea2'], ['/dev/sda1', 'pci-0000:00:17.0-ata-2', 'LITEON_LCH-256V2S', '0x5002303100d82b06', 'ext4', 'n/a', 'c3890bf3-9273-4877-ad1f-68144e1eb858']] monkeypatch.setattr(library, '_get_cmd_output', get_cmd_output_mocked) expected = [ SystemdMountEntry( node='/dev/dm-1', path='n/a', model='n/a', wwn='n/a', fs_type='ext4', label='n/a', uuid='bec30ca5-5403-4c23-ae6e-cb2a911bc076'), SystemdMountEntry( node='/dev/dm-3', path='n/a', model='n/a', wwn='n/a', fs_type='ext4', label='n/a', uuid='d6eaf17d-e2a9-4e8d-bb54-a89c18923ea2'), SystemdMountEntry( node='/dev/sda1', path='pci-0000:00:17.0-ata-2', model='LITEON_LCH-256V2S', wwn='0x5002303100d82b06', fs_type='ext4', label='n/a', uuid='c3890bf3-9273-4877-ad1f-68144e1eb858')] assert expected == library._get_systemd_mount_info()
def test_actor_without_systemdmount_entry(current_actor_context): without_systemdmount_entry = [ SystemdMountEntry(node="/dev/sda1", path="pci-0000:00:17.0-ata-2", model="TOSHIBA_THNSNJ512GDNU_A", wwn="0x500080d9108e8753", fs_type="ext4", label="n/a", uuid="5675d309-eff7-4eb1-9c27-58bc5880ec72") ] current_actor_context.feed( StorageInfo(systemdmount=without_systemdmount_entry)) current_actor_context.run() assert not current_actor_context.consume(Report)
def test_actor_with_systemdmount_entry(current_actor_context): with_systemdmount_entry = [ SystemdMountEntry(node="nfs", path="n/a", model="n/a", wwn="n/a", fs_type="nfs", label="n/a", uuid="n/a") ] current_actor_context.feed( StorageInfo(systemdmount=with_systemdmount_entry)) current_actor_context.run() assert 'inhibitor' in current_actor_context.consume(Report)[0].flags
def test_actor_with_systemdmount_entry(current_actor_context, nfs_fstype): with_systemdmount_entry = [ SystemdMountEntry(node="nfs", path="n/a", model="n/a", wwn="n/a", fs_type=nfs_fstype, label="n/a", uuid="n/a") ] current_actor_context.feed( StorageInfo(systemdmount=with_systemdmount_entry)) current_actor_context.run() report_fields = current_actor_context.consume(Report)[0].report assert 'inhibitor' in report_fields['flags']
def _get_systemd_mount_info(): """ Collect storage info from systemd-mount command """ for entry in _get_cmd_output(['systemd-mount', '--list'], ' ', 7): # We need to filter the entry because there is a ton of whitespace. node, path, model, wwn, fs_type, label, uuid = [x for x in entry if x != ''] if node == "NODE": # First row of the "systemd-mount --list" output is a header. # Just skip it. continue yield SystemdMountEntry( node=node, path=path, model=model, wwn=wwn, fs_type=fs_type, label=label, uuid=uuid)
def _get_systemd_mount_info(): """ Collect the same storage info as provided by the systemd-mount command. The actual implementation no longer relies on calling the systemd-mount, but rather collects the same information from udev directly using pyudev. The systemd-mount output parsing has proved not to be unreliable due to its tabular format. """ ctx = pyudev.Context() # Filter the devices in the same way `systemd-mount --list` does for device in ctx.list_devices(subsystem='block', ID_FS_USAGE='filesystem'): # Use 'n/a' to provide the same value for unknown output fields same way the systemd-mount does yield SystemdMountEntry( node=device.device_node, path=device.get('ID_PATH', default='n/a'), model=device.get('ID_MODEL', default='n/a'), wwn=device.get('ID_WWN', default='n/a'), fs_type=device.get('ID_FS_TYPE', default='n/a'), label=device.get('ID_FS_LABEL', default='n/a'), uuid=device.get('ID_FS_UUID', default='n/a') )
def process(self): result = StorageInfo() partitions_path = '/proc/partitions' if self.is_file_readable(partitions_path): with open(partitions_path, 'r') as partitions: skipped_header = False for entry in partitions: if entry.startswith('#'): continue if not skipped_header: skipped_header = True continue entry = entry.strip() if not entry: continue major, minor, blocks, name = entry.split() result.partitions.append(PartitionEntry( major=major, minor=minor, blocks=blocks, name=name)) fstab_path = '/etc/fstab' if self.is_file_readable(fstab_path): with open(fstab_path, 'r') as fstab: for entry in fstab: if entry.startswith('#'): continue entry = entry.strip() if not entry: continue fs_spec, fs_file, fs_vfstype, fs_mntops, fs_freq, fs_passno = entry.split() result.fstab.append(FstabEntry( fs_spec=fs_spec, fs_file=fs_file, fs_vfstype=fs_vfstype, fs_mntops=fs_mntops, fs_freq=fs_freq, fs_passno=fs_passno)) for entry in self.get_cmd_output(['mount'], ' ', 6): name, _, mount, _, tp, options = entry result.mount.append(MountEntry( name=name, mount=mount, tp=tp, options=options)) for entry in self.get_cmd_output(['lsblk', '-r', '--noheadings'], ' ', 7): name, maj_min, rm, size, ro, tp, mountpoint = entry result.lsblk.append(LsblkEntry( name=name, maj_min=maj_min, rm=rm, size=size, ro=ro, tp=tp, mountpoint=mountpoint)) for entry in self.get_cmd_output(['pvs', '--noheadings', '--separator', r':'], ':', 6): pv, vg, fmt, attr, psize, pfree = entry result.pvs.append(PvsEntry( pv=pv, vg=vg, fmt=fmt, attr=attr, psize=psize, pfree=pfree)) for entry in self.get_cmd_output(['vgs', '--noheadings', '--separator', r':'], ':', 7): vg, pv, lv, sn, attr, vsize, vfree = entry result.vgs.append(VgsEntry( vg=vg, pv=pv, lv=lv, sn=sn, attr=attr, vsize=vsize, vfree=vfree)) for entry in self.get_cmd_output(['lvdisplay', '-C', '--noheadings', '--separator', r':'], ':', 12): lv, vg, attr, lsize, pool, origin, data, meta, move, log, cpy_sync, convert = entry result.lvdisplay.append(LvdisplayEntry( lv=lv, vg=vg, attr=attr, lsize=lsize, pool=pool, origin=origin, data=data, meta=meta, move=move, log=log, cpy_sync=cpy_sync, convert=convert)) for entry in self.get_cmd_output(['systemd-mount', '--list'], ' ', 7): # We need to filter the entry because there is a ton of whitespace. node, path, model, wwn, fs_type, label, uuid = list(filter(lambda x: x != '', entry)) if node == "NODE": # First row of the "systemd-mount --list" output is a header. # Just skip it. continue result.systemdmount.append(SystemdMountEntry( node=node, path=path, model=model, wwn=wwn, fs_type=fs_type, label=label, uuid=uuid)) self.produce(result)
def test_get_systemd_mount_info(monkeypatch): class UdevDeviceMocked(object): def __init__(self, device_node, path, model, wwn, fs_type, label, uuid): self.device_node = device_node # Simulate udev device attributes that should be queried self.device_attributes = { 'ID_PATH': path, 'ID_MODEL': model, 'ID_WWN': wwn, 'ID_FS_TYPE': fs_type, 'ID_FS_LABEL': label, 'ID_FS_UUID': uuid, } def get(self, attribute, default=None): if attribute not in self.device_attributes: raise KeyError( 'Actor tried to query an udev device attribute that is not a part of the mocks.' ) if self.device_attributes[attribute] is None: return default return self.device_attributes[attribute] class UdevContextMocked(object): def __init__(self, mocked_devices): self.mocked_devices = mocked_devices def list_devices(self, **dummy_kwargs): return self.mocked_devices mocked_block_devices = [ UdevDeviceMocked(device_node='/dev/dm-1', path=None, model=None, wwn=None, fs_type='ext4', label=None, uuid='bec30ca5-5403-4c23-ae6e-cb2a911bc076'), UdevDeviceMocked(device_node='/dev/dm-3', path=None, model=None, wwn=None, fs_type='ext4', label=None, uuid='d6eaf17d-e2a9-4e8d-bb54-a89c18923ea2'), UdevDeviceMocked(device_node='/dev/sda1', path='pci-0000:00:17.0-ata-2', model='LITEON_LCH-256V2S', wwn='0x5002303100d82b06', fs_type='ext4', label=None, uuid='c3890bf3-9273-4877-ad1f-68144e1eb858') ] # Partially apply mocked_block_devices to the UdevContextMocked, so that it # is OK to initialize it with no arguments (same as original Context) monkeypatch.setattr( pyudev, 'Context', functools.partial(UdevContextMocked, mocked_block_devices)) expected = [ SystemdMountEntry(node='/dev/dm-1', path='n/a', model='n/a', wwn='n/a', fs_type='ext4', label='n/a', uuid='bec30ca5-5403-4c23-ae6e-cb2a911bc076'), SystemdMountEntry(node='/dev/dm-3', path='n/a', model='n/a', wwn='n/a', fs_type='ext4', label='n/a', uuid='d6eaf17d-e2a9-4e8d-bb54-a89c18923ea2'), SystemdMountEntry(node='/dev/sda1', path='pci-0000:00:17.0-ata-2', model='LITEON_LCH-256V2S', wwn='0x5002303100d82b06', fs_type='ext4', label='n/a', uuid='c3890bf3-9273-4877-ad1f-68144e1eb858') ] assert expected == storagescanner._get_systemd_mount_info()