Add UUID, label and id links to devices when building facts (#25448)
At present, the available facts around block devices are not sufficient to be able to find stable names guaranteed to work across reboots, or to identify block devices by label (UUID, etc). This patch provides a list of observed links for each device. It relies on functionality specific to Linux (as does the existing sysfs-based code which it extends), but should not cause issues on other platforms. Moreover, it prevents virtual devices from being excluded, and links such devices to the physical devices to which they are attached.
This commit is contained in:
parent
56b7483b85
commit
d46dd99f47
1 changed files with 51 additions and 4 deletions
|
@ -16,12 +16,16 @@
|
|||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import collections
|
||||
import errno
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ansible.module_utils.six import iteritems
|
||||
|
||||
from ansible.module_utils.basic import bytes_to_human
|
||||
|
||||
from ansible.module_utils.facts.hardware.base import Hardware, HardwareCollector
|
||||
|
@ -449,6 +453,41 @@ class LinuxHardware(Hardware):
|
|||
|
||||
return mount_facts
|
||||
|
||||
def get_device_links(self, link_dir):
|
||||
if not os.path.exists(link_dir):
|
||||
return {}
|
||||
try:
|
||||
retval = collections.defaultdict(set)
|
||||
for entry in os.listdir(link_dir):
|
||||
try:
|
||||
target = os.path.basename(os.readlink(os.path.join(link_dir, entry)))
|
||||
retval[target].add(entry)
|
||||
except OSError:
|
||||
continue
|
||||
return dict((k, list(sorted(v))) for (k, v) in iteritems(retval))
|
||||
except OSError:
|
||||
return {}
|
||||
|
||||
def get_all_device_owners(self):
|
||||
try:
|
||||
retval = collections.defaultdict(set)
|
||||
for path in glob.glob('/sys/block/*/slaves/*'):
|
||||
elements = path.split('/')
|
||||
device = elements[3]
|
||||
target = elements[5]
|
||||
retval[target].add(device)
|
||||
return dict((k, list(sorted(v))) for (k, v) in iteritems(retval))
|
||||
except OSError:
|
||||
return {}
|
||||
|
||||
def get_all_device_links(self):
|
||||
return {
|
||||
'ids': self.get_device_links('/dev/disk/by-id'),
|
||||
'uuids': self.get_device_links('/dev/disk/by-uuid'),
|
||||
'labels': self.get_device_links('/dev/disk/by-label'),
|
||||
'masters': self.get_all_device_owners(),
|
||||
}
|
||||
|
||||
def get_holders(self, block_dev_dict, sysdir):
|
||||
block_dev_dict['holders'] = []
|
||||
if os.path.isdir(sysdir + "/holders"):
|
||||
|
@ -490,6 +529,9 @@ class LinuxHardware(Hardware):
|
|||
continue
|
||||
devs_wwn[os.path.basename(wwn_link)] = link_name[4:]
|
||||
|
||||
links = self.get_all_device_links()
|
||||
device_facts['device_links'] = links
|
||||
|
||||
for block in block_devs:
|
||||
virtual = 1
|
||||
sysfs_no_links = 0
|
||||
|
@ -502,17 +544,17 @@ class LinuxHardware(Hardware):
|
|||
sysfs_no_links = 1
|
||||
else:
|
||||
continue
|
||||
if "virtual" in path:
|
||||
continue
|
||||
sysdir = os.path.join("/sys/block", path)
|
||||
if sysfs_no_links == 1:
|
||||
for folder in os.listdir(sysdir):
|
||||
if "device" in folder:
|
||||
virtual = 0
|
||||
break
|
||||
if virtual:
|
||||
continue
|
||||
d = {}
|
||||
d['virtual'] = virtual
|
||||
d['links'] = {}
|
||||
for (link_type, link_values) in iteritems(links):
|
||||
d['links'][link_type] = link_values.get(block, [])
|
||||
diskname = os.path.basename(sysdir)
|
||||
for key in ['vendor', 'model', 'sas_address', 'sas_device_handle']:
|
||||
d[key] = get_file_content(sysdir + "/device/" + key)
|
||||
|
@ -546,8 +588,13 @@ class LinuxHardware(Hardware):
|
|||
partname = m.group(1)
|
||||
part_sysdir = sysdir + "/" + partname
|
||||
|
||||
part['links'] = {}
|
||||
for (link_type, link_values) in iteritems(links):
|
||||
part['links'][link_type] = link_values.get(partname, [])
|
||||
|
||||
part['start'] = get_file_content(part_sysdir + "/start", 0)
|
||||
part['sectors'] = get_file_content(part_sysdir + "/size", 0)
|
||||
|
||||
part['sectorsize'] = get_file_content(part_sysdir + "/queue/logical_block_size")
|
||||
if not part['sectorsize']:
|
||||
part['sectorsize'] = get_file_content(part_sysdir + "/queue/hw_sector_size", 512)
|
||||
|
|
Loading…
Reference in a new issue