Exemple #1
0
    def collect(self, module=None, collected_facts=None):
        platform_facts = {}
        # platform.system() can be Linux, Darwin, Java, or Windows
        platform_facts['system'] = platform.system()
        platform_facts['kernel'] = platform.release()
        platform_facts['machine'] = platform.machine()

        platform_facts['python_version'] = platform.python_version()

        platform_facts['fqdn'] = socket.getfqdn()
        platform_facts['hostname'] = platform.node().split('.')[0]
        platform_facts['nodename'] = platform.node()

        platform_facts['domain'] = '.'.join(platform_facts['fqdn'].split('.')[1:])

        arch_bits = platform.architecture()[0]

        platform_facts['userspace_bits'] = arch_bits.replace('bit', '')
        if platform_facts['machine'] == 'x86_64':
            platform_facts['architecture'] = platform_facts['machine']
            if platform_facts['userspace_bits'] == '64':
                platform_facts['userspace_architecture'] = 'x86_64'
            elif platform_facts['userspace_bits'] == '32':
                platform_facts['userspace_architecture'] = 'i386'
        elif solaris_i86_re.search(platform_facts['machine']):
            platform_facts['architecture'] = 'i386'
            if platform_facts['userspace_bits'] == '64':
                platform_facts['userspace_architecture'] = 'x86_64'
            elif platform_facts['userspace_bits'] == '32':
                platform_facts['userspace_architecture'] = 'i386'
        else:
            platform_facts['architecture'] = platform_facts['machine']

        if platform_facts['system'] == 'AIX':
            # Attempt to use getconf to figure out architecture
            # fall back to bootinfo if needed
            getconf_bin = module.get_bin_path('getconf')
            if getconf_bin:
                rc, out, err = module.run_command([getconf_bin, 'MACHINE_ARCHITECTURE'])
                data = out.splitlines()
                platform_facts['architecture'] = data[0]
            else:
                bootinfo_bin = module.get_bin_path('bootinfo')
                rc, out, err = module.run_command([bootinfo_bin, '-p'])
                data = out.splitlines()
                platform_facts['architecture'] = data[0]
        elif platform_facts['system'] == 'OpenBSD':
            platform_facts['architecture'] = platform.uname()[5]

        machine_id = get_file_content("/var/lib/dbus/machine-id") or get_file_content("/etc/machine-id")
        if machine_id:
            machine_id = machine_id.splitlines()[0]
            platform_facts["machine_id"] = machine_id

        return platform_facts
Exemple #2
0
    def get_distribution_SunOS(self):
        sunos_facts = {}

        # print('platform.release: %s' % distribution_release)
        data = get_file_content('/etc/release').splitlines()[0]

        # print('get_file_content: data=%s' % data)

        if 'Solaris' in data:
            ora_prefix = ''
            if 'Oracle Solaris' in data:
                data = data.replace('Oracle ', '')
                ora_prefix = 'Oracle '
            sunos_facts['distribution'] = data.split()[0]
            sunos_facts['distribution_version'] = data.split()[1]
            sunos_facts['distribution_release'] = ora_prefix + data
            return sunos_facts

        uname_v = get_uname_version(self.module)
        distribution_version = None

        # print('uname_v: %s' % uname_v)

        if 'SmartOS' in data:
            sunos_facts['distribution'] = 'SmartOS'
            if _file_exists('/etc/product'):
                product_data = dict([l.split(': ', 1) for l in get_file_content('/etc/product').splitlines() if ': ' in l])
                if 'Image' in product_data:
                    distribution_version = product_data.get('Image').split()[-1]
        elif 'OpenIndiana' in data:
            sunos_facts['distribution'] = 'OpenIndiana'
        elif 'OmniOS' in data:
            sunos_facts['distribution'] = 'OmniOS'
            distribution_version = data.split()[-1]
        elif uname_v is not None and 'NexentaOS_' in uname_v:
            sunos_facts['distribution'] = 'Nexenta'
            distribution_version = data.split()[-1].lstrip('v')

        # print('sunos_facts: %s' % sunos_facts)
        if sunos_facts.get('distribution', '') in ('SmartOS', 'OpenIndiana', 'OmniOS', 'Nexenta'):
            sunos_facts['distribution_release'] = data.strip()
            if distribution_version is not None:
                sunos_facts['distribution_version'] = distribution_version
            elif uname_v is not None:
                sunos_facts['distribution_version'] = uname_v.splitlines()[0].strip()
            return sunos_facts

        return sunos_facts
 def collect(self, module=None, collected_facts=None):
     # NOTE: this is populated even if it is not set
     fips_facts = {}
     fips_facts['fips'] = False
     data = get_file_content('/proc/sys/crypto/fips_enabled')
     if data and data == '1':
         fips_facts['fips'] = True
     return fips_facts
Exemple #4
0
 def collect(self, module=None, collected_facts=None):
     # NOTE: this is populated even if it is not set
     fips_facts = {}
     fips_facts['fips'] = False
     data = get_file_content('/proc/sys/crypto/fips_enabled')
     if data and data == '1':
         fips_facts['fips'] = True
     return fips_facts
Exemple #5
0
    def get_uptime_facts(self):
        uptime_facts = {}
        uptime_file_content = get_file_content('/proc/uptime')
        if uptime_file_content:
            uptime_seconds_string = uptime_file_content.split(' ')[0]
            uptime_facts['uptime_seconds'] = int(float(uptime_seconds_string))

        return uptime_facts
Exemple #6
0
    def get_uptime_facts(self):
        uptime_facts = {}
        uptime_file_content = get_file_content('/proc/uptime')
        if uptime_file_content:
            uptime_seconds_string = uptime_file_content.split(' ')[0]
            uptime_facts['uptime_seconds'] = int(float(uptime_seconds_string))

        return uptime_facts
Exemple #7
0
    def parse_distribution_file_SUSE(self, name, data, path, collected_facts):
        suse_facts = {}
        if 'suse' not in data.lower():
            return False, suse_facts  # TODO: remove if tested without this
        if path == '/etc/os-release':
            for line in data.splitlines():
                distribution = re.search("^NAME=(.*)", line)
                if distribution:
                    suse_facts['distribution'] = distribution.group(1).strip(
                        '"')
                # example pattern are 13.04 13.0 13
                distribution_version = re.search(
                    r'^VERSION_ID="?([0-9]+\.?[0-9]*)"?', line)
                if distribution_version:
                    suse_facts[
                        'distribution_version'] = distribution_version.group(1)
                if 'open' in data.lower():
                    release = re.search(r'^VERSION_ID="?[0-9]+\.?([0-9]*)"?',
                                        line)
                    if release:
                        suse_facts['distribution_release'] = release.groups(
                        )[0]
                elif 'enterprise' in data.lower() and 'VERSION_ID' in line:
                    # SLES doesn't got funny release names
                    release = re.search(r'^VERSION_ID="?[0-9]+\.?([0-9]*)"?',
                                        line)
                    if release.group(1):
                        release = release.group(1)
                    else:
                        release = "0"  # no minor number, so it is the first release
                    suse_facts['distribution_release'] = release
        elif path == '/etc/SuSE-release':
            if 'open' in data.lower():
                data = data.splitlines()
                distdata = get_file_content(path).splitlines()[0]
                suse_facts['distribution'] = distdata.split()[0]
                for line in data:
                    release = re.search('CODENAME *= *([^\n]+)', line)
                    if release:
                        suse_facts['distribution_release'] = release.groups(
                        )[0].strip()
            elif 'enterprise' in data.lower():
                lines = data.splitlines()
                distribution = lines[0].split()[0]
                if "Server" in data:
                    suse_facts['distribution'] = "SLES"
                elif "Desktop" in data:
                    suse_facts['distribution'] = "SLED"
                for line in lines:
                    release = re.search(
                        'PATCHLEVEL = ([0-9]+)',
                        line)  # SLES doesn't got funny release names
                    if release:
                        suse_facts['distribution_release'] = release.group(1)
                        suse_facts['distribution_version'] = collected_facts[
                            'distribution_version'] + '.' + release.group(1)

        return True, suse_facts
Exemple #8
0
    def get_distribution_SunOS(self):
        sunos_facts = {}

        data = get_file_content('/etc/release').splitlines()[0]

        if 'Solaris' in data:
            # for solaris 10 uname_r will contain 5.10, for solaris 11 it will have 5.11
            uname_r = get_uname(self.module, flags=['-r'])
            ora_prefix = ''
            if 'Oracle Solaris' in data:
                data = data.replace('Oracle ', '')
                ora_prefix = 'Oracle '
            sunos_facts['distribution'] = data.split()[0]
            sunos_facts['distribution_version'] = data.split()[1]
            sunos_facts['distribution_release'] = ora_prefix + data
            sunos_facts['distribution_major_version'] = uname_r.split('.')[1].rstrip()
            return sunos_facts

        uname_v = get_uname(self.module, flags=['-v'])
        distribution_version = None

        if 'SmartOS' in data:
            sunos_facts['distribution'] = 'SmartOS'
            if _file_exists('/etc/product'):
                product_data = dict([l.split(': ', 1) for l in get_file_content('/etc/product').splitlines() if ': ' in l])
                if 'Image' in product_data:
                    distribution_version = product_data.get('Image').split()[-1]
        elif 'OpenIndiana' in data:
            sunos_facts['distribution'] = 'OpenIndiana'
        elif 'OmniOS' in data:
            sunos_facts['distribution'] = 'OmniOS'
            distribution_version = data.split()[-1]
        elif uname_v is not None and 'NexentaOS_' in uname_v:
            sunos_facts['distribution'] = 'Nexenta'
            distribution_version = data.split()[-1].lstrip('v')

        if sunos_facts.get('distribution', '') in ('SmartOS', 'OpenIndiana', 'OmniOS', 'Nexenta'):
            sunos_facts['distribution_release'] = data.strip()
            if distribution_version is not None:
                sunos_facts['distribution_version'] = distribution_version
            elif uname_v is not None:
                sunos_facts['distribution_version'] = uname_v.splitlines()[0].strip()
            return sunos_facts

        return sunos_facts
Exemple #9
0
def main():
    module_args = oci_utils.get_taggable_arg_spec(supports_create=True,
                                                  supports_wait=True)
    module_args.update(
        dict(instance_id=dict(type='str', required=False),
             public_key=dict(type='str', required=False),
             instance_console_connection_id=dict(type='str',
                                                 required=False,
                                                 aliases=['id']),
             state=dict(type='str',
                        required=False,
                        default='present',
                        choices=['absent', 'present'])))

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=False,
        mutually_exclusive=['instance_console_connection_id', 'instance_id'],
        required_if=[('state', 'absent', ['instance_console_connection_id']),
                     ('state', 'present', ['instance_id', 'public_key'])])

    if not HAS_OCI_PY_SDK:
        module.fail_json(msg='oci python sdk required for this module.')

    compute_client = oci_utils.create_service_client(module, ComputeClient)

    state = module.params['state']

    if state == 'absent':
        result = delete_instance_console_connection(compute_client, module)

    else:
        # Replace value of `public_key` key by content of file pointed to by the `public_key` param
        module.params["public_key"] = get_file_content(
            module.params['public_key'])

        instance_id = module.params['instance_id']
        kwargs_list = {
            'instance_id':
            instance_id,
            'compartment_id':
            _get_compartment_of_instance(compute_client, instance_id)
        }

        result = oci_utils.check_and_create_resource(
            resource_type='instance_console_connection',
            create_fn=create_instance_console_connection,
            kwargs_create={
                'compute_client': compute_client,
                'module': module
            },
            list_fn=compute_client.list_instance_console_connections,
            kwargs_list=kwargs_list,
            module=module,
            model=CreateInstanceConsoleConnectionDetails(),
            exclude_attributes=None)
    module.exit_json(**result)
    def collect(self, module=None, collected_facts=None):
        local_facts = {}
        local_facts['local'] = {}

        if not module:
            return local_facts

        fact_path = module.params.get('fact_path', None)

        if not fact_path or not os.path.exists(fact_path):
            return local_facts

        local = {}
        for fn in sorted(glob.glob(fact_path + '/*.fact')):
            # where it will sit under local facts
            fact_base = os.path.basename(fn).replace('.fact', '')
            if stat.S_IXUSR & os.stat(fn)[stat.ST_MODE]:
                # run it
                # try to read it as json first
                # if that fails read it with ConfigParser
                # if that fails, skip it
                try:
                    rc, out, err = module.run_command(fn)
                except UnicodeError:
                    fact = 'error loading fact - output of running %s was not utf-8' % fn
                    local[fact_base] = fact
                    local_facts['local'] = local
                    module.warn(fact)
                    return local_facts
            else:
                out = get_file_content(fn, default='')

            # load raw json
            fact = 'loading %s' % fact_base
            try:
                fact = json.loads(out)
            except ValueError:
                # load raw ini
                cp = configparser.ConfigParser()
                try:
                    cp.readfp(StringIO(out))
                except configparser.Error:
                    fact = "error loading fact - please check content"
                    module.warn(fact)
                else:
                    fact = {}
                    for sect in cp.sections():
                        if sect not in fact:
                            fact[sect] = {}
                        for opt in cp.options(sect):
                            val = cp.get(sect, opt)
                            fact[sect][opt] = val

            local[fact_base] = fact

        local_facts['local'] = local
        return local_facts
