View difference between Paste ID: UTjprw7D and fcnfQLMz
SHOW: | | - or go back to the newest paste.
1-
# (c) 2012, Michael DeHaan <[email protected]>
1+
# (c) 2012, Michael DeHaan <[email protected]>
2-
#
2+
#
3-
# This file is part of Ansible
3+
# This file is part of Ansible
4-
#
4+
#
5-
# Ansible is free software: you can redistribute it and/or modify
5+
# Ansible is free software: you can redistribute it and/or modify
6-
# it under the terms of the GNU General Public License as published by
6+
# it under the terms of the GNU General Public License as published by
7-
# the Free Software Foundation, either version 3 of the License, or
7+
# the Free Software Foundation, either version 3 of the License, or
8-
# (at your option) any later version.
8+
# (at your option) any later version.
9-
#
9+
#
10-
# Ansible is distributed in the hope that it will be useful,
10+
# Ansible is distributed in the hope that it will be useful,
11-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13-
# GNU General Public License for more details.
13+
# GNU General Public License for more details.
14-
#
14+
#
15-
# You should have received a copy of the GNU General Public License
15+
# You should have received a copy of the GNU General Public License
16-
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
16+
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17-
17+
18-
import os
18+
import os
19-
import array
19+
import array
20-
import errno
20+
import errno
21-
import fcntl
21+
import fcntl
22-
import fnmatch
22+
import fnmatch
23-
import glob
23+
import glob
24-
import platform
24+
import platform
25-
import re
25+
import re
26-
import signal
26+
import signal
27-
import socket
27+
import socket
28-
import struct
28+
import struct
29-
import datetime
29+
import datetime
30-
import getpass
30+
import getpass
31-
import ConfigParser
31+
import ConfigParser
32-
import StringIO
32+
import StringIO
33-
33+
34-
try:
34+
try:
35-
    import selinux
35+
    import selinux
36-
    HAVE_SELINUX=True
36+
    HAVE_SELINUX=True
37-
except ImportError:
37+
except ImportError:
38-
    HAVE_SELINUX=False
38+
    HAVE_SELINUX=False
39-
39+
40-
try:
40+
try:
41-
    import json
41+
    import json
42-
except ImportError:
42+
except ImportError:
43-
    import simplejson as json
43+
    import simplejson as json
44-
44+
45-
# --------------------------------------------------------------
45+
# --------------------------------------------------------------
46-
# timeout function to make sure some fact gathering 
46+
# timeout function to make sure some fact gathering 
47-
# steps do not exceed a time limit
47+
# steps do not exceed a time limit
48-
48+
49-
class TimeoutError(Exception):
49+
class TimeoutError(Exception):
50-
    pass
50+
    pass
51-
51+
52-
def timeout(seconds=10, error_message="Timer expired"):
52+
def timeout(seconds=10, error_message="Timer expired"):
53-
    def decorator(func):
53+
    def decorator(func):
54-
        def _handle_timeout(signum, frame):
54+
        def _handle_timeout(signum, frame):
55-
            raise TimeoutError(error_message)
55+
            raise TimeoutError(error_message)
56-
56+
57-
        def wrapper(*args, **kwargs):
57+
        def wrapper(*args, **kwargs):
58-
            signal.signal(signal.SIGALRM, _handle_timeout)
58+
            signal.signal(signal.SIGALRM, _handle_timeout)
59-
            signal.alarm(seconds)
59+
            signal.alarm(seconds)
60-
            try:
60+
            try:
61-
                result = func(*args, **kwargs)
61+
                result = func(*args, **kwargs)
62-
            finally:
62+
            finally:
63-
                signal.alarm(0)
63+
                signal.alarm(0)
64-
            return result
64+
            return result
65-
65+
66-
        return wrapper
66+
        return wrapper
67-
67+
68-
    return decorator
68+
    return decorator
69-
69+
70-
# --------------------------------------------------------------
70+
# --------------------------------------------------------------
71-
71+
72-
class Facts(object):
72+
class Facts(object):
73-
    """
73+
    """
74-
    This class should only attempt to populate those facts that
74+
    This class should only attempt to populate those facts that
75-
    are mostly generic to all systems.  This includes platform facts,
75+
    are mostly generic to all systems.  This includes platform facts,
76-
    service facts (eg. ssh keys or selinux), and distribution facts.
76+
    service facts (eg. ssh keys or selinux), and distribution facts.
77-
    Anything that requires extensive code or may have more than one
77+
    Anything that requires extensive code or may have more than one
78-
    possible implementation to establish facts for a given topic should
78+
    possible implementation to establish facts for a given topic should
79-
    subclass Facts.
79+
    subclass Facts.
80-
    """
80+
    """
81-
81+
82-
    _I386RE = re.compile(r'i[3456]86')
82+
    _I386RE = re.compile(r'i[3456]86')
83-
    # For the most part, we assume that platform.dist() will tell the truth.
83+
    # For the most part, we assume that platform.dist() will tell the truth.
84-
    # This is the fallback to handle unknowns or exceptions
84+
    # This is the fallback to handle unknowns or exceptions
85-
    OSDIST_DICT = { '/etc/redhat-release': 'RedHat',
85+
    OSDIST_DICT = { '/etc/redhat-release': 'RedHat',
86-
                    '/etc/vmware-release': 'VMwareESX',
86+
                    '/etc/vmware-release': 'VMwareESX',
87-
                    '/etc/openwrt_release': 'OpenWrt',
87+
                    '/etc/openwrt_release': 'OpenWrt',
88-
                    '/etc/system-release': 'OtherLinux',
88+
                    '/etc/system-release': 'OtherLinux',
89-
                    '/etc/alpine-release': 'Alpine',
89+
                    '/etc/alpine-release': 'Alpine',
90-
                    '/etc/release': 'Solaris',
90+
                    '/etc/release': 'Solaris',
91-
                    '/etc/arch-release': 'Archlinux',
91+
                    '/etc/arch-release': 'Archlinux',
92-
                    '/etc/SuSE-release': 'SuSE',
92+
                    '/etc/SuSE-release': 'SuSE',
93-
                    '/etc/gentoo-release': 'Gentoo',
93+
                    '/etc/gentoo-release': 'Gentoo',
94-
                    '/etc/os-release': 'Debian' }
94+
                    '/etc/os-release': 'Debian' }
95-
    SELINUX_MODE_DICT = { 1: 'enforcing', 0: 'permissive', -1: 'disabled' }
95+
    SELINUX_MODE_DICT = { 1: 'enforcing', 0: 'permissive', -1: 'disabled' }
96-
96+
97-
    # A list of dicts.  If there is a platform with more than one
97+
    # A list of dicts.  If there is a platform with more than one
98-
    # package manager, put the preferred one last.  If there is an
98+
    # package manager, put the preferred one last.  If there is an
99-
    # ansible module, use that as the value for the 'name' key.
99+
    # ansible module, use that as the value for the 'name' key.
100-
    PKG_MGRS = [ { 'path' : '/usr/bin/yum',         'name' : 'yum' },
100+
    PKG_MGRS = [ { 'path' : '/usr/bin/yum',         'name' : 'yum' },
101-
                 { 'path' : '/usr/bin/apt-get',     'name' : 'apt' },
101+
                 { 'path' : '/usr/bin/apt-get',     'name' : 'apt' },
102-
                 { 'path' : '/usr/bin/zypper',      'name' : 'zypper' },
102+
                 { 'path' : '/usr/bin/zypper',      'name' : 'zypper' },
103-
                 { 'path' : '/usr/sbin/urpmi',      'name' : 'urpmi' },
103+
                 { 'path' : '/usr/sbin/urpmi',      'name' : 'urpmi' },
104-
                 { 'path' : '/usr/bin/pacman',      'name' : 'pacman' },
104+
                 { 'path' : '/usr/bin/pacman',      'name' : 'pacman' },
105-
                 { 'path' : '/bin/opkg',            'name' : 'opkg' },
105+
                 { 'path' : '/bin/opkg',            'name' : 'opkg' },
106-
                 { 'path' : '/opt/local/bin/pkgin', 'name' : 'pkgin' },
106+
                 { 'path' : '/opt/local/bin/pkgin', 'name' : 'pkgin' },
107-
                 { 'path' : '/opt/local/bin/port',  'name' : 'macports' },
107+
                 { 'path' : '/opt/local/bin/port',  'name' : 'macports' },
108-
                 { 'path' : '/sbin/apk',            'name' : 'apk' },
108+
                 { 'path' : '/sbin/apk',            'name' : 'apk' },
109-
                 { 'path' : '/usr/sbin/pkg',        'name' : 'pkgng' },
109+
                 { 'path' : '/usr/sbin/pkg',        'name' : 'pkgng' },
110-
                 { 'path' : '/usr/sbin/swlist',     'name' : 'SD-UX' },
110+
                 { 'path' : '/usr/sbin/swlist',     'name' : 'SD-UX' },
111-
                 { 'path' : '/usr/bin/emerge',      'name' : 'portage' },
111+
                 { 'path' : '/usr/bin/emerge',      'name' : 'portage' },
112-
    ]
112+
    ]
113-
113+
114-
    def __init__(self):
114+
    def __init__(self):
115-
        self.facts = {}
115+
        self.facts = {}
116-
        self.get_platform_facts()
116+
        self.get_platform_facts()
117-
        self.get_distribution_facts()
117+
        self.get_distribution_facts()
118-
        self.get_cmdline()
118+
        self.get_cmdline()
119-
        self.get_public_ssh_host_keys()
119+
        self.get_public_ssh_host_keys()
120-
        self.get_selinux_facts()
120+
        self.get_selinux_facts()
121-
        self.get_pkg_mgr_facts()
121+
        self.get_pkg_mgr_facts()
122-
        self.get_lsb_facts()
122+
        self.get_lsb_facts()
123-
        self.get_date_time_facts()
123+
        self.get_date_time_facts()
124-
        self.get_user_facts()
124+
        self.get_user_facts()
125-
        self.get_local_facts()
125+
        self.get_local_facts()
126-
        self.get_env_facts()
126+
        self.get_env_facts()
127-
127+
128-
    def populate(self):
128+
    def populate(self):
129-
        return self.facts
129+
        return self.facts
130-
130+
131-
    # Platform
131+
    # Platform
132-
    # platform.system() can be Linux, Darwin, Java, or Windows
132+
    # platform.system() can be Linux, Darwin, Java, or Windows
133-
    def get_platform_facts(self):
133+
    def get_platform_facts(self):
134-
        self.facts['system'] = platform.system()
134+
        self.facts['system'] = platform.system()
135-
        self.facts['kernel'] = platform.release()
135+
        self.facts['kernel'] = platform.release()
136-
        self.facts['machine'] = platform.machine()
136+
        self.facts['machine'] = platform.machine()
137-
        self.facts['python_version'] = platform.python_version()
137+
        self.facts['python_version'] = platform.python_version()
138-
        self.facts['fqdn'] = socket.getfqdn()
138+
        self.facts['fqdn'] = socket.getfqdn()
139-
        self.facts['hostname'] = platform.node().split('.')[0]
139+
        self.facts['hostname'] = platform.node().split('.')[0]
140-
        self.facts['nodename'] = platform.node()
140+
        self.facts['nodename'] = platform.node()
141-
        self.facts['domain'] = '.'.join(self.facts['fqdn'].split('.')[1:])
141+
        self.facts['domain'] = '.'.join(self.facts['fqdn'].split('.')[1:])
142-
        arch_bits = platform.architecture()[0]
142+
        arch_bits = platform.architecture()[0]
143-
        self.facts['userspace_bits'] = arch_bits.replace('bit', '')
143+
        self.facts['userspace_bits'] = arch_bits.replace('bit', '')
144-
        if self.facts['machine'] == 'x86_64':
144+
        if self.facts['machine'] == 'x86_64':
145-
            self.facts['architecture'] = self.facts['machine']
145+
            self.facts['architecture'] = self.facts['machine']
146-
            if self.facts['userspace_bits'] == '64':
146+
            if self.facts['userspace_bits'] == '64':
147-
                self.facts['userspace_architecture'] = 'x86_64'
147+
                self.facts['userspace_architecture'] = 'x86_64'
148-
            elif self.facts['userspace_bits'] == '32':
148+
            elif self.facts['userspace_bits'] == '32':
149-
                self.facts['userspace_architecture'] = 'i386'
149+
                self.facts['userspace_architecture'] = 'i386'
150-
        elif Facts._I386RE.search(self.facts['machine']):
150+
        elif Facts._I386RE.search(self.facts['machine']):
151-
            self.facts['architecture'] = 'i386'
151+
            self.facts['architecture'] = 'i386'
152-
            if self.facts['userspace_bits'] == '64':
152+
            if self.facts['userspace_bits'] == '64':
153-
                self.facts['userspace_architecture'] = 'x86_64'
153+
                self.facts['userspace_architecture'] = 'x86_64'
154-
            elif self.facts['userspace_bits'] == '32':
154+
            elif self.facts['userspace_bits'] == '32':
155-
                self.facts['userspace_architecture'] = 'i386'
155+
                self.facts['userspace_architecture'] = 'i386'
156-
        else:
156+
        else:
157-
            self.facts['architecture'] = self.facts['machine']
157+
            self.facts['architecture'] = self.facts['machine']
158-
        if self.facts['system'] == 'Linux':
158+
        if self.facts['system'] == 'Linux':
159-
            self.get_distribution_facts()
159+
            self.get_distribution_facts()
160-
        elif self.facts['system'] == 'AIX':
160+
        elif self.facts['system'] == 'AIX':
161-
            rc, out, err = module.run_command("/usr/sbin/bootinfo -p")
161+
            rc, out, err = module.run_command("/usr/sbin/bootinfo -p")
162-
            data = out.split('\n')
162+
            data = out.split('\n')
163-
            self.facts['architecture'] = data[0]
163+
            self.facts['architecture'] = data[0]
164-
164+
165-
165+
166-
    def get_local_facts(self):
166+
    def get_local_facts(self):
167-
167+
168-
        fact_path = module.params.get('fact_path', None)
168+
        fact_path = module.params.get('fact_path', None)
169-
        if not fact_path or not os.path.exists(fact_path):
169+
        if not fact_path or not os.path.exists(fact_path):
170-
            return
170+
            return
171-
171+
172-
        local = {}
172+
        local = {}
173-
        for fn in sorted(glob.glob(fact_path + '/*.fact')):
173+
        for fn in sorted(glob.glob(fact_path + '/*.fact')):
174-
            # where it will sit under local facts
174+
            # where it will sit under local facts
175-
            fact_base = os.path.basename(fn).replace('.fact','')
175+
            fact_base = os.path.basename(fn).replace('.fact','')
176-
            if os.access(fn, os.X_OK):
176+
            if os.access(fn, os.X_OK):
177-
                # run it
177+
                # run it
178-
                # try to read it as json first
178+
                # try to read it as json first
179-
                # if that fails read it with ConfigParser
179+
                # if that fails read it with ConfigParser
180-
                # if that fails, skip it
180+
                # if that fails, skip it
181-
                rc, out, err = module.run_command(fn)
181+
                rc, out, err = module.run_command(fn)
182-
            else:
182+
            else:
183-
                out = open(fn).read()
183+
                out = open(fn).read()
184-
184+
185-
            # load raw json
185+
            # load raw json
186-
            fact = 'loading %s' % fact_base
186+
            fact = 'loading %s' % fact_base
187-
            try:
187+
            try:
188-
                fact = json.loads(out)
188+
                fact = json.loads(out)
189-
            except ValueError, e:
189+
            except ValueError, e:
190-
                # load raw ini
190+
                # load raw ini
191-
                cp = ConfigParser.ConfigParser()
191+
                cp = ConfigParser.ConfigParser()
192-
                try:
192+
                try:
193-
                    cp.readfp(StringIO.StringIO(out))
193+
                    cp.readfp(StringIO.StringIO(out))
194-
                except ConfigParser.Error, e:
194+
                except ConfigParser.Error, e:
195-
                    fact="error loading fact - please check content"
195+
                    fact="error loading fact - please check content"
196-
                else:
196+
                else:
197-
                    fact = {}
197+
                    fact = {}
198-
                    #print cp.sections()
198+
                    #print cp.sections()
199-
                    for sect in cp.sections():
199+
                    for sect in cp.sections():
200-
                        if sect not in fact:
200+
                        if sect not in fact:
201-
                            fact[sect] = {}
201+
                            fact[sect] = {}
202-
                        for opt in cp.options(sect):
202+
                        for opt in cp.options(sect):
203-
                            val = cp.get(sect, opt)
203+
                            val = cp.get(sect, opt)
204-
                            fact[sect][opt]=val
204+
                            fact[sect][opt]=val
205-
205+
206-
            local[fact_base] = fact
206+
            local[fact_base] = fact
207-
        if not local:
207+
        if not local:
208-
            return
208+
            return
209-
        self.facts['local'] = local
209+
        self.facts['local'] = local
210-
210+
211-
    # platform.dist() is deprecated in 2.6
211+
    # platform.dist() is deprecated in 2.6
212-
    # in 2.6 and newer, you should use platform.linux_distribution()
212+
    # in 2.6 and newer, you should use platform.linux_distribution()
213-
    def get_distribution_facts(self):
213+
    def get_distribution_facts(self):
214-
214+
215-
        # A list with OS Family members
215+
        # A list with OS Family members
216-
        OS_FAMILY = dict(
216+
        OS_FAMILY = dict(
217-
            RedHat = 'RedHat', Fedora = 'RedHat', CentOS = 'RedHat', Scientific = 'RedHat',
217+
            RedHat = 'RedHat', Fedora = 'RedHat', CentOS = 'RedHat', Scientific = 'RedHat',
218-
            SLC = 'RedHat', Ascendos = 'RedHat', CloudLinux = 'RedHat', PSBM = 'RedHat',
218+
            SLC = 'RedHat', Ascendos = 'RedHat', CloudLinux = 'RedHat', PSBM = 'RedHat',
219-
            OracleLinux = 'RedHat', OVS = 'RedHat', OEL = 'RedHat', Amazon = 'RedHat',
219+
            OracleLinux = 'RedHat', OVS = 'RedHat', OEL = 'RedHat', Amazon = 'RedHat',
220-
            XenServer = 'RedHat', Ubuntu = 'Debian', Debian = 'Debian', SLES = 'Suse',
220+
            XenServer = 'RedHat', Ubuntu = 'Debian', Debian = 'Debian', SLES = 'Suse',
221-
            SLED = 'Suse', OpenSuSE = 'Suse', SuSE = 'Suse', Gentoo = 'Gentoo', Funtoo = 'Gentoo',
221+
            SLED = 'Suse', OpenSuSE = 'Suse', SuSE = 'Suse', Gentoo = 'Gentoo', Funtoo = 'Gentoo',
222-
            Archlinux = 'Archlinux', Mandriva = 'Mandrake', Mandrake = 'Mandrake',
222+
            Archlinux = 'Archlinux', Mandriva = 'Mandrake', Mandrake = 'Mandrake',
223-
            Solaris = 'Solaris', Nexenta = 'Solaris', OmniOS = 'Solaris', OpenIndiana = 'Solaris',
223+
            Solaris = 'Solaris', Nexenta = 'Solaris', OmniOS = 'Solaris', OpenIndiana = 'Solaris',
224-
            SmartOS = 'Solaris', AIX = 'AIX', Alpine = 'Alpine', MacOSX = 'Darwin',
224+
            SmartOS = 'Solaris', AIX = 'AIX', Alpine = 'Alpine', MacOSX = 'Darwin',
225-
            FreeBSD = 'FreeBSD', HPUX = 'HP-UX'
225+
            FreeBSD = 'FreeBSD', HPUX = 'HP-UX'
226-
        )
226+
        )
227-
227+
228-
        if self.facts['system'] == 'AIX':
228+
        if self.facts['system'] == 'AIX':
229-
            self.facts['distribution'] = 'AIX'
229+
            self.facts['distribution'] = 'AIX'
230-
            rc, out, err = module.run_command("/usr/bin/oslevel")
230+
            rc, out, err = module.run_command("/usr/bin/oslevel")
231-
            data = out.split('.')
231+
            data = out.split('.')
232-
            self.facts['distribution_version'] = data[0]
232+
            self.facts['distribution_version'] = data[0]
233-
            self.facts['distribution_release'] = data[1]
233+
            self.facts['distribution_release'] = data[1]
234-
        elif self.facts['system'] == 'HP-UX':
234+
        elif self.facts['system'] == 'HP-UX':
235-
            self.facts['distribution'] = 'HP-UX'
235+
            self.facts['distribution'] = 'HP-UX'
236-
            rc, out, err = module.run_command("/usr/sbin/swlist |egrep 'HPUX.*OE.*[AB].[0-9]+\.[0-9]+'", use_unsafe_shell=True)
236+
            rc, out, err = module.run_command("/usr/sbin/swlist |egrep 'HPUX.*OE.*[AB].[0-9]+\.[0-9]+'", use_unsafe_shell=True)
237-
            data = re.search('HPUX.*OE.*([AB].[0-9]+\.[0-9]+)\.([0-9]+).*', out)
237+
            data = re.search('HPUX.*OE.*([AB].[0-9]+\.[0-9]+)\.([0-9]+).*', out)
238-
            if data:
238+
            if data:
239-
                self.facts['distribution_version'] = data.groups()[0]
239+
                self.facts['distribution_version'] = data.groups()[0]
240-
                self.facts['distribution_release'] = data.groups()[1]
240+
                self.facts['distribution_release'] = data.groups()[1]
241-
        elif self.facts['system'] == 'Darwin':
241+
        elif self.facts['system'] == 'Darwin':
242-
            self.facts['distribution'] = 'MacOSX'
242+
            self.facts['distribution'] = 'MacOSX'
243-
            rc, out, err = module.run_command("/usr/bin/sw_vers -productVersion")
243+
            rc, out, err = module.run_command("/usr/bin/sw_vers -productVersion")
244-
            data = out.split()[-1]
244+
            data = out.split()[-1]
245-
            self.facts['distribution_version'] = data
245+
            self.facts['distribution_version'] = data
246-
        elif self.facts['system'] == 'FreeBSD':
246+
        elif self.facts['system'] == 'FreeBSD':
247-
            self.facts['distribution'] = 'FreeBSD'
247+
            self.facts['distribution'] = 'FreeBSD'
248-
            self.facts['distribution_release'] = platform.release()
248+
            self.facts['distribution_release'] = platform.release()
249-
            self.facts['distribution_version'] = platform.version()
249+
            self.facts['distribution_version'] = platform.version()
250-
        elif self.facts['system'] == 'OpenBSD':
250+
        elif self.facts['system'] == 'OpenBSD':
251-
            self.facts['distribution'] = 'OpenBSD'
251+
            self.facts['distribution'] = 'OpenBSD'
252-
            self.facts['distribution_release'] = platform.release()
252+
            self.facts['distribution_release'] = platform.release()
253-
            rc, out, err = module.run_command("/sbin/sysctl -n kern.version")
253+
            rc, out, err = module.run_command("/sbin/sysctl -n kern.version")
254-
            match = re.match('OpenBSD\s[0-9]+.[0-9]+-(\S+)\s.*', out)
254+
            match = re.match('OpenBSD\s[0-9]+.[0-9]+-(\S+)\s.*', out)
255-
            if match:
255+
            if match:
256-
                self.facts['distribution_version'] = match.groups()[0]
256+
                self.facts['distribution_version'] = match.groups()[0]
257-
            else:
257+
            else:
258-
                self.facts['distribution_version'] = 'release'
258+
                self.facts['distribution_version'] = 'release'
259-
        else:
259+
        else:
260-
            dist = platform.dist()
260+
            dist = platform.dist()
261-
            self.facts['distribution'] = dist[0].capitalize() or 'NA'
261+
            self.facts['distribution'] = dist[0].capitalize() or 'NA'
262-
            self.facts['distribution_version'] = dist[1] or 'NA'
262+
            self.facts['distribution_version'] = dist[1] or 'NA'
263-
            self.facts['distribution_major_version'] = dist[1].split('.')[0] or 'NA'
263+
            self.facts['distribution_major_version'] = dist[1].split('.')[0] or 'NA'
264-
            self.facts['distribution_release'] = dist[2] or 'NA'
264+
            self.facts['distribution_release'] = dist[2] or 'NA'
265-
            # Try to handle the exceptions now ...
265+
            # Try to handle the exceptions now ...
266-
            for (path, name) in Facts.OSDIST_DICT.items():
266+
            for (path, name) in Facts.OSDIST_DICT.items():
267-
                if os.path.exists(path):
267+
                if os.path.exists(path):
268-
                    if self.facts['distribution'] == 'Fedora':
268+
                    if self.facts['distribution'] == 'Fedora':
269-
                        pass
269+
                        pass
270-
                    elif name == 'RedHat':
270+
                    elif name == 'RedHat':
271-
                        data = get_file_content(path)
271+
                        data = get_file_content(path)
272-
                        if 'Red Hat' in data:
272+
                        if 'Red Hat' in data:
273-
                            self.facts['distribution'] = name
273+
                            self.facts['distribution'] = name
274-
                        else:
274+
                        else:
275-
                            self.facts['distribution'] = data.split()[0]
275+
                            self.facts['distribution'] = data.split()[0]
276-
                    elif name == 'OtherLinux':
276+
                    elif name == 'OtherLinux':
277-
                        data = get_file_content(path)
277+
                        data = get_file_content(path)
278-
                        if 'Amazon' in data:
278+
                        if 'Amazon' in data:
279-
                            self.facts['distribution'] = 'Amazon'
279+
                            self.facts['distribution'] = 'Amazon'
280-
                            self.facts['distribution_version'] = data.split()[-1]
280+
                            self.facts['distribution_version'] = data.split()[-1]
281-
                    elif name == 'OpenWrt':
281+
                    elif name == 'OpenWrt':
282-
                        data = get_file_content(path)
282+
                        data = get_file_content(path)
283-
                        if 'OpenWrt' in data:
283+
                        if 'OpenWrt' in data:
284-
                            self.facts['distribution'] = name
284+
                            self.facts['distribution'] = name
285-
                        version = re.search('DISTRIB_RELEASE="(.*)"', data)
285+
                        version = re.search('DISTRIB_RELEASE="(.*)"', data)
286-
                        if version:
286+
                        if version:
287-
                            self.facts['distribution_version'] = version.groups()[0]
287+
                            self.facts['distribution_version'] = version.groups()[0]
288-
                        release = re.search('DISTRIB_CODENAME="(.*)"', data)
288+
                        release = re.search('DISTRIB_CODENAME="(.*)"', data)
