From 5a1e35224b82e8f0776dfea3d34bcb005195bbdb Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 14 Mar 2016 09:45:28 -0700 Subject: [PATCH] Make changes proposed during review of restrict fact gathering feature: * Make documentation examples into code blocks * Make code to call the subsets more general. * Made min subset always execute (cannot disable it). * Use a passed in modules parameter rather than global modules. This is needed for ziploader * Remove unneeded __init__() * Remove uneeded multiple inheritance from a base class * gather_facts is now a list type --- docsite/rst/intro_configuration.rst | 4 +- lib/ansible/module_utils/facts.py | 312 ++++++++++++---------------- lib/ansible/playbook/play.py | 2 +- 3 files changed, 131 insertions(+), 187 deletions(-) diff --git a/docsite/rst/intro_configuration.rst b/docsite/rst/intro_configuration.rst index ddcf673618..1f7c6ca313 100644 --- a/docsite/rst/intro_configuration.rst +++ b/docsite/rst/intro_configuration.rst @@ -355,7 +355,7 @@ This option can be useful for those wishing to save fact gathering time. Both 's .. versionadded:: 2.1 -You can specify a subset of gathered facts using the following options: +You can specify a subset of gathered facts using the following options:: gather_subset = all @@ -367,7 +367,7 @@ You can specify a subset of gathered facts using the following options: You can combine them using comma separated list (ex: min,network,virtual) -You can also disable puppet facter or chef ohai facts collection using following options: +You can also disable puppet facter or chef ohai facts collection using following options:: ignore_ohai = True ignore_facter = True diff --git a/lib/ansible/module_utils/facts.py b/lib/ansible/module_utils/facts.py index d683ee2a26..d38ce9207f 100644 --- a/lib/ansible/module_utils/facts.py +++ b/lib/ansible/module_utils/facts.py @@ -159,11 +159,9 @@ class Facts(object): { 'path' : '/usr/local/sbin/pkg', 'name' : 'pkgng' }, ] - # Allowed fact subset for gather_subset options - ALLOWED_FACT_SUBSET = frozenset([ 'all', 'min', 'network', 'hardware', 'virtual' ]) - - def __init__(self, load_on_init=True): + def __init__(self, module, load_on_init=True): + self.module = module self.facts = {} if load_on_init: @@ -218,14 +216,14 @@ class Facts(object): elif self.facts['system'] == 'AIX': # Attempt to use getconf to figure out architecture # fall back to bootinfo if needed - if module.get_bin_path('getconf'): - rc, out, err = module.run_command([module.get_bin_path('getconf'), - 'MACHINE_ARCHITECTURE']) + getconf_bin = self.module.get_bin_path('getconf') + if getconf_bin: + rc, out, err = self.module.run_command([getconf_bin, 'MACHINE_ARCHITECTURE']) data = out.split('\n') self.facts['architecture'] = data[0] else: - rc, out, err = module.run_command([module.get_bin_path('bootinfo'), - '-p']) + bootinfo_bin = self.module.get_bin_path('bootinfo') + rc, out, err = self.module.run_command([bootinfo_bin, '-p']) data = out.split('\n') self.facts['architecture'] = data[0] elif self.facts['system'] == 'OpenBSD': @@ -233,7 +231,7 @@ class Facts(object): def get_local_facts(self): - fact_path = module.params.get('fact_path', None) + fact_path = self.module.params.get('fact_path', None) if not fact_path or not os.path.exists(fact_path): return @@ -246,7 +244,7 @@ class Facts(object): # try to read it as json first # if that fails read it with ConfigParser # if that fails, skip it - rc, out, err = module.run_command(fn) + rc, out, err = self.module.run_command(fn) else: out = get_file_content(fn, default='') @@ -297,20 +295,20 @@ class Facts(object): # as it's much cleaner than this massive if-else if self.facts['system'] == 'AIX': self.facts['distribution'] = 'AIX' - rc, out, err = module.run_command("/usr/bin/oslevel") + rc, out, err = self.module.run_command("/usr/bin/oslevel") data = out.split('.') self.facts['distribution_version'] = data[0] self.facts['distribution_release'] = data[1] elif self.facts['system'] == 'HP-UX': self.facts['distribution'] = 'HP-UX' - rc, out, err = module.run_command("/usr/sbin/swlist |egrep 'HPUX.*OE.*[AB].[0-9]+\.[0-9]+'", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/sbin/swlist |egrep 'HPUX.*OE.*[AB].[0-9]+\.[0-9]+'", use_unsafe_shell=True) data = re.search('HPUX.*OE.*([AB].[0-9]+\.[0-9]+)\.([0-9]+).*', out) if data: self.facts['distribution_version'] = data.groups()[0] self.facts['distribution_release'] = data.groups()[1] elif self.facts['system'] == 'Darwin': self.facts['distribution'] = 'MacOSX' - rc, out, err = module.run_command("/usr/bin/sw_vers -productVersion") + rc, out, err = self.module.run_command("/usr/bin/sw_vers -productVersion") data = out.split()[-1] self.facts['distribution_version'] = data elif self.facts['system'] == 'FreeBSD': @@ -324,7 +322,7 @@ class Facts(object): elif self.facts['system'] == 'OpenBSD': self.facts['distribution'] = 'OpenBSD' self.facts['distribution_release'] = platform.release() - rc, out, err = module.run_command("/sbin/sysctl -n kern.version") + rc, out, err = self.module.run_command("/sbin/sysctl -n kern.version") match = re.match('OpenBSD\s[0-9]+.[0-9]+-(\S+)\s.*', out) if match: self.facts['distribution_version'] = match.groups()[0] @@ -414,7 +412,7 @@ class Facts(object): self.facts['distribution_release'] = ora_prefix + data break - uname_rc, uname_out, uname_err = module.run_command(['uname', '-v']) + uname_rc, uname_out, uname_err = self.module.run_command(['uname', '-v']) distribution_version = None if 'SmartOS' in data: self.facts['distribution'] = 'SmartOS' @@ -580,7 +578,7 @@ class Facts(object): # try various forms of querying pid 1 proc_1 = get_file_content('/proc/1/comm') if proc_1 is None: - rc, proc_1, err = module.run_command("ps -p 1 -o comm|tail -n 1", use_unsafe_shell=True) + rc, proc_1, err = self.module.run_command("ps -p 1 -o comm|tail -n 1", use_unsafe_shell=True) else: proc_1 = os.path.basename(proc_1) @@ -613,7 +611,7 @@ class Facts(object): elif self.facts['system'] == 'Linux': if self._check_systemd(): self.facts['service_mgr'] = 'systemd' - elif module.get_bin_path('initctl') and os.path.exists("/etc/init/"): + elif self.module.get_bin_path('initctl') and os.path.exists("/etc/init/"): self.facts['service_mgr'] = 'upstart' elif os.path.realpath('/sbin/rc') == '/sbin/openrc': self.facts['service_mgr'] = 'openrc' @@ -625,9 +623,9 @@ class Facts(object): self.facts['service_mgr'] = 'service' def get_lsb_facts(self): - lsb_path = module.get_bin_path('lsb_release') + lsb_path = self.module.get_bin_path('lsb_release') if lsb_path: - rc, out, err = module.run_command([lsb_path, "-a"]) + rc, out, err = self.module.run_command([lsb_path, "-a"]) if rc == 0: self.facts['lsb'] = {} for line in out.split('\n'): @@ -735,7 +733,7 @@ class Facts(object): def _check_systemd(self): # tools must be installed - if module.get_bin_path('systemctl'): + if self.module.get_bin_path('systemctl'): # this should show if systemd is the boot init system, if checking init faild to mark as systemd # these mirror systemd's own sd_boot test http://www.freedesktop.org/software/systemd/man/sd_booted.html @@ -845,9 +843,6 @@ class Hardware(Facts): subclass = sc return super(cls, subclass).__new__(subclass, *arguments, **keyword) - def __init__(self): - Facts.__init__(self) - def populate(self): return self.facts @@ -872,9 +867,6 @@ class LinuxHardware(Hardware): # Now we have all of these in a dict structure MEMORY_FACTS = ORIGINAL_MEMORY_FACTS.union(('Buffers', 'Cached', 'SwapCached')) - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1058,7 +1050,7 @@ class LinuxHardware(Hardware): else: # Fall back to using dmidecode, if available - dmi_bin = module.get_bin_path('dmidecode') + dmi_bin = self.module.get_bin_path('dmidecode') DMI_DICT = { 'bios_date': 'bios-release-date', 'bios_version': 'bios-version', @@ -1071,7 +1063,7 @@ class LinuxHardware(Hardware): } for (k, v) in DMI_DICT.items(): if dmi_bin is not None: - (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v)) + (rc, out, err) = self.module.run_command('%s -s %s' % (dmi_bin, v)) if rc == 0: # Strip out commented lines (specific dmidecode output) thisvalue = ''.join([ line for line in out.split('\n') if not line.startswith('#') ]) @@ -1100,9 +1092,9 @@ class LinuxHardware(Hardware): uuid = uuids[fields[0]] else: uuid = 'NA' - lsblkPath = module.get_bin_path("lsblk") + lsblkPath = self.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) + rc, out, err = self.module.run_command("%s -ln --output UUID %s" % (lsblkPath, fields[0]), use_unsafe_shell=True) if rc == 0: uuid = out.strip() @@ -1121,9 +1113,9 @@ class LinuxHardware(Hardware): def get_device_facts(self): self.facts['devices'] = {} - lspci = module.get_bin_path('lspci') + lspci = self.module.get_bin_path('lspci') if lspci: - rc, pcidata, err = module.run_command([lspci, '-D']) + rc, pcidata, err = self.module.run_command([lspci, '-D']) else: pcidata = None @@ -1176,7 +1168,7 @@ class LinuxHardware(Hardware): 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) - part['size'] = module.pretty_bytes((float(part['sectors']) * float(part['sectorsize']))) + part['size'] = self.module.pretty_bytes((float(part['sectors']) * float(part['sectorsize']))) d['partitions'][partname] = part d['rotational'] = get_file_content(sysdir + "/queue/rotational") @@ -1193,7 +1185,7 @@ class LinuxHardware(Hardware): d['sectorsize'] = get_file_content(sysdir + "/queue/logical_block_size") if not d['sectorsize']: d['sectorsize'] = get_file_content(sysdir + "/queue/hw_sector_size",512) - d['size'] = module.pretty_bytes(float(d['sectors']) * float(d['sectorsize'])) + d['size'] = self.module.pretty_bytes(float(d['sectors']) * float(d['sectorsize'])) d['host'] = "" @@ -1228,14 +1220,14 @@ class LinuxHardware(Hardware): def get_lvm_facts(self): """ Get LVM Facts if running as root and lvm utils are available """ - if os.getuid() == 0 and module.get_bin_path('vgs'): + if os.getuid() == 0 and self.module.get_bin_path('vgs'): lvm_util_options = '--noheadings --nosuffix --units g' - vgs_path = module.get_bin_path('vgs') + vgs_path = self.module.get_bin_path('vgs') #vgs fields: VG #PV #LV #SN Attr VSize VFree vgs={} if vgs_path: - rc, vg_lines, err = module.run_command( '%s %s' % (vgs_path, lvm_util_options)) + rc, vg_lines, err = self.module.run_command( '%s %s' % (vgs_path, lvm_util_options)) for vg_line in vg_lines.splitlines(): items = vg_line.split() vgs[items[0]] = {'size_g':items[-2], @@ -1243,12 +1235,12 @@ class LinuxHardware(Hardware): 'num_lvs': items[2], 'num_pvs': items[1]} - lvs_path = module.get_bin_path('lvs') + lvs_path = self.module.get_bin_path('lvs') #lvs fields: #LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert lvs = {} if lvs_path: - rc, lv_lines, err = module.run_command( '%s %s' % (lvs_path, lvm_util_options)) + rc, lv_lines, err = self.module.run_command( '%s %s' % (lvs_path, lvm_util_options)) for lv_line in lv_lines.splitlines(): items = lv_line.split() lvs[items[0]] = {'size_g': items[3], 'vg': items[1]} @@ -1263,9 +1255,6 @@ class SunOSHardware(Hardware): """ platform = 'SunOS' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1278,7 +1267,7 @@ class SunOSHardware(Hardware): def get_cpu_facts(self): physid = 0 sockets = {} - rc, out, err = module.run_command("/usr/bin/kstat cpu_info") + rc, out, err = self.module.run_command("/usr/bin/kstat cpu_info") self.facts['processor'] = [] for line in out.split('\n'): if len(line) < 1: @@ -1319,11 +1308,11 @@ class SunOSHardware(Hardware): self.facts['processor_count'] = len(self.facts['processor']) def get_memory_facts(self): - rc, out, err = module.run_command(["/usr/sbin/prtconf"]) + rc, out, err = self.module.run_command(["/usr/sbin/prtconf"]) for line in out.split('\n'): if 'Memory size' in line: self.facts['memtotal_mb'] = line.split()[2] - rc, out, err = module.run_command("/usr/sbin/swap -s") + rc, out, err = self.module.run_command("/usr/sbin/swap -s") allocated = long(out.split()[1][:-1]) reserved = long(out.split()[5][:-1]) used = long(out.split()[8][:-1]) @@ -1362,9 +1351,6 @@ class OpenBSDHardware(Hardware): platform = 'OpenBSD' DMESG_BOOT = '/var/run/dmesg.boot' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.sysctl = self.get_sysctl() self.get_memory_facts() @@ -1374,7 +1360,7 @@ class OpenBSDHardware(Hardware): return self.facts def get_sysctl(self): - rc, out, err = module.run_command(["/sbin/sysctl", "hw"]) + rc, out, err = self.module.run_command(["/sbin/sysctl", "hw"]) if rc != 0: return dict() sysctl = dict() @@ -1403,7 +1389,7 @@ class OpenBSDHardware(Hardware): # procs memory page disks traps cpu # r b w avm fre flt re pi po fr sr wd0 fd0 int sys cs us sy id # 0 0 0 47512 28160 51 0 0 0 0 0 1 0 116 89 17 0 1 99 - rc, out, err = module.run_command("/usr/bin/vmstat") + rc, out, err = self.module.run_command("/usr/bin/vmstat") if rc == 0: self.facts['memfree_mb'] = long(out.splitlines()[-1].split()[4]) / 1024 self.facts['memtotal_mb'] = long(self.sysctl['hw.usermem']) / 1024 / 1024 @@ -1412,7 +1398,7 @@ class OpenBSDHardware(Hardware): # total: 69268 1K-blocks allocated, 0 used, 69268 available # And for older OpenBSD: # total: 69268k bytes allocated = 0k used, 69268k available - rc, out, err = module.run_command("/sbin/swapctl -sk") + rc, out, err = self.module.run_command("/sbin/swapctl -sk") if rc == 0: swaptrans = maketrans(' ', ' ') data = out.split() @@ -1423,7 +1409,7 @@ class OpenBSDHardware(Hardware): processor = [] dmesg_boot = get_file_content(OpenBSDHardware.DMESG_BOOT) if not dmesg_boot: - rc, dmesg_boot, err = module.run_command("/sbin/dmesg") + rc, dmesg_boot, err = self.module.run_command("/sbin/dmesg") i = 0 for line in dmesg_boot.splitlines(): if line.split(' ', 1)[0] == 'cpu%i:' % i: @@ -1455,9 +1441,6 @@ class FreeBSDHardware(Hardware): platform = 'FreeBSD' DMESG_BOOT = '/var/run/dmesg.boot' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1471,12 +1454,12 @@ class FreeBSDHardware(Hardware): def get_cpu_facts(self): self.facts['processor'] = [] - rc, out, err = module.run_command("/sbin/sysctl -n hw.ncpu") + rc, out, err = self.module.run_command("/sbin/sysctl -n hw.ncpu") self.facts['processor_count'] = out.strip() dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT) if not dmesg_boot: - rc, dmesg_boot, err = module.run_command("/sbin/dmesg") + rc, dmesg_boot, err = self.module.run_command("/sbin/dmesg") for line in dmesg_boot.split('\n'): if 'CPU:' in line: cpu = re.sub(r'CPU:\s+', r"", line) @@ -1486,7 +1469,7 @@ class FreeBSDHardware(Hardware): def get_memory_facts(self): - rc, out, err = module.run_command("/sbin/sysctl vm.stats") + rc, out, err = self.module.run_command("/sbin/sysctl vm.stats") for line in out.split('\n'): data = line.split() if 'vm.stats.vm.v_page_size' in line: @@ -1501,7 +1484,7 @@ class FreeBSDHardware(Hardware): # Device 1M-blocks Used Avail Capacity # /dev/ada0p3 314368 0 314368 0% # - rc, out, err = module.run_command("/usr/sbin/swapinfo -k") + rc, out, err = self.module.run_command("/usr/sbin/swapinfo -k") lines = out.split('\n') if len(lines[-1]) == 0: lines.pop() @@ -1525,7 +1508,7 @@ class FreeBSDHardware(Hardware): def get_device_facts(self): sysdir = '/dev' self.facts['devices'] = {} - drives = re.compile('(ada?\d+|da\d+|a?cd\d+)') #TODO: rc, disks, err = module.run_command("/sbin/sysctl kern.disks") + drives = re.compile('(ada?\d+|da\d+|a?cd\d+)') #TODO: rc, disks, err = self.module.run_command("/sbin/sysctl kern.disks") slices = re.compile('(ada?\d+s\d+\w*|da\d+s\d+\w*)') if os.path.isdir(sysdir): dirlist = sorted(os.listdir(sysdir)) @@ -1543,7 +1526,7 @@ class FreeBSDHardware(Hardware): Use dmidecode executable if available''' # Fall back to using dmidecode, if available - dmi_bin = module.get_bin_path('dmidecode') + dmi_bin = self.module.get_bin_path('dmidecode') DMI_DICT = dict( bios_date='bios-release-date', bios_version='bios-version', @@ -1556,7 +1539,7 @@ class FreeBSDHardware(Hardware): ) for (k, v) in DMI_DICT.items(): if dmi_bin is not None: - (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v)) + (rc, out, err) = self.module.run_command('%s -s %s' % (dmi_bin, v)) if rc == 0: # Strip out commented lines (specific dmidecode output) self.facts[k] = ''.join([ line for line in out.split('\n') if not line.startswith('#') ]) @@ -1587,9 +1570,6 @@ class NetBSDHardware(Hardware): platform = 'NetBSD' MEMORY_FACTS = ['MemTotal', 'SwapTotal', 'MemFree', 'SwapFree'] - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1665,9 +1645,6 @@ class AIX(Hardware): """ platform = 'AIX' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1678,7 +1655,7 @@ class AIX(Hardware): self.facts['processor'] = [] - rc, out, err = module.run_command("/usr/sbin/lsdev -Cc processor") + rc, out, err = self.module.run_command("/usr/sbin/lsdev -Cc processor") if out: i = 0 for line in out.split('\n'): @@ -1691,19 +1668,19 @@ class AIX(Hardware): i += 1 self.facts['processor_count'] = int(i) - rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a type") + rc, out, err = self.module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a type") data = out.split(' ') self.facts['processor'] = data[1] - rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a smt_threads") + rc, out, err = self.module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a smt_threads") data = out.split(' ') self.facts['processor_cores'] = int(data[1]) def get_memory_facts(self): pagesize = 4096 - rc, out, err = module.run_command("/usr/bin/vmstat -v") + rc, out, err = self.module.run_command("/usr/bin/vmstat -v") for line in out.split('\n'): data = line.split() if 'memory pages' in line: @@ -1716,7 +1693,7 @@ class AIX(Hardware): # Device 1M-blocks Used Avail Capacity # /dev/ada0p3 314368 0 314368 0% # - rc, out, err = module.run_command("/usr/sbin/lsps -s") + rc, out, err = self.module.run_command("/usr/sbin/lsps -s") if out: lines = out.split('\n') data = lines[1].split() @@ -1726,7 +1703,7 @@ class AIX(Hardware): self.facts['swapfree_mb'] = long(swaptotal_mb * ( 100 - percused ) / 100) def get_dmi_facts(self): - rc, out, err = module.run_command("/usr/sbin/lsattr -El sys0 -a fwversion") + rc, out, err = self.module.run_command("/usr/sbin/lsattr -El sys0 -a fwversion") data = out.split() self.facts['firmware_version'] = data[1].strip('IBM,') @@ -1746,9 +1723,6 @@ class HPUX(Hardware): platform = 'HP-UX' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.get_cpu_facts() self.get_memory_facts() @@ -1757,31 +1731,31 @@ class HPUX(Hardware): def get_cpu_facts(self): if self.facts['architecture'] == '9000/800': - rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True) + rc, out, err = self.module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True) self.facts['processor_count'] = int(out.strip()) #Working with machinfo mess elif self.facts['architecture'] == 'ia64': if self.facts['distribution_version'] == "B.11.23": - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'Number of CPUs'", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep 'Number of CPUs'", use_unsafe_shell=True) self.facts['processor_count'] = int(out.strip().split('=')[1]) - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'processor family'", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep 'processor family'", use_unsafe_shell=True) self.facts['processor'] = re.search('.*(Intel.*)', out).groups()[0].strip() - rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True) + rc, out, err = self.module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True) self.facts['processor_cores'] = int(out.strip()) if self.facts['distribution_version'] == "B.11.31": #if machinfo return cores strings release B.11.31 > 1204 - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep core | wc -l", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep core | wc -l", use_unsafe_shell=True) if out.strip()== '0': - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True) self.facts['processor_count'] = int(out.strip().split(" ")[0]) #If hyperthreading is active divide cores by 2 - rc, out, err = module.run_command("/usr/sbin/psrset | grep LCPU", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/sbin/psrset | grep LCPU", use_unsafe_shell=True) data = re.sub(' +',' ',out).strip().split(' ') if len(data) == 1: hyperthreading = 'OFF' else: hyperthreading = data[1] - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep logical", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep logical", use_unsafe_shell=True) data = out.strip().split(" ") if hyperthreading == 'ON': self.facts['processor_cores'] = int(data[0])/2 @@ -1790,54 +1764,54 @@ class HPUX(Hardware): self.facts['processor_cores'] = self.facts['processor_count'] else: self.facts['processor_cores'] = int(data[0]) - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel |cut -d' ' -f4-", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep Intel |cut -d' ' -f4-", use_unsafe_shell=True) self.facts['processor'] = out.strip() else: - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | egrep 'socket[s]?$' | tail -1", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | egrep 'socket[s]?$' | tail -1", use_unsafe_shell=True) self.facts['processor_count'] = int(out.strip().split(" ")[0]) - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep -e '[0-9] core' | tail -1", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep -e '[0-9] core' | tail -1", use_unsafe_shell=True) self.facts['processor_cores'] = int(out.strip().split(" ")[0]) - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True) self.facts['processor'] = out.strip() def get_memory_facts(self): pagesize = 4096 - rc, out, err = module.run_command("/usr/bin/vmstat | tail -1", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/bin/vmstat | tail -1", use_unsafe_shell=True) data = int(re.sub(' +',' ',out).split(' ')[5].strip()) self.facts['memfree_mb'] = pagesize * data / 1024 / 1024 if self.facts['architecture'] == '9000/800': try: - rc, out, err = module.run_command("grep Physical /var/adm/syslog/syslog.log") + rc, out, err = self.module.run_command("grep Physical /var/adm/syslog/syslog.log") data = re.search('.*Physical: ([0-9]*) Kbytes.*',out).groups()[0].strip() self.facts['memtotal_mb'] = int(data) / 1024 except AttributeError: #For systems where memory details aren't sent to syslog or the log has rotated, use parsed #adb output. Unfortunately /dev/kmem doesn't have world-read, so this only works as root. if os.access("/dev/kmem", os.R_OK): - rc, out, err = module.run_command("echo 'phys_mem_pages/D' | adb -k /stand/vmunix /dev/kmem | tail -1 | awk '{print $2}'", use_unsafe_shell=True) + rc, out, err = self.module.run_command("echo 'phys_mem_pages/D' | adb -k /stand/vmunix /dev/kmem | tail -1 | awk '{print $2}'", use_unsafe_shell=True) if not err: data = out self.facts['memtotal_mb'] = int(data) / 256 else: - rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Memory", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo | grep Memory", use_unsafe_shell=True) data = re.search('Memory[\ :=]*([0-9]*).*MB.*',out).groups()[0].strip() self.facts['memtotal_mb'] = int(data) - rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f -q") + rc, out, err = self.module.run_command("/usr/sbin/swapinfo -m -d -f -q") self.facts['swaptotal_mb'] = int(out.strip()) - rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f | egrep '^dev|^fs'", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/sbin/swapinfo -m -d -f | egrep '^dev|^fs'", use_unsafe_shell=True) swap = 0 for line in out.strip().split('\n'): swap += int(re.sub(' +',' ',line).split(' ')[3].strip()) self.facts['swapfree_mb'] = swap def get_hw_facts(self): - rc, out, err = module.run_command("model") + rc, out, err = self.module.run_command("model") self.facts['model'] = out.strip() if self.facts['architecture'] == 'ia64': separator = ':' if self.facts['distribution_version'] == "B.11.23": separator = '=' - rc, out, err = module.run_command("/usr/contrib/bin/machinfo |grep -i 'Firmware revision' | grep -v BMC", use_unsafe_shell=True) + rc, out, err = self.module.run_command("/usr/contrib/bin/machinfo |grep -i 'Firmware revision' | grep -v BMC", use_unsafe_shell=True) self.facts['firmware_version'] = out.split(separator)[1].strip() @@ -1854,9 +1828,6 @@ class Darwin(Hardware): """ platform = 'Darwin' - def __init__(self): - Hardware.__init__(self) - def populate(self): self.sysctl = self.get_sysctl() self.get_mac_facts() @@ -1865,7 +1836,7 @@ class Darwin(Hardware): return self.facts def get_sysctl(self): - rc, out, err = module.run_command(["/usr/sbin/sysctl", "hw", "machdep", "kern"]) + rc, out, err = self.module.run_command(["/usr/sbin/sysctl", "hw", "machdep", "kern"]) if rc != 0: return dict() sysctl = dict() @@ -1876,7 +1847,7 @@ class Darwin(Hardware): return sysctl def get_system_profile(self): - rc, out, err = module.run_command(["/usr/sbin/system_profiler", "SPHardwareDataType"]) + rc, out, err = self.module.run_command(["/usr/sbin/system_profiler", "SPHardwareDataType"]) if rc != 0: return dict() system_profile = dict() @@ -1887,7 +1858,7 @@ class Darwin(Hardware): return system_profile def get_mac_facts(self): - rc, out, err = module.run_command("sysctl hw.model") + rc, out, err = self.module.run_command("sysctl hw.model") if rc == 0: self.facts['model'] = out.splitlines()[-1].split()[1] self.facts['osversion'] = self.sysctl['kern.osversion'] @@ -1905,7 +1876,7 @@ class Darwin(Hardware): def get_memory_facts(self): self.facts['memtotal_mb'] = long(self.sysctl['hw.memsize']) / 1024 / 1024 - rc, out, err = module.run_command("sysctl hw.usermem") + rc, out, err = self.module.run_command("sysctl hw.usermem") if rc == 0: self.facts['memfree_mb'] = long(out.splitlines()[-1].split()[1]) / 1024 / 1024 @@ -1936,10 +1907,6 @@ class Network(Facts): subclass = sc return super(cls, subclass).__new__(subclass, *arguments, **keyword) - def __init__(self, module): - self.module = module - Facts.__init__(self) - def populate(self): return self.facts @@ -1953,9 +1920,6 @@ class LinuxNetwork(Network): """ platform = 'Linux' - def __init__(self, module): - Network.__init__(self, module) - def populate(self): ip_path = self.module.get_bin_path('ip') if ip_path is None: @@ -1987,7 +1951,7 @@ class LinuxNetwork(Network): continue if v == 'v6' and not socket.has_ipv6: continue - rc, out, err = module.run_command(command[v]) + rc, out, err = self.module.run_command(command[v]) if not out: # v6 routing may result in # RTNETLINK answers: Invalid argument @@ -2147,7 +2111,7 @@ class LinuxNetwork(Network): if not address == '::1': ips['all_ipv6_addresses'].append(address) - ip_path = module.get_bin_path("ip") + ip_path = self.module.get_bin_path("ip") args = [ip_path, 'addr', 'show', 'primary', device] rc, stdout, stderr = self.module.run_command(args) @@ -2182,16 +2146,13 @@ class GenericBsdIfconfigNetwork(Network): """ platform = 'Generic_BSD_Ifconfig' - def __init__(self, module): - Network.__init__(self, module) - def populate(self): - ifconfig_path = module.get_bin_path('ifconfig') + ifconfig_path = self.module.get_bin_path('ifconfig') if ifconfig_path is None: return self.facts - route_path = module.get_bin_path('route') + route_path = self.module.get_bin_path('route') if route_path is None: return self.facts @@ -2230,7 +2191,7 @@ class GenericBsdIfconfigNetwork(Network): if v == 'v6' and not socket.has_ipv6: continue - rc, out, err = module.run_command(command[v]) + rc, out, err = self.module.run_command(command[v]) if not out: # v6 routing may result in # RTNETLINK answers: Invalid argument @@ -2257,7 +2218,7 @@ class GenericBsdIfconfigNetwork(Network): # FreeBSD, DragonflyBSD, NetBSD, OpenBSD and OS X all implicitly add '-a' # when running the command 'ifconfig'. # Solaris must explicitly run the command 'ifconfig -a'. - rc, out, err = module.run_command([ifconfig_path, ifconfig_options]) + rc, out, err = self.module.run_command([ifconfig_path, ifconfig_options]) for line in out.split('\n'): @@ -2403,9 +2364,6 @@ class HPUXNetwork(Network): """ platform = 'HP-UX' - def __init__(self, module): - Network.__init__(self, module) - def populate(self): netstat_path = self.module.get_bin_path('netstat') if netstat_path is None: @@ -2418,7 +2376,7 @@ class HPUXNetwork(Network): return self.facts def get_default_interfaces(self): - rc, out, err = module.run_command("/usr/bin/netstat -nr") + rc, out, err = self.module.run_command("/usr/bin/netstat -nr") lines = out.split('\n') for line in lines: words = line.split() @@ -2429,7 +2387,7 @@ class HPUXNetwork(Network): def get_interfaces_info(self): interfaces = {} - rc, out, err = module.run_command("/usr/bin/netstat -ni") + rc, out, err = self.module.run_command("/usr/bin/netstat -ni") lines = out.split('\n') for line in lines: words = line.split() @@ -2445,7 +2403,7 @@ class HPUXNetwork(Network): 'address': address } return interfaces -class DarwinNetwork(GenericBsdIfconfigNetwork, Network): +class DarwinNetwork(GenericBsdIfconfigNetwork): """ This is the Mac OS X/Darwin Network Class. It uses the GenericBsdIfconfigNetwork unchanged @@ -2469,21 +2427,21 @@ class DarwinNetwork(GenericBsdIfconfigNetwork, Network): current_if['media_options'] = self.get_options(words[3]) -class FreeBSDNetwork(GenericBsdIfconfigNetwork, Network): +class FreeBSDNetwork(GenericBsdIfconfigNetwork): """ This is the FreeBSD Network Class. It uses the GenericBsdIfconfigNetwork unchanged. """ platform = 'FreeBSD' -class DragonFlyNetwork(GenericBsdIfconfigNetwork, Network): +class DragonFlyNetwork(GenericBsdIfconfigNetwork): """ This is the DragonFly Network Class. It uses the GenericBsdIfconfigNetwork unchanged. """ platform = 'DragonFly' -class AIXNetwork(GenericBsdIfconfigNetwork, Network): +class AIXNetwork(GenericBsdIfconfigNetwork): """ This is the AIX Network Class. It uses the GenericBsdIfconfigNetwork unchanged. @@ -2491,9 +2449,9 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network): platform = 'AIX' def get_default_interfaces(self, route_path): - netstat_path = module.get_bin_path('netstat') + netstat_path = self.module.get_bin_path('netstat') - rc, out, err = module.run_command([netstat_path, '-nr']) + rc, out, err = self.module.run_command([netstat_path, '-nr']) interface = dict(v4 = {}, v6 = {}) @@ -2518,14 +2476,14 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network): all_ipv4_addresses = [], all_ipv6_addresses = [], ) - rc, out, err = module.run_command([ifconfig_path, ifconfig_options]) + rc, out, err = self.module.run_command([ifconfig_path, ifconfig_options]) for line in out.split('\n'): if line: words = line.split() - # only this condition differs from GenericBsdIfconfigNetwork + # only this condition differs from GenericBsdIfconfigNetwork if re.match('^\w*\d*:', line): current_if = self.parse_interface_line(words) interfaces[ current_if['device'] ] = current_if @@ -2547,16 +2505,16 @@ 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') + uname_path = self.module.get_bin_path('uname') if uname_path: - rc, out, err = module.run_command([uname_path, '-W']) + rc, out, err = self.module.run_command([uname_path, '-W']) # don't bother with wpars it does not work # zero means not in wpar if not rc and out.split()[0] == '0': if current_if['macaddress'] == 'unknown' and re.match('^en', current_if['device']): - entstat_path = module.get_bin_path('entstat') + entstat_path = self.module.get_bin_path('entstat') if entstat_path: - rc, out, err = module.run_command([entstat_path, current_if['device'] ]) + rc, out, err = self.module.run_command([entstat_path, current_if['device'] ]) if rc != 0: break for line in out.split('\n'): @@ -2571,9 +2529,9 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network): current_if['type'] = 'ether' # device must have mtu attribute in ODM if 'mtu' not in current_if: - lsattr_path = module.get_bin_path('lsattr') + lsattr_path = self.module.get_bin_path('lsattr') if lsattr_path: - rc, out, err = module.run_command([lsattr_path,'-El', current_if['device'] ]) + rc, out, err = self.module.run_command([lsattr_path,'-El', current_if['device'] ]) if rc != 0: break for line in out.split('\n'): @@ -2591,7 +2549,7 @@ class AIXNetwork(GenericBsdIfconfigNetwork, Network): current_if['macaddress'] = 'unknown' # will be overwritten later return current_if -class OpenBSDNetwork(GenericBsdIfconfigNetwork, Network): +class OpenBSDNetwork(GenericBsdIfconfigNetwork): """ This is the OpenBSD Network Class. It uses the GenericBsdIfconfigNetwork. @@ -2606,7 +2564,7 @@ class OpenBSDNetwork(GenericBsdIfconfigNetwork, Network): def parse_lladdr_line(self, words, current_if, ips): current_if['macaddress'] = words[1] -class SunOSNetwork(GenericBsdIfconfigNetwork, Network): +class SunOSNetwork(GenericBsdIfconfigNetwork): """ This is the SunOS Network Class. It uses the GenericBsdIfconfigNetwork. @@ -2627,7 +2585,7 @@ class SunOSNetwork(GenericBsdIfconfigNetwork, Network): all_ipv4_addresses = [], all_ipv6_addresses = [], ) - rc, out, err = module.run_command([ifconfig_path, '-a']) + rc, out, err = self.module.run_command([ifconfig_path, '-a']) for line in out.split('\n'): @@ -2711,9 +2669,6 @@ class Virtual(Facts): subclass = sc return super(cls, subclass).__new__(subclass, *arguments, **keyword) - def __init__(self): - Facts.__init__(self) - def populate(self): return self.facts @@ -2725,9 +2680,6 @@ class LinuxVirtual(Virtual): """ platform = 'Linux' - def __init__(self): - Virtual.__init__(self) - def populate(self): self.get_virtual_facts() return self.facts @@ -2844,9 +2796,9 @@ class LinuxVirtual(Virtual): self.facts['virtualization_type'] = 'powervm_lx86' elif re.match('^vendor_id.*IBM/S390', line): self.facts['virtualization_type'] = 'PR/SM' - lscpu = module.get_bin_path('lscpu') + lscpu = self.module.get_bin_path('lscpu') if lscpu: - rc, out, err = module.run_command(["lscpu"]) + rc, out, err = self.module.run_command(["lscpu"]) if rc == 0: for line in out.split("\n"): data = line.split(":", 1) @@ -2894,9 +2846,6 @@ class FreeBSDVirtual(Virtual): """ platform = 'FreeBSD' - def __init__(self): - Virtual.__init__(self) - def populate(self): self.get_virtual_facts() return self.facts @@ -2916,9 +2865,6 @@ class OpenBSDVirtual(Virtual): """ platform = 'OpenBSD' - def __init__(self): - Virtual.__init__(self) - def populate(self): self.get_virtual_facts() return self.facts @@ -2935,21 +2881,18 @@ class HPUXVirtual(Virtual): """ platform = 'HP-UX' - def __init__(self): - Virtual.__init__(self) - def populate(self): self.get_virtual_facts() return self.facts def get_virtual_facts(self): if os.path.exists('/usr/sbin/vecheck'): - rc, out, err = module.run_command("/usr/sbin/vecheck") + rc, out, err = self.module.run_command("/usr/sbin/vecheck") if rc == 0: self.facts['virtualization_type'] = 'guest' self.facts['virtualization_role'] = 'HP vPar' if os.path.exists('/opt/hpvm/bin/hpvminfo'): - rc, out, err = module.run_command("/opt/hpvm/bin/hpvminfo") + rc, out, err = self.module.run_command("/opt/hpvm/bin/hpvminfo") if rc == 0 and re.match('.*Running.*HPVM vPar.*', out): self.facts['virtualization_type'] = 'guest' self.facts['virtualization_role'] = 'HPVM vPar' @@ -2960,7 +2903,7 @@ class HPUXVirtual(Virtual): self.facts['virtualization_type'] = 'host' self.facts['virtualization_role'] = 'HPVM' if os.path.exists('/usr/sbin/parstatus'): - rc, out, err = module.run_command("/usr/sbin/parstatus") + rc, out, err = self.module.run_command("/usr/sbin/parstatus") if rc == 0: self.facts['virtualization_type'] = 'guest' self.facts['virtualization_role'] = 'HP nPar' @@ -2975,15 +2918,12 @@ class SunOSVirtual(Virtual): """ platform = 'SunOS' - def __init__(self): - Virtual.__init__(self) - def populate(self): self.get_virtual_facts() return self.facts def get_virtual_facts(self): - rc, out, err = module.run_command("/usr/sbin/prtdiag") + rc, out, err = self.module.run_command("/usr/sbin/prtdiag") for line in out.split('\n'): if 'VMware' in line: self.facts['virtualization_type'] = 'vmware' @@ -2999,7 +2939,7 @@ class SunOSVirtual(Virtual): self.facts['virtualization_role'] = 'guest' # Check if it's a zone if os.path.exists("/usr/bin/zonename"): - rc, out, err = module.run_command("/usr/bin/zonename") + rc, out, err = self.module.run_command("/usr/bin/zonename") if out.rstrip() != "global": self.facts['container'] = 'zone' # Check if it's a branded zone (i.e. Solaris 8/9 zone) @@ -3008,7 +2948,7 @@ class SunOSVirtual(Virtual): # If it's a zone check if we can detect if our global zone is itself virtualized. # Relies on the "guest tools" (e.g. vmware tools) to be installed if 'container' in self.facts and self.facts['container'] == 'zone': - rc, out, err = module.run_command("/usr/sbin/modinfo") + rc, out, err = self.module.run_command("/usr/sbin/modinfo") for line in out.split('\n'): if 'VMware' in line: self.facts['virtualization_type'] = 'vmware' @@ -3020,7 +2960,7 @@ class SunOSVirtual(Virtual): 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") + rc, out, err = self.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 formatted and the returncode is set to 0 regardless of the error condition: @@ -3071,28 +3011,24 @@ def get_file_lines(path): def ansible_facts(module): # Retrieve module parameters - gather_subset = [ 'all' ] + gather_subset = ('all',) if 'gather_subset' in module.params: gather_subset = module.params['gather_subset'] # Retrieve all facts elements if 'all' in gather_subset: - gather_subset = [ 'min', 'hardware', 'network', 'virtual' ] - - # Check subsets and forbid unallowed name - for subset in gather_subset: - if subset not in Facts.ALLOWED_FACT_SUBSET: - raise TypeError("Bad subset '%s' given to Ansible. gather_subset options allowed: %s" % (subset, ", ".join(Facts.ALLOWED_FACT_SUBSET))) + gather_subset = FACT_SUBSETS.keys() + else: + # Check subsets and forbid unallowed name + for subset in gather_subset: + if subset not in FACT_SUBSETS.keys(): + raise TypeError("Bad subset '%s' given to Ansible. gather_subset options allowed: all, %s" % (subset, ", ".join(FACT_SUBSETS.keys()))) facts = {} - facts.update(Facts().populate()) - if 'hardware' in gather_subset: - facts.update(Hardware().populate()) - if 'network' in gather_subset: - facts.update(Network(module).populate()) - if 'virtual' in gather_subset: - facts.update(Virtual().populate()) facts['gather_subset'] = gather_subset + facts.update(Facts(module).populate()) + for subset in gather_subset: + facts.update(FACT_SUBSETS[subset](module).populate()) return facts # =========================================== @@ -3153,3 +3089,11 @@ def get_all_facts(module): setup_result['_ansible_verbose_override'] = True return setup_result + +### Note: have to define this at the bottom as it references classes defined earlier in this file +# Allowed fact subset for gather_subset options and what classes they use +FACT_SUBSETS = dict( + hardware=Hardware, + network=Network, + virtual=Virtual, +) diff --git a/lib/ansible/playbook/play.py b/lib/ansible/playbook/play.py index c001419732..6be4c5367e 100644 --- a/lib/ansible/playbook/play.py +++ b/lib/ansible/playbook/play.py @@ -64,7 +64,7 @@ class Play(Base, Taggable, Become): # Connection _gather_facts = FieldAttribute(isa='bool', default=None, always_post_validate=True) - _gather_subset = FieldAttribute(isa='string', default=None, always_post_validate=True) + _gather_subset = FieldAttribute(isa='list', default=None, always_post_validate=True) _ignore_facter = FieldAttribute(isa='bool', default=None, always_post_validate=True) _ignore_ohai = FieldAttribute(isa='bool', default=None, always_post_validate=True) _hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True)