Exemple #11
0
    def get_permanent_hostname(self):
        if not os.path.isfile(self.FILE):
            return ''

        try:
            return get_file_content(self.FILE, default='', strip=True)
        except Exception as e:
            self.module.fail_json(msg="failed to read hostname: %s" %
                                  to_native(e),
                                  exception=traceback.format_exc())
Exemple #12
0
    def collect(self, module=None, collected_facts=None):
        local_facts = {}
        local_facts['local'] = {}

        if not module:
            return local_facts

        fact_path = module.params.get('fact_path', None)

        if not fact_path or not os.path.exists(fact_path):
            return local_facts

        local = {}
        for fn in sorted(glob.glob(fact_path + '/*.fact')):
            # where it will sit under local facts
            fact_base = os.path.basename(fn).replace('.fact', '')
            if stat.S_IXUSR & os.stat(fn)[stat.ST_MODE]:
                # run it
                # try to read it as json first
                # if that fails read it with ConfigParser
                # if that fails, skip it
                try:
                    rc, out, err = module.run_command(fn)
                except UnicodeError:
                    fact = 'error loading fact - output of running %s was not utf-8' % fn
                    local[fact_base] = fact
                    local_facts['local'] = local
                    return local_facts
            else:
                out = get_file_content(fn, default='')

            # load raw json
            fact = 'loading %s' % fact_base
            try:
                fact = json.loads(out)
            except ValueError:
                # load raw ini
                cp = configparser.ConfigParser()
                try:
                    cp.readfp(StringIO(out))
                except configparser.Error:
                    fact = "error loading fact - please check content"
                else:
                    fact = {}
                    for sect in cp.sections():
                        if sect not in fact:
                            fact[sect] = {}
                        for opt in cp.options(sect):
                            val = cp.get(sect, opt)
                            fact[sect][opt] = val

            local[fact_base] = fact

        local_facts['local'] = local
        return local_facts
Exemple #13
0
 def get_holders(self, block_dev_dict, sysdir):
     block_dev_dict['holders'] = []
     if os.path.isdir(sysdir + "/holders"):
         for folder in os.listdir(sysdir + "/holders"):
             if not folder.startswith("dm-"):
                 continue
             name = get_file_content(sysdir + "/holders/" + folder + "/dm/name")
             if name:
                 block_dev_dict['holders'].append(name)
             else:
                 block_dev_dict['holders'].append(folder)
Exemple #14
0
 def get_holders(self, block_dev_dict, sysdir):
     block_dev_dict['holders'] = []
     if os.path.isdir(sysdir + "/holders"):
         for folder in os.listdir(sysdir + "/holders"):
             if not folder.startswith("dm-"):
                 continue
             name = get_file_content(sysdir + "/holders/" + folder + "/dm/name")
             if name:
                 block_dev_dict['holders'].append(name)
             else:
                 block_dev_dict['holders'].append(folder)
Exemple #15
0
    def parse_distribution_file_SUSE(self, name, data, path, collected_facts):
        suse_facts = {}
        if 'suse' not in data.lower():
            return False, suse_facts  # TODO: remove if tested without this
        if path == '/etc/os-release':
            for line in data.splitlines():
                distribution = re.search("^NAME=(.*)", line)
                if distribution:
                    suse_facts['distribution'] = distribution.group(1).strip('"')
                # example pattern are 13.04 13.0 13
                distribution_version = re.search(r'^VERSION_ID="?([0-9]+\.?[0-9]*)"?', line)
                if distribution_version:
                    suse_facts['distribution_version'] = distribution_version.group(1)
                    suse_facts['distribution_major_version'] = distribution_version.group(1).split('.')[0]
                if 'open' in data.lower():
                    release = re.search(r'^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line)
                    if release:
                        suse_facts['distribution_release'] = release.groups()[0]
                elif 'enterprise' in data.lower() and 'VERSION_ID' in line:
                    # SLES doesn't got funny release names
                    release = re.search(r'^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line)
                    if release.group(1):
                        release = release.group(1)
                    else:
                        release = "0"  # no minor number, so it is the first release
                    suse_facts['distribution_release'] = release
                # Starting with SLES4SAP12 SP3 NAME reports 'SLES' instead of 'SLES_SAP'
                # According to SuSe Support (SR101182877871) we should use the CPE_NAME to detect SLES4SAP
                if re.search("^CPE_NAME=.*sles_sap.*$", line):
                    suse_facts['distribution'] = 'SLES_SAP'
        elif path == '/etc/SuSE-release':
            if 'open' in data.lower():
                data = data.splitlines()
                distdata = get_file_content(path).splitlines()[0]
                suse_facts['distribution'] = distdata.split()[0]
                for line in data:
                    release = re.search('CODENAME *= *([^\n]+)', line)
                    if release:
                        suse_facts['distribution_release'] = release.groups()[0].strip()
            elif 'enterprise' in data.lower():
                lines = data.splitlines()
                distribution = lines[0].split()[0]
                if "Server" in data:
                    suse_facts['distribution'] = "SLES"
                elif "Desktop" in data:
                    suse_facts['distribution'] = "SLED"
                for line in lines:
                    release = re.search('PATCHLEVEL = ([0-9]+)', line)  # SLES doesn't got funny release names
                    if release:
                        suse_facts['distribution_release'] = release.group(1)
                        suse_facts['distribution_version'] = collected_facts['distribution_version'] + '.' + release.group(1)

        return True, suse_facts
Exemple #16
0
    def _mtab_entries(self):
        mtab_file = '/etc/mtab'
        if not os.path.exists(mtab_file):
            mtab_file = '/proc/mounts'

        mtab = get_file_content(mtab_file, '')
        mtab_entries = []
        for line in mtab.splitlines():
            fields = line.split()
            if len(fields) < 4:
                continue
            mtab_entries.append(fields)
        return mtab_entries
Exemple #17
0
    def _mtab_entries(self):
        mtab_file = '/etc/mtab'
        if not os.path.exists(mtab_file):
            mtab_file = '/proc/mounts'

        mtab = get_file_content(mtab_file, '')
        mtab_entries = []
        for line in mtab.splitlines():
            fields = line.split()
            if len(fields) < 4:
                continue
            mtab_entries.append(fields)
        return mtab_entries
Exemple #18
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            test=dict(type='str', default='strip'),
            touch_file=dict(type='str', default='/dev/null'),
            line_sep_file=dict(type='str', default='/dev/null'),
            line_sep_sep=dict(type='str', default='\n'),
        )
    )

    test = module.params['test']
    facts = {}

    if test == 'strip':
        etc_passwd = get_file_content('/etc/passwd')
        etc_passwd_unstripped = get_file_content('/etc/passwd', strip=False)
        facts['etc_passwd_newlines'] = etc_passwd.count('\n')
        facts['etc_passwd_newlines_unstripped'] = etc_passwd_unstripped.count('\n')

    elif test == 'default':
        path = module.params['touch_file']
        facts['touch_default'] = get_file_content(path, default='i am a default')

    elif test == 'line_sep':
        path = module.params['line_sep_file']
        sep = module.params['line_sep_sep']
        facts['line_sep'] = get_file_lines(path, line_sep=sep)

    elif test == 'invalid_mountpoint':
        facts['invalid_mountpoint'] = get_mount_size('/doesnotexist')

    result = {
        'changed': False,
        'ansible_facts': facts,
    }

    module.exit_json(**result)
Exemple #19
0
    def parse_distribution_file_SUSE(self, name, data, path, collected_facts):
        suse_facts = {}
        if 'suse' not in data.lower():
            return False, suse_facts  # TODO: remove if tested without this
        if path == '/etc/os-release':
            for line in data.splitlines():
                distribution = re.search("^NAME=(.*)", line)
                if distribution:
                    suse_facts['distribution'] = distribution.group(1).strip('"')
                # example pattern are 13.04 13.0 13
                distribution_version = re.search('^VERSION_ID="?([0-9]+\.?[0-9]*)"?', line)
                if distribution_version:
                    suse_facts['distribution_version'] = distribution_version.group(1)
                if 'open' in data.lower():
                    release = re.search('^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line)
                    if release:
                        suse_facts['distribution_release'] = release.groups()[0]
                elif 'enterprise' in data.lower() and 'VERSION_ID' in line:
                    # SLES doesn't got funny release names
                    release = re.search('^VERSION_ID="?[0-9]+\.?([0-9]*)"?', line)
                    if release.group(1):
                        release = release.group(1)
                    else:
                        release = "0"  # no minor number, so it is the first release
                    suse_facts['distribution_release'] = release
        elif path == '/etc/SuSE-release':
            if 'open' in data.lower():
                data = data.splitlines()
                distdata = get_file_content(path).splitlines()[0]
                suse_facts['distribution'] = distdata.split()[0]
                for line in data:
                    release = re.search('CODENAME *= *([^\n]+)', line)
                    if release:
                        suse_facts['distribution_release'] = release.groups()[0].strip()
            elif 'enterprise' in data.lower():
                lines = data.splitlines()
                distribution = lines[0].split()[0]
                if "Server" in data:
                    suse_facts['distribution'] = "SLES"
                elif "Desktop" in data:
                    suse_facts['distribution'] = "SLED"
                for line in lines:
                    release = re.search('PATCHLEVEL = ([0-9]+)', line)  # SLES doesn't got funny release names
                    if release:
                        suse_facts['distribution_release'] = release.group(1)
                        suse_facts['distribution_version'] = collected_facts['distribution_version'] + '.' + release.group(1)

        return True, suse_facts
Exemple #20
0
    def get_cpu_facts(self):
        cpu_facts = {}
        cpu_facts['processor'] = []
        rc, out, err = self.module.run_command("/sbin/sysctl -n hw.ncpu")
        cpu_facts['processor_count'] = out.strip()

        dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT)
        if not dmesg_boot:
            rc, dmesg_boot, err = self.module.run_command("/sbin/dmesg")
        for line in dmesg_boot.splitlines():
            if 'CPU:' in line:
                cpu = re.sub(r'CPU:\s+', r"", line)
                cpu_facts['processor'].append(cpu.strip())
            if 'Logical CPUs per core' in line:
                cpu_facts['processor_cores'] = line.split()[4]

        return cpu_facts
Exemple #21
0
    def get_mount_facts(self):
        mount_facts = {}

        mount_facts['mounts'] = []
        fstab = get_file_content('/etc/fstab')
        if fstab:
            for line in fstab.splitlines():
                if line.startswith('#') or line.strip() == '':
                    continue
                fields = re.sub(r'\s+', ' ', line).split()
                mount_statvfs_info = get_mount_size(fields[1])
                mount_info = {'mount': fields[1],
                              'device': fields[0],
                              'fstype': fields[2],
                              'options': fields[3]}
                mount_info.update(mount_statvfs_info)
                mount_facts['mounts'].append(mount_info)

        return mount_facts
Exemple #22
0
    def get_mount_facts(self):
        mount_facts = {}

        mount_facts['mounts'] = []
        fstab = get_file_content('/etc/fstab')
        if fstab:
            for line in fstab.splitlines():
                if line.startswith('#') or line.strip() == '':
                    continue
                fields = re.sub(r'\s+', ' ', line).split()
                mount_statvfs_info = get_mount_size(fields[1])
                mount_info = {'mount': fields[1],
                              'device': fields[0],
                              'fstype': fields[2],
                              'options': fields[3]}
                mount_info.update(mount_statvfs_info)
                mount_facts['mounts'].append(mount_info)

        return mount_facts
Exemple #23
0
 def set_permanent_hostname(self, name):
     try:
         lines = []
         found = False
         content = get_file_content(self.NETWORK_FILE, strip=False) or ""
         for line in content.splitlines(True):
             line = to_native(line)
             if line.strip().startswith('HOSTNAME'):
                 lines.append("HOSTNAME=%s\n" % name)
                 found = True
             else:
                 lines.append(line)
         if not found:
             lines.append("HOSTNAME=%s\n" % name)
         with open(self.NETWORK_FILE, 'w+') as f:
             f.writelines(lines)
     except Exception as e:
         self.module.fail_json(
             msg="failed to update hostname: %s" % to_native(e),
             exception=traceback.format_exc())
    def collect(self, module=None, collected_facts=None):
        dns_facts = {}

        # TODO: flatten
        dns_facts['dns'] = {}

        for line in get_file_content('/etc/resolv.conf', '').splitlines():
            if line.startswith('#') or line.startswith(
                    ';') or line.strip() == '':
                continue
            tokens = line.split()
            if len(tokens) == 0:
                continue
            if tokens[0] == 'nameserver':
                if 'nameservers' not in dns_facts['dns']:
                    dns_facts['dns']['nameservers'] = []
                for nameserver in tokens[1:]:
                    dns_facts['dns']['nameservers'].append(nameserver)
            elif tokens[0] == 'domain':
                if len(tokens) > 1:
                    dns_facts['dns']['domain'] = tokens[1]
            elif tokens[0] == 'search':
                dns_facts['dns']['search'] = []
                for suffix in tokens[1:]:
                    dns_facts['dns']['search'].append(suffix)
            elif tokens[0] == 'sortlist':
                dns_facts['dns']['sortlist'] = []
                for address in tokens[1:]:
                    dns_facts['dns']['sortlist'].append(address)
            elif tokens[0] == 'options':
                dns_facts['dns']['options'] = {}
                if len(tokens) > 1:
                    for option in tokens[1:]:
                        option_tokens = option.split(':', 1)
                        if len(option_tokens) == 0:
                            continue
                        val = len(
                            option_tokens) == 2 and option_tokens[1] or True
                        dns_facts['dns']['options'][option_tokens[0]] = val

        return dns_facts