289-
                        if release:
289+
                        if release:
290-
                            self.facts['distribution_release'] = release.groups()[0]
290+
                            self.facts['distribution_release'] = release.groups()[0]
291-
                    elif name == 'Alpine':
291+
                    elif name == 'Alpine':
292-
                        data = get_file_content(path)
292+
                        data = get_file_content(path)
293-
                        self.facts['distribution'] = 'Alpine'
293+
                        self.facts['distribution'] = 'Alpine'
294-
                        self.facts['distribution_version'] = data
294+
                        self.facts['distribution_version'] = data
295-
                    elif name == 'Solaris':
295+
                    elif name == 'Solaris':
296-
                        data = get_file_content(path).split('\n')[0]
296+
                        data = get_file_content(path).split('\n')[0]
297-
                        ora_prefix = ''
297+
                        ora_prefix = ''
298-
                        if 'Oracle Solaris' in data:
298+
                        if 'Oracle Solaris' in data:
299-
                            data = data.replace('Oracle ','')
299+
                            data = data.replace('Oracle ','')
300-
                            ora_prefix = 'Oracle '
300+
                            ora_prefix = 'Oracle '
301-
                        self.facts['distribution'] = data.split()[0]
301+
                        self.facts['distribution'] = data.split()[0]
302-
                        self.facts['distribution_version'] = data.split()[1]
302+
                        self.facts['distribution_version'] = data.split()[1]
303-
                        self.facts['distribution_release'] = ora_prefix + data
303+
                        self.facts['distribution_release'] = ora_prefix + data
304-
                    elif name == 'SuSE':
304+
                    elif name == 'SuSE':
305-
                        data = get_file_content(path).splitlines()
305+
                        data = get_file_content(path).splitlines()
306-
                        for line in data:
306+
                        for line in data:
307-
                            if '=' in line:
307+
                            if '=' in line:
308-
                            	self.facts['distribution_release'] = line.split('=')[1].strip()
308+
                            	self.facts['distribution_release'] = line.split('=')[1].strip()
309-
                    elif name == 'Debian':
309+
                    elif name == 'Debian':
310-
                        data = get_file_content(path).split('\n')[0]
310+
                        data = get_file_content(path).split('\n')[0]
311-
                        release = re.search("PRETTY_NAME.+ \(?([^ ]+?)\)?\"", data)
311+
                        release = re.search("PRETTY_NAME.+ \(?([^ ]+?)\)?\"", data)
312-
                        if release:
312+
                        if release:
313-
                            self.facts['distribution_release'] = release.groups()[0]
313+
                            self.facts['distribution_release'] = release.groups()[0]
314-
                    else:
314+
                    else:
315-
                        self.facts['distribution'] = name
315+
                        self.facts['distribution'] = name
316-
316+
317-
        self.facts['os_family'] = self.facts['distribution']
317+
        self.facts['os_family'] = self.facts['distribution']
318-
        if self.facts['distribution'] in OS_FAMILY:
318+
        if self.facts['distribution'] in OS_FAMILY:
319-
            self.facts['os_family'] = OS_FAMILY[self.facts['distribution']]
319+
            self.facts['os_family'] = OS_FAMILY[self.facts['distribution']]
320-
320+
321-
    def get_cmdline(self):
321+
    def get_cmdline(self):
322-
        data = get_file_content('/proc/cmdline')
322+
        data = get_file_content('/proc/cmdline')
323-
        if data:
323+
        if data:
324-
            self.facts['cmdline'] = {}
324+
            self.facts['cmdline'] = {}
325-
            for piece in shlex.split(data):
325+
            for piece in shlex.split(data):
326-
                item = piece.split('=', 1)
326+
                item = piece.split('=', 1)
327-
                if len(item) == 1:
327+
                if len(item) == 1:
328-
                    self.facts['cmdline'][item[0]] = True
328+
                    self.facts['cmdline'][item[0]] = True
329-
                else:
329+
                else:
330-
                    self.facts['cmdline'][item[0]] = item[1]
330+
                    self.facts['cmdline'][item[0]] = item[1]
331-
331+
332-
    def get_public_ssh_host_keys(self):
332+
    def get_public_ssh_host_keys(self):
333-
        dsa_filename = '/etc/ssh/ssh_host_dsa_key.pub'
333+
        dsa_filename = '/etc/ssh/ssh_host_dsa_key.pub'
334-
        rsa_filename = '/etc/ssh/ssh_host_rsa_key.pub'
334+
        rsa_filename = '/etc/ssh/ssh_host_rsa_key.pub'
335-
        ecdsa_filename = '/etc/ssh/ssh_host_ecdsa_key.pub'
335+
        ecdsa_filename = '/etc/ssh/ssh_host_ecdsa_key.pub'
336-
336+
337-
        if self.facts['system'] == 'Darwin':
337+
        if self.facts['system'] == 'Darwin':
338-
            dsa_filename = '/etc/ssh_host_dsa_key.pub'
338+
            dsa_filename = '/etc/ssh_host_dsa_key.pub'
339-
            rsa_filename = '/etc/ssh_host_rsa_key.pub'
339+
            rsa_filename = '/etc/ssh_host_rsa_key.pub'
340-
            ecdsa_filename = '/etc/ssh_host_ecdsa_key.pub'
340+
            ecdsa_filename = '/etc/ssh_host_ecdsa_key.pub'
341-
        dsa = get_file_content(dsa_filename)
341+
        dsa = get_file_content(dsa_filename)
342-
        rsa = get_file_content(rsa_filename)
342+
        rsa = get_file_content(rsa_filename)
343-
        ecdsa = get_file_content(ecdsa_filename)
343+
        ecdsa = get_file_content(ecdsa_filename)
344-
        if dsa is None:
344+
        if dsa is None:
345-
            dsa = 'NA'
345+
            dsa = 'NA'
346-
        else:
346+
        else:
347-
            self.facts['ssh_host_key_dsa_public'] = dsa.split()[1]
347+
            self.facts['ssh_host_key_dsa_public'] = dsa.split()[1]
348-
        if rsa is None:
348+
        if rsa is None:
349-
            rsa = 'NA'
349+
            rsa = 'NA'
350-
        else:
350+
        else:
351-
            self.facts['ssh_host_key_rsa_public'] = rsa.split()[1]
351+
            self.facts['ssh_host_key_rsa_public'] = rsa.split()[1]
352-
        if ecdsa is None:
352+
        if ecdsa is None:
353-
            ecdsa = 'NA'
353+
            ecdsa = 'NA'
354-
        else:
354+
        else:
355-
            self.facts['ssh_host_key_ecdsa_public'] = ecdsa.split()[1]
355+
            self.facts['ssh_host_key_ecdsa_public'] = ecdsa.split()[1]
356-
356+
357-
    def get_pkg_mgr_facts(self):
357+
    def get_pkg_mgr_facts(self):
358-
        self.facts['pkg_mgr'] = 'unknown'
358+
        self.facts['pkg_mgr'] = 'unknown'
359-
        for pkg in Facts.PKG_MGRS:
359+
        for pkg in Facts.PKG_MGRS:
360-
            if os.path.exists(pkg['path']):
360+
            if os.path.exists(pkg['path']):
361-
                self.facts['pkg_mgr'] = pkg['name']
361+
                self.facts['pkg_mgr'] = pkg['name']
362-
        if self.facts['system'] == 'OpenBSD':
362+
        if self.facts['system'] == 'OpenBSD':
363-
                self.facts['pkg_mgr'] = 'openbsd_pkg'
363+
                self.facts['pkg_mgr'] = 'openbsd_pkg'
364-
364+
365-
    def get_lsb_facts(self):
365+
    def get_lsb_facts(self):
366-
        lsb_path = module.get_bin_path('lsb_release')
366+
        lsb_path = module.get_bin_path('lsb_release')
367-
        if lsb_path:
367+
        if lsb_path:
368-
            rc, out, err = module.run_command([lsb_path, "-a"])
368+
            rc, out, err = module.run_command([lsb_path, "-a"])
369-
            if rc == 0:
369+
            if rc == 0:
370-
                self.facts['lsb'] = {}
370+
                self.facts['lsb'] = {}
371-
            for line in out.split('\n'):
371+
            for line in out.split('\n'):
372-
                if len(line) < 1:
372+
                if len(line) < 1:
373-
                    continue
373+
                    continue
374-
                value = line.split(':', 1)[1].strip()
374+
                value = line.split(':', 1)[1].strip()
375-
                if 'LSB Version:' in line:
375+
                if 'LSB Version:' in line:
376-
                    self.facts['lsb']['release'] = value
376+
                    self.facts['lsb']['release'] = value
377-
                elif 'Distributor ID:' in line:
377+
                elif 'Distributor ID:' in line:
378-
                    self.facts['lsb']['id'] = value
378+
                    self.facts['lsb']['id'] = value
379-
                elif 'Description:' in line:
379+
                elif 'Description:' in line:
380-
                    self.facts['lsb']['description'] = value
380+
                    self.facts['lsb']['description'] = value
381-
                elif 'Release:' in line:
381+
                elif 'Release:' in line:
382-
                    self.facts['lsb']['release'] = value
382+
                    self.facts['lsb']['release'] = value
383-
                elif 'Codename:' in line:
383+
                elif 'Codename:' in line:
384-
                    self.facts['lsb']['codename'] = value
384+
                    self.facts['lsb']['codename'] = value
385-
            if 'lsb' in self.facts and 'release' in self.facts['lsb']:
385+
            if 'lsb' in self.facts and 'release' in self.facts['lsb']:
386-
                self.facts['lsb']['major_release'] = self.facts['lsb']['release'].split('.')[0]
386+
                self.facts['lsb']['major_release'] = self.facts['lsb']['release'].split('.')[0]
387-
        elif lsb_path is None and os.path.exists('/etc/lsb-release'):
387+
        elif lsb_path is None and os.path.exists('/etc/lsb-release'):
388-
            self.facts['lsb'] = {}
388+
            self.facts['lsb'] = {}
389-
            f = open('/etc/lsb-release', 'r')
389+
            f = open('/etc/lsb-release', 'r')
390-
            try:
390+
            try:
391-
                for line in f.readlines():
391+
                for line in f.readlines():
392-
                    value = line.split('=',1)[1].strip()
392+
                    value = line.split('=',1)[1].strip()
393-
                    if 'DISTRIB_ID' in line:
393+
                    if 'DISTRIB_ID' in line:
394-
                        self.facts['lsb']['id'] = value
394+
                        self.facts['lsb']['id'] = value
395-
                    elif 'DISTRIB_RELEASE' in line:
395+
                    elif 'DISTRIB_RELEASE' in line:
396-
                        self.facts['lsb']['release'] = value
396+
                        self.facts['lsb']['release'] = value
397-
                    elif 'DISTRIB_DESCRIPTION' in line:
397+
                    elif 'DISTRIB_DESCRIPTION' in line:
398-
                        self.facts['lsb']['description'] = value
398+
                        self.facts['lsb']['description'] = value
399-
                    elif 'DISTRIB_CODENAME' in line:
399+
                    elif 'DISTRIB_CODENAME' in line:
400-
                        self.facts['lsb']['codename'] = value
400+
                        self.facts['lsb']['codename'] = value
401-
            finally:
401+
            finally:
402-
                f.close()
402+
                f.close()
403-
        else:
403+
        else:
404-
            return self.facts
404+
            return self.facts
405-
405+
406-
        if 'lsb' in self.facts and 'release' in self.facts['lsb']:
406+
        if 'lsb' in self.facts and 'release' in self.facts['lsb']:
407-
            self.facts['lsb']['major_release'] = self.facts['lsb']['release'].split('.')[0]
407+
            self.facts['lsb']['major_release'] = self.facts['lsb']['release'].split('.')[0]
408-
408+
409-
409+
410-
    def get_selinux_facts(self):
410+
    def get_selinux_facts(self):
411-
        if not HAVE_SELINUX:
411+
        if not HAVE_SELINUX:
412-
            self.facts['selinux'] = False
412+
            self.facts['selinux'] = False
413-
            return
413+
            return
414-
        self.facts['selinux'] = {}
414+
        self.facts['selinux'] = {}
415-
        if not selinux.is_selinux_enabled():
415+
        if not selinux.is_selinux_enabled():
416-
            self.facts['selinux']['status'] = 'disabled'
416+
            self.facts['selinux']['status'] = 'disabled'
417-
        else:
417+
        else:
418-
            self.facts['selinux']['status'] = 'enabled'
418+
            self.facts['selinux']['status'] = 'enabled'
419-
            try:
419+
            try:
420-
                self.facts['selinux']['policyvers'] = selinux.security_policyvers()
420+
                self.facts['selinux']['policyvers'] = selinux.security_policyvers()
421-
            except OSError, e:
421+
            except OSError, e:
422-
                self.facts['selinux']['policyvers'] = 'unknown'
422+
                self.facts['selinux']['policyvers'] = 'unknown'
423-
            try:
423+
            try:
424-
                (rc, configmode) = selinux.selinux_getenforcemode()
424+
                (rc, configmode) = selinux.selinux_getenforcemode()
425-
                if rc == 0:
425+
                if rc == 0:
426-
                    self.facts['selinux']['config_mode'] = Facts.SELINUX_MODE_DICT.get(configmode, 'unknown')
426+
                    self.facts['selinux']['config_mode'] = Facts.SELINUX_MODE_DICT.get(configmode, 'unknown')
427-
                else:
427+
                else:
428-
                    self.facts['selinux']['config_mode'] = 'unknown'
428+
                    self.facts['selinux']['config_mode'] = 'unknown'
429-
            except OSError, e:
429+
            except OSError, e:
430-
                self.facts['selinux']['config_mode'] = 'unknown'
430+
                self.facts['selinux']['config_mode'] = 'unknown'
431-
            try:
431+
            try:
432-
                mode = selinux.security_getenforce()
432+
                mode = selinux.security_getenforce()
433-
                self.facts['selinux']['mode'] = Facts.SELINUX_MODE_DICT.get(mode, 'unknown')
433+
                self.facts['selinux']['mode'] = Facts.SELINUX_MODE_DICT.get(mode, 'unknown')
434-
            except OSError, e:
434+
            except OSError, e:
435-
                self.facts['selinux']['mode'] = 'unknown'
435+
                self.facts['selinux']['mode'] = 'unknown'
436-
            try:
436+
            try:
437-
                (rc, policytype) = selinux.selinux_getpolicytype()
437+
                (rc, policytype) = selinux.selinux_getpolicytype()
438-
                if rc == 0:
438+
                if rc == 0:
439-
                    self.facts['selinux']['type'] = policytype
439+
                    self.facts['selinux']['type'] = policytype
440-
                else:
440+
                else:
441-
                    self.facts['selinux']['type'] = 'unknown'
441+
                    self.facts['selinux']['type'] = 'unknown'
442-
            except OSError, e:
442+
            except OSError, e:
443-
                self.facts['selinux']['type'] = 'unknown'
443+
                self.facts['selinux']['type'] = 'unknown'
444-
444+
445-
445+
446-
    def get_date_time_facts(self):
446+
    def get_date_time_facts(self):
447-
        self.facts['date_time'] = {}
447+
        self.facts['date_time'] = {}
448-
448+
449-
        now = datetime.datetime.now()
449+
        now = datetime.datetime.now()
450-
        self.facts['date_time']['year'] = now.strftime('%Y')
450+
        self.facts['date_time']['year'] = now.strftime('%Y')
451-
        self.facts['date_time']['month'] = now.strftime('%m')
451+
        self.facts['date_time']['month'] = now.strftime('%m')
452-
        self.facts['date_time']['weekday'] = now.strftime('%A')
452+
        self.facts['date_time']['weekday'] = now.strftime('%A')
453-
        self.facts['date_time']['day'] = now.strftime('%d')
453+
        self.facts['date_time']['day'] = now.strftime('%d')
454-
        self.facts['date_time']['hour'] = now.strftime('%H')
454+
        self.facts['date_time']['hour'] = now.strftime('%H')
455-
        self.facts['date_time']['minute'] = now.strftime('%M')
455+
        self.facts['date_time']['minute'] = now.strftime('%M')
456-
        self.facts['date_time']['second'] = now.strftime('%S')
456+
        self.facts['date_time']['second'] = now.strftime('%S')
457-
        self.facts['date_time']['epoch'] = now.strftime('%s')
457+
        self.facts['date_time']['epoch'] = now.strftime('%s')
458-
        if self.facts['date_time']['epoch'] == '' or self.facts['date_time']['epoch'][0] == '%':
458+
        if self.facts['date_time']['epoch'] == '' or self.facts['date_time']['epoch'][0] == '%':
459-
            self.facts['date_time']['epoch'] = str(int(time.time()))
459+
            self.facts['date_time']['epoch'] = str(int(time.time()))
460-
        self.facts['date_time']['date'] = now.strftime('%Y-%m-%d')
460+
        self.facts['date_time']['date'] = now.strftime('%Y-%m-%d')
461-
        self.facts['date_time']['time'] = now.strftime('%H:%M:%S')
461+
        self.facts['date_time']['time'] = now.strftime('%H:%M:%S')
462-
        self.facts['date_time']['iso8601_micro'] = now.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
462+
        self.facts['date_time']['iso8601_micro'] = now.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
463-
        self.facts['date_time']['iso8601'] = now.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
463+
        self.facts['date_time']['iso8601'] = now.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")
464-
        self.facts['date_time']['tz'] = time.strftime("%Z")
464+
        self.facts['date_time']['tz'] = time.strftime("%Z")
465-
        self.facts['date_time']['tz_offset'] = time.strftime("%z")
465+
        self.facts['date_time']['tz_offset'] = time.strftime("%z")
466-
466+
467-
467+
468-
    # User
468+
    # User
469-
    def get_user_facts(self):
469+
    def get_user_facts(self):
470-
        self.facts['user_id'] = getpass.getuser()
470+
        self.facts['user_id'] = getpass.getuser()
471-
471+
472-
    def get_env_facts(self):
472+
    def get_env_facts(self):
473-
        self.facts['env'] = {}
473+
        self.facts['env'] = {}
474-
        for k,v in os.environ.iteritems():
474+
        for k,v in os.environ.iteritems():
475-
            self.facts['env'][k] = v
475+
            self.facts['env'][k] = v
476-
476+
477-
class Hardware(Facts):
477+
class Hardware(Facts):
478-
    """
478+
    """
479-
    This is a generic Hardware subclass of Facts.  This should be further
479+
    This is a generic Hardware subclass of Facts.  This should be further
480-
    subclassed to implement per platform.  If you subclass this, it
480+
    subclassed to implement per platform.  If you subclass this, it
481-
    should define:
481+
    should define:
482-
    - memfree_mb
482+
    - memfree_mb
483-
    - memtotal_mb
483+
    - memtotal_mb
484-
    - swapfree_mb
484+
    - swapfree_mb
485-
    - swaptotal_mb
485+
    - swaptotal_mb
486-
    - processor (a list)
486+
    - processor (a list)
487-
    - processor_cores
487+
    - processor_cores
488-
    - processor_count
488+
    - processor_count
489-
489+
490-
    All subclasses MUST define platform.
490+
    All subclasses MUST define platform.
491-
    """
491+
    """
492-
    platform = 'Generic'
492+
    platform = 'Generic'
493-
493+
494-
    def __new__(cls, *arguments, **keyword):
494+
    def __new__(cls, *arguments, **keyword):
495-
        subclass = cls
495+
        subclass = cls
496-
        for sc in Hardware.__subclasses__():
496+
        for sc in Hardware.__subclasses__():
497-
            if sc.platform == platform.system():
497+
            if sc.platform == platform.system():
498-
                subclass = sc
498+
                subclass = sc
499-
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
499+
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
500-
500+
501-
    def __init__(self):
501+
    def __init__(self):
502-
        Facts.__init__(self)
502+
        Facts.__init__(self)
503-
503+
504-
    def populate(self):
504+
    def populate(self):
505-
        return self.facts
505+
        return self.facts
506-
506+
507-
class LinuxHardware(Hardware):
507+
class LinuxHardware(Hardware):
508-
    """
508+
    """
509-
    Linux-specific subclass of Hardware.  Defines memory and CPU facts:
509+
    Linux-specific subclass of Hardware.  Defines memory and CPU facts:
510-
    - memfree_mb
510+
    - memfree_mb
511-
    - memtotal_mb
511+
    - memtotal_mb
512-
    - swapfree_mb
512+
    - swapfree_mb
513-
    - swaptotal_mb
513+
    - swaptotal_mb
514-
    - processor (a list)
514+
    - processor (a list)
515-
    - processor_cores
515+
    - processor_cores
516-
    - processor_count
516+
    - processor_count
517-
517+
518-
    In addition, it also defines number of DMI facts and device facts.
518+
    In addition, it also defines number of DMI facts and device facts.
519-
    """
519+
    """
520-
520+
521-
    platform = 'Linux'
521+
    platform = 'Linux'
522-
    MEMORY_FACTS = ['MemTotal', 'SwapTotal', 'MemFree', 'SwapFree']
522+
    MEMORY_FACTS = ['MemTotal', 'SwapTotal', 'MemFree', 'SwapFree']
523-
523+
524-
    def __init__(self):
524+
    def __init__(self):
525-
        Hardware.__init__(self)
525+
        Hardware.__init__(self)
526-
526+
527-
    def populate(self):
527+
    def populate(self):
528-
        self.get_cpu_facts()
528+
        self.get_cpu_facts()
529-
        self.get_memory_facts()
529+
        self.get_memory_facts()
530-
        self.get_dmi_facts()
530+
        self.get_dmi_facts()
531-
        self.get_device_facts()
531+
        self.get_device_facts()
532-
        try:
532+
        try:
533-
            self.get_mount_facts()
533+
            self.get_mount_facts()
534-
        except TimeoutError:
534+
        except TimeoutError:
535-
            pass
535+
            pass
536-
        return self.facts
536+
        return self.facts
537-
537+
538-
    def get_memory_facts(self):
538+
    def get_memory_facts(self):
539-
        if not os.access("/proc/meminfo", os.R_OK):
539+
        if not os.access("/proc/meminfo", os.R_OK):
540-
            return
540+
            return
541-
        for line in open("/proc/meminfo").readlines():
541+
        for line in open("/proc/meminfo").readlines():
542-
            data = line.split(":", 1)
542+
            data = line.split(":", 1)
543-
            key = data[0]
543+
            key = data[0]
544-
            if key in LinuxHardware.MEMORY_FACTS:
544+
            if key in LinuxHardware.MEMORY_FACTS:
545-
                val = data[1].strip().split(' ')[0]
545+
                val = data[1].strip().split(' ')[0]
546-
                self.facts["%s_mb" % key.lower()] = long(val) / 1024
546+
                self.facts["%s_mb" % key.lower()] = long(val) / 1024
547-
547+
548-
    def get_cpu_facts(self):
548+
    def get_cpu_facts(self):
549-
        i = 0
549+
        i = 0
550-
        physid = 0
550+
        physid = 0
551-
        coreid = 0
551+
        coreid = 0
552-
        sockets = {}
552+
        sockets = {}
553-
        cores = {}
553+
        cores = {}
554-
        if not os.access("/proc/cpuinfo", os.R_OK):
554+
        if not os.access("/proc/cpuinfo", os.R_OK):
555-
            return
555+
            return
556-
        self.facts['processor'] = []
556+
        self.facts['processor'] = []
557-
        for line in open("/proc/cpuinfo").readlines():
557+
        for line in open("/proc/cpuinfo").readlines():
558-
            data = line.split(":", 1)
558+
            data = line.split(":", 1)
559-
            key = data[0].strip()
559+
            key = data[0].strip()
560-
            # model name is for Intel arch, Processor (mind the uppercase P)
560+
            # model name is for Intel arch, Processor (mind the uppercase P)
561-
            # works for some ARM devices, like the Sheevaplug.
561+
            # works for some ARM devices, like the Sheevaplug.
562-
            if key == 'model name' or key == 'Processor':
562+
            if key == 'model name' or key == 'Processor':
563-
                if 'processor' not in self.facts:
563+
                if 'processor' not in self.facts:
564-
                    self.facts['processor'] = []
564+
                    self.facts['processor'] = []
565-
                self.facts['processor'].append(data[1].strip())
565+
                self.facts['processor'].append(data[1].strip())
566-
                i += 1
566+
                i += 1
567-
            elif key == 'physical id':
567+
            elif key == 'physical id':
568-
                physid = data[1].strip()
568+
                physid = data[1].strip()
569-
                if physid not in sockets:
569+
                if physid not in sockets:
570-
                    sockets[physid] = 1
570+
                    sockets[physid] = 1
571-
            elif key == 'core id':
571+
            elif key == 'core id':
572-
                coreid = data[1].strip()
572+
                coreid = data[1].strip()
573-
                if coreid not in sockets:
573+
                if coreid not in sockets:
574-
                    cores[coreid] = 1
574+
                    cores[coreid] = 1
575-
            elif key == 'cpu cores':
575+
            elif key == 'cpu cores':
576-
                sockets[physid] = int(data[1].strip())
576+
                sockets[physid] = int(data[1].strip())
577-
            elif key == 'siblings':
577+
            elif key == 'siblings':
578-
                cores[coreid] = int(data[1].strip())
578+
                cores[coreid] = int(data[1].strip())
579-
        self.facts['processor_count'] = sockets and len(sockets) or i
579+
        self.facts['processor_count'] = sockets and len(sockets) or i
580-
        self.facts['processor_cores'] = sockets.values() and sockets.values()[0] or 1
580+
        self.facts['processor_cores'] = sockets.values() and sockets.values()[0] or 1
581-
        self.facts['processor_threads_per_core'] = ((cores.values() and
581+
        self.facts['processor_threads_per_core'] = ((cores.values() and
582-
            cores.values()[0] or 1) / self.facts['processor_cores'])
582+
            cores.values()[0] or 1) / self.facts['processor_cores'])
583-
        self.facts['processor_vcpus'] = (self.facts['processor_threads_per_core'] *
583+
        self.facts['processor_vcpus'] = (self.facts['processor_threads_per_core'] *
584-
            self.facts['processor_count'] * self.facts['processor_cores'])
584+
            self.facts['processor_count'] * self.facts['processor_cores'])
585-
585+
586-
    def get_dmi_facts(self):
586+
    def get_dmi_facts(self):
587-
        ''' learn dmi facts from system
587+
        ''' learn dmi facts from system
588-
588+
589-
        Try /sys first for dmi related facts.
589+
        Try /sys first for dmi related facts.
590-
        If that is not available, fall back to dmidecode executable '''
590+
        If that is not available, fall back to dmidecode executable '''
