aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/report/report.jinja11
-rw-r--r--tools/report/report.py39
-rw-r--r--tools/systeminfo.py135
-rw-r--r--vnfs/qemu/qemu.py5
-rwxr-xr-xvsperf11
5 files changed, 162 insertions, 39 deletions
diff --git a/tools/report/report.jinja b/tools/report/report.jinja
index 6542a202..f59dba72 100644
--- a/tools/report/report.jinja
+++ b/tools/report/report.jinja
@@ -61,7 +61,16 @@ Below is the environment that the test was performed in:
- CPU cores: {{tests[0].env.cpu_cores}}
- Memory: {{tests[0].env.memory}}
- Virtual Switch Set-up: {{tests[0].deployment}}
-- IxNetwork: {{tests[0].env.ixnetwork_ver}}
+- vswitchperf: GIT tag: {{tests[0].env.vsperf['git_tag']}}
+- Traffic Generator: {{tests[0].env.traffic_gen['name']}}, Version: {{tests[0].env.traffic_gen['version']}}, GIT tag: {{tests[0].env.traffic_gen['git_tag']}}
+- vSwitch: {{tests[0].env.vswitch['name']}}, Version: {{tests[0].env.vswitch['version']}}, GIT tag: {{tests[0].env.vswitch['git_tag']}}
+- DPDK Version: {{tests[0].env.dpdk['version']}}, GIT tag: {{tests[0].env.dpdk['git_tag']}}
+{%- if 'vnf' in tests[0].env %}
+- VNF: {{tests[0].env.vnf['name']}}, Version: {{tests[0].env.vnf['version']}}, GIT tag: {{tests[0].env.vnf['git_tag']}}
+- VM images: {% for guest_image in tests[0].env.guest_image %}{{guest_image}} {% endfor %}
+- VM loopback apps: {% for loopback_app in tests[0].env.loopback_app %}{{loopback_app['name']}}, Version: {{loopback_app['version']}}, GIT tag: {{loopback_app['git_tag']}}
+ {% endfor %}
+{%- endif %}
For each test, a summary of the key test results is provided.
{% for test in tests %}
diff --git a/tools/report/report.py b/tools/report/report.py
index d51ff47d..4264c055 100644
--- a/tools/report/report.py
+++ b/tools/report/report.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,14 +24,14 @@ import jinja2
import logging
from core.results.results_constants import ResultsConstants
-from conf import settings
+from conf import settings as S
from tools import systeminfo
_TEMPLATE_FILE = 'report.jinja'
_ROOT_DIR = os.path.normpath(os.path.dirname(os.path.realpath(__file__)))
-def _get_env():
+def _get_env(result):
"""
Get system configuration.
@@ -53,8 +53,18 @@ def _get_env():
'cpu_cores': systeminfo.get_cpu_cores(),
'memory' : systeminfo.get_memory(),
'platform': systeminfo.get_platform(),
+ 'vsperf': systeminfo.get_version('vswitchperf'),
+ 'traffic_gen': systeminfo.get_version(S.getValue('TRAFFICGEN')),
+ 'vswitch': systeminfo.get_version(S.getValue('VSWITCH')),
+ 'dpdk': systeminfo.get_version('dpdk'),
}
+ if result[ResultsConstants.DEPLOYMENT].count('v'):
+ env.update({'vnf': systeminfo.get_version(S.getValue('VNF')),
+ 'guest_image': S.getValue('GUEST_IMAGE'),
+ 'loopback_app': list(map(systeminfo.get_version, S.getValue('GUEST_LOOPBACK'))),
+ })
+
return env
@@ -78,28 +88,27 @@ def generate(input_file, tc_results, tc_stats):
try:
for result in tc_results:
test_config = {}
- for tc_conf in settings.getValue('PERFORMANCE_TESTS'):
+ for tc_conf in S.getValue('PERFORMANCE_TESTS'):
if tc_conf['Name'] == result[ResultsConstants.ID]:
test_config = tc_conf
break
- # remove id and deployment from results but store their values
- tc_id = result[ResultsConstants.ID]
- tc_deployment = result[ResultsConstants.DEPLOYMENT]
- del result[ResultsConstants.ID]
- del result[ResultsConstants.DEPLOYMENT]
-
# pass test results, env details and configuration to template
tests.append({
- 'ID': tc_id.upper(),
- 'id': tc_id,
- 'deployment': tc_deployment,
+ 'ID': result[ResultsConstants.ID].upper(),
+ 'id': result[ResultsConstants.ID],
+ 'deployment': result[ResultsConstants.DEPLOYMENT],
'conf': test_config,
'result': result,
- 'env': _get_env(),
+ 'env': _get_env(result),
'stats': tc_stats
})
+ # remove id and deployment from results before rendering
+ # but after _get_env() is called; tests dict has its shallow copy
+ del result[ResultsConstants.ID]
+ del result[ResultsConstants.DEPLOYMENT]
+
template_vars = {
'tests': tests,
}
@@ -117,6 +126,6 @@ def generate(input_file, tc_results, tc_stats):
if __name__ == '__main__':
- settings.load_from_dir('conf')
+ S.load_from_dir('conf')
OUT = generate(sys.argv[1], '', '')
print('Test report written to "%s"...' % OUT)
diff --git a/tools/systeminfo.py b/tools/systeminfo.py
index cb9ca6ee..901b334e 100644
--- a/tools/systeminfo.py
+++ b/tools/systeminfo.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -20,7 +20,25 @@ import platform
import subprocess
import locale
-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.
@@ -41,14 +59,8 @@ 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.
@@ -59,7 +71,7 @@ def get_nic():
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'):
+ for nic_pciid in S.getValue('WHITELIST_NICS'):
if line.startswith(nic_pciid):
nics.append(''.join(line.split(':')[2:]).strip())
return ', '.join(nics).strip()
@@ -108,14 +120,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
@@ -145,7 +151,7 @@ def get_pids(proc_names_list):
"""
try:
- pids = subprocess.check_output(['sudo', 'LC_ALL=' + settings.getValue('DEFAULT_CMD_LOCALE'), 'pidof']
+ pids = subprocess.check_output(['sudo', 'LC_ALL=' + S.getValue('DEFAULT_CMD_LOCALE'), 'pidof']
+ proc_names_list)
except subprocess.CalledProcessError:
# such process isn't running
@@ -160,3 +166,92 @@ def get_pid(proc_name_str):
with given name is not running
"""
return get_pids([proc_name_str])
+
+# This function uses long switch per purpose, so let us suppress pylint warning too-many-branches
+# pylint: disable=R0912
+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' : os.path.join(S.getValue('OVS_DIR'), 'include/openvswitch/version.h'),
+ 'dpdk' : os.path.join(S.getValue('RTE_SDK'), 'lib/librte_eal/common/include/rte_version.h'),
+ 'qemu' : os.path.join(S.getValue('QEMU_DIR'), 'VERSION'),
+ 'l2fwd' : os.path.join(S.getValue('ROOT_DIR'), 'src/l2fwd/l2fwd.c'),
+ 'ixnet' : os.path.join(S.getValue('TRAFFICGEN_IXNET_LIB_PATH'), 'pkgIndex.tcl')
+ }
+
+
+ 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
+
+
+ app_version = None
+ app_git_tag = None
+
+ if app_name.lower().startswith('ovs'):
+ app_version = match_line(app_version_file['ovs'], '#define OVS_PACKAGE_VERSION')
+ if app_version:
+ app_version = app_version.split('"')[1]
+ app_git_tag = get_git_tag(S.getValue('OVS_DIR'))
+ elif app_name.lower() in ['dpdk', 'testpmd']:
+ tmp_ver = ['', '', '']
+ found = False
+ with open(app_version_file['dpdk']) as file_:
+ for line in file_:
+ if not line.strip():
+ continue
+ if line.startswith('#define RTE_VER_MAJOR'):
+ found = True
+ tmp_ver[0] = line.rstrip('\n').split(' ')[2]
+ if line.startswith('#define RTE_VER_MINOR'):
+ found = True
+ tmp_ver[1] = line.rstrip('\n').split(' ')[2]
+ if line.startswith('#define RTE_VER_PATCH_LEVEL'):
+ found = True
+ tmp_ver[2] = line.rstrip('\n').split(' ')[2]
+
+ if found:
+ app_version = '.'.join(tmp_ver)
+ app_git_tag = get_git_tag(S.getValue('RTE_SDK'))
+ elif app_name.lower().startswith('qemu'):
+ app_version = match_line(app_version_file['qemu'], '')
+ app_git_tag = get_git_tag(S.getValue('QEMU_DIR'))
+ 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() == '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[app_name], 'MODULE_VERSION')
+ if app_version:
+ app_version = app_version.split('"')[1]
+ app_git_tag = get_git_tag(app_version_file[app_name])
+ 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}
diff --git a/vnfs/qemu/qemu.py b/vnfs/qemu/qemu.py
index bf7b1a90..83eea679 100644
--- a/vnfs/qemu/qemu.py
+++ b/vnfs/qemu/qemu.py
@@ -1,4 +1,4 @@
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -200,7 +200,8 @@ class IVnfQemu(IVnf):
"""
# set guest loopback application based on VNF configuration
# cli option take precedence to config file values
- guest_loopback = get_test_param('guest_loopback', S.getValue('GUEST_LOOPBACK')[self._number])
+ guest_loopback = S.getValue('GUEST_LOOPBACK')[self._number]
+
if guest_loopback == 'testpmd':
self._login()
self._configure_testpmd()
diff --git a/vsperf b/vsperf
index 62c905c3..53699104 100755
--- a/vsperf
+++ b/vsperf
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@ import locale
sys.dont_write_bytecode = True
from conf import settings
+from conf import get_test_param
from core.loader import Loader
from testcases import TestCase
from tools import tasks
@@ -358,6 +359,14 @@ def main():
logging.error('The selected Duration is not a number')
sys.exit(1)
+ # update global settings
+ guest_loopback = get_test_param('guest_loopback', None)
+ if guest_loopback:
+ tmp_gl = []
+ for i in range(len(settings.getValue('GUEST_LOOPBACK'))):
+ tmp_gl.append(guest_loopback)
+ settings.setValue('GUEST_LOOPBACK', tmp_gl)
+
# generate results directory name
date = datetime.datetime.fromtimestamp(time.time())
results_dir = "results_" + date.strftime('%Y-%m-%d_%H-%M-%S')