Exemple #25
0
    def collect(self, module=None, collected_facts=None):
        """
        Example of contents of /etc/iscsi/initiatorname.iscsi:

        ## DO NOT EDIT OR REMOVE THIS FILE!
        ## If you remove this file, the iSCSI daemon will not start.
        ## If you change the InitiatorName, existing access control lists
        ## may reject this initiator.  The InitiatorName must be unique
        ## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames.
        InitiatorName=iqn.1993-08.org.debian:01:44a42c8ddb8b

        Example of output from the AIX lsattr command:

        # lsattr -E -l iscsi0
        disc_filename  /etc/iscsi/targets            Configuration file                            False
        disc_policy    file                          Discovery Policy                              True
        initiator_name iqn.localhost.hostid.7f000001 iSCSI Initiator Name                          True
        isns_srvnames  auto                          iSNS Servers IP Addresses                     True
        isns_srvports                                iSNS Servers Port Numbers                     True
        max_targets    16                            Maximum Targets Allowed                       True
        num_cmd_elems  200                           Maximum number of commands to queue to driver True
        """

        iscsi_facts = ""
        iscsi_facts['iscsi_iqn'] = ""
        if sys.platform.startswith('linux') or sys.platform.startswith(
                'sunos'):
            for line in get_file_content('/etc/iscsi/initiatorname.iscsi',
                                         '').splitlines():
                if line.startswith('#') or line.startswith(
                        ';') or line.strip() == '':
                    continue
                if line.startswith('InitiatorName='):
                    iscsi_facts['iscsi_iqn'] = line.split('=', 1)[1]
                    break
        elif sys.platform.startswith('aix'):
            aixcmd = '/usr/sbin/lsattr -E -l iscsi0 | grep initiator_name'
            aixret = subprocess.check_output(aixcmd, shell=True)
            if aixret[0].isalpha():
                iscsi_facts['iscsi_iqn'] = aixret.split()[1].rstrip()
        return iscsi_facts
Exemple #26
0
    def collect(self, module=None, collected_facts=None):
        cmdline_facts = {}

        data = get_file_content('/proc/cmdline')

        if not data:
            return cmdline_facts

        cmdline_facts['cmdline'] = {}

        try:
            for piece in shlex.split(data):
                item = piece.split('=', 1)
                if len(item) == 1:
                    cmdline_facts['cmdline'][item[0]] = True
                else:
                    cmdline_facts['cmdline'][item[0]] = item[1]
        except ValueError:
            pass

        return cmdline_facts
Exemple #27
0
def create_certificates(certificate_details_dict):
    if certificate_details_dict is None:
        return None
    result_certificates = dict()
    attributes = ['ca_certificate', 'private_key', 'public_certificate']
    for key, value in six.iteritems(certificate_details_dict):
        certificate_details = CertificateDetails()
        certificate_name = value.get('certificate_name')
        if certificate_name is None:
            raise ClientError(
                Exception(
                    "certificate_name is mandatory and must not be empty for certificate creation"
                ))
        certificate_details.certificate_name = certificate_name
        certificate_details.passphrase = value.get('passphrase', None)
        for attribute in attributes:
            if value.get(attribute) is not None:
                certificate_details.__setattr__(
                    attribute, get_file_content(value.get(attribute, None)))
        result_certificates.update({key: certificate_details})
    return result_certificates
Exemple #28
0
    def get_mount_facts(self):
        mount_facts = {}

        mount_facts['mounts'] = []
        fstab = get_file_content('/etc/fstab')
        if fstab:
            for line in fstab.splitlines():
                if line.startswith('#') or line.strip() == '':
                    continue
                fields = re.sub(r'\s+', ' ', line).split()
                size_total, size_available = get_mount_size(fields[1])
                mount_facts['mounts'].append({
                    'mount': fields[1],
                    'device': fields[0],
                    'fstype': fields[2],
                    'options': fields[3],
                    'size_total': size_total,
                    'size_available': size_available
                })

        return mount_facts
Exemple #29
0
    def collect(self, module=None, collected_facts=None):
        ssh_pub_key_facts = {}
        keytypes = ('dsa', 'rsa', 'ecdsa', 'ed25519')

        # list of directories to check for ssh keys
        # used in the order listed here, the first one with keys is used
        keydirs = ['/etc/ssh', '/etc/openssh', '/etc']

        for keydir in keydirs:
            for type_ in keytypes:
                factname = 'ssh_host_key_%s_public' % type_
                if factname in ssh_pub_key_facts:
                    # a previous keydir was already successful, stop looking
                    # for keys
                    return ssh_pub_key_facts
                key_filename = '%s/ssh_host_%s_key.pub' % (keydir, type_)
                keydata = get_file_content(key_filename)
                if keydata is not None:
                    ssh_pub_key_facts[factname] = keydata.split()[1]

        return ssh_pub_key_facts
    def get_mount_facts(self):
        mount_facts = {}
        mount_facts['mounts'] = []

        # For a detailed format description see mnttab(4)
        #   special mount_point fstype options time
        fstab = get_file_content('/etc/mnttab')

        if fstab:
            for line in fstab.splitlines():
                fields = line.split('\t')
                mount_statvfs_info = get_mount_size(fields[1])
                mount_info = {'mount': fields[1],
                              'device': fields[0],
                              'fstype': fields[2],
                              'options': fields[3],
                              'time': fields[4]}
                mount_info.update(mount_statvfs_info)
                mount_facts['mounts'].append(mount_info)

        return mount_facts
Exemple #31
0
    def collect(self, module=None, collected_facts=None):
        dns_facts = {}

        # TODO: flatten
        dns_facts['dns'] = {}

        for line in get_file_content('/etc/resolv.conf', '').splitlines():
            if line.startswith('#') or line.startswith(';') or line.strip() == '':
                continue
            tokens = line.split()
            if len(tokens) == 0:
                continue
            if tokens[0] == 'nameserver':
                if 'nameservers' not in dns_facts['dns']:
                    dns_facts['dns']['nameservers'] = []
                for nameserver in tokens[1:]:
                    dns_facts['dns']['nameservers'].append(nameserver)
            elif tokens[0] == 'domain':
                if len(tokens) > 1:
                    dns_facts['dns']['domain'] = tokens[1]
            elif tokens[0] == 'search':
                dns_facts['dns']['search'] = []
                for suffix in tokens[1:]:
                    dns_facts['dns']['search'].append(suffix)
            elif tokens[0] == 'sortlist':
                dns_facts['dns']['sortlist'] = []
                for address in tokens[1:]:
                    dns_facts['dns']['sortlist'].append(address)
            elif tokens[0] == 'options':
                dns_facts['dns']['options'] = {}
                if len(tokens) > 1:
                    for option in tokens[1:]:
                        option_tokens = option.split(':', 1)
                        if len(option_tokens) == 0:
                            continue
                        val = len(option_tokens) == 2 and option_tokens[1] or True
                        dns_facts['dns']['options'][option_tokens[0]] = val

        return dns_facts
Exemple #32
0
    def collect(self, module=None, collected_facts=None):
        """
        Example of contents of /etc/iscsi/initiatorname.iscsi:

        ## DO NOT EDIT OR REMOVE THIS FILE!
        ## If you remove this file, the iSCSI daemon will not start.
        ## If you change the InitiatorName, existing access control lists
        ## may reject this initiator.  The InitiatorName must be unique
        ## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames.
        InitiatorName=iqn.1993-08.org.debian:01:44a42c8ddb8b

        Example of output from the AIX lsattr command:

        # lsattr -E -l iscsi0
        disc_filename  /etc/iscsi/targets            Configuration file                            False
        disc_policy    file                          Discovery Policy                              True
        initiator_name iqn.localhost.hostid.7f000001 iSCSI Initiator Name                          True
        isns_srvnames  auto                          iSNS Servers IP Addresses                     True
        isns_srvports                                iSNS Servers Port Numbers                     True
        max_targets    16                            Maximum Targets Allowed                       True
        num_cmd_elems  200                           Maximum number of commands to queue to driver True
        """

        iscsi_facts = {}
        iscsi_facts['iscsi_iqn'] = ""
        if sys.platform.startswith('linux') or sys.platform.startswith('sunos'):
            for line in get_file_content('/etc/iscsi/initiatorname.iscsi', '').splitlines():
                if line.startswith('#') or line.startswith(';') or line.strip() == '':
                    continue
                if line.startswith('InitiatorName='):
                    iscsi_facts['iscsi_iqn'] = line.split('=', 1)[1]
                    break
        elif sys.platform.startswith('aix'):
            aixcmd = '/usr/sbin/lsattr -E -l iscsi0 | grep initiator_name'
            aixret = subprocess.check_output(aixcmd, shell=True)
            if aixret[0].isalpha():
                iscsi_facts['iscsi_iqn'] = aixret.split()[1].rstrip()
        return iscsi_facts
Exemple #33
0
    def get_cpu_facts(self):
        cpu_facts = {}
        cpu_facts['processor'] = []
        sysctl = self.module.get_bin_path('sysctl')
        if sysctl:
            rc, out, err = self.module.run_command("%s -n hw.ncpu" % sysctl, check_rc=False)
            cpu_facts['processor_count'] = out.strip()

        dmesg_boot = get_file_content(FreeBSDHardware.DMESG_BOOT)
        if not dmesg_boot:
            try:
                rc, dmesg_boot, err = self.module.run_command(self.module.get_bin_path("dmesg"), check_rc=False)
            except Exception:
                dmesg_boot = ''

        for line in dmesg_boot.splitlines():
            if 'CPU:' in line:
                cpu = re.sub(r'CPU:\s+', r"", line)
                cpu_facts['processor'].append(cpu.strip())
            if 'Logical CPUs per core' in line:
                cpu_facts['processor_cores'] = line.split()[4]

        return cpu_facts
Exemple #34
0
    def get_mount_facts(self):
        mount_facts = {}
        mount_facts['mounts'] = []

        # For a detailed format description see mnttab(4)
        #   special mount_point fstype options time
        fstab = get_file_content('/etc/mnttab')

        if fstab:
            for line in fstab.splitlines():
                fields = line.split('\t')
                size_total, size_available = get_mount_size(fields[1])
                mount_facts['mounts'].append({
                    'mount': fields[1],
                    'device': fields[0],
                    'fstype': fields[2],
                    'options': fields[3],
                    'time': fields[4],
                    'size_total': size_total,
                    'size_available': size_available
                })

        return mount_facts
    def get_virtual_facts(self):
        virtual_facts = {}

        # Set empty values as default
        virtual_facts['virtualization_type'] = ''
        virtual_facts['virtualization_role'] = ''

        virtual_product_facts = self.detect_virt_product('hw.product')
        virtual_facts.update(virtual_product_facts)

        if virtual_facts['virtualization_type'] == '':
            virtual_vendor_facts = self.detect_virt_vendor('hw.vendor')
            virtual_facts.update(virtual_vendor_facts)

        # Check the dmesg if vmm(4) attached, indicating the host is
        # capable of virtualization.
        dmesg_boot = get_file_content(OpenBSDVirtual.DMESG_BOOT)
        for line in dmesg_boot.splitlines():
            match = re.match('^vmm0 at mainbus0: (SVM/RVI|VMX/EPT)$', line)
            if match:
                virtual_facts['virtualization_type'] = 'vmm'
                virtual_facts['virtualization_role'] = 'host'

        return virtual_facts