591-
591+
592-
        if os.path.exists('/sys/devices/virtual/dmi/id/product_name'):
592+
        if os.path.exists('/sys/devices/virtual/dmi/id/product_name'):
593-
            # Use kernel DMI info, if available
593+
            # Use kernel DMI info, if available
594-
594+
595-
            # DMI SPEC -- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
595+
            # DMI SPEC -- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
596-
            FORM_FACTOR = [ "Unknown", "Other", "Unknown", "Desktop",
596+
            FORM_FACTOR = [ "Unknown", "Other", "Unknown", "Desktop",
597-
                            "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower",
597+
                            "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower",
598-
                            "Portable", "Laptop", "Notebook", "Hand Held", "Docking Station",
598+
                            "Portable", "Laptop", "Notebook", "Hand Held", "Docking Station",
599-
                            "All In One", "Sub Notebook", "Space-saving", "Lunch Box",
599+
                            "All In One", "Sub Notebook", "Space-saving", "Lunch Box",
600-
                            "Main Server Chassis", "Expansion Chassis", "Sub Chassis",
600+
                            "Main Server Chassis", "Expansion Chassis", "Sub Chassis",
601-
                            "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis",
601+
                            "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis",
602-
                            "Rack Mount Chassis", "Sealed-case PC", "Multi-system",
602+
                            "Rack Mount Chassis", "Sealed-case PC", "Multi-system",
603-
                            "CompactPCI", "AdvancedTCA", "Blade" ]
603+
                            "CompactPCI", "AdvancedTCA", "Blade" ]
604-
604+
605-
            DMI_DICT = {
605+
            DMI_DICT = {
606-
                    'bios_date': '/sys/devices/virtual/dmi/id/bios_date',
606+
                    'bios_date': '/sys/devices/virtual/dmi/id/bios_date',
607-
                    'bios_version': '/sys/devices/virtual/dmi/id/bios_version',
607+
                    'bios_version': '/sys/devices/virtual/dmi/id/bios_version',
608-
                    'form_factor': '/sys/devices/virtual/dmi/id/chassis_type',
608+
                    'form_factor': '/sys/devices/virtual/dmi/id/chassis_type',
609-
                    'product_name': '/sys/devices/virtual/dmi/id/product_name',
609+
                    'product_name': '/sys/devices/virtual/dmi/id/product_name',
610-
                    'product_serial': '/sys/devices/virtual/dmi/id/product_serial',
610+
                    'product_serial': '/sys/devices/virtual/dmi/id/product_serial',
611-
                    'product_uuid': '/sys/devices/virtual/dmi/id/product_uuid',
611+
                    'product_uuid': '/sys/devices/virtual/dmi/id/product_uuid',
612-
                    'product_version': '/sys/devices/virtual/dmi/id/product_version',
612+
                    'product_version': '/sys/devices/virtual/dmi/id/product_version',
613-
                    'system_vendor': '/sys/devices/virtual/dmi/id/sys_vendor'
613+
                    'system_vendor': '/sys/devices/virtual/dmi/id/sys_vendor'
614-
                    }
614+
                    }
615-
615+
616-
            for (key,path) in DMI_DICT.items():
616+
            for (key,path) in DMI_DICT.items():
617-
                data = get_file_content(path)
617+
                data = get_file_content(path)
618-
                if data is not None:
618+
                if data is not None:
619-
                    if key == 'form_factor':
619+
                    if key == 'form_factor':
620-
                        try:
620+
                        try:
621-
                            self.facts['form_factor'] = FORM_FACTOR[int(data)]
621+
                            self.facts['form_factor'] = FORM_FACTOR[int(data)]
622-
                        except IndexError, e:
622+
                        except IndexError, e:
623-
                            self.facts['form_factor'] = 'unknown (%s)' % data
623+
                            self.facts['form_factor'] = 'unknown (%s)' % data
624-
                    else:
624+
                    else:
625-
                        self.facts[key] = data
625+
                        self.facts[key] = data
626-
                else:
626+
                else:
627-
                    self.facts[key] = 'NA'
627+
                    self.facts[key] = 'NA'
628-
628+
629-
        else:
629+
        else:
630-
            # Fall back to using dmidecode, if available
630+
            # Fall back to using dmidecode, if available
631-
            dmi_bin = module.get_bin_path('dmidecode')
631+
            dmi_bin = module.get_bin_path('dmidecode')
632-
            DMI_DICT = {
632+
            DMI_DICT = {
633-
                    'bios_date': 'bios-release-date',
633+
                    'bios_date': 'bios-release-date',
634-
                    'bios_version': 'bios-version',
634+
                    'bios_version': 'bios-version',
635-
                    'form_factor': 'chassis-type',
635+
                    'form_factor': 'chassis-type',
636-
                    'product_name': 'system-product-name',
636+
                    'product_name': 'system-product-name',
637-
                    'product_serial': 'system-serial-number',
637+
                    'product_serial': 'system-serial-number',
638-
                    'product_uuid': 'system-uuid',
638+
                    'product_uuid': 'system-uuid',
639-
                    'product_version': 'system-version',
639+
                    'product_version': 'system-version',
640-
                    'system_vendor': 'system-manufacturer'
640+
                    'system_vendor': 'system-manufacturer'
641-
                    }
641+
                    }
642-
            for (k, v) in DMI_DICT.items():
642+
            for (k, v) in DMI_DICT.items():
643-
                if dmi_bin is not None:
643+
                if dmi_bin is not None:
644-
                    (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v))
644+
                    (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v))
645-
                    if rc == 0:
645+
                    if rc == 0:
646-
                        # Strip out commented lines (specific dmidecode output)
646+
                        # Strip out commented lines (specific dmidecode output)
647-
                        thisvalue = ''.join([ line for line in out.split('\n') if not line.startswith('#') ])
647+
                        thisvalue = ''.join([ line for line in out.split('\n') if not line.startswith('#') ])
648-
                        try:
648+
                        try:
649-
                            json.dumps(thisvalue)
649+
                            json.dumps(thisvalue)
650-
                        except UnicodeDecodeError:
650+
                        except UnicodeDecodeError:
651-
                            thisvalue = "NA"
651+
                            thisvalue = "NA"
652-
652+
653-
                        self.facts[k] = thisvalue
653+
                        self.facts[k] = thisvalue
654-
                    else:
654+
                    else:
655-
                        self.facts[k] = 'NA'
655+
                        self.facts[k] = 'NA'
656-
                else:
656+
                else:
657-
                    self.facts[k] = 'NA'
657+
                    self.facts[k] = 'NA'
658-
658+
659-
    @timeout(10)
659+
    @timeout(10)
660-
    def get_mount_facts(self):
660+
    def get_mount_facts(self):
661-
        self.facts['mounts'] = []
661+
        self.facts['mounts'] = []
662-
        mtab = get_file_content('/etc/mtab', '')
662+
        mtab = get_file_content('/etc/mtab', '')
663-
        for line in mtab.split('\n'):
663+
        for line in mtab.split('\n'):
664-
            if line.startswith('/'):
664+
            if line.startswith('/'):
665-
                fields = line.rstrip('\n').split()
665+
                fields = line.rstrip('\n').split()
666-
                if(fields[2] != 'none'):
666+
                if(fields[2] != 'none'):
667-
                    size_total = None
667+
                    size_total = None
668-
                    size_available = None
668+
                    size_available = None
669-
                    try:
669+
                    try:
670-
                        statvfs_result = os.statvfs(fields[1])
670+
                        statvfs_result = os.statvfs(fields[1])
671-
                        size_total = statvfs_result.f_bsize * statvfs_result.f_blocks
671+
                        size_total = statvfs_result.f_bsize * statvfs_result.f_blocks
672-
                        size_available = statvfs_result.f_bsize * (statvfs_result.f_bavail)
672+
                        size_available = statvfs_result.f_bsize * (statvfs_result.f_bavail)
673-
                    except OSError, e:
673+
                    except OSError, e:
674-
                        continue
674+
                        continue
675-
675+
676-
                    self.facts['mounts'].append(
676+
                    self.facts['mounts'].append(
677-
                        {'mount': fields[1],
677+
                        {'mount': fields[1],
678-
                         'device':fields[0],
678+
                         'device':fields[0],
679-
                         'fstype': fields[2],
679+
                         'fstype': fields[2],
680-
                         'options': fields[3],
680+
                         'options': fields[3],
681-
                         # statvfs data
681+
                         # statvfs data
682-
                         'size_total': size_total,
682+
                         'size_total': size_total,
683-
                         'size_available': size_available,
683+
                         'size_available': size_available,
684-
                         })
684+
                         })
685-
685+
686-
    def get_device_facts(self):
686+
    def get_device_facts(self):
687-
        self.facts['devices'] = {}
687+
        self.facts['devices'] = {}
688-
        lspci = module.get_bin_path('lspci')
688+
        lspci = module.get_bin_path('lspci')
689-
        if lspci:
689+
        if lspci:
690-
            rc, pcidata, err = module.run_command([lspci, '-D'])
690+
            rc, pcidata, err = module.run_command([lspci, '-D'])
691-
        else:
691+
        else:
692-
            pcidata = None
692+
            pcidata = None
693-
693+
694-
        try:
694+
        try:
695-
            block_devs = os.listdir("/sys/block")
695+
            block_devs = os.listdir("/sys/block")
696-
        except OSError:
696+
        except OSError:
697-
            return
697+
            return
698-
698+
699-
        for block in block_devs:
699+
        for block in block_devs:
700-
            virtual = 1
700+
            virtual = 1
701-
            sysfs_no_links = 0
701+
            sysfs_no_links = 0
702-
            try:
702+
            try:
703-
                path = os.readlink(os.path.join("/sys/block/", block))
703+
                path = os.readlink(os.path.join("/sys/block/", block))
704-
            except OSError, e:
704+
            except OSError, e:
705-
                if e.errno == errno.EINVAL:
705+
                if e.errno == errno.EINVAL:
706-
                    path = block
706+
                    path = block
707-
                    sysfs_no_links = 1
707+
                    sysfs_no_links = 1
708-
                else:
708+
                else:
709-
                    continue
709+
                    continue
710-
            if "virtual" in path:
710+
            if "virtual" in path:
711-
                continue
711+
                continue
712-
            sysdir = os.path.join("/sys/block", path)
712+
            sysdir = os.path.join("/sys/block", path)
713-
            if sysfs_no_links == 1:
713+
            if sysfs_no_links == 1:
714-
                for folder in os.listdir(sysdir):
714+
                for folder in os.listdir(sysdir):
715-
                    if "device" in folder:
715+
                    if "device" in folder:
716-
                        virtual = 0
716+
                        virtual = 0
717-
                        break
717+
                        break
718-
                if virtual:
718+
                if virtual:
719-
                    continue
719+
                    continue
720-
            d = {}
720+
            d = {}
721-
            diskname = os.path.basename(sysdir)
721+
            diskname = os.path.basename(sysdir)
722-
            for key in ['vendor', 'model']:
722+
            for key in ['vendor', 'model']:
723-
                d[key] = get_file_content(sysdir + "/device/" + key)
723+
                d[key] = get_file_content(sysdir + "/device/" + key)
724-
724+
725-
            for key,test in [ ('removable','/removable'), \
725+
            for key,test in [ ('removable','/removable'), \
726-
                              ('support_discard','/queue/discard_granularity'),
726+
                              ('support_discard','/queue/discard_granularity'),
727-
                              ]:
727+
                              ]:
728-
                d[key] = get_file_content(sysdir + test)
728+
                d[key] = get_file_content(sysdir + test)
729-
729+
730-
            d['partitions'] = {}
730+
            d['partitions'] = {}
731-
            for folder in os.listdir(sysdir):
731+
            for folder in os.listdir(sysdir):
732-
                m = re.search("(" + diskname + "\d+)", folder)
732+
                m = re.search("(" + diskname + "\d+)", folder)
733-
                if m:
733+
                if m:
734-
                    part = {}
734+
                    part = {}
735-
                    partname = m.group(1)
735+
                    partname = m.group(1)
736-
                    part_sysdir = sysdir + "/" + partname
736+
                    part_sysdir = sysdir + "/" + partname
737-
737+
738-
                    part['start'] = get_file_content(part_sysdir + "/start",0)
738+
                    part['start'] = get_file_content(part_sysdir + "/start",0)
739-
                    part['sectors'] = get_file_content(part_sysdir + "/size",0)
739+
                    part['sectors'] = get_file_content(part_sysdir + "/size",0)
740-
                    part['sectorsize'] = get_file_content(part_sysdir + "/queue/hw_sector_size",512)
740+
                    part['sectorsize'] = get_file_content(part_sysdir + "/queue/hw_sector_size",512)
741-
                    part['size'] = module.pretty_bytes((float(part['sectors']) * float(part['sectorsize'])))
741+
                    part['size'] = module.pretty_bytes((float(part['sectors']) * float(part['sectorsize'])))
742-
                    d['partitions'][partname] = part
742+
                    d['partitions'][partname] = part
743-
743+
744-
            d['rotational'] = get_file_content(sysdir + "/queue/rotational")
744+
            d['rotational'] = get_file_content(sysdir + "/queue/rotational")
745-
            d['scheduler_mode'] = ""
745+
            d['scheduler_mode'] = ""
746-
            scheduler = get_file_content(sysdir + "/queue/scheduler")
746+
            scheduler = get_file_content(sysdir + "/queue/scheduler")
747-
            if scheduler is not None:
747+
            if scheduler is not None:
748-
                m = re.match(".*?(\[(.*)\])", scheduler)
748+
                m = re.match(".*?(\[(.*)\])", scheduler)
749-
                if m:
749+
                if m:
750-
                    d['scheduler_mode'] = m.group(2)
750+
                    d['scheduler_mode'] = m.group(2)
751-
751+
752-
            d['sectors'] = get_file_content(sysdir + "/size")
752+
            d['sectors'] = get_file_content(sysdir + "/size")
753-
            if not d['sectors']:
753+
            if not d['sectors']:
754-
                d['sectors'] = 0
754+
                d['sectors'] = 0
755-
            d['sectorsize'] = get_file_content(sysdir + "/queue/hw_sector_size")
755+
            d['sectorsize'] = get_file_content(sysdir + "/queue/hw_sector_size")
756-
            if not d['sectorsize']:
756+
            if not d['sectorsize']:
757-
                d['sectorsize'] = 512
757+
                d['sectorsize'] = 512
758-
            d['size'] = module.pretty_bytes(float(d['sectors']) * float(d['sectorsize']))
758+
            d['size'] = module.pretty_bytes(float(d['sectors']) * float(d['sectorsize']))
759-
759+
760-
            d['host'] = ""
760+
            d['host'] = ""
761-
761+
762-
            # domains are numbered (0 to ffff), bus (0 to ff), slot (0 to 1f), and function (0 to 7).
762+
            # domains are numbered (0 to ffff), bus (0 to ff), slot (0 to 1f), and function (0 to 7).
763-
            m = re.match(".+/([a-f0-9]{4}:[a-f0-9]{2}:[0|1][a-f0-9]\.[0-7])/", sysdir)
763+
            m = re.match(".+/([a-f0-9]{4}:[a-f0-9]{2}:[0|1][a-f0-9]\.[0-7])/", sysdir)
764-
            if m and pcidata:
764+
            if m and pcidata:
765-
                pciid = m.group(1)
765+
                pciid = m.group(1)
766-
                did = re.escape(pciid)
766+
                did = re.escape(pciid)
767-
                m = re.search("^" + did + "\s(.*)$", pcidata, re.MULTILINE)
767+
                m = re.search("^" + did + "\s(.*)$", pcidata, re.MULTILINE)
768-
                d['host'] = m.group(1)
768+
                d['host'] = m.group(1)
769-
769+
770-
            d['holders'] = []
770+
            d['holders'] = []
771-
            if os.path.isdir(sysdir + "/holders"):
771+
            if os.path.isdir(sysdir + "/holders"):
772-
                for folder in os.listdir(sysdir + "/holders"):
772+
                for folder in os.listdir(sysdir + "/holders"):
773-
                    if not folder.startswith("dm-"):
773+
                    if not folder.startswith("dm-"):
774-
                        continue
774+
                        continue
775-
                    name = get_file_content(sysdir + "/holders/" + folder + "/dm/name")
775+
                    name = get_file_content(sysdir + "/holders/" + folder + "/dm/name")
776-
                    if name:
776+
                    if name:
777-
                        d['holders'].append(name)
777+
                        d['holders'].append(name)
778-
                    else:
778+
                    else:
779-
                        d['holders'].append(folder)
779+
                        d['holders'].append(folder)
780-
780+
781-
            self.facts['devices'][diskname] = d
781+
            self.facts['devices'][diskname] = d
782-
782+
783-
783+
784-
class SunOSHardware(Hardware):
784+
class SunOSHardware(Hardware):
785-
    """
785+
    """
786-
    In addition to the generic memory and cpu facts, this also sets
786+
    In addition to the generic memory and cpu facts, this also sets
787-
    swap_reserved_mb and swap_allocated_mb that is available from *swap -s*.
787+
    swap_reserved_mb and swap_allocated_mb that is available from *swap -s*.
788-
    """
788+
    """
789-
    platform = 'SunOS'
789+
    platform = 'SunOS'
790-
790+
791-
    def __init__(self):
791+
    def __init__(self):
792-
        Hardware.__init__(self)
792+
        Hardware.__init__(self)
793-
793+
794-
    def populate(self):
794+
    def populate(self):
795-
        self.get_cpu_facts()
795+
        self.get_cpu_facts()
796-
        self.get_memory_facts()
796+
        self.get_memory_facts()
797-
        return self.facts
797+
        return self.facts
798-
798+
799-
    def get_cpu_facts(self):
799+
    def get_cpu_facts(self):
800-
        physid = 0
800+
        physid = 0
801-
        sockets = {}
801+
        sockets = {}
802-
        rc, out, err = module.run_command("/usr/bin/kstat cpu_info")
802+
        rc, out, err = module.run_command("/usr/bin/kstat cpu_info")
803-
        self.facts['processor'] = []
803+
        self.facts['processor'] = []
804-
        for line in out.split('\n'):
804+
        for line in out.split('\n'):
805-
            if len(line) < 1:
805+
            if len(line) < 1:
806-
                continue
806+
                continue
807-
            data = line.split(None, 1)
807+
            data = line.split(None, 1)
808-
            key = data[0].strip()
808+
            key = data[0].strip()
809-
            # "brand" works on Solaris 10 & 11. "implementation" for Solaris 9.
809+
            # "brand" works on Solaris 10 & 11. "implementation" for Solaris 9.
810-
            if key == 'module:':
810+
            if key == 'module:':
811-
                brand = ''
811+
                brand = ''
812-
            elif key == 'brand':
812+
            elif key == 'brand':
813-
                brand = data[1].strip()
813+
                brand = data[1].strip()
814-
            elif key == 'clock_MHz':
814+
            elif key == 'clock_MHz':
815-
                clock_mhz = data[1].strip()
815+
                clock_mhz = data[1].strip()
816-
            elif key == 'implementation':
816+
            elif key == 'implementation':
817-
                processor = brand or data[1].strip()
817+
                processor = brand or data[1].strip()
818-
                # Add clock speed to description for SPARC CPU
818+
                # Add clock speed to description for SPARC CPU
819-
                if self.facts['machine'] != 'i86pc':
819+
                if self.facts['machine'] != 'i86pc':
820-
                    processor += " @ " + clock_mhz + "MHz"
820+
                    processor += " @ " + clock_mhz + "MHz"
821-
                if 'processor' not in self.facts:
821+
                if 'processor' not in self.facts:
822-
                    self.facts['processor'] = []
822+
                    self.facts['processor'] = []
823-
                self.facts['processor'].append(processor)
823+
                self.facts['processor'].append(processor)
824-
            elif key == 'chip_id':
824+
            elif key == 'chip_id':
825-
                physid = data[1].strip()
825+
                physid = data[1].strip()
826-
                if physid not in sockets:
826+
                if physid not in sockets:
827-
                    sockets[physid] = 1
827+
                    sockets[physid] = 1
828-
                else:
828+
                else:
829-
                    sockets[physid] += 1
829+
                    sockets[physid] += 1
830-
        # Counting cores on Solaris can be complicated.
830+
        # Counting cores on Solaris can be complicated.
831-
        # https://blogs.oracle.com/mandalika/entry/solaris_show_me_the_cpu
831+
        # https://blogs.oracle.com/mandalika/entry/solaris_show_me_the_cpu
832-
        # Treat 'processor_count' as physical sockets and 'processor_cores' as
832+
        # Treat 'processor_count' as physical sockets and 'processor_cores' as
833-
        # virtual CPUs visisble to Solaris. Not a true count of cores for modern SPARC as
833+
        # virtual CPUs visisble to Solaris. Not a true count of cores for modern SPARC as
834-
        # these processors have: sockets -> cores -> threads/virtual CPU.
834+
        # these processors have: sockets -> cores -> threads/virtual CPU.
835-
        if len(sockets) > 0:
835+
        if len(sockets) > 0:
836-
            self.facts['processor_count'] = len(sockets)
836+
            self.facts['processor_count'] = len(sockets)
837-
            self.facts['processor_cores'] = reduce(lambda x, y: x + y, sockets.values())
837+
            self.facts['processor_cores'] = reduce(lambda x, y: x + y, sockets.values())
838-
        else:
838+
        else:
839-
            self.facts['processor_cores'] = 'NA'
839+
            self.facts['processor_cores'] = 'NA'
840-
            self.facts['processor_count'] = len(self.facts['processor'])
840+
            self.facts['processor_count'] = len(self.facts['processor'])
841-
841+
842-
    def get_memory_facts(self):
842+
    def get_memory_facts(self):
843-
        rc, out, err = module.run_command(["/usr/sbin/prtconf"])
843+
        rc, out, err = module.run_command(["/usr/sbin/prtconf"])
844-
        for line in out.split('\n'):
844+
        for line in out.split('\n'):
845-
            if 'Memory size' in line:
845+
            if 'Memory size' in line:
846-
                self.facts['memtotal_mb'] = line.split()[2]
846+
                self.facts['memtotal_mb'] = line.split()[2]
847-
        rc, out, err = module.run_command("/usr/sbin/swap -s")
847+
        rc, out, err = module.run_command("/usr/sbin/swap -s")
848-
        allocated = long(out.split()[1][:-1])
848+
        allocated = long(out.split()[1][:-1])
849-
        reserved = long(out.split()[5][:-1])
849+
        reserved = long(out.split()[5][:-1])
850-
        used = long(out.split()[8][:-1])
850+
        used = long(out.split()[8][:-1])
851-
        free = long(out.split()[10][:-1])
851+
        free = long(out.split()[10][:-1])
852-
        self.facts['swapfree_mb'] = free / 1024
852+
        self.facts['swapfree_mb'] = free / 1024
853-
        self.facts['swaptotal_mb'] = (free + used) / 1024
853+
        self.facts['swaptotal_mb'] = (free + used) / 1024
854-
        self.facts['swap_allocated_mb'] = allocated / 1024
854+
        self.facts['swap_allocated_mb'] = allocated / 1024
855-
        self.facts['swap_reserved_mb'] = reserved / 1024
855+
        self.facts['swap_reserved_mb'] = reserved / 1024
856-
856+
857-
class OpenBSDHardware(Hardware):
857+
class OpenBSDHardware(Hardware):
858-
    """
858+
    """
859-
    OpenBSD-specific subclass of Hardware. Defines memory, CPU and device facts:
859+
    OpenBSD-specific subclass of Hardware. Defines memory, CPU and device facts:
860-
    - memfree_mb
860+
    - memfree_mb
861-
    - memtotal_mb
861+
    - memtotal_mb
862-
    - swapfree_mb
862+
    - swapfree_mb
863-
    - swaptotal_mb
863+
    - swaptotal_mb
864-
    - processor (a list)
864+
    - processor (a list)
865-
    - processor_cores
865+
    - processor_cores
866-
    - processor_count
866+
    - processor_count
867-
    - processor_speed
867+
    - processor_speed
868-
    - devices
868+
    - devices
869-
    """
869+
    """
870-
    platform = 'OpenBSD'
870+
    platform = 'OpenBSD'
871-
    DMESG_BOOT = '/var/run/dmesg.boot'
871+
    DMESG_BOOT = '/var/run/dmesg.boot'
872-
872+
873-
    def __init__(self):
873+
    def __init__(self):
874-
        Hardware.__init__(self)
874+
        Hardware.__init__(self)
875-
875+
876-
    def populate(self):
876+
    def populate(self):
877-
        self.sysctl = self.get_sysctl()
877+
        self.sysctl = self.get_sysctl()
878-
        self.get_memory_facts()
878+
        self.get_memory_facts()
879-
        self.get_processor_facts()
879+
        self.get_processor_facts()
880-
        self.get_device_facts()
880+
        self.get_device_facts()
881-
        return self.facts
881+
        return self.facts
882-
882+
883-
    def get_sysctl(self):
883+
    def get_sysctl(self):
884-
        rc, out, err = module.run_command(["/sbin/sysctl", "hw"])
884+
        rc, out, err = module.run_command(["/sbin/sysctl", "hw"])
885-
        if rc != 0:
885+
        if rc != 0:
886-
            return dict()
886+
            return dict()
887-
        sysctl = dict()
887+
        sysctl = dict()
888-
        for line in out.splitlines():
888+
        for line in out.splitlines():
889-
            (key, value) = line.split('=')
889+
            (key, value) = line.split('=')
890-
            sysctl[key] = value.strip()
890+
            sysctl[key] = value.strip()
891-
        return sysctl
891+
        return sysctl
892-
892+
893-
    def get_memory_facts(self):
893+
    def get_memory_facts(self):
894-
        # Get free memory. vmstat output looks like:
894+
        # Get free memory. vmstat output looks like:
895-
        #  procs    memory       page                    disks    traps          cpu
895+
        #  procs    memory       page                    disks    traps          cpu
896-
        #  r b w    avm     fre  flt  re  pi  po  fr  sr wd0 fd0  int   sys   cs us sy id
896+
        #  r b w    avm     fre  flt  re  pi  po  fr  sr wd0 fd0  int   sys   cs us sy id
897-
        #  0 0 0  47512   28160   51   0   0   0   0   0   1   0  116    89   17  0  1 99
897+
        #  0 0 0  47512   28160   51   0   0   0   0   0   1   0  116    89   17  0  1 99
898-
        rc, out, err = module.run_command("/usr/bin/vmstat")
898+
        rc, out, err = module.run_command("/usr/bin/vmstat")
