def _get_hostname_unix(): try: # fqdn out, err = subp.call('/bin/hostname -f') return out[0] except Exception: return None
def find_packages(self, meta): """ Find a package with running binary """ package_name = None # find which package contains our binary dpkg_s_nginx_out, dpkg_s_nginx_err = subp.call('dpkg -S %s' % self.object.bin_path, check=False) for line in dpkg_s_nginx_out: kv = re.match(self.dpkg_s_re, line) if kv: package_name = kv.group(1) break if dpkg_s_nginx_err: if 'no_path' in dpkg_s_nginx_err[0]: meta['warnings'].append('self-made binary, is not from any nginx package') if not package_name: return # get version all_installed_packages = self.installed_nginx_packages() if package_name in all_installed_packages: meta['packages'] = {package_name: all_installed_packages[package_name]}
def alive_interfaces(): """ Returns a list of all network interfaces which have UP state see ip link show dev eth0 will always return lo in a list if lo exists :return: [] of str """ alive_interfaces = set() try: for interface_name, interface in psutil.net_if_stats().iteritems(): if interface.isup: alive_interfaces.add(interface_name) except: context.log.debug('failed to use psutil.net_if_stats', exc_info=True) # fallback for centos6 for interface_name in netifaces.interfaces(): ip_link_out, _ = subp.call("ip link show dev %s" % interface_name, check=False) if ip_link_out: first_line = ip_link_out[0] r = re.match('.+state\s+(\w+)\s+.*', first_line) if r: state = r.group(1) if interface_name == 'lo' or state == 'UP': alive_interfaces.add(interface_name) return alive_interfaces
def rlimit_nofile(self): if hasattr(self, 'rlimit'): return self.rlimit(psutil.RLIMIT_NOFILE)[1] else: # fallback for old systems without rlimit cat_limits, _ = subp.call("cat /proc/%s/limits | grep 'Max open files' | awk '{print $5}'" % self.pid, check=False) if cat_limits: return int(cat_limits[0])
def certificate_ocsp_uri(filename): result = None openssl_out, _ = subp.call("openssl x509 -in %s -noout -ocsp_uri" % filename, check=False) if openssl_out[0]: result = openssl_out[0] return result
def installed_nginx_packages(self): """ trying to find some installed packages """ result = {} dpkg_grep_nginx_out, _ = subp.call("dpkg -l | grep nginx") for line in dpkg_grep_nginx_out: gwe = re.match(self.dpkg_l_re, line) if gwe: if gwe.group(2).startswith('nginx'): result[gwe.group(2)] = gwe.group(3) return result
def nginx_v(path_to_binary): """ call -V and parse results :param path_to_binary str - path to binary :return {} - see result """ result = { 'version': None, 'plus': {'enabled': False, 'release': None}, 'ssl': {'built': None, 'run': None}, 'configure': {} } _, nginx_v_err = subp.call("%s -V" % path_to_binary) for line in nginx_v_err: # SSL stuff if line.lower().startswith('built with') and 'ssl' in line.lower(): parts = line.split(' ') lib_name, lib_version = parts[2:4] result['ssl'] = { 'built': [lib_name, lib_version], 'run': [lib_name, lib_version], } if line.lower().startswith('run with') and 'ssl' in line.lower(): parts = line.split(' ') lib_name, lib_version = parts[2:4] result['ssl']['run'] = [lib_name, lib_version] parts = line.split(':') if len(parts) < 2: continue # parse version key, value = parts if key == 'nginx version': # parse major version major_parsed = re.match('.*/([\d\w\.]+)', value) result['version'] = major_parsed.group(1) if major_parsed else value.lstrip() # parse plus version if 'plus' in value: plus_parsed = re.match('.*\(([\w\-]+)\).*', value) if plus_parsed: result['plus']['enabled'] = True result['plus']['release'] = plus_parsed.group(1) # parse configure if key == 'configure arguments': arguments = _parse_arguments(value) result['configure'] = arguments return result
def proc_cpuinfo(meta): """ cat /proc/cpuinfo """ proc_cpuinfo_out, _ = subp.call('cat /proc/cpuinfo') for line in proc_cpuinfo_out: kv = re.match('([\w|\s]+):\s*(.+)', line) if kv: key, value = kv.group(1), kv.group(2) if key.startswith('model name'): meta['processor']['model'] = value elif key.startswith('cpu cores'): meta['processor']['cores'] = value
def certificate_purpose(filename): results = {} openssl_out, _ = subp.call("openssl x509 -in %s -noout -purpose" % filename, check=False) for line in openssl_out: if line: split = line.split(' : ') if len(split) == 2: key, value = line.split(' : ') results[key] = value return results or None
def open_ssl(self, meta): """Old nginx uses standart openssl library - find its version""" if not meta['ssl']: openssl_out, _ = subp.call("dpkg -l | grep openssl") for line in openssl_out: gwe = re.match('([\d\w]+)\s+([\d\w\.\-]+)\s+([\d\w\.\-\+_~]+)\s', line) if gwe: if gwe.group(2).startswith('openssl'): meta['ssl'] = { 'built': [gwe.group(2), gwe.group(3)], 'run': [gwe.group(2), gwe.group(3)], }
def certificate_issuer(filename): results = {} openssl_out, _ = subp.call("openssl x509 -in %s -noout -issuer" % filename, check=False) for line in openssl_out: if line: for regex in ssl_regexs: match_obj = regex.match(line) if match_obj: results.update(match_obj.groupdict()) return results or None
def etc_release(meta): SystemCommonMetaCollector.etc_release(meta) # centos6 has different *-release format # for example: CentOS release 6.7 (Final) if meta['release']['version_id'] is None and meta['release']['version'] is None: etc_release_out, _ = subp.call('cat /etc/centos-release') for line in etc_release_out: r = re.match('(\w+)\s+(\w+)\s+([\d\.]+)\s+([\w\(\)]+)', line) if r: meta['release']['name'] = r.group(1) meta['release']['version_id'] = r.group(3) meta['release']['version'] = '%s %s' % (r.group(3), r.group(4))
def test_default_interface(self): container = SystemContainer() container.discover_objects() os_obj = container.objects.values().pop() collector = SystemCommonMetaCollector(object=os_obj) collector.collect() default_from_netstat, _ = subp.call( 'netstat -nr | egrep -i "^0.0.0.0|default" | head -1 | sed "s/.*[ ]\([^ ][^ ]*\)$/\\1/"' )[0] default_interface = os_obj.metad.current['network']['default'] assert_that(default_interface, equal_to(default_from_netstat))
def certificate_dates(filename): keys = { 'notBefore': 'start', 'notAfter': 'end' } results = {} openssl_out, _ = subp.call("openssl x509 -in %s -noout -dates" % filename, check=False) for line in openssl_out: if line: key, value = line.split('=') if key in keys: results[keys[key]] = int(datetime.datetime.strptime(value, '%b %d %H:%M:%S %Y %Z').strftime('%s')) return results or None
def network(meta): """ network """ # collect info for all hte alive interfaces for interface in alive_interfaces(): addresses = netifaces.ifaddresses(interface) interface_info = { 'name': interface } # collect ipv4 and ipv6 addresses for proto, key in { 'ipv4': netifaces.AF_INET, 'ipv6': netifaces.AF_INET6 }.iteritems(): # get the first address protocol_data = addresses.get(key, [{}])[0] if protocol_data: addr = protocol_data.get('addr').split('%').pop(0) netmask = protocol_data.get('netmask') try: prefixlen = netaddr.IPNetwork('%s/%s' % (addr, netmask)).prefixlen except: prefixlen = None interface_info[proto] = { 'netmask': netmask, 'address': addr, 'prefixlen': prefixlen } # collect mac address interface_info['mac'] = addresses.get(netifaces.AF_LINK, [{}])[0].get('addr') meta['network']['interfaces'].append(interface_info) # get default interface name netstat_out, _ = subp.call("netstat -nr | egrep -i '^0.0.0.0|default'", check=False) if len(netstat_out) and netstat_out[0]: first_matched_line = netstat_out[0] default_interface = first_matched_line.split(' ')[-1] elif len(meta['network']['interfaces']): default_interface = meta['network']['interfaces'][0]['name'] else: default_interface = None meta['network']['default'] = default_interface
def certificate_full(filename): results = {} openssl_out, _ = subp.call("openssl x509 -in %s -noout -text" % filename, check=False) for line in openssl_out: for regex in ssl_text_regexs: match_obj = regex.match(line) if match_obj: results.update(match_obj.groupdict()) continue # If a match was made skip the DNS check. dns_matches = ssl_dns_regex.findall(line) if dns_matches: results['names'] = map(lambda x: x.split(':')[1], dns_matches) return results or None
def netstat(self): """ netstat -s (check for "SYNs to LISTEN sockets dropped” and "times the listen queue of a socket overflowed") """ new_stamp = time.time() netstat_out, _ = subp.call("netstat -s | grep -i 'times the listen queue of a socket overflowed'", check=False) gwe = re.match('\s*(\d+)\s*', netstat_out.pop(0)) new_value = int(gwe.group(1)) if gwe else 0 prev_stamp, prev_value = self.previous_values.get('system.net.listen_overflows', [None, None]) if prev_stamp: delta_value = new_value - prev_value self.statsd.incr('system.net.listen_overflows', delta_value) self.previous_values['system.net.listen_overflows'] = [new_stamp, new_value]
def run_test(self): """ Tests the configuration using nginx -t Saves event info if syntax check was not successful """ start_time = time.time() context.log.info("running %s -t -c %s" % (self.binary, self.filename)) if self.binary: try: _, nginx_t_err = subp.call("%s -t -c %s" % (self.binary, self.filename), check=False) for line in nginx_t_err: if "syntax is" in line and "syntax is ok" not in line: self.test_errors.append(line) except Exception, e: exception_name = e.__class__.__name__ context.log.error("failed to %s -t -c %s due to %s" % (self.binary, self.filename, exception_name)) context.log.debug("additional info:", exc_info=True)
def get_master_workers(self): master, workers = None, [] ps, _ = subp.call('ps -xa -o pid,ppid,command | egrep "PID|nginx" | grep -v egrep') for line in ps: # 21355 1 nginx: master process /usr/sbin/nginx gwe = re.match(r'\s*(?P<pid>\d+)\s+(?P<ppid>\d+)\s+(?P<cmd>.+)\s*', line) # if not parsed - switch to next line if not gwe or 'py.test' in line: continue pid = int(gwe.group('pid')) cmd = gwe.group('cmd') if 'nginx: master process' in cmd: master = pid else: workers.append(pid) return master, workers
def lscpu(meta): """ lscpu """ lscpu_out, _ = subp.call('lscpu') for line in lscpu_out: kv = re.match('([\w\d\s\(\)]+):\s+([\w|\d]+)', line) if kv: key, value = kv.group(1), kv.group(2) if key == 'Architecture': meta['processor']['architecture'] = value elif key == 'CPU MHz': meta['processor']['mhz'] = value elif key == 'Hypervisor vendor': meta['processor']['hypervisor'] = value elif key == 'Virtualization type': meta['processor']['virtualization'] = value elif key == 'CPU(s)': meta['processor']['cpus'] = value elif 'cache' in key: key = key.replace(' cache', '') meta['processor']['cache'][key] = value
def etc_release(meta): """ /etc/*-release """ mapper = { 'name': ('NAME', 'DISTRIB_ID'), 'version_id': ('VERSION_ID', 'DISTRIB_RELEASE'), 'version': ('VERSION', 'DISTRIB_DESCRIPTION') } for release_file in glob.glob("/etc/*-release"): etc_release_out, _ = subp.call('cat %s' % release_file) for line in etc_release_out: kv = re.match('(\w+)=(.+)', line) if kv: key, value = kv.group(1), kv.group(2) for var_name, release_vars in mapper.iteritems(): if key in release_vars: if meta['release'][var_name] is None: meta['release'][var_name] = value.replace('"', '') if meta['release']['name'] is None: meta['release']['name'] = 'unix'
def find_packages(self, meta): """ Find a package with running binary """ package, version = None, None rpm_qf_out, rpm_qf_err = subp.call( 'rpm -qf %s ' % self.object.bin_path + '--queryformat="%{NAME} %{VERSION}-%{RELEASE}.%{ARCH}' + '\\n"', check=False ) if rpm_qf_out and rpm_qf_out[0]: package, version = rpm_qf_out[0].split(' ') if rpm_qf_err: if 'is not owned by' in rpm_qf_err[0]: meta['warnings'].append('self-made binary, is not from any nginx package') if not package: return meta['packages'] = {package: version}
def setup_method(self, method): super(RealNginxTestCase, self).setup_method(method) self.second_started = False subp.call('service nginx start')
def restart_nginx(self): subp.call('service nginx restart')
def start_second_nginx(self): subp.call('/usr/sbin/nginx2 -c /etc/nginx/nginx2.conf') self.second_started = True
def reload_nginx(self): subp.call('service nginx reload')
def teardown_method(self, method): subp.call('pgrep nginx |sudo xargs kill -SIGKILL') super(RealNginxTestCase, self).teardown_method(method)
def nginx_plus_installed(): out, err = subp.call('/usr/sbin/nginx -V') first_line = err[0] return True if 'nginx-plus' in first_line else False
def stop_first_nginx(self): subp.call('service nginx stop')
def start_second_nginx(self, conf='nginx2.conf'): subp.call('/usr/sbin/nginx2 -c /etc/nginx/%s' % conf) self.second_started = True