Exemple #36
0
    def collect(self, module=None, collected_facts=None):
        facts_dict = {}

        if not module:
            return facts_dict

        collected_facts = collected_facts or {}
        service_mgr_name = None

        # TODO: detect more custom init setups like bootscripts, dmd, s6, Epoch, etc
        # also other OSs other than linux might need to check across several possible candidates

        # Mapping of proc_1 values to more useful names
        proc_1_map = {
            'procd': 'openwrt_init',
            'runit-init': 'runit',
            'svscan': 'svc',
            'openrc-init': 'openrc',
        }

        # try various forms of querying pid 1
        proc_1 = get_file_content('/proc/1/comm')
        if proc_1 is None:
            # FIXME: return code isnt checked
            # FIXME: if stdout is empty string, odd things
            # FIXME: other code seems to think we could get proc_1 == None past this point
            rc, proc_1, err = module.run_command("ps -p 1 -o comm|tail -n 1", use_unsafe_shell=True)
            # If the output of the command starts with what looks like a PID, then the 'ps' command
            # probably didn't work the way we wanted, probably because it's busybox
            if re.match(r' *[0-9]+ ', proc_1):
                proc_1 = None

        # The ps command above may return "COMMAND" if the user cannot read /proc, e.g. with grsecurity
        if proc_1 == "COMMAND\n":
            proc_1 = None

        # FIXME: empty string proc_1 staus empty string
        if proc_1 is not None:
            proc_1 = os.path.basename(proc_1)
            proc_1 = to_native(proc_1)
            proc_1 = proc_1.strip()

        if proc_1 is not None and (proc_1 == 'init' or proc_1.endswith('sh')):
            # many systems return init, so this cannot be trusted, if it ends in 'sh' it probalby is a shell in a container
            proc_1 = None

        # if not init/None it should be an identifiable or custom init, so we are done!
        if proc_1 is not None:
            # Lookup proc_1 value in map and use proc_1 value itself if no match
            # FIXME: empty string still falls through
            service_mgr_name = proc_1_map.get(proc_1, proc_1)

        # FIXME: replace with a system->service_mgr_name map?
        # start with the easy ones
        elif collected_facts.get('distribution', None) == 'MacOSX':
            # FIXME: find way to query executable, version matching is not ideal
            if LooseVersion(platform.mac_ver()[0]) >= LooseVersion('10.4'):
                service_mgr_name = 'launchd'
            else:
                service_mgr_name = 'systemstarter'
        elif 'BSD' in collected_facts.get('system', '') or collected_facts.get('system') in ['Bitrig', 'DragonFly']:
            # FIXME: we might want to break out to individual BSDs or 'rc'
            service_mgr_name = 'bsdinit'
        elif collected_facts.get('system') == 'AIX':
            service_mgr_name = 'src'
        elif collected_facts.get('system') == 'SunOS':
            service_mgr_name = 'smf'
        elif collected_facts.get('distribution') == 'OpenWrt':
            service_mgr_name = 'openwrt_init'
        elif collected_facts.get('system') == 'Linux':
            # FIXME: mv is_systemd_managed
            if self.is_systemd_managed(module=module):
                service_mgr_name = 'systemd'
            elif module.get_bin_path('initctl') and os.path.exists("/etc/init/"):
                service_mgr_name = 'upstart'
            elif os.path.exists('/sbin/openrc'):
                service_mgr_name = 'openrc'
            elif os.path.exists('/etc/init.d/'):
                service_mgr_name = 'sysvinit'

        if not service_mgr_name:
            # if we cannot detect, fallback to generic 'service'
            service_mgr_name = 'service'

        facts_dict['service_mgr'] = service_mgr_name
        return facts_dict
Exemple #37
0
    def get_device_facts(self):
        device_facts = {}

        device_facts['devices'] = {}
        lspci = self.module.get_bin_path('lspci')
        if lspci:
            rc, pcidata, err = self.module.run_command(
                [lspci, '-D'], errors='surrogate_then_replace')
        else:
            pcidata = None

        try:
            block_devs = os.listdir("/sys/block")
        except OSError:
            return device_facts

        devs_wwn = {}
        try:
            devs_by_id = os.listdir("/dev/disk/by-id")
        except OSError:
            pass
        else:
            for link_name in devs_by_id:
                if link_name.startswith("wwn-"):
                    try:
                        wwn_link = os.readlink(
                            os.path.join("/dev/disk/by-id", link_name))
                    except OSError:
                        continue
                    devs_wwn[os.path.basename(wwn_link)] = link_name[4:]

        links = self.get_all_device_links()
        device_facts['device_links'] = links

        for block in block_devs:
            virtual = 1
            sysfs_no_links = 0
            try:
                path = os.readlink(os.path.join("/sys/block/", block))
            except OSError:
                e = sys.exc_info()[1]
                if e.errno == errno.EINVAL:
                    path = block
                    sysfs_no_links = 1
                else:
                    continue
            sysdir = os.path.join("/sys/block", path)
            if sysfs_no_links == 1:
                for folder in os.listdir(sysdir):
                    if "device" in folder:
                        virtual = 0
                        break
            d = {}
            d['virtual'] = virtual
            d['links'] = {}
            for (link_type, link_values) in iteritems(links):
                d['links'][link_type] = link_values.get(block, [])
            diskname = os.path.basename(sysdir)
            for key in ['vendor', 'model', 'sas_address', 'sas_device_handle']:
                d[key] = get_file_content(sysdir + "/device/" + key)

            sg_inq = self.module.get_bin_path('sg_inq')

            if sg_inq:
                device = "/dev/%s" % (block)
                rc, drivedata, err = self.module.run_command([sg_inq, device])
                if rc == 0:
                    serial = re.search(r"Unit serial number:\s+(\w+)",
                                       drivedata)
                    if serial:
                        d['serial'] = serial.group(1)

            for key in ['vendor', 'model']:
                d[key] = get_file_content(sysdir + "/device/" + key)

            for key, test in [
                ('removable', '/removable'),
                ('support_discard', '/queue/discard_granularity'),
            ]:
                d[key] = get_file_content(sysdir + test)

            if diskname in devs_wwn:
                d['wwn'] = devs_wwn[diskname]

            d['partitions'] = {}
            for folder in os.listdir(sysdir):
                m = re.search("(" + diskname + r"[p]*\d+)", folder)
                if m:
                    part = {}
                    partname = m.group(1)
                    part_sysdir = sysdir + "/" + partname

                    part['links'] = {}
                    for (link_type, link_values) in iteritems(links):
                        part['links'][link_type] = link_values.get(
                            partname, [])

                    part['start'] = get_file_content(part_sysdir + "/start", 0)
                    part['sectors'] = get_file_content(part_sysdir + "/size",
                                                       0)

                    part['sectorsize'] = get_file_content(
                        part_sysdir + "/queue/logical_block_size")
                    if not part['sectorsize']:
                        part['sectorsize'] = get_file_content(
                            part_sysdir + "/queue/hw_sector_size", 512)
                    part['size'] = bytes_to_human(
                        (float(part['sectors']) * 512.0))
                    part['uuid'] = get_partition_uuid(partname)
                    self.get_holders(part, part_sysdir)

                    d['partitions'][partname] = part

            d['rotational'] = get_file_content(sysdir + "/queue/rotational")
            d['scheduler_mode'] = ""
            scheduler = get_file_content(sysdir + "/queue/scheduler")
            if scheduler is not None:
                m = re.match(r".*?(\[(.*)\])", scheduler)
                if m:
                    d['scheduler_mode'] = m.group(2)

            d['sectors'] = get_file_content(sysdir + "/size")
            if not d['sectors']:
                d['sectors'] = 0
            d['sectorsize'] = get_file_content(sysdir +
                                               "/queue/logical_block_size")
            if not d['sectorsize']:
                d['sectorsize'] = get_file_content(
                    sysdir + "/queue/hw_sector_size", 512)
            d['size'] = bytes_to_human(float(d['sectors']) * 512.0)

            d['host'] = ""

            # domains are numbered (0 to ffff), bus (0 to ff), slot (0 to 1f), and function (0 to 7).
            m = re.match(r".+/([a-f0-9]{4}:[a-f0-9]{2}:[0|1][a-f0-9]\.[0-7])/",
                         sysdir)
            if m and pcidata:
                pciid = m.group(1)
                did = re.escape(pciid)
                m = re.search("^" + did + r"\s(.*)$", pcidata, re.MULTILINE)
                if m:
                    d['host'] = m.group(1)

            self.get_holders(d, sysdir)

            device_facts['devices'][diskname] = d

        return device_facts
Exemple #38
0
    def get_dmi_facts(self):
        ''' learn dmi facts from system

        Try /sys first for dmi related facts.
        If that is not available, fall back to dmidecode executable '''

        dmi_facts = {}

        if os.path.exists('/sys/devices/virtual/dmi/id/product_name'):
            # Use kernel DMI info, if available

            # DMI SPEC -- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
            FORM_FACTOR = [
                "Unknown", "Other", "Unknown", "Desktop",
                "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower",
                "Portable", "Laptop", "Notebook", "Hand Held",
                "Docking Station", "All In One", "Sub Notebook",
                "Space-saving", "Lunch Box", "Main Server Chassis",
                "Expansion Chassis", "Sub Chassis", "Bus Expansion Chassis",
                "Peripheral Chassis", "RAID Chassis", "Rack Mount Chassis",
                "Sealed-case PC", "Multi-system", "CompactPCI", "AdvancedTCA",
                "Blade"
            ]

            DMI_DICT = {
                'bios_date': '/sys/devices/virtual/dmi/id/bios_date',
                'bios_version': '/sys/devices/virtual/dmi/id/bios_version',
                'form_factor': '/sys/devices/virtual/dmi/id/chassis_type',
                'product_name': '/sys/devices/virtual/dmi/id/product_name',
                'product_serial': '/sys/devices/virtual/dmi/id/product_serial',
                'product_uuid': '/sys/devices/virtual/dmi/id/product_uuid',
                'product_version':
                '/sys/devices/virtual/dmi/id/product_version',
                'system_vendor': '/sys/devices/virtual/dmi/id/sys_vendor'
            }

            for (key, path) in DMI_DICT.items():
                data = get_file_content(path)
                if data is not None:
                    if key == 'form_factor':
                        try:
                            dmi_facts['form_factor'] = FORM_FACTOR[int(data)]
                        except IndexError:
                            dmi_facts['form_factor'] = 'unknown (%s)' % data
                    else:
                        dmi_facts[key] = data
                else:
                    dmi_facts[key] = 'NA'

        else:
            # Fall back to using dmidecode, if available
            dmi_bin = self.module.get_bin_path('dmidecode')
            DMI_DICT = {
                'bios_date': 'bios-release-date',
                'bios_version': 'bios-version',
                'form_factor': 'chassis-type',
                'product_name': 'system-product-name',
                'product_serial': 'system-serial-number',
                'product_uuid': 'system-uuid',
                'product_version': 'system-version',
                'system_vendor': 'system-manufacturer'
            }
            for (k, v) in DMI_DICT.items():
                if dmi_bin is not None:
                    (rc, out,
                     err) = self.module.run_command('%s -s %s' % (dmi_bin, v))
                    if rc == 0:
                        # Strip out commented lines (specific dmidecode output)
                        thisvalue = ''.join([
                            line for line in out.splitlines()
                            if not line.startswith('#')
                        ])
                        try:
                            json.dumps(thisvalue)
                        except UnicodeDecodeError:
                            thisvalue = "NA"

                        dmi_facts[k] = thisvalue
                    else:
                        dmi_facts[k] = 'NA'
                else:
                    dmi_facts[k] = 'NA'

        return dmi_facts
Exemple #39
0
 def _get_file_content(self, path):
     return get_file_content(path)
Exemple #40
0
 def _get_proc_cmdline(self):
     return get_file_content('/proc/cmdline')
Exemple #41
0
 def _get_file_content(self, path):
     return get_file_content(path)
Exemple #42
0
    def collect(self, module=None, collected_facts=None):
        facts_dict = {}

        if not module:
            return facts_dict

        collected_facts = collected_facts or {}
        service_mgr_name = None

        # TODO: detect more custom init setups like bootscripts, dmd, s6, Epoch, etc
        # also other OSs other than linux might need to check across several possible candidates

        # Mapping of proc_1 values to more useful names
        proc_1_map = {
            'procd': 'openwrt_init',
            'runit-init': 'runit',
            'svscan': 'svc',
            'openrc-init': 'openrc',
        }

        # try various forms of querying pid 1
        proc_1 = get_file_content('/proc/1/comm')
        if proc_1 is None:
            # FIXME: return code isnt checked
            # FIXME: if stdout is empty string, odd things
            # FIXME: other code seems to think we could get proc_1 == None past this point
            rc, proc_1, err = module.run_command("ps -p 1 -o comm|tail -n 1",
                                                 use_unsafe_shell=True)
            # If the output of the command starts with what looks like a PID, then the 'ps' command
            # probably didn't work the way we wanted, probably because it's busybox
            if re.match(r' *[0-9]+ ', proc_1):
                proc_1 = None

        # The ps command above may return "COMMAND" if the user cannot read /proc, e.g. with grsecurity
        if proc_1 == "COMMAND\n":
            proc_1 = None

        # FIXME: empty string proc_1 staus empty string
        if proc_1 is not None:
            proc_1 = os.path.basename(proc_1)
            proc_1 = to_native(proc_1)
            proc_1 = proc_1.strip()

        if proc_1 is not None and (proc_1 == 'init' or proc_1.endswith('sh')):
            # many systems return init, so this cannot be trusted, if it ends in 'sh' it probalby is a shell in a container
            proc_1 = None

        # if not init/None it should be an identifiable or custom init, so we are done!
        if proc_1 is not None:
            # Lookup proc_1 value in map and use proc_1 value itself if no match
            # FIXME: empty string still falls through
            service_mgr_name = proc_1_map.get(proc_1, proc_1)

        # FIXME: replace with a system->service_mgr_name map?
        # start with the easy ones
        elif collected_facts.get('ansible_distribution', None) == 'MacOSX':
            # FIXME: find way to query executable, version matching is not ideal
            if LooseVersion(platform.mac_ver()[0]) >= LooseVersion('10.4'):
                service_mgr_name = 'launchd'
            else:
                service_mgr_name = 'systemstarter'
        elif 'BSD' in collected_facts.get(
                'ansible_system',
                '') or collected_facts.get('ansible_system') in [
                    'Bitrig', 'DragonFly'
                ]:
            # FIXME: we might want to break out to individual BSDs or 'rc'
            service_mgr_name = 'bsdinit'
        elif collected_facts.get('ansible_system') == 'AIX':
            service_mgr_name = 'src'
        elif collected_facts.get('ansible_system') == 'SunOS':
            service_mgr_name = 'smf'
        elif collected_facts.get('ansible_distribution') == 'OpenWrt':
            service_mgr_name = 'openwrt_init'
        elif collected_facts.get('ansible_system') == 'Linux':
            # FIXME: mv is_systemd_managed
            if self.is_systemd_managed(module=module):
                service_mgr_name = 'systemd'
            elif module.get_bin_path('initctl') and os.path.exists(
                    "/etc/init/"):
                service_mgr_name = 'upstart'
            elif os.path.exists('/sbin/openrc'):
                service_mgr_name = 'openrc'
            elif self.is_systemd_managed_offline(module=module):
                service_mgr_name = 'systemd'
            elif os.path.exists('/etc/init.d/'):
                service_mgr_name = 'sysvinit'

        if not service_mgr_name:
            # if we cannot detect, fallback to generic 'service'
            service_mgr_name = 'service'

        facts_dict['service_mgr'] = service_mgr_name
        return facts_dict