899-
        if rc == 0:
899+
        if rc == 0:
900-
            self.facts['memfree_mb'] = long(out.splitlines()[-1].split()[4]) / 1024
900+
            self.facts['memfree_mb'] = long(out.splitlines()[-1].split()[4]) / 1024
901-
            self.facts['memtotal_mb'] = long(self.sysctl['hw.usermem']) / 1024 / 1024
901+
            self.facts['memtotal_mb'] = long(self.sysctl['hw.usermem']) / 1024 / 1024
902-
902+
903-
        # Get swapctl info. swapctl output looks like:
903+
        # Get swapctl info. swapctl output looks like:
904-
        # total: 69268 1K-blocks allocated, 0 used, 69268 available
904+
        # total: 69268 1K-blocks allocated, 0 used, 69268 available
905-
        # And for older OpenBSD:
905+
        # And for older OpenBSD:
906-
        # total: 69268k bytes allocated = 0k used, 69268k available
906+
        # total: 69268k bytes allocated = 0k used, 69268k available
907-
        rc, out, err = module.run_command("/sbin/swapctl -sk")
907+
        rc, out, err = module.run_command("/sbin/swapctl -sk")
908-
        if rc == 0:
908+
        if rc == 0:
909-
            data = out.split()
909+
            data = out.split()
910-
            self.facts['swapfree_mb'] = long(data[-2].translate(None, "kmg")) / 1024
910+
            self.facts['swapfree_mb'] = long(data[-2].translate(None, "kmg")) / 1024
911-
            self.facts['swaptotal_mb'] = long(data[1].translate(None, "kmg")) / 1024
911+
            self.facts['swaptotal_mb'] = long(data[1].translate(None, "kmg")) / 1024
912-
912+
913-
    def get_processor_facts(self):
913+
    def get_processor_facts(self):
914-
        processor = []
914+
        processor = []
915-
        dmesg_boot = get_file_content(OpenBSDHardware.DMESG_BOOT)
915+
        dmesg_boot = get_file_content(OpenBSDHardware.DMESG_BOOT)
916-
        if not dmesg_boot:
916+
        if not dmesg_boot:
917-
            rc, dmesg_boot, err = module.run_command("/sbin/dmesg")
917+
            rc, dmesg_boot, err = module.run_command("/sbin/dmesg")
918-
        i = 0
918+
        i = 0
919-
        for line in dmesg_boot.splitlines():
919+
        for line in dmesg_boot.splitlines():
920-
            if line.split(' ', 1)[0] == 'cpu%i:' % i:
920+
            if line.split(' ', 1)[0] == 'cpu%i:' % i:
921-
                processor.append(line.split(' ', 1)[1])
921+
                processor.append(line.split(' ', 1)[1])
922-
                i = i + 1
922+
                i = i + 1
923-
        processor_count = i
923+
        processor_count = i
924-
        self.facts['processor'] = processor
924+
        self.facts['processor'] = processor
925-
        self.facts['processor_count'] = processor_count
925+
        self.facts['processor_count'] = processor_count
926-
        # I found no way to figure out the number of Cores per CPU in OpenBSD
926+
        # I found no way to figure out the number of Cores per CPU in OpenBSD
927-
        self.facts['processor_cores'] = 'NA'
927+
        self.facts['processor_cores'] = 'NA'
928-
928+
929-
    def get_device_facts(self):
929+
    def get_device_facts(self):
930-
        devices = []
930+
        devices = []
931-
        devices.extend(self.sysctl['hw.disknames'].split(','))
931+
        devices.extend(self.sysctl['hw.disknames'].split(','))
932-
        self.facts['devices'] = devices
932+
        self.facts['devices'] = devices
933-
933+
934-
class FreeBSDHardware(Hardware):
934+
class FreeBSDHardware(Hardware):
935-
    """
935+
    """
936-
    FreeBSD-specific subclass of Hardware.  Defines memory and CPU facts:
936+
    FreeBSD-specific subclass of Hardware.  Defines memory and CPU facts:
937-
    - memfree_mb
937+
    - memfree_mb
938-
    - memtotal_mb
938+
    - memtotal_mb
939-
    - swapfree_mb
939+
    - swapfree_mb
940-
    - swaptotal_mb
940+
    - swaptotal_mb
941-
    - processor (a list)
941+
    - processor (a list)
942-
    - processor_cores
942+
    - processor_cores
943-
    - processor_count
943+
    - processor_count
944-
    - devices
944+
    - devices
945-
    """
945+
    """
946-
    platform = 'FreeBSD'
946+
    platform = 'FreeBSD'
947-
    DMESG_BOOT = '/var/run/dmesg.boot'
947+
    DMESG_BOOT = '/var/run/dmesg.boot'
948-
948+
949-
    def __init__(self):
949+
    def __init__(self):
950-
        Hardware.__init__(self)
950+
        Hardware.__init__(self)
951-
951+
952-
    def populate(self):
952+
    def populate(self):
953-
        self.get_cpu_facts()
953+
        self.get_cpu_facts()
954-
        self.get_memory_facts()
954+
        self.get_memory_facts()
955-
        self.get_dmi_facts()
955+
        self.get_dmi_facts()
956-
        self.get_device_facts()
956+
        self.get_device_facts()
957-
        try:
957+
        try:
958-
            self.get_mount_facts()
958+
            self.get_mount_facts()
959-
        except TimeoutError:
959+
        except TimeoutError:
960-
            pass
960+
            pass
961-
        return self.facts
961+
        return self.facts
962-
962+
963-
    def get_cpu_facts(self):
963+
    def get_cpu_facts(self):
964-
        self.facts['processor'] = []
964+
        self.facts['processor'] = []
965-
        rc, out, err = module.run_command("/sbin/sysctl -n hw.ncpu")
965+
        rc, out, err = module.run_command("/sbin/sysctl -n hw.ncpu")
966-
        self.facts['processor_count'] = out.strip()
966+
        self.facts['processor_count'] = out.strip()
967-
967+
968-
        dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT)
968+
        dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT)
969-
        if not dmesg_boot:
969+
        if not dmesg_boot:
970-
            rc, dmesg_boot, err = module.run_command("/sbin/dmesg")
970+
            rc, dmesg_boot, err = module.run_command("/sbin/dmesg")
971-
        for line in dmesg_boot.split('\n'):
971+
        for line in dmesg_boot.split('\n'):
972-
            if 'CPU:' in line:
972+
            if 'CPU:' in line:
973-
                cpu = re.sub(r'CPU:\s+', r"", line)
973+
                cpu = re.sub(r'CPU:\s+', r"", line)
974-
                self.facts['processor'].append(cpu.strip())
974+
                self.facts['processor'].append(cpu.strip())
975-
            if 'Logical CPUs per core' in line:
975+
            if 'Logical CPUs per core' in line:
976-
                self.facts['processor_cores'] = line.split()[4]
976+
                self.facts['processor_cores'] = line.split()[4]
977-
977+
978-
978+
979-
    def get_memory_facts(self):
979+
    def get_memory_facts(self):
980-
        rc, out, err = module.run_command("/sbin/sysctl vm.stats")
980+
        rc, out, err = module.run_command("/sbin/sysctl vm.stats")
981-
        for line in out.split('\n'):
981+
        for line in out.split('\n'):
982-
            data = line.split()
982+
            data = line.split()
983-
            if 'vm.stats.vm.v_page_size' in line:
983+
            if 'vm.stats.vm.v_page_size' in line:
984-
                pagesize = long(data[1])
984+
                pagesize = long(data[1])
985-
            if 'vm.stats.vm.v_page_count' in line:
985+
            if 'vm.stats.vm.v_page_count' in line:
986-
                pagecount = long(data[1])
986+
                pagecount = long(data[1])
987-
            if 'vm.stats.vm.v_free_count' in line:
987+
            if 'vm.stats.vm.v_free_count' in line:
988-
                freecount = long(data[1])
988+
                freecount = long(data[1])
989-
        self.facts['memtotal_mb'] = pagesize * pagecount / 1024 / 1024
989+
        self.facts['memtotal_mb'] = pagesize * pagecount / 1024 / 1024
990-
        self.facts['memfree_mb'] = pagesize * freecount / 1024 / 1024
990+
        self.facts['memfree_mb'] = pagesize * freecount / 1024 / 1024
991-
        # Get swapinfo.  swapinfo output looks like:
991+
        # Get swapinfo.  swapinfo output looks like:
992-
        # Device          1M-blocks     Used    Avail Capacity
992+
        # Device          1M-blocks     Used    Avail Capacity
993-
        # /dev/ada0p3        314368        0   314368     0%
993+
        # /dev/ada0p3        314368        0   314368     0%
994-
        #
994+
        #
995-
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m")
995+
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m")
996-
        lines = out.split('\n')
996+
        lines = out.split('\n')
997-
        if len(lines[-1]) == 0:
997+
        if len(lines[-1]) == 0:
998-
            lines.pop()
998+
            lines.pop()
999-
        data = lines[-1].split()
999+
        data = lines[-1].split()
1000-
        self.facts['swaptotal_mb'] = data[1]
1000+
        self.facts['swaptotal_mb'] = data[1]
1001-
        self.facts['swapfree_mb'] = data[3]
1001+
        self.facts['swapfree_mb'] = data[3]
1002-
1002+
1003-
    @timeout(10)
1003+
    @timeout(10)
1004-
    def get_mount_facts(self):
1004+
    def get_mount_facts(self):
1005-
        self.facts['mounts'] = []
1005+
        self.facts['mounts'] = []
1006-
        fstab = get_file_content('/etc/fstab')
1006+
        fstab = get_file_content('/etc/fstab')
1007-
        if fstab:
1007+
        if fstab:
1008-
            for line in fstab.split('\n'):
1008+
            for line in fstab.split('\n'):
1009-
                if line.startswith('#') or line.strip() == '':
1009+
                if line.startswith('#') or line.strip() == '':
1010-
                    continue
1010+
                    continue
1011-
                fields = re.sub(r'\s+',' ',line.rstrip('\n')).split()
1011+
                fields = re.sub(r'\s+',' ',line.rstrip('\n')).split()
1012-
                self.facts['mounts'].append({'mount': fields[1] , 'device': fields[0], 'fstype' : fields[2], 'options': fields[3]})
1012+
                self.facts['mounts'].append({'mount': fields[1] , 'device': fields[0], 'fstype' : fields[2], 'options': fields[3]})
1013-
1013+
1014-
    def get_device_facts(self):
1014+
    def get_device_facts(self):
1015-
        sysdir = '/dev'
1015+
        sysdir = '/dev'
1016-
        self.facts['devices'] = {}
1016+
        self.facts['devices'] = {}
1017-
        drives = re.compile('(ada?\d+|da\d+|a?cd\d+)') #TODO: rc, disks, err = module.run_command("/sbin/sysctl kern.disks")
1017+
        drives = re.compile('(ada?\d+|da\d+|a?cd\d+)') #TODO: rc, disks, err = module.run_command("/sbin/sysctl kern.disks")
1018-
        slices = re.compile('(ada?\d+s\d+\w*|da\d+s\d+\w*)')
1018+
        slices = re.compile('(ada?\d+s\d+\w*|da\d+s\d+\w*)')
1019-
        if os.path.isdir(sysdir):
1019+
        if os.path.isdir(sysdir):
1020-
            dirlist = sorted(os.listdir(sysdir))
1020+
            dirlist = sorted(os.listdir(sysdir))
1021-
            for device in dirlist:
1021+
            for device in dirlist:
1022-
                d = drives.match(device)
1022+
                d = drives.match(device)
1023-
                if d:
1023+
                if d:
1024-
                    self.facts['devices'][d.group(1)] = []
1024+
                    self.facts['devices'][d.group(1)] = []
1025-
                s = slices.match(device)
1025+
                s = slices.match(device)
1026-
                if s:
1026+
                if s:
1027-
                    self.facts['devices'][d.group(1)].append(s.group(1))
1027+
                    self.facts['devices'][d.group(1)].append(s.group(1))
1028-
1028+
1029-
    def get_dmi_facts(self):
1029+
    def get_dmi_facts(self):
1030-
        ''' learn dmi facts from system
1030+
        ''' learn dmi facts from system
1031-
1031+
1032-
        Use dmidecode executable if available'''
1032+
        Use dmidecode executable if available'''
1033-
1033+
1034-
        # Fall back to using dmidecode, if available
1034+
        # Fall back to using dmidecode, if available
1035-
        dmi_bin = module.get_bin_path('dmidecode')
1035+
        dmi_bin = module.get_bin_path('dmidecode')
1036-
        DMI_DICT = dict(
1036+
        DMI_DICT = dict(
1037-
            bios_date='bios-release-date',
1037+
            bios_date='bios-release-date',
1038-
            bios_version='bios-version',
1038+
            bios_version='bios-version',
1039-
            form_factor='chassis-type',
1039+
            form_factor='chassis-type',
1040-
            product_name='system-product-name',
1040+
            product_name='system-product-name',
1041-
            product_serial='system-serial-number',
1041+
            product_serial='system-serial-number',
1042-
            product_uuid='system-uuid',
1042+
            product_uuid='system-uuid',
1043-
            product_version='system-version',
1043+
            product_version='system-version',
1044-
            system_vendor='system-manufacturer'
1044+
            system_vendor='system-manufacturer'
1045-
        )
1045+
        )
1046-
        for (k, v) in DMI_DICT.items():
1046+
        for (k, v) in DMI_DICT.items():
1047-
            if dmi_bin is not None:
1047+
            if dmi_bin is not None:
1048-
                (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v))
1048+
                (rc, out, err) = module.run_command('%s -s %s' % (dmi_bin, v))
1049-
                if rc == 0:
1049+
                if rc == 0:
1050-
                    # Strip out commented lines (specific dmidecode output)
1050+
                    # Strip out commented lines (specific dmidecode output)
1051-
                    self.facts[k] = ''.join([ line for line in out.split('\n') if not line.startswith('#') ])
1051+
                    self.facts[k] = ''.join([ line for line in out.split('\n') if not line.startswith('#') ])
1052-
                    try:
1052+
                    try:
1053-
                        json.dumps(self.facts[k])
1053+
                        json.dumps(self.facts[k])
1054-
                    except UnicodeDecodeError:
1054+
                    except UnicodeDecodeError:
1055-
                        self.facts[k] = 'NA'
1055+
                        self.facts[k] = 'NA'
1056-
                else:
1056+
                else:
1057-
                    self.facts[k] = 'NA'
1057+
                    self.facts[k] = 'NA'
1058-
            else:
1058+
            else:
1059-
                self.facts[k] = 'NA'
1059+
                self.facts[k] = 'NA'
1060-
1060+
1061-
1061+
1062-
class NetBSDHardware(Hardware):
1062+
class NetBSDHardware(Hardware):
1063-
    """
1063+
    """
1064-
    NetBSD-specific subclass of Hardware.  Defines memory and CPU facts:
1064+
    NetBSD-specific subclass of Hardware.  Defines memory and CPU facts:
1065-
    - memfree_mb
1065+
    - memfree_mb
1066-
    - memtotal_mb
1066+
    - memtotal_mb
1067-
    - swapfree_mb
1067+
    - swapfree_mb
1068-
    - swaptotal_mb
1068+
    - swaptotal_mb
1069-
    - processor (a list)
1069+
    - processor (a list)
1070-
    - processor_cores
1070+
    - processor_cores
1071-
    - processor_count
1071+
    - processor_count
1072-
    - devices
1072+
    - devices
1073-
    """
1073+
    """
1074-
    platform = 'NetBSD'
1074+
    platform = 'NetBSD'
1075-
    MEMORY_FACTS = ['MemTotal', 'SwapTotal', 'MemFree', 'SwapFree']
1075+
    MEMORY_FACTS = ['MemTotal', 'SwapTotal', 'MemFree', 'SwapFree']
1076-
1076+
1077-
    def __init__(self):
1077+
    def __init__(self):
1078-
        Hardware.__init__(self)
1078+
        Hardware.__init__(self)
1079-
1079+
1080-
    def populate(self):
1080+
    def populate(self):
1081-
        self.get_cpu_facts()
1081+
        self.get_cpu_facts()
1082-
        self.get_memory_facts()
1082+
        self.get_memory_facts()
1083-
        try:
1083+
        try:
1084-
            self.get_mount_facts()
1084+
            self.get_mount_facts()
1085-
        except TimeoutError:
1085+
        except TimeoutError:
1086-
            pass
1086+
            pass
1087-
        return self.facts
1087+
        return self.facts
1088-
1088+
1089-
    def get_cpu_facts(self):
1089+
    def get_cpu_facts(self):
1090-
1090+
1091-
        i = 0
1091+
        i = 0
1092-
        physid = 0
1092+
        physid = 0
1093-
        sockets = {}
1093+
        sockets = {}
1094-
        if not os.access("/proc/cpuinfo", os.R_OK):
1094+
        if not os.access("/proc/cpuinfo", os.R_OK):
1095-
            return
1095+
            return
1096-
        self.facts['processor'] = []
1096+
        self.facts['processor'] = []
1097-
        for line in open("/proc/cpuinfo").readlines():
1097+
        for line in open("/proc/cpuinfo").readlines():
1098-
            data = line.split(":", 1)
1098+
            data = line.split(":", 1)
1099-
            key = data[0].strip()
1099+
            key = data[0].strip()
1100-
            # model name is for Intel arch, Processor (mind the uppercase P)
1100+
            # model name is for Intel arch, Processor (mind the uppercase P)
1101-
            # works for some ARM devices, like the Sheevaplug.
1101+
            # works for some ARM devices, like the Sheevaplug.
1102-
            if key == 'model name' or key == 'Processor':
1102+
            if key == 'model name' or key == 'Processor':
1103-
                if 'processor' not in self.facts:
1103+
                if 'processor' not in self.facts:
1104-
                    self.facts['processor'] = []
1104+
                    self.facts['processor'] = []
1105-
                self.facts['processor'].append(data[1].strip())
1105+
                self.facts['processor'].append(data[1].strip())
1106-
                i += 1
1106+
                i += 1
1107-
            elif key == 'physical id':
1107+
            elif key == 'physical id':
1108-
                physid = data[1].strip()
1108+
                physid = data[1].strip()
1109-
                if physid not in sockets:
1109+
                if physid not in sockets:
1110-
                    sockets[physid] = 1
1110+
                    sockets[physid] = 1
1111-
            elif key == 'cpu cores':
1111+
            elif key == 'cpu cores':
1112-
                sockets[physid] = int(data[1].strip())
1112+
                sockets[physid] = int(data[1].strip())
1113-
        if len(sockets) > 0:
1113+
        if len(sockets) > 0:
1114-
            self.facts['processor_count'] = len(sockets)
1114+
            self.facts['processor_count'] = len(sockets)
1115-
            self.facts['processor_cores'] = reduce(lambda x, y: x + y, sockets.values())
1115+
            self.facts['processor_cores'] = reduce(lambda x, y: x + y, sockets.values())
1116-
        else:
1116+
        else:
1117-
            self.facts['processor_count'] = i
1117+
            self.facts['processor_count'] = i
1118-
            self.facts['processor_cores'] = 'NA'
1118+
            self.facts['processor_cores'] = 'NA'
1119-
1119+
1120-
    def get_memory_facts(self):
1120+
    def get_memory_facts(self):
1121-
        if not os.access("/proc/meminfo", os.R_OK):
1121+
        if not os.access("/proc/meminfo", os.R_OK):
1122-
            return
1122+
            return
1123-
        for line in open("/proc/meminfo").readlines():
1123+
        for line in open("/proc/meminfo").readlines():
1124-
            data = line.split(":", 1)
1124+
            data = line.split(":", 1)
1125-
            key = data[0]
1125+
            key = data[0]
1126-
            if key in NetBSDHardware.MEMORY_FACTS:
1126+
            if key in NetBSDHardware.MEMORY_FACTS:
1127-
                val = data[1].strip().split(' ')[0]
1127+
                val = data[1].strip().split(' ')[0]
1128-
                self.facts["%s_mb" % key.lower()] = long(val) / 1024
1128+
                self.facts["%s_mb" % key.lower()] = long(val) / 1024
1129-
1129+
1130-
    @timeout(10)
1130+
    @timeout(10)
1131-
    def get_mount_facts(self):
1131+
    def get_mount_facts(self):
1132-
        self.facts['mounts'] = []
1132+
        self.facts['mounts'] = []
1133-
        fstab = get_file_content('/etc/fstab')
1133+
        fstab = get_file_content('/etc/fstab')
1134-
        if fstab:
1134+
        if fstab:
1135-
            for line in fstab.split('\n'):
1135+
            for line in fstab.split('\n'):
1136-
                if line.startswith('#') or line.strip() == '':
1136+
                if line.startswith('#') or line.strip() == '':
1137-
                    continue
1137+
                    continue
1138-
                fields = re.sub(r'\s+',' ',line.rstrip('\n')).split()
1138+
                fields = re.sub(r'\s+',' ',line.rstrip('\n')).split()
1139-
                self.facts['mounts'].append({'mount': fields[1] , 'device': fields[0], 'fstype' : fields[2], 'options': fields[3]})
1139+
                self.facts['mounts'].append({'mount': fields[1] , 'device': fields[0], 'fstype' : fields[2], 'options': fields[3]})
1140-
1140+
1141-
class AIX(Hardware):
1141+
class AIX(Hardware):
1142-
    """
1142+
    """
1143-
    AIX-specific subclass of Hardware.  Defines memory and CPU facts:
1143+
    AIX-specific subclass of Hardware.  Defines memory and CPU facts:
1144-
    - memfree_mb
1144+
    - memfree_mb
1145-
    - memtotal_mb
1145+
    - memtotal_mb
1146-
    - swapfree_mb
1146+
    - swapfree_mb
1147-
    - swaptotal_mb
1147+
    - swaptotal_mb
1148-
    - processor (a list)
1148+
    - processor (a list)
1149-
    - processor_cores
1149+
    - processor_cores
1150-
    - processor_count
1150+
    - processor_count
1151-
    """
1151+
    """
1152-
    platform = 'AIX'
1152+
    platform = 'AIX'
1153-
1153+
1154-
    def __init__(self):
1154+
    def __init__(self):
1155-
        Hardware.__init__(self)
1155+
        Hardware.__init__(self)
1156-
1156+
1157-
    def populate(self):
1157+
    def populate(self):
1158-
        self.get_cpu_facts()
1158+
        self.get_cpu_facts()
1159-
        self.get_memory_facts()
1159+
        self.get_memory_facts()
1160-
        self.get_dmi_facts()
1160+
        self.get_dmi_facts()
1161-
        return self.facts
1161+
        return self.facts
1162-
1162+
1163-
    def get_cpu_facts(self):
1163+
    def get_cpu_facts(self):
1164-
        self.facts['processor'] = []
1164+
        self.facts['processor'] = []
1165-
1165+
1166-
1166+
1167-
        rc, out, err = module.run_command("/usr/sbin/lsdev -Cc processor")
1167+
        rc, out, err = module.run_command("/usr/sbin/lsdev -Cc processor")
1168-
        if out:
1168+
        if out:
1169-
            i = 0
1169+
            i = 0
1170-
            for line in out.split('\n'):
1170+
            for line in out.split('\n'):
1171-
1171+
1172-
                if 'Available' in line:
1172+
                if 'Available' in line:
1173-
                    if i == 0:
1173+
                    if i == 0:
1174-
                        data = line.split(' ')
1174+
                        data = line.split(' ')
1175-
                        cpudev = data[0]
1175+
                        cpudev = data[0]
1176-
1176+
1177-
                    i += 1
1177+
                    i += 1
1178-
            self.facts['processor_count'] = int(i)
1178+
            self.facts['processor_count'] = int(i)
1179-
1179+
1180-
            rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a type")
1180+
            rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a type")
1181-
1181+
1182-
            data = out.split(' ')
1182+
            data = out.split(' ')
1183-
            self.facts['processor'] = data[1]
1183+
            self.facts['processor'] = data[1]
1184-
1184+
1185-
            rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a smt_threads")
1185+
            rc, out, err = module.run_command("/usr/sbin/lsattr -El " + cpudev + " -a smt_threads")
1186-
1186+
1187-
            data = out.split(' ')
1187+
            data = out.split(' ')
1188-
            self.facts['processor_cores'] = int(data[1])
1188+
            self.facts['processor_cores'] = int(data[1])
1189-
1189+
1190-
    def get_memory_facts(self):
1190+
    def get_memory_facts(self):
1191-
        pagesize = 4096
1191+
        pagesize = 4096
1192-
        rc, out, err = module.run_command("/usr/bin/vmstat -v")
1192+
        rc, out, err = module.run_command("/usr/bin/vmstat -v")
1193-
        for line in out.split('\n'):
1193+
        for line in out.split('\n'):
1194-
            data = line.split()
1194+
            data = line.split()
1195-
            if 'memory pages' in line:
1195+
            if 'memory pages' in line:
1196-
                pagecount = long(data[0])
1196+
                pagecount = long(data[0])
1197-
            if 'free pages' in line:
1197+
            if 'free pages' in line:
1198-
                freecount = long(data[0])
1198+
                freecount = long(data[0])
1199-
        self.facts['memtotal_mb'] = pagesize * pagecount / 1024 / 1024
1199+
        self.facts['memtotal_mb'] = pagesize * pagecount / 1024 / 1024
1200-
        self.facts['memfree_mb'] = pagesize * freecount / 1024 / 1024
1200+
        self.facts['memfree_mb'] = pagesize * freecount / 1024 / 1024
1201-
        # Get swapinfo.  swapinfo output looks like:
1201+
        # Get swapinfo.  swapinfo output looks like:
1202-
        # Device          1M-blocks     Used    Avail Capacity
1202+
        # Device          1M-blocks     Used    Avail Capacity
1203-
        # /dev/ada0p3        314368        0   314368     0%
1203+
        # /dev/ada0p3        314368        0   314368     0%
1204-
        #
1204+
        #
1205-
        rc, out, err = module.run_command("/usr/sbin/lsps -s")
1205+
        rc, out, err = module.run_command("/usr/sbin/lsps -s")
1206-
        if out:
1206+
        if out:
1207-
            lines = out.split('\n')
1207+
            lines = out.split('\n')
1208-
            data = lines[1].split()
1208+
            data = lines[1].split()
1209-
            swaptotal_mb = long(data[0].rstrip('MB'))
1209+
            swaptotal_mb = long(data[0].rstrip('MB'))
1210-
            percused = int(data[1].rstrip('%'))
1210+
            percused = int(data[1].rstrip('%'))
