return stat.S_ISBLK(stat_obj)
-def lsblk(device, columns=None):
+def _lsblk_parser(line):
+ """
+ Parses lines in lsblk output. Requires output to be in pair mode (``-P`` flag). Lines
+ need to be whole strings, the line gets split when processed.
+
+ :param line: A string, with the full line from lsblk output
+ """
+ # parse the COLUMN="value" output to construct the dictionary
+ pairs = line.split('" ')
+ parsed = {}
+ for pair in pairs:
+ try:
+ column, value = pair.split('=')
+ except ValueError:
+ continue
+ parsed[column] = value.strip().strip().strip('"')
+ return parsed
+
+
+def device_family(device):
+ """
+ Returns a list of associated devices. It assumes that ``device`` is
+ a parent device. It is up to the caller to ensure that the device being
+ used is a parent, not a partition.
+ """
+ labels = ['NAME', 'PARTLABEL', 'TYPE']
+ command = ['lsblk', '-P', '-p', '-o', ','.join(labels), device]
+ out, err, rc = process.call(command)
+ devices = []
+ for line in out:
+ devices.append(_lsblk_parser(line))
+
+ return devices
+
+
+def lsblk(device, columns=None, abspath=False):
"""
Create a dictionary of identifying values for a device using ``lsblk``.
Each supported column is a key, in its *raw* format (all uppercase
``lsblk`` versions. The newer versions support a richer set of columns,
while older ones were a bit limited.
- These are the default lsblk columns reported which are safe to use for
- Ubuntu 14.04.5 LTS:
+ These are a subset of lsblk columns which are known to work on both CentOS 7 and Xenial:
NAME device name
KNAME internal kernel device name
SCHED I/O scheduler name
RQ-SIZE request queue size
TYPE device type
+ PKNAME internal parent kernel device name
DISC-ALN discard alignment offset
DISC-GRAN discard granularity
DISC-MAX discard max bytes
NAME="sda1" KNAME="sda1" MAJ:MIN="8:1" FSTYPE="ext4" MOUNTPOINT="/"
:param columns: A list of columns to report as keys in its original form.
+ :param abspath: Set the flag for absolute paths on the report
"""
default_columns = [
'NAME', 'KNAME', 'MAJ:MIN', 'FSTYPE', 'MOUNTPOINT', 'LABEL', 'UUID',
'RO', 'RM', 'MODEL', 'SIZE', 'STATE', 'OWNER', 'GROUP', 'MODE',
'ALIGNMENT', 'PHY-SEC', 'LOG-SEC', 'ROTA', 'SCHED', 'TYPE', 'DISC-ALN',
- 'DISC-GRAN', 'DISC-MAX', 'DISC-ZERO'
+ 'DISC-GRAN', 'DISC-MAX', 'DISC-ZERO', 'PKNAME', 'PARTLABEL'
]
device = device.rstrip('/')
columns = columns or default_columns
# --nodeps -> Avoid adding children/parents to the device, only give information
# on the actual device we are querying for
# -P -> Produce pairs of COLUMN="value"
+ # -p -> Return full paths to devices, not just the names, when ``abspath`` is set
# -o -> Use the columns specified or default ones provided by this function
- command = ['lsblk', '--nodeps', '-P', '-o']
- command.append(','.join(columns))
- command.append(device)
- out, err, rc = process.call(command)
+ base_command = ['lsblk', '--nodeps', '-P']
+ if abspath:
+ base_command.append('-p')
+ base_command.append('-o')
+ base_command.append(','.join(columns))
+ base_command.append(device)
+ out, err, rc = process.call(base_command)
if rc != 0:
return {}
- # parse the COLUMN="value" output to construct the dictionary
- pairs = ' '.join(out).split()
- parsed = {}
- for pair in pairs:
- try:
- column, value = pair.split('=')
- except ValueError:
- continue
- parsed[column] = value.strip().strip().strip('"')
- return parsed
+ return _lsblk_parser(' '.join(out))
def _lsblk_type(device):