Exemple #43
0
    def get_virtual_facts(self):
        virtual_facts = {}

        # We want to maintain compatibility with the old "virtualization_type"
        # and "virtualization_role" entries, so we need to track if we found
        # them. We won't return them until the end, but if we found them early,
        # we should avoid updating them again.
        found_virt = False

        # But as we go along, we also want to track virt tech the new way.
        host_tech = set()
        guest_tech = set()

        # lxc/docker
        if os.path.exists('/proc/1/cgroup'):
            for line in get_file_lines('/proc/1/cgroup'):
                if re.search(r'/docker(/|-[0-9a-f]+\.scope)', line):
                    guest_tech.add('docker')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'docker'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True
                if re.search('/lxc/', line) or re.search('/machine.slice/machine-lxc', line):
                    guest_tech.add('lxc')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'lxc'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True
                if re.search('/system.slice/containerd.service', line):
                    guest_tech.add('containerd')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'containerd'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True

        # lxc does not always appear in cgroups anymore but sets 'container=lxc' environment var, requires root privs
        if os.path.exists('/proc/1/environ'):
            for line in get_file_lines('/proc/1/environ', line_sep='\x00'):
                if re.search('container=lxc', line):
                    guest_tech.add('lxc')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'lxc'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True
                if re.search('container=podman', line):
                    guest_tech.add('podman')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'podman'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True
                if re.search('^container=.', line):
                    guest_tech.add('container')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'container'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True

        if os.path.exists('/proc/vz') and not os.path.exists('/proc/lve'):
            virtual_facts['virtualization_type'] = 'openvz'
            if os.path.exists('/proc/bc'):
                host_tech.add('openvz')
                if not found_virt:
                    virtual_facts['virtualization_role'] = 'host'
            else:
                guest_tech.add('openvz')
                if not found_virt:
                    virtual_facts['virtualization_role'] = 'guest'
            found_virt = True

        systemd_container = get_file_content('/run/systemd/container')
        if systemd_container:
            guest_tech.add(systemd_container)
            if not found_virt:
                virtual_facts['virtualization_type'] = systemd_container
                virtual_facts['virtualization_role'] = 'guest'
                found_virt = True

        # ensure 'container' guest_tech is appropriately set
        if guest_tech.intersection(set(['docker', 'lxc', 'podman', 'openvz', 'containerd'])) or systemd_container:
            guest_tech.add('container')

        if os.path.exists("/proc/xen"):
            is_xen_host = False
            try:
                for line in get_file_lines('/proc/xen/capabilities'):
                    if "control_d" in line:
                        is_xen_host = True
            except IOError:
                pass

            if is_xen_host:
                host_tech.add('xen')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'xen'
                    virtual_facts['virtualization_role'] = 'host'
            else:
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'xen'
                    virtual_facts['virtualization_role'] = 'guest'
            found_virt = True

        # assume guest for this block
        if not found_virt:
            virtual_facts['virtualization_role'] = 'guest'

        product_name = get_file_content('/sys/devices/virtual/dmi/id/product_name')
        sys_vendor = get_file_content('/sys/devices/virtual/dmi/id/sys_vendor')
        product_family = get_file_content('/sys/devices/virtual/dmi/id/product_family')

        if product_name in ('KVM', 'KVM Server', 'Bochs', 'AHV'):
            guest_tech.add('kvm')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'kvm'
                found_virt = True

        if sys_vendor == 'oVirt':
            guest_tech.add('oVirt')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'oVirt'
                found_virt = True

        if sys_vendor == 'Red Hat':
            if product_family == 'RHV':
                guest_tech.add('RHV')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'RHV'
                    found_virt = True
            elif product_family == 'RHEV Hypervisor':
                guest_tech.add('RHEV')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'RHEV'
                    found_virt = True

        if product_name in ('VMware Virtual Platform', 'VMware7,1'):
            guest_tech.add('VMware')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'VMware'
                found_virt = True

        if product_name in ('OpenStack Compute', 'OpenStack Nova'):
            guest_tech.add('openstack')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'openstack'
                found_virt = True

        bios_vendor = get_file_content('/sys/devices/virtual/dmi/id/bios_vendor')

        if bios_vendor == 'Xen':
            guest_tech.add('xen')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'xen'
                found_virt = True

        if bios_vendor == 'innotek GmbH':
            guest_tech.add('virtualbox')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'virtualbox'
                found_virt = True

        if bios_vendor in ('Amazon EC2', 'DigitalOcean', 'Hetzner'):
            guest_tech.add('kvm')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'kvm'
                found_virt = True

        KVM_SYS_VENDORS = ('QEMU', 'Amazon EC2', 'DigitalOcean', 'Google', 'Scaleway', 'Nutanix')
        if sys_vendor in KVM_SYS_VENDORS:
            guest_tech.add('kvm')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'kvm'
                found_virt = True

        if sys_vendor == 'KubeVirt':
            guest_tech.add('KubeVirt')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'KubeVirt'
                found_virt = True

        # FIXME: This does also match hyperv
        if sys_vendor == 'Microsoft Corporation':
            guest_tech.add('VirtualPC')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'VirtualPC'
                found_virt = True

        if sys_vendor == 'Parallels Software International Inc.':
            guest_tech.add('parallels')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'parallels'
                found_virt = True

        if sys_vendor == 'OpenStack Foundation':
            guest_tech.add('openstack')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'openstack'
                found_virt = True

        # unassume guest
        if not found_virt:
            del virtual_facts['virtualization_role']

        if os.path.exists('/proc/self/status'):
            for line in get_file_lines('/proc/self/status'):
                if re.match(r'^VxID:\s+\d+', line):
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'linux_vserver'
                    if re.match(r'^VxID:\s+0', line):
                        host_tech.add('linux_vserver')
                        if not found_virt:
                            virtual_facts['virtualization_role'] = 'host'
                    else:
                        guest_tech.add('linux_vserver')
                        if not found_virt:
                            virtual_facts['virtualization_role'] = 'guest'
                    found_virt = True

        if os.path.exists('/proc/cpuinfo'):
            for line in get_file_lines('/proc/cpuinfo'):
                if re.match('^model name.*QEMU Virtual CPU', line):
                    guest_tech.add('kvm')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*User Mode Linux', line):
                    guest_tech.add('uml')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^model name.*UML', line):
                    guest_tech.add('uml')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^machine.*CHRP IBM pSeries .emulated by qemu.', line):
                    guest_tech.add('kvm')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*PowerVM Lx86', line):
                    guest_tech.add('powervm_lx86')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'powervm_lx86'
                elif re.match('^vendor_id.*IBM/S390', line):
                    guest_tech.add('PR/SM')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'PR/SM'
                    lscpu = self.module.get_bin_path('lscpu')
                    if lscpu:
                        rc, out, err = self.module.run_command(["lscpu"])
                        if rc == 0:
                            for line in out.splitlines():
                                data = line.split(":", 1)
                                key = data[0].strip()
                                if key == 'Hypervisor':
                                    tech = data[1].strip()
                                    guest_tech.add(tech)
                                    if not found_virt:
                                        virtual_facts['virtualization_type'] = tech
                    else:
                        guest_tech.add('ibm_systemz')
                        if not found_virt:
                            virtual_facts['virtualization_type'] = 'ibm_systemz'
                else:
                    continue
                if virtual_facts['virtualization_type'] == 'PR/SM':
                    if not found_virt:
                        virtual_facts['virtualization_role'] = 'LPAR'
                else:
                    if not found_virt:
                        virtual_facts['virtualization_role'] = 'guest'
                if not found_virt:
                    found_virt = True

        # Beware that we can have both kvm and virtualbox running on a single system
        if os.path.exists("/proc/modules") and os.access('/proc/modules', os.R_OK):
            modules = []
            for line in get_file_lines("/proc/modules"):
                data = line.split(" ", 1)
                modules.append(data[0])

            if 'kvm' in modules:
                host_tech.add('kvm')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'kvm'
                    virtual_facts['virtualization_role'] = 'host'

                if os.path.isdir('/rhev/'):
                    # Check whether this is a RHEV hypervisor (is vdsm running ?)
                    for f in glob.glob('/proc/[0-9]*/comm'):
                        try:
                            with open(f) as virt_fh:
                                comm_content = virt_fh.read().rstrip()

                            if comm_content in ('vdsm', 'vdsmd'):
                                # We add both kvm and RHEV to host_tech in this case.
                                # It's accurate. RHEV uses KVM.
                                host_tech.add('RHEV')
                                if not found_virt:
                                    virtual_facts['virtualization_type'] = 'RHEV'
                                break
                        except Exception:
                            pass

                found_virt = True

            if 'vboxdrv' in modules:
                host_tech.add('virtualbox')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'virtualbox'
                    virtual_facts['virtualization_role'] = 'host'
                    found_virt = True

            if 'virtio' in modules:
                host_tech.add('kvm')
                if not found_virt:
                    virtual_facts['virtualization_type'] = 'kvm'
                    virtual_facts['virtualization_role'] = 'guest'
                    found_virt = True

        # In older Linux Kernel versions, /sys filesystem is not available
        # dmidecode is the safest option to parse virtualization related values
        dmi_bin = self.module.get_bin_path('dmidecode')
        # We still want to continue even if dmidecode is not available
        if dmi_bin is not None:
            (rc, out, err) = self.module.run_command('%s -s system-product-name' % dmi_bin)
            if rc == 0:
                # Strip out commented lines (specific dmidecode output)
                vendor_name = ''.join([line.strip() for line in out.splitlines() if not line.startswith('#')])
                if vendor_name.startswith('VMware'):
                    guest_tech.add('VMware')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'VMware'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True

                if 'BHYVE' in out:
                    guest_tech.add('bhyve')
                    if not found_virt:
                        virtual_facts['virtualization_type'] = 'bhyve'
                        virtual_facts['virtualization_role'] = 'guest'
                        found_virt = True

        if os.path.exists('/dev/kvm'):
            host_tech.add('kvm')
            if not found_virt:
                virtual_facts['virtualization_type'] = 'kvm'
                virtual_facts['virtualization_role'] = 'host'
                found_virt = True

        # If none of the above matches, return 'NA' for virtualization_type
        # and virtualization_role. This allows for proper grouping.
        if not found_virt:
            virtual_facts['virtualization_type'] = 'NA'
            virtual_facts['virtualization_role'] = 'NA'
            found_virt = True

        virtual_facts['virtualization_tech_guest'] = guest_tech
        virtual_facts['virtualization_tech_host'] = host_tech
        return virtual_facts
    def get_interfaces_info(self, ip_path, default_ipv4, default_ipv6):
        interfaces = {}
        ips = dict(
            all_ipv4_addresses=[],
            all_ipv6_addresses=[],
        )

        # FIXME: maybe split into smaller methods?
        # FIXME: this is pretty much a constructor

        for path in glob.glob('/sys/class/net/*'):
            if not os.path.isdir(path):
                continue
            device = os.path.basename(path)
            interfaces[device] = {'device': device}
            if os.path.exists(os.path.join(path, 'address')):
                macaddress = get_file_content(os.path.join(path, 'address'),
                                              default='')
                if macaddress and macaddress != '00:00:00:00:00:00':
                    interfaces[device]['macaddress'] = macaddress
            if os.path.exists(os.path.join(path, 'mtu')):
                interfaces[device]['mtu'] = int(
                    get_file_content(os.path.join(path, 'mtu')))
            if os.path.exists(os.path.join(path, 'operstate')):
                interfaces[device]['active'] = get_file_content(
                    os.path.join(path, 'operstate')) != 'down'
            if os.path.exists(os.path.join(path, 'device', 'driver',
                                           'module')):
                interfaces[device]['module'] = os.path.basename(
                    os.path.realpath(
                        os.path.join(path, 'device', 'driver', 'module')))
            if os.path.exists(os.path.join(path, 'type')):
                _type = get_file_content(os.path.join(path, 'type'))
                interfaces[device]['type'] = self.INTERFACE_TYPE.get(
                    _type, 'unknown')
            if os.path.exists(os.path.join(path, 'bridge')):
                interfaces[device]['type'] = 'bridge'
                interfaces[device]['interfaces'] = [
                    os.path.basename(b)
                    for b in glob.glob(os.path.join(path, 'brif', '*'))
                ]
                if os.path.exists(os.path.join(path, 'bridge', 'bridge_id')):
                    interfaces[device]['id'] = get_file_content(os.path.join(
                        path, 'bridge', 'bridge_id'),
                                                                default='')
                if os.path.exists(os.path.join(path, 'bridge', 'stp_state')):
                    interfaces[device]['stp'] = get_file_content(
                        os.path.join(path, 'bridge', 'stp_state')) == '1'
            if os.path.exists(os.path.join(path, 'bonding')):
                interfaces[device]['type'] = 'bonding'
                interfaces[device]['slaves'] = get_file_content(
                    os.path.join(path, 'bonding',
                                 'slaves'), default='').split()
                interfaces[device]['mode'] = get_file_content(
                    os.path.join(path, 'bonding',
                                 'mode'), default='').split()[0]
                interfaces[device]['miimon'] = get_file_content(
                    os.path.join(path, 'bonding',
                                 'miimon'), default='').split()[0]
                interfaces[device]['lacp_rate'] = get_file_content(
                    os.path.join(path, 'bonding',
                                 'lacp_rate'), default='').split()[0]
                primary = get_file_content(
                    os.path.join(path, 'bonding', 'primary'))
                if primary:
                    interfaces[device]['primary'] = primary
                    path = os.path.join(path, 'bonding', 'all_slaves_active')
                    if os.path.exists(path):
                        interfaces[device][
                            'all_slaves_active'] = get_file_content(
                                path) == '1'
            if os.path.exists(os.path.join(path, 'bonding_slave')):
                interfaces[device]['perm_macaddress'] = get_file_content(
                    os.path.join(path, 'bonding_slave', 'perm_hwaddr'),
                    default='')
            if os.path.exists(os.path.join(path, 'device')):
                interfaces[device]['pciid'] = os.path.basename(
                    os.readlink(os.path.join(path, 'device')))
            if os.path.exists(os.path.join(path, 'speed')):
                speed = get_file_content(os.path.join(path, 'speed'))
                if speed is not None:
                    interfaces[device]['speed'] = int(speed)

            # Check whether an interface is in promiscuous mode
            if os.path.exists(os.path.join(path, 'flags')):
                promisc_mode = False
                # The second byte indicates whether the interface is in promiscuous mode.
                # 1 = promisc
                # 0 = no promisc
                data = int(get_file_content(os.path.join(path, 'flags')), 16)
                promisc_mode = (data & 0x0100 > 0)
                interfaces[device]['promisc'] = promisc_mode

            # TODO: determine if this needs to be in a nested scope/closure
            def parse_ip_output(output, secondary=False):
                for line in output.splitlines():
                    if not line:
                        continue
                    words = line.split()
                    broadcast = ''
                    if words[0] == 'inet':
                        if '/' in words[1]:
                            address, netmask_length = words[1].split('/')
                            if len(words) > 3:
                                broadcast = words[3]
                        else:
                            # pointopoint interfaces do not have a prefix
                            address = words[1]
                            netmask_length = "32"
                        address_bin = struct.unpack(
                            '!L', socket.inet_aton(address))[0]
                        netmask_bin = (1 << 32) - (
                            1 << 32 >> int(netmask_length))
                        netmask = socket.inet_ntoa(
                            struct.pack('!L', netmask_bin))
                        network = socket.inet_ntoa(
                            struct.pack('!L', address_bin & netmask_bin))
                        iface = words[-1]
                        # NOTE: device is ref to outside scope
                        # NOTE: interfaces is also ref to outside scope
                        if iface != device:
                            interfaces[iface] = {}
                        if not secondary and "ipv4" not in interfaces[iface]:
                            interfaces[iface]['ipv4'] = {
                                'address': address,
                                'broadcast': broadcast,
                                'netmask': netmask,
                                'network': network
                            }
                        else:
                            if "ipv4_secondaries" not in interfaces[iface]:
                                interfaces[iface]["ipv4_secondaries"] = []
                            interfaces[iface]["ipv4_secondaries"].append({
                                'address':
                                address,
                                'broadcast':
                                broadcast,
                                'netmask':
                                netmask,
                                'network':
                                network,
                            })

                        # add this secondary IP to the main device
                        if secondary:
                            if "ipv4_secondaries" not in interfaces[device]:
                                interfaces[device]["ipv4_secondaries"] = []
                            if device != iface:
                                interfaces[device]["ipv4_secondaries"].append({
                                    'address':
                                    address,
                                    'broadcast':
                                    broadcast,
                                    'netmask':
                                    netmask,
                                    'network':
                                    network,
                                })

                        # NOTE: default_ipv4 is ref to outside scope
                        # If this is the default address, update default_ipv4
                        if 'address' in default_ipv4 and default_ipv4[
                                'address'] == address:
                            default_ipv4['broadcast'] = broadcast
                            default_ipv4['netmask'] = netmask
                            default_ipv4['network'] = network
                            # NOTE: macaddress is ref from outside scope
                            default_ipv4['macaddress'] = macaddress
                            default_ipv4['mtu'] = interfaces[device]['mtu']
                            default_ipv4['type'] = interfaces[device].get(
                                "type", "unknown")
                            default_ipv4['alias'] = words[-1]
                        if not address.startswith('127.'):
                            ips['all_ipv4_addresses'].append(address)
                    elif words[0] == 'inet6':
                        if 'peer' == words[2]:
                            address = words[1]
                            _, prefix = words[3].split('/')
                            scope = words[5]
                        else:
                            address, prefix = words[1].split('/')
                            scope = words[3]
                        if 'ipv6' not in interfaces[device]:
                            interfaces[device]['ipv6'] = []
                        interfaces[device]['ipv6'].append({
                            'address': address,
                            'prefix': prefix,
                            'scope': scope
                        })
                        # If this is the default address, update default_ipv6
                        if 'address' in default_ipv6 and default_ipv6[
                                'address'] == address:
                            default_ipv6['prefix'] = prefix
                            default_ipv6['scope'] = scope
                            default_ipv6['macaddress'] = macaddress
                            default_ipv6['mtu'] = interfaces[device]['mtu']
                            default_ipv6['type'] = interfaces[device].get(
                                "type", "unknown")
                        if not address == '::1':
                            ips['all_ipv6_addresses'].append(address)

            ip_path = self.module.get_bin_path("ip")

            args = [ip_path, 'addr', 'show', 'primary', device]
            rc, primary_data, stderr = self.module.run_command(
                args, errors='surrogate_then_replace')
            if rc == 0:
                parse_ip_output(primary_data)
            else:
                # possibly busybox, fallback to running without the "primary" arg
                # https://github.com/ansible/ansible/issues/50871
                args = [ip_path, 'addr', 'show', device]
                rc, data, stderr = self.module.run_command(
                    args, errors='surrogate_then_replace')
                if rc == 0:
                    parse_ip_output(data)

            args = [ip_path, 'addr', 'show', 'secondary', device]
            rc, secondary_data, stderr = self.module.run_command(
                args, errors='surrogate_then_replace')
            if rc == 0:
                parse_ip_output(secondary_data, secondary=True)

            interfaces[device].update(self.get_ethtool_data(device))

        # replace : by _ in interface name since they are hard to use in template
        new_interfaces = {}
        # i is a dict key (string) not an index int
        for i in interfaces:
            if ':' in i:
                new_interfaces[i.replace(':', '_')] = interfaces[i]
            else:
                new_interfaces[i] = interfaces[i]
        return new_interfaces, ips