1211-
            self.facts['swaptotal_mb'] = swaptotal_mb
1211+
            self.facts['swaptotal_mb'] = swaptotal_mb
1212-
            self.facts['swapfree_mb'] = long(swaptotal_mb * ( 100 - percused ) / 100)
1212+
            self.facts['swapfree_mb'] = long(swaptotal_mb * ( 100 - percused ) / 100)
1213-
1213+
1214-
    def get_dmi_facts(self):
1214+
    def get_dmi_facts(self):
1215-
        rc, out, err = module.run_command("/usr/sbin/lsattr -El sys0 -a fwversion")
1215+
        rc, out, err = module.run_command("/usr/sbin/lsattr -El sys0 -a fwversion")
1216-
        data = out.split()
1216+
        data = out.split()
1217-
        self.facts['firmware_version'] = data[1].strip('IBM,')
1217+
        self.facts['firmware_version'] = data[1].strip('IBM,')
1218-
1218+
1219-
class HPUX(Hardware):
1219+
class HPUX(Hardware):
1220-
    """
1220+
    """
1221-
    HP-UX-specifig subclass of Hardware. Defines memory and CPU facts:
1221+
    HP-UX-specifig subclass of Hardware. Defines memory and CPU facts:
1222-
    - memfree_mb
1222+
    - memfree_mb
1223-
    - memtotal_mb
1223+
    - memtotal_mb
1224-
    - swapfree_mb
1224+
    - swapfree_mb
1225-
    - swaptotal_mb
1225+
    - swaptotal_mb
1226-
    - processor
1226+
    - processor
1227-
    - processor_cores
1227+
    - processor_cores
1228-
    - processor_count
1228+
    - processor_count
1229-
    - model
1229+
    - model
1230-
    - firmware
1230+
    - firmware
1231-
    """
1231+
    """
1232-
1232+
1233-
    platform = 'HP-UX'
1233+
    platform = 'HP-UX'
1234-
1234+
1235-
    def __init__(self):
1235+
    def __init__(self):
1236-
        Hardware.__init__(self)
1236+
        Hardware.__init__(self)
1237-
1237+
1238-
    def populate(self):
1238+
    def populate(self):
1239-
        self.get_cpu_facts()
1239+
        self.get_cpu_facts()
1240-
        self.get_memory_facts()
1240+
        self.get_memory_facts()
1241-
        self.get_hw_facts()
1241+
        self.get_hw_facts()
1242-
        return self.facts
1242+
        return self.facts
1243-
1243+
1244-
    def get_cpu_facts(self):
1244+
    def get_cpu_facts(self):
1245-
        if self.facts['architecture'] == '9000/800':
1245+
        if self.facts['architecture'] == '9000/800':
1246-
            rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True)
1246+
            rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True)
1247-
            self.facts['processor_count'] = int(out.strip())
1247+
            self.facts['processor_count'] = int(out.strip())
1248-
        #Working with machinfo mess
1248+
        #Working with machinfo mess
1249-
        elif self.facts['architecture'] == 'ia64':
1249+
        elif self.facts['architecture'] == 'ia64':
1250-
            if self.facts['distribution_version'] == "B.11.23":
1250+
            if self.facts['distribution_version'] == "B.11.23":
1251-
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'Number of CPUs'", use_unsafe_shell=True)
1251+
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'Number of CPUs'", use_unsafe_shell=True)
1252-
                self.facts['processor_count'] = int(out.strip().split('=')[1])
1252+
                self.facts['processor_count'] = int(out.strip().split('=')[1])
1253-
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'processor family'", use_unsafe_shell=True)
1253+
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep 'processor family'", use_unsafe_shell=True)
1254-
                self.facts['processor'] = re.search('.*(Intel.*)', out).groups()[0].strip()
1254+
                self.facts['processor'] = re.search('.*(Intel.*)', out).groups()[0].strip()
1255-
                rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True)
1255+
                rc, out, err = module.run_command("ioscan -FkCprocessor | wc -l", use_unsafe_shell=True)
1256-
                self.facts['processor_cores'] = int(out.strip())
1256+
                self.facts['processor_cores'] = int(out.strip())
1257-
            if self.facts['distribution_version'] == "B.11.31":
1257+
            if self.facts['distribution_version'] == "B.11.31":
1258-
                #if machinfo return cores strings release B.11.31 > 1204
1258+
                #if machinfo return cores strings release B.11.31 > 1204
1259-
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep core | wc -l", use_unsafe_shell=True)
1259+
                rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep core | wc -l", use_unsafe_shell=True)
1260-
                if out.strip()== '0':
1260+
                if out.strip()== '0':
1261-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True)
1261+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True)
1262-
                    self.facts['processor_count'] = int(out.strip().split(" ")[0])
1262+
                    self.facts['processor_count'] = int(out.strip().split(" ")[0])
1263-
                    #If hyperthreading is active divide cores by 2
1263+
                    #If hyperthreading is active divide cores by 2
1264-
                    rc, out, err = module.run_command("/usr/sbin/psrset | grep LCPU", use_unsafe_shell=True)
1264+
                    rc, out, err = module.run_command("/usr/sbin/psrset | grep LCPU", use_unsafe_shell=True)
1265-
                    data = re.sub(' +',' ',out).strip().split(' ')
1265+
                    data = re.sub(' +',' ',out).strip().split(' ')
1266-
                    if len(data) == 1:
1266+
                    if len(data) == 1:
1267-
                        hyperthreading = 'OFF'
1267+
                        hyperthreading = 'OFF'
1268-
                    else:
1268+
                    else:
1269-
                        hyperthreading = data[1]
1269+
                        hyperthreading = data[1]
1270-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep logical", use_unsafe_shell=True)
1270+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep logical", use_unsafe_shell=True)
1271-
                    data = out.strip().split(" ")
1271+
                    data = out.strip().split(" ")
1272-
                    if hyperthreading == 'ON':
1272+
                    if hyperthreading == 'ON':
1273-
                        self.facts['processor_cores'] = int(data[0])/2
1273+
                        self.facts['processor_cores'] = int(data[0])/2
1274-
                    else:
1274+
                    else:
1275-
                        if len(data) == 1:
1275+
                        if len(data) == 1:
1276-
                            self.facts['processor_cores'] = self.facts['processor_count']
1276+
                            self.facts['processor_cores'] = self.facts['processor_count']
1277-
                        else:
1277+
                        else:
1278-
                            self.facts['processor_cores'] = int(data[0])
1278+
                            self.facts['processor_cores'] = int(data[0])
1279-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel |cut -d' ' -f4-", use_unsafe_shell=True)
1279+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel |cut -d' ' -f4-", use_unsafe_shell=True)
1280-
                    self.facts['processor'] = out.strip()
1280+
                    self.facts['processor'] = out.strip()
1281-
                else:
1281+
                else:
1282-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | egrep 'socket[s]?$' | tail -1", use_unsafe_shell=True)
1282+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | egrep 'socket[s]?$' | tail -1", use_unsafe_shell=True)
1283-
                    self.facts['processor_count'] = int(out.strip().split(" ")[0])
1283+
                    self.facts['processor_count'] = int(out.strip().split(" ")[0])
1284-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep -e '[0-9] core' | tail -1", use_unsafe_shell=True)
1284+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep -e '[0-9] core' | tail -1", use_unsafe_shell=True)
1285-
                    self.facts['processor_cores'] = int(out.strip().split(" ")[0])
1285+
                    self.facts['processor_cores'] = int(out.strip().split(" ")[0])
1286-
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True)
1286+
                    rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Intel", use_unsafe_shell=True)
1287-
                    self.facts['processor'] = out.strip()
1287+
                    self.facts['processor'] = out.strip()
1288-
1288+
1289-
    def get_memory_facts(self):
1289+
    def get_memory_facts(self):
1290-
        pagesize = 4096
1290+
        pagesize = 4096
1291-
        rc, out, err = module.run_command("/usr/bin/vmstat | tail -1", use_unsafe_shell=True)
1291+
        rc, out, err = module.run_command("/usr/bin/vmstat | tail -1", use_unsafe_shell=True)
1292-
        data = int(re.sub(' +',' ',out).split(' ')[5].strip())
1292+
        data = int(re.sub(' +',' ',out).split(' ')[5].strip())
1293-
        self.facts['memfree_mb'] = pagesize * data / 1024 / 1024
1293+
        self.facts['memfree_mb'] = pagesize * data / 1024 / 1024
1294-
        if self.facts['architecture'] == '9000/800':
1294+
        if self.facts['architecture'] == '9000/800':
1295-
            rc, out, err = module.run_command("grep Physical /var/adm/syslog/syslog.log")
1295+
            rc, out, err = module.run_command("grep Physical /var/adm/syslog/syslog.log")
1296-
            data = re.search('.*Physical: ([0-9]*) Kbytes.*',out).groups()[0].strip()
1296+
            data = re.search('.*Physical: ([0-9]*) Kbytes.*',out).groups()[0].strip()
1297-
            self.facts['memtotal_mb'] = int(data) / 1024
1297+
            self.facts['memtotal_mb'] = int(data) / 1024
1298-
        else:
1298+
        else:
1299-
            rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Memory", use_unsafe_shell=True)
1299+
            rc, out, err = module.run_command("/usr/contrib/bin/machinfo | grep Memory", use_unsafe_shell=True)
1300-
            data = re.search('Memory[\ :=]*([0-9]*).*MB.*',out).groups()[0].strip()
1300+
            data = re.search('Memory[\ :=]*([0-9]*).*MB.*',out).groups()[0].strip()
1301-
            self.facts['memtotal_mb'] = int(data)
1301+
            self.facts['memtotal_mb'] = int(data)
1302-
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f -q")
1302+
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f -q")
1303-
        self.facts['swaptotal_mb'] = int(out.strip())
1303+
        self.facts['swaptotal_mb'] = int(out.strip())
1304-
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f | egrep '^dev|^fs'", use_unsafe_shell=True)
1304+
        rc, out, err = module.run_command("/usr/sbin/swapinfo -m -d -f | egrep '^dev|^fs'", use_unsafe_shell=True)
1305-
        swap = 0
1305+
        swap = 0
1306-
        for line in out.strip().split('\n'):
1306+
        for line in out.strip().split('\n'):
1307-
            swap += int(re.sub(' +',' ',line).split(' ')[3].strip())
1307+
            swap += int(re.sub(' +',' ',line).split(' ')[3].strip())
1308-
        self.facts['swapfree_mb'] = swap
1308+
        self.facts['swapfree_mb'] = swap
1309-
1309+
1310-
    def get_hw_facts(self):
1310+
    def get_hw_facts(self):
1311-
        rc, out, err = module.run_command("model")
1311+
        rc, out, err = module.run_command("model")
1312-
        self.facts['model'] = out.strip()
1312+
        self.facts['model'] = out.strip()
1313-
        if self.facts['architecture'] == 'ia64':
1313+
        if self.facts['architecture'] == 'ia64':
1314-
            rc, out, err = module.run_command("/usr/contrib/bin/machinfo |grep -i 'Firmware revision' | grep -v BMC", use_unsafe_shell=True)
1314+
            rc, out, err = module.run_command("/usr/contrib/bin/machinfo |grep -i 'Firmware revision' | grep -v BMC", use_unsafe_shell=True)
1315-
            self.facts['firmware_version'] = out.split(':')[1].strip()
1315+
            self.facts['firmware_version'] = out.split(':')[1].strip()
1316-
1316+
1317-
1317+
1318-
class Darwin(Hardware):
1318+
class Darwin(Hardware):
1319-
    """
1319+
    """
1320-
    Darwin-specific subclass of Hardware.  Defines memory and CPU facts:
1320+
    Darwin-specific subclass of Hardware.  Defines memory and CPU facts:
1321-
    - processor
1321+
    - processor
1322-
    - processor_cores
1322+
    - processor_cores
1323-
    - memtotal_mb
1323+
    - memtotal_mb
1324-
    - memfree_mb
1324+
    - memfree_mb
1325-
    - model
1325+
    - model
1326-
    - osversion
1326+
    - osversion
1327-
    - osrevision
1327+
    - osrevision
1328-
    """
1328+
    """
1329-
    platform = 'Darwin'
1329+
    platform = 'Darwin'
1330-
1330+
1331-
    def __init__(self):
1331+
    def __init__(self):
1332-
        Hardware.__init__(self)
1332+
        Hardware.__init__(self)
1333-
1333+
1334-
    def populate(self):
1334+
    def populate(self):
1335-
        self.sysctl = self.get_sysctl()
1335+
        self.sysctl = self.get_sysctl()
1336-
        self.get_mac_facts()
1336+
        self.get_mac_facts()
1337-
        self.get_cpu_facts()
1337+
        self.get_cpu_facts()
1338-
        self.get_memory_facts()
1338+
        self.get_memory_facts()
1339-
        return self.facts
1339+
        return self.facts
1340-
1340+
1341-
    def get_sysctl(self):
1341+
    def get_sysctl(self):
1342-
        rc, out, err = module.run_command(["/usr/sbin/sysctl", "hw", "machdep", "kern"])
1342+
        rc, out, err = module.run_command(["/usr/sbin/sysctl", "hw", "machdep", "kern"])
1343-
        if rc != 0:
1343+
        if rc != 0:
1344-
            return dict()
1344+
            return dict()
1345-
        sysctl = dict()
1345+
        sysctl = dict()
1346-
        for line in out.splitlines():
1346+
        for line in out.splitlines():
1347-
            if line.rstrip("\n"):
1347+
            if line.rstrip("\n"):
1348-
                (key, value) = re.split(' = |: ', line, maxsplit=1)
1348+
                (key, value) = re.split(' = |: ', line, maxsplit=1)
1349-
                sysctl[key] = value.strip()
1349+
                sysctl[key] = value.strip()
1350-
        return sysctl
1350+
        return sysctl
1351-
1351+
1352-
    def get_system_profile(self):
1352+
    def get_system_profile(self):
1353-
        rc, out, err = module.run_command(["/usr/sbin/system_profiler", "SPHardwareDataType"])
1353+
        rc, out, err = module.run_command(["/usr/sbin/system_profiler", "SPHardwareDataType"])
1354-
        if rc != 0:
1354+
        if rc != 0:
1355-
            return dict()
1355+
            return dict()
1356-
        system_profile = dict()
1356+
        system_profile = dict()
1357-
        for line in out.splitlines():
1357+
        for line in out.splitlines():
1358-
            if ': ' in line:
1358+
            if ': ' in line:
1359-
                (key, value) = line.split(': ', 1)
1359+
                (key, value) = line.split(': ', 1)
1360-
                system_profile[key.strip()] = ' '.join(value.strip().split())
1360+
                system_profile[key.strip()] = ' '.join(value.strip().split())
1361-
        return system_profile
1361+
        return system_profile
1362-
1362+
1363-
    def get_mac_facts(self):
1363+
    def get_mac_facts(self):
1364-
        self.facts['model'] = self.sysctl['hw.model']
1364+
        self.facts['model'] = self.sysctl['hw.model']
1365-
        self.facts['osversion'] = self.sysctl['kern.osversion']
1365+
        self.facts['osversion'] = self.sysctl['kern.osversion']
1366-
        self.facts['osrevision'] = self.sysctl['kern.osrevision']
1366+
        self.facts['osrevision'] = self.sysctl['kern.osrevision']
1367-
1367+
1368-
    def get_cpu_facts(self):
1368+
    def get_cpu_facts(self):
1369-
        if 'machdep.cpu.brand_string' in self.sysctl: # Intel
1369+
        if 'machdep.cpu.brand_string' in self.sysctl: # Intel
1370-
            self.facts['processor'] = self.sysctl['machdep.cpu.brand_string']
1370+
            self.facts['processor'] = self.sysctl['machdep.cpu.brand_string']
1371-
            self.facts['processor_cores'] = self.sysctl['machdep.cpu.core_count']
1371+
            self.facts['processor_cores'] = self.sysctl['machdep.cpu.core_count']
1372-
        else: # PowerPC
1372+
        else: # PowerPC
1373-
            system_profile = self.get_system_profile()
1373+
            system_profile = self.get_system_profile()
1374-
            self.facts['processor'] = '%s @ %s' % (system_profile['Processor Name'], system_profile['Processor Speed'])
1374+
            self.facts['processor'] = '%s @ %s' % (system_profile['Processor Name'], system_profile['Processor Speed'])
1375-
            self.facts['processor_cores'] = self.sysctl['hw.physicalcpu']
1375+
            self.facts['processor_cores'] = self.sysctl['hw.physicalcpu']
1376-
1376+
1377-
    def get_memory_facts(self):
1377+
    def get_memory_facts(self):
1378-
        self.facts['memtotal_mb'] = long(self.sysctl['hw.memsize']) / 1024 / 1024
1378+
        self.facts['memtotal_mb'] = long(self.sysctl['hw.memsize']) / 1024 / 1024
1379-
        self.facts['memfree_mb'] = long(self.sysctl['hw.usermem']) / 1024 / 1024
1379+
        self.facts['memfree_mb'] = long(self.sysctl['hw.usermem']) / 1024 / 1024
1380-
1380+
1381-
class Network(Facts):
1381+
class Network(Facts):
1382-
    """
1382+
    """
1383-
    This is a generic Network subclass of Facts.  This should be further
1383+
    This is a generic Network subclass of Facts.  This should be further
1384-
    subclassed to implement per platform.  If you subclass this,
1384+
    subclassed to implement per platform.  If you subclass this,
1385-
    you must define:
1385+
    you must define:
1386-
    - interfaces (a list of interface names)
1386+
    - interfaces (a list of interface names)
1387-
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1387+
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1388-
1388+
1389-
    All subclasses MUST define platform.
1389+
    All subclasses MUST define platform.
1390-
    """
1390+
    """
1391-
    platform = 'Generic'
1391+
    platform = 'Generic'
1392-
1392+
1393-
    IPV6_SCOPE = { '0' : 'global',
1393+
    IPV6_SCOPE = { '0' : 'global',
1394-
                   '10' : 'host',
1394+
                   '10' : 'host',
1395-
                   '20' : 'link',
1395+
                   '20' : 'link',
1396-
                   '40' : 'admin',
1396+
                   '40' : 'admin',
1397-
                   '50' : 'site',
1397+
                   '50' : 'site',
1398-
                   '80' : 'organization' }
1398+
                   '80' : 'organization' }
1399-
1399+
1400-
    def __new__(cls, *arguments, **keyword):
1400+
    def __new__(cls, *arguments, **keyword):
1401-
        subclass = cls
1401+
        subclass = cls
1402-
        for sc in Network.__subclasses__():
1402+
        for sc in Network.__subclasses__():
1403-
            if sc.platform == platform.system():
1403+
            if sc.platform == platform.system():
1404-
                subclass = sc
1404+
                subclass = sc
1405-
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
1405+
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
1406-
1406+
1407-
    def __init__(self, module):
1407+
    def __init__(self, module):
1408-
        self.module = module
1408+
        self.module = module
1409-
        Facts.__init__(self)
1409+
        Facts.__init__(self)
1410-
1410+
1411-
    def populate(self):
1411+
    def populate(self):
1412-
        return self.facts
1412+
        return self.facts
1413-
1413+
1414-
class LinuxNetwork(Network):
1414+
class LinuxNetwork(Network):
1415-
    """
1415+
    """
1416-
    This is a Linux-specific subclass of Network.  It defines
1416+
    This is a Linux-specific subclass of Network.  It defines
1417-
    - interfaces (a list of interface names)
1417+
    - interfaces (a list of interface names)
1418-
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1418+
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1419-
    - all_ipv4_addresses and all_ipv6_addresses: lists of all configured addresses.
1419+
    - all_ipv4_addresses and all_ipv6_addresses: lists of all configured addresses.
1420-
    - ipv4_address and ipv6_address: the first non-local address for each family.
1420+
    - ipv4_address and ipv6_address: the first non-local address for each family.
1421-
    """
1421+
    """
1422-
    platform = 'Linux'
1422+
    platform = 'Linux'
1423-
1423+
1424-
    def __init__(self, module):
1424+
    def __init__(self, module):
1425-
        Network.__init__(self, module)
1425+
        Network.__init__(self, module)
1426-
1426+
1427-
    def populate(self):
1427+
    def populate(self):
1428-
        ip_path = self.module.get_bin_path('ip')
1428+
        ip_path = self.module.get_bin_path('ip')
1429-
        if ip_path is None:
1429+
        if ip_path is None:
1430-
            return self.facts
1430+
            return self.facts
1431-
        default_ipv4, default_ipv6 = self.get_default_interfaces(ip_path)
1431+
        default_ipv4, default_ipv6 = self.get_default_interfaces(ip_path)
1432-
        interfaces, ips = self.get_interfaces_info(ip_path, default_ipv4, default_ipv6)
1432+
        interfaces, ips = self.get_interfaces_info(ip_path, default_ipv4, default_ipv6)
1433-
        self.facts['interfaces'] = interfaces.keys()
1433+
        self.facts['interfaces'] = interfaces.keys()
1434-
        for iface in interfaces:
1434+
        for iface in interfaces:
1435-
            self.facts[iface] = interfaces[iface]
1435+
            self.facts[iface] = interfaces[iface]
1436-
        self.facts['default_ipv4'] = default_ipv4
1436+
        self.facts['default_ipv4'] = default_ipv4
1437-
        self.facts['default_ipv6'] = default_ipv6
1437+
        self.facts['default_ipv6'] = default_ipv6
1438-
        self.facts['all_ipv4_addresses'] = ips['all_ipv4_addresses']
1438+
        self.facts['all_ipv4_addresses'] = ips['all_ipv4_addresses']
1439-
        self.facts['all_ipv6_addresses'] = ips['all_ipv6_addresses']
1439+
        self.facts['all_ipv6_addresses'] = ips['all_ipv6_addresses']
1440-
        return self.facts
1440+
        return self.facts
1441-
1441+
1442-
    def get_default_interfaces(self, ip_path):
1442+
    def get_default_interfaces(self, ip_path):
1443-
        # Use the commands:
1443+
        # Use the commands:
1444-
        #     ip -4 route get 8.8.8.8                     -> Google public DNS
1444+
        #     ip -4 route get 8.8.8.8                     -> Google public DNS
1445-
        #     ip -6 route get 2404:6800:400a:800::1012    -> ipv6.google.com
1445+
        #     ip -6 route get 2404:6800:400a:800::1012    -> ipv6.google.com
1446-
        # to find out the default outgoing interface, address, and gateway
1446+
        # to find out the default outgoing interface, address, and gateway
1447-
        command = dict(
1447+
        command = dict(
1448-
            v4 = [ip_path, '-4', 'route', 'get', '8.8.8.8'],
1448+
            v4 = [ip_path, '-4', 'route', 'get', '8.8.8.8'],
1449-
            v6 = [ip_path, '-6', 'route', 'get', '2404:6800:400a:800::1012']
1449+
            v6 = [ip_path, '-6', 'route', 'get', '2404:6800:400a:800::1012']
1450-
        )
1450+
        )
1451-
        interface = dict(v4 = {}, v6 = {})
1451+
        interface = dict(v4 = {}, v6 = {})
1452-
        for v in 'v4', 'v6':
1452+
        for v in 'v4', 'v6':
1453-
            if v == 'v6' and self.facts['os_family'] == 'RedHat' \
1453+
            if v == 'v6' and self.facts['os_family'] == 'RedHat' \
1454-
                and self.facts['distribution_version'].startswith('4.'):
1454+
                and self.facts['distribution_version'].startswith('4.'):
1455-
                continue
1455+
                continue
1456-
            if v == 'v6' and not socket.has_ipv6:
1456+
            if v == 'v6' and not socket.has_ipv6:
1457-
                continue
1457+
                continue
1458-
            rc, out, err = module.run_command(command[v])
1458+
            rc, out, err = module.run_command(command[v])
1459-
            if not out:
1459+
            if not out:
1460-
                # v6 routing may result in
1460+
                # v6 routing may result in
1461-
                #   RTNETLINK answers: Invalid argument
1461+
                #   RTNETLINK answers: Invalid argument
1462-
                continue
1462+
                continue
1463-
            words = out.split('\n')[0].split()
1463+
            words = out.split('\n')[0].split()
1464-
            # A valid output starts with the queried address on the first line
1464+
            # A valid output starts with the queried address on the first line
1465-
            if len(words) > 0 and words[0] == command[v][-1]:
1465+
            if len(words) > 0 and words[0] == command[v][-1]:
1466-
                for i in range(len(words) - 1):
1466+
                for i in range(len(words) - 1):
1467-
                    if words[i] == 'dev':
1467+
                    if words[i] == 'dev':
1468-
                        interface[v]['interface'] = words[i+1]
1468+
                        interface[v]['interface'] = words[i+1]
1469-
                    elif words[i] == 'src':
1469+
                    elif words[i] == 'src':
1470-
                        interface[v]['address'] = words[i+1]
1470+
                        interface[v]['address'] = words[i+1]
1471-
                    elif words[i] == 'via' and words[i+1] != command[v][-1]:
1471+
                    elif words[i] == 'via' and words[i+1] != command[v][-1]:
1472-
                        interface[v]['gateway'] = words[i+1]
1472+
                        interface[v]['gateway'] = words[i+1]
1473-
        return interface['v4'], interface['v6']
1473+
        return interface['v4'], interface['v6']
1474-
1474+
1475-
    def get_interfaces_info(self, ip_path, default_ipv4, default_ipv6):
1475+
    def get_interfaces_info(self, ip_path, default_ipv4, default_ipv6):
1476-
        interfaces = {}
1476+
        interfaces = {}
1477-
        ips = dict(
1477+
        ips = dict(
1478-
            all_ipv4_addresses = [],
1478+
            all_ipv4_addresses = [],
1479-
            all_ipv6_addresses = [],
1479+
            all_ipv6_addresses = [],
1480-
        )
1480+
        )
1481-
1481+
1482-
        for path in glob.glob('/sys/class/net/*'):
1482+
        for path in glob.glob('/sys/class/net/*'):
1483-
            if not os.path.isdir(path):
1483+
            if not os.path.isdir(path):
1484-
                continue
1484+
                continue
1485-
            device = os.path.basename(path)
1485+
            device = os.path.basename(path)
1486-
            interfaces[device] = { 'device': device }
1486+
            interfaces[device] = { 'device': device }
1487-
            if os.path.exists(os.path.join(path, 'address')):
1487+
            if os.path.exists(os.path.join(path, 'address')):
1488-
                macaddress = open(os.path.join(path, 'address')).read().strip()
1488+
                macaddress = open(os.path.join(path, 'address')).read().strip()
