From 3a5263a92f01d486996e35f7ce05ddb1f1b79c9d Mon Sep 17 00:00:00 2001 From: Martin Krizek Date: Fri, 16 Feb 2018 16:52:51 +0100 Subject: [PATCH] facts: fix device uuid's on el6 (#36128) * facts: fix device uuid's on el6 Fixes #36077 --- .../module_utils/facts/hardware/linux.py | 32 ++++++++++++++++++- .../module_utils/facts/hardware/linux_data.py | 22 +++++++++++++ .../module_utils/facts/hardware/test_linux.py | 14 ++++++-- test/units/module_utils/facts/test_facts.py | 6 +++- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/lib/ansible/module_utils/facts/hardware/linux.py b/lib/ansible/module_utils/facts/hardware/linux.py index e781419d98..b758d11bf7 100644 --- a/lib/ansible/module_utils/facts/hardware/linux.py +++ b/lib/ansible/module_utils/facts/hardware/linux.py @@ -372,6 +372,31 @@ class LinuxHardware(Hardware): return uuids + def _udevadm_uuid(self, device): + # fallback for versions of lsblk <= 2.23 that don't have --paths, see _run_lsblk() above + uuid = 'N/A' + + udevadm_path = self.module.get_bin_path('udevadm') + if not udevadm_path: + return uuid + + cmd = [udevadm_path, 'info', '--query', 'property', '--name', device] + rc, out, err = self.module.run_command(cmd) + if rc != 0: + return uuid + + # a snippet of the output of the udevadm command below will be: + # ... + # ID_FS_TYPE=ext4 + # ID_FS_USAGE=filesystem + # ID_FS_UUID=57b1a3e7-9019-4747-9809-7ec52bba9179 + # ... + m = re.search('ID_FS_UUID=(.*)\n', out) + if m: + uuid = m.group(1) + + return uuid + def _run_findmnt(self, findmnt_path): args = ['--list', '--noheadings', '--notruncate'] cmd = [findmnt_path] + args @@ -442,11 +467,16 @@ class LinuxHardware(Hardware): if not self.MTAB_BIND_MOUNT_RE.match(options): options += ",bind" + # _udevadm_uuid is a fallback for versions of lsblk <= 2.23 that don't have --paths + # see _run_lsblk() above + # https://github.com/ansible/ansible/issues/36077 + uuid = uuids.get(device, self._udevadm_uuid(device)) + mount_info = {'mount': mount, 'device': device, 'fstype': fstype, 'options': options, - 'uuid': uuids.get(device, 'N/A')} + 'uuid': uuid} mount_info.update(mount_statvfs_info) diff --git a/test/units/module_utils/facts/hardware/linux_data.py b/test/units/module_utils/facts/hardware/linux_data.py index 61f0d0a511..f41c4d6f70 100644 --- a/test/units/module_utils/facts/hardware/linux_data.py +++ b/test/units/module_utils/facts/hardware/linux_data.py @@ -47,6 +47,28 @@ LSBLK_OUTPUT_2 = b""" LSBLK_UUIDS = {'/dev/sda1': '66Ojcd-ULtu-1cZa-Tywo-mx0d-RF4O-ysA9jK'} +UDEVADM_UUID = 'N/A' + +UDEVADM_OUTPUT = """ +UDEV_LOG=3 +DEVPATH=/devices/pci0000:00/0000:00:07.0/virtio2/block/vda/vda1 +MAJOR=252 +MINOR=1 +DEVNAME=/dev/vda1 +DEVTYPE=partition +SUBSYSTEM=block +MPATH_SBIN_PATH=/sbin +ID_PATH=pci-0000:00:07.0-virtio-pci-virtio2 +ID_PART_TABLE_TYPE=dos +ID_FS_UUID=57b1a3e7-9019-4747-9809-7ec52bba9179 +ID_FS_UUID_ENC=57b1a3e7-9019-4747-9809-7ec52bba9179 +ID_FS_VERSION=1.0 +ID_FS_TYPE=ext4 +ID_FS_USAGE=filesystem +LVM_SBIN_PATH=/sbin +DEVLINKS=/dev/block/252:1 /dev/disk/by-path/pci-0000:00:07.0-virtio-pci-virtio2-part1 /dev/disk/by-uuid/57b1a3e7-9019-4747-9809-7ec52bba9179 +""" + MTAB = """ sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 diff --git a/test/units/module_utils/facts/hardware/test_linux.py b/test/units/module_utils/facts/hardware/test_linux.py index b5dd81892c..f581c8068b 100644 --- a/test/units/module_utils/facts/hardware/test_linux.py +++ b/test/units/module_utils/facts/hardware/test_linux.py @@ -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 +from . linux_data import LSBLK_OUTPUT, LSBLK_OUTPUT_2, LSBLK_UUIDS, MTAB, MTAB_ENTRIES, BIND_MOUNTS, STATVFS_INFO, UDEVADM_UUID, UDEVADM_OUTPUT with open(os.path.join(os.path.dirname(__file__), '../fixtures/findmount_output.txt')) as f: FINDMNT_OUTPUT = f.read() @@ -50,11 +50,13 @@ class TestFactsLinuxHardwareGetMountFacts(unittest.TestCase): @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._find_bind_mounts', return_value=BIND_MOUNTS) @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._lsblk_uuid', return_value=LSBLK_UUIDS) @patch('ansible.module_utils.facts.hardware.linux.get_mount_size', side_effect=mock_get_mount_size) + @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._udevadm_uuid', return_value=UDEVADM_UUID) def test_get_mount_facts(self, mock_get_mount_size, mock_lsblk_uuid, mock_find_bind_mounts, - mock_mtab_entries): + mock_mtab_entries, + mock_udevadm_uuid): module = Mock() # Returns a LinuxHardware-ish lh = linux.LinuxHardware(module=module, load_on_init=False) @@ -162,3 +164,11 @@ class TestFactsLinuxHardwareGetMountFacts(unittest.TestCase): self.assertIn(b'/dev/sda1', lsblk_uuids) self.assertEqual(lsblk_uuids[b'/dev/mapper/an-example-mapper with a space in the name'], b'84639acb-013f-4d2f-9392-526a572b4373') self.assertEqual(lsblk_uuids[b'/dev/sda1'], b'32caaec3-ef40-4691-a3b6-438c3f9bc1c0') + + def test_udevadm_uuid(self): + module = Mock() + module.run_command = Mock(return_value=(0, UDEVADM_OUTPUT, '')) # (rc, out, err) + lh = linux.LinuxHardware(module=module, load_on_init=False) + udevadm_uuid = lh._udevadm_uuid('mock_device') + + self.assertEqual(udevadm_uuid, '57b1a3e7-9019-4747-9809-7ec52bba9179') diff --git a/test/units/module_utils/facts/test_facts.py b/test/units/module_utils/facts/test_facts.py index 7ee36ae210..d83058bb92 100644 --- a/test/units/module_utils/facts/test_facts.py +++ b/test/units/module_utils/facts/test_facts.py @@ -265,6 +265,8 @@ LSBLK_OUTPUT_2 = b""" LSBLK_UUIDS = {'/dev/sda1': '66Ojcd-ULtu-1cZa-Tywo-mx0d-RF4O-ysA9jK'} +UDEVADM_UUID = 'N/A' + MTAB = """ sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 @@ -536,10 +538,12 @@ class TestFactsLinuxHardwareGetMountFacts(unittest.TestCase): @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._mtab_entries', return_value=MTAB_ENTRIES) @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._find_bind_mounts', return_value=BIND_MOUNTS) @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._lsblk_uuid', return_value=LSBLK_UUIDS) + @patch('ansible.module_utils.facts.hardware.linux.LinuxHardware._udevadm_uuid', return_value=UDEVADM_UUID) def test_get_mount_facts(self, mock_lsblk_uuid, mock_find_bind_mounts, - mock_mtab_entries): + mock_mtab_entries, + mock_udevadm_uuid): module = Mock() # Returns a LinuxHardware-ish lh = hardware.linux.LinuxHardware(module=module, load_on_init=False)