Exemple #45
0
    def get_dmi_facts(self):
        ''' learn dmi facts from system

        Try /sys first for dmi related facts.
        If that is not available, fall back to dmidecode executable '''

        dmi_facts = {}

        if os.path.exists('/sys/devices/virtual/dmi/id/product_name'):
            # Use kernel DMI info, if available

            # DMI SPEC -- http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.0.pdf
            FORM_FACTOR = ["Unknown", "Other", "Unknown", "Desktop",
                           "Low Profile Desktop", "Pizza Box", "Mini Tower", "Tower",
                           "Portable", "Laptop", "Notebook", "Hand Held", "Docking Station",
                           "All In One", "Sub Notebook", "Space-saving", "Lunch Box",
                           "Main Server Chassis", "Expansion Chassis", "Sub Chassis",
                           "Bus Expansion Chassis", "Peripheral Chassis", "RAID Chassis",
                           "Rack Mount Chassis", "Sealed-case PC", "Multi-system",
                           "CompactPCI", "AdvancedTCA", "Blade"]

            DMI_DICT = {
                'bios_date': '/sys/devices/virtual/dmi/id/bios_date',
                'bios_version': '/sys/devices/virtual/dmi/id/bios_version',
                'form_factor': '/sys/devices/virtual/dmi/id/chassis_type',
                'product_name': '/sys/devices/virtual/dmi/id/product_name',
                'product_serial': '/sys/devices/virtual/dmi/id/product_serial',
                'product_uuid': '/sys/devices/virtual/dmi/id/product_uuid',
                'product_version': '/sys/devices/virtual/dmi/id/product_version',
                'system_vendor': '/sys/devices/virtual/dmi/id/sys_vendor'
            }

            for (key, path) in DMI_DICT.items():
                data = get_file_content(path)
                if data is not None:
                    if key == 'form_factor':
                        try:
                            dmi_facts['form_factor'] = FORM_FACTOR[int(data)]
                        except IndexError:
                            dmi_facts['form_factor'] = 'unknown (%s)' % data
                    else:
                        dmi_facts[key] = data
                else:
                    dmi_facts[key] = 'NA'

        else:
            # Fall back to using dmidecode, if available
            dmi_bin = self.module.get_bin_path('dmidecode')
            DMI_DICT = {
                'bios_date': 'bios-release-date',
                'bios_version': 'bios-version',
                'form_factor': 'chassis-type',
                'product_name': 'system-product-name',
                'product_serial': 'system-serial-number',
                'product_uuid': 'system-uuid',
                'product_version': 'system-version',
                'system_vendor': 'system-manufacturer'
            }
            for (k, v) in DMI_DICT.items():
                if dmi_bin is not None:
                    (rc, out, err) = self.module.run_command('%s -s %s' % (dmi_bin, v))
                    if rc == 0:
                        # Strip out commented lines (specific dmidecode output)
                        thisvalue = ''.join([line for line in out.splitlines() if not line.startswith('#')])
                        try:
                            json.dumps(thisvalue)
                        except UnicodeDecodeError:
                            thisvalue = "NA"

                        dmi_facts[k] = thisvalue
                    else:
                        dmi_facts[k] = 'NA'
                else:
                    dmi_facts[k] = 'NA'

        return dmi_facts