1489-
                if macaddress and macaddress != '00:00:00:00:00:00':
1489+
                if macaddress and macaddress != '00:00:00:00:00:00':
1490-
                    interfaces[device]['macaddress'] = macaddress
1490+
                    interfaces[device]['macaddress'] = macaddress
1491-
            if os.path.exists(os.path.join(path, 'mtu')):
1491+
            if os.path.exists(os.path.join(path, 'mtu')):
1492-
                interfaces[device]['mtu'] = int(open(os.path.join(path, 'mtu')).read().strip())
1492+
                interfaces[device]['mtu'] = int(open(os.path.join(path, 'mtu')).read().strip())
1493-
            if os.path.exists(os.path.join(path, 'operstate')):
1493+
            if os.path.exists(os.path.join(path, 'operstate')):
1494-
                interfaces[device]['active'] = open(os.path.join(path, 'operstate')).read().strip() != 'down'
1494+
                interfaces[device]['active'] = open(os.path.join(path, 'operstate')).read().strip() != 'down'
1495-
#            if os.path.exists(os.path.join(path, 'carrier')):
1495+
#            if os.path.exists(os.path.join(path, 'carrier')):
1496-
#                interfaces[device]['link'] = open(os.path.join(path, 'carrier')).read().strip() == '1'
1496+
#                interfaces[device]['link'] = open(os.path.join(path, 'carrier')).read().strip() == '1'
1497-
            if os.path.exists(os.path.join(path, 'device','driver', 'module')):
1497+
            if os.path.exists(os.path.join(path, 'device','driver', 'module')):
1498-
                interfaces[device]['module'] = os.path.basename(os.path.realpath(os.path.join(path, 'device', 'driver', 'module')))
1498+
                interfaces[device]['module'] = os.path.basename(os.path.realpath(os.path.join(path, 'device', 'driver', 'module')))
1499-
            if os.path.exists(os.path.join(path, 'type')):
1499+
            if os.path.exists(os.path.join(path, 'type')):
1500-
                type = open(os.path.join(path, 'type')).read().strip()
1500+
                type = open(os.path.join(path, 'type')).read().strip()
1501-
                if type == '1':
1501+
                if type == '1':
1502-
                    interfaces[device]['type'] = 'ether'
1502+
                    interfaces[device]['type'] = 'ether'
1503-
                elif type == '512':
1503+
                elif type == '512':
1504-
                    interfaces[device]['type'] = 'ppp'
1504+
                    interfaces[device]['type'] = 'ppp'
1505-
                elif type == '772':
1505+
                elif type == '772':
1506-
                    interfaces[device]['type'] = 'loopback'
1506+
                    interfaces[device]['type'] = 'loopback'
1507-
            if os.path.exists(os.path.join(path, 'bridge')):
1507+
            if os.path.exists(os.path.join(path, 'bridge')):
1508-
                interfaces[device]['type'] = 'bridge'
1508+
                interfaces[device]['type'] = 'bridge'
1509-
                interfaces[device]['interfaces'] = [ os.path.basename(b) for b in glob.glob(os.path.join(path, 'brif', '*')) ]
1509+
                interfaces[device]['interfaces'] = [ os.path.basename(b) for b in glob.glob(os.path.join(path, 'brif', '*')) ]
1510-
                if os.path.exists(os.path.join(path, 'bridge', 'bridge_id')):
1510+
                if os.path.exists(os.path.join(path, 'bridge', 'bridge_id')):
1511-
                    interfaces[device]['id'] = open(os.path.join(path, 'bridge', 'bridge_id')).read().strip()
1511+
                    interfaces[device]['id'] = open(os.path.join(path, 'bridge', 'bridge_id')).read().strip()
1512-
                if os.path.exists(os.path.join(path, 'bridge', 'stp_state')):
1512+
                if os.path.exists(os.path.join(path, 'bridge', 'stp_state')):
1513-
                    interfaces[device]['stp'] = open(os.path.join(path, 'bridge', 'stp_state')).read().strip() == '1'
1513+
                    interfaces[device]['stp'] = open(os.path.join(path, 'bridge', 'stp_state')).read().strip() == '1'
1514-
            if os.path.exists(os.path.join(path, 'bonding')):
1514+
            if os.path.exists(os.path.join(path, 'bonding')):
1515-
                interfaces[device]['type'] = 'bonding'
1515+
                interfaces[device]['type'] = 'bonding'
1516-
                interfaces[device]['slaves'] = open(os.path.join(path, 'bonding', 'slaves')).read().split()
1516+
                interfaces[device]['slaves'] = open(os.path.join(path, 'bonding', 'slaves')).read().split()
1517-
                interfaces[device]['mode'] = open(os.path.join(path, 'bonding', 'mode')).read().split()[0]
1517+
                interfaces[device]['mode'] = open(os.path.join(path, 'bonding', 'mode')).read().split()[0]
1518-
                interfaces[device]['miimon'] = open(os.path.join(path, 'bonding', 'miimon')).read().split()[0]
1518+
                interfaces[device]['miimon'] = open(os.path.join(path, 'bonding', 'miimon')).read().split()[0]
1519-
                interfaces[device]['lacp_rate'] = open(os.path.join(path, 'bonding', 'lacp_rate')).read().split()[0]
1519+
                interfaces[device]['lacp_rate'] = open(os.path.join(path, 'bonding', 'lacp_rate')).read().split()[0]
1520-
                primary = open(os.path.join(path, 'bonding', 'primary')).read()
1520+
                primary = open(os.path.join(path, 'bonding', 'primary')).read()
1521-
                if primary:
1521+
                if primary:
1522-
                    interfaces[device]['primary'] = primary
1522+
                    interfaces[device]['primary'] = primary
1523-
                    path = os.path.join(path, 'bonding', 'all_slaves_active')
1523+
                    path = os.path.join(path, 'bonding', 'all_slaves_active')
1524-
                    if os.path.exists(path):
1524+
                    if os.path.exists(path):
1525-
                        interfaces[device]['all_slaves_active'] = open(path).read() == '1'
1525+
                        interfaces[device]['all_slaves_active'] = open(path).read() == '1'
1526-
1526+
1527-
            # Check whether a interface is in promiscuous mode
1527+
            # Check whether a interface is in promiscuous mode
1528-
            if os.path.exists(os.path.join(path,'flags')):
1528+
            if os.path.exists(os.path.join(path,'flags')):
1529-
                promisc_mode = False
1529+
                promisc_mode = False
1530-
                # The second byte indicates whether the interface is in promiscuous mode.
1530+
                # The second byte indicates whether the interface is in promiscuous mode.
1531-
                # 1 = promisc
1531+
                # 1 = promisc
1532-
                # 0 = no promisc
1532+
                # 0 = no promisc
1533-
                data = int(open(os.path.join(path, 'flags')).read().strip(),16)
1533+
                data = int(open(os.path.join(path, 'flags')).read().strip(),16)
1534-
                promisc_mode = (data & 0x0100 > 0)
1534+
                promisc_mode = (data & 0x0100 > 0)
1535-
                interfaces[device]['promisc'] = promisc_mode
1535+
                interfaces[device]['promisc'] = promisc_mode
1536-
1536+
1537-
            def parse_ip_output(output, secondary=False):
1537+
            def parse_ip_output(output, secondary=False):
1538-
                for line in output.split('\n'):
1538+
                for line in output.split('\n'):
1539-
                    if not line:
1539+
                    if not line:
1540-
                        continue
1540+
                        continue
1541-
                    words = line.split()
1541+
                    words = line.split()
1542-
                    if words[0] == 'inet':
1542+
                    if words[0] == 'inet':
1543-
                        if '/' in words[1]:
1543+
                        if '/' in words[1]:
1544-
                            address, netmask_length = words[1].split('/')
1544+
                            address, netmask_length = words[1].split('/')
1545-
                        else:
1545+
                        else:
1546-
                            # pointopoint interfaces do not have a prefix
1546+
                            # pointopoint interfaces do not have a prefix
1547-
                            address = words[1]
1547+
                            address = words[1]
1548-
                            netmask_length = "32"
1548+
                            netmask_length = "32"
1549-
                        address_bin = struct.unpack('!L', socket.inet_aton(address))[0]
1549+
                        address_bin = struct.unpack('!L', socket.inet_aton(address))[0]
1550-
                        netmask_bin = (1<<32) - (1<<32>>int(netmask_length))
1550+
                        netmask_bin = (1<<32) - (1<<32>>int(netmask_length))
1551-
                        netmask = socket.inet_ntoa(struct.pack('!L', netmask_bin))
1551+
                        netmask = socket.inet_ntoa(struct.pack('!L', netmask_bin))
1552-
                        network = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
1552+
                        network = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
1553-
                        iface = words[-1]
1553+
                        iface = words[-1]
1554-
                        if iface != device:
1554+
                        if iface != device:
1555-
                            interfaces[iface] = {}
1555+
                            interfaces[iface] = {}
1556-
                        if not secondary or "ipv4" not in interfaces[iface]:
1556+
                        if not secondary or "ipv4" not in interfaces[iface]:
1557-
                            interfaces[iface]['ipv4'] = {'address': address,
1557+
                            interfaces[iface]['ipv4'] = {'address': address,
1558-
                                                         'netmask': netmask,
1558+
                                                         'netmask': netmask,
1559-
                                                         'network': network}
1559+
                                                         'network': network}
1560-
                        else:
1560+
                        else:
1561-
                            if "ipv4_secondaries" not in interfaces[iface]:
1561+
                            if "ipv4_secondaries" not in interfaces[iface]:
1562-
                                interfaces[iface]["ipv4_secondaries"] = []
1562+
                                interfaces[iface]["ipv4_secondaries"] = []
1563-
                            interfaces[iface]["ipv4_secondaries"].append({
1563+
                            interfaces[iface]["ipv4_secondaries"].append({
1564-
                                'address': address,
1564+
                                'address': address,
1565-
                                'netmask': netmask,
1565+
                                'netmask': netmask,
1566-
                                'network': network,
1566+
                                'network': network,
1567-
                            })
1567+
                            })
1568-
1568+
1569-
                        # add this secondary IP to the main device
1569+
                        # add this secondary IP to the main device
1570-
                        if secondary:
1570+
                        if secondary:
1571-
                            if "ipv4_secondaries" not in interfaces[device]:
1571+
                            if "ipv4_secondaries" not in interfaces[device]:
1572-
                                interfaces[device]["ipv4_secondaries"] = []
1572+
                                interfaces[device]["ipv4_secondaries"] = []
1573-
                            interfaces[device]["ipv4_secondaries"].append({
1573+
                            interfaces[device]["ipv4_secondaries"].append({
1574-
                                'address': address,
1574+
                                'address': address,
1575-
                                'netmask': netmask,
1575+
                                'netmask': netmask,
1576-
                                'network': network,
1576+
                                'network': network,
1577-
                            })
1577+
                            })
1578-
1578+
1579-
                        # If this is the default address, update default_ipv4
1579+
                        # If this is the default address, update default_ipv4
1580-
                        if 'address' in default_ipv4 and default_ipv4['address'] == address:
1580+
                        if 'address' in default_ipv4 and default_ipv4['address'] == address:
1581-
                            default_ipv4['netmask'] = netmask
1581+
                            default_ipv4['netmask'] = netmask
1582-
                            default_ipv4['network'] = network
1582+
                            default_ipv4['network'] = network
1583-
                            default_ipv4['macaddress'] = macaddress
1583+
                            default_ipv4['macaddress'] = macaddress
1584-
                            default_ipv4['mtu'] = interfaces[device]['mtu']
1584+
                            default_ipv4['mtu'] = interfaces[device]['mtu']
1585-
                            default_ipv4['type'] = interfaces[device].get("type", "unknown")
1585+
                            default_ipv4['type'] = interfaces[device].get("type", "unknown")
1586-
                            default_ipv4['alias'] = words[-1]
1586+
                            default_ipv4['alias'] = words[-1]
1587-
                        if not address.startswith('127.'):
1587+
                        if not address.startswith('127.'):
1588-
                            ips['all_ipv4_addresses'].append(address)
1588+
                            ips['all_ipv4_addresses'].append(address)
1589-
                    elif words[0] == 'inet6':
1589+
                    elif words[0] == 'inet6':
1590-
                        address, prefix = words[1].split('/')
1590+
                        address, prefix = words[1].split('/')
1591-
                        scope = words[3]
1591+
                        scope = words[3]
1592-
                        if 'ipv6' not in interfaces[device]:
1592+
                        if 'ipv6' not in interfaces[device]:
1593-
                            interfaces[device]['ipv6'] = []
1593+
                            interfaces[device]['ipv6'] = []
1594-
                        interfaces[device]['ipv6'].append({
1594+
                        interfaces[device]['ipv6'].append({
1595-
                            'address' : address,
1595+
                            'address' : address,
1596-
                            'prefix'  : prefix,
1596+
                            'prefix'  : prefix,
1597-
                            'scope'   : scope
1597+
                            'scope'   : scope
1598-
                        })
1598+
                        })
1599-
                        # If this is the default address, update default_ipv6
1599+
                        # If this is the default address, update default_ipv6
1600-
                        if 'address' in default_ipv6 and default_ipv6['address'] == address:
1600+
                        if 'address' in default_ipv6 and default_ipv6['address'] == address:
1601-
                            default_ipv6['prefix']     = prefix
1601+
                            default_ipv6['prefix']     = prefix
1602-
                            default_ipv6['scope']      = scope
1602+
                            default_ipv6['scope']      = scope
1603-
                            default_ipv6['macaddress'] = macaddress
1603+
                            default_ipv6['macaddress'] = macaddress
1604-
                            default_ipv6['mtu']        = interfaces[device]['mtu']
1604+
                            default_ipv6['mtu']        = interfaces[device]['mtu']
1605-
                            default_ipv6['type']       = interfaces[device].get("type", "unknown")
1605+
                            default_ipv6['type']       = interfaces[device].get("type", "unknown")
1606-
                        if not address == '::1':
1606+
                        if not address == '::1':
1607-
                            ips['all_ipv6_addresses'].append(address)
1607+
                            ips['all_ipv6_addresses'].append(address)
1608-
1608+
1609-
            ip_path = module.get_bin_path("ip")
1609+
            ip_path = module.get_bin_path("ip")
1610-
1610+
1611-
            args = [ip_path, 'addr', 'show', 'primary', device]
1611+
            args = [ip_path, 'addr', 'show', 'primary', device]
1612-
            rc, stdout, stderr = self.module.run_command(args)
1612+
            rc, stdout, stderr = self.module.run_command(args)
1613-
            primary_data = stdout
1613+
            primary_data = stdout
1614-
1614+
1615-
            args = [ip_path, 'addr', 'show', 'secondary', device]
1615+
            args = [ip_path, 'addr', 'show', 'secondary', device]
1616-
            rc, stdout, stderr = self.module.run_command(args)
1616+
            rc, stdout, stderr = self.module.run_command(args)
1617-
            secondary_data = stdout
1617+
            secondary_data = stdout
1618-
1618+
1619-
            parse_ip_output(primary_data)
1619+
            parse_ip_output(primary_data)
1620-
            parse_ip_output(secondary_data, secondary=True)
1620+
            parse_ip_output(secondary_data, secondary=True)
1621-
1621+
1622-
        # replace : by _ in interface name since they are hard to use in template
1622+
        # replace : by _ in interface name since they are hard to use in template
1623-
        new_interfaces = {}
1623+
        new_interfaces = {}
1624-
        for i in interfaces:
1624+
        for i in interfaces:
1625-
            if ':' in i:
1625+
            if ':' in i:
1626-
                new_interfaces[i.replace(':','_')] = interfaces[i]
1626+
                new_interfaces[i.replace(':','_')] = interfaces[i]
1627-
            else:
1627+
            else:
1628-
                new_interfaces[i] = interfaces[i]
1628+
                new_interfaces[i] = interfaces[i]
1629-
        return new_interfaces, ips
1629+
        return new_interfaces, ips
1630-
1630+
1631-
class GenericBsdIfconfigNetwork(Network):
1631+
class GenericBsdIfconfigNetwork(Network):
1632-
    """
1632+
    """
1633-
    This is a generic BSD subclass of Network using the ifconfig command.
1633+
    This is a generic BSD subclass of Network using the ifconfig command.
1634-
    It defines
1634+
    It defines
1635-
    - interfaces (a list of interface names)
1635+
    - interfaces (a list of interface names)
1636-
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1636+
    - interface_<name> dictionary of ipv4, ipv6, and mac address information.
1637-
    - all_ipv4_addresses and all_ipv6_addresses: lists of all configured addresses.
1637+
    - all_ipv4_addresses and all_ipv6_addresses: lists of all configured addresses.
1638-
    It currently does not define
1638+
    It currently does not define
1639-
    - default_ipv4 and default_ipv6
1639+
    - default_ipv4 and default_ipv6
1640-
    - type, mtu and network on interfaces
1640+
    - type, mtu and network on interfaces
1641-
    """
1641+
    """
1642-
    platform = 'Generic_BSD_Ifconfig'
1642+
    platform = 'Generic_BSD_Ifconfig'
1643-
1643+
1644-
    def __init__(self, module):
1644+
    def __init__(self, module):
1645-
        Network.__init__(self, module)
1645+
        Network.__init__(self, module)
1646-
1646+
1647-
    def populate(self):
1647+
    def populate(self):
1648-
1648+
1649-
        ifconfig_path = module.get_bin_path('ifconfig')
1649+
        ifconfig_path = module.get_bin_path('ifconfig')
1650-
1650+
1651-
        if ifconfig_path is None:
1651+
        if ifconfig_path is None:
1652-
            return self.facts
1652+
            return self.facts
1653-
        route_path = module.get_bin_path('route')
1653+
        route_path = module.get_bin_path('route')
1654-
1654+
1655-
        if route_path is None:
1655+
        if route_path is None:
1656-
            return self.facts
1656+
            return self.facts
1657-
1657+
1658-
        default_ipv4, default_ipv6 = self.get_default_interfaces(route_path)
1658+
        default_ipv4, default_ipv6 = self.get_default_interfaces(route_path)
1659-
        interfaces, ips = self.get_interfaces_info(ifconfig_path)
1659+
        interfaces, ips = self.get_interfaces_info(ifconfig_path)
1660-
        self.merge_default_interface(default_ipv4, interfaces, 'ipv4')
1660+
        self.merge_default_interface(default_ipv4, interfaces, 'ipv4')
1661-
        self.merge_default_interface(default_ipv6, interfaces, 'ipv6')
1661+
        self.merge_default_interface(default_ipv6, interfaces, 'ipv6')
1662-
        self.facts['interfaces'] = interfaces.keys()
1662+
        self.facts['interfaces'] = interfaces.keys()
1663-
1663+
1664-
        for iface in interfaces:
1664+
        for iface in interfaces:
1665-
            self.facts[iface] = interfaces[iface]
1665+
            self.facts[iface] = interfaces[iface]
1666-
1666+
1667-
        self.facts['default_ipv4'] = default_ipv4
1667+
        self.facts['default_ipv4'] = default_ipv4
1668-
        self.facts['default_ipv6'] = default_ipv6
1668+
        self.facts['default_ipv6'] = default_ipv6
1669-
        self.facts['all_ipv4_addresses'] = ips['all_ipv4_addresses']
1669+
        self.facts['all_ipv4_addresses'] = ips['all_ipv4_addresses']
1670-
        self.facts['all_ipv6_addresses'] = ips['all_ipv6_addresses']
1670+
        self.facts['all_ipv6_addresses'] = ips['all_ipv6_addresses']
1671-
1671+
1672-
        return self.facts
1672+
        return self.facts
1673-
1673+
1674-
    def get_default_interfaces(self, route_path):
1674+
    def get_default_interfaces(self, route_path):
1675-
1675+
1676-
        # Use the commands:
1676+
        # Use the commands:
1677-
        #     route -n get 8.8.8.8                            -> Google public DNS
1677+
        #     route -n get 8.8.8.8                            -> Google public DNS
1678-
        #     route -n get -inet6 2404:6800:400a:800::1012    -> ipv6.google.com
1678+
        #     route -n get -inet6 2404:6800:400a:800::1012    -> ipv6.google.com
1679-
        # to find out the default outgoing interface, address, and gateway
1679+
        # to find out the default outgoing interface, address, and gateway
1680-
1680+
1681-
        command = dict(
1681+
        command = dict(
1682-
            v4 = [route_path, '-n', 'get', '8.8.8.8'],
1682+
            v4 = [route_path, '-n', 'get', '8.8.8.8'],
1683-
            v6 = [route_path, '-n', 'get', '-inet6', '2404:6800:400a:800::1012']
1683+
            v6 = [route_path, '-n', 'get', '-inet6', '2404:6800:400a:800::1012']
1684-
        )
1684+
        )
1685-
1685+
1686-
        interface = dict(v4 = {}, v6 = {})
1686+
        interface = dict(v4 = {}, v6 = {})
1687-
1687+
1688-
        for v in 'v4', 'v6':
1688+
        for v in 'v4', 'v6':
1689-
1689+
1690-
            if v == 'v6' and not socket.has_ipv6:
1690+
            if v == 'v6' and not socket.has_ipv6:
1691-
                continue
1691+
                continue
1692-
            rc, out, err = module.run_command(command[v])
1692+
            rc, out, err = module.run_command(command[v])
1693-
            if not out:
1693+
            if not out:
1694-
                # v6 routing may result in
1694+
                # v6 routing may result in
1695-
                #   RTNETLINK answers: Invalid argument
1695+
                #   RTNETLINK answers: Invalid argument
1696-
                continue
1696+
                continue
1697-
            lines = out.split('\n')
1697+
            lines = out.split('\n')
1698-
            for line in lines:
1698+
            for line in lines:
1699-
                words = line.split()
1699+
                words = line.split()
1700-
                # Collect output from route command
1700+
                # Collect output from route command
1701-
                if len(words) > 1:
1701+
                if len(words) > 1:
1702-
                    if words[0] == 'interface:':
1702+
                    if words[0] == 'interface:':
1703-
                        interface[v]['interface'] = words[1]
1703+
                        interface[v]['interface'] = words[1]
1704-
                    if words[0] == 'gateway:':
1704+
                    if words[0] == 'gateway:':
1705-
                        interface[v]['gateway'] = words[1]
1705+
                        interface[v]['gateway'] = words[1]
1706-
1706+
1707-
        return interface['v4'], interface['v6']
1707+
        return interface['v4'], interface['v6']
1708-
1708+
1709-
    def get_interfaces_info(self, ifconfig_path):
1709+
    def get_interfaces_info(self, ifconfig_path):
1710-
        interfaces = {}
1710+
        interfaces = {}
1711-
        current_if = {}
1711+
        current_if = {}
1712-
        ips = dict(
1712+
        ips = dict(
1713-
            all_ipv4_addresses = [],
1713+
            all_ipv4_addresses = [],
1714-
            all_ipv6_addresses = [],
1714+
            all_ipv6_addresses = [],
1715-
        )
1715+
        )
1716-
        # FreeBSD, DragonflyBSD, NetBSD, OpenBSD and OS X all implicitly add '-a'
1716+
        # FreeBSD, DragonflyBSD, NetBSD, OpenBSD and OS X all implicitly add '-a'
1717-
        # when running the command 'ifconfig'.
1717+
        # when running the command 'ifconfig'.
1718-
        # Solaris must explicitly run the command 'ifconfig -a'.
1718+
        # Solaris must explicitly run the command 'ifconfig -a'.
1719-
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1719+
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1720-
1720+
1721-
        for line in out.split('\n'):
1721+
        for line in out.split('\n'):
1722-
1722+
1723-
            if line:
1723+
            if line:
1724-
                words = line.split()
1724+
                words = line.split()
1725-
1725+
1726-
                if words[0] == 'pass':
1726+
                if words[0] == 'pass':
1727-
                    continue
1727+
                    continue
1728-
                elif re.match('^\S', line) and len(words) > 3:
1728+
                elif re.match('^\S', line) and len(words) > 3:
1729-
                    current_if = self.parse_interface_line(words)
1729+
                    current_if = self.parse_interface_line(words)
1730-
                    interfaces[ current_if['device'] ] = current_if
1730+
                    interfaces[ current_if['device'] ] = current_if
1731-
                elif words[0].startswith('options='):
1731+
                elif words[0].startswith('options='):
1732-
                    self.parse_options_line(words, current_if, ips)
1732+
                    self.parse_options_line(words, current_if, ips)
1733-
                elif words[0] == 'nd6':
1733+
                elif words[0] == 'nd6':
1734-
                    self.parse_nd6_line(words, current_if, ips)
1734+
                    self.parse_nd6_line(words, current_if, ips)
1735-
                elif words[0] == 'ether':
1735+
                elif words[0] == 'ether':
1736-
                    self.parse_ether_line(words, current_if, ips)
1736+
                    self.parse_ether_line(words, current_if, ips)
1737-
                elif words[0] == 'media:':
1737+
                elif words[0] == 'media:':
1738-
                    self.parse_media_line(words, current_if, ips)
1738+
                    self.parse_media_line(words, current_if, ips)
1739-
                elif words[0] == 'status:':
1739+
                elif words[0] == 'status:':
1740-
                    self.parse_status_line(words, current_if, ips)
1740+
                    self.parse_status_line(words, current_if, ips)
1741-
                elif words[0] == 'lladdr':
1741+
                elif words[0] == 'lladdr':
1742-
                    self.parse_lladdr_line(words, current_if, ips)
1742+
                    self.parse_lladdr_line(words, current_if, ips)
1743-
                elif words[0] == 'inet':
1743+
                elif words[0] == 'inet':
1744-
                    self.parse_inet_line(words, current_if, ips)
1744+
                    self.parse_inet_line(words, current_if, ips)
1745-
                elif words[0] == 'inet6':
1745+
                elif words[0] == 'inet6':
1746-
                    self.parse_inet6_line(words, current_if, ips)
1746+
                    self.parse_inet6_line(words, current_if, ips)
1747-
                else:
1747+
                else:
1748-
                    self.parse_unknown_line(words, current_if, ips)
1748+
                    self.parse_unknown_line(words, current_if, ips)
1749-
1749+
1750-
        return interfaces, ips
1750+
        return interfaces, ips
1751-
1751+
1752-
    def parse_interface_line(self, words):
1752+
    def parse_interface_line(self, words):
1753-
        device = words[0][0:-1]
1753+
        device = words[0][0:-1]
1754-
        current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
1754+
        current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
1755-
        current_if['flags']  = self.get_options(words[1])
1755+
        current_if['flags']  = self.get_options(words[1])
