mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Port some changes that occured on v1 get_facts modules to v2
-5c64956a7
Set distribution, release, and version for NetBSD -ec01e071d
adjusted for the possibility of lsblk not existing for fact gathering -d4eddabb2
Patch for bug #10485 - ansible_distribution fact populates as 'RedHat' on Oracle Linux systems -7813ffd71
Adding uptime_seconds fact for linux and darwin platforms -29cca0191
Adding oVirt recognition for oVirt guests. -d0197195e
Handle /etc/os-release files with 'Raspbian' in them -58a5f8dfa
Pulls machine id in ansible facts -1968f9969
Wrong OS_FAMILY declaration for openSUSE -5dec45e24
Fix wrong distribution facts on SLES/openSUSE and a few others
This commit is contained in:
parent
eae6005a89
commit
2a6a01e122
1 changed files with 170 additions and 29 deletions
|
@ -87,7 +87,8 @@ class Facts(object):
|
|||
_I386RE = re.compile(r'i([3456]86|86pc)')
|
||||
# For the most part, we assume that platform.dist() will tell the truth.
|
||||
# This is the fallback to handle unknowns or exceptions
|
||||
OSDIST_LIST = ( ('/etc/redhat-release', 'RedHat'),
|
||||
OSDIST_LIST = ( ('/etc/oracle-release', 'Oracle Linux'),
|
||||
('/etc/redhat-release', 'RedHat'),
|
||||
('/etc/vmware-release', 'VMwareESX'),
|
||||
('/etc/openwrt_release', 'OpenWrt'),
|
||||
('/etc/system-release', 'OtherLinux'),
|
||||
|
@ -170,9 +171,14 @@ class Facts(object):
|
|||
if self.facts['system'] == 'Linux':
|
||||
self.get_distribution_facts()
|
||||
elif self.facts['system'] == 'AIX':
|
||||
try:
|
||||
rc, out, err = module.run_command("/usr/sbin/bootinfo -p")
|
||||
data = out.split('\n')
|
||||
self.facts['architecture'] = data[0]
|
||||
except:
|
||||
self.facts['architecture'] = 'Not Available'
|
||||
elif self.facts['system'] == 'OpenBSD':
|
||||
self.facts['architecture'] = platform.uname()[5]
|
||||
|
||||
|
||||
def get_local_facts(self):
|
||||
|
@ -229,8 +235,8 @@ class Facts(object):
|
|||
RedHat = 'RedHat', Fedora = 'RedHat', CentOS = 'RedHat', Scientific = 'RedHat',
|
||||
SLC = 'RedHat', Ascendos = 'RedHat', CloudLinux = 'RedHat', PSBM = 'RedHat',
|
||||
OracleLinux = 'RedHat', OVS = 'RedHat', OEL = 'RedHat', Amazon = 'RedHat',
|
||||
XenServer = 'RedHat', Ubuntu = 'Debian', Debian = 'Debian', SLES = 'Suse',
|
||||
SLED = 'Suse', OpenSuSE = 'Suse', SuSE = 'Suse', Gentoo = 'Gentoo', Funtoo = 'Gentoo',
|
||||
XenServer = 'RedHat', Ubuntu = 'Debian', Debian = 'Debian', Raspbian = 'Debian', SLES = 'Suse',
|
||||
SLED = 'Suse', openSUSE = 'Suse', SuSE = 'Suse', Gentoo = 'Gentoo', Funtoo = 'Gentoo',
|
||||
Archlinux = 'Archlinux', Mandriva = 'Mandrake', Mandrake = 'Mandrake',
|
||||
Solaris = 'Solaris', Nexenta = 'Solaris', OmniOS = 'Solaris', OpenIndiana = 'Solaris',
|
||||
SmartOS = 'Solaris', AIX = 'AIX', Alpine = 'Alpine', MacOSX = 'Darwin',
|
||||
|
@ -261,6 +267,10 @@ class Facts(object):
|
|||
self.facts['distribution'] = 'FreeBSD'
|
||||
self.facts['distribution_release'] = platform.release()
|
||||
self.facts['distribution_version'] = platform.version()
|
||||
elif self.facts['system'] == 'NetBSD':
|
||||
self.facts['distribution'] = 'NetBSD'
|
||||
self.facts['distribution_release'] = platform.release()
|
||||
self.facts['distribution_version'] = platform.version()
|
||||
elif self.facts['system'] == 'OpenBSD':
|
||||
self.facts['distribution'] = 'OpenBSD'
|
||||
self.facts['distribution_release'] = platform.release()
|
||||
|
@ -284,6 +294,13 @@ class Facts(object):
|
|||
# Once we determine the value is one of these distros
|
||||
# we trust the values are always correct
|
||||
break
|
||||
elif name == 'Oracle Linux':
|
||||
data = get_file_content(path)
|
||||
if 'Oracle Linux' in data:
|
||||
self.facts['distribution'] = name
|
||||
else:
|
||||
self.facts['distribution'] = data.split()[0]
|
||||
break
|
||||
elif name == 'RedHat':
|
||||
data = get_file_content(path)
|
||||
if 'Red Hat' in data:
|
||||
|
@ -354,13 +371,27 @@ class Facts(object):
|
|||
data = get_file_content(path)
|
||||
if 'suse' in data.lower():
|
||||
if path == '/etc/os-release':
|
||||
release = re.search("PRETTY_NAME=[^(]+ \(?([^)]+?)\)", data)
|
||||
distdata = get_file_content(path).split('\n')[0]
|
||||
self.facts['distribution'] = distdata.split('=')[1]
|
||||
for line in data.splitlines():
|
||||
distribution = re.search("^NAME=(.*)", line)
|
||||
if distribution:
|
||||
self.facts['distribution'] = distribution.group(1).strip('"')
|
||||
distribution_version = re.search('^VERSION_ID="?([0-9]+\.?[0-9]*)"?', line) # example pattern are 13.04 13.0 13
|
||||
if distribution_version:
|
||||
self.facts['distribution_version'] = distribution_version.group(1)
|
||||
if 'open' in data.lower():
|
||||
release = re.search("^PRETTY_NAME=[^(]+ \(?([^)]+?)\)", line)
|
||||
if release:
|
||||
self.facts['distribution_release'] = release.groups()[0]
|
||||
elif 'enterprise' in data.lower():
|
||||
release = re.search('^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line) # SLES doesn't got funny release names
|
||||
if release:
|
||||
release = release.group(1)
|
||||
else:
|
||||
release = "0" # no minor number, so it is the first release
|
||||
self.facts['distribution_release'] = release
|
||||
break
|
||||
elif path == '/etc/SuSE-release':
|
||||
if 'open' in data.lower():
|
||||
data = data.splitlines()
|
||||
distdata = get_file_content(path).split('\n')[0]
|
||||
self.facts['distribution'] = distdata.split()[0]
|
||||
|
@ -368,10 +399,21 @@ class Facts(object):
|
|||
release = re.search('CODENAME *= *([^\n]+)', line)
|
||||
if release:
|
||||
self.facts['distribution_release'] = release.groups()[0].strip()
|
||||
break
|
||||
elif 'enterprise' in data.lower():
|
||||
lines = data.splitlines()
|
||||
distribution = lines[0].split()[0]
|
||||
if "Server" in data:
|
||||
self.facts['distribution'] = "SLES"
|
||||
elif "Desktop" in data:
|
||||
self.facts['distribution'] = "SLED"
|
||||
for line in lines:
|
||||
release = re.search('PATCHLEVEL = ([0-9]+)', line) # SLES doesn't got funny release names
|
||||
if release:
|
||||
self.facts['distribution_release'] = release.group(1)
|
||||
self.facts['distribution_version'] = self.facts['distribution_version'] + '.' + release.group(1)
|
||||
elif name == 'Debian':
|
||||
data = get_file_content(path)
|
||||
if 'Debian' in data:
|
||||
if 'Debian' in data or 'Raspbian' in data:
|
||||
release = re.search("PRETTY_NAME=[^(]+ \(?([^)]+?)\)", data)
|
||||
if release:
|
||||
self.facts['distribution_release'] = release.groups()[0]
|
||||
|
@ -403,7 +445,10 @@ class Facts(object):
|
|||
self.facts['distribution_release'] = release.group(1).strip('"')
|
||||
else:
|
||||
self.facts['distribution'] = name
|
||||
|
||||
machine_id = get_file_content("/var/lib/dbus/machine-id") or get_file_content("/etc/machine-id")
|
||||
if machine_id:
|
||||
machine_id = machine_id.split('\n')[0]
|
||||
self.facts["machine_id"] = machine_id
|
||||
self.facts['os_family'] = self.facts['distribution']
|
||||
if self.facts['distribution'] in OS_FAMILY:
|
||||
self.facts['os_family'] = OS_FAMILY[self.facts['distribution']]
|
||||
|
@ -462,7 +507,7 @@ class Facts(object):
|
|||
if rc == 0:
|
||||
self.facts['lsb'] = {}
|
||||
for line in out.split('\n'):
|
||||
if len(line) < 1:
|
||||
if len(line) < 1 or ':' not in line:
|
||||
continue
|
||||
value = line.split(':', 1)[1].strip()
|
||||
if 'LSB Version:' in line:
|
||||
|
@ -635,6 +680,7 @@ class LinuxHardware(Hardware):
|
|||
self.get_memory_facts()
|
||||
self.get_dmi_facts()
|
||||
self.get_device_facts()
|
||||
self.get_uptime_facts()
|
||||
try:
|
||||
self.get_mount_facts()
|
||||
except TimeoutError:
|
||||
|
@ -855,13 +901,14 @@ class LinuxHardware(Hardware):
|
|||
size_available = statvfs_result.f_bsize * (statvfs_result.f_bavail)
|
||||
except OSError, e:
|
||||
continue
|
||||
|
||||
uuid = 'NA'
|
||||
lsblkPath = module.get_bin_path("lsblk")
|
||||
if lsblkPath:
|
||||
rc, out, err = module.run_command("%s -ln --output UUID %s" % (lsblkPath, fields[0]), use_unsafe_shell=True)
|
||||
|
||||
if rc == 0:
|
||||
uuid = out.strip()
|
||||
else:
|
||||
uuid = 'NA'
|
||||
|
||||
self.facts['mounts'].append(
|
||||
{'mount': fields[1],
|
||||
|
@ -973,6 +1020,9 @@ class LinuxHardware(Hardware):
|
|||
|
||||
self.facts['devices'][diskname] = d
|
||||
|
||||
def get_uptime_facts(self):
|
||||
uptime_seconds_string = get_file_content('/proc/uptime').split(' ')[0]
|
||||
self.facts['uptime_seconds'] = int(float(uptime_seconds_string))
|
||||
|
||||
class SunOSHardware(Hardware):
|
||||
"""
|
||||
|
@ -987,6 +1037,10 @@ class SunOSHardware(Hardware):
|
|||
def populate(self):
|
||||
self.get_cpu_facts()
|
||||
self.get_memory_facts()
|
||||
try:
|
||||
self.get_mount_facts()
|
||||
except TimeoutError:
|
||||
pass
|
||||
return self.facts
|
||||
|
||||
def get_cpu_facts(self):
|
||||
|
@ -1047,6 +1101,17 @@ class SunOSHardware(Hardware):
|
|||
self.facts['swap_allocated_mb'] = allocated / 1024
|
||||
self.facts['swap_reserved_mb'] = reserved / 1024
|
||||
|
||||
@timeout(10)
|
||||
def get_mount_facts(self):
|
||||
self.facts['mounts'] = []
|
||||
# For a detailed format description see mnttab(4)
|
||||
# special mount_point fstype options time
|
||||
fstab = get_file_content('/etc/mnttab')
|
||||
if fstab:
|
||||
for line in fstab.split('\n'):
|
||||
fields = line.rstrip('\n').split('\t')
|
||||
self.facts['mounts'].append({'mount': fields[1], 'device': fields[0], 'fstype' : fields[2], 'options': fields[3], 'time': fields[4]})
|
||||
|
||||
class OpenBSDHardware(Hardware):
|
||||
"""
|
||||
OpenBSD-specific subclass of Hardware. Defines memory, CPU and device facts:
|
||||
|
@ -1071,6 +1136,7 @@ class OpenBSDHardware(Hardware):
|
|||
self.get_memory_facts()
|
||||
self.get_processor_facts()
|
||||
self.get_device_facts()
|
||||
self.get_mount_facts()
|
||||
return self.facts
|
||||
|
||||
def get_sysctl(self):
|
||||
|
@ -1083,6 +1149,19 @@ class OpenBSDHardware(Hardware):
|
|||
sysctl[key] = value.strip()
|
||||
return sysctl
|
||||
|
||||
@timeout(10)
|
||||
def get_mount_facts(self):
|
||||
self.facts['mounts'] = []
|
||||
fstab = get_file_content('/etc/fstab')
|
||||
if fstab:
|
||||
for line in fstab.split('\n'):
|
||||
if line.startswith('#') or line.strip() == '':
|
||||
continue
|
||||
fields = re.sub(r'\s+',' ',line.rstrip('\n')).split()
|
||||
if fields[1] == 'none' or fields[3] == 'xx':
|
||||
continue
|
||||
self.facts['mounts'].append({'mount': fields[1], 'device': fields[0], 'fstype' : fields[2], 'options': fields[3]})
|
||||
|
||||
def get_memory_facts(self):
|
||||
# Get free memory. vmstat output looks like:
|
||||
# procs memory page disks traps cpu
|
||||
|
@ -2133,7 +2212,40 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network):
|
|||
self.parse_inet6_line(words, current_if, ips)
|
||||
else:
|
||||
self.parse_unknown_line(words, current_if, ips)
|
||||
uname_path = module.get_bin_path('uname')
|
||||
if uname_path:
|
||||
rc, out, err = module.run_command([uname_path, '-W'])
|
||||
# don't bother with wpars it does not work
|
||||
# zero means not in wpar
|
||||
if out.split()[0] == '0':
|
||||
if current_if['macaddress'] == 'unknown' and re.match('^en', current_if['device']):
|
||||
entstat_path = module.get_bin_path('entstat')
|
||||
if entstat_path:
|
||||
rc, out, err = module.run_command([entstat_path, current_if['device'] ])
|
||||
if rc != 0:
|
||||
break
|
||||
for line in out.split('\n'):
|
||||
if not line:
|
||||
pass
|
||||
buff = re.match('^Hardware Address: (.*)', line)
|
||||
if buff:
|
||||
current_if['macaddress'] = buff.group(1)
|
||||
|
||||
buff = re.match('^Device Type:', line)
|
||||
if buff and re.match('.*Ethernet', line):
|
||||
current_if['type'] = 'ether'
|
||||
# device must have mtu attribute in ODM
|
||||
if 'mtu' not in current_if:
|
||||
lsattr_path = module.get_bin_path('lsattr')
|
||||
if lsattr_path:
|
||||
rc, out, err = module.run_command([lsattr_path,'-El', current_if['device'] ])
|
||||
if rc != 0:
|
||||
break
|
||||
for line in out.split('\n'):
|
||||
if line:
|
||||
words = line.split()
|
||||
if words[0] == 'mtu':
|
||||
current_if['mtu'] = words[1]
|
||||
return interfaces, ips
|
||||
|
||||
# AIX 'ifconfig -a' does not inform about MTU, so remove current_if['mtu'] here
|
||||
|
@ -2360,6 +2472,11 @@ class LinuxVirtual(Virtual):
|
|||
self.facts['virtualization_role'] = 'guest'
|
||||
return
|
||||
|
||||
if sys_vendor == 'oVirt':
|
||||
self.facts['virtualization_type'] = 'kvm'
|
||||
self.facts['virtualization_role'] = 'guest'
|
||||
return
|
||||
|
||||
if os.path.exists('/proc/self/status'):
|
||||
for line in get_file_lines('/proc/self/status'):
|
||||
if re.match('^VxID: \d+', line):
|
||||
|
@ -2514,6 +2631,30 @@ class SunOSVirtual(Virtual):
|
|||
if 'VirtualBox' in line:
|
||||
self.facts['virtualization_type'] = 'virtualbox'
|
||||
self.facts['virtualization_role'] = 'guest'
|
||||
# Detect domaining on Sparc hardware
|
||||
if os.path.exists("/usr/sbin/virtinfo"):
|
||||
# The output of virtinfo is different whether we are on a machine with logical
|
||||
# domains ('LDoms') on a T-series or domains ('Domains') on a M-series. Try LDoms first.
|
||||
rc, out, err = module.run_command("/usr/sbin/virtinfo -p")
|
||||
# The output contains multiple lines with different keys like this:
|
||||
# DOMAINROLE|impl=LDoms|control=false|io=false|service=false|root=false
|
||||
# The output may also be not formated and the returncode is set to 0 regardless of the error condition:
|
||||
# virtinfo can only be run from the global zone
|
||||
try:
|
||||
for line in out.split('\n'):
|
||||
fields = line.split('|')
|
||||
if( fields[0] == 'DOMAINROLE' and fields[1] == 'impl=LDoms' ):
|
||||
self.facts['virtualization_type'] = 'ldom'
|
||||
self.facts['virtualization_role'] = 'guest'
|
||||
hostfeatures = []
|
||||
for field in fields[2:]:
|
||||
arg = field.split('=')
|
||||
if( arg[1] == 'true' ):
|
||||
hostfeatures.append(arg[0])
|
||||
if( len(hostfeatures) > 0 ):
|
||||
self.facts['virtualization_role'] = 'host (' + ','.join(hostfeatures) + ')'
|
||||
except ValueError, e:
|
||||
pass
|
||||
|
||||
def get_file_content(path, default=None, strip=True):
|
||||
data = default
|
||||
|
|
Loading…
Reference in a new issue