X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=tools%2Fsysteminfo.py;h=d515983d3dea86701c0a6e21e3a77bc9f38185f4;hb=5c9af545cd8c20b6cda52b3acb3df34f82a1216d;hp=19c5d16ed8ae2a7835b7ee22323f4b7f58206d63;hpb=91bc210a11e44eb9e377c18b5ae0e95dce159409;p=vswitchperf.git diff --git a/tools/systeminfo.py b/tools/systeminfo.py index 19c5d16e..d515983d 100644 --- a/tools/systeminfo.py +++ b/tools/systeminfo.py @@ -1,4 +1,4 @@ -# Copyright 2015 Intel Corporation. +# Copyright 2015-2017 Intel Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,15 +19,35 @@ import os import platform import subprocess import locale +import re +import distro -from conf import settings +from conf import settings as S + +def match_line(file_name, pattern): + """ loops through given file and returns first line matching given pattern + + :returns: string with the matching line without end of line or None + """ + try: + with open(file_name, encoding="latin-1") as file_: + for line in file_: + if not line.strip(): + continue + if not line.strip().startswith(pattern): + continue + + return line.strip().rstrip('\n') + return None + except OSError: + return None def get_os(): """Get distro name. :returns: Return distro name as a string """ - return ' '.join(platform.dist()) + return ' '.join(distro.linux_distribution()) def get_kernel(): """Get kernel version. @@ -41,28 +61,23 @@ def get_cpu(): :returns: Return CPU information as a string """ - with open('/proc/cpuinfo') as file_: - for line in file_: - if not line.strip(): - continue - if not line.rstrip('\n').startswith('model name'): - continue - - return line.rstrip('\n').split(':')[1] + cpu = match_line('/proc/cpuinfo', 'model name') + return cpu.split(':')[1] if cpu else cpu def get_nic(): """Get NIC(s) information. - :returns: Return NIC(s) information as a string + :returns: Return NIC(s) information as a list """ nics = [] output = subprocess.check_output('lspci', shell=True) output = output.decode(locale.getdefaultlocale()[1]) for line in output.split('\n'): - for nic_pciid in settings.getValue('WHITELIST_NICS'): - if line.startswith(nic_pciid): + for nic in S.getValue('NICS'): + # lspci shows PCI addresses without domain part, i.e. last 7 chars + if line.startswith(nic['pci'][-7:]): nics.append(''.join(line.split(':')[2:]).strip()) - return ', '.join(nics).strip() + return nics def get_platform(): """Get platform information. @@ -108,14 +123,8 @@ def get_memory(): :returns: amount of system memory as string together with unit """ - with open('/proc/meminfo') as file_: - for line in file_: - if not line.strip(): - continue - if not line.rstrip('\n').startswith('MemTotal'): - continue - - return line.rstrip('\n').split(':')[1].strip() + memory = match_line('/proc/meminfo', 'MemTotal') + return memory.split(':')[1].strip() if memory else memory def get_memory_bytes(): """Get memory information in bytes @@ -137,3 +146,196 @@ def get_memory_bytes(): return int(mem) +def get_pids(proc_names_list): + """ Get pid(s) of process(es) with given name(s) + + :returns: list with pid(s) of given processes or None if processes + with given names are not running + """ + + try: + pids = subprocess.check_output(['sudo', 'LC_ALL=' + S.getValue('DEFAULT_CMD_LOCALE'), 'pidof'] + + proc_names_list) + except subprocess.CalledProcessError: + # such process isn't running + return None + + return list(map(str, map(int, pids.split()))) + +def get_pid(proc_name_str): + """ Get pid(s) of process with given name + + :returns: list with pid(s) of given process or None if process + with given name is not running + """ + return get_pids([proc_name_str]) + +def pid_isalive(pid): + """ Checks if given PID is alive + + :param pid: PID of the process + :returns: True if given process is running, False otherwise + """ + return os.path.isdir('/proc/' + str(pid)) + +def get_bin_version(binary, regex): + """ get version of given binary selected by given regex + + :returns: version string or None + """ + try: + output = subprocess.check_output(binary, shell=True).decode().rstrip('\n') + except subprocess.CalledProcessError: + return None + + versions = re.findall(regex, output) + if len(versions): + return versions[0] + else: + return None + +def get_git_tag(path): + """ get tag of recent commit from repository located at 'path' + + :returns: git tag in form of string with commit hash or None if there + isn't any git repository at given path + """ + try: + if os.path.isdir(path): + return subprocess.check_output('cd {}; git rev-parse HEAD'.format(path), shell=True, + stderr=subprocess.DEVNULL).decode().rstrip('\n') + elif os.path.isfile(path): + return subprocess.check_output('cd $(dirname {}); git log -1 --pretty="%H" {}'.format(path, path), + shell=True, stderr=subprocess.DEVNULL).decode().rstrip('\n') + else: + return None + except subprocess.CalledProcessError: + return None + +# This function uses long switch per purpose, so let us suppress pylint warning too-many-branches +# pylint: disable=too-many-branches, too-many-statements +def get_version(app_name): + """ Get version of given application and its git tag + + :returns: dictionary {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag) in case that + version or git tag are not known or not applicaple, than None is returned for any unknown value + + """ + app_version_file = { + 'ovs' : r'Open vSwitch\) ([0-9.]+)', + 'testpmd' : r'RTE Version: \'\S+ ([0-9.]+)', + 'qemu' : r'QEMU emulator version ([0-9.]+)', + 'loopback_l2fwd' : os.path.join(S.getValue('ROOT_DIR'), 'src/l2fwd/l2fwd.c'), + 'loopback_testpmd' : os.path.join(S.getValue('TOOLS')['dpdk_src'], + 'lib/librte_eal/common/include/rte_version.h'), + 'ixnet' : os.path.join(S.getValue('TRAFFICGEN_IXNET_LIB_PATH'), 'pkgIndex.tcl'), + 'ixia' : os.path.join(S.getValue('TRAFFICGEN_IXIA_ROOT_DIR'), 'lib/ixTcl1.0/ixTclHal.tcl'), + } + + + + app_version = None + app_git_tag = None + + if app_name.lower().startswith('ovs'): + app_version = get_bin_version('{} --version'.format(S.getValue('TOOLS')['ovs-vswitchd']), + app_version_file['ovs']) + if 'vswitch_src' in S.getValue('TOOLS'): + app_git_tag = get_git_tag(S.getValue('TOOLS')['vswitch_src']) + elif app_name.lower() in ['dpdk', 'testpmd']: + app_version = get_bin_version('{} -v -h'.format(S.getValue('TOOLS')['testpmd']), + app_version_file['testpmd']) + # we have to consult PATHS settings to be sure, that dpdk/testpmd + # were build from the sources + if S.getValue('PATHS')[app_name.lower()]['type'] == 'src': + app_git_tag = get_git_tag(S.getValue('TOOLS')['dpdk_src']) + elif app_name.lower() == 'loopback_testpmd': + # testpmd inside the guest is compiled from downloaded sources + # stored at TOOS['dpdk_src'] directory + tmp_ver = ['', '', ''] + dpdk_16 = False + with open(app_version_file['loopback_testpmd']) as file_: + for line in file_: + if not line.strip(): + continue + # DPDK version < 16 + if line.startswith('#define RTE_VER_MAJOR'): + tmp_ver[0] = line.rstrip('\n').split(' ')[2] + # DPDK version < 16 + elif line.startswith('#define RTE_VER_PATCH_LEVEL'): + tmp_ver[2] = line.rstrip('\n').split(' ')[2] + # DPDK version < 16 + elif line.startswith('#define RTE_VER_PATCH_RELEASE'): + release = line.rstrip('\n').split(' ')[2] + if not '16' in release: + tmp_ver[2] += line.rstrip('\n').split(' ')[2] + # DPDK all versions + elif line.startswith('#define RTE_VER_MINOR'): + if dpdk_16: + tmp_ver[2] = line.rstrip('\n').split(' ')[2] + else: + tmp_ver[1] = line.rstrip('\n').split(' ')[2] + # DPDK all versions + elif line.startswith('#define RTE_VER_SUFFIX'): + tmp_ver[2] += line.rstrip('\n').split('"')[1] + # DPDK version >= 16 + elif line.startswith('#define RTE_VER_YEAR'): + dpdk_16 = True + tmp_ver[0] = line.rstrip('\n').split(' ')[2] + # DPDK version >= 16 + elif line.startswith('#define RTE_VER_MONTH'): + tmp_ver[1] = '{:0>2}'.format(line.rstrip('\n').split(' ')[2]) + # DPDK version >= 16 + elif line.startswith('#define RTE_VER_RELEASE'): + release = line.rstrip('\n').split(' ')[2] + if not '16' in release: + tmp_ver[2] += line.rstrip('\n').split(' ')[2] + + if len(tmp_ver[0]): + app_version = '.'.join(tmp_ver) + app_git_tag = get_git_tag(S.getValue('TOOLS')['dpdk_src']) + elif app_name.lower().startswith('qemu'): + app_version = get_bin_version('{} --version'.format(S.getValue('TOOLS')['qemu-system']), + app_version_file['qemu']) + if 'qemu_src' in S.getValue('TOOLS'): + app_git_tag = get_git_tag(S.getValue('TOOLS')['qemu_src']) + elif app_name.lower() == 'ixnet': + app_version = match_line(app_version_file['ixnet'], 'package provide IxTclNetwork') + if app_version: + app_version = app_version.split(' ')[3] + elif app_name.lower() == 'ixia': + app_version = match_line(app_version_file['ixia'], 'package provide IxTclHal') + if app_version: + app_version = app_version.split(' ')[3] + elif app_name.lower() == 'xena': + try: + app_version = S.getValue('XENA_VERSION') + except AttributeError: + # setting was not available after execution + app_version = 'N/A' + elif app_name.lower() == 'dummy': + # get git tag of file with Dummy implementation + app_git_tag = get_git_tag(os.path.join(S.getValue('ROOT_DIR'), 'tools/pkt_gen/dummy/dummy.py')) + elif app_name.lower() == 'vswitchperf': + app_git_tag = get_git_tag(S.getValue('ROOT_DIR')) + elif app_name.lower() == 'l2fwd': + app_version = match_line(app_version_file['loopback_l2fwd'], 'MODULE_VERSION') + if app_version: + app_version = app_version.split('"')[1] + app_git_tag = get_git_tag(app_version_file['loopback_l2fwd']) + elif app_name.lower() in ['linux_bridge', 'buildin']: + # without login into running VM, it is not possible to check bridge_utils version + app_version = 'NA' + app_git_tag = 'NA' + + return {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag} + +def get_loopback_version(loopback_app_name): + """ Get version of given guest loopback application and its git tag + + :returns: dictionary {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag) in case that + version or git tag are not known or not applicaple, than None is returned for any unknown value + """ + version = get_version("loopback_{}".format(loopback_app_name)) + version['name'] = loopback_app_name + return version