1756-
        current_if['macaddress'] = 'unknown'    # will be overwritten later
1756+
        current_if['macaddress'] = 'unknown'    # will be overwritten later
1757-
1757+
1758-
        if len(words) >= 5 : # Newer FreeBSD versions
1758+
        if len(words) >= 5 : # Newer FreeBSD versions
1759-
            current_if['metric'] = words[3]
1759+
            current_if['metric'] = words[3]
1760-
            current_if['mtu'] = words[5]
1760+
            current_if['mtu'] = words[5]
1761-
        else:
1761+
        else:
1762-
            current_if['mtu'] = words[3]
1762+
            current_if['mtu'] = words[3]
1763-
1763+
1764-
        return current_if
1764+
        return current_if
1765-
1765+
1766-
    def parse_options_line(self, words, current_if, ips):
1766+
    def parse_options_line(self, words, current_if, ips):
1767-
        # Mac has options like this...
1767+
        # Mac has options like this...
1768-
        current_if['options'] = self.get_options(words[0])
1768+
        current_if['options'] = self.get_options(words[0])
1769-
1769+
1770-
    def parse_nd6_line(self, words, current_if, ips):
1770+
    def parse_nd6_line(self, words, current_if, ips):
1771-
        # FreBSD has options like this...
1771+
        # FreBSD has options like this...
1772-
        current_if['options'] = self.get_options(words[1])
1772+
        current_if['options'] = self.get_options(words[1])
1773-
1773+
1774-
    def parse_ether_line(self, words, current_if, ips):
1774+
    def parse_ether_line(self, words, current_if, ips):
1775-
        current_if['macaddress'] = words[1]
1775+
        current_if['macaddress'] = words[1]
1776-
1776+
1777-
    def parse_media_line(self, words, current_if, ips):
1777+
    def parse_media_line(self, words, current_if, ips):
1778-
        # not sure if this is useful - we also drop information
1778+
        # not sure if this is useful - we also drop information
1779-
        current_if['media'] = words[1]
1779+
        current_if['media'] = words[1]
1780-
        if len(words) > 2:
1780+
        if len(words) > 2:
1781-
            current_if['media_select'] = words[2]
1781+
            current_if['media_select'] = words[2]
1782-
        if len(words) > 3:
1782+
        if len(words) > 3:
1783-
            current_if['media_type'] = words[3][1:]
1783+
            current_if['media_type'] = words[3][1:]
1784-
        if len(words) > 4:
1784+
        if len(words) > 4:
1785-
            current_if['media_options'] = self.get_options(words[4])
1785+
            current_if['media_options'] = self.get_options(words[4])
1786-
1786+
1787-
    def parse_status_line(self, words, current_if, ips):
1787+
    def parse_status_line(self, words, current_if, ips):
1788-
        current_if['status'] = words[1]
1788+
        current_if['status'] = words[1]
1789-
1789+
1790-
    def parse_lladdr_line(self, words, current_if, ips):
1790+
    def parse_lladdr_line(self, words, current_if, ips):
1791-
        current_if['lladdr'] = words[1]
1791+
        current_if['lladdr'] = words[1]
1792-
1792+
1793-
    def parse_inet_line(self, words, current_if, ips):
1793+
    def parse_inet_line(self, words, current_if, ips):
1794-
        address = {'address': words[1]}
1794+
        address = {'address': words[1]}
1795-
        # deal with hex netmask
1795+
        # deal with hex netmask
1796-
        if re.match('([0-9a-f]){8}', words[3]) and len(words[3]) == 8:
1796+
        if re.match('([0-9a-f]){8}', words[3]) and len(words[3]) == 8:
1797-
            words[3] = '0x' + words[3]
1797+
            words[3] = '0x' + words[3]
1798-
        if words[3].startswith('0x'):
1798+
        if words[3].startswith('0x'):
1799-
            address['netmask'] = socket.inet_ntoa(struct.pack('!L', int(words[3], base=16)))
1799+
            address['netmask'] = socket.inet_ntoa(struct.pack('!L', int(words[3], base=16)))
1800-
        else:
1800+
        else:
1801-
            # otherwise assume this is a dotted quad
1801+
            # otherwise assume this is a dotted quad
1802-
            address['netmask'] = words[3]
1802+
            address['netmask'] = words[3]
1803-
        # calculate the network
1803+
        # calculate the network
1804-
        address_bin = struct.unpack('!L', socket.inet_aton(address['address']))[0]
1804+
        address_bin = struct.unpack('!L', socket.inet_aton(address['address']))[0]
1805-
        netmask_bin = struct.unpack('!L', socket.inet_aton(address['netmask']))[0]
1805+
        netmask_bin = struct.unpack('!L', socket.inet_aton(address['netmask']))[0]
1806-
        address['network'] = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
1806+
        address['network'] = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
1807-
        # broadcast may be given or we need to calculate
1807+
        # broadcast may be given or we need to calculate
1808-
        if len(words) > 5:
1808+
        if len(words) > 5:
1809-
            address['broadcast'] = words[5]
1809+
            address['broadcast'] = words[5]
1810-
        else:
1810+
        else:
1811-
            address['broadcast'] = socket.inet_ntoa(struct.pack('!L', address_bin | (~netmask_bin & 0xffffffff)))
1811+
            address['broadcast'] = socket.inet_ntoa(struct.pack('!L', address_bin | (~netmask_bin & 0xffffffff)))
1812-
        # add to our list of addresses
1812+
        # add to our list of addresses
1813-
        if not words[1].startswith('127.'):
1813+
        if not words[1].startswith('127.'):
1814-
            ips['all_ipv4_addresses'].append(address['address'])
1814+
            ips['all_ipv4_addresses'].append(address['address'])
1815-
        current_if['ipv4'].append(address)
1815+
        current_if['ipv4'].append(address)
1816-
1816+
1817-
    def parse_inet6_line(self, words, current_if, ips):
1817+
    def parse_inet6_line(self, words, current_if, ips):
1818-
        address = {'address': words[1]}
1818+
        address = {'address': words[1]}
1819-
        if (len(words) >= 4) and (words[2] == 'prefixlen'):
1819+
        if (len(words) >= 4) and (words[2] == 'prefixlen'):
1820-
            address['prefix'] = words[3]
1820+
            address['prefix'] = words[3]
1821-
        if (len(words) >= 6) and (words[4] == 'scopeid'):
1821+
        if (len(words) >= 6) and (words[4] == 'scopeid'):
1822-
            address['scope'] = words[5]
1822+
            address['scope'] = words[5]
1823-
        localhost6 = ['::1', '::1/128', 'fe80::1%lo0']
1823+
        localhost6 = ['::1', '::1/128', 'fe80::1%lo0']
1824-
        if address['address'] not in localhost6:
1824+
        if address['address'] not in localhost6:
1825-
            ips['all_ipv6_addresses'].append(address['address'])
1825+
            ips['all_ipv6_addresses'].append(address['address'])
1826-
        current_if['ipv6'].append(address)
1826+
        current_if['ipv6'].append(address)
1827-
1827+
1828-
    def parse_unknown_line(self, words, current_if, ips):
1828+
    def parse_unknown_line(self, words, current_if, ips):
1829-
        # we are going to ignore unknown lines here - this may be
1829+
        # we are going to ignore unknown lines here - this may be
1830-
        # a bad idea - but you can override it in your subclass
1830+
        # a bad idea - but you can override it in your subclass
1831-
        pass
1831+
        pass
1832-
1832+
1833-
    def get_options(self, option_string):
1833+
    def get_options(self, option_string):
1834-
        start = option_string.find('<') + 1
1834+
        start = option_string.find('<') + 1
1835-
        end = option_string.rfind('>')
1835+
        end = option_string.rfind('>')
1836-
        if (start > 0) and (end > 0) and (end > start + 1):
1836+
        if (start > 0) and (end > 0) and (end > start + 1):
1837-
            option_csv = option_string[start:end]
1837+
            option_csv = option_string[start:end]
1838-
            return option_csv.split(',')
1838+
            return option_csv.split(',')
1839-
        else:
1839+
        else:
1840-
            return []
1840+
            return []
1841-
1841+
1842-
    def merge_default_interface(self, defaults, interfaces, ip_type):
1842+
    def merge_default_interface(self, defaults, interfaces, ip_type):
1843-
        if not 'interface' in defaults.keys():
1843+
        if not 'interface' in defaults.keys():
1844-
            return
1844+
            return
1845-
        if not defaults['interface'] in interfaces:
1845+
        if not defaults['interface'] in interfaces:
1846-
            return
1846+
            return
1847-
        ifinfo = interfaces[defaults['interface']]
1847+
        ifinfo = interfaces[defaults['interface']]
1848-
        # copy all the interface values across except addresses
1848+
        # copy all the interface values across except addresses
1849-
        for item in ifinfo.keys():
1849+
        for item in ifinfo.keys():
1850-
            if item != 'ipv4' and item != 'ipv6':
1850+
            if item != 'ipv4' and item != 'ipv6':
1851-
                defaults[item] = ifinfo[item]
1851+
                defaults[item] = ifinfo[item]
1852-
        if len(ifinfo[ip_type]) > 0:
1852+
        if len(ifinfo[ip_type]) > 0:
1853-
            for item in ifinfo[ip_type][0].keys():
1853+
            for item in ifinfo[ip_type][0].keys():
1854-
                defaults[item] = ifinfo[ip_type][0][item]
1854+
                defaults[item] = ifinfo[ip_type][0][item]
1855-
1855+
1856-
class DarwinNetwork(GenericBsdIfconfigNetwork, Network):
1856+
class DarwinNetwork(GenericBsdIfconfigNetwork, Network):
1857-
    """
1857+
    """
1858-
    This is the Mac OS X/Darwin Network Class.
1858+
    This is the Mac OS X/Darwin Network Class.
1859-
    It uses the GenericBsdIfconfigNetwork unchanged
1859+
    It uses the GenericBsdIfconfigNetwork unchanged
1860-
    """
1860+
    """
1861-
    platform = 'Darwin'
1861+
    platform = 'Darwin'
1862-
1862+
1863-
    # media line is different to the default FreeBSD one
1863+
    # media line is different to the default FreeBSD one
1864-
    def parse_media_line(self, words, current_if, ips):
1864+
    def parse_media_line(self, words, current_if, ips):
1865-
        # not sure if this is useful - we also drop information
1865+
        # not sure if this is useful - we also drop information
1866-
        current_if['media'] = 'Unknown' # Mac does not give us this
1866+
        current_if['media'] = 'Unknown' # Mac does not give us this
1867-
        current_if['media_select'] = words[1]
1867+
        current_if['media_select'] = words[1]
1868-
        if len(words) > 2:
1868+
        if len(words) > 2:
1869-
            current_if['media_type'] = words[2][1:]
1869+
            current_if['media_type'] = words[2][1:]
1870-
        if len(words) > 3:
1870+
        if len(words) > 3:
1871-
            current_if['media_options'] = self.get_options(words[3])
1871+
            current_if['media_options'] = self.get_options(words[3])
1872-
1872+
1873-
1873+
1874-
class FreeBSDNetwork(GenericBsdIfconfigNetwork, Network):
1874+
class FreeBSDNetwork(GenericBsdIfconfigNetwork, Network):
1875-
    """
1875+
    """
1876-
    This is the FreeBSD Network Class.
1876+
    This is the FreeBSD Network Class.
1877-
    It uses the GenericBsdIfconfigNetwork unchanged.
1877+
    It uses the GenericBsdIfconfigNetwork unchanged.
1878-
    """
1878+
    """
1879-
    platform = 'FreeBSD'
1879+
    platform = 'FreeBSD'
1880-
1880+
1881-
class AIXNetwork(GenericBsdIfconfigNetwork, Network):
1881+
class AIXNetwork(GenericBsdIfconfigNetwork, Network):
1882-
    """
1882+
    """
1883-
    This is the AIX Network Class.
1883+
    This is the AIX Network Class.
1884-
    It uses the GenericBsdIfconfigNetwork unchanged.
1884+
    It uses the GenericBsdIfconfigNetwork unchanged.
1885-
    """
1885+
    """
1886-
    platform = 'AIX'
1886+
    platform = 'AIX'
1887-
1887+
1888-
    # AIX 'ifconfig -a' does not have three words in the interface line
1888+
    # AIX 'ifconfig -a' does not have three words in the interface line
1889-
    def get_interfaces_info(self, ifconfig_path):
1889+
    def get_interfaces_info(self, ifconfig_path):
1890-
        interfaces = {}
1890+
        interfaces = {}
1891-
        current_if = {}
1891+
        current_if = {}
1892-
        ips = dict(
1892+
        ips = dict(
1893-
            all_ipv4_addresses = [],
1893+
            all_ipv4_addresses = [],
1894-
            all_ipv6_addresses = [],
1894+
            all_ipv6_addresses = [],
1895-
        )
1895+
        )
1896-
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1896+
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1897-
1897+
1898-
        for line in out.split('\n'):
1898+
        for line in out.split('\n'):
1899-
1899+
1900-
            if line:
1900+
            if line:
1901-
                words = line.split()
1901+
                words = line.split()
1902-
1902+
1903-
		# only this condition differs from GenericBsdIfconfigNetwork
1903+
		# only this condition differs from GenericBsdIfconfigNetwork
1904-
                if re.match('^\w*\d*:', line):
1904+
                if re.match('^\w*\d*:', line):
1905-
                    current_if = self.parse_interface_line(words)
1905+
                    current_if = self.parse_interface_line(words)
1906-
                    interfaces[ current_if['device'] ] = current_if
1906+
                    interfaces[ current_if['device'] ] = current_if
1907-
                elif words[0].startswith('options='):
1907+
                elif words[0].startswith('options='):
1908-
                    self.parse_options_line(words, current_if, ips)
1908+
                    self.parse_options_line(words, current_if, ips)
1909-
                elif words[0] == 'nd6':
1909+
                elif words[0] == 'nd6':
1910-
                    self.parse_nd6_line(words, current_if, ips)
1910+
                    self.parse_nd6_line(words, current_if, ips)
1911-
                elif words[0] == 'ether':
1911+
                elif words[0] == 'ether':
1912-
                    self.parse_ether_line(words, current_if, ips)
1912+
                    self.parse_ether_line(words, current_if, ips)
1913-
                elif words[0] == 'media:':
1913+
                elif words[0] == 'media:':
1914-
                    self.parse_media_line(words, current_if, ips)
1914+
                    self.parse_media_line(words, current_if, ips)
1915-
                elif words[0] == 'status:':
1915+
                elif words[0] == 'status:':
1916-
                    self.parse_status_line(words, current_if, ips)
1916+
                    self.parse_status_line(words, current_if, ips)
1917-
                elif words[0] == 'lladdr':
1917+
                elif words[0] == 'lladdr':
1918-
                    self.parse_lladdr_line(words, current_if, ips)
1918+
                    self.parse_lladdr_line(words, current_if, ips)
1919-
                elif words[0] == 'inet':
1919+
                elif words[0] == 'inet':
1920-
                    self.parse_inet_line(words, current_if, ips)
1920+
                    self.parse_inet_line(words, current_if, ips)
1921-
                elif words[0] == 'inet6':
1921+
                elif words[0] == 'inet6':
1922-
                    self.parse_inet6_line(words, current_if, ips)
1922+
                    self.parse_inet6_line(words, current_if, ips)
1923-
                else:
1923+
                else:
1924-
                    self.parse_unknown_line(words, current_if, ips)
1924+
                    self.parse_unknown_line(words, current_if, ips)
1925-
1925+
1926-
        return interfaces, ips
1926+
        return interfaces, ips
1927-
1927+
1928-
    # AIX 'ifconfig -a' does not inform about MTU, so remove current_if['mtu'] here
1928+
    # AIX 'ifconfig -a' does not inform about MTU, so remove current_if['mtu'] here
1929-
    def parse_interface_line(self, words):
1929+
    def parse_interface_line(self, words):
1930-
        device = words[0][0:-1]
1930+
        device = words[0][0:-1]
1931-
        current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
1931+
        current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
1932-
        current_if['flags'] = self.get_options(words[1])
1932+
        current_if['flags'] = self.get_options(words[1])
1933-
        current_if['macaddress'] = 'unknown'    # will be overwritten later
1933+
        current_if['macaddress'] = 'unknown'    # will be overwritten later
1934-
        return current_if
1934+
        return current_if
1935-
1935+
1936-
class OpenBSDNetwork(GenericBsdIfconfigNetwork, Network):
1936+
class OpenBSDNetwork(GenericBsdIfconfigNetwork, Network):
1937-
    """
1937+
    """
1938-
    This is the OpenBSD Network Class.
1938+
    This is the OpenBSD Network Class.
1939-
    It uses the GenericBsdIfconfigNetwork.
1939+
    It uses the GenericBsdIfconfigNetwork.
1940-
    """
1940+
    """
1941-
    platform = 'OpenBSD'
1941+
    platform = 'OpenBSD'
1942-
1942+
1943-
    # Return macaddress instead of lladdr
1943+
    # Return macaddress instead of lladdr
1944-
    def parse_lladdr_line(self, words, current_if, ips):
1944+
    def parse_lladdr_line(self, words, current_if, ips):
1945-
        current_if['macaddress'] = words[1]
1945+
        current_if['macaddress'] = words[1]
1946-
1946+
1947-
class SunOSNetwork(GenericBsdIfconfigNetwork, Network):
1947+
class SunOSNetwork(GenericBsdIfconfigNetwork, Network):
1948-
    """
1948+
    """
1949-
    This is the SunOS Network Class.
1949+
    This is the SunOS Network Class.
1950-
    It uses the GenericBsdIfconfigNetwork.
1950+
    It uses the GenericBsdIfconfigNetwork.
1951-
1951+
1952-
    Solaris can have different FLAGS and MTU for IPv4 and IPv6 on the same interface
1952+
    Solaris can have different FLAGS and MTU for IPv4 and IPv6 on the same interface
1953-
    so these facts have been moved inside the 'ipv4' and 'ipv6' lists.
1953+
    so these facts have been moved inside the 'ipv4' and 'ipv6' lists.
1954-
    """
1954+
    """
1955-
    platform = 'SunOS'
1955+
    platform = 'SunOS'
1956-
1956+
1957-
    # Solaris 'ifconfig -a' will print interfaces twice, once for IPv4 and again for IPv6.
1957+
    # Solaris 'ifconfig -a' will print interfaces twice, once for IPv4 and again for IPv6.
1958-
    # MTU and FLAGS also may differ between IPv4 and IPv6 on the same interface.
1958+
    # MTU and FLAGS also may differ between IPv4 and IPv6 on the same interface.
1959-
    # 'parse_interface_line()' checks for previously seen interfaces before defining
1959+
    # 'parse_interface_line()' checks for previously seen interfaces before defining
1960-
    # 'current_if' so that IPv6 facts don't clobber IPv4 facts (or vice versa).
1960+
    # 'current_if' so that IPv6 facts don't clobber IPv4 facts (or vice versa).
1961-
    def get_interfaces_info(self, ifconfig_path):
1961+
    def get_interfaces_info(self, ifconfig_path):
1962-
        interfaces = {}
1962+
        interfaces = {}
1963-
        current_if = {}
1963+
        current_if = {}
1964-
        ips = dict(
1964+
        ips = dict(
1965-
            all_ipv4_addresses = [],
1965+
            all_ipv4_addresses = [],
1966-
            all_ipv6_addresses = [],
1966+
            all_ipv6_addresses = [],
1967-
        )
1967+
        )
1968-
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1968+
        rc, out, err = module.run_command([ifconfig_path, '-a'])
1969-
1969+
1970-
        for line in out.split('\n'):
1970+
        for line in out.split('\n'):
1971-
1971+
1972-
            if line:
1972+
            if line:
1973-
                words = line.split()
1973+
                words = line.split()
1974-
1974+
1975-
                if re.match('^\S', line) and len(words) > 3:
1975+
                if re.match('^\S', line) and len(words) > 3:
1976-
                    current_if = self.parse_interface_line(words, current_if, interfaces)
1976+
                    current_if = self.parse_interface_line(words, current_if, interfaces)
1977-
                    interfaces[ current_if['device'] ] = current_if
1977+
                    interfaces[ current_if['device'] ] = current_if
1978-
                elif words[0].startswith('options='):
1978+
                elif words[0].startswith('options='):
1979-
                    self.parse_options_line(words, current_if, ips)
1979+
                    self.parse_options_line(words, current_if, ips)
1980-
                elif words[0] == 'nd6':
1980+
                elif words[0] == 'nd6':
1981-
                    self.parse_nd6_line(words, current_if, ips)
1981+
                    self.parse_nd6_line(words, current_if, ips)
1982-
                elif words[0] == 'ether':
1982+
                elif words[0] == 'ether':
1983-
                    self.parse_ether_line(words, current_if, ips)
1983+
                    self.parse_ether_line(words, current_if, ips)
1984-
                elif words[0] == 'media:':
1984+
                elif words[0] == 'media:':
1985-
                    self.parse_media_line(words, current_if, ips)
1985+
                    self.parse_media_line(words, current_if, ips)
1986-
                elif words[0] == 'status:':
1986+
                elif words[0] == 'status:':
1987-
                    self.parse_status_line(words, current_if, ips)
1987+
                    self.parse_status_line(words, current_if, ips)
1988-
                elif words[0] == 'lladdr':
1988+
                elif words[0] == 'lladdr':
1989-
                    self.parse_lladdr_line(words, current_if, ips)
1989+
                    self.parse_lladdr_line(words, current_if, ips)
1990-
                elif words[0] == 'inet':
1990+
                elif words[0] == 'inet':
1991-
                    self.parse_inet_line(words, current_if, ips)
1991+
                    self.parse_inet_line(words, current_if, ips)
1992-
                elif words[0] == 'inet6':
1992+
                elif words[0] == 'inet6':
1993-
                    self.parse_inet6_line(words, current_if, ips)
1993+
                    self.parse_inet6_line(words, current_if, ips)
1994-
                else:
1994+
                else:
1995-
                    self.parse_unknown_line(words, current_if, ips)
1995+
                    self.parse_unknown_line(words, current_if, ips)
1996-
1996+
1997-
        # 'parse_interface_line' and 'parse_inet*_line' leave two dicts in the
1997+
        # 'parse_interface_line' and 'parse_inet*_line' leave two dicts in the
1998-
        # ipv4/ipv6 lists which is ugly and hard to read.
1998+
        # ipv4/ipv6 lists which is ugly and hard to read.
1999-
        # This quick hack merges the dictionaries. Purely cosmetic.
1999+
        # This quick hack merges the dictionaries. Purely cosmetic.
2000-
        for iface in interfaces:
2000+
        for iface in interfaces:
2001-
            for v in 'ipv4', 'ipv6':
2001+
            for v in 'ipv4', 'ipv6':
2002-
                combined_facts = {}
2002+
                combined_facts = {}
2003-
                for facts in interfaces[iface][v]:
2003+
                for facts in interfaces[iface][v]:
2004-
                    combined_facts.update(facts)
2004+
                    combined_facts.update(facts)
2005-
                if len(combined_facts.keys()) > 0:
2005+
                if len(combined_facts.keys()) > 0:
2006-
                    interfaces[iface][v] = [combined_facts]
2006+
                    interfaces[iface][v] = [combined_facts]
2007-
2007+
2008-
        return interfaces, ips
2008+
        return interfaces, ips
2009-
2009+
2010-
    def parse_interface_line(self, words, current_if, interfaces):
2010+
    def parse_interface_line(self, words, current_if, interfaces):
2011-
        device = words[0][0:-1]
2011+
        device = words[0][0:-1]
2012-
        if device not in interfaces.keys():
2012+
        if device not in interfaces.keys():
2013-
            current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
2013+
            current_if = {'device': device, 'ipv4': [], 'ipv6': [], 'type': 'unknown'}
2014-
        else:
2014+
        else:
2015-
            current_if = interfaces[device]
2015+
            current_if = interfaces[device]
2016-
        flags = self.get_options(words[1])
2016+
        flags = self.get_options(words[1])
2017-
        if 'IPv4' in flags:
2017+
        if 'IPv4' in flags:
2018-
            v = 'ipv4'
2018+
            v = 'ipv4'
2019-
        if 'IPv6' in flags:
2019+
        if 'IPv6' in flags:
2020-
            v = 'ipv6'
2020+
            v = 'ipv6'
2021-
        current_if[v].append({'flags': flags, 'mtu': words[3]})
2021+
        current_if[v].append({'flags': flags, 'mtu': words[3]})
2022-
        current_if['macaddress'] = 'unknown'    # will be overwritten later
2022+
        current_if['macaddress'] = 'unknown'    # will be overwritten later
2023-
        return current_if
2023+
        return current_if
2024-
2024+
2025-
    # Solaris displays single digit octets in MAC addresses e.g. 0:1:2:d:e:f
2025+
    # Solaris displays single digit octets in MAC addresses e.g. 0:1:2:d:e:f
2026-
    # Add leading zero to each octet where needed.
2026+
    # Add leading zero to each octet where needed.
2027-
    def parse_ether_line(self, words, current_if, ips):
2027+
    def parse_ether_line(self, words, current_if, ips):
2028-
        macaddress = ''
2028+
        macaddress = ''
2029-
        for octet in words[1].split(':'):
2029+
        for octet in words[1].split(':'):
2030-
            octet = ('0' + octet)[-2:None]
2030+
            octet = ('0' + octet)[-2:None]
2031-
            macaddress += (octet + ':')
2031+
            macaddress += (octet + ':')
2032-
        current_if['macaddress'] = macaddress[0:-1]
2032+
        current_if['macaddress'] = macaddress[0:-1]
2033-
2033+
2034-
class Virtual(Facts):
2034+
class Virtual(Facts):
2035-
    """
2035+
    """
2036-
    This is a generic Virtual subclass of Facts.  This should be further
2036+
    This is a generic Virtual subclass of Facts.  This should be further
2037-
    subclassed to implement per platform.  If you subclass this,
2037+
    subclassed to implement per platform.  If you subclass this,
2038-
    you should define:
2038+
    you should define:
2039-
    - virtualization_type
2039+
    - virtualization_type
2040-
    - virtualization_role
2040+
    - virtualization_role
2041-
    - container (e.g. solaris zones, freebsd jails, linux containers)
2041+
    - container (e.g. solaris zones, freebsd jails, linux containers)
2042-
2042+
2043-
    All subclasses MUST define platform.
2043+
    All subclasses MUST define platform.
2044-
    """
2044+
    """
2045-
2045+
2046-
    def __new__(cls, *arguments, **keyword):