Exemple #46
0
    def get_virtual_facts(self):
        virtual_facts = {}
        # lxc/docker
        if os.path.exists('/proc/1/cgroup'):
            for line in get_file_lines('/proc/1/cgroup'):
                if re.search(r'/docker(/|-[0-9a-f]+\.scope)', line):
                    virtual_facts['virtualization_type'] = 'docker'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts
                if re.search('/lxc/', line) or re.search(
                        '/machine.slice/machine-lxc', line):
                    virtual_facts['virtualization_type'] = 'lxc'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        # lxc does not always appear in cgroups anymore but sets 'container=lxc' environment var, requires root privs
        if os.path.exists('/proc/1/environ'):
            for line in get_file_lines('/proc/1/environ', line_sep='\x00'):
                if re.search('container=lxc', line):
                    virtual_facts['virtualization_type'] = 'lxc'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts
                if re.search('container=podman', line):
                    virtual_facts['virtualization_type'] = 'podman'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts
                if re.search('^container=.', line):
                    virtual_facts['virtualization_type'] = 'container'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        if os.path.exists('/proc/vz') and not os.path.exists('/proc/lve'):
            virtual_facts['virtualization_type'] = 'openvz'
            if os.path.exists('/proc/bc'):
                virtual_facts['virtualization_role'] = 'host'
            else:
                virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        systemd_container = get_file_content('/run/systemd/container')
        if systemd_container:
            virtual_facts['virtualization_type'] = systemd_container
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if os.path.exists("/proc/xen"):
            virtual_facts['virtualization_type'] = 'xen'
            virtual_facts['virtualization_role'] = 'guest'
            try:
                for line in get_file_lines('/proc/xen/capabilities'):
                    if "control_d" in line:
                        virtual_facts['virtualization_role'] = 'host'
            except IOError:
                pass
            return virtual_facts

        # assume guest for this block
        virtual_facts['virtualization_role'] = 'guest'

        product_name = get_file_content(
            '/sys/devices/virtual/dmi/id/product_name')

        if product_name in ('KVM', 'KVM Server', 'Bochs', 'AHV'):
            virtual_facts['virtualization_type'] = 'kvm'
            return virtual_facts

        if product_name == 'RHEV Hypervisor':
            virtual_facts['virtualization_type'] = 'RHEV'
            return virtual_facts

        if product_name in ('VMware Virtual Platform', 'VMware7,1'):
            virtual_facts['virtualization_type'] = 'VMware'
            return virtual_facts

        if product_name in ('OpenStack Compute', 'OpenStack Nova'):
            virtual_facts['virtualization_type'] = 'openstack'
            return virtual_facts

        bios_vendor = get_file_content(
            '/sys/devices/virtual/dmi/id/bios_vendor')

        if bios_vendor == 'Xen':
            virtual_facts['virtualization_type'] = 'xen'
            return virtual_facts

        if bios_vendor == 'innotek GmbH':
            virtual_facts['virtualization_type'] = 'virtualbox'
            return virtual_facts

        if bios_vendor in ('Amazon EC2', 'DigitalOcean', 'Hetzner'):
            virtual_facts['virtualization_type'] = 'kvm'
            return virtual_facts

        sys_vendor = get_file_content('/sys/devices/virtual/dmi/id/sys_vendor')

        KVM_SYS_VENDORS = ('QEMU', 'oVirt', 'Amazon EC2', 'DigitalOcean',
                           'Google', 'Scaleway', 'Nutanix')
        if sys_vendor in KVM_SYS_VENDORS:
            virtual_facts['virtualization_type'] = 'kvm'
            return virtual_facts

        # FIXME: This does also match hyperv
        if sys_vendor == 'Microsoft Corporation':
            virtual_facts['virtualization_type'] = 'VirtualPC'
            return virtual_facts

        if sys_vendor == 'Parallels Software International Inc.':
            virtual_facts['virtualization_type'] = 'parallels'
            return virtual_facts

        if sys_vendor == 'OpenStack Foundation':
            virtual_facts['virtualization_type'] = 'openstack'
            return virtual_facts

        # unassume guest
        del virtual_facts['virtualization_role']

        if os.path.exists('/proc/self/status'):
            for line in get_file_lines('/proc/self/status'):
                if re.match(r'^VxID:\s+\d+', line):
                    virtual_facts['virtualization_type'] = 'linux_vserver'
                    if re.match(r'^VxID:\s+0', line):
                        virtual_facts['virtualization_role'] = 'host'
                    else:
                        virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        if os.path.exists('/proc/cpuinfo'):
            for line in get_file_lines('/proc/cpuinfo'):
                if re.match('^model name.*QEMU Virtual CPU', line):
                    virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*User Mode Linux', line):
                    virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^model name.*UML', line):
                    virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^machine.*CHRP IBM pSeries .emulated by qemu.',
                              line):
                    virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*PowerVM Lx86', line):
                    virtual_facts['virtualization_type'] = 'powervm_lx86'
                elif re.match('^vendor_id.*IBM/S390', line):
                    virtual_facts['virtualization_type'] = 'PR/SM'
                    lscpu = self.module.get_bin_path('lscpu')
                    if lscpu:
                        rc, out, err = self.module.run_command(["lscpu"])
                        if rc == 0:
                            for line in out.splitlines():
                                data = line.split(":", 1)
                                key = data[0].strip()
                                if key == 'Hypervisor':
                                    virtual_facts[
                                        'virtualization_type'] = data[1].strip(
                                        )
                    else:
                        virtual_facts['virtualization_type'] = 'ibm_systemz'
                else:
                    continue
                if virtual_facts['virtualization_type'] == 'PR/SM':
                    virtual_facts['virtualization_role'] = 'LPAR'
                else:
                    virtual_facts['virtualization_role'] = 'guest'
                return virtual_facts

        # Beware that we can have both kvm and virtualbox running on a single system
        if os.path.exists("/proc/modules") and os.access(
                '/proc/modules', os.R_OK):
            modules = []
            for line in get_file_lines("/proc/modules"):
                data = line.split(" ", 1)
                modules.append(data[0])

            if 'kvm' in modules:
                virtual_facts['virtualization_type'] = 'kvm'
                virtual_facts['virtualization_role'] = 'host'

                if os.path.isdir('/rhev/'):
                    # Check whether this is a RHEV hypervisor (is vdsm running ?)
                    for f in glob.glob('/proc/[0-9]*/comm'):
                        try:
                            with open(f) as virt_fh:
                                comm_content = virt_fh.read().rstrip()
                            if comm_content in ('vdsm', 'vdsmd'):
                                virtual_facts['virtualization_type'] = 'RHEV'
                                break
                        except Exception:
                            pass

                return virtual_facts

            if 'vboxdrv' in modules:
                virtual_facts['virtualization_type'] = 'virtualbox'
                virtual_facts['virtualization_role'] = 'host'
                return virtual_facts

            if 'virtio' in modules:
                virtual_facts['virtualization_type'] = 'kvm'
                virtual_facts['virtualization_role'] = 'guest'
                return virtual_facts

        # In older Linux Kernel versions, /sys filesystem is not available
        # dmidecode is the safest option to parse virtualization related values
        dmi_bin = self.module.get_bin_path('dmidecode')
        # We still want to continue even if dmidecode is not available
        if dmi_bin is not None:
            (rc, out, err) = self.module.run_command(
                '%s -s system-product-name' % dmi_bin)
            if rc == 0:
                # Strip out commented lines (specific dmidecode output)
                vendor_name = ''.join([
                    line.strip() for line in out.splitlines()
                    if not line.startswith('#')
                ])
                if vendor_name.startswith('VMware'):
                    virtual_facts['virtualization_type'] = 'VMware'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        if os.path.exists('/dev/kvm'):
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'host'
            return virtual_facts

        # If none of the above matches, return 'NA' for virtualization_type
        # and virtualization_role. This allows for proper grouping.
        virtual_facts['virtualization_type'] = 'NA'
        virtual_facts['virtualization_role'] = 'NA'

        return virtual_facts
Exemple #47
0
    def get_device_facts(self):
        device_facts = {}

        device_facts['devices'] = {}
        lspci = self.module.get_bin_path('lspci')
        if lspci:
            rc, pcidata, err = self.module.run_command([lspci, '-D'], errors='surrogate_then_replace')
        else:
            pcidata = None

        try:
            block_devs = os.listdir("/sys/block")
        except OSError:
            return device_facts

        devs_wwn = {}
        try:
            devs_by_id = os.listdir("/dev/disk/by-id")
        except OSError:
            pass
        else:
            for link_name in devs_by_id:
                if link_name.startswith("wwn-"):
                    try:
                        wwn_link = os.readlink(os.path.join("/dev/disk/by-id", link_name))
                    except OSError:
                        continue
                    devs_wwn[os.path.basename(wwn_link)] = link_name[4:]

        links = self.get_all_device_links()
        device_facts['device_links'] = links

        for block in block_devs:
            virtual = 1
            sysfs_no_links = 0
            try:
                path = os.readlink(os.path.join("/sys/block/", block))
            except OSError:
                e = sys.exc_info()[1]
                if e.errno == errno.EINVAL:
                    path = block
                    sysfs_no_links = 1
                else:
                    continue
            sysdir = os.path.join("/sys/block", path)
            if sysfs_no_links == 1:
                for folder in os.listdir(sysdir):
                    if "device" in folder:
                        virtual = 0
                        break
            d = {}
            d['virtual'] = virtual
            d['links'] = {}
            for (link_type, link_values) in iteritems(links):
                d['links'][link_type] = link_values.get(block, [])
            diskname = os.path.basename(sysdir)
            for key in ['vendor', 'model', 'sas_address', 'sas_device_handle']:
                d[key] = get_file_content(sysdir + "/device/" + key)

            sg_inq = self.module.get_bin_path('sg_inq')

            if sg_inq:
                device = "/dev/%s" % (block)
                rc, drivedata, err = self.module.run_command([sg_inq, device])
                if rc == 0:
                    serial = re.search(r"Unit serial number:\s+(\w+)", drivedata)
                    if serial:
                        d['serial'] = serial.group(1)

            for key in ['vendor', 'model']:
                d[key] = get_file_content(sysdir + "/device/" + key)

            for key, test in [('removable', '/removable'),
                              ('support_discard', '/queue/discard_granularity'),
                              ]:
                d[key] = get_file_content(sysdir + test)

            if diskname in devs_wwn:
                d['wwn'] = devs_wwn[diskname]

            d['partitions'] = {}
            for folder in os.listdir(sysdir):
                m = re.search("(" + diskname + r"[p]?\d+)", folder)
                if m:
                    part = {}
                    partname = m.group(1)
                    part_sysdir = sysdir + "/" + partname

                    part['links'] = {}
                    for (link_type, link_values) in iteritems(links):
                        part['links'][link_type] = link_values.get(partname, [])

                    part['start'] = get_file_content(part_sysdir + "/start", 0)
                    part['sectors'] = get_file_content(part_sysdir + "/size", 0)

                    part['sectorsize'] = get_file_content(part_sysdir + "/queue/logical_block_size")
                    if not part['sectorsize']:
                        part['sectorsize'] = get_file_content(part_sysdir + "/queue/hw_sector_size", 512)
                    part['size'] = bytes_to_human((float(part['sectors']) * 512.0))
                    part['uuid'] = get_partition_uuid(partname)
                    self.get_holders(part, part_sysdir)

                    d['partitions'][partname] = part

            d['rotational'] = get_file_content(sysdir + "/queue/rotational")
            d['scheduler_mode'] = ""
            scheduler = get_file_content(sysdir + "/queue/scheduler")
            if scheduler is not None:
                m = re.match(r".*?(\[(.*)\])", scheduler)
                if m:
                    d['scheduler_mode'] = m.group(2)

            d['sectors'] = get_file_content(sysdir + "/size")
            if not d['sectors']:
                d['sectors'] = 0
            d['sectorsize'] = get_file_content(sysdir + "/queue/logical_block_size")
            if not d['sectorsize']:
                d['sectorsize'] = get_file_content(sysdir + "/queue/hw_sector_size", 512)
            d['size'] = bytes_to_human(float(d['sectors']) * 512.0)

            d['host'] = ""

            # domains are numbered (0 to ffff), bus (0 to ff), slot (0 to 1f), and function (0 to 7).
            m = re.match(r".+/([a-f0-9]{4}:[a-f0-9]{2}:[0|1][a-f0-9]\.[0-7])/", sysdir)
            if m and pcidata:
                pciid = m.group(1)
                did = re.escape(pciid)
                m = re.search("^" + did + r"\s(.*)$", pcidata, re.MULTILINE)
                if m:
                    d['host'] = m.group(1)

            self.get_holders(d, sysdir)

            device_facts['devices'][diskname] = d

        return device_facts
