Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mimic ceph-volume add device_id to inventory listing #25349

Merged
merged 2 commits into from Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/ceph-volume/ceph_volume/tests/util/test_disk.py
Expand Up @@ -45,6 +45,34 @@ def test_parses_translated(self, stub_call):
assert result['UUID'] == '62416664-cbaf-40bd-9689-10bd337379c3'
assert result['TYPE'] == 'xfs'

class TestUdevadmProperty(object):

def test_good_output(self, stub_call):
output = """ID_MODEL=SK_hynix_SC311_SATA_512GB
ID_PART_TABLE_TYPE=gpt
ID_SERIAL_SHORT=MS83N71801150416A""".split()
stub_call((output, [], 0))
result = disk.udevadm_property('dev/sda')
assert result['ID_MODEL'] == 'SK_hynix_SC311_SATA_512GB'
assert result['ID_PART_TABLE_TYPE'] == 'gpt'
assert result['ID_SERIAL_SHORT'] == 'MS83N71801150416A'

def test_property_filter(self, stub_call):
output = """ID_MODEL=SK_hynix_SC311_SATA_512GB
ID_PART_TABLE_TYPE=gpt
ID_SERIAL_SHORT=MS83N71801150416A""".split()
stub_call((output, [], 0))
result = disk.udevadm_property('dev/sda', ['ID_MODEL',
'ID_SERIAL_SHORT'])
assert result['ID_MODEL'] == 'SK_hynix_SC311_SATA_512GB'
assert 'ID_PART_TABLE_TYPE' not in result

def test_fail_on_broken_output(self, stub_call):
output = ["ID_MODEL:SK_hynix_SC311_SATA_512GB"]
stub_call((output, [], 0))
with pytest.raises(ValueError):
disk.udevadm_property('dev/sda')


class TestDeviceFamily(object):

Expand Down
17 changes: 17 additions & 0 deletions src/ceph-volume/ceph_volume/util/device.py
Expand Up @@ -79,6 +79,7 @@ def __init__(self, path):
self._is_lvm_member = None
self._parse()
self.available, self.rejected_reasons = self._check_reject_reasons()
self.device_id = self._get_device_id()

def __lt__(self, other):
'''
Expand Down Expand Up @@ -172,6 +173,22 @@ def json_report(self):
output['lvs'] = [lv.report() for lv in self.lvs]
return output

def _get_device_id(self):
props = ['ID_MODEL','ID_SERIAL_SHORT']
dev_id = disk.udevadm_property(self.abspath, props)
if all([prop in dev_id and dev_id[prop] for prop in props]):
values = [dev_id[prop].replace(' ', '_') for prop in props]
return '_'.join(values)
else:
# the else branch should fallback to using sysfs and ioctl to
# retrieve device_id on FreeBSD. Still figuring out if/how the
# python ioctl implementation does that on FreeBSD
return ''
return ''




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
Expand Down
41 changes: 41 additions & 0 deletions src/ceph-volume/ceph_volume/util/disk.py
Expand Up @@ -170,6 +170,47 @@ def device_family(device):
return devices


def udevadm_property(device, properties=[]):
"""
Query udevadm for information about device properties.
Optionally pass a list of properties to return. A requested property might
not be returned if not present.

Expected output format::
# udevadm info --query=property --name=/dev/sda :(
DEVNAME=/dev/sda
DEVTYPE=disk
ID_ATA=1
ID_BUS=ata
ID_MODEL=SK_hynix_SC311_SATA_512GB
ID_PART_TABLE_TYPE=gpt
ID_PART_TABLE_UUID=c8f91d57-b26c-4de1-8884-0c9541da288c
ID_PATH=pci-0000:00:17.0-ata-3
ID_PATH_TAG=pci-0000_00_17_0-ata-3
ID_REVISION=70000P10
ID_SERIAL=SK_hynix_SC311_SATA_512GB_MS83N71801150416A
TAGS=:systemd:
USEC_INITIALIZED=16117769
...
"""
out = _udevadm_info(device)
ret = {}
for line in out:
p, v = line.split('=', 1)
if not properties or p in properties:
ret[p] = v
return ret


def _udevadm_info(device):
"""
Call udevadm and return the output
"""
cmd = ['udevadm', 'info', '--query=property', device]
out, _err, _rc = process.call(cmd)
return out


def lsblk(device, columns=None, abspath=False):
"""
Create a dictionary of identifying values for a device using ``lsblk``.
Expand Down