2046+
    def __new__(cls, *arguments, **keyword):
2047-
        subclass = cls
2047+
        subclass = cls
2048-
        for sc in Virtual.__subclasses__():
2048+
        for sc in Virtual.__subclasses__():
2049-
            if sc.platform == platform.system():
2049+
            if sc.platform == platform.system():
2050-
                subclass = sc
2050+
                subclass = sc
2051-
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
2051+
        return super(cls, subclass).__new__(subclass, *arguments, **keyword)
2052-
2052+
2053-
    def __init__(self):
2053+
    def __init__(self):
2054-
        Facts.__init__(self)
2054+
        Facts.__init__(self)
2055-
2055+
2056-
    def populate(self):
2056+
    def populate(self):
2057-
        return self.facts
2057+
        return self.facts
2058-
2058+
2059-
class LinuxVirtual(Virtual):
2059+
class LinuxVirtual(Virtual):
2060-
    """
2060+
    """
2061-
    This is a Linux-specific subclass of Virtual.  It defines
2061+
    This is a Linux-specific subclass of Virtual.  It defines
2062-
    - virtualization_type
2062+
    - virtualization_type
2063-
    - virtualization_role
2063+
    - virtualization_role
2064-
    """
2064+
    """
2065-
    platform = 'Linux'
2065+
    platform = 'Linux'
2066-
2066+
2067-
    def __init__(self):
2067+
    def __init__(self):
2068-
        Virtual.__init__(self)
2068+
        Virtual.__init__(self)
2069-
2069+
2070-
    def populate(self):
2070+
    def populate(self):
2071-
        self.get_virtual_facts()
2071+
        self.get_virtual_facts()
2072-
        return self.facts
2072+
        return self.facts
2073-
2073+
2074-
    # For more information, check: http://people.redhat.com/~rjones/virt-what/
2074+
    # For more information, check: http://people.redhat.com/~rjones/virt-what/
2075-
    def get_virtual_facts(self):
2075+
    def get_virtual_facts(self):
2076-
        if os.path.exists("/proc/xen"):
2076+
        if os.path.exists("/proc/xen"):
2077-
            self.facts['virtualization_type'] = 'xen'
2077+
            self.facts['virtualization_type'] = 'xen'
2078-
            self.facts['virtualization_role'] = 'guest'
2078+
            self.facts['virtualization_role'] = 'guest'
2079-
            try:
2079+
            try:
2080-
                for line in open('/proc/xen/capabilities'):
2080+
                for line in open('/proc/xen/capabilities'):
2081-
                    if "control_d" in line:
2081+
                    if "control_d" in line:
2082-
                        self.facts['virtualization_role'] = 'host'
2082+
                        self.facts['virtualization_role'] = 'host'
2083-
            except IOError:
2083+
            except IOError:
2084-
                pass
2084+
                pass
2085-
            return
2085+
            return
2086-
2086+
2087-
        if os.path.exists('/proc/vz'):
2087+
        if os.path.exists('/proc/vz'):
2088-
            self.facts['virtualization_type'] = 'openvz'
2088+
            self.facts['virtualization_type'] = 'openvz'
2089-
            if os.path.exists('/proc/bc'):
2089+
            if os.path.exists('/proc/bc'):
2090-
                self.facts['virtualization_role'] = 'host'
2090+
                self.facts['virtualization_role'] = 'host'
2091-
            else:
2091+
            else:
2092-
                self.facts['virtualization_role'] = 'guest'
2092+
                self.facts['virtualization_role'] = 'guest'
2093-
            return
2093+
            return
2094-
2094+
2095-
        if os.path.exists('/proc/1/cgroup'):
2095+
        if os.path.exists('/proc/1/cgroup'):
2096-
            for line in open('/proc/1/cgroup').readlines():
2096+
            for line in open('/proc/1/cgroup').readlines():
2097-
                if re.search('/lxc/', line):
2097+
                if re.search('/lxc/', line):
2098-
                    self.facts['virtualization_type'] = 'lxc'
2098+
                    self.facts['virtualization_type'] = 'lxc'
2099-
                    self.facts['virtualization_role'] = 'guest'
2099+
                    self.facts['virtualization_role'] = 'guest'
2100-
                    return
2100+
                    return
2101-
2101+
2102-
        product_name = get_file_content('/sys/devices/virtual/dmi/id/product_name')
2102+
        product_name = get_file_content('/sys/devices/virtual/dmi/id/product_name')
2103-
2103+
2104-
        if product_name in ['KVM', 'Bochs']:
2104+
        if product_name in ['KVM', 'Bochs']:
2105-
            self.facts['virtualization_type'] = 'kvm'
2105+
            self.facts['virtualization_type'] = 'kvm'
2106-
            self.facts['virtualization_role'] = 'guest'
2106+
            self.facts['virtualization_role'] = 'guest'
2107-
            return
2107+
            return
2108-
2108+
2109-
        if product_name == 'RHEV Hypervisor':
2109+
        if product_name == 'RHEV Hypervisor':
2110-
            self.facts['virtualization_type'] = 'RHEV'
2110+
            self.facts['virtualization_type'] = 'RHEV'
2111-
            self.facts['virtualization_role'] = 'guest'
2111+
            self.facts['virtualization_role'] = 'guest'
2112-
            return
2112+
            return
2113-
2113+
2114-
        if product_name == 'VMware Virtual Platform':
2114+
        if product_name == 'VMware Virtual Platform':
2115-
            self.facts['virtualization_type'] = 'VMware'
2115+
            self.facts['virtualization_type'] = 'VMware'
2116-
            self.facts['virtualization_role'] = 'guest'
2116+
            self.facts['virtualization_role'] = 'guest'
2117-
            return
2117+
            return
2118-
2118+
2119-
        bios_vendor = get_file_content('/sys/devices/virtual/dmi/id/bios_vendor')
2119+
        bios_vendor = get_file_content('/sys/devices/virtual/dmi/id/bios_vendor')
2120-
2120+
2121-
        if bios_vendor == 'Xen':
2121+
        if bios_vendor == 'Xen':
2122-
            self.facts['virtualization_type'] = 'xen'
2122+
            self.facts['virtualization_type'] = 'xen'
2123-
            self.facts['virtualization_role'] = 'guest'
2123+
            self.facts['virtualization_role'] = 'guest'
2124-
            return
2124+
            return
2125-
2125+
2126-
        if bios_vendor == 'innotek GmbH':
2126+
        if bios_vendor == 'innotek GmbH':
2127-
            self.facts['virtualization_type'] = 'virtualbox'
2127+
            self.facts['virtualization_type'] = 'virtualbox'
2128-
            self.facts['virtualization_role'] = 'guest'
2128+
            self.facts['virtualization_role'] = 'guest'
2129-
            return
2129+
            return
2130-
2130+
2131-
        sys_vendor = get_file_content('/sys/devices/virtual/dmi/id/sys_vendor')
2131+
        sys_vendor = get_file_content('/sys/devices/virtual/dmi/id/sys_vendor')
2132-
2132+
2133-
        # FIXME: This does also match hyperv
2133+
        # FIXME: This does also match hyperv
2134-
        if sys_vendor == 'Microsoft Corporation':
2134+
        if sys_vendor == 'Microsoft Corporation':
2135-
            self.facts['virtualization_type'] = 'VirtualPC'
2135+
            self.facts['virtualization_type'] = 'VirtualPC'
2136-
            self.facts['virtualization_role'] = 'guest'
2136+
            self.facts['virtualization_role'] = 'guest'
2137-
            return
2137+
            return
2138-
2138+
2139-
        if sys_vendor == 'Parallels Software International Inc.':
2139+
        if sys_vendor == 'Parallels Software International Inc.':
2140-
            self.facts['virtualization_type'] = 'parallels'
2140+
            self.facts['virtualization_type'] = 'parallels'
2141-
            self.facts['virtualization_role'] = 'guest'
2141+
            self.facts['virtualization_role'] = 'guest'
2142-
            return
2142+
            return
2143-
2143+
2144-
        if os.path.exists('/proc/self/status'):
2144+
        if os.path.exists('/proc/self/status'):
2145-
            for line in open('/proc/self/status').readlines():
2145+
            for line in open('/proc/self/status').readlines():
2146-
                if re.match('^VxID: \d+', line):
2146+
                if re.match('^VxID: \d+', line):
2147-
                    self.facts['virtualization_type'] = 'linux_vserver'
2147+
                    self.facts['virtualization_type'] = 'linux_vserver'
2148-
                    if re.match('^VxID: 0', line):
2148+
                    if re.match('^VxID: 0', line):
2149-
                        self.facts['virtualization_role'] = 'host'
2149+
                        self.facts['virtualization_role'] = 'host'
2150-
                    else:
2150+
                    else:
2151-
                        self.facts['virtualization_role'] = 'guest'
2151+
                        self.facts['virtualization_role'] = 'guest'
2152-
                    return
2152+
                    return
2153-
2153+
2154-
        if os.path.exists('/proc/cpuinfo'):
2154+
        if os.path.exists('/proc/cpuinfo'):
2155-
            for line in open('/proc/cpuinfo').readlines():
2155+
            for line in open('/proc/cpuinfo').readlines():
2156-
                if re.match('^model name.*QEMU Virtual CPU', line):
2156+
                if re.match('^model name.*QEMU Virtual CPU', line):
2157-
                    self.facts['virtualization_type'] = 'kvm'
2157+
                    self.facts['virtualization_type'] = 'kvm'
2158-
                elif re.match('^vendor_id.*User Mode Linux', line):
2158+
                elif re.match('^vendor_id.*User Mode Linux', line):
2159-
                    self.facts['virtualization_type'] = 'uml'
2159+
                    self.facts['virtualization_type'] = 'uml'
2160-
                elif re.match('^model name.*UML', line):
2160+
                elif re.match('^model name.*UML', line):
2161-
                    self.facts['virtualization_type'] = 'uml'
2161+
                    self.facts['virtualization_type'] = 'uml'
2162-
                elif re.match('^vendor_id.*PowerVM Lx86', line):
2162+
                elif re.match('^vendor_id.*PowerVM Lx86', line):
2163-
                    self.facts['virtualization_type'] = 'powervm_lx86'
2163+
                    self.facts['virtualization_type'] = 'powervm_lx86'
2164-
                elif re.match('^vendor_id.*IBM/S390', line):
2164+
                elif re.match('^vendor_id.*IBM/S390', line):
2165-
                    self.facts['virtualization_type'] = 'ibm_systemz'
2165+
                    self.facts['virtualization_type'] = 'ibm_systemz'
2166-
                else:
2166+
                else:
2167-
                    continue
2167+
                    continue
2168-
                self.facts['virtualization_role'] = 'guest'
2168+
                self.facts['virtualization_role'] = 'guest'
2169-
                return
2169+
                return
2170-
2170+
2171-
        # Beware that we can have both kvm and virtualbox running on a single system
2171+
        # Beware that we can have both kvm and virtualbox running on a single system
2172-
        if os.path.exists("/proc/modules") and os.access('/proc/modules', os.R_OK):
2172+
        if os.path.exists("/proc/modules") and os.access('/proc/modules', os.R_OK):
2173-
            modules = []
2173+
            modules = []
2174-
            for line in open("/proc/modules").readlines():
2174+
            for line in open("/proc/modules").readlines():
2175-
                data = line.split(" ", 1)
2175+
                data = line.split(" ", 1)
2176-
                modules.append(data[0])
2176+
                modules.append(data[0])
2177-
2177+
2178-
            if 'kvm' in modules:
2178+
            if 'kvm' in modules:
2179-
                self.facts['virtualization_type'] = 'kvm'
2179+
                self.facts['virtualization_type'] = 'kvm'
2180-
                self.facts['virtualization_role'] = 'host'
2180+
                self.facts['virtualization_role'] = 'host'
2181-
                return
2181+
                return
2182-
2182+
2183-
            if 'vboxdrv' in modules:
2183+
            if 'vboxdrv' in modules:
2184-
                self.facts['virtualization_type'] = 'virtualbox'
2184+
                self.facts['virtualization_type'] = 'virtualbox'
2185-
                self.facts['virtualization_role'] = 'host'
2185+
                self.facts['virtualization_role'] = 'host'
2186-
                return
2186+
                return
2187-
2187+
2188-
        # If none of the above matches, return 'NA' for virtualization_type
2188+
        # If none of the above matches, return 'NA' for virtualization_type
2189-
        # and virtualization_role. This allows for proper grouping.
2189+
        # and virtualization_role. This allows for proper grouping.
2190-
        self.facts['virtualization_type'] = 'NA'
2190+
        self.facts['virtualization_type'] = 'NA'
2191-
        self.facts['virtualization_role'] = 'NA'
2191+
        self.facts['virtualization_role'] = 'NA'
2192-
        return
2192+
        return
2193-
2193+
2194-
2194+
2195-
class HPUXVirtual(Virtual):
2195+
class HPUXVirtual(Virtual):
2196-
    """
2196+
    """
2197-
    This is a HP-UX specific subclass of Virtual. It defines
2197+
    This is a HP-UX specific subclass of Virtual. It defines
2198-
    - virtualization_type
2198+
    - virtualization_type
2199-
    - virtualization_role
2199+
    - virtualization_role
2200-
    """
2200+
    """
2201-
    platform = 'HP-UX'
2201+
    platform = 'HP-UX'
2202-
2202+
2203-
    def __init__(self):
2203+
    def __init__(self):
2204-
        Virtual.__init__(self)
2204+
        Virtual.__init__(self)
2205-
2205+
2206-
    def populate(self):
2206+
    def populate(self):
2207-
        self.get_virtual_facts()
2207+
        self.get_virtual_facts()
2208-
        return self.facts
2208+
        return self.facts
2209-
2209+
2210-
    def get_virtual_facts(self):
2210+
    def get_virtual_facts(self):
2211-
        if os.path.exists('/usr/sbin/vecheck'):
2211+
        if os.path.exists('/usr/sbin/vecheck'):
2212-
            rc, out, err = module.run_command("/usr/sbin/vecheck")
2212+
            rc, out, err = module.run_command("/usr/sbin/vecheck")
2213-
            if rc == 0:
2213+
            if rc == 0:
2214-
                self.facts['virtualization_type'] = 'guest'
2214+
                self.facts['virtualization_type'] = 'guest'
2215-
                self.facts['virtualization_role'] = 'HP vPar'
2215+
                self.facts['virtualization_role'] = 'HP vPar'
2216-
        if os.path.exists('/opt/hpvm/bin/hpvminfo'):
2216+
        if os.path.exists('/opt/hpvm/bin/hpvminfo'):
2217-
            rc, out, err = module.run_command("/opt/hpvm/bin/hpvminfo")
2217+
            rc, out, err = module.run_command("/opt/hpvm/bin/hpvminfo")
2218-
            if rc == 0 and re.match('.*Running.*HPVM vPar.*', out):
2218+
            if rc == 0 and re.match('.*Running.*HPVM vPar.*', out):
2219-
                self.facts['virtualization_type'] = 'guest'
2219+
                self.facts['virtualization_type'] = 'guest'
2220-
                self.facts['virtualization_role'] = 'HPVM vPar'
2220+
                self.facts['virtualization_role'] = 'HPVM vPar'
2221-
            elif rc == 0 and re.match('.*Running.*HPVM guest.*', out):
2221+
            elif rc == 0 and re.match('.*Running.*HPVM guest.*', out):
2222-
                self.facts['virtualization_type'] = 'guest'
2222+
                self.facts['virtualization_type'] = 'guest'
2223-
                self.facts['virtualization_role'] = 'HPVM IVM'
2223+
                self.facts['virtualization_role'] = 'HPVM IVM'
2224-
            elif rc == 0 and re.match('.*Running.*HPVM host.*', out):
2224+
            elif rc == 0 and re.match('.*Running.*HPVM host.*', out):
2225-
                self.facts['virtualization_type'] = 'host'
2225+
                self.facts['virtualization_type'] = 'host'
2226-
                self.facts['virtualization_role'] = 'HPVM'
2226+
                self.facts['virtualization_role'] = 'HPVM'
2227-
        if os.path.exists('/usr/sbin/parstatus'):
2227+
        if os.path.exists('/usr/sbin/parstatus'):
2228-
            rc, out, err = module.run_command("/usr/sbin/parstatus")
2228+
            rc, out, err = module.run_command("/usr/sbin/parstatus")
2229-
            if rc == 0:
2229+
            if rc == 0:
2230-
                self.facts['virtualization_type'] = 'guest'
2230+
                self.facts['virtualization_type'] = 'guest'
2231-
                self.facts['virtualization_role'] = 'HP nPar'
2231+
                self.facts['virtualization_role'] = 'HP nPar'
2232-
2232+
2233-
2233+
2234-
class SunOSVirtual(Virtual):
2234+
class SunOSVirtual(Virtual):
2235-
    """
2235+
    """
2236-
    This is a SunOS-specific subclass of Virtual.  It defines
2236+
    This is a SunOS-specific subclass of Virtual.  It defines
2237-
    - virtualization_type
2237+
    - virtualization_type
2238-
    - virtualization_role
2238+
    - virtualization_role
2239-
    - container
2239+
    - container
2240-
    """
2240+
    """
2241-
    platform = 'SunOS'
2241+
    platform = 'SunOS'
2242-
2242+
2243-
    def __init__(self):
2243+
    def __init__(self):
2244-
        Virtual.__init__(self)
2244+
        Virtual.__init__(self)
2245-
2245+
2246-
    def populate(self):
2246+
    def populate(self):
2247-
        self.get_virtual_facts()
2247+
        self.get_virtual_facts()
2248-
        return self.facts
2248+
        return self.facts
2249-
2249+
2250-
    def get_virtual_facts(self):
2250+
    def get_virtual_facts(self):
2251-
        rc, out, err = module.run_command("/usr/sbin/prtdiag")
2251+
        rc, out, err = module.run_command("/usr/sbin/prtdiag")
2252-
        for line in out.split('\n'):
2252+
        for line in out.split('\n'):
2253-
            if 'VMware' in line:
2253+
            if 'VMware' in line:
2254-
                self.facts['virtualization_type'] = 'vmware'
2254+
                self.facts['virtualization_type'] = 'vmware'
2255-
                self.facts['virtualization_role'] = 'guest'
2255+
                self.facts['virtualization_role'] = 'guest'
2256-
            if 'Parallels' in line:
2256+
            if 'Parallels' in line:
2257-
                self.facts['virtualization_type'] = 'parallels'
2257+
                self.facts['virtualization_type'] = 'parallels'
2258-
                self.facts['virtualization_role'] = 'guest'
2258+
                self.facts['virtualization_role'] = 'guest'
2259-
            if 'VirtualBox' in line:
2259+
            if 'VirtualBox' in line:
2260-
                self.facts['virtualization_type'] = 'virtualbox'
2260+
                self.facts['virtualization_type'] = 'virtualbox'
2261-
                self.facts['virtualization_role'] = 'guest'
2261+
                self.facts['virtualization_role'] = 'guest'
2262-
            if 'HVM domU' in line:
2262+
            if 'HVM domU' in line:
2263-
                self.facts['virtualization_type'] = 'xen'
2263+
                self.facts['virtualization_type'] = 'xen'
2264-
                self.facts['virtualization_role'] = 'guest'
2264+
                self.facts['virtualization_role'] = 'guest'
2265-
        # Check if it's a zone
2265+
        # Check if it's a zone
2266-
        if os.path.exists("/usr/bin/zonename"):
2266+
        if os.path.exists("/usr/bin/zonename"):
2267-
            rc, out, err = module.run_command("/usr/bin/zonename")
2267+
            rc, out, err = module.run_command("/usr/bin/zonename")
2268-
            if out.rstrip() != "global":
2268+
            if out.rstrip() != "global":
2269-
                self.facts['container'] = 'zone'
2269+
                self.facts['container'] = 'zone'
2270-
        # Check if it's a branded zone (i.e. Solaris 8/9 zone)
2270+
        # Check if it's a branded zone (i.e. Solaris 8/9 zone)
2271-
        if os.path.isdir('/.SUNWnative'):
2271+
        if os.path.isdir('/.SUNWnative'):
2272-
            self.facts['container'] = 'zone'
2272+
            self.facts['container'] = 'zone'
2273-
        # If it's a zone check if we can detect if our global zone is itself virtualized.
2273+
        # If it's a zone check if we can detect if our global zone is itself virtualized.
2274-
        # Relies on the "guest tools" (e.g. vmware tools) to be installed
2274+
        # Relies on the "guest tools" (e.g. vmware tools) to be installed
2275-
        if 'container' in self.facts and self.facts['container'] == 'zone':
2275+
        if 'container' in self.facts and self.facts['container'] == 'zone':
2276-
            rc, out, err = module.run_command("/usr/sbin/modinfo")
2276+
            rc, out, err = module.run_command("/usr/sbin/modinfo")
2277-
            for line in out.split('\n'):
2277+
            for line in out.split('\n'):
2278-
                if 'VMware' in line:
2278+
                if 'VMware' in line:
2279-
                    self.facts['virtualization_type'] = 'vmware'
2279+
                    self.facts['virtualization_type'] = 'vmware'
2280-
                    self.facts['virtualization_role'] = 'guest'
2280+
                    self.facts['virtualization_role'] = 'guest'
2281-
                if 'VirtualBox' in line:
2281+
                if 'VirtualBox' in line:
2282-
                    self.facts['virtualization_type'] = 'virtualbox'
2282+
                    self.facts['virtualization_type'] = 'virtualbox'
2283-
                    self.facts['virtualization_role'] = 'guest'
2283+
                    self.facts['virtualization_role'] = 'guest'
2284-
2284+
2285-
def get_file_content(path, default=None):
2285+
def get_file_content(path, default=None):
2286-
    data = default
2286+
    data = default
2287-
    if os.path.exists(path) and os.access(path, os.R_OK):
2287+
    if os.path.exists(path) and os.access(path, os.R_OK):
2288-
        data = open(path).read().strip()
2288+
        data = open(path).read().strip()
2289-
        if len(data) == 0:
2289+
        if len(data) == 0:
2290-
            data = default
2290+
            data = default
2291-
    return data
2291+
    return data
2292-
2292+
2293-
def ansible_facts(module):
2293+
def ansible_facts(module):
2294-
    facts = {}
2294+
    facts = {}
2295-
    facts.update(Facts().populate())
2295+
    facts.update(Facts().populate())
2296-
    facts.update(Hardware().populate())
2296+
    facts.update(Hardware().populate())
2297-
    facts.update(Network(module).populate())
2297+
    facts.update(Network(module).populate())
2298-
    facts.update(Virtual().populate())
2298+
    facts.update(Virtual().populate())
2299-
    return facts
2299+
    return facts
2300-
2300+
2301-
# ===========================================
2301+
# ===========================================
2302-
2302+
2303-
def get_all_facts(module):
2303+
def get_all_facts(module):
2304-
2304+
2305-
    setup_options = dict(module_setup=True)
2305+
    setup_options = dict(module_setup=True)
2306-
    facts = ansible_facts(module)
2306+
    facts = ansible_facts(module)
2307-
2307+
2308-
    for (k, v) in facts.items():
2308+
    for (k, v) in facts.items():
2309-
        setup_options["ansible_%s" % k.replace('-', '_')] = v
2309+
        setup_options["ansible_%s" % k.replace('-', '_')] = v
2310-
2310+
2311-
    # Look for the path to the facter and ohai binary and set
2311+
    # Look for the path to the facter and ohai binary and set
2312-
    # the variable to that path.
2312+
    # the variable to that path.
2313-
2313+
2314-
    facter_path = module.get_bin_path('facter')
2314+
    facter_path = module.get_bin_path('facter')
2315-
    ohai_path = module.get_bin_path('ohai')
2315+
    ohai_path = module.get_bin_path('ohai')
2316-
2316+
2317-
    # if facter is installed, and we can use --json because
2317+
    # if facter is installed, and we can use --json because
2318-
    # ruby-json is ALSO installed, include facter data in the JSON
2318+
    # ruby-json is ALSO installed, include facter data in the JSON
2319-
2319+
2320-
    if facter_path is not None:
2320+
    if facter_path is not None:
2321-
        rc, out, err = module.run_command(facter_path + " --json")
2321+
        rc, out, err = module.run_command(facter_path + " --json")
2322-
        facter = True
2322+
        facter = True
2323-
        try:
2323+
        try:
2324-
            facter_ds = json.loads(out)
2324+
            facter_ds = json.loads(out)
2325-
        except:
2325+
        except:
2326-
            facter = False
2326+
            facter = False
2327-
        if facter:
2327+
        if facter:
2328-
            for (k,v) in facter_ds.items():
2328+
            for (k,v) in facter_ds.items():
2329-
                setup_options["facter_%s" % k] = v
2329+
                setup_options["facter_%s" % k] = v
2330-
2330+
2331-
    # ditto for ohai
2331+
    # ditto for ohai
2332-
2332+
2333-
    if ohai_path is not None:
2333+
    if ohai_path is not None:
2334-
        rc, out, err = module.run_command(ohai_path)
2334+
        rc, out, err = module.run_command(ohai_path)
2335-
        ohai = True
2335+
        ohai = True
2336-
        try:
2336+
        try:
2337-
            ohai_ds = json.loads(out)
2337+
            ohai_ds = json.loads(out)
2338-
        except:
2338+
        except:
2339-
            ohai = False
2339+
            ohai = False
2340-
        if ohai:
2340+
        if ohai:
2341-
            for (k,v) in ohai_ds.items():
2341+
            for (k,v) in ohai_ds.items():
2342-
                k2 = "ohai_%s" % k.replace('-', '_')
2342+
                k2 = "ohai_%s" % k.replace('-', '_')
2343-
                setup_options[k2] = v
2343+
                setup_options[k2] = v
2344-
2344+
2345-
    setup_result = { 'ansible_facts': {} }
2345+
    setup_result = { 'ansible_facts': {} }
2346-
2346+
2347-
    for (k,v) in setup_options.items():
2347+
    for (k,v) in setup_options.items():
2348-
        if module.params['filter'] == '*' or fnmatch.fnmatch(k, module.params['filter']):
2348+
        if module.params['filter'] == '*' or fnmatch.fnmatch(k, module.params['filter']):
2349-
            setup_result['ansible_facts'][k] = v
2349+
            setup_result['ansible_facts'][k] = v
2350-
2350+
2351-
    # hack to keep --verbose from showing all the setup module results
2351+
    # hack to keep --verbose from showing all the setup module results
2352-
    setup_result['verbose_override'] = True
2352+
    setup_result['verbose_override'] = True
2353-
2353+
2354
    return setup_result