Exemple #48
0
    def get_virtual_facts(self):
        virtual_facts = {}
        # lxc/docker
        if os.path.exists('/proc/1/cgroup'):
            for line in get_file_lines('/proc/1/cgroup'):
                if re.search(r'/docker(/|-[0-9a-f]+\.scope)', line):
                    virtual_facts['virtualization_type'] = 'docker'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts
                if re.search('/lxc/', line) or re.search('/machine.slice/machine-lxc', line):
                    virtual_facts['virtualization_type'] = 'lxc'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        # lxc does not always appear in cgroups anymore but sets 'container=lxc' environment var, requires root privs
        if os.path.exists('/proc/1/environ'):
            for line in get_file_lines('/proc/1/environ'):
                if re.search('container=lxc', line):
                    virtual_facts['virtualization_type'] = 'lxc'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        if os.path.exists('/proc/vz') and not os.path.exists('/proc/lve'):
            virtual_facts['virtualization_type'] = 'openvz'
            if os.path.exists('/proc/bc'):
                virtual_facts['virtualization_role'] = 'host'
            else:
                virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        systemd_container = get_file_content('/run/systemd/container')
        if systemd_container:
            virtual_facts['virtualization_type'] = systemd_container
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if os.path.exists("/proc/xen"):
            virtual_facts['virtualization_type'] = 'xen'
            virtual_facts['virtualization_role'] = 'guest'
            try:
                for line in get_file_lines('/proc/xen/capabilities'):
                    if "control_d" in line:
                        virtual_facts['virtualization_role'] = 'host'
            except IOError:
                pass
            return virtual_facts

        product_name = get_file_content('/sys/devices/virtual/dmi/id/product_name')

        if product_name in ['KVM', 'Bochs']:
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if product_name == 'RHEV Hypervisor':
            virtual_facts['virtualization_type'] = 'RHEV'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if product_name in ['VMware Virtual Platform', 'VMware7,1']:
            virtual_facts['virtualization_type'] = 'VMware'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if product_name in ['OpenStack Compute', 'OpenStack Nova']:
            virtual_facts['virtualization_type'] = 'openstack'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        bios_vendor = get_file_content('/sys/devices/virtual/dmi/id/bios_vendor')

        if bios_vendor == 'Xen':
            virtual_facts['virtualization_type'] = 'xen'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if bios_vendor == 'innotek GmbH':
            virtual_facts['virtualization_type'] = 'virtualbox'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if bios_vendor == 'Amazon EC2':
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        sys_vendor = get_file_content('/sys/devices/virtual/dmi/id/sys_vendor')

        # FIXME: This does also match hyperv
        if sys_vendor == 'Microsoft Corporation':
            virtual_facts['virtualization_type'] = 'VirtualPC'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if sys_vendor == 'Parallels Software International Inc.':
            virtual_facts['virtualization_type'] = 'parallels'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if sys_vendor == 'QEMU':
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if sys_vendor == 'oVirt':
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if sys_vendor == 'OpenStack Foundation':
            virtual_facts['virtualization_type'] = 'openstack'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if sys_vendor == 'Amazon EC2':
            virtual_facts['virtualization_type'] = 'kvm'
            virtual_facts['virtualization_role'] = 'guest'
            return virtual_facts

        if os.path.exists('/proc/self/status'):
            for line in get_file_lines('/proc/self/status'):
                if re.match(r'^VxID:\s+\d+', line):
                    virtual_facts['virtualization_type'] = 'linux_vserver'
                    if re.match(r'^VxID:\s+0', line):
                        virtual_facts['virtualization_role'] = 'host'
                    else:
                        virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        if os.path.exists('/proc/cpuinfo'):
            for line in get_file_lines('/proc/cpuinfo'):
                if re.match('^model name.*QEMU Virtual CPU', line):
                    virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*User Mode Linux', line):
                    virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^model name.*UML', line):
                    virtual_facts['virtualization_type'] = 'uml'
                elif re.match('^machine.*CHRP IBM pSeries .emulated by qemu.', line):
                    virtual_facts['virtualization_type'] = 'kvm'
                elif re.match('^vendor_id.*PowerVM Lx86', line):
                    virtual_facts['virtualization_type'] = 'powervm_lx86'
                elif re.match('^vendor_id.*IBM/S390', line):
                    virtual_facts['virtualization_type'] = 'PR/SM'
                    lscpu = self.module.get_bin_path('lscpu')
                    if lscpu:
                        rc, out, err = self.module.run_command(["lscpu"])
                        if rc == 0:
                            for line in out.splitlines():
                                data = line.split(":", 1)
                                key = data[0].strip()
                                if key == 'Hypervisor':
                                    virtual_facts['virtualization_type'] = data[1].strip()
                    else:
                        virtual_facts['virtualization_type'] = 'ibm_systemz'
                else:
                    continue
                if virtual_facts['virtualization_type'] == 'PR/SM':
                    virtual_facts['virtualization_role'] = 'LPAR'
                else:
                    virtual_facts['virtualization_role'] = 'guest'
                return virtual_facts

        # Beware that we can have both kvm and virtualbox running on a single system
        if os.path.exists("/proc/modules") and os.access('/proc/modules', os.R_OK):
            modules = []
            for line in get_file_lines("/proc/modules"):
                data = line.split(" ", 1)
                modules.append(data[0])

            if 'kvm' in modules:

                if os.path.isdir('/rhev/'):

                    # Check whether this is a RHEV hypervisor (is vdsm running ?)
                    for f in glob.glob('/proc/[0-9]*/comm'):
                        try:
                            if open(f).read().rstrip() == 'vdsm':
                                virtual_facts['virtualization_type'] = 'RHEV'
                                break
                        except Exception:
                            pass
                    else:
                        virtual_facts['virtualization_type'] = 'kvm'

                else:
                    virtual_facts['virtualization_type'] = 'kvm'
                    virtual_facts['virtualization_role'] = 'host'

                return virtual_facts

            if 'vboxdrv' in modules:
                virtual_facts['virtualization_type'] = 'virtualbox'
                virtual_facts['virtualization_role'] = 'host'
                return virtual_facts

            if 'virtio' in modules:
                virtual_facts['virtualization_type'] = 'kvm'
                virtual_facts['virtualization_role'] = 'guest'
                return virtual_facts

        # In older Linux Kernel versions, /sys filesystem is not available
        # dmidecode is the safest option to parse virtualization related values
        dmi_bin = self.module.get_bin_path('dmidecode')
        # We still want to continue even if dmidecode is not available
        if dmi_bin is not None:
            (rc, out, err) = self.module.run_command('%s -s system-product-name' % dmi_bin)
            if rc == 0:
                # Strip out commented lines (specific dmidecode output)
                vendor_name = ''.join([line.strip() for line in out.splitlines() if not line.startswith('#')])
                if vendor_name.startswith('VMware'):
                    virtual_facts['virtualization_type'] = 'VMware'
                    virtual_facts['virtualization_role'] = 'guest'
                    return virtual_facts

        # If none of the above matches, return 'NA' for virtualization_type
        # and virtualization_role. This allows for proper grouping.
        virtual_facts['virtualization_type'] = 'NA'
        virtual_facts['virtualization_role'] = 'NA'

        return virtual_facts
Exemple #49
0
    def get_interfaces_info(self, ip_path, default_ipv4, default_ipv6):
        interfaces = {}
        ips = dict(
            all_ipv4_addresses=[],
            all_ipv6_addresses=[],
        )

        # FIXME: maybe split into smaller methods?
        # FIXME: this is pretty much a constructor

        for path in glob.glob('/sys/class/net/*'):
            if not os.path.isdir(path):
                continue
            device = os.path.basename(path)
            interfaces[device] = {'device': device}
            if os.path.exists(os.path.join(path, 'address')):
                macaddress = get_file_content(os.path.join(path, 'address'), default='')
                if macaddress and macaddress != '00:00:00:00:00:00':
                    interfaces[device]['macaddress'] = macaddress
            if os.path.exists(os.path.join(path, 'mtu')):
                interfaces[device]['mtu'] = int(get_file_content(os.path.join(path, 'mtu')))
            if os.path.exists(os.path.join(path, 'operstate')):
                interfaces[device]['active'] = get_file_content(os.path.join(path, 'operstate')) != 'down'
            if os.path.exists(os.path.join(path, 'device', 'driver', 'module')):
                interfaces[device]['module'] = os.path.basename(os.path.realpath(os.path.join(path, 'device', 'driver', 'module')))
            if os.path.exists(os.path.join(path, 'type')):
                _type = get_file_content(os.path.join(path, 'type'))
                interfaces[device]['type'] = self.INTERFACE_TYPE.get(_type, 'unknown')
            if os.path.exists(os.path.join(path, 'bridge')):
                interfaces[device]['type'] = 'bridge'
                interfaces[device]['interfaces'] = [os.path.basename(b) for b in glob.glob(os.path.join(path, 'brif', '*'))]
                if os.path.exists(os.path.join(path, 'bridge', 'bridge_id')):
                    interfaces[device]['id'] = get_file_content(os.path.join(path, 'bridge', 'bridge_id'), default='')
                if os.path.exists(os.path.join(path, 'bridge', 'stp_state')):
                    interfaces[device]['stp'] = get_file_content(os.path.join(path, 'bridge', 'stp_state')) == '1'
            if os.path.exists(os.path.join(path, 'bonding')):
                interfaces[device]['type'] = 'bonding'
                interfaces[device]['slaves'] = get_file_content(os.path.join(path, 'bonding', 'slaves'), default='').split()
                interfaces[device]['mode'] = get_file_content(os.path.join(path, 'bonding', 'mode'), default='').split()[0]
                interfaces[device]['miimon'] = get_file_content(os.path.join(path, 'bonding', 'miimon'), default='').split()[0]
                interfaces[device]['lacp_rate'] = get_file_content(os.path.join(path, 'bonding', 'lacp_rate'), default='').split()[0]
                primary = get_file_content(os.path.join(path, 'bonding', 'primary'))
                if primary:
                    interfaces[device]['primary'] = primary
                    path = os.path.join(path, 'bonding', 'all_slaves_active')
                    if os.path.exists(path):
                        interfaces[device]['all_slaves_active'] = get_file_content(path) == '1'
            if os.path.exists(os.path.join(path, 'bonding_slave')):
                interfaces[device]['perm_macaddress'] = get_file_content(os.path.join(path, 'bonding_slave', 'perm_hwaddr'), default='')
            if os.path.exists(os.path.join(path, 'device')):
                interfaces[device]['pciid'] = os.path.basename(os.readlink(os.path.join(path, 'device')))
            if os.path.exists(os.path.join(path, 'speed')):
                speed = get_file_content(os.path.join(path, 'speed'))
                if speed is not None:
                    interfaces[device]['speed'] = int(speed)

            # Check whether an interface is in promiscuous mode
            if os.path.exists(os.path.join(path, 'flags')):
                promisc_mode = False
                # The second byte indicates whether the interface is in promiscuous mode.
                # 1 = promisc
                # 0 = no promisc
                data = int(get_file_content(os.path.join(path, 'flags')), 16)
                promisc_mode = (data & 0x0100 > 0)
                interfaces[device]['promisc'] = promisc_mode

            # TODO: determine if this needs to be in a nested scope/closure
            def parse_ip_output(output, secondary=False):
                for line in output.splitlines():
                    if not line:
                        continue
                    words = line.split()
                    broadcast = ''
                    if words[0] == 'inet':
                        if '/' in words[1]:
                            address, netmask_length = words[1].split('/')
                            if len(words) > 3:
                                broadcast = words[3]
                        else:
                            # pointopoint interfaces do not have a prefix
                            address = words[1]
                            netmask_length = "32"
                        address_bin = struct.unpack('!L', socket.inet_aton(address))[0]
                        netmask_bin = (1 << 32) - (1 << 32 >> int(netmask_length))
                        netmask = socket.inet_ntoa(struct.pack('!L', netmask_bin))
                        network = socket.inet_ntoa(struct.pack('!L', address_bin & netmask_bin))
                        iface = words[-1]
                        # NOTE: device is ref to outside scope
                        # NOTE: interfaces is also ref to outside scope
                        if iface != device:
                            interfaces[iface] = {}
                        if not secondary and "ipv4" not in interfaces[iface]:
                            interfaces[iface]['ipv4'] = {'address': address,
                                                         'broadcast': broadcast,
                                                         'netmask': netmask,
                                                         'network': network}
                        else:
                            if "ipv4_secondaries" not in interfaces[iface]:
                                interfaces[iface]["ipv4_secondaries"] = []
                            interfaces[iface]["ipv4_secondaries"].append({
                                'address': address,
                                'broadcast': broadcast,
                                'netmask': netmask,
                                'network': network,
                            })

                        # add this secondary IP to the main device
                        if secondary:
                            if "ipv4_secondaries" not in interfaces[device]:
                                interfaces[device]["ipv4_secondaries"] = []
                            if device != iface:
                                interfaces[device]["ipv4_secondaries"].append({
                                    'address': address,
                                    'broadcast': broadcast,
                                    'netmask': netmask,
                                    'network': network,
                                })

                        # NOTE: default_ipv4 is ref to outside scope
                        # If this is the default address, update default_ipv4
                        if 'address' in default_ipv4 and default_ipv4['address'] == address:
                            default_ipv4['broadcast'] = broadcast
                            default_ipv4['netmask'] = netmask
                            default_ipv4['network'] = network
                            # NOTE: macadress is ref from outside scope
                            default_ipv4['macaddress'] = macaddress
                            default_ipv4['mtu'] = interfaces[device]['mtu']
                            default_ipv4['type'] = interfaces[device].get("type", "unknown")
                            default_ipv4['alias'] = words[-1]
                        if not address.startswith('127.'):
                            ips['all_ipv4_addresses'].append(address)
                    elif words[0] == 'inet6':
                        if 'peer' == words[2]:
                            address = words[1]
                            _, prefix = words[3].split('/')
                            scope = words[5]
                        else:
                            address, prefix = words[1].split('/')
                            scope = words[3]
                        if 'ipv6' not in interfaces[device]:
                            interfaces[device]['ipv6'] = []
                            interfaces[device]['ipv6'].append({
                                'address': address,
                                'prefix': prefix,
                                'scope': scope
                            })
                        # If this is the default address, update default_ipv6
                        if 'address' in default_ipv6 and default_ipv6['address'] == address:
                            default_ipv6['prefix'] = prefix
                            default_ipv6['scope'] = scope
                            default_ipv6['macaddress'] = macaddress
                            default_ipv6['mtu'] = interfaces[device]['mtu']
                            default_ipv6['type'] = interfaces[device].get("type", "unknown")
                        if not address == '::1':
                            ips['all_ipv6_addresses'].append(address)

            ip_path = self.module.get_bin_path("ip")

            args = [ip_path, 'addr', 'show', 'primary', device]
            rc, primary_data, stderr = self.module.run_command(args, errors='surrogate_then_replace')

            args = [ip_path, 'addr', 'show', 'secondary', device]
            rc, secondary_data, stderr = self.module.run_command(args, errors='surrogate_then_replace')

            parse_ip_output(primary_data)
            parse_ip_output(secondary_data, secondary=True)

            interfaces[device].update(self.get_ethtool_data(device))

        # replace : by _ in interface name since they are hard to use in template
        new_interfaces = {}
        # i is a dict key (string) not an index int
        for i in interfaces:
            if ':' in i:
                new_interfaces[i.replace(':', '_')] = interfaces[i]
            else:
                new_interfaces[i] = interfaces[i]
        return new_interfaces, ips