Fix parsing of device serial number for RHEL8 (#75876)

* Fix parsing of device serial number for RHEL8

* Add tests and changelog

Co-authored-by: Miroslav Brabenec <miroslav.brabenec@memsource.com>
pull/75930/head
Miroslav Brabenec 3 years ago committed by GitHub
parent 9a4346bae3
commit bc0caad2ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- ansible_facts.devices - Fix parsing of device serial number detected via sg_inq for rhel8 (https://github.com/ansible/ansible/issues/75420)

@ -649,6 +649,14 @@ class LinuxHardware(Hardware):
else:
block_dev_dict['holders'].append(folder)
def _get_sg_inq_serial(self, sg_inq, block):
device = "/dev/%s" % (block)
rc, drivedata, err = self.module.run_command([sg_inq, device])
if rc == 0:
serial = re.search(r"(?:Unit serial|Serial) number:\s+(\w+)", drivedata)
if serial:
return serial.group(1)
def get_device_facts(self):
device_facts = {}
@ -714,12 +722,9 @@ class LinuxHardware(Hardware):
serial_path = "/sys/block/%s/device/serial" % (block)
if sg_inq:
device = "/dev/%s" % (block)
rc, drivedata, err = self.module.run_command([sg_inq, device])
if rc == 0:
serial = re.search(r"Unit serial number:\s+(\w+)", drivedata)
serial = self._get_sg_inq_serial(sg_inq, block)
if serial:
d['serial'] = serial.group(1)
d['serial'] = serial
else:
serial = get_file_content(serial_path)
if serial:

@ -583,3 +583,51 @@ CPU_INFO_TEST_SCENARIOS = [
},
},
]
SG_INQ_OUTPUTS = ["""
Identify controller for /dev/nvme0n1:
Model number: Amazon Elastic Block Store
Serial number: vol0123456789
Firmware revision: 1.0
Version: 0.0
No optional admin command support
No optional NVM command support
PCI vendor ID VID/SSVID: 0x1d0f/0x1d0f
IEEE OUI Identifier: 0xa002dc
Controller ID: 0x0
Number of namespaces: 1
Maximum data transfer size: 64 pages
Namespace 1 (deduced from device name):
Namespace size/capacity: 62914560/62914560 blocks
Namespace utilization: 0 blocks
Number of LBA formats: 1
Index LBA size: 0
LBA format 0 support: <-- active
Logical block size: 512 bytes
Approximate namespace size: 32 GB
Metadata size: 0 bytes
Relative performance: Best [0x0]
""", """
Identify controller for /dev/nvme0n1:
Model number: Amazon Elastic Block Store
Unit serial number: vol0123456789
Firmware revision: 1.0
Version: 0.0
No optional admin command support
No optional NVM command support
PCI vendor ID VID/SSVID: 0x1d0f/0x1d0f
IEEE OUI Identifier: 0xa002dc
Controller ID: 0x0
Number of namespaces: 1
Maximum data transfer size: 64 pages
Namespace 1 (deduced from device name):
Namespace size/capacity: 62914560/62914560 blocks
Namespace utilization: 0 blocks
Number of LBA formats: 1
Index LBA size: 0
LBA format 0 support: <-- active
Logical block size: 512 bytes
Approximate namespace size: 32 GB
Metadata size: 0 bytes
Relative performance: Best [0x0]
"""]

@ -25,7 +25,7 @@ from ansible.module_utils.facts import timeout
from ansible.module_utils.facts.hardware import linux
from . linux_data import LSBLK_OUTPUT, LSBLK_OUTPUT_2, LSBLK_UUIDS, MTAB, MTAB_ENTRIES, BIND_MOUNTS, STATVFS_INFO, UDEVADM_UUID, UDEVADM_OUTPUT
from . linux_data import LSBLK_OUTPUT, LSBLK_OUTPUT_2, LSBLK_UUIDS, MTAB, MTAB_ENTRIES, BIND_MOUNTS, STATVFS_INFO, UDEVADM_UUID, UDEVADM_OUTPUT, SG_INQ_OUTPUTS
with open(os.path.join(os.path.dirname(__file__), '../fixtures/findmount_output.txt')) as f:
FINDMNT_OUTPUT = f.read()
@ -173,3 +173,26 @@ class TestFactsLinuxHardwareGetMountFacts(unittest.TestCase):
udevadm_uuid = lh._udevadm_uuid('mock_device')
self.assertEqual(udevadm_uuid, '57b1a3e7-9019-4747-9809-7ec52bba9179')
def test_get_sg_inq_serial(self):
# Valid outputs
for sq_inq_output in SG_INQ_OUTPUTS:
module = Mock()
module.run_command = Mock(return_value=(0, sq_inq_output, '')) # (rc, out, err)
lh = linux.LinuxHardware(module=module, load_on_init=False)
sg_inq_serial = lh._get_sg_inq_serial('/usr/bin/sg_inq', 'nvme0n1')
self.assertEqual(sg_inq_serial, 'vol0123456789')
# Invalid output
module = Mock()
module.run_command = Mock(return_value=(0, '', '')) # (rc, out, err)
lh = linux.LinuxHardware(module=module, load_on_init=False)
sg_inq_serial = lh._get_sg_inq_serial('/usr/bin/sg_inq', 'nvme0n1')
self.assertEqual(sg_inq_serial, None)
# Non zero rc
module = Mock()
module.run_command = Mock(return_value=(42, '', 'Error 42')) # (rc, out, err)
lh = linux.LinuxHardware(module=module, load_on_init=False)
sg_inq_serial = lh._get_sg_inq_serial('/usr/bin/sg_inq', 'nvme0n1')
self.assertEqual(sg_inq_serial, None)

Loading…
Cancel
Save