def test_get_path_path_raise_valueerror(mocker): mocker.patch.dict('os.environ', {'PATH': ''}) mocker.patch('os.path.exists', return_value=False) mocker.patch('os.path.isdir', return_value=False) mocker.patch('assible.module_utils.common.process.is_executable', return_value=True) with pytest.raises(ValueError, match='Failed to find required executable notacommand'): get_bin_path('notacommand')
def is_available(self): ''' we expect the python bindings installed, but this gives warning if they are missing and we have rpm cli''' we_have_lib = super(RPM, self).is_available() try: get_bin_path('rpm') if not we_have_lib: module.warn('Found "rpm" but %s' % (missing_required_lib('rpm'))) except ValueError: pass return we_have_lib
def is_available(self): ''' we expect the python bindings installed, but if there is apt/apt-get give warning about missing bindings''' we_have_lib = super(APT, self).is_available() if not we_have_lib: for exe in ('apt', 'apt-get', 'aptitude'): try: get_bin_path(exe) except ValueError: continue else: module.warn('Found "%s" but %s' % (exe, missing_required_lib('apt'))) break return we_have_lib
def scm_archive_resource(src, scm='git', name=None, version='HEAD', keep_scm_meta=False): def run_scm_cmd(cmd, tempdir): try: stdout = '' stderr = '' popen = Popen(cmd, cwd=tempdir, stdout=PIPE, stderr=PIPE) stdout, stderr = popen.communicate() except Exception as e: ran = " ".join(cmd) display.debug("ran %s:" % ran) raise AssibleError("when executing %s: %s" % (ran, to_native(e))) if popen.returncode != 0: raise AssibleError("- command %s failed in directory %s (rc=%s) - %s" % (' '.join(cmd), tempdir, popen.returncode, to_native(stderr))) if scm not in ['hg', 'git']: raise AssibleError("- scm %s is not currently supported" % scm) try: scm_path = get_bin_path(scm) except (ValueError, OSError, IOError): raise AssibleError("could not find/use %s, it is required to continue with installing %s" % (scm, src)) tempdir = tempfile.mkdtemp(dir=C.DEFAULT_LOCAL_TMP) clone_cmd = [scm_path, 'clone', src, name] run_scm_cmd(clone_cmd, tempdir) if scm == 'git' and version: checkout_cmd = [scm_path, 'checkout', to_text(version)] run_scm_cmd(checkout_cmd, os.path.join(tempdir, name)) temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.tar', dir=C.DEFAULT_LOCAL_TMP) archive_cmd = None if keep_scm_meta: display.vvv('tarring %s from %s to %s' % (name, tempdir, temp_file.name)) with tarfile.open(temp_file.name, "w") as tar: tar.add(os.path.join(tempdir, name), arcname=name) elif scm == 'hg': archive_cmd = [scm_path, 'archive', '--prefix', "%s/" % name] if version: archive_cmd.extend(['-r', version]) archive_cmd.append(temp_file.name) elif scm == 'git': archive_cmd = [scm_path, 'archive', '--prefix=%s/' % name, '--output=%s' % temp_file.name] if version: archive_cmd.append(version) else: archive_cmd.append('HEAD') if archive_cmd is not None: display.vvv('archiving %s' % archive_cmd) run_scm_cmd(archive_cmd, os.path.join(tempdir, name)) return temp_file.name
def clear_facls(path): setfacl = get_bin_path('setfacl') # FIXME "setfacl -b" is available on Linux and FreeBSD. There is "setfacl -D e" on z/OS. Others? acl_command = [setfacl, '-b', path] b_acl_command = [to_bytes(x) for x in acl_command] rc, out, err = module.run_command(b_acl_command, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')) if rc != 0: raise RuntimeError( 'Error running "{0}": stdout: "{1}"; stderr: "{2}"'.format( ' '.join(b_acl_command), out, err))
def test_get_bin_path(mocker): path = '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' mocker.patch.dict('os.environ', {'PATH': path}) mocker.patch('os.pathsep', ':') mocker.patch('os.path.isdir', return_value=False) mocker.patch('assible.module_utils.common.process.is_executable', return_value=True) # pytest-mock 2.0.0 will throw when os.path.exists is messed with # and then another method is patched afterwards. Likely # something in the pytest-mock chain uses os.path.exists internally, and # since pytest-mock prohibits context-specific patching, there's not a # good solution. For now, just patch os.path.exists last. mocker.patch('os.path.exists', side_effect=[False, True]) assert '/usr/local/bin/notacommand' == get_bin_path('notacommand')
def get_memory_facts(self): memory_facts = { 'memtotal_mb': int(self.sysctl['hw.memsize']) // 1024 // 1024, 'memfree_mb': 0, } total_used = 0 page_size = 4096 try: vm_stat_command = get_bin_path('vm_stat') except ValueError: return memory_facts rc, out, err = self.module.run_command(vm_stat_command) if rc == 0: # Free = Total - (Wired + active + inactive) # Get a generator of tuples from the command output so we can later # turn it into a dictionary memory_stats = (line.rstrip('.').split(':', 1) for line in out.splitlines()) # Strip extra left spaces from the value memory_stats = dict((k, v.lstrip()) for k, v in memory_stats) for k, v in memory_stats.items(): try: memory_stats[k] = int(v) except ValueError: # Most values convert cleanly to integer values but if the field does # not convert to an integer, just leave it alone. pass if memory_stats.get('Pages wired down'): total_used += memory_stats['Pages wired down'] * page_size if memory_stats.get('Pages active'): total_used += memory_stats['Pages active'] * page_size if memory_stats.get('Pages inactive'): total_used += memory_stats['Pages inactive'] * page_size memory_facts['memfree_mb'] = memory_facts['memtotal_mb'] - ( total_used // 1024 // 1024) return memory_facts
def is_available(self): try: self._cli = get_bin_path(self.CLI) except ValueError: return False return True
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.7f000002 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 Example of output from the HP-UX iscsiutil command: #iscsiutil -l Initiator Name : iqn.1986-03.com.hp:mcel_VMhost3.1f355cf6-e2db-11e0-a999-b44c0aef5537 Initiator Alias : Authentication Method : None CHAP Method : CHAP_UNI Initiator CHAP Name : CHAP Secret : NAS Hostname : NAS Secret : Radius Server Hostname : Header Digest : None, CRC32C (default) Data Digest : None, CRC32C (default) SLP Scope list for iSLPD : """ 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'): try: cmd = get_bin_path('lsattr') except ValueError: return iscsi_facts cmd += " -E -l iscsi0" rc, out, err = module.run_command(cmd) if rc == 0 and out: line = self.findstr(out, 'initiator_name') iscsi_facts['iscsi_iqn'] = line.split()[1].rstrip() elif sys.platform.startswith('hp-ux'): # try to find it in the default PATH and opt_dirs try: cmd = get_bin_path('iscsiutil', opt_dirs=['/opt/iscsi/bin']) except ValueError: return iscsi_facts cmd += " -l" rc, out, err = module.run_command(cmd) if out: line = self.findstr(out, 'Initiator Name') iscsi_facts['iscsi_iqn'] = line.split(":", 1)[1].rstrip() return iscsi_facts
def get_cpu_facts(self, collected_facts=None): cpu_facts = {} collected_facts = collected_facts or {} i = 0 vendor_id_occurrence = 0 model_name_occurrence = 0 processor_occurence = 0 physid = 0 coreid = 0 sockets = {} cores = {} xen = False xen_paravirt = False try: if os.path.exists('/proc/xen'): xen = True else: for line in get_file_lines('/sys/hypervisor/type'): if line.strip() == 'xen': xen = True # Only interested in the first line break except IOError: pass if not os.access("/proc/cpuinfo", os.R_OK): return cpu_facts cpu_facts['processor'] = [] for line in get_file_lines('/proc/cpuinfo'): data = line.split(":", 1) key = data[0].strip() try: val = data[1].strip() except IndexError: val = "" if xen: if key == 'flags': # Check for vme cpu flag, Xen paravirt does not expose this. # Need to detect Xen paravirt because it exposes cpuinfo # differently than Xen HVM or KVM and causes reporting of # only a single cpu core. if 'vme' not in val: xen_paravirt = True # model name is for Intel arch, Processor (mind the uppercase P) # works for some ARM devices, like the Sheevaplug. # 'ncpus active' is SPARC attribute if key in [ 'model name', 'Processor', 'vendor_id', 'cpu', 'Vendor', 'processor' ]: if 'processor' not in cpu_facts: cpu_facts['processor'] = [] cpu_facts['processor'].append(val) if key == 'vendor_id': vendor_id_occurrence += 1 if key == 'model name': model_name_occurrence += 1 if key == 'processor': processor_occurence += 1 i += 1 elif key == 'physical id': physid = val if physid not in sockets: sockets[physid] = 1 elif key == 'core id': coreid = val if coreid not in sockets: cores[coreid] = 1 elif key == 'cpu cores': sockets[physid] = int(val) elif key == 'siblings': cores[coreid] = int(val) elif key == '# processors': cpu_facts['processor_cores'] = int(val) elif key == 'ncpus active': i = int(val) # Skip for platforms without vendor_id/model_name in cpuinfo (e.g ppc64le) if vendor_id_occurrence > 0: if vendor_id_occurrence == model_name_occurrence: i = vendor_id_occurrence # The fields for ARM CPUs do not always include 'vendor_id' or 'model name', # and sometimes includes both 'processor' and 'Processor'. # The fields for Power CPUs include 'processor' and 'cpu'. # Always use 'processor' count for ARM and Power systems if collected_facts.get('assible_architecture', '').startswith( ('armv', 'aarch', 'ppc')): i = processor_occurence # FIXME if collected_facts.get('assible_architecture') != 's390x': if xen_paravirt: cpu_facts['processor_count'] = i cpu_facts['processor_cores'] = i cpu_facts['processor_threads_per_core'] = 1 cpu_facts['processor_vcpus'] = i else: if sockets: cpu_facts['processor_count'] = len(sockets) else: cpu_facts['processor_count'] = i socket_values = list(sockets.values()) if socket_values and socket_values[0]: cpu_facts['processor_cores'] = socket_values[0] else: cpu_facts['processor_cores'] = 1 core_values = list(cores.values()) if core_values: cpu_facts['processor_threads_per_core'] = core_values[ 0] // cpu_facts['processor_cores'] else: cpu_facts['processor_threads_per_core'] = 1 // cpu_facts[ 'processor_cores'] cpu_facts['processor_vcpus'] = ( cpu_facts['processor_threads_per_core'] * cpu_facts['processor_count'] * cpu_facts['processor_cores']) # if the number of processors available to the module's # thread cannot be determined, the processor count # reported by /proc will be the default: cpu_facts['processor_nproc'] = processor_occurence try: cpu_facts['processor_nproc'] = len(os.sched_getaffinity(0)) except AttributeError: # In Python < 3.3, os.sched_getaffinity() is not available try: cmd = get_bin_path('nproc') except ValueError: pass else: rc, out, _err = self.module.run_command(cmd) if rc == 0: cpu_facts['processor_nproc'] = int(out) return cpu_facts