diff options
121 files changed, 4565 insertions, 309 deletions
@@ -46,6 +46,63 @@ It is for macOS uses TLS instead of OpenSSL and no header files supported. The s # export LDFLAGS='-L $openssl_install_path/lib' ``` +### Third Party Code + +QTIP includes a few third party code via [subrepo](https://github.com/ingydotnet/git-subrepo). +All third party code are stored in `/third-party`. + +To pull the changes from remote repository, use + +``` +git subrepo pull third-party/<subdir> +``` + +It will create a new commit in parent repo, i.e. `qtip`. However, the +auto generated commit message does not include mandatory tags such as +`Change-Id` required by gerrit. You need to manually amend the commit to +append those. + +``` +git commit --amend -s +``` + +Example of final commit message + +``` +Include third party script for license checking and amending +The following commit message are generated automatically by git-subrepo +----------------------------------------------------------------------------- +git subrepo clone git@github.com:openzero-zte/License.git third-party/License + +subrepo: + subdir: "third-party/License" + merged: "61489da" +upstream: + origin: "git@github.com:openzero-zte/License.git" + branch: "master" + commit: "61489da" +git-subrepo: + version: "0.3.0" + origin: "https://github.com/ingydotnet/git-subrepo" + commit: "988f8c8" +----------------------------------------------------------------------------- +Change-Id: I8eab86a8ce3f26995af3e3535f31f361b4826a8b +Signed-off-by: Yujun Zhang <zhang.yujunz@zte.com.cn> +``` + +Sometimes you may modify the third-party code to adapt it in `qtip`. +To push the changes to remote repository, run + +``` +git subrepo push third-party/<subdir> +``` + +If you want to include a new repository of third party code. Use + +``` +git subrepo clone <remote-url> [<subdir>] +``` + ## Architecture **TODO**: move to design spec @@ -94,7 +151,23 @@ TBD ### CLI -TBD +Click currently supports Bash completion. The prerequisite for this is that the program +needs to be installed correctly. To install Qtip, execute the following command in root +folder of Qtip: + +``` +cd <project root> +pip install -e . +``` + +Once the installation has been completed successfully, the following needs to be added to +the `.bashrc` file: + +``` +eval "$(_QTIP_COMPLETE=source qtip)" +``` + +The above would activate command completion for Qtip. ### API diff --git a/benchmarks/QPI/compute.yaml b/benchmarks/QPI/compute.yaml new file mode 100644 index 00000000..78a2d324 --- /dev/null +++ b/benchmarks/QPI/compute.yaml @@ -0,0 +1,37 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +title: compute +description: sample performance index of computing +formula: weighted arithmetic mean +sections: +- name: Integer + weight: 0.3 + formula: geometric mean + metrics: + - dhrystone.yaml +- name: Float + weight: 0.3 + formula: geometric mean + metrics: + - whetstone.yaml +- name: Memory + weight: 0.2 + formula: geometric mean + metrics: + - ramspeed.yaml +- name: DPI + weight: 0.1 + formula: geometric mean + metrics: + - dpi.yaml +- name: SSL + weight: 0.1 + formula: geometric mean + metrics: + - ssl.yaml diff --git a/benchmarks/metric/dhrystone.yaml b/benchmarks/metric/dhrystone.yaml new file mode 100644 index 00000000..e4d26248 --- /dev/null +++ b/benchmarks/metric/dhrystone.yaml @@ -0,0 +1,17 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +name: dhrystone +description: > + A synthetic computing benchmark program intended to be representative of + system (integer) programming. +links: + - https://en.wikipedia.org/wiki/Dhrystone +workloads: + - single_cpu + - multi_cpu diff --git a/qtip/driver/sample.py b/benchmarks/metric/dpi.yaml index 9b347949..c90075d2 100644 --- a/qtip/driver/sample.py +++ b/benchmarks/metric/dpi.yaml @@ -1,15 +1,13 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2016 ZTE Corporation and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - - -from base import BaseDriver - - -class SampleDriver(BaseDriver): - """sample driver that generates random data for testing""" +name: dpi +description: deep packet inspection +workloads: + - bps + - pps diff --git a/benchmarks/metric/ramspeed.yaml b/benchmarks/metric/ramspeed.yaml new file mode 100644 index 00000000..e2e2b98f --- /dev/null +++ b/benchmarks/metric/ramspeed.yaml @@ -0,0 +1,13 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +name: ramspeed +description: a memory performance benchmarking +workloads: + - int: [add, average, copy, scale, triad] + - float: [add, average, copy, scale, triad] diff --git a/benchmarks/metric/ssl.yaml b/benchmarks/metric/ssl.yaml new file mode 100644 index 00000000..2b01dccd --- /dev/null +++ b/benchmarks/metric/ssl.yaml @@ -0,0 +1,13 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +name: ssl +description: a Secure Sockets Layer performance benchmarking +workloads: + - aes_128_cbc: [512, 1024, 2048, 4096] + - rsa_sig: [16, 64, 256, 1024, 8192] diff --git a/benchmarks/metric/whetstone.yaml b/benchmarks/metric/whetstone.yaml new file mode 100644 index 00000000..625ea87f --- /dev/null +++ b/benchmarks/metric/whetstone.yaml @@ -0,0 +1,18 @@ +############################################################################## +# Copyright (c) 2016 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +name: whetstone +description: > + A synthetic benchmark for evaluating the performance of computers. + The Whetstone benchmark primarily measures the floating-point arithmetic + performance. +links: + - https://en.wikipedia.org/wiki/Whetstone_(benchmark) +workloads: + - single_cpu + - multi_cpu diff --git a/benchmarks/plan/compute.yaml b/benchmarks/plan/compute.yaml new file mode 100644 index 00000000..f4a7a2dc --- /dev/null +++ b/benchmarks/plan/compute.yaml @@ -0,0 +1,120 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +name: compute QPI +description: compute QPI profile +info: + facility: local + engineer: local +config: + driver: ansible + collectors: + - type: logfile + paths: + - '../../external/dpi/' + logs: + - filename: dpi_dump.txt + parsers: + - type: grep + regex: |- + ^\s+nDPI throughput:.+?(?P<pps>\d+.\d+)\sM\spps.+ + ?(?P<bps>\d+.\d+)\sGb\/sec + - type: logfile + paths: + - '../../external/ramspeed/' + logs: + - filename: Intmem + parsers: + - type: grep + regex: '^INTEGER\s+BatchRun\s+Copy:\s+?(?P<integer_copy>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Scale:\s+?(?P<integer_scale>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Add:\s+?(?P<integer_add>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Triad:\s+?(?P<integer_triad>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+AVERAGE:\s+?(?P<integer_average>\d+\.\d+)\sMB/s$' + - filename: Floatmem + parsers: + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Copy:\s+?(?P<float_copy>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Scale:\s+?(?P<float_scale>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Add:\s+?(?P<float_add>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Triad:\s+?(?P<float_triad>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+AVERAGE:\s+?(?P<float_average>\d+\.\d+)\sMB/s$' + - type: logfile + paths: + - '../../external/ssl/' + logs: + - filename: RSA_dump + parsers: + - type: grep + regex: |- + ^rsa\s+512\sbits\s.+ + ?(?P<rsa_sign_512>\d+\.\d)\s+ + ?(?P<rsa_verify_512>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+1024\sbits\s.+ + ?(?P<rsa_sign_1024>\d+\.\d)\s+ + ?(?P<rsa_verify_1024>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+2048\sbits\s.+ + ?(?P<rsa_sign_2048>\d+\.\d)\s+ + ?(?P<rsa_verify_2048>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+4096\sbits\s.+ + ?(?P<rsa_sign_4096>\d+\.\d)\s+ + ?(?P<rsa_verify_4096>\d+\.\d)$ + - filename: AES-128-CBC_dump + parsers: + - type: grep + regex: |- + ^aes-128-cbc\s+ + ?(?P<aes_128_cbc_16_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_64_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_256_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_1024_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_8192_bytes>\d+\.\w+)$ + - type: logfile + paths: + - '../../external/sysinfo' + logs: + - filename: top.log + parsers: + - type: grep + regex: 'Cpu\(s\):.+?(?P<cpu_idle>\d+\.\d)\sid' + - filename: inxi.log + parsers: + - type: grep + regex: '.+\s+Host:\s+(?P<hostname>.+)\sKernel' + - type: grep + regex: '.+\sMemory:\s+(?P<memory>.+MB)\s' + - type: grep + regex: '^CPU\(s\):\s+(?P<cpu>.+)' + - type: grep + regex: '.+\sDistro:\s+(?P<os>.+)' + - type: grep + regex: '.+\sKernel:\s+(?P<kernel>.+)\sConsole' + - type: grep + regex: '.+\s+HDD Total Size:\s+(?P<disk>.+)\s' + - type: grep + regex: '.+\sproduct:\s+(?P<product>.+)\sversion' + reporter: + name: console + # transform collected data into timeline + transformer: timeline +QPIs: + - compute.yaml diff --git a/qtip/driver/yardstick.py b/benchmarks/plan/sample.yaml index 83f1b3d8..04e8caf9 100644 --- a/qtip/driver/yardstick.py +++ b/benchmarks/plan/sample.yaml @@ -1,14 +1,14 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 ZTE Corporation and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -from base import BaseDriver - - -class YardstickDriver(BaseDriver): - """driver for running performance test with yardstick""" +name: sample +description: sample benchmark plan for testing default path +config: + collectors: [] + reporters: [] +QPIs: [] diff --git a/collector/2017-03-16-20-07/result.json b/collector/2017-03-16-20-07/result.json new file mode 100644 index 00000000..d26ad400 --- /dev/null +++ b/collector/2017-03-16-20-07/result.json @@ -0,0 +1,265 @@ +{ + "plan_name": "compute_qpi", + "start_time": "2017-03-11-03-14", + "stop_time": "2017-03-11-03-32", + "sut": [ + { + "name": "node-41", + "qpis": [ + { + "benchmarks": [ + { + "name": "ssl", + "cpu_usage": "3%", + "results": { + "aes_128_cbc_1024_bytes": "584709.80k", + "aes_128_cbc_16_bytes": "531050.51k", + "aes_128_cbc_256_bytes": "584951.30k", + "aes_128_cbc_64_bytes": "571063.66k", + "aes_128_cbc_8192_bytes": "584723.11k", + "rsa_sign_1024": "2.6", + "rsa_sign_2048": "9.9", + "rsa_sign_4096": "1.7", + "rsa_sign_512": "0.5", + "rsa_verify_1024": "101616.4", + "rsa_verify_2048": "31104.1", + "rsa_verify_4096": "7688.5", + "rsa_verify_512": "257411.2" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1199/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-41.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4449.9/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "ramspeed", + "cpu_usage": "3%", + "results": { + "float_add": "10217.62", + "float_average": "9176.88", + "float_copy": "8127.13", + "float_scale": "8085.40", + "float_triad": "10277.38", + "integer_add": "11471.63", + "integer_average": "11396.35", + "integer_copy": "11297.18", + "integer_scale": "11316.86", + "integer_triad": "11499.74" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1200/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-41.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4388.3/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "whetstone", + "cpu_usage": "3%", + "results": { + "multi_cpus": { + "num": "40", + "score": "21198.3" + }, + "single_cpu": { + "num": "1", + "score": "633.2" + }, + "total_cpus": "40" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1393/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-41.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4390.1/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "dpi", + "cpu_usage": "3%", + "results": { + "bps": 3.638, + "pps": 1.45 + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1199/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-41.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4409.8/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "dhrystone", + "cpu_usage": "3%", + "results": { + "multi_cpus": { + "num": "40", + "score": "63529.6" + }, + "single_cpu": { + "num": "1", + "score": "2981.5" + }, + "total_cpus": "40" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1199/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-41.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4390.9/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + } + ], + "name": "compute_qpi" + } + ], + "type": "baremetal" + }, + { + "name": "node-38", + "qpis": [ + { + "benchmarks": [ + { + "name": "ssl", + "cpu_usage": "3%", + "results": { + "aes_128_cbc_1024_bytes": "654325.42k", + "aes_128_cbc_16_bytes": "602261.15k", + "aes_128_cbc_256_bytes": "663959.64k", + "aes_128_cbc_64_bytes": "650967.68k", + "aes_128_cbc_8192_bytes": "667303.94k", + "rsa_sign_1024": "6.8", + "rsa_sign_2048": "8.8", + "rsa_sign_4096": "7.1", + "rsa_sign_512": "8.5", + "rsa_verify_1024": "100088.3", + "rsa_verify_2048": "31316.4", + "rsa_verify_4096": "8551.8", + "rsa_verify_512": "252476.3" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1199/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-38.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4403.7/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "ramspeed", + "cpu_usage": "3%", + "results": { + "float_add": "10522.33", + "float_average": "9465.11", + "float_copy": "8434.94", + "float_scale": "8436.36", + "float_triad": "10466.82", + "integer_add": "11489.06", + "integer_average": "11466.52", + "integer_copy": "11398.52", + "integer_scale": "11413.87", + "integer_triad": "11564.61" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1200/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-38.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4402.9/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "whetstone", + "cpu_usage": "3%", + "results": { + "multi_cpus": { + "num": "40", + "score": "21194.7" + }, + "single_cpu": { + "num": "1", + "score": "676.6" + }, + "total_cpus": "40" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1200/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-38.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4405.5/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "dpi", + "cpu_usage": "3%", + "results": { + "bps": 3.69, + "pps": 1.458 + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1200/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-38.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4418.2/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + }, + { + "name": "dhrystone", + "cpu_usage": "3%", + "results": { + "multi_cpus": { + "num": "40", + "score": "63834.1" + }, + "single_cpu": { + "num": "1", + "score": "3026.2" + }, + "total_cpus": "40" + }, + "sysinfo": { + "cpu": "2 Deca core Intel Xeon E5-2650 v3s (-HT-MCP-SMP-) speed/max: 1200/3000 MHz", + "disk": "1200.3GB (1.0% used)", + "hostname": "node-38.zte.com.cn", + "kernel": "4.4.0-62-generic x86_64 (64 bit)", + "memory": "4404.9/128524.1MB", + "os": "Ubuntu 16.04 xenial", + "product": "EC600G3" + } + } + ], + "name": "compute_qpi" + } + ], + "type": "baremetal" + } + ] +} diff --git a/collector/timeline.json b/collector/timeline.json new file mode 100644 index 00000000..dea929e7 --- /dev/null +++ b/collector/timeline.json @@ -0,0 +1,39 @@ +{ + "phases": [{ + "name": "Monitor", + "checkpoints": [{ + "name": "T00", + "timestamp": "1" + }] + }, { + "name": "Inspector", + "checkpoints": [{ + "name": "T01", + "timestamp": "2" + }, { + "name": "T02 ", + "timestamp": "5" + }, { + "name": "T03 ", + "timestamp": "8" + }] + }, { + "name": "Controller", + "checkpoints": [{ + "name": "T04", + "timestamp": "11" + }] + }, { + "name": "Notifier", + "checkpoints": [{ + "name": "T05 ", + "timestamp": "16" + }] + }, { + "name": "Evaluator", + "checkpoints": [{ + "name": "T06 ", + "timestamp": "40" + }] + }] +} diff --git a/docker/Dockerfile b/docker/Dockerfile index f2a543e6..d609273d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -22,6 +22,9 @@ RUN apt-get update && apt-get install -y \ gcc \ ssh \ expect \ + build-essential\ + libssl-dev\ + libffi-dev\ python-matplotlib \ python-dev \ python-pip \ @@ -32,6 +35,8 @@ RUN apt-get update && apt-get install -y \ curl \ supervisor \ python-setuptools \ + iputils-ping\ + rsync \ --no-install-recommends \ && rm -rf /var/lib/apt/lists/* @@ -50,14 +55,14 @@ RUN mkdir -p $HOME/qtip/results RUN chmod 700 /root/.ssh #Config ansible -COPY ansible.cfg.default /root/.ansible.cfg +COPY ansible.cfg.default $HOME/.ansible.cfg #Cloning Repos RUN git config --global http.sslVerify false RUN git clone -b $BRANCH https://gerrit.opnfv.org/gerrit/qtip $REPOS_DIR/qtip RUN git clone https://gerrit.opnfv.org/gerrit/releng $REPOS_DIR/releng -RUN pip install -r $REPOS_DIR/qtip/requirements.txt +RUN pip install -U -r $REPOS_DIR/qtip/requirements.txt #Config supervisor RUN mkdir -p /var/log/supervisor diff --git a/docker/Dockerfile.aarch64.patch b/docker/Dockerfile.aarch64.patch new file mode 100644 index 00000000..80529476 --- /dev/null +++ b/docker/Dockerfile.aarch64.patch @@ -0,0 +1,33 @@ +From: Cristina Pauna <cristina.pauna@enea.com> +Date: Mon, 13 Mar 2017 11:56:59 +0200 +Subject: [PATCH] Modify Dockerfile to build an aarch64 image + +This patch adapts the Dockerfile so that the qtip image +can be build on an aarch64 machine + +Signed-off-by: Cristina Pauna <cristina.pauna@enea.com> +--- + docker/Dockerfile | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/docker/Dockerfile b/docker/Dockerfile +index a4a7e47..5d4467b 100644 +--- a/docker/Dockerfile ++++ b/docker/Dockerfile +@@ -1,10 +1,10 @@ +-########################################## +-#####Docker container for QTIP############ +-########################################## ++################################################### ++##### AArch64 Docker container for QTIP############ ++################################################### + +-FROM ubuntu:16.04 +-MAINTAINER Yujun Zhang <zhang.yujunz@zte.com.cn> +-LABEL version="0.1" description="OPNFV QTIP Docker container" ++FROM aarch64/ubuntu:16.04 ++MAINTAINER Armband team <armband@enea.com> ++LABEL version="0.1" description="OPNFV QTIP AArch64 Docker container" + + ARG BRANCH=master + diff --git a/docs/release/release-notes/index.rst b/docs/release/release-notes/index.rst index 5d045388..3864c451 100644 --- a/docs/release/release-notes/index.rst +++ b/docs/release/release-notes/index.rst @@ -1,3 +1,5 @@ +.. _qtip-releasenotes: + .. This work is licensed under a Creative Commons Attribution 4.0 International License. .. http://creativecommons.org/licenses/by/4.0 .. (c) 2015 Dell Inc. diff --git a/docs/development/design/apidocs/index.rst b/docs/testing/developer/design/apidocs/index.rst index 241a2680..241a2680 100644 --- a/docs/development/design/apidocs/index.rst +++ b/docs/testing/developer/design/apidocs/index.rst diff --git a/docs/development/design/apidocs/qtip_restful_api.rst b/docs/testing/developer/design/apidocs/qtip_restful_api.rst index 06c01292..06c01292 100644 --- a/docs/development/design/apidocs/qtip_restful_api.rst +++ b/docs/testing/developer/design/apidocs/qtip_restful_api.rst diff --git a/docs/testing/developer/design/cli.rst b/docs/testing/developer/design/cli.rst new file mode 100644 index 00000000..72d1fbaf --- /dev/null +++ b/docs/testing/developer/design/cli.rst @@ -0,0 +1,92 @@ +*************************** +QTIP Command Line Interface +*************************** + +Abstract +######## + +QTIP consists of different tools(metrics) to benchmark the NFVI. These metrics fall under different NFVI +subsystems(QPI's) such as compute, storage and network. A plan consists of one or more QPI's, depending upon how +the end user would want to measure performance. CLI is designed to help the user, execute benchmarks and +view respective scores. + +Framework +========= + +QTIP CLI has been created using the Python package `Click`_, Command Line Interface Creation Kit. It has been +chosen for number of reasons. It presents the user with a very simple yet powerful API to build complex +applications. One of the most striking features is command nesting. + +As explained, QTIP consists of metrics, QPI's and plans. CLI is designed to provide interface to all +these components. It is responsible for execution, as well as provide listing and details of each individual +element making up these components. + +Design +====== + +CLI's entry point extends Click's built in MultiCommand class object. It provides two methods, which are +overridden to provide custom configurations. + +.. code-block:: python + + class QtipCli(click.MultiCommand): + + def list_commands(self, ctx): + rv = [] + for filename in os.listdir(cmd_folder): + if filename.endswith('.py') and \ + filename.startswith('cmd_'): + rv.append(filename[4:-3]) + rv.sort() + return rv + + def get_command(self, ctx, name): + try: + if sys.version_info[0] == 2: + name = name.encode('ascii', 'replace') + mod = __import__('qtip.cli.commands.cmd_' + name, + None, None, ['cli']) + except ImportError: + return + return mod.cli + +Commands and subcommands will then be loaded by the ``get_command`` method above. + +Extending the Framework +======================= + +Framework can be easily extended, as per the users requirements. One such example can be to override the builtin +configurations with user defined ones. These can be written in a file, loaded via a Click Context and passed +through to all the commands. + +.. code-block:: python + + class Context: + + def __init__(): + + self.config = ConfigParser.ConfigParser() + self.config.read('path/to/configuration_file') + + def get_paths(): + + paths = self.config.get('section', 'path') + return paths + +The above example loads configuration from user defined paths, which then need to be provided to the actual +command definitions. + +.. code-block:: python + + from qtip.cli.entry import Context + + pass_context = click.make_pass_decorator(Context, ensure=False) + + @cli.command('list', help='List the Plans') + @pass_context + def list(ctx): + plans = Plan.list_all(ctx.paths()) + table = utils.table('Plans', plans) + click.echo(table) + +.. _Click: http://click.pocoo.org/5/ diff --git a/docs/development/design/compute_QPI.rst b/docs/testing/developer/design/compute_QPI.rst index 2e5aa87c..2e5aa87c 100644 --- a/docs/development/design/compute_QPI.rst +++ b/docs/testing/developer/design/compute_QPI.rst diff --git a/docs/development/design/dashboard.rst b/docs/testing/developer/design/dashboard.rst index 60c4720d..60c4720d 100644 --- a/docs/development/design/dashboard.rst +++ b/docs/testing/developer/design/dashboard.rst diff --git a/docs/development/design/index.rst b/docs/testing/developer/design/index.rst index b6dd0c01..b6dd0c01 100644 --- a/docs/development/design/index.rst +++ b/docs/testing/developer/design/index.rst diff --git a/docs/development/design/integration_with_yardstick.rst b/docs/testing/developer/design/integration_with_yardstick.rst index a8298d6f..a8298d6f 100644 --- a/docs/development/design/integration_with_yardstick.rst +++ b/docs/testing/developer/design/integration_with_yardstick.rst diff --git a/docs/development/overview/.gitkeep b/docs/testing/developer/overview/.gitkeep index e69de29b..e69de29b 100644 --- a/docs/development/overview/.gitkeep +++ b/docs/testing/developer/overview/.gitkeep diff --git a/docs/development/requirement/.gitkeep b/docs/testing/developer/requirement/.gitkeep index e69de29b..e69de29b 100644 --- a/docs/development/requirement/.gitkeep +++ b/docs/testing/developer/requirement/.gitkeep diff --git a/docs/release/installation/.gitkeep b/docs/testing/user/.gitkeep index e69de29b..e69de29b 100644 --- a/docs/release/installation/.gitkeep +++ b/docs/testing/user/.gitkeep diff --git a/docs/release/configguide/configuration.rst b/docs/testing/user/configguide/configuration.rst index 78e96492..78e96492 100644 --- a/docs/release/configguide/configuration.rst +++ b/docs/testing/user/configguide/configuration.rst diff --git a/docs/release/configguide/index.rst b/docs/testing/user/configguide/index.rst index d5e05d63..d5e05d63 100644 --- a/docs/release/configguide/index.rst +++ b/docs/testing/user/configguide/index.rst diff --git a/docs/release/scenarios/.gitkeep b/docs/testing/user/installation/.gitkeep index e69de29b..e69de29b 100644 --- a/docs/release/scenarios/.gitkeep +++ b/docs/testing/user/installation/.gitkeep diff --git a/qtip/driver/ansible/__init__.py b/docs/testing/user/scenarios/.gitkeep index e69de29b..e69de29b 100644 --- a/qtip/driver/ansible/__init__.py +++ b/docs/testing/user/scenarios/.gitkeep diff --git a/docs/release/userguide/_01-compute.rst b/docs/testing/user/userguide/_01-compute.rst index 56be5488..56be5488 100644 --- a/docs/release/userguide/_01-compute.rst +++ b/docs/testing/user/userguide/_01-compute.rst diff --git a/docs/release/userguide/_02-network.rst b/docs/testing/user/userguide/_02-network.rst index 00fe5b0a..00fe5b0a 100644 --- a/docs/release/userguide/_02-network.rst +++ b/docs/testing/user/userguide/_02-network.rst diff --git a/docs/release/userguide/_03-storage.rst b/docs/testing/user/userguide/_03-storage.rst index b1490432..b1490432 100644 --- a/docs/release/userguide/_03-storage.rst +++ b/docs/testing/user/userguide/_03-storage.rst diff --git a/docs/release/userguide/_testcase_description.rst b/docs/testing/user/userguide/_testcase_description.rst index d60ca949..d60ca949 100644 --- a/docs/release/userguide/_testcase_description.rst +++ b/docs/testing/user/userguide/_testcase_description.rst diff --git a/docs/release/userguide/annex.rst b/docs/testing/user/userguide/annex.rst index e8bf5555..e8bf5555 100644 --- a/docs/release/userguide/annex.rst +++ b/docs/testing/user/userguide/annex.rst diff --git a/docs/release/userguide/benchmark-suites.rst b/docs/testing/user/userguide/benchmark-suites.rst index 84d1c647..84d1c647 100644 --- a/docs/release/userguide/benchmark-suites.rst +++ b/docs/testing/user/userguide/benchmark-suites.rst diff --git a/docs/testing/user/userguide/cli.rst b/docs/testing/user/userguide/cli.rst new file mode 100644 index 00000000..e18a36f9 --- /dev/null +++ b/docs/testing/user/userguide/cli.rst @@ -0,0 +1,38 @@ +************** +QTIP CLI Usage +************** + +QTIP consists of a number of benchmarking tools or metrics, grouped under QPI's. QPI's map to the different +components of a NFVI ecosystem, such as compute, network and storage. Depending on the type of application, +a user may group them under plans. + +QTIP CLI provides interface to all of the above the components. A help page provides a list of all the commands +along with a short description. +:: + + qtip [-h|--help] + +Typically a complete plan is executed at the +target environment. QTIP defaults to a number of sample plans. One may be able to list them using +:: + + qtip plan list + +One can also be able to view the details about a specific plan. +:: + + qtip plan show <plan_name> + +where *plan_name* is one of those listed from the previous command. + +To execute a complete plan +:: + + qtip plan run <plan_name> + +Similarly, the same commands can be used for the other two components making up the plans, i.e QPI's and metrics. + +Debug option helps identify the error by providing a detailed traceback. It can be enabled as +:: + + qtip [-d|--debug] plan run <plan_name> diff --git a/docs/release/userguide/index.rst b/docs/testing/user/userguide/index.rst index 4be3e498..4be3e498 100644 --- a/docs/release/userguide/index.rst +++ b/docs/testing/user/userguide/index.rst diff --git a/docs/release/userguide/introduction.rst b/docs/testing/user/userguide/introduction.rst index 3147f0aa..3147f0aa 100644 --- a/docs/release/userguide/introduction.rst +++ b/docs/testing/user/userguide/introduction.rst diff --git a/legacy/assets/perftest/etc/dpi_average.sh b/legacy/assets/perftest/etc/dpi_average.sh deleted file mode 100644 index 405d3ff6..00000000 --- a/legacy/assets/perftest/etc/dpi_average.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -COUNTER=0 -WDIR=$PWD -while [ $COUNTER -lt 10 ]; do - - echo $WDIR - $( ./ndpiReader -i test.pcap >> $WDIR/dpi_dump.txt ) - let COUNTER=COUNTER+1 - echo "Run number: $COUNTER" - -done - - diff --git a/opt/infra/roles/qtip/files/run_qtip_server.sh b/opt/infra/roles/qtip/files/run_qtip_server.sh index 0f5cafea..75145e2b 100644 --- a/opt/infra/roles/qtip/files/run_qtip_server.sh +++ b/opt/infra/roles/qtip/files/run_qtip_server.sh @@ -1,4 +1,24 @@ #!/bin/bash envs="INSTALLER_TYPE=fuel -e INSTALLER_IP=10.20.0.2 -e NODE_NAME=zte-pod1" -docker run --name qtip -id -e $envs -p 5000:5000 opnfv/qtip + +# use ramfs to fix docker socket connection issue with overlay mode in centos +ramfs=/tmp/qtip/ramfs +if [ ! -d $ramfs ]; then + mkdir -p $ramfs +fi + +if [ ! -z $(df $ramfs | tail -n -1 | grep $ramfs) ]; then + sudo mount -t tmpfs -o size=32M tmpfs $ramfs +fi + +# enable contro path in docker +echo <<EOF > /tmp/ansible.cfg +[defaults] +callback_whitelist = profile_tasks +[ssh_connection] +control_path=/mnt/ramfs/ansible-ssh-%%h-%%p-%%r +EOF + +docker run --name qtip -id -e $envs -p 5000:5000 -v $ramfs:/mnt/ramfs opnfv/qtip +docker cp qtip /tmp/ansible.cfg /home/opnfv/.ansible.cfg diff --git a/qtip/api/__main__.py b/qtip/api/__main__.py index 89298e6d..381622af 100644 --- a/qtip/api/__main__.py +++ b/qtip/api/__main__.py @@ -1,10 +1,28 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + import connexion +import os + + +swagger_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'swagger/')) + + +def get_app(): + app = connexion.App(__name__, specification_dir=swagger_dir) + app.add_api('swagger.yaml', base_path='/v1.0', strict_validation=True) + return app def main(): - app = connexion.App(__name__, specification_dir='swagger/') - app.add_api('swagger.yaml', base_path='/v1.0') - app.run(host='0.0.0.0', port='5000') + app = get_app() + app.run(host="0.0.0.0", port=5000) if __name__ == '__main__': diff --git a/qtip/api/controllers/common.py b/qtip/api/controllers/common.py new file mode 100644 index 00000000..6ddab7a9 --- /dev/null +++ b/qtip/api/controllers/common.py @@ -0,0 +1,35 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib + +import connexion + +from qtip.base import error + + +def check_endpoint_for_error(resource, operation=None): + def _decorator(func): + def _execute(name=None): + try: + return func(name), httplib.OK + except error.NotFoundError: + return connexion.problem( + httplib.NOT_FOUND, + '{} not found'.format(resource), + 'Requested {} `{}` not found.' + .format(resource.lower(), name)) + except error.ToBeDoneError: + return connexion.problem( + httplib.NOT_IMPLEMENTED, + '{} handler not implemented'.format(operation), + 'Requested operation `{}` on {} not implemented.' + .format(operation.lower(), resource.lower())) + return _execute + return _decorator diff --git a/qtip/api/controllers/metric.py b/qtip/api/controllers/metric.py new file mode 100644 index 00000000..96cd985c --- /dev/null +++ b/qtip/api/controllers/metric.py @@ -0,0 +1,25 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib + +from qtip.api.controllers import common +from qtip.loader import metric + + +def list_metrics(): + metrics = list(metric.MetricSpec.list_all()) + metrics_by_name = [m['name'] for m in metrics] + return {'metrics': metrics_by_name}, httplib.OK + + +@common.check_endpoint_for_error(resource='Metric') +def get_metric(name): + metric_spec = metric.MetricSpec(name) + return metric_spec.content diff --git a/qtip/api/controllers/plan.py b/qtip/api/controllers/plan.py new file mode 100644 index 00000000..00593878 --- /dev/null +++ b/qtip/api/controllers/plan.py @@ -0,0 +1,31 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib + +from qtip.api.controllers import common +from qtip.base import error +from qtip.loader import plan + + +def list_plans(): + plans = list(plan.Plan.list_all()) + plans_by_name = [p['name'] for p in plans] + return {'plans': plans_by_name}, httplib.OK + + +@common.check_endpoint_for_error(resource='Plan') +def get_plan(name): + plan_spec = plan.Plan(name) + return plan_spec.content + + +@common.check_endpoint_for_error(resource='Plan', operation='Run') +def run_plan(name, action="run"): + raise error.ToBeDoneError('run_plan', 'plan') diff --git a/qtip/api/controllers/qpi.py b/qtip/api/controllers/qpi.py new file mode 100644 index 00000000..af08a824 --- /dev/null +++ b/qtip/api/controllers/qpi.py @@ -0,0 +1,25 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib + +from qtip.api.controllers import common +from qtip.loader import qpi + + +def list_qpis(): + qpi_specs = list(qpi.QPISpec.list_all()) + qpis_by_name = [q['name'] for q in qpi_specs] + return {'qpis': qpis_by_name}, httplib.OK + + +@common.check_endpoint_for_error(resource='QPI') +def get_qpi(name): + qpi_spec = qpi.QPISpec(name) + return qpi_spec.content diff --git a/qtip/api/swagger/swagger.yaml b/qtip/api/swagger/swagger.yaml index 97a9c352..51c3ebb8 100644 --- a/qtip/api/swagger/swagger.yaml +++ b/qtip/api/swagger/swagger.yaml @@ -1,9 +1,302 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + swagger: '2.0' info: title: QTIP-API + version: "1.0" consumes: - application/json produces: - application/json paths: - #TODO (akhil) add paths
\ No newline at end of file + /plans: + get: + summary: List all plans + operationId: qtip.api.controllers.plan.list_plans + tags: + - Plan + - Standalone + responses: + 200: + description: A list of plans + schema: + type: array + items: + $ref: '#/definitions/Plans' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /plans/{name}: + get: + summary: Get a plan by plan name + operationId: qtip.api.controllers.plan.get_plan + tags: + - Plan + - Standalone + parameters: + - name: name + in: path + description: Plan name + required: true + type: string + responses: + 200: + description: Plan information + schema: + $ref: '#/definitions/Plan' + 404: + description: Plan not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + post: + summary: Run a plan and return results + operationId: qtip.api.controllers.plan.run_plan + tags: + - Plan + - Standalone + parameters: + - name: name + in: path + description: Plan name + required: true + type: string + - name: action + in: query + description: action for a plan + required: true + type: string + responses: + 200: + description: Result of the run of the plan + #TODO (akhil) define schema + 404: + description: Plan not found + schema: + $ref: '#/definitions/Error' + 400: + description: Invalid parameters + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /qpis: + get: + summary: List all QPIs + operationId: qtip.api.controllers.qpi.list_qpis + tags: + - QPI + - Standalone + - Agent + responses: + 200: + description: A list of QPIs + schema: + items: + $ref: '#/definitions/QPIs' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /qpis/{name}: + get: + summary: Get a QPI + operationId: qtip.api.controllers.qpi.get_qpi + tags: + - QPI + - Standalone + - Agent + parameters: + - name: name + in: path + description: QPI name + required: true + type: string + responses: + 200: + description: QPI information + schema: + $ref: '#/definitions/QPI' + 404: + description: QPI not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /metrics: + get: + summary: List all metrics + operationId: qtip.api.controllers.metric.list_metrics + tags: + - Metric + - Standalone + - Agent + responses: + 200: + description: A list of metrics + schema: + items: + $ref: '#/definitions/Metrics' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' + /metrics/{name}: + get: + summary: Get a metric + operationId: qtip.api.controllers.metric.get_metric + tags: + - Metric + - Standalone + - Agent + parameters: + - name: name + in: path + description: Metric name + required: true + type: string + responses: + 200: + description: Metric information + schema: + $ref: '#/definitions/Metric' + 404: + description: Metric not found + schema: + $ref: '#/definitions/Error' + 501: + description: Resource not implemented + schema: + $ref: '#/definitions/Error' + default: + description: Unexpected error + schema: + $ref: '#/definitions/Error' +definitions: + Plan: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + info: + type: object + config: + type: object + QPIs: + type: array + items: + type: object + Plans: + type: object + required: + - plans + properties: + plans: + type: array + items: + type: string + Metric: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + links: + type: array + items: + type: string + workloads: + type: array + items: + type: string + Metrics: + type: object + required: + - metrics + properties: + metrics: + type: array + items: + type: string + QPI: + type: object + required: + - name + properties: + name: + type: string + description: + type: string + formula: + type: string + sections: + type: array + items: + type: object + QPIs: + type: object + required: + - qpis + properties: + qpis: + type: array + items: + type: string + Error: + type: object + properties: + status: + type: integer + format: int32 + title: + type: string + detail: + type: string + type: + type: string
\ No newline at end of file diff --git a/qtip/cli/commands/cmd_metric.py b/qtip/cli/commands/cmd_metric.py index b6035e2d..31b7b702 100644 --- a/qtip/cli/commands/cmd_metric.py +++ b/qtip/cli/commands/cmd_metric.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -9,7 +9,9 @@ import click +from qtip.cli import utils from qtip.cli.entry import Context +from qtip.loader.metric import MetricSpec pass_context = click.make_pass_decorator(Context, ensure=False) @@ -24,14 +26,19 @@ def cli(ctx): @cli.command('list', help='List all the Metric Groups') @pass_context def cmd_list(ctx): - pass + metrics = MetricSpec.list_all() + table = utils.table('Metrics', metrics) + click.echo(table) @cli.command('show', help='View details of a Metric') @click.argument('name') @pass_context def show(ctx, name): - pass + metric = MetricSpec('{}.yaml'.format(name)) + cnt = metric.content + output = utils.render('metric', cnt) + click.echo(output) @cli.command('run', help='Run tests to run Performance Metrics') diff --git a/qtip/cli/commands/cmd_plan.py b/qtip/cli/commands/cmd_plan.py index 64c702d3..90773491 100644 --- a/qtip/cli/commands/cmd_plan.py +++ b/qtip/cli/commands/cmd_plan.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2016 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -10,7 +10,9 @@ import click +from qtip.cli import utils from qtip.cli.entry import Context +from qtip.loader.plan import Plan pass_context = click.make_pass_decorator(Context, ensure=False) @@ -32,14 +34,19 @@ def init(ctx): @cli.command('list', help='List the Plans') @pass_context def list(ctx): - pass + plans = Plan.list_all() + table = utils.table('Plans', plans) + click.echo(table) @cli.command('show', help='View details of a Plan') @click.argument('name') @pass_context def show(ctx, name): - pass + plan = Plan('{}.yaml'.format(name)) + cnt = plan.content + output = utils.render('plan', cnt) + click.echo(output) @cli.command('run', help='Execute a Plan') diff --git a/qtip/cli/commands/cmd_qpi.py b/qtip/cli/commands/cmd_qpi.py index 5fc9bec8..1f23211e 100644 --- a/qtip/cli/commands/cmd_qpi.py +++ b/qtip/cli/commands/cmd_qpi.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -10,7 +10,9 @@ import click +from qtip.cli import utils from qtip.cli.entry import Context +from qtip.loader.qpi import QPISpec pass_context = click.make_pass_decorator(Context, ensure=False) @@ -25,14 +27,19 @@ def cli(ctx): @cli.command('list', help='List all the QPI specs') @pass_context def cmd_list(ctx): - pass + qpis = QPISpec.list_all() + table = utils.table('QPIs', qpis) + click.echo(table) @cli.command('show', help='View details of a QPI') @click.argument('name') @pass_context def show(ctx, name): - pass + qpi = QPISpec('{}.yaml'.format(name)) + cnt = qpi.content + output = utils.render('qpi', cnt) + click.echo(output) @cli.command('run', help='Run performance tests for the specified QPI') diff --git a/qtip/cli/commands/cmd_report.py b/qtip/cli/commands/cmd_report.py new file mode 100644 index 00000000..cb9c70b6 --- /dev/null +++ b/qtip/cli/commands/cmd_report.py @@ -0,0 +1,31 @@ +############################################################################## +# Copyright (c) 2017 taseer94@gmail.com and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import click + +from qtip.cli.entry import Context +from qtip.reporter.console import ConsoleReporter + +pass_context = click.make_pass_decorator(Context, ensure=False) + + +@click.group() +@pass_context +def cli(ctx): + """ View Qtip results""" + pass + + +@cli.command('show') +@click.argument('metric') +@pass_context +def show(ctx, metric): + reporter = ConsoleReporter({}) + report = reporter.render(metric) + click.echo(report) diff --git a/qtip/cli/entry.py b/qtip/cli/entry.py index 9f51f25e..6cf78b58 100644 --- a/qtip/cli/entry.py +++ b/qtip/cli/entry.py @@ -1,5 +1,5 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -7,33 +7,19 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +import click import os import sys -import click CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) +# TODO (taseer) define user friendly error messages +sys.tracebacklimit = 0 -class Context(object): - - ''' TODO(taseer) implementation''' - - def __init__(self): - self.verbose = False - self.debug = False - - def log(self, msg, *args): - ''' Log message to stderr ''' - pass - def verbose(self, msg, *args): - ''' Log message to stderr when verbose ''' - pass - - def debug(self, msg, *args): - ''' Log message to debug ''' - pass +class Context(object): + """ Load configuration and pass to subcommands """ pass_context = click.make_pass_decorator(Context, ensure=True) @@ -70,4 +56,5 @@ class QtipCli(click.MultiCommand): @click.version_option('dev') @pass_context def cli(ctx, verbose, debug): - pass + if debug: + sys.tracebacklimit = 8 diff --git a/qtip/cli/templates/metric.j2 b/qtip/cli/templates/metric.j2 new file mode 100644 index 00000000..126587f9 --- /dev/null +++ b/qtip/cli/templates/metric.j2 @@ -0,0 +1,6 @@ +Name: {{ name }} +Description: {{ description }} +Workloads: +{% for wl in workloads %} + {{ wl }} +{% endfor %} diff --git a/qtip/cli/templates/plan.j2 b/qtip/cli/templates/plan.j2 new file mode 100644 index 00000000..c9adccc8 --- /dev/null +++ b/qtip/cli/templates/plan.j2 @@ -0,0 +1,2 @@ +Name: {{ name }} +Description: {{ description }} diff --git a/qtip/cli/templates/qpi.j2 b/qtip/cli/templates/qpi.j2 new file mode 100644 index 00000000..cc85f10d --- /dev/null +++ b/qtip/cli/templates/qpi.j2 @@ -0,0 +1,12 @@ +Name: {{ title }} +Description: {{ description }} +{% for section in sections %} + Name: {{ section.name }} + Weight: {{ section.weight }} + Formula: {{ section.formula }} + Metrics: + {% for metric in section.metrics %} + {{ metric }} + {% endfor %} +{% endfor %} + diff --git a/qtip/cli/utils.py b/qtip/cli/utils.py new file mode 100644 index 00000000..a7473236 --- /dev/null +++ b/qtip/cli/utils.py @@ -0,0 +1,31 @@ +############################################################################## +# Copyright (c) 2017 taseer94@gmail.com and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from jinja2 import Environment +from jinja2 import FileSystemLoader +from os import path +from prettytable import PrettyTable + + +def table(name, components): + """ Return a PrettyTable for component listing """ + table = PrettyTable([name]) + table.align[name] = 'l' + [table.add_row([component['name'][0:-5]]) for component in components] + return table + + +def render(name, var_dict): + """ Get the templates to render for specific component """ + tmpl_path = path.join(path.dirname(__file__), 'templates') + tmpl_loader = FileSystemLoader(tmpl_path) + env = Environment(loader=tmpl_loader) + template = env.get_template('{}.j2'.format(name)) + result = template.render(var_dict) + return result diff --git a/qtip/collector/calculator.py b/qtip/collector/calculator.py new file mode 100644 index 00000000..c3d961b3 --- /dev/null +++ b/qtip/collector/calculator.py @@ -0,0 +1,38 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corp and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from operator import add + +from qtip.util.logger import QtipLogger + +logger = QtipLogger('calculator').get + + +def dpi_calculator(samples): + try: + float_pps = map(lambda x: float(x), samples['pps']) + float_bps = map(lambda x: float(x), samples['bps']) + sum_dpi_pps = reduce(add, + map(lambda x: x / 1000 if x > 100 else x, float_pps)) + sum_dpi_bps = reduce(add, + map(lambda x: x / 1000 if x > 100 else x, float_bps)) + + return {'pps': round(sum_dpi_pps / 10, 3), 'bps': round(sum_dpi_bps / 10, 3)} + except Exception as error: + logger.error(error) + return {'pps': None, 'bps': None} + + +def calculate_cpu_usage(cpu_idle): + try: + cpu_usage = round((100.0 - float(cpu_idle)), 3) + return '{0}%'.format(str(cpu_usage)) + except Exception, error: + logger.error(error) + return None diff --git a/qtip/collector/logfile.py b/qtip/collector/logfile.py index 2c2e532f..5f0951cb 100644 --- a/qtip/collector/logfile.py +++ b/qtip/collector/logfile.py @@ -18,8 +18,8 @@ from qtip.loader.file import FileLoader class LogItem(BaseActor): - def find(self, filename, paths=None): - return self._parent.find(filename, paths) + def find(self, filename): + return self._parent.find(filename) class LogfileCollector(BaseActor): @@ -33,8 +33,7 @@ class LogfileCollector(BaseActor): self._parent = parent # plan # TODO(yujunz) handle exception of invalid parent dirname = os.path.dirname(self._parent.abspath) - paths = [os.path.join(dirname, p) for p in config.get(self.PATHS, [])] - self._loader = FileLoader('.', paths) + self.paths = [os.path.join(dirname, p) for p in config.get(self.PATHS, [])] def run(self): collected = [] @@ -45,8 +44,8 @@ class LogfileCollector(BaseActor): collected = chain(collected, reduce(chain, matches)) return reduce(merge_matchobj_to_dict, collected, {'groups': (), 'groupdict': {}}) - def find(self, filename, paths=None): - return self._loader.find(filename, paths) + def find(self, filename): + return FileLoader.find(filename, self.paths) def merge_matchobj_to_dict(d, m): diff --git a/qtip/collector/parser/grep.py b/qtip/collector/parser/grep.py index f74ce403..d3a8210a 100644 --- a/qtip/collector/parser/grep.py +++ b/qtip/collector/parser/grep.py @@ -7,12 +7,20 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - +from collections import defaultdict +from os import path import re +import yaml -from qtip.base.constant import BaseProp from qtip.base import BaseActor +from qtip.base.constant import BaseProp +from qtip.collector import calculator +from qtip.util.logger import QtipLogger + +logger = QtipLogger('grep').get + +REGEX_FILE = path.join(path.dirname(__file__), 'regex.yaml') class GrepProp(BaseProp): @@ -32,3 +40,63 @@ def grep_in_file(filename, regex): with open(filename, 'r') as f: return filter(lambda x: x is not None, re.finditer(regex, f.read(), re.MULTILINE)) + + +def _parse_logfile(config, paths): + captured = {} + for regex_rules_by_file in config: + filename = \ + '{0}/{1}'.format(paths, regex_rules_by_file[GrepProp.FILENAME]) + for regex in regex_rules_by_file['grep']: + matches = grep_in_file(filename, regex) + if len(matches) > 1: + temp_dict = defaultdict(list) + for item in [match.groupdict() for match in matches]: + for key in item: + temp_dict[key].append(item[key]) + captured.update(temp_dict) + elif len(matches) == 1: + captured.update(matches[0].groupdict()) + else: + logger.error("Nothing is matched from {0}".format(filename)) + return captured + + +# TODO: Hardcord in Danube, it will be removed in the future. +def parse_sysinfo(config, result_dir): + sysinfo = _parse_logfile(config, result_dir) + if "cpu_idle" in sysinfo: + sysinfo['cpu_usage'] = \ + calculator.calculate_cpu_usage(sysinfo['cpu_idle']) + sysinfo.pop('cpu_idle') + return sysinfo + + +# TODO: Hardcord in Danube, it will be removed in the future. +def parse_test_result(benchmark, config, result_dir): + test_result = _parse_logfile(config, result_dir) + if benchmark == 'dpi': + return calculator.dpi_calculator(test_result) + if benchmark == 'dhrystone' or benchmark == 'whetstone': + return {'total_cpus': test_result['total_cpus'], + 'single_cpu': {'num': test_result['single_cpu'], + 'score': test_result['score'][0]}, + 'multi_cpus': {'num': test_result['multi_cpus'], + 'score': test_result['score'][1]}} + return test_result + + +# TODO: Hardcord in Danube, it will be removed in the future. +def parse_benchmark_result(result_dir): + regex_config = yaml.safe_load(file(REGEX_FILE)) + benchmark = result_dir.split('/')[-1] + result = {'name': benchmark} + + test_result = \ + parse_test_result(benchmark, regex_config[benchmark], result_dir) + result['results'] = test_result.copy() + + sysinfo = parse_sysinfo(regex_config['sysinfo'], result_dir) + result['sysinfo'] = sysinfo.copy() + + return result diff --git a/qtip/collector/parser/regex.yaml b/qtip/collector/parser/regex.yaml new file mode 100644 index 00000000..397f8973 --- /dev/null +++ b/qtip/collector/parser/regex.yaml @@ -0,0 +1,85 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +dhrystone: + - filename: dhrystone + grep: + - '^(?P<total_cpus>\d+)\sCPUs in system; running 1 parallel copy of tests$' + - '.+\srunning (?P<single_cpu>\d+) parallel copy of tests$' + - '.+\srunning (?P<multi_cpus>\d+) parallel copies of tests$' + - '^System Benchmarks Index Score \(Partial Only\)\s+(?P<score>\d+\.\d)$' +whetstone: + - filename: whetstone + grep: + - '^(?P<total_cpus>\d+)\sCPUs in system; running 1 parallel copy of tests$' + - '.+\srunning (?P<single_cpu>\d+) parallel copy of tests$' + - '.+\srunning (?P<multi_cpus>\d+) parallel copies of tests$' + - '^System Benchmarks Index Score \(Partial Only\)\s+(?P<score>\d+\.\d)$' +dpi: + - filename: dpi_dump.txt + grep: + - |- + ^\s+nDPI throughput:.+?(?P<pps>\d+.\d+)\sM\spps.+ + ?(?P<bps>\d+.\d+)\sGb\/sec +ramspeed: + - filename: Intmem + grep: + - '^INTEGER\s+BatchRun\s+Copy:\s+?(?P<integer_copy>\d+\.\d+)\sMB/s$' + - '^INTEGER\s+BatchRun\s+Scale:\s+?(?P<integer_scale>\d+\.\d+)\sMB/s$' + - '^INTEGER\s+BatchRun\s+Add:\s+?(?P<integer_add>\d+\.\d+)\sMB/s$' + - '^INTEGER\s+BatchRun\s+Triad:\s+?(?P<integer_triad>\d+\.\d+)\sMB/s$' + - '^INTEGER\s+BatchRun\s+AVERAGE:\s+?(?P<integer_average>\d+\.\d+)\sMB/s$' + - filename: Floatmem + grep: + - '^FL-POINT\s+BatchRun\s+Copy:\s+?(?P<float_copy>\d+\.\d+)\sMB/s$' + - '^FL-POINT\s+BatchRun\s+Scale:\s+?(?P<float_scale>\d+\.\d+)\sMB/s$' + - '^FL-POINT\s+BatchRun\s+Add:\s+?(?P<float_add>\d+\.\d+)\sMB/s$' + - '^FL-POINT\s+BatchRun\s+Triad:\s+?(?P<float_triad>\d+\.\d+)\sMB/s$' + - '^FL-POINT\s+BatchRun\s+AVERAGE:\s+?(?P<float_average>\d+\.\d+)\sMB/s$' +ssl: + - filename: RSA_dump + grep: + - |- + ^rsa\s+512\sbits\s.+ + ?(?P<rsa_sign_512>\d+\.\d)\s+ + ?(?P<rsa_verify_512>\d+\.\d)$ + - |- + ^rsa\s+1024\sbits\s.+ + ?(?P<rsa_sign_1024>\d+\.\d)\s+ + ?(?P<rsa_verify_1024>\d+\.\d)$ + - |- + ^rsa\s+2048\sbits\s.+ + ?(?P<rsa_sign_2048>\d+\.\d)\s+ + ?(?P<rsa_verify_2048>\d+\.\d)$ + - |- + ^rsa\s+4096\sbits\s.+ + ?(?P<rsa_sign_4096>\d+\.\d)\s+ + ?(?P<rsa_verify_4096>\d+\.\d)$ + - filename: AES-128-CBC_dump + grep: + - |- + ^aes-128-cbc\s+ + ?(?P<aes_128_cbc_16_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_64_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_256_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_1024_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_8192_bytes>\d+\.\w+)$ +sysinfo: + - filename: top.log + grep: + - 'Cpu\(s\):.+?(?P<cpu_idle>\d+\.\d)\sid' + - filename: inxi.log + grep: + - '.+\s+Host:\s+(?P<hostname>.+)\sKernel' + - '.+\sMemory:\s+(?P<memory>.+MB)\s' + - '^CPU\(s\):\s+(?P<cpu>.+)' + - '.+\sDistro:\s+(?P<os>.+)' + - '.+\sKernel:\s+(?P<kernel>.+)\sConsole' + - '.+\s+HDD Total Size:\s+(?P<disk>.+)\s' + - '.+\sproduct:\s+(?P<product>.+)\sv'
\ No newline at end of file diff --git a/qtip/driver/ansible_api.py b/qtip/driver/ansible_api.py new file mode 100644 index 00000000..5c5baffc --- /dev/null +++ b/qtip/driver/ansible_api.py @@ -0,0 +1,58 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corp and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from collections import namedtuple + +from ansible.executor.playbook_executor import PlaybookExecutor +from ansible.inventory import Inventory +from ansible.parsing.dataloader import DataLoader +from ansible.vars import VariableManager + + +class AnsibleApi(object): + + def __init__(self): + self.variable_manager = VariableManager() + self.loader = DataLoader() + self.passwords = {} + self.playbook_executor = None + + def execute_playbook(self, playbook_path, hosts_file=None, + key_file=None, extra_vars=None): + inventory = Inventory(loader=self.loader, + variable_manager=self.variable_manager, + host_list=hosts_file) + Options = namedtuple('Options', + ['listtags', 'listtasks', 'listhosts', 'syntax', + 'connection', 'module_path', 'forks', 'remote_user', + 'private_key_file', 'ssh_common_args', 'ssh_extra_args', + 'sftp_extra_args', 'scp_extra_args', 'become', + 'become_method', 'become_user', 'verbosity', 'check']) + options = Options(listtags=False, listtasks=False, listhosts=False, + syntax=False, connection='ssh', module_path=None, + forks=100, remote_user='root', private_key_file=key_file, + ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, + scp_extra_args=None, become=None, become_method=None, + become_user='root', verbosity=None, check=False) + self.variable_manager.extra_vars = extra_vars + + self.playbook_executor = PlaybookExecutor(playbooks=[playbook_path], + inventory=inventory, + variable_manager=self.variable_manager, + loader=self.loader, + options=options, + passwords=self.passwords) + return self.playbook_executor.run() + + def get_detail_playbook_stats(self): + if self.playbook_executor: + stats = self.playbook_executor._tqm._stats + return map(lambda x: (x, stats.summarize(x)), stats.processed.keys()) + else: + return None diff --git a/qtip/driver/ansible_driver.py b/qtip/driver/ansible_driver.py new file mode 100644 index 00000000..34ef46ed --- /dev/null +++ b/qtip/driver/ansible_driver.py @@ -0,0 +1,102 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corp and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from collections import defaultdict +from os import path +from operator import add + +from qtip.driver.ansible_api import AnsibleApi +from qtip.util.env import AnsibleEnvSetup +from qtip.util.logger import QtipLogger + +logger = QtipLogger('ansible_driver').get +PLAYBOOK_DIR = path.join(path.dirname(__file__), 'playbook') + + +class AnsibleDriver(object): + """driver for running performance tests with Ansible""" + + def __init__(self, config={}): + self.config = config + self.env = AnsibleEnvSetup() + self.env_setup_flag = False + + @staticmethod + def merge_two_dicts(x, y): + ''' + It is from http://stackoverflow.com/questions/38987/ + how-can-i-merge-two-python-dictionaries-in-a-single-expression + ''' + z = x.copy() + z.update(y) + return z + + def pre_run(self): + if self.env_setup_flag: + logger.info("Already setup environment......") + else: + logger.info("Starting to setup test environment...") + self.env.setup(self.config) + self.env_setup_flag = True + logger.info("Setup test enviroment, Done!") + + def cleanup(self): + self.env.cleanup() + + def run(self, metric_list, **kwargs): + if 'args' in self.config: + extra_vars = self.merge_two_dicts(kwargs, self.config['args']) + else: + extra_vars = kwargs + logger.info("extra_var: {0}".format(extra_vars)) + + tool_to_metrics = defaultdict(list) + for metric in metric_list: + if metric == 'dhrystone' or metric == 'whetstone': + tool_to_metrics['unixbench'].append(metric) + extra_vars[metric] = True + elif metric == 'ssl': + tool_to_metrics['openssl'].append(metric) + else: + tool_to_metrics[metric].append(metric) + + result_list = map(lambda tool: self._run_metric(tool, + tool_to_metrics[tool], + extra_vars), + tool_to_metrics) + return False not in result_list + + def _run_metric(self, tool, metrics, extra_vars): + logger.info('Using {0} to measure metrics {1}'.format(tool, metrics)) + + setup_pbook = "{0}/{1}/setup.yaml".format(PLAYBOOK_DIR, tool) + run_pbook = "{0}/{1}/run.yaml".format(PLAYBOOK_DIR, tool) + clean_pbook = "{0}/{1}/clean.yaml".format(PLAYBOOK_DIR, tool) + + if self._run_ansible_playbook(setup_pbook, extra_vars): + self._run_ansible_playbook(run_pbook, extra_vars) + else: + logger.error("{0} is failed.".format(setup_pbook)) + + return self._run_ansible_playbook(clean_pbook, extra_vars) + + def _run_ansible_playbook(self, pbook, extra_vars): + ansible_api = AnsibleApi() + logger.debug("Run {0} with extra_vars: {1}".format(pbook, extra_vars)) + ansible_api.execute_playbook(pbook, self.env.hostfile, + self.env.keypair['private'], extra_vars) + playbook_stats = ansible_api.get_detail_playbook_stats() + logger.debug("playbook_stat: {0}".format(playbook_stats)) + return self.is_pass(playbook_stats) + + @staticmethod + def is_pass(stats): + return 0 == reduce(add, + map(lambda x: x[1]['failures'] + x[1]['unreachable'], + stats)) diff --git a/qtip/driver/ansible/playbook/bwn_ng.yaml b/qtip/driver/playbook/bwn_ng.yaml index 99477856..c52cb14e 100644 --- a/qtip/driver/ansible/playbook/bwn_ng.yaml +++ b/qtip/driver/playbook/bwn_ng.yaml @@ -20,4 +20,6 @@ when: ansible_os_family == "Debian" - name: Run bwm-ng - shell: bwm-ng -o plain -c 1 > $HOME/qtip_result/bwm-dump.log
\ No newline at end of file + shell: bwm-ng -o plain -c 1 > bwm-dump.log + args: + chdir: '{{ dest_path }}'
\ No newline at end of file diff --git a/qtip/driver/playbook/dpi/clean.yaml b/qtip/driver/playbook/dpi/clean.yaml new file mode 100644 index 00000000..0b9f9291 --- /dev/null +++ b/qtip/driver/playbook/dpi/clean.yaml @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning tempD + file: + path: '{{ ansible_env.HOME }}/tempD' + state: absent + + - name: Cleaning qtip_result + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent diff --git a/qtip/driver/playbook/dpi/dpi_average.sh b/qtip/driver/playbook/dpi/dpi_average.sh new file mode 100644 index 00000000..6f038053 --- /dev/null +++ b/qtip/driver/playbook/dpi/dpi_average.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +COUNTER=0 +WDIR=$PWD +while [ $COUNTER -lt 10 ]; do + echo $WDIR + $( ./ndpiReader -i test.pcap >> $WDIR/dpi_dump.txt ) + let COUNTER=COUNTER+1 + echo "Run number: $COUNTER" +done
\ No newline at end of file diff --git a/qtip/driver/playbook/dpi/run.yaml b/qtip/driver/playbook/dpi/run.yaml new file mode 100644 index 00000000..f4c8c457 --- /dev/null +++ b/qtip/driver/playbook/dpi/run.yaml @@ -0,0 +1,42 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Make some directories needed + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' + state: directory + + - include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' + + - include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' + + - name: Run nDPI benchmark + shell: ./dpi_average.sh + args: + chdir: '{{ ansible_env.HOME }}/tempD/nDPI/example/' + + - name: Copying result and system info to qtip result directory + command: cp $HOME/tempD/nDPI/example/dpi_dump.txt ./ + args: + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dpi/' + + - name: Fetch result files to local manchine + synchronize: + mode: pull + src: '{{ ansible_env.HOME }}/qtip_result/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/dpi/setup.yaml b/qtip/driver/playbook/dpi/setup.yaml new file mode 100644 index 00000000..76e62e6d --- /dev/null +++ b/qtip/driver/playbook/dpi/setup.yaml @@ -0,0 +1,93 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Making Dpi directory + file: + path: '{{ result_dir }}/' + state: directory + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning tempD directory + file: + path: '{{ ansible_env.HOME }}/tempD' + state: absent + + - name: Cleaning qtip_result directory + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent + + - include: ../prepare_env.yaml + + - name: Installing nDPI dependencies if CentOS + yum: + name: '{{ item }}' + state: present + when: ansible_os_family == "RedHat" + with_items: + - git + - gcc + - patch + - perl-Time-HiRes + - autofconf + - automake + - libpcap-devel libtool + + - name: Installing nDPI dependencies if Ubuntu + apt: + name: '{{ item }}' + state: present + when: ansible_os_family == "Debian" + with_items: + - git + - gcc + - patch + - autoconf + - automake + - libpcap-dev + - libtool + + - name: Making nDPI temporary directory + file: + path: '{{ ansible_env.HOME }}/tempD' + state: directory + + - name: Clone nDPI + git: + repo: https://github.com/ntop/nDPI.git + dest: '{{ ansible_env.HOME }}/tempD/nDPI' + + - name: Run autogen && configure Dpi && make Dpi + command: '{{ item }}' + with_items: + - ./autogen.sh + - ./configure + - make + args: + chdir: '{{ ansible_env.HOME }}/tempD/nDPI/' + + - name: Fetching Test_pcap file + get_url: + url: http://build.opnfv.org/artifacts.opnfv.org/qtip/utilities/test.pcap + dest: '{{ ansible_env.HOME }}/tempD/nDPI/example/test.pcap' + + - name: Fetch Averaging script + copy: + src: ./dpi_average.sh + dest: '{{ ansible_env.HOME }}/tempD/nDPI/example' + mode: 777
\ No newline at end of file diff --git a/qtip/driver/ansible/playbook/inxi.yaml b/qtip/driver/playbook/inxi.yaml index f6a0311d..2a4d9b3f 100644 --- a/qtip/driver/ansible/playbook/inxi.yaml +++ b/qtip/driver/playbook/inxi.yaml @@ -20,4 +20,6 @@ when: ansible_os_family == "Debian" - name: Run inxi - shell: inxi -b -c0 -n > $HOME/qtip_result/inxi.log + shell: inxi -b -c0 -n > inxi.log + args: + chdir: '{{ dest_path }}' diff --git a/qtip/driver/playbook/openssl/clean.yaml b/qtip/driver/playbook/openssl/clean.yaml new file mode 100644 index 00000000..0139ba54 --- /dev/null +++ b/qtip/driver/playbook/openssl/clean.yaml @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning Open_SSL + file: + path: '{{ ansible_env.HOME }}/Open_SSL' + state: absent + + - name: Cleaning qtip_result + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent diff --git a/qtip/driver/playbook/openssl/run.yaml b/qtip/driver/playbook/openssl/run.yaml new file mode 100644 index 00000000..db923fed --- /dev/null +++ b/qtip/driver/playbook/openssl/run.yaml @@ -0,0 +1,45 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Make some directories needed + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' + state: directory + + - include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' + + - include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' + + - name: Benchmarking RSA signatures and AES-128-cbc cipher encryption throughput + shell: '{{ item }}' + with_items: + - ./openssl speed rsa >> RSA_dump + - ./openssl speed -evp aes-128-cbc >> AES-128-CBC_dump + args: + chdir: '{{ ansible_env.HOME }}/Open_SSL/openssl-1.0.2f/apps' + + - name: Copying result to qtip result directory + shell: cp ~/Open_SSL/openssl-1.0.2f/apps/*_dump ./ + args: + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ssl/' + + - name: Fetch result files to local manchine + synchronize: + mode: pull + src: '{{ ansible_env.HOME }}/qtip_result/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/openssl/setup.yaml b/qtip/driver/playbook/openssl/setup.yaml new file mode 100644 index 00000000..3a6f385a --- /dev/null +++ b/qtip/driver/playbook/openssl/setup.yaml @@ -0,0 +1,87 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Making ssl directory + file: + path: '{{ result_dir }}/' + state: directory + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning Open_SSL directory + file: + path: '{{ ansible_env.HOME }}/Open_SSL' + state: absent + + - name: Cleaning qtip_result directory + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent + + - include: ../prepare_env.yaml + + - name: Installing UnixBench dependencies if CentOS + yum: + name: '{{ item }}' + state: present + when: ansible_os_family == "RedHat" + with_items: + - git + - gcc + - patch + - perl-Time-HiRes + - wget + - autofconf + - automake + - libpcap-devel + - libtool + + - name: Installing UnixBench dependencies if Ubuntu + apt: + name: '{{ item }}' + state: present + when: ansible_os_family == "Debian" + with_items: + - git + - gcc + - patch + - perl + - wget + - autoconf + - automake + - libpcap-dev + - libtool + + - name: Make Open_SSL directory + file: + path: '{{ ansible_env.HOME }}/Open_SSL' + state: directory + + - name: Untar OpenSSL + unarchive: + src: http://artifacts.opnfv.org/qtip/utilities/openssl-1.0.2f.tar.gz + dest: '{{ ansible_env.HOME }}/Open_SSL/' + remote_src: True + + - name: Configure && Make && Install OpenSSL + shell: "{{ item }}" + with_items: + - ./config + - make + - make install + args: + chdir: '{{ ansible_env.HOME }}/Open_SSL/openssl-1.0.2f'
\ No newline at end of file diff --git a/qtip/driver/ansible/playbook/prepare_env.yaml b/qtip/driver/playbook/prepare_env.yaml index 0595d988..1ec71520 100644 --- a/qtip/driver/ansible/playbook/prepare_env.yaml +++ b/qtip/driver/playbook/prepare_env.yaml @@ -10,7 +10,7 @@ yum: name: epel-release state: present - when: ansible_os_family == "RedHat" + when: ansible_os_family == "RedHat" - name: Software Properties Common apt: @@ -40,3 +40,15 @@ name: python-selinux state: present when: ansible_os_family == "Debian" + +- name: Install rsync when CentOS + yum: + name: rsync + state: present + when: ansible_os_family == "RedHat" + +- name: Install rsync when Ubuntu + apt: + name: rsync + state: present + when: ansible_os_family == "Debian" diff --git a/qtip/driver/playbook/ramspeed/clean.yaml b/qtip/driver/playbook/ramspeed/clean.yaml new file mode 100644 index 00000000..f0188159 --- /dev/null +++ b/qtip/driver/playbook/ramspeed/clean.yaml @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning ramspeed + file: + path: '{{ ansible_env.HOME }}/ramspeed' + state: absent + + - name: Cleaning qtip_result + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent diff --git a/qtip/driver/playbook/ramspeed/run.yaml b/qtip/driver/playbook/ramspeed/run.yaml new file mode 100644 index 00000000..496cd5db --- /dev/null +++ b/qtip/driver/playbook/ramspeed/run.yaml @@ -0,0 +1,40 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Make some directories needed + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' + state: directory + + - include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' + + - include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' + + - name: Benchmarking IntMem Bandwidth and FloatMem Bandwidth + shell: '{{ item }}' + with_items: + - ~/ramspeed/ramsmp-3.5.0/ramsmp -b 3 -l 5 -p 1 >> Intmem + - ~/ramspeed/ramsmp-3.5.0/ramsmp -b 6 -l 5 -p 1 >> Floatmem + args: + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/ramspeed/' + + - name: Fetch result files to local manchine + synchronize: + mode: pull + src: '{{ ansible_env.HOME }}/qtip_result/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/ramspeed/setup.yaml b/qtip/driver/playbook/ramspeed/setup.yaml new file mode 100644 index 00000000..842bbda2 --- /dev/null +++ b/qtip/driver/playbook/ramspeed/setup.yaml @@ -0,0 +1,70 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Making ramspeed directory + file: + path: '{{ result_dir }}/' + state: directory + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning ramspeed directory + file: + path: '{{ ansible_env.HOME }}/ramspeed' + state: absent + + - name: Cleaning qtip_result directory + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent + + - include: ../prepare_env.yaml + + - name: Installing RAM_Speed dependencies if CentOS + yum: + name: '{{ item }}' + state: present + when: ansible_os_family == "RedHat" + with_items: + - gcc + - wget + + - name: Installing RAM_Speed dependencies if Ubuntu + apt: + name: '{{ item }}' + state: present + when: ansible_os_family == "Debian" + with_items: + - gcc + - wget + + - name: Making ramspeed temporary directory + file: + path: '{{ ansible_env.HOME }}/ramspeed' + state: directory + + - name: Fetch and untar ramspeed.tar.gz + unarchive: + # TODO: Need to upload this file to http://artifacts.opnfv.org/qtip/utilities + src: https://docs.google.com/uc?id=0B92Bp5LZTM7gRFctalZLMktTNDQ + dest: '{{ ansible_env.HOME }}/ramspeed/' + remote_src: True + + - name: Build ramsmp + shell: ./build.sh + args: + chdir: '{{ ansible_env.HOME }}/ramspeed/ramsmp-3.5.0' diff --git a/qtip/driver/ansible/playbook/top.yaml b/qtip/driver/playbook/top.yaml index 8de7e3d6..dfa0aff2 100644 --- a/qtip/driver/ansible/playbook/top.yaml +++ b/qtip/driver/playbook/top.yaml @@ -7,4 +7,6 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - name: Collect cpu usage - shell: top -bn1 > $HOME/qtip_result/top.log + shell: top -bn1 > top.log + args: + chdir: '{{ dest_path }}' diff --git a/qtip/driver/playbook/unixbench/clean.yaml b/qtip/driver/playbook/unixbench/clean.yaml new file mode 100644 index 00000000..a7cb2540 --- /dev/null +++ b/qtip/driver/playbook/unixbench/clean.yaml @@ -0,0 +1,25 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# zhihui.wu1@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning tempT + file: + path: '{{ ansible_env.HOME }}/tempT' + state: absent + + - name: Cleaning qtip_result + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent + + diff --git a/qtip/driver/playbook/unixbench/dhrystone.yaml b/qtip/driver/playbook/unixbench/dhrystone.yaml new file mode 100644 index 00000000..a0ee89a3 --- /dev/null +++ b/qtip/driver/playbook/unixbench/dhrystone.yaml @@ -0,0 +1,41 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# zhihui.wu1@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- name: Make dhrystone directories + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + state: directory + +- include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + +- include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + +- name: Run dhrystone + shell: ./Run -v dhrystone + args: + chdir: '{{ ansible_env.HOME }}/tempT/UnixBench/' + +- name: Copying result to qtip result directory + shell: '{{ item }}' + with_items: + - mv ~/tempT/UnixBench/results/*.log ./ + - mv ~/tempT/UnixBench/results/*.html ./ + - mv ~/tempT/UnixBench/results/* ./dhrystone + args: + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/dhrystone/' + +- name: Fetch dhrystone result files to local manchine + synchronize: + mode: pull + src: '{{ ansible_env.HOME }}/qtip_result/' + dest: '{{ result_dir }}/' diff --git a/qtip/driver/playbook/unixbench/run.yaml b/qtip/driver/playbook/unixbench/run.yaml new file mode 100644 index 00000000..fbe4d4ad --- /dev/null +++ b/qtip/driver/playbook/unixbench/run.yaml @@ -0,0 +1,23 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# zhihui.wu1@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - set_fact: + is_dhrystone: "{{ dhrystone | default(False) }}" + is_whetstone: "{{ whetstone | default(False) }}" + + - include: ./dhrystone.yaml + when: "{{ is_dhrystone }}" + + - include: ./whetstone.yaml + when: "{{ is_whetstone }}"
\ No newline at end of file diff --git a/qtip/driver/playbook/unixbench/setup.yaml b/qtip/driver/playbook/unixbench/setup.yaml new file mode 100644 index 00000000..4b9b5240 --- /dev/null +++ b/qtip/driver/playbook/unixbench/setup.yaml @@ -0,0 +1,65 @@ +############################################################################# +# Copyright (c) 2017 ZTE Corporation and others. +# zhihui.wu1@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################# + +- hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Making dhrystone directory + file: + path: '{{ result_dir }}/' + state: directory + +- hosts: hosts + become: yes + remote_user: root + + tasks: + - name: Cleaning tempT directory + file: + path: '{{ ansible_env.HOME }}/tempT' + state: absent + + - name: Cleaning qtip_result directory + file: + path: '{{ ansible_env.HOME }}/qtip_result' + state: absent + + - include: ../prepare_env.yaml + + - name: Installing UnixBench dependencies if CentOS + yum: + name: '{{ item }}' + state: present + when: ansible_os_family == "RedHat" + with_items: + - git + - gcc + - patch + - perl-Time-HiRes + + - name: Installing UnixBench dependencies if Ubuntu + apt: + name: '{{ item }}' + state: present + when: ansible_os_family == "Debian" + with_items: + - git + - gcc + - patch + - perl + + - name: Clone UnixBench + git: + repo: https://github.com/kdlucas/byte-unixbench.git + dest: '{{ ansible_env.HOME }}/tempT/' + + - name: Make UnixBench + shell: make --directory $HOME/tempT/UnixBench/
\ No newline at end of file diff --git a/qtip/driver/playbook/unixbench/whetstone.yaml b/qtip/driver/playbook/unixbench/whetstone.yaml new file mode 100644 index 00000000..c753779f --- /dev/null +++ b/qtip/driver/playbook/unixbench/whetstone.yaml @@ -0,0 +1,41 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# zhihui.wu1@zte.com.cn +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +- name: Make whetstone directories + file: + path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + state: directory + +- include: ../inxi.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + +- include: ../top.yaml + vars: + dest_path: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + +- name: Run whetstone + shell: ./Run -v whetstone + args: + chdir: '{{ ansible_env.HOME }}/tempT/UnixBench/' + +- name: Copying result to qtip result directory + shell: '{{ item }}' + with_items: + - mv ~/tempT/UnixBench/results/*.log ./ + - mv ~/tempT/UnixBench/results/*.html ./ + - mv ~/tempT/UnixBench/results/* ./whetstone + args: + chdir: '{{ ansible_env.HOME }}/qtip_result/{{ ansible_hostname }}/whetstone/' + +- name: Fetch whetstone result files to local manchine + synchronize: + mode: pull + src: '{{ ansible_env.HOME }}/qtip_result/' + dest: '{{ result_dir }}/' diff --git a/qtip/loader/file.py b/qtip/loader/file.py index 038f57dd..a39e15f6 100644 --- a/qtip/loader/file.py +++ b/qtip/loader/file.py @@ -28,11 +28,12 @@ class FileLoader(BaseLoader): self._filename = name self.abspath = self.find(name, paths=paths) - def find(self, name, paths=None): + @classmethod + def find(cls, name, paths=None): """find a specification in searching paths""" - paths = [self.abspath] if paths is None else paths + paths = cls._paths if paths is None else paths for p in paths: - abspath = path.join(p, self.RELATIVE_PATH, name) + abspath = path.join(p, cls.RELATIVE_PATH, name) if path.exists(abspath): return abspath raise NotFoundError(name, paths) diff --git a/qtip/reporter/console.py b/qtip/reporter/console.py new file mode 100644 index 00000000..64d677ba --- /dev/null +++ b/qtip/reporter/console.py @@ -0,0 +1,46 @@ +############################################################################## +# Copyright (c) 2017 taseer94@gmail.com and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import glob +import json +from os import path + +from jinja2 import Environment +from jinja2 import FileSystemLoader +from qtip.base import BaseActor + +ROOT_DIR = path.join(path.dirname(__file__), path.pardir, path.pardir) + + +class ConsoleReporter(BaseActor): + """ report benchmark result to console """ + + def __init__(self, config, parent=None): + super(ConsoleReporter, self).__init__(config, parent=parent) + + # TODO (taseer) load template from config + tpl_path = path.join(path.dirname(__file__), 'templates') + tpl_loader = FileSystemLoader(tpl_path) + self._env = Environment(loader=tpl_loader) + self.result_path = path.join(ROOT_DIR, 'collector') + + def load_result(self): + # TODO (taseer) change result directory format more suitable to filter out + result_dirs = glob.glob('{}/20*'.format(self.result_path)) + # select the last (latest) directory for rendering report, result_dirs[-1] + with open(path.join(self.result_path, result_dirs[-1], 'result.json')) as sample: + result = json.load(sample) + return result + + def render(self, metric): + template = self._env.get_template('base.j2') + var_dict = self.load_result() + var_dict['metric_name'] = metric + out = template.render(var_dict) + return out diff --git a/qtip/reporter/templates/base.j2 b/qtip/reporter/templates/base.j2 new file mode 100644 index 00000000..12a27536 --- /dev/null +++ b/qtip/reporter/templates/base.j2 @@ -0,0 +1,25 @@ +Plan Name: {{ plan_name }} +Start Time: {{ start_time }} +Stop Time: {{ stop_time }} +{%- for sys in sut -%} +{% for qpi in sys.qpis %} +{% for bm in qpi.benchmarks %} +{%- if bm.name == metric_name -%} +{%- if metric_name == 'dhrystone' or metric_name == 'whetstone' -%} +{# TODO (taseer) remove hardcoded material #} +{% include 'unixbench.j2' %} +{% else %} +{% include '%s.j2' % metric_name %} +{% endif %} +System Information: + CPU Brand: {{ bm.sysinfo.cpu }} + Disk: {{ bm.sysinfo.disk }} + Host Name: {{ bm.sysinfo.hostname }} + Kernel: {{ bm.sysinfo.kernel }} + Memory: {{ bm.sysinfo.memory }} + Operating System: {{ bm.sysinfo.os }} + Product: {{ bm.sysinfo.product }} +{%- endif -%} +{%- endfor -%} +{%- endfor -%} +{%- endfor -%} diff --git a/qtip/reporter/templates/dpi.j2 b/qtip/reporter/templates/dpi.j2 new file mode 100644 index 00000000..758a821e --- /dev/null +++ b/qtip/reporter/templates/dpi.j2 @@ -0,0 +1,5 @@ +Benchmark: {{ bm.name }} +CPU Usage: {{ bm. cpu_usage }} +Results: + Bits per Second: {{ bm.results.bps }} + Packets per Second: {{ bm.results.pps }}
\ No newline at end of file diff --git a/qtip/reporter/templates/ramspeed.j2 b/qtip/reporter/templates/ramspeed.j2 new file mode 100644 index 00000000..d08d7e2e --- /dev/null +++ b/qtip/reporter/templates/ramspeed.j2 @@ -0,0 +1,13 @@ +Benchmark: {{ bm.name }} +CPU Usage: {{ bm. cpu_usage }} +Results: + Float Addition: {{ bm.results.float_add }} + Float Average: {{ bm.results.float_average }} + Float Copy: {{ bm.results.float_copy }} + Float Scale: {{ bm.results.float_scale }} + Float Triad: {{ bm.results.float_triad }} + Integer Addition: {{ bm.results.integer_add }} + Integer Average: {{ bm.results.integer_average }} + Integer Copy: {{ bm.results.integer_copy}} + Integer Scale: {{ bm.results.integer_scale }} + Integer Triad: {{ bm.results.integer_triad}}
\ No newline at end of file diff --git a/qtip/reporter/templates/ssl.j2 b/qtip/reporter/templates/ssl.j2 new file mode 100644 index 00000000..b46927a8 --- /dev/null +++ b/qtip/reporter/templates/ssl.j2 @@ -0,0 +1,21 @@ +Benchmark: {{ bm.name }} +CPU Usage: {{ bm.cpu_usage }} +Results: + AES 128 CBC (bytes): + 16: {{ bm.results.aes_128_cbc_16_bytes }} + 64: {{ bm.results.aes_128_cbc_64_bytes }} + 256: {{ bm.results.aes_128_cbc_256_bytes }} + 1024: {{ bm.results.aes_128_cbc_1024_bytes }} + 8192: {{ bm.results.aes_128_cbc_8192_bytes }} + + RSA SIGN: + 512: {{ bm.results.rsa_sign_512 }} + 1024: {{ bm.results.rsa_sign_1024 }} + 2048: {{ bm.results.rsa_sign_2048 }} + 4096: {{ bm.results.rsa_sign_4096 }} + + RSA VERIFY: + 512: {{ bm.results.rsa_verify_512 }} + 1024: {{ bm.results.rsa_verify_1024 }} + 2048: {{ bm.results.rsa_verify_2048 }} + 4096: {{ bm.results.rsa_verify_4096 }}
\ No newline at end of file diff --git a/qtip/reporter/console/timeline.j2 b/qtip/reporter/templates/timeline.j2 index 9c18a996..ccb089e0 100644 --- a/qtip/reporter/console/timeline.j2 +++ b/qtip/reporter/templates/timeline.j2 @@ -1,8 +1,8 @@ -{% title %} +{{ title }} {% for phase in phases %} -{{ phase.name|upper }}{{ "TIME" }} +{{ phase.name|upper }}{{ "TIME"}} {% for cp in phase.checkpoints %} -{{ cp.name }}{{ cp.timestamp}} +{{ cp.name }}{{ cp.timestamp| indent(15, True)}} {% endfor %} {% endfor %} Total: {{ total }} diff --git a/qtip/reporter/templates/unixbench.j2 b/qtip/reporter/templates/unixbench.j2 new file mode 100644 index 00000000..69006da7 --- /dev/null +++ b/qtip/reporter/templates/unixbench.j2 @@ -0,0 +1,10 @@ +Benchmark: {{ bm.name }} +CPU Usage: {{ bm. cpu_usage }} +Results: + Multi CPU: + Number: {{ bm.results.multi_cpus.num }} + Score: {{ bm.results.multi_cpus.score }} + Single CPU: + Number: {{ bm.results.single_cpu.num }} + Score: {{ bm.results.single_cpu.num }} + Total CPUs: {{ bm.results.total_cpus }}
\ No newline at end of file diff --git a/qtip/runner/__init__.py b/qtip/runner/__init__.py index 52c43a14..e69de29b 100644 --- a/qtip/runner/__init__.py +++ b/qtip/runner/__init__.py @@ -1,43 +0,0 @@ -############################################################################## -# Copyright (c) 2016 ZTE Corp and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## - -from qtip.base.constant import PkgName, BaseProp -from qtip.base.error import NotFoundError -from qtip.collector.stdout import StdoutCollector -from qtip.driver.random import RandomDriver -from qtip.reporter.console import ConsoleReporter - - -class Runner(object): - def __init__(self, spec, config=None): - if config is None: - config = spec[BaseProp.CONFIG] - - driver_name = config[BaseProp.DRIVER] - collector_name = config[BaseProp.COLLECTOR] - reporter_name = config[BaseProp.REPORTER] - - # TODO(yujunz) dynamically load modules by name - - if driver_name == 'random': - self.driver = RandomDriver() - else: - raise NotFoundError(driver_name, heystack=PkgName.DRIVER) - - if collector_name == 'stdout': - self.collector = StdoutCollector() - else: - raise NotFoundError(collector_name, - heystack=PkgName.COLLECTOR) - - if reporter_name == 'console': - self.reporter = ConsoleReporter() - else: - raise NotFoundError(reporter_name, - heystack=PkgName.REPORTER) diff --git a/qtip/reporter/base.py b/qtip/runner/base.py index b931d14d..a86626d9 100644 --- a/qtip/reporter/base.py +++ b/qtip/runner/base.py @@ -8,7 +8,5 @@ ############################################################################## -class BaseReporter(object): - """benchmark result reporter""" - def __init__(self, collector=None): - self.collector = collector +class BaseRunner(object): + """benchmark task runner""" diff --git a/qtip/runner/runner.py b/qtip/runner/runner.py new file mode 100644 index 00000000..8bdbfb78 --- /dev/null +++ b/qtip/runner/runner.py @@ -0,0 +1,107 @@ +############################################################################## +# Copyright (c) 2017 ZTE corp. and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import argparse +import json +import os +from os import path +import sys +import time + +from qtip.collector.parser import grep +from qtip.driver.ansible_driver import AnsibleDriver +from qtip.util.logger import QtipLogger + +logger = QtipLogger('runner').get + +ALL_BENCHMARKS = ['dpi', 'ramspeed', 'ssl', 'dhrystone', 'whetstone'] + + +def parse_args(args): + parser = argparse.ArgumentParser() + parser.add_argument('-d', '--dest', required=True, + help='the destination where results will be stored.') + parser.add_argument('-b', '--benchmark', required=True, action='append', + help='the benchmark you want to execute.') + return parser.parse_args(args) + + +def run_benchmark(result_dir, benchmarks): + if not path.isdir(result_dir): + os.makedirs(result_dir) + driver = AnsibleDriver({'args': {'result_dir': result_dir}}) + driver.pre_run() + result = driver.run(benchmarks) + driver.cleanup() + return result + + +def generate_report(result_dir, start_time, stop_time): + output = { + "plan_name": "compute_qpi", + "start_time": start_time, + "stop_time": stop_time, + "sut": [] + } + output.update(parse_result(result_dir)) + output.update({'stop_time': stop_time}) + with open('{0}/result.json'.format(result_dir), 'w+') as f: + json.dump(output, f, indent=4, sort_keys=True) + + +def parse_result(result_dir): + sut_template = {'sut': []} + nodes_list = os.listdir(result_dir) + for node in nodes_list: + node_output_template = { + 'name': node, + 'type': 'baremetal', + 'qpis': [] + } + qpi_result = {'name': 'compute_qpi', 'benchmarks': []} + for benchmark in os.listdir('{0}/{1}'.format(result_dir, node)): + benchmark_result = \ + grep.parse_benchmark_result( + '{0}/{1}/{2}'.format(result_dir, node, benchmark)) + qpi_result['benchmarks'].append(benchmark_result) + node_output_template['qpis'].append(qpi_result) + sut_template['sut'].append(node_output_template) + return sut_template + + +def main(args=sys.argv[1:]): + args = parse_args(args) + + if not path.isdir(str(args.dest)): + logger.error("The destination {0} you give doesn't exist. " + "Please check!".format(args.dest)) + sys.exit(1) + + if args.benchmark == ['all']: + args.benchmark = ALL_BENCHMARKS + elif len(set(args.benchmark).difference(ALL_BENCHMARKS)) != 0: + logger.error("Please check benchmarks name. The supported benchmarks are" + "{0}".format(ALL_BENCHMARKS)) + logger.info("Start to run benchmark test: {0}.".format(args.benchmark)) + + start_time = time.strftime("%Y-%m-%d-%H-%M") + logger.info("start_time: {0}".format(start_time)) + if not args.dest.endswith('/'): + args.dest += '/' + result_dir = args.dest + start_time + ansible_result = run_benchmark(result_dir, args.benchmark) + stop_time = time.strftime("%Y-%m-%d-%H-%M") + logger.info("stop_time: {0}".format(stop_time)) + if not ansible_result: + logger.error("Bechmarks run failed. Cann't generate any report.") + sys.exit(1) + generate_report(result_dir, start_time, stop_time) + + +if __name__ == "__main__": + main() diff --git a/qtip/scripts/cleanup_creds.sh b/qtip/scripts/cleanup_creds.sh new file mode 100755 index 00000000..ad66ba95 --- /dev/null +++ b/qtip/scripts/cleanup_creds.sh @@ -0,0 +1,20 @@ +#! /bin/bash +############################################################################## +# Copyright (c) 2017 ZTE corp. and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +DEST_IP=$1 +PRIVATE_KEY=$2 +PUBLIC_KEY=$3 +sshoptions="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" + +case "$INSTALLER_TYPE" in + fuel) + ssh $sshoptions -i $PRIVATE_KEY root@$DEST_IP "sed -i '/$PUBLIC_KEY/d' /root/.ssh/authorized_keys" + ;; +esac diff --git a/qtip/scripts/fetch_compute_ips.sh b/qtip/scripts/generate_host_file.sh index a2618ec9..ecc4d55f 100755 --- a/qtip/scripts/fetch_compute_ips.sh +++ b/qtip/scripts/generate_host_file.sh @@ -10,17 +10,15 @@ usage(){ - echo "usage: $0 [-v] -i <installer_type> -a <installer_ip>" >&2 - echo "[-v] Virtualized deployment" >&2 + echo "usage: $0 -t <installer_type> -i <installer_ipaddr> -d <dest_hostfile>" >&2 } info() { - logger -s -t "fetch_compute_info.info" "$*" + logger -s -t "generate_host_file.info" "$*" } - error() { - logger -s -t "fetch_compute_info.error" "$*" + logger -s -t "generate_host_file.error" "$*" exit 1 } @@ -40,11 +38,11 @@ verify_connectivity(){ :${DEPLOY_TYPE:=''} #Getoptions -while getopts ":i:a:h:v" optchar; do +while getopts ":t:i:d:" optchar; do case "${optchar}" in - i) installer_type=${OPTARG} ;; - a) installer_ip=${OPTARG} ;; - v) DEPLOY_TYPE="virt" ;; + t) installer_type=${OPTARG} ;; + i) installer_ipaddr=${OPTARG} ;; + d) dest_hostfile=${OPTARG} ;; *) echo "Non-option argument: '-${OPTARG}'" >&2 usage exit 2 @@ -54,9 +52,9 @@ done #set vars from env if not provided by user as options installer_type=${installer_type:-$INSTALLER_TYPE} -installer_ip=${installer_ip:-$INSTALLER_IP} +installer_ipaddr=${installer_ipaddr:-$INSTALLER_IP} -if [ -z $installer_type ] || [ -z $installer_ip ]; then +if [ -z $installer_type ] || [ -z $installer_ipaddr ]; then usage exit 2 fi @@ -65,9 +63,9 @@ ssh_options="-oUserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" #Start fetching compute ip if [ "$installer_type" == "fuel" ]; then - verify_connectivity $installer_ip + verify_connectivity $installer_ipaddr - env=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + env=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ipaddr} \ 'fuel env'|grep operational|head -1|awk '{print $1}') &> /dev/null if [ -z $env ]; then error "No operational environment detected in Fuel" @@ -75,7 +73,7 @@ if [ "$installer_type" == "fuel" ]; then env_id="${FUEL_ENV:-$env}" # Check if compute is alive (online='True') - IPS=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ip} \ + IPS=$(sshpass -p r00tme ssh 2>/dev/null $ssh_options root@${installer_ipaddr} \ "fuel node --env ${env_id} | grep compute | grep 'True\| 1' | awk -F\| '{print \$5}' " | \ sed 's/ //g') &> /dev/null @@ -86,8 +84,8 @@ elif [ "$installer_type" == "apex" ]; then elif [ "$installer_type" == "compass" ]; then # need test - verify_connectivity $installer_ip - IPS=$(sshpass -p'root' ssh 2>/dev/null $ssh_options root@${installer_ip} \ + verify_connectivity $installer_ipaddr + IPS=$(sshpass -p'root' ssh 2>/dev/null $ssh_options root@${installer_ipaddr} \ 'mysql -ucompass -pcompass -Dcompass -e"select * from cluster;"' \ | awk -F"," '{for(i=1;i<NF;i++)if($i~/\"host[4-5]\"/) {print $(i+1);}}' \ | grep -oP "\d+.\d+.\d+.\d+") @@ -108,10 +106,11 @@ if [ -z "$IPS" ]; then error "The compute node $IPS are not up. Please check that the POD is correctly deployed." else echo "-------- all compute node ips: --------" - rm $HOME/ips.log - touch $HOME/ips.log - echo "$IPS" > $HOME/qtip/ips.log - echo $IPS + rm $dest_hostfile + touch $dest_hostfile + echo "[hosts]" >> $dest_hostfile + echo "$IPS" >> $dest_hostfile + cat $dest_hostfile fi exit 0 diff --git a/qtip/scripts/qtip_creds.sh b/qtip/scripts/qtip_creds.sh index af051ac5..239c60c1 100755 --- a/qtip/scripts/qtip_creds.sh +++ b/qtip/scripts/qtip_creds.sh @@ -1,30 +1,34 @@ #! /bin/bash DEST_IP=$1 +PRIVATE_KEY=$2 +PUBLIC_KEY=$2.pub +KEYNAME=$(basename $PRIVATE_KEY) + echo $INSTALLER_TYPE echo $INSTALLER_IP sshoptions="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" case "$INSTALLER_TYPE" in apex) - scp $sshoptions -i $APEX_KEY ./config/QtipKey.pub stack@$INSTALLER_IP:/home/stack - scp $sshoptions -i $APEX_KEY ./config/QtipKey stack@$INSTALLER_IP:/home/stack - ssh $sshoptions -i $APEX_KEY stack@$INSTALLER_IP "ssh-copy-id $sshoptions -i /home/stack/QtipKey.pub heat-admin@$DEST_IP && rm -rf /home/stack/QtipKey && rm -rf /home/stack/QtipKey.pub" + scp $sshoptions -i $APEX_KEY $PUBLIC_KEY stack@$INSTALLER_IP:/home/stack + scp $sshoptions -i $APEX_KEY $PRIVATE_KEY stack@$INSTALLER_IP:/home/stack + ssh $sshoptions -i $APEX_KEY stack@$INSTALLER_IP "ssh-copy-id $sshoptions -i /home/stack/$KEYNAME.pub heat-admin@$DEST_IP && rm -rf /home/stack/$KEYNAME && rm -rf /home/stack/$KEYNAME.pub" ;; fuel) PSWD="r00tme" - sshpass -p $PSWD scp $sshoptions ./config/QtipKey.pub root@$INSTALLER_IP:/root - sshpass -p $PSWD scp $sshoptions ./config/QtipKey root@$INSTALLER_IP:/root + sshpass -p $PSWD scp $sshoptions $PUBLIC_KEY root@$INSTALLER_IP:/root + sshpass -p $PSWD scp $sshoptions $PRIVATE_KEY root@$INSTALLER_IP:/root sshpass -p $PSWD ssh $sshoptions root@$INSTALLER_IP "grep -q '\-F /dev/null ' /usr/bin/ssh-copy-id || sed -i 's/\(ssh -i.*$\)/\1\n -F \/dev\/null \\\/g' `which ssh-copy-id`" - sshpass -p $PSWD ssh $sshoptions root@$INSTALLER_IP "ssh-copy-id $sshoptions -i /root/QtipKey root@$DEST_IP && rm -rf /root/QtipKey && rm -rf /root/QtipKey.pub" + sshpass -p $PSWD ssh $sshoptions root@$INSTALLER_IP "ssh-copy-id $sshoptions -i /root/$KEYNAME root@$DEST_IP && rm -rf /root/$KEYNAME && rm -rf /root/$KEYNAME.pub" ;; compass) PSWD="root" - sshpass -p $PSWD scp $sshoptions ./config/QtipKey.pub root@$INSTALLER_IP:/root - sshpass -p $PSWD scp $sshoptions ./config/QtipKey root@$INSTALLER_IP:/root - sshpass -p $PSWD ssh $sshoptions root@$INSTALLER_IP "ssh-copy-id $sshoptions -i /root/QtipKey.pub root@$DEST_IP && rm -rf /root/QtipKey && rm -rf /root/QtipKey.pub" + sshpass -p $PSWD scp $sshoptions $PUBLIC_KEY root@$INSTALLER_IP:/root + sshpass -p $PSWD scp $sshoptions $PRIVATE_KEY root@$INSTALLER_IP:/root + sshpass -p $PSWD ssh $sshoptions root@$INSTALLER_IP "ssh-copy-id $sshoptions -i /root/$KEYNAME.pub root@$DEST_IP && rm -rf /root/$KEYNAME && rm -rf /root/$KEYNAME.pub" ;; joid) PSWD="joid";; *) echo "Unkown installer $INSTALLER_TYPE specified";; -esac +esac
\ No newline at end of file diff --git a/qtip/util/env.py b/qtip/util/env.py index 4e7a31c7..9299f8c0 100644 --- a/qtip/util/env.py +++ b/qtip/util/env.py @@ -1,137 +1,213 @@ ############################################################################## -# Copyright (c) 2016 Dell Inc, ZTE and others. +# Copyright (c) 2017 ZTE and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## +from collections import defaultdict import os -import paramiko +from os import path +import re import socket +import sys import time -from os import path -from os.path import expanduser - -SCRIPT_DIR = path.join(path.dirname(__file__), path.pardir, 'scripts') -CONFIG_DIR = path.join(path.dirname(__file__), path.pardir, path.pardir, - 'config') -PRIVATE_KEY = CONFIG_DIR + '/QtipKey' -PUBLIC_KEY = CONFIG_DIR + '/QtipKey.pub' -IPS_FILE = expanduser('~') + "/qtip/ips.log" -HOST_FILE = CONFIG_DIR + "/host" - - -def fetch_compute_ips_via_installer(): - clean_file(IPS_FILE) - - installer_type = str(os.environ['INSTALLER_TYPE'].lower()) - installer_ip = str(os.environ['INSTALLER_IP']) - if installer_type not in ["fuel"]: - raise RuntimeError("%s is not supported" % installer_type) - if not installer_ip: - raise RuntimeError("undefine environment variable INSTALLER_IP") - - cmd = "bash %s/fetch_compute_ips.sh -i %s -a %s" % \ - (SCRIPT_DIR, installer_type, installer_ip) - os.system(cmd) - if path.isfile(IPS_FILE): - return True - else: - return False +import paramiko -def parse_ips(): - ip_list = [] - with open(IPS_FILE, "r") as outfile: - data = outfile.read() - if data: - ip_list.extend(data.rstrip('\n').split('\n')) - return ip_list +from qtip.util.logger import QtipLogger +logger = QtipLogger('env').get -def ssh_test(ip): - os.system('ssh-keyscan %s >> /root/.ssh/known_hosts' % ip) - time.sleep(2) +SCRIPT_DIR = path.join(path.dirname(__file__), path.pardir, 'scripts') +KEYNAME = 'QtipKey' +PRIVATE_KEY = '{0}/qtip/{1}'.format(os.environ['HOME'], KEYNAME) +PUBLIC_KEY = PRIVATE_KEY + '.pub' +HOST_FILE = '{0}/qtip/hosts'.format(os.environ['HOME']) - ssh_cmd = '%s/qtip_creds.sh %s' % (SCRIPT_DIR, ip) - os.system(ssh_cmd) - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect(ip, key_filename='{0}/QtipKey'.format(CONFIG_DIR)) +def all_files_exist(*files): + if len(files) == 0: + return False + flag = True + for f_item in files: + flag &= path.isfile(f_item) + logger.info("Is {0} existed: {1}".format(f_item, flag)) + return flag - for attempts in range(100): - try: - stdin, stdout, stderr = ssh.exec_command('uname') - if not stderr.readlines(): - print("{0}: SSH test successful") - return True - except socket.error: - if attempts == 99: - return False - time.sleep(2) +def clean_file(*files): + if len(files) == 0: + logger.info('Nothing to clean') + return False -def ping_test(ip, attempts=30): - ping_cmd = 'ping -D -c1 {0}'.format(ip) - for i in range(attempts): - if os.system(ping_cmd): - print('\nWaiting for machine\n') - time.sleep(10) - else: - print('\n\n %s is UP \n\n ' % ip) + def clean(f): + try: + if all_files_exist(f): + os.remove(f) + logger.info("Removed: {0}".format(f)) + else: + logger.info("Not exists: {0}".format(f)) return True - if i == 29: + except OSError as error: + logger.error("Not able to Remove: {0}".format(f), error) return False + results = map(clean, files) + return len(results) == len(files) and False not in results -def check_nodes_connectivity(): - ip_list = parse_ips() - for ip in ip_list: - if not ping_test(ip): - raise RuntimeError("{0}: Ping test failed".format(ip)) - if not ssh_test(ip): - raise RuntimeError("{0}: SSH test failed".format(ip)) +class AnsibleEnvSetup(object): + def __init__(self): + self.keypair = defaultdict(str) + self.hostfile = None + self.host_ip_list = [] -def generate_host_file(): - ip_list = parse_ips() - with open(HOST_FILE, 'w') as host_file: - for index, item in enumerate(ip_list): - host_file.write("[host_{0}]\n".format(index)) - host_file.write(item + '\n') - - -def generate_keypair(): - """Generating ssh keypair""" - if not clean_keypair(): - raise RuntimeError("Cann't remove old keypair") - - cmd = "ssh-keygen -t rsa -N "" -f {0} -q".format(PRIVATE_KEY) - os.system(cmd) - - if path.isfile(PRIVATE_KEY) and path.isfile(PUBLIC_KEY): - return True - else: - return False + def setup(self, config={}): + try: + if 'hostfile' in config: + self.check_hostfile(config['hostfile']) + else: + self.generate_default_hostfile() + self.fetch_host_ip_from_hostfile() + if 'keypair' in config: + self.check_keypair(config['keypair']) + else: + self.generate_default_keypair() + self.pass_keypair_to_remote() + self.check_hosts_ssh_connectivity() + except Exception as error: + logger.info(error) + sys.exit(1) + + def check_keypair(self, keypair): + self.keypair = defaultdict(str) + if all_files_exist(keypair, '{0}.pub'.format(keypair)): + self.keypair['private'] = keypair + self.keypair['public'] = '{0}.pub'.format(keypair) + else: + raise RuntimeError("The keypairs you in the configuration file" + " is invalid or not existed.") + + def generate_default_keypair(self): + if not all_files_exist(PRIVATE_KEY, PUBLIC_KEY): + logger.info("Generate default keypair {0} under " + "{1}".format(KEYNAME, os.environ['HOME'])) + cmd = '''ssh-keygen -t rsa -N "" -f {0} -q -b 2048 + -C qtip@insecure'''.format(PRIVATE_KEY) + os.system(cmd) + self.keypair['private'] = PRIVATE_KEY + self.keypair['public'] = PUBLIC_KEY + + def pass_keypair_to_remote(self): + results = map(lambda ip: self._pass_keypair(ip, self.keypair['private']), + self.host_ip_list) + + if not (len(results) == len(self.host_ip_list) and False not in results): + raise RuntimeError("Failed on passing keypair to remote.") + + @staticmethod + def _pass_keypair(ip, private_key): + try: + os.system('ssh-keyscan %s >> /root/.ssh/known_hosts' % ip) + time.sleep(2) + ssh_cmd = '%s/qtip_creds.sh %s %s' % (SCRIPT_DIR, ip, private_key) + os.system(ssh_cmd) + logger.info('Pass keypair to remote hosts {0} successfully'.format(ip)) + return True + except Exception as error: + logger.error(error) + return False + def check_hostfile(self, hostfile): + if all_files_exist(hostfile): + self.hostfile = hostfile + else: + raise RuntimeError( + "The hostfile {0} is invalid or not existed.".format(hostfile)) -def clean_file(file_path): - try: - if path.isfile(file_path): - os.remove(file_path) - print("Removed: " + file_path) + def generate_default_hostfile(self): + try: + # check whether the file is already existed + self.check_hostfile(HOST_FILE) + except Exception: + logger.info("Generate default hostfile {0} under " + "{1}".format(HOST_FILE, os.environ['HOME'])) + self._generate_hostfile_via_installer() + + def _generate_hostfile_via_installer(self): + self.hostfile = None + + installer_type = str(os.environ['INSTALLER_TYPE'].lower()) + installer_ip = str(os.environ['INSTALLER_IP']) + + if installer_type not in ["fuel"]: + raise ValueError("{0} is not supported".format(installer_type)) + if not installer_ip: + raise ValueError( + "The value of environment variable INSTALLER_IP is empty.") + + cmd = "bash %s/generate_host_file.sh -t %s -i %s -d %s" % \ + (SCRIPT_DIR, installer_type, installer_ip, HOST_FILE) + os.system(cmd) + + self.hostfile = HOST_FILE + + def fetch_host_ip_from_hostfile(self): + self.host_ip_list = [] + logger.info('Fetch host ips from hostfile...') + with open(self.hostfile, 'r') as f: + self.host_ip_list = re.findall('\d+.\d+.\d+.\d+', f.read()) + if self.host_ip_list: + logger.info("The remote compute nodes: {0}".format(self.host_ip_list)) else: - print("Not exists: " + file_path) - except OSError, error: - print("Not able to Remove: " + file_path, error) + raise ValueError("The hostfile doesn't include host ip addresses.") + + def check_hosts_ssh_connectivity(self): + results = map(lambda ip: self._ssh_is_ok(ip, self.keypair['private']), + self.host_ip_list) + if not (len(results) == len(self.host_ip_list) and False not in results): + raise RuntimeError("Failed on checking hosts ssh connectivity.") + + @staticmethod + def _ssh_is_ok(ip, private_key, attempts=100): + logger.info('Check hosts {0} ssh connectivity...'.format(ip)) + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect(ip, key_filename=private_key) + + for attempt in range(attempts): + try: + stdin, stdout, stderr = ssh.exec_command('uname') + if not stderr.readlines(): + logger.info("{0}: SSH test successful.".format(ip)) + return True + except socket.error: + logger.debug("%s times ssh test......failed." % str(attempt + 1)) + if attempt == (attempts - 1): + return False + time.sleep(2) return False - return True + def cleanup(self): + CI_DEBUG = os.getenv('CI_DEBUG') -def clean_keypair(): - flag = True - flag &= clean_file(PRIVATE_KEY) - flag &= clean_file(PUBLIC_KEY) - return flag + if CI_DEBUG is not None and CI_DEBUG.lower() == 'true': + logger.info("DEBUG Mode: please do cleanup by manual.") + else: + with open(self.keypair['public'], 'r') as f: + key = f.read().strip('\n').replace('/', '\/') + if key: + for ip in self.host_ip_list: + logger.info("Cleanup authorized_keys from {0}...".format(ip)) + cmd = '''bash {0}/cleanup_creds.sh {1} {2} "{3}"'''.format( + SCRIPT_DIR, ip, self.keypair['private'], key) + os.system(cmd) + else: + logger.error("Nothing in public key file.") + + logger.info("Cleanup hostfile and keypair.") + clean_file(self.hostfile, + self.keypair['private'], + self.keypair['public']) diff --git a/requirements.txt b/requirements.txt index c51228f2..d00b3cf1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,5 @@ paramiko connexion numpy pbr +ConfigParser +prettytable @@ -14,11 +14,15 @@ setup-hooks = [entry_points] console_scripts = qtip = qtip.cli.entry:cli - # TODO(akhil) add qtip-api + qtip-api = qtip.api.__main__:main [files] packages = qtip + benchmarks +package_data = + benchmarks = + plan/*.* data_files = opt/qtip = opt/* diff --git a/test-requirements.txt b/test-requirements.txt index e434748e..cfbbdcdd 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,6 +5,7 @@ tox pytest pytest-cov +pytest-mock coverage pykwalify mock diff --git a/tests/data/benchmarks/plan/compute.yaml b/tests/data/benchmarks/plan/compute.yaml index 8529d8dc..f4a7a2dc 100644 --- a/tests/data/benchmarks/plan/compute.yaml +++ b/tests/data/benchmarks/plan/compute.yaml @@ -16,6 +16,80 @@ config: collectors: - type: logfile paths: + - '../../external/dpi/' + logs: + - filename: dpi_dump.txt + parsers: + - type: grep + regex: |- + ^\s+nDPI throughput:.+?(?P<pps>\d+.\d+)\sM\spps.+ + ?(?P<bps>\d+.\d+)\sGb\/sec + - type: logfile + paths: + - '../../external/ramspeed/' + logs: + - filename: Intmem + parsers: + - type: grep + regex: '^INTEGER\s+BatchRun\s+Copy:\s+?(?P<integer_copy>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Scale:\s+?(?P<integer_scale>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Add:\s+?(?P<integer_add>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+Triad:\s+?(?P<integer_triad>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^INTEGER\s+BatchRun\s+AVERAGE:\s+?(?P<integer_average>\d+\.\d+)\sMB/s$' + - filename: Floatmem + parsers: + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Copy:\s+?(?P<float_copy>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Scale:\s+?(?P<float_scale>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Add:\s+?(?P<float_add>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+Triad:\s+?(?P<float_triad>\d+\.\d+)\sMB/s$' + - type: grep + regex: '^FL-POINT\s+BatchRun\s+AVERAGE:\s+?(?P<float_average>\d+\.\d+)\sMB/s$' + - type: logfile + paths: + - '../../external/ssl/' + logs: + - filename: RSA_dump + parsers: + - type: grep + regex: |- + ^rsa\s+512\sbits\s.+ + ?(?P<rsa_sign_512>\d+\.\d)\s+ + ?(?P<rsa_verify_512>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+1024\sbits\s.+ + ?(?P<rsa_sign_1024>\d+\.\d)\s+ + ?(?P<rsa_verify_1024>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+2048\sbits\s.+ + ?(?P<rsa_sign_2048>\d+\.\d)\s+ + ?(?P<rsa_verify_2048>\d+\.\d)$ + - type: grep + regex: |- + ^rsa\s+4096\sbits\s.+ + ?(?P<rsa_sign_4096>\d+\.\d)\s+ + ?(?P<rsa_verify_4096>\d+\.\d)$ + - filename: AES-128-CBC_dump + parsers: + - type: grep + regex: |- + ^aes-128-cbc\s+ + ?(?P<aes_128_cbc_16_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_64_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_256_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_1024_bytes>\d+\.\w+)\s+ + ?(?P<aes_128_cbc_8192_bytes>\d+\.\w+)$ + - type: logfile + paths: - '../../external/sysinfo' logs: - filename: top.log diff --git a/qtip/driver/ansible/ansible.py b/tests/data/benchmarks/plan/sample.yaml index cd17625d..04e8caf9 100644 --- a/qtip/driver/ansible/ansible.py +++ b/tests/data/benchmarks/plan/sample.yaml @@ -1,14 +1,14 @@ ############################################################################## -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 ZTE Corporation and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## - -from qtip.driver.base import BaseDriver - - -class AnsibleDriver(BaseDriver): - """driver for running performance tests with Ansible""" +name: sample +description: sample benchmark plan for testing default path +config: + collectors: [] + reporters: [] +QPIs: [] diff --git a/tests/data/external/dpi/dpi_dump.txt b/tests/data/external/dpi/dpi_dump.txt new file mode 100644 index 00000000..1f4e2839 --- /dev/null +++ b/tests/data/external/dpi/dpi_dump.txt @@ -0,0 +1,809 @@ +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.56 M pps / 14.62 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.31 M pps / 12.31 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.54 M pps / 14.45 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.35 M pps / 12.71 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.55 M pps / 14.53 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.32 M pps / 12.42 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.54 M pps / 14.46 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.54 M pps / 14.49 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.37 M pps / 12.89 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes + +----------------------------------------------------------- +* NOTE: This is demo app to show *some* nDPI features. +* In this demo we have implemented only some basic features +* just to show you what you can do with the library. Feel +* free to extend it and send us the patches for inclusion +------------------------------------------------------------ + +Using nDPI (1.8.0-dev-707-6a27b62) [1 thread(s)] +Reading packets from pcap file test.pcap... +Running thread 0... + +nDPI Memory statistics: + nDPI Memory (once): 110.55 KB + Flow Memory (per flow): 1.95 KB + Actual Memory: 3.46 MB + Peak Memory: 3.46 MB + +Traffic statistics: + Ethernet bytes: 75948198 (includes ethernet CRC/IFC/trailer) + Discarded bytes: 55256 + IP packets: 60265 of 61155 packets total + IP bytes: 74501838 (avg pkt size 1218 bytes) + Unique flows: 545 + TCP Packets: 21188 + UDP Packets: 39042 + VLAN Packets: 0 + MPLS Packets: 0 + PPPoE Packets: 0 + Fragmented Packets: 4 + Max Packet size: 64260 + Packet Len < 64: 30624 + Packet Len 64-128: 1158 + Packet Len 128-256: 674 + Packet Len 256-1024: 817 + Packet Len 1024-1500: 21924 + Packet Len > 1500: 5068 + nDPI throughput: 1.55 M pps / 14.57 Gb/sec + Traffic throughput: 228.03 pps / 2.19 Mb/sec + Traffic duration: 264.290 sec + Guessed flow protos: 9 + + +Detected protocols: + Unknown packets: 6126 bytes: 10913415 flows: 46 + FTP_CONTROL packets: 42 bytes: 4384 flows: 1 + DNS packets: 66 bytes: 6520 flows: 23 + IPP packets: 46 bytes: 12059 flows: 1 + HTTP packets: 377 bytes: 113616 flows: 24 + MDNS packets: 43 bytes: 11742 flows: 9 + NetBIOS packets: 48 bytes: 4754 flows: 12 + SSDP packets: 101 bytes: 32533 flows: 21 + DHCP packets: 21 bytes: 7346 flows: 2 + BitTorrent packets: 37639 bytes: 29656716 flows: 65 + ICMP packets: 15 bytes: 4956 flows: 5 + IGMP packets: 10 bytes: 600 flows: 9 + SSL packets: 1199 bytes: 622508 flows: 24 + ICMPV6 packets: 2 bytes: 172 flows: 2 + DHCPV6 packets: 1 bytes: 144 flows: 1 + Facebook packets: 349 bytes: 206444 flows: 21 + Twitter packets: 137 bytes: 45679 flows: 8 + Dropbox packets: 155 bytes: 45358 flows: 12 + GMail packets: 35 bytes: 10470 flows: 3 + YouTube packets: 11721 bytes: 31050728 flows: 33 + Skype packets: 237 bytes: 35082 flows: 30 + Google packets: 558 bytes: 164639 flows: 52 + WhatsApp packets: 969 bytes: 1477350 flows: 17 + Viber packets: 60 bytes: 27602 flows: 1 + LLMNR packets: 71 bytes: 5297 flows: 36 + Amazon packets: 89 bytes: 23572 flows: 9 + QUIC packets: 41 bytes: 3474 flows: 1 + BJNP packets: 72 bytes: 4320 flows: 72 + Microsoft packets: 35 bytes: 10358 flows: 5 + + +Protocol statistics: + Safe 632978 bytes + Acceptable 31693889 bytes + Fun 31257172 bytes + Unsafe 4384 bytes + Unrated 10913415 bytes
\ No newline at end of file diff --git a/tests/data/external/ramspeed/Floatmem b/tests/data/external/ramspeed/Floatmem new file mode 100644 index 00000000..f3cc1e6d --- /dev/null +++ b/tests/data/external/ramspeed/Floatmem @@ -0,0 +1,52 @@ +RAMspeed/SMP (Linux) v3.5.0 by Rhett M. Hollander and Paul V. Bolotoff, 2002-09 + +8Gb per pass mode, 1 processes + +5-benchmark FLOATmem BatchRun mode + +Benchmark #1: +FL-POINT Copy: 8220.47 MB/s +FL-POINT Scale: 8195.78 MB/s +FL-POINT Add: 10319.18 MB/s +FL-POINT Triad: 10403.87 MB/s +--- +FL-POINT AVERAGE: 9284.83 MB/s + +Benchmark #2: +FL-POINT Copy: 8086.66 MB/s +FL-POINT Scale: 7842.82 MB/s +FL-POINT Add: 9900.13 MB/s +FL-POINT Triad: 10029.43 MB/s +--- +FL-POINT AVERAGE: 8964.76 MB/s + +Benchmark #3: +FL-POINT Copy: 7766.98 MB/s +FL-POINT Scale: 7837.62 MB/s +FL-POINT Add: 9827.57 MB/s +FL-POINT Triad: 9918.89 MB/s +--- +FL-POINT AVERAGE: 8837.77 MB/s + +Benchmark #4: +FL-POINT Copy: 7647.89 MB/s +FL-POINT Scale: 7594.00 MB/s +FL-POINT Add: 9873.93 MB/s +FL-POINT Triad: 9970.89 MB/s +--- +FL-POINT AVERAGE: 8771.68 MB/s + +Benchmark #5: +FL-POINT Copy: 7821.21 MB/s +FL-POINT Scale: 7880.56 MB/s +FL-POINT Add: 9914.84 MB/s +FL-POINT Triad: 10044.05 MB/s +--- +FL-POINT AVERAGE: 8915.17 MB/s + +FL-POINT BatchRun Copy: 7908.64 MB/s +FL-POINT BatchRun Scale: 7870.16 MB/s +FL-POINT BatchRun Add: 9967.13 MB/s +FL-POINT BatchRun Triad: 10073.43 MB/s +--- +FL-POINT BatchRun AVERAGE: 8954.84 MB/s
\ No newline at end of file diff --git a/tests/data/external/ramspeed/Intmem b/tests/data/external/ramspeed/Intmem new file mode 100644 index 00000000..08fffe47 --- /dev/null +++ b/tests/data/external/ramspeed/Intmem @@ -0,0 +1,52 @@ +RAMspeed/SMP (Linux) v3.5.0 by Rhett M. Hollander and Paul V. Bolotoff, 2002-09 + +8Gb per pass mode, 1 processes + +5-benchmark INTmem BatchRun mode + +Benchmark #1: +INTEGER Copy: 11493.80 MB/s +INTEGER Scale: 11527.61 MB/s +INTEGER Add: 11567.60 MB/s +INTEGER Triad: 11546.06 MB/s +--- +INTEGER AVERAGE: 11533.77 MB/s + +Benchmark #2: +INTEGER Copy: 11580.06 MB/s +INTEGER Scale: 11617.25 MB/s +INTEGER Add: 11748.95 MB/s +INTEGER Triad: 11837.43 MB/s +--- +INTEGER AVERAGE: 11695.92 MB/s + +Benchmark #3: +INTEGER Copy: 11674.45 MB/s +INTEGER Scale: 11566.59 MB/s +INTEGER Add: 11643.59 MB/s +INTEGER Triad: 11633.42 MB/s +--- +INTEGER AVERAGE: 11629.51 MB/s + +Benchmark #4: +INTEGER Copy: 11496.38 MB/s +INTEGER Scale: 11528.06 MB/s +INTEGER Add: 11641.10 MB/s +INTEGER Triad: 11742.61 MB/s +--- +INTEGER AVERAGE: 11602.04 MB/s + +Benchmark #5: +INTEGER Copy: 11568.45 MB/s +INTEGER Scale: 11579.32 MB/s +INTEGER Add: 11646.55 MB/s +INTEGER Triad: 11596.57 MB/s +--- +INTEGER AVERAGE: 11597.72 MB/s + +INTEGER BatchRun Copy: 11562.63 MB/s +INTEGER BatchRun Scale: 11563.77 MB/s +INTEGER BatchRun Add: 11649.55 MB/s +INTEGER BatchRun Triad: 11671.22 MB/s +--- +INTEGER BatchRun AVERAGE: 11611.79 MB/s
\ No newline at end of file diff --git a/tests/data/external/ssl/AES-128-CBC_dump b/tests/data/external/ssl/AES-128-CBC_dump new file mode 100644 index 00000000..32568e14 --- /dev/null +++ b/tests/data/external/ssl/AES-128-CBC_dump @@ -0,0 +1,7 @@ +OpenSSL 1.0.2f 28 Jan 2016 +built on: reproducible build, date unspecified +options:bn(64,64) rc4(16x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx) +compiler: gcc -I. -I.. -I../include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM +The 'numbers' are in 1000s of bytes per second processed. +type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes +aes-128-cbc 533103.05k 570042.22k 580021.25k 584568.83k 599470.83k
\ No newline at end of file diff --git a/tests/data/external/ssl/RSA_dump b/tests/data/external/ssl/RSA_dump new file mode 100644 index 00000000..55e40792 --- /dev/null +++ b/tests/data/external/ssl/RSA_dump @@ -0,0 +1,9 @@ +OpenSSL 1.0.2f 28 Jan 2016 +built on: reproducible build, date unspecified +options:bn(64,64) rc4(16x,int) des(idx,cisc,16,int) aes(partial) idea(int) blowfish(idx) +compiler: gcc -I. -I.. -I../include -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -Wa,--noexecstack -m64 -DL_ENDIAN -O3 -Wall -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM + sign verify sign/s verify/s +rsa 512 bits 0.000056s 0.000004s 17828.4 222903.5 +rsa 1024 bits 0.000169s 0.000011s 5923.9 88397.9 +rsa 2048 bits 0.000793s 0.000037s 1261.4 26951.3 +rsa 4096 bits 0.008280s 0.000131s 120.8 7633.7 diff --git a/tests/unit/api/conftest.py b/tests/unit/api/conftest.py new file mode 100644 index 00000000..23a3be82 --- /dev/null +++ b/tests/unit/api/conftest.py @@ -0,0 +1,22 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import pytest + +from qtip.api import __main__ + + +@pytest.fixture(scope="session") +def app(): + return __main__.get_app().app + + +@pytest.fixture(scope="session") +def app_client(app): + return app.test_client() diff --git a/tests/unit/api/metric_controller_test.py b/tests/unit/api/metric_controller_test.py new file mode 100644 index 00000000..caba7972 --- /dev/null +++ b/tests/unit/api/metric_controller_test.py @@ -0,0 +1,37 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib +import json + +from qtip.base.constant import BaseProp + + +def test_get_list_metrics(app_client): + response_success = app_client.get("/v1.0/metrics") + assert response_success.status_code == httplib.OK + metric_list = json.loads(response_success.data)['metrics'] + assert len(metric_list) > 0 + assert metric_list[0].endswith('.yaml') + + +def test_get_metric(app_client): + response_success = app_client.get("/v1.0/metrics/dpi.yaml") + assert response_success.status_code == httplib.OK + metric_data = json.loads(response_success.data) + assert BaseProp.NAME in metric_data + assert BaseProp.WORKLOADS in metric_data + assert isinstance(metric_data[BaseProp.WORKLOADS], list) + + +def test_get_metric_not_found(app_client): + response_not_found = app_client.get("/v1.0/metrics/fake.yaml") + response_data = json.loads(response_not_found.data) + assert response_not_found.status_code == httplib.NOT_FOUND + assert response_data['title'] == "Metric not found" diff --git a/tests/unit/api/plan_controller_test.py b/tests/unit/api/plan_controller_test.py new file mode 100644 index 00000000..136bd3c6 --- /dev/null +++ b/tests/unit/api/plan_controller_test.py @@ -0,0 +1,49 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib +import json + + +from qtip.loader.plan import PlanProp + + +def test_invalid_url(app_client): + response_url_not_found = app_client.get("/v1.0/fakeresource") + assert response_url_not_found.status_code == httplib.NOT_FOUND + + +def test_get_list_plans(app_client): + response_success = app_client.get("/v1.0/plans") + assert response_success.status_code == httplib.OK + plan_list = json.loads(response_success.data)['plans'] + assert len(plan_list) > 0 + assert plan_list[0].endswith('.yaml') + + +def test_get_plan(app_client): + response_success = app_client.get("/v1.0/plans/sample.yaml") + assert response_success.status_code == httplib.OK + plan_data = json.loads(response_success.data) + assert PlanProp.NAME in plan_data + assert PlanProp.DESCRIPTION in plan_data + assert PlanProp.CONFIG in plan_data + assert PlanProp.QPIS in plan_data + + +def test_get_plan_not_found(app_client): + response_not_found = app_client.get("/v1.0/plans/fake.yaml") + response_data = json.loads(response_not_found.data) + assert response_not_found.status_code == httplib.NOT_FOUND + assert response_data['title'] == "Plan not found" + + +def test_runner_not_implemented(app_client): + response_error = app_client.post("/v1.0/plans/fake.yaml?action=run", follow_redirects=False) + assert response_error.status_code == httplib.NOT_IMPLEMENTED diff --git a/tests/unit/api/qpi_controller_test.py b/tests/unit/api/qpi_controller_test.py new file mode 100644 index 00000000..6291dd9b --- /dev/null +++ b/tests/unit/api/qpi_controller_test.py @@ -0,0 +1,43 @@ +############################################################################## +# Copyright (c) 2017 akhil.batra@research.iiit.ac.in and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import httplib +import json + +from qtip.base.constant import FormulaName +from qtip.base.constant import SpecProp + + +def test_get_list_qpis(app_client): + response_success = app_client.get("/v1.0/qpis") + assert response_success.status_code == httplib.OK + qpi_spec_list = json.loads(response_success.data)['qpis'] + assert len(qpi_spec_list) > 0 + assert qpi_spec_list[0].endswith('.yaml') + + +def test_get_qpi(app_client): + response_success = app_client.get("/v1.0/qpis/compute.yaml") + assert response_success.status_code == httplib.OK + qpi_data = json.loads(response_success.data) + assert SpecProp.DESCRIPTION in qpi_data + assert SpecProp.FORMULA in qpi_data + assert SpecProp.SECTIONS in qpi_data + assert qpi_data[SpecProp.FORMULA] in FormulaName.__dict__.values() + sections = qpi_data[SpecProp.SECTIONS] + assert isinstance(sections, list) + for section in sections: + assert SpecProp.NAME in section + + +def test_get_qpi_not_found(app_client): + response_not_found = app_client.get("/v1.0/qpis/fake.yaml") + response_data = json.loads(response_not_found.data) + assert response_not_found.status_code == httplib.NOT_FOUND + assert response_data['title'] == "QPI not found" diff --git a/tests/unit/cli/cmd_metric_test.py b/tests/unit/cli/cmd_metric_test.py index 30f3448a..cd496ad9 100644 --- a/tests/unit/cli/cmd_metric_test.py +++ b/tests/unit/cli/cmd_metric_test.py @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -8,8 +8,8 @@ ############################################################################## import pytest -from click.testing import CliRunner +from click.testing import CliRunner from qtip.cli.entry import cli @@ -20,7 +20,9 @@ def runner(): def test_list(runner): result = runner.invoke(cli, ['metric', 'list']) - assert result.output == '' + assert 'dhrystone' and 'whetstone' and 'dpi' and \ + 'ramspeed' and 'fake-metric' and 'ssl' \ + in result.output def test_run(runner): @@ -32,8 +34,10 @@ def test_run(runner): def test_show(runner): - result = runner.invoke(cli, ['metric', 'show', 'fake-metric']) - assert result.output == '' + result = runner.invoke(cli, ['metric', 'show', 'dhrystone']) + assert 'Name: dhrystone' in result.output + assert 'Description: A synthetic computing benchmark program intended to be representative of' \ + 'system (integer) programming.' result = runner.invoke(cli, ['metric', 'show']) assert 'Missing argument "name".' in result.output diff --git a/tests/unit/cli/cmd_plan_test.py b/tests/unit/cli/cmd_plan_test.py index 1708c340..30025ae0 100644 --- a/tests/unit/cli/cmd_plan_test.py +++ b/tests/unit/cli/cmd_plan_test.py @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -20,7 +20,7 @@ def runner(): def test_list(runner): result = runner.invoke(cli, ['plan', 'list']) - assert result.output == '' + assert 'Plan' and 'compute' and 'sample' in result.output def test_run(runner): @@ -32,8 +32,9 @@ def test_run(runner): def test_show(runner): - result = runner.invoke(cli, ['plan', 'show', 'fake-plan']) - assert result.output == '' + result = runner.invoke(cli, ['plan', 'show', 'compute']) + assert 'Name: compute QPI' in result.output + assert 'Description: compute QPI profile' result = runner.invoke(cli, ['plan', 'show']) assert 'Missing argument "name".' in result.output diff --git a/tests/unit/cli/cmd_qpi_test.py b/tests/unit/cli/cmd_qpi_test.py index 485d5462..3d2c2613 100644 --- a/tests/unit/cli/cmd_qpi_test.py +++ b/tests/unit/cli/cmd_qpi_test.py @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -8,9 +8,9 @@ ############################################################################## import pytest -from click.testing import CliRunner from qtip.cli.entry import cli +from click.testing import CliRunner @pytest.fixture(scope="module") @@ -20,7 +20,7 @@ def runner(): def test_list(runner): result = runner.invoke(cli, ['qpi', 'list']) - assert result.output == '' + assert 'QPIs' and 'compute' in result.output def test_run(runner): @@ -32,8 +32,9 @@ def test_run(runner): def test_show(runner): - result = runner.invoke(cli, ['qpi', 'show', 'fake-qpi']) - assert result.output == '' + result = runner.invoke(cli, ['qpi', 'show', 'compute']) + assert 'Name: compute' in result.output + assert 'Description: sample performance index of computing' in result.output result = runner.invoke(cli, ['qpi', 'show']) assert 'Missing argument "name".' in result.output diff --git a/tests/unit/cli/cmd_report_test.py b/tests/unit/cli/cmd_report_test.py new file mode 100644 index 00000000..963ce987 --- /dev/null +++ b/tests/unit/cli/cmd_report_test.py @@ -0,0 +1,91 @@ +############################################################### +# Copyright (c) 2017 taseer94@gmail.com and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import pytest + +from click.testing import CliRunner +from qtip.cli.entry import cli + + +@pytest.fixture(scope="module") +def runner(): + return CliRunner() + + +def test_dhrystone(runner): + """Test dhrystone report""" + + result = runner.invoke(cli, ['report', 'show', 'dhrystone']) + assert "Benchmark: dhrystone" in result.output + assert "CPU Usage: 3%" in result.output + assert "Number: 40" in result.output + assert "Score: 63529.6" in result.output + assert "Single CPU:" in result.output + assert "Total CPUs: 40" in result.output + + +def test_whetstone(runner): + """ Test whetstone output""" + + result = runner.invoke(cli, ['report', 'show', 'whetstone']) + assert "Benchmark: whetstone" in result.output + assert "CPU Usage: 3%" in result.output + assert "Results:" in result.output + assert "Multi CPU:" in result.output + assert "Number: 40" in result.output + assert "Score: 21198.3" in result.output + assert "Single CPU:" in result.output + + +def test_dpi(runner): + """ Test dpi report""" + result = runner.invoke(cli, ['report', 'show', 'dpi']) + assert "Benchmark: dpi" in result.output + assert "CPU Usage: 3%" in result.output + assert "Bits per Second: 3.638" in result.output + assert "Packets per Second: 1.45" in result.output + assert "Bits per Second: 3.69" in result.output + assert "Packets per Second: 1.458" in result.output + + +def test_ramspeed(runner): + """ Test ramspeed report """ + result = runner.invoke(cli, ['report', 'show', 'ramspeed']) + assert "Benchmark: ramspeed" in result.output + assert "CPU Usage: 3%" in result.output + assert "Float Addition: 10217.62" in result.output + assert "Float Average: 9176.88" in result.output + assert "Float Copy: 8127.13" in result.output + assert "Float Scale: 8085.40" in result.output + assert "Float Triad: 10277.38" in result.output + assert "Integer Addition: 11471.63" in result.output + assert "Integer Average: 11396.35" in result.output + + +def test_ssl(runner): + """ Test ssl report""" + + result = runner.invoke(cli, ['report', 'show', 'ssl']) + assert "Benchmark: ssl" in result.output + assert "CPU Usage: 3%" in result.output + assert "AES 128 CBC (bytes):" in result.output + assert "256: 584951.30k" in result.output + assert "RSA SIGN:" in result.output + assert "2048: 9.9" in result.output + assert "RSA VERIFY:" in result.output + assert "4096: 7688.5" in result.output + + +def test_sys(runner): + """ Test sys_info """ + + result = runner.invoke(cli, ['report', 'show', 'ssl']) + assert "System Information:" in result.output + assert "Host Name: node-38.zte.com.cn" in result.output + assert "Memory: 4403.7/128524.1MB" in result.output diff --git a/tests/unit/cli/options_test.py b/tests/unit/cli/options_test.py index f9472814..9dbbe6f3 100644 --- a/tests/unit/cli/options_test.py +++ b/tests/unit/cli/options_test.py @@ -1,5 +1,5 @@ ############################################################### -# Copyright (c) 2016 ZTE Corp and others. +# Copyright (c) 2017 taseer94@gmail.com and others. # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Apache License, Version 2.0 @@ -8,8 +8,9 @@ ############################################################################## import pytest -from click.testing import CliRunner +import sys +from click.testing import CliRunner from qtip.cli.entry import cli @@ -28,5 +29,5 @@ class TestClass(object): assert 'dev' in result.output def test_debug(self, runner): - result = runner.invoke(cli, ['-d']) - assert '' in result.output + runner.invoke(cli, ['-d']) + assert sys.tracebacklimit == 8 diff --git a/tests/unit/collector/base_test.py b/tests/unit/collector/collector_test.py index 17fe1af1..17fe1af1 100644 --- a/tests/unit/collector/base_test.py +++ b/tests/unit/collector/collector_test.py diff --git a/tests/unit/loader/plan_test.py b/tests/unit/loader/plan_test.py index 70ae2ad5..4c92e8d5 100644 --- a/tests/unit/loader/plan_test.py +++ b/tests/unit/loader/plan_test.py @@ -13,15 +13,18 @@ from qtip.collector.logfile import LogfileCollector from qtip.loader.plan import load_collector from qtip.loader.plan import Plan from qtip.loader.plan import PlanProp -from qtip.loader.plan import QPISpec -def test_init(plan): - assert plan.name == 'doctor performance profiling' - assert isinstance(plan.content, dict) - for qpi in plan.qpis: - assert isinstance(qpi, QPISpec) +def test_construct(benchmarks_root): + sample = Plan('sample.yaml') + assert isinstance(sample, Plan) + # fixture can not be used in pytest.mark.parametrized + sample = Plan('sample.yaml', [benchmarks_root]) + assert isinstance(sample, Plan) + + +def test_invalid_construct(): with pytest.raises(TypeError) as excinfo: Plan() assert '__init__() takes at least 2 arguments (1 given)' \ @@ -30,7 +33,7 @@ def test_init(plan): def test_list_all(benchmarks_root): plan_list = list(Plan.list_all(paths=[benchmarks_root])) - assert len(plan_list) is 2 + assert len(plan_list) is 3 for desc in plan_list: assert PlanProp.NAME in desc assert PlanProp.ABSPATH in desc diff --git a/tests/unit/reporter/console_test.py b/tests/unit/reporter/console_test.py new file mode 100644 index 00000000..aa7f848b --- /dev/null +++ b/tests/unit/reporter/console_test.py @@ -0,0 +1,89 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import pytest + +from qtip.reporter.console import ConsoleReporter + + +@pytest.fixture +def console_reporter(): + return ConsoleReporter({}) + + +def test_constructor(console_reporter): + assert isinstance(console_reporter, ConsoleReporter) + + +def test_dhrystone(console_reporter): + """ Test dhrystone report""" + + result = console_reporter.render('dhrystone') + assert "Benchmark: dhrystone" in result + assert "Number: 40" in result + assert "Score: 63529.6" in result + assert "Single CPU:" in result + assert "Total CPUs: 40" in result + + +def test_whetstone(console_reporter): + """ Test whetstone output""" + + result = console_reporter.render('whetstone') + assert "Benchmark: whetstone" in result + assert "Results:" in result + assert "Multi CPU:" in result + assert "Number: 40" in result + assert "Score: 21198.3" in result + assert "Single CPU:" in result + + +def test_dpi(console_reporter): + """ Test dpi report""" + + result = console_reporter.render('dpi') + assert "Benchmark: dpi" in result + assert "Bits per Second: 3.638" in result + assert "Packets per Second: 1.45" in result + assert "Bits per Second: 3.69" in result + assert "Packets per Second: 1.458" in result + + +def test_ramspeed(console_reporter): + """ Test ramspeed report """ + + result = console_reporter.render('ramspeed') + assert "Float Addition: 10217.62" in result + assert "Float Average: 9176.88" in result + assert "Float Copy: 8127.13" in result + assert "Float Scale: 8085.40" in result + assert "Float Triad: 10277.38" in result + assert "Integer Addition: 11471.63" in result + assert "Integer Average: 11396.35" in result + + +def test_ssl(console_reporter): + """ Test ssl report""" + + result = console_reporter.render('ssl') + assert "AES 128 CBC (bytes):" in result + assert "256: 584951.30k" in result + assert "RSA SIGN:" in result + assert "2048: 9.9" in result + assert "RSA VERIFY:" in result + assert "4096: 7688.5" in result + + +def test_sys(console_reporter): + """ Test sys_info """ + + result = console_reporter.render('ssl') + assert "System Information:" in result + assert "Host Name: node-38.zte.com.cn" in result + assert "Memory: 4403.7/128524.1MB" in result diff --git a/qtip/reporter/console/__init__.py b/tests/unit/runner/runner_test.py index 02d63288..b7da1611 100644 --- a/qtip/reporter/console/__init__.py +++ b/tests/unit/runner/runner_test.py @@ -8,8 +8,9 @@ ############################################################################## -from qtip.reporter.base import BaseReporter +from qtip.runner.base import BaseRunner -class ConsoleReporter(BaseReporter): - """report result to console""" +def test_constructor(): + runner = BaseRunner() + assert isinstance(runner, BaseRunner) diff --git a/tests/unit/util/env_test.py b/tests/unit/util/env_test.py new file mode 100644 index 00000000..793d1e4e --- /dev/null +++ b/tests/unit/util/env_test.py @@ -0,0 +1,307 @@ +############################################################### +# Copyright (c) 2017 ZTE Corporation +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import time + +import pytest +import mock +from collections import defaultdict +import socket + +from qtip.util import env +from qtip.util.env import AnsibleEnvSetup + + +@pytest.fixture(scope='session') +def ansible_envsetup(): + return AnsibleEnvSetup() + + +@pytest.fixture() +def hostfile(tmpdir): + fake_hostfile = tmpdir.join('hosts') + fake_hostfile.write("[hosts]\n") + fake_hostfile.write("10.20.0.3") + return fake_hostfile + + +@pytest.fixture() +def private_key(tmpdir): + fake_private_key = tmpdir.join('QtipKey') + fake_private_key.write("fake keypair") + return fake_private_key + + +@pytest.fixture() +def public_key(tmpdir): + fake_public_key = tmpdir.join('QtipKey.pub') + fake_public_key.write("fake public key") + return fake_public_key + + +def test_all_files_exist(tmpdir): + exist_file = tmpdir.mkdir('qtip').join('hello.txt') + exist_file.write("hello") + non_exist_file = tmpdir.strpath + '/tmp.txt' + assert env.all_files_exist() is False + assert env.all_files_exist(str(exist_file)) + assert env.all_files_exist(non_exist_file) is False + assert env.all_files_exist(str(exist_file), non_exist_file) is False + + +def test_clean_file(tmpdir): + exist_file = tmpdir.mkdir('qtip').join('hello.txt') + exist_file.write("hello") + non_exist_file = tmpdir.strpath + '/tmp.txt' + + assert env.clean_file() is False + assert env.clean_file(str(exist_file)) + assert env.clean_file(non_exist_file) + + +def test_init(ansible_envsetup): + assert 'AnsibleEnvSetup' in str(type(ansible_envsetup)) + assert ansible_envsetup.keypair == defaultdict(str) + assert ansible_envsetup.hostfile is None + assert ansible_envsetup.host_ip_list == [] + + +def test_setup_exception(mocker, ansible_envsetup, hostfile): + with mock.patch.object(AnsibleEnvSetup, 'check_hostfile', side_effect=RuntimeError()): + mock_os = mocker.patch('sys.exit') + ansible_envsetup.setup({'hostfile': str(hostfile)}) + assert mock_os.call_count == 1 + + +# TODO(zhihui_wu) Need find a smart way to write this pytest +def test_setup(mocker, ansible_envsetup): + mock_check_hostfile = \ + mocker.patch.object(AnsibleEnvSetup, 'check_hostfile') + mock_generate_default_hostfile = \ + mocker.patch.object(AnsibleEnvSetup, 'generate_default_hostfile') + mock_fetch_ip = \ + mocker.patch.object(AnsibleEnvSetup, 'fetch_host_ip_from_hostfile') + mock_check_keypair = \ + mocker.patch.object(AnsibleEnvSetup, 'check_keypair') + mock_generate_default_keypair = \ + mocker.patch.object(AnsibleEnvSetup, 'generate_default_keypair') + mock_pass_keypair = \ + mocker.patch.object(AnsibleEnvSetup, 'pass_keypair_to_remote') + mock_check_ssh = \ + mocker.patch.object(AnsibleEnvSetup, 'check_hosts_ssh_connectivity') + + ansible_envsetup.setup({'keypair': str(private_key), + 'hostfile': str(hostfile)}) + mock_check_hostfile.assert_called_with(str(hostfile)) + mock_fetch_ip.assert_called_with() + mock_check_keypair.assert_called_with(str(private_key)) + mock_pass_keypair.assert_called_with() + mock_check_ssh.assert_called_with() + + ansible_envsetup.setup({'keypair': str(private_key)}) + mock_generate_default_hostfile.assert_called_with() + mock_fetch_ip.assert_called_with() + mock_check_keypair.assert_called_with(str(private_key)) + mock_pass_keypair.assert_called_with() + mock_check_ssh.assert_called_with() + + ansible_envsetup.setup({'hostfile': str(hostfile)}) + mock_check_hostfile.assert_called_with(str(hostfile)) + mock_fetch_ip.assert_called_with() + mock_generate_default_keypair.assert_called_with() + mock_pass_keypair.assert_called_with() + mock_check_ssh.assert_called_with() + + ansible_envsetup.setup() + mock_generate_default_hostfile.assert_called_with() + mock_fetch_ip.assert_called_with() + mock_generate_default_keypair.assert_called_with() + mock_pass_keypair.assert_called_with() + mock_check_ssh.assert_called_with() + + +def test_check_keypair(mocker, ansible_envsetup, private_key, public_key): + with mocker.patch.object(env, 'all_files_exist', return_value=True): + ansible_envsetup.check_keypair(str(private_key)) + assert ansible_envsetup.keypair['private'] == str(private_key) + assert ansible_envsetup.keypair['public'] == str(public_key) + + +def test_check_keypair_failed(mocker, ansible_envsetup): + mocker.patch.object(env, 'all_files_exist', return_value=False) + with pytest.raises(RuntimeError) as excinfo: + ansible_envsetup.check_keypair(str(private_key)) + assert 'The keypairs you in the configuration file ' \ + 'is invalid or not existed.' == str(excinfo.value) + assert ansible_envsetup.keypair['private'] == '' + assert ansible_envsetup.keypair['public'] == '' + + +@pytest.mark.parametrize("file_existence, expected", [ + (True, 0), + (False, 1) +]) +def test_generate_default_keypair(mocker, ansible_envsetup, file_existence, expected): + mock_os = mocker.patch('os.system') + mocker.patch.object(env, 'all_files_exist', return_value=file_existence) + ansible_envsetup.generate_default_keypair() + assert mock_os.call_count == expected + assert ansible_envsetup.keypair['private'] == env.PRIVATE_KEY + assert ansible_envsetup.keypair['public'] == env.PUBLIC_KEY + + +@pytest.mark.parametrize("ips, expected", [ + (['10.20.0.3'], 1), + (['10.20.0.3', '10.20.0.4'], 2) +]) +def test_pass_keypair_to_remote_successful(mocker, ansible_envsetup, ips, expected): + ansible_envsetup.host_ip_list = ips + mock_pass_keypair = \ + mocker.patch.object(AnsibleEnvSetup, '_pass_keypair', return_value=True) + ansible_envsetup.pass_keypair_to_remote() + assert mock_pass_keypair.call_count == expected + + +def test_pass_keypair_to_remote_failed(mocker, ansible_envsetup): + ansible_envsetup.host_ip_list = ['10.20.0.3'] + mocker.patch.object(AnsibleEnvSetup, '_pass_keypair', return_value=False) + with pytest.raises(RuntimeError) as excinfo: + ansible_envsetup.pass_keypair_to_remote() + assert "Failed on passing keypair to remote." in str(excinfo.value) + + +def test_pass_keypair(monkeypatch, mocker, ansible_envsetup): + monkeypatch.setattr(time, 'sleep', lambda s: None) + mock_os = mocker.patch('os.system') + ansible_envsetup._pass_keypair('10.20.0.3', str(private_key)) + assert mock_os.call_count == 2 + + +def test_pass_keypair_exception(ansible_envsetup): + with mock.patch('os.system', side_effect=Exception()) as mock_os: + result = ansible_envsetup._pass_keypair('10.20.0.3', str(private_key)) + assert result is False + assert mock_os.call_count == 1 + + +def test_check_hostfile(mocker, ansible_envsetup, hostfile): + ansible_envsetup.check_hostfile(str(hostfile)) + assert ansible_envsetup.hostfile == str(hostfile) + + with pytest.raises(RuntimeError) as excinfo: + mocker.patch.object(env, 'all_files_exist', return_value=False) + ansible_envsetup.check_hostfile(str(hostfile)) + assert str(excinfo.value) == 'The hostfile {0} is invalid or not ' \ + 'existed.'.format(str(hostfile)) + + +def test_default_hostfile_non_existed(mocker, ansible_envsetup): + with mocker.patch.object(env, 'all_files_exist', return_value=False): + mock_generate_hostfile_via_installer = \ + mocker.patch.object(AnsibleEnvSetup, + '_generate_hostfile_via_installer') + ansible_envsetup.generate_default_hostfile() + mock_generate_hostfile_via_installer.assert_called_once_with() + + +def test_default_hostfile_existed(mocker, ansible_envsetup): + with mocker.patch.object(env, 'all_files_exist', return_value=True): + mock_generate_hostfile_via_installer = \ + mocker.patch.object(AnsibleEnvSetup, + '_generate_hostfile_via_installer') + ansible_envsetup.generate_default_hostfile() + mock_generate_hostfile_via_installer.assert_not_called() + + +@pytest.mark.parametrize("test_input, expected", [ + (({}, KeyError), 'INSTALLER_TYPE'), + (({'INSTALLER_TYPE': 'fuel'}, KeyError), 'INSTALLER_IP'), + (({'INSTALLER_TYPE': 'fuel_1', 'INSTALLER_IP': '10.20.0.2'}, ValueError), + 'fuel_1 is not supported'), + (({'INSTALLER_TYPE': 'fuel', 'INSTALLER_IP': ''}, ValueError), + 'The value of environment variable INSTALLER_IP is empty') +]) +def test_generate_hostfile_via_installer_exception(monkeypatch, ansible_envsetup, test_input, expected): + if test_input[0]: + for key in test_input[0]: + monkeypatch.setenv(key, test_input[0][key]) + + with pytest.raises(test_input[1]) as excinfo: + ansible_envsetup._generate_hostfile_via_installer() + assert expected in str(excinfo.value) + + +def test_generate_hostfile_via_installer(monkeypatch, mocker, ansible_envsetup): + monkeypatch.setenv('INSTALLER_TYPE', 'fuel') + monkeypatch.setenv('INSTALLER_IP', '10.20.0.2') + mock_os = mocker.patch('os.system') + ansible_envsetup._generate_hostfile_via_installer() + assert mock_os.call_count == 1 + assert ansible_envsetup.hostfile == env.HOST_FILE + + +def test_fetch_host_ip_from_hostfile(ansible_envsetup, hostfile): + ansible_envsetup.hostfile = str(hostfile) + ansible_envsetup.fetch_host_ip_from_hostfile() + assert ansible_envsetup.host_ip_list == ['10.20.0.3'] + + +def test_fetch_host_ip_from_empty_hostfile(ansible_envsetup, tmpdir): + empty_hostfile = tmpdir.join('empty_hostfile') + empty_hostfile.write("") + ansible_envsetup.hostfile = str(empty_hostfile) + with pytest.raises(ValueError) as excinfo: + ansible_envsetup.fetch_host_ip_from_hostfile() + assert str(excinfo.value) == "The hostfile doesn't include host ip addresses." + + +@pytest.mark.parametrize("ips, expected", [ + (['10.20.0.3'], 1), + (['10.20.0.3', '10.20.0.4'], 2) +]) +def test_check_hosts_ssh_connectivity(mocker, ansible_envsetup, ips, expected): + ansible_envsetup.host_ip_list = ips + mock_ssh_is_ok = \ + mocker.patch.object(AnsibleEnvSetup, '_ssh_is_ok', return_value=True) + ansible_envsetup.check_hosts_ssh_connectivity() + assert mock_ssh_is_ok.call_count == expected + + +def test_check_hosts_ssh_connectivity_failed(mocker, ansible_envsetup): + ansible_envsetup.host_ip_list = ['10.20.0.3'] + mocker.patch.object(AnsibleEnvSetup, '_ssh_is_ok', return_value=False) + with pytest.raises(RuntimeError) as excinfo: + ansible_envsetup.check_hosts_ssh_connectivity() + assert "Failed on checking hosts ssh connectivity." == str(excinfo.value) + + +@pytest.mark.parametrize("stderrinfo, expected", [ + ('', True), + ('sorry', False) +]) +def test_ssh_is_ok(mocker, ansible_envsetup, private_key, stderrinfo, expected): + stderr = mock.MagicMock() + stderr.readlines.return_value = stderrinfo + mock_sshclient = mocker.patch('paramiko.SSHClient') + test_ssh_client = mock_sshclient.return_value + test_ssh_client.exec_command.return_value = ('', '', stderr) + result = ansible_envsetup._ssh_is_ok('10.20.0.3', str(private_key)) + assert result == expected + test_ssh_client.connect.assert_called_once_with( + '10.20.0.3', key_filename=str(private_key)) + test_ssh_client.exec_command.assert_called_with('uname') + + +def test_ssh_exception(monkeypatch, mocker, ansible_envsetup): + monkeypatch.setattr(time, 'sleep', lambda s: None) + mock_sshclient = mocker.patch('paramiko.SSHClient') + test_ssh_client = mock_sshclient.return_value + test_ssh_client.exec_command.side_effect = socket.error() + result = ansible_envsetup._ssh_is_ok('10.20.0.3', str(private_key), attempts=1) + assert result is False diff --git a/tests/unit/util/logger_test.py b/tests/unit/util/logger_test.py index 339b2bf6..78c4c109 100644 --- a/tests/unit/util/logger_test.py +++ b/tests/unit/util/logger_test.py @@ -1,3 +1,12 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + import pytest from qtip.util import logger diff --git a/third-party/License/.gitrepo b/third-party/License/.gitrepo index 29cd5a75..03fab6f7 100644 --- a/third-party/License/.gitrepo +++ b/third-party/License/.gitrepo @@ -5,7 +5,7 @@ ; [subrepo] remote = git@github.com:openzero-zte/License.git - branch = master - commit = 61489dae4453b66887d0d90a2244610a30f7e53c - parent = 3e443dff14a2be02b914e66f27b549d0ed4cc600 + branch = develop + commit = 88b1440008b6acac8ad65afc93606cddef63cea9 + parent = 473deae9a10162f000c49ca49b4e31b28c4bf0d8 cmdver = 0.3.0 diff --git a/third-party/License/README.md b/third-party/License/README.md index 0232de7e..57444c1f 100644 --- a/third-party/License/README.md +++ b/third-party/License/README.md @@ -5,6 +5,7 @@ A script for checking and adding license header according to [OPNFV contribution ## Quick Start ``` -$ cd <project-folder> -$ curl https://raw.githubusercontent.com/Justin-chi/License/master/add_license.sh |bash +$ cd <project-root> +$ curl https://raw.githubusercontent.com/openzero-team/License/develop/add_license.sh |bash ``` + |