diff options
104 files changed, 7913 insertions, 1782 deletions
@@ -11,19 +11,24 @@ IRC: Server:freenode.net Channel:#opnfv-functest Repository: functest Committers: -yaohelan@huawei.com -feng.xiaowei@zte.com.cn -ollivier.cedric@gmail.com -jose.lausuch@ericsson.com -morgan.richomme@orange.com -meimei@huawei.com -valentin.boucher@orange.com -lanqinglong@huawei.com -viktor.tikkanen@nokia.com -juha.kosonen@nokia.com -zhanghaoyu7@huawei.com -raghavendrachari.kamsali@hpe.com -lixiaoguang5@huawei.com +Morgan Richomme <morgan.richomme@orange.com> +Jose Lausuch <jose.lausuch@ericsson.com> +Cedric Ollivier <ollivier.cedric@gmail.com> +Helen Yao <yaohelan@huawei.com> +Serena Feng <feng.xiaowei@zte.com.cn> +Juha Kosonen <juha.kosonen@nokia.com> +Valentin Boucher <valentin.boucher@orange.com> +Viktor Tikkanen <viktor.tikkanen@nokia.com> +Mei Mei <meimei@huawei.com> + +Additional contributors: +Linda Wang <wangwulin@huawei.com> +Georgios Paraskevopoulos <georgepar.91@gmail.com> +Romanos Skiadas <rom.skiad@gmail.com> +Michael Polenchuk <mpolenchuk@mirantis.com> +Cristina Pauna <cristina.pauna@enea.com> +Matthew Li <matthew.lijun@huawei.com> +Steven Pisarski <s.pisarski@cablelabs.com> Link to TSC approval of the project: http://meetbot.opnfv.org/meetings/opnfv-meeting/2015/opnfv-meeting.2015-01-20-14.57.html diff --git a/docker/Dockerfile b/docker/Dockerfile index 6137cc94..202eb5cb 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -25,6 +25,7 @@ ARG REPOS_DIR=/home/opnfv/repos ARG FUNCTEST_BASE_DIR=/home/opnfv/functest ARG FUNCTEST_CONF_DIR=${FUNCTEST_BASE_DIR}/conf ARG FUNCTEST_DATA_DIR=${FUNCTEST_BASE_DIR}/data +ARG FUNCTEST_IMAGES_DIR=${FUNCTEST_BASE_DIR}/images ARG FUNCTEST_RESULTS_DIR=${FUNCTEST_BASE_DIR}/results ARG FUNCTEST_REPO_DIR=${REPOS_DIR}/functest ARG FUNCTEST_TEST_DIR=${FUNCTEST_REPO_DIR}/functest/opnfv_tests @@ -71,7 +72,9 @@ RUN pip install --upgrade pip RUN mkdir -p ${REPOS_DIR} \ && mkdir -p ${REPOS_VNFS_DIR} \ && mkdir -p ${FUNCTEST_BASE_DIR}/results \ - && mkdir -p ${FUNCTEST_BASE_DIR}/conf \ + && mkdir -p ${FUNCTEST_CONF_DIR} \ + && mkdir -p ${FUNCTEST_DATA_DIR} \ + && mkdir -p ${FUNCTEST_IMAGES_DIR} \ && mkdir -p /root/.ssh \ && chmod 700 /root/.ssh diff --git a/docker/Dockerfile.aarch64 b/docker/Dockerfile.aarch64 index 83df2d0c..b03c6d97 100644 --- a/docker/Dockerfile.aarch64 +++ b/docker/Dockerfile.aarch64 @@ -24,6 +24,7 @@ ARG REPOS_DIR=/home/opnfv/repos ARG FUNCTEST_BASE_DIR=/home/opnfv/functest ARG FUNCTEST_CONF_DIR=${FUNCTEST_BASE_DIR}/conf ARG FUNCTEST_DATA_DIR=${FUNCTEST_BASE_DIR}/data +ARG FUNCTEST_IMAGES_DIR=${FUNCTEST_BASE_DIR}/images ARG FUNCTEST_RESULTS_DIR=${FUNCTEST_BASE_DIR}/results ARG FUNCTEST_REPO_DIR=${REPOS_DIR}/functest ARG FUNCTEST_TEST_DIR=${FUNCTEST_REPO_DIR}/functest/opnfv_tests @@ -71,6 +72,8 @@ RUN mkdir -p ${REPOS_DIR} \ && mkdir -p ${REPOS_VNFS_DIR} \ && mkdir -p ${FUNCTEST_BASE_DIR}/results \ && mkdir -p ${FUNCTEST_BASE_DIR}/conf \ + && mkdir -p ${FUNCTEST_DATA_DIR} \ + && mkdir -p ${FUNCTEST_IMAGES_DIR} \ && mkdir -p /root/.ssh \ && chmod 700 /root/.ssh diff --git a/docker/add_images.sh b/docker/add_images.sh index af2956c2..919cecd8 100755 --- a/docker/add_images.sh +++ b/docker/add_images.sh @@ -7,11 +7,10 @@ CIRROS_REPO_URL=http://download.cirros-cloud.net CIRROS_AARCH64_TAG=161201 CIRROS_X86_64_TAG=0.3.5 -wget ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-disk.img -P ${FUNCTEST_BASE_DIR}/data/ -wget ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-lxc.tar.gz -P ${FUNCTEST_BASE_DIR}/data/ -wget http://205.177.226.237:9999/onosfw/firewall_block_image.img -P ${FUNCTEST_BASE_DIR}/data/ +wget ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-disk.img -P ${FUNCTEST_IMAGES_DIR} +wget ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-lxc.tar.gz -P ${FUNCTEST_IMAGES_DIR} # Add the 3-part image for aarch64, since functest can be run from an x86 machine to test an aarch64 POD -wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-disk.img -P ${FUNCTEST_BASE_DIR}/data/ -wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-initramfs -P ${FUNCTEST_BASE_DIR}/data/ -wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-kernel -P ${FUNCTEST_BASE_DIR}/data/ +wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-disk.img -P ${FUNCTEST_IMAGES_DIR} +wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-initramfs -P ${FUNCTEST_IMAGES_DIR} +wget ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-kernel -P ${FUNCTEST_IMAGES_DIR} diff --git a/docs/com/pres/framework/framework.html b/docs/com/pres/framework/framework.html new file mode 100644 index 00000000..950c2beb --- /dev/null +++ b/docs/com/pres/framework/framework.html @@ -0,0 +1,52 @@ +<html> +<head> +<title>OPNFV Functest Framework</title> +<meta name="author" content="Cédric Ollivier"> +<meta name="viewport" + content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> +<link rel="stylesheet" href="../reveal.js/css/reveal.css"> +<link rel="stylesheet" href="../reveal.js/css/theme/white.css"> +<link rel="stylesheet" href="../reveal.js/lib/css/zenburn.css"> +<script> +var link = document.createElement( 'link' ); +link.rel = 'stylesheet'; +link.type = 'text/css'; +link.href = window.location.search.match( /print-pdf/gi ) ? '../reveal.js/css/print/pdf.css' : '../reveal.js/css/print/paper.css'; +document.getElementsByTagName( 'head' )[0].appendChild( link ); +</script> +</head> +<body> + <div class="reveal"> + <div class="slides"> + <section data-markdown="framework.md" data-separator="^\n\n\n" + data-separator-vertical="^\n\n" data-separator-notes="^Note:"></section> + </div> + </div> + <script src="../reveal.js/lib/js/head.min.js"></script> + <script src="../reveal.js/js/reveal.js"></script> + <script> + Reveal.initialize({ + dependencies : [ { + src : '../reveal.js/plugin/markdown/marked.js', + condition : function() { + return !!document.querySelector('[data-markdown]'); + } + }, { + src : '../reveal.js/plugin/markdown/markdown.js', + condition : function() { + return !!document.querySelector('[data-markdown]'); + } + }, { + src: '../reveal.js/plugin/highlight/highlight.js', + async: true, + callback: function() { + hljs.initHighlightingOnLoad(); + } + }, { + src: '../reveal.js/plugin/notes/notes.js', + async: true + } ] + }); + </script> +</body> +</html> diff --git a/docs/com/pres/framework/framework.md b/docs/com/pres/framework/framework.md new file mode 100644 index 00000000..3c1aae1b --- /dev/null +++ b/docs/com/pres/framework/framework.md @@ -0,0 +1,268 @@ +# Functest Framework + +created by [Cédric Ollivier](mailto:cedric.ollivier@orange.com) + +2017/05/06 + +Note: + +- Functest integrates lots of heterogeneous testcases: + - python vs bash + - internal vs external +- it aims to benefit from object programming + - to define common operations + - to avoid conditional instructions regarding the testcases + - to avoid duplicating code + - to ease the integration of third-party testcases (written in Bash or Python) + + + +## Quick overview + + +### Functest function calls + +- **CI** calls *run_tests.py* (please see [jenkins jobs](https://gerrit.opnfv.org/gerrit/gitweb?p=releng.git;a=tree;f=jjb/functest)) +- *run_tests.py* parses *functest/ci/testcases.yaml* to: + - check which testcase(s) must be run + - execute the common operations on every testcase (run, push its results to db...) +<!-- .element: class="fragment highlight-red"--> + - return the right status code to **CI** + + +### Our target + +- limit run_tests.py instructions by defining: + - the basic testcase attributes + - all common operations + - the status codes expected +- avoid duplicating codes between testcases +- ease the development of third-party testcases (aka features) + + + +## class TestCase + +base model for single test case + + +### instance attributes + +- project_name (default: 'functest') +- case_name +- criteria +- result +- start_time +- stop_time +- details + + +### methods + +| Method | Purpose | +|-------------------|--------------------------------------------| +| run(**kwargs) | run the test case | +| is_successful() | interpret the results of the test case | +| get_duration() | return the duration of the test case | +| push_to_db() | push the results of the test case to the DB| + + +### run(**kwargs) + +- the subclasses must override the default implementation which is false on purpose +- the new implementation must set the following attributes to push the results to DB: + - result + - start_time + - stop_time + + +### class attributes + +| Status code | Returned when | +|--------------------|---------------------| +| EX_OK | everything is OK | +| EX_RUN_ERROR | run() failed | +| EX_TESTCASE_FAILED | results are false | +| EX_PUSH_TO_DB_ERROR| push_to_db() failed | + + +### run_tests.py + +```python +module = importlib.import_module(run_dict['module']) +cls = getattr(module, run_dict['class']) +test_dict = ft_utils.get_dict_by_test(test_name) +test_case = cls(**test_dict) +try: + kwargs = run_dict['args'] + result = test_case.run(**kwargs) +except KeyError: + result = test_case.run() +if result == testcase.TestCase.EX_OK: + if GlobalVariables.REPORT_FLAG: + test_case.push_to_db() + result = test_case.is_successful() +``` + + + +## Your first test case + + +### first.py + +```python +#!/usr/bin/env python + +import time + +from functest.core import testcase + +class Test(testcase.TestCase): + + def run(self, **kwargs): + self.start_time = time.time() + print "Hello World" + self.result = 100 + self.stop_time = time.time() + return testcase.TestCase.EX_OK +``` + + +### functest/ci/testcases.yaml + +```yaml +case_name: first +project_name: functest +criteria: 100 +blocking: true +clean_flag: false +description: '' +dependencies: + installer: '' + scenario: '' +run: + module: 'first' + class: 'Test' +``` + + + +## class Feature +bases: TestCase + +base model for single feature + + +### methods + +| Method | Purpose | +|-------------------|---------------------------| +| run(**kwargs) | run the feature | +| execute(**kwargs) | execute the Python method | + + +### run(**kwargs) + +- allows executing any Python method by calling execute() +- sets the following attributes required to push the results to DB: + - result + - start_time + - stop_time +- doesn't fulfill details when pushing the results to the DB. + + +### execute(**kwargs) + +- the subclasses must override the default implementation which is false on purpose +- the new implementation must return 0 if success or anything else if failure. + + + +## Your second test case + + +### second.py + +```python +#!/usr/bin/env python + +from functest.core import feature + +class Test(feature.Feature): + + def execute(self, **kwargs): + print "Hello World" + return 0 +``` + + +### functest/ci/testcases.yaml + +```yaml +case_name: second +project_name: functest +criteria: 100 +blocking: true +clean_flag: false +description: '' +dependencies: + installer: '' + scenario: '' +run: + module: 'second' + class: 'Test' +``` + + + +## class BashFeature +bases: Feature + +class designed to run any bash command + + +### execute(**kwargs) + +execute the cmd passed as arg. + + + +## Your third test case + + +### functest/ci/testcases.yaml + +``` +case_name: third +project_name: functest +criteria: 100 +blocking: true +clean_flag: false +description: '' +dependencies: + installer: '' + scenario: '' +run: + module: 'functest.core.feature' + class: 'BashFeature' + args: + cmd: 'echo Hello World; exit 0' +``` + + + +## Euphrates + + +### Next actions + +- __to finish VNF abstraction (coverage + pylint)__ +- to publish doc API +- to manage criteria as written in testcases.yaml + +Please see [Functest Euphrates page](https://wiki.opnfv.org/display/functest/Functest+Euphrates+page) for more details + + + +## Thank You! diff --git a/docs/results/danube/2.0/apex.html b/docs/results/danube/2.0/apex.html new file mode 100644 index 00000000..4460087e --- /dev/null +++ b/docs/results/danube/2.0/apex.html @@ -0,0 +1,1057 @@ + <html> + <head> + <meta charset="utf-8"> + <!-- Bootstrap core CSS --> + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"> + <link href="../../js/default.css" rel="stylesheet"> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> + <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> + <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> + <script type="text/javascript" src="../../js/gauge.js"></script> + <script type="text/javascript" src="../../js/trend.js"></script> + <script> + function onDocumentReady() { + // Gauge management + var gaugeScenario1 = gauge('#gaugeScenario1');var gaugeScenario2 = gauge('#gaugeScenario2');var gaugeScenario3 = gauge('#gaugeScenario3');var gaugeScenario4 = gauge('#gaugeScenario4');var gaugeScenario5 = gauge('#gaugeScenario5');var gaugeScenario6 = gauge('#gaugeScenario6');var gaugeScenario7 = gauge('#gaugeScenario7');var gaugeScenario8 = gauge('#gaugeScenario8');var gaugeScenario9 = gauge('#gaugeScenario9');var gaugeScenario10 = gauge('#gaugeScenario10');var gaugeScenario11 = gauge('#gaugeScenario11');var gaugeScenario12 = gauge('#gaugeScenario12');var gaugeScenario13 = gauge('#gaugeScenario13');var gaugeScenario14 = gauge('#gaugeScenario14'); + + // assign success rate to the gauge + function updateReadings() { + gaugeScenario1.update(93.3333333333);gaugeScenario2.update(50.0);gaugeScenario3.update(27.2727272727);gaugeScenario4.update(77.7777777778);gaugeScenario5.update(18.1818181818);gaugeScenario6.update(44.4444444444);gaugeScenario7.update(90.9090909091);gaugeScenario8.update(76.6666666667);gaugeScenario9.update(20.0);gaugeScenario10.update(69.696969697);gaugeScenario11.update(18.1818181818);gaugeScenario12.update(80.5555555556);gaugeScenario13.update(90.9090909091);gaugeScenario14.update(76.6666666667); + } + updateReadings(); + } + + // trend line management + d3.csv("./scenario_history.txt", function(data) { + // *************************************** + // Create the trend line + // for scenario os-nosdn-fdio-noha + // Filter results + var trend1 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-fdio-noha" && row["installer"]=="apex"; + }) + // Parse the date + trend1.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg1",trend1) + // ****************************************// for scenario os-odl-gluon-noha + // Filter results + var trend2 = data.filter(function(row) { + return row["scenario"]=="os-odl-gluon-noha" && row["installer"]=="apex"; + }) + // Parse the date + trend2.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg2",trend2) + // ****************************************// for scenario os-ovn-nofeature-noha + // Filter results + var trend3 = data.filter(function(row) { + return row["scenario"]=="os-ovn-nofeature-noha" && row["installer"]=="apex"; + }) + // Parse the date + trend3.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg3",trend3) + // ****************************************// for scenario os-odl_l2-fdio-noha + // Filter results + var trend4 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-fdio-noha" && row["installer"]=="apex"; + }) + // Parse the date + trend4.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg4",trend4) + // ****************************************// for scenario os-odl_l3-ovs-ha + // Filter results + var trend5 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-ovs-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend5.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg5",trend5) + // ****************************************// for scenario os-odl-bgpvpn-ha + // Filter results + var trend6 = data.filter(function(row) { + return row["scenario"]=="os-odl-bgpvpn-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend6.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg6",trend6) + // ****************************************// for scenario os-nosdn-kvm-ha + // Filter results + var trend7 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend7.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg7",trend7) + // ****************************************// for scenario os-odl_l3-fdio-noha + // Filter results + var trend8 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-fdio-noha" && row["installer"]=="apex"; + }) + // Parse the date + trend8.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg8",trend8) + // ****************************************// for scenario os-nosdn-fdio-ha + // Filter results + var trend9 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-fdio-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend9.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg9",trend9) + // ****************************************// for scenario os-odl_l3-nofeature-ha + // Filter results + var trend10 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-nofeature-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend10.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg10",trend10) + // ****************************************// for scenario os-nosdn-ovs-ha + // Filter results + var trend11 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-ovs-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend11.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg11",trend11) + // ****************************************// for scenario os-odl_l2-fdio-ha + // Filter results + var trend12 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-fdio-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend12.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg12",trend12) + // ****************************************// for scenario os-nosdn-nofeature-ha + // Filter results + var trend13 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend13.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg13",trend13) + // ****************************************// for scenario os-odl_l3-fdio-ha + // Filter results + var trend14 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-fdio-ha" && row["installer"]=="apex"; + }) + // Parse the date + trend14.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg14",trend14) + // **************************************** + }); + if ( !window.isLoaded ) { + window.addEventListener("load", function() { + onDocumentReady(); + }, false); + } else { + onDocumentReady(); + } +</script> +<script type="text/javascript"> +$(document).ready(function (){ + $(".btn-more").click(function() { + $(this).hide(); + $(this).parent().find(".panel-default").show(); + }); +}) +</script> + + </head> + <body> + <div class="container"> + <div class="masthead"> + <h3 class="text-muted">Functest status page (danube, 2017-05-05 01:45)</h3> + <nav> + <ul class="nav nav-justified"> + <li class="active"><a href="http://testresults.opnfv.org/reporting/index.html">Home</a></li> + <li><a href="apex.html">Apex</a></li> + <li><a href="compass.html">Compass</a></li> + <li><a href="fuel.html">Fuel</a></li> + <li><a href="joid.html">Joid</a></li> + </ul> + </nav> + </div> +<div class="row"> + <div class="col-md-1"></div> + <div class="col-md-10"> + <div class="page-header"> + <h2>apex</h2> + </div> + + <div class="scenario-overview"> + <div class="panel-heading"><h4><b>List of last scenarios (danube) run over the last 10 days </b></h4></div> + <table class="table"> + <tr> + <th width="40%">Scenario</th> + <th width="20%">Status</th> + <th width="20%">Trend</th> + <th width="10%">Score</th> + <th width="10%">Iteration</th> + </tr> + <tr class="tr-ok"> + <td><a href=http://testresultS.opnfv.org/reporting>os-nosdn-fdio-noha</a></td> + <td><div id="gaugeScenario1"></div></td> + <td><div id="trend_svg1"></div></td> + <td>28/30</td> + <td>10</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/225/console>os-odl-gluon-noha</a></td> + <td><div id="gaugeScenario2"></div></td> + <td><div id="trend_svg2"></div></td> + <td>18/36</td> + <td>3</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/221/console>os-ovn-nofeature-noha</a></td> + <td><div id="gaugeScenario3"></div></td> + <td><div id="trend_svg3"></div></td> + <td>9/33</td> + <td>5</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/226/console>os-odl_l2-fdio-noha</a></td> + <td><div id="gaugeScenario4"></div></td> + <td><div id="trend_svg4"></div></td> + <td>28/36</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/220/console>os-odl_l3-ovs-ha</a></td> + <td><div id="gaugeScenario5"></div></td> + <td><div id="trend_svg5"></div></td> + <td>6/33</td> + <td>4</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/224/console>os-odl-bgpvpn-ha</a></td> + <td><div id="gaugeScenario6"></div></td> + <td><div id="trend_svg6"></div></td> + <td>16/36</td> + <td>3</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/228/console>os-nosdn-kvm-ha</a></td> + <td><div id="gaugeScenario7"></div></td> + <td><div id="trend_svg7"></div></td> + <td>30/33</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/217/console>os-odl_l3-fdio-noha</a></td> + <td><div id="gaugeScenario8"></div></td> + <td><div id="trend_svg8"></div></td> + <td>23/30</td> + <td>13</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/230/console>os-nosdn-fdio-ha</a></td> + <td><div id="gaugeScenario9"></div></td> + <td><div id="trend_svg9"></div></td> + <td>6/30</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/211/console>os-odl_l3-nofeature-ha</a></td> + <td><div id="gaugeScenario10"></div></td> + <td><div id="trend_svg10"></div></td> + <td>23/33</td> + <td>5</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/231/console>os-nosdn-ovs-ha</a></td> + <td><div id="gaugeScenario11"></div></td> + <td><div id="trend_svg11"></div></td> + <td>6/33</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/227/console>os-odl_l2-fdio-ha</a></td> + <td><div id="gaugeScenario12"></div></td> + <td><div id="trend_svg12"></div></td> + <td>29/36</td> + <td>20</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/222/console>os-nosdn-nofeature-ha</a></td> + <td><div id="gaugeScenario13"></div></td> + <td><div id="trend_svg13"></div></td> + <td>30/33</td> + <td>5</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/229/console>os-odl_l3-fdio-ha</a></td> + <td><div id="gaugeScenario14"></div></td> + <td><div id="trend_svg14"></div></td> + <td>23/30</td> + <td>6</td> + </tr> + </table> + </div> + + + <div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-fdio-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl-gluon-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th><th> + Netready + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-ovn-nofeature-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-fdio-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + FDS + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-ovs-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl-bgpvpn-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + bgpvpn + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-fdio-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-fdio-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-ovs-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-fdio-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + FDS + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-fdio-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div> + see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring + <div> <br> + <a href="./status-apex.pdf" class="myButtonPdf">Export to PDF</a> <a href="./scenario_history_apex.txt" class="myButtonCSV">Export to CSV</a> + </div> + </div> + <div class="col-md-1"></div> +</div> diff --git a/docs/results/danube/2.0/compass.html b/docs/results/danube/2.0/compass.html new file mode 100644 index 00000000..cde66359 --- /dev/null +++ b/docs/results/danube/2.0/compass.html @@ -0,0 +1,493 @@ + <html> + <head> + <meta charset="utf-8"> + <!-- Bootstrap core CSS --> + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"> + <link href="../../js/default.css" rel="stylesheet"> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> + <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> + <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> + <script type="text/javascript" src="../../js/gauge.js"></script> + <script type="text/javascript" src="../../js/trend.js"></script> + <script> + function onDocumentReady() { + // Gauge management + var gaugeScenario1 = gauge('#gaugeScenario1');var gaugeScenario2 = gauge('#gaugeScenario2');var gaugeScenario3 = gauge('#gaugeScenario3');var gaugeScenario4 = gauge('#gaugeScenario4');var gaugeScenario5 = gauge('#gaugeScenario5');var gaugeScenario6 = gauge('#gaugeScenario6'); + + // assign success rate to the gauge + function updateReadings() { + gaugeScenario1.update(83.3333333333);gaugeScenario2.update(10.0);gaugeScenario3.update(84.8484848485);gaugeScenario4.update(84.8484848485);gaugeScenario5.update(96.6666666667);gaugeScenario6.update(96.6666666667); + } + updateReadings(); + } + + // trend line management + d3.csv("./scenario_history.txt", function(data) { + // *************************************** + // Create the trend line + // for scenario os-odl_l3-nofeature-ha + // Filter results + var trend1 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-nofeature-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend1.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg1",trend1) + // ****************************************// for scenario os-ocl-nofeature-ha + // Filter results + var trend2 = data.filter(function(row) { + return row["scenario"]=="os-ocl-nofeature-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend2.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg2",trend2) + // ****************************************// for scenario os-onos-nofeature-ha + // Filter results + var trend3 = data.filter(function(row) { + return row["scenario"]=="os-onos-nofeature-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend3.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg3",trend3) + // ****************************************// for scenario os-odl_l2-nofeature-ha + // Filter results + var trend4 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-nofeature-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend4.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg4",trend4) + // ****************************************// for scenario os-nosdn-openo-ha + // Filter results + var trend5 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-openo-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend5.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg5",trend5) + // ****************************************// for scenario os-nosdn-nofeature-ha + // Filter results + var trend6 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-ha" && row["installer"]=="compass"; + }) + // Parse the date + trend6.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg6",trend6) + // **************************************** + }); + if ( !window.isLoaded ) { + window.addEventListener("load", function() { + onDocumentReady(); + }, false); + } else { + onDocumentReady(); + } +</script> +<script type="text/javascript"> +$(document).ready(function (){ + $(".btn-more").click(function() { + $(this).hide(); + $(this).parent().find(".panel-default").show(); + }); +}) +</script> + + </head> + <body> + <div class="container"> + <div class="masthead"> + <h3 class="text-muted">Functest status page (danube, 2017-05-05 01:45)</h3> + <nav> + <ul class="nav nav-justified"> + <li class="active"><a href="http://testresults.opnfv.org/reporting/index.html">Home</a></li> + <li><a href="apex.html">Apex</a></li> + <li><a href="compass.html">Compass</a></li> + <li><a href="fuel.html">Fuel</a></li> + <li><a href="joid.html">Joid</a></li> + </ul> + </nav> + </div> +<div class="row"> + <div class="col-md-1"></div> + <div class="col-md-10"> + <div class="page-header"> + <h2>compass</h2> + </div> + + <div class="scenario-overview"> + <div class="panel-heading"><h4><b>List of last scenarios (danube) run over the last 10 days </b></h4></div> + <table class="table"> + <tr> + <th width="40%">Scenario</th> + <th width="20%">Status</th> + <th width="20%">Trend</th> + <th width="10%">Score</th> + <th width="10%">Iteration</th> + </tr> + <tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/217/console>os-odl_l3-nofeature-ha</a></td> + <td><div id="gaugeScenario1"></div></td> + <td><div id="trend_svg1"></div></td> + <td>25/30</td> + <td>18</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-baremetal-daily-danube/222/console>os-ocl-nofeature-ha</a></td> + <td><div id="gaugeScenario2"></div></td> + <td><div id="trend_svg2"></div></td> + <td>3/30</td> + <td>7</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/213/console>os-onos-nofeature-ha</a></td> + <td><div id="gaugeScenario3"></div></td> + <td><div id="trend_svg3"></div></td> + <td>28/33</td> + <td>16</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/218/console>os-odl_l2-nofeature-ha</a></td> + <td><div id="gaugeScenario4"></div></td> + <td><div id="trend_svg4"></div></td> + <td>28/33</td> + <td>18</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/212/console>os-nosdn-openo-ha</a></td> + <td><div id="gaugeScenario5"></div></td> + <td><div id="trend_svg5"></div></td> + <td>29/30</td> + <td>7</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-baremetal-daily-danube/224/console>os-nosdn-nofeature-ha</a></td> + <td><div id="gaugeScenario6"></div></td> + <td><div id="trend_svg6"></div></td> + <td>29/30</td> + <td>18</td> + </tr> + </table> + </div> + + + <div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-ocl-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-onos-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ONOS + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-openo-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div> + see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring + <div> <br> + <a href="./status-compass.pdf" class="myButtonPdf">Export to PDF</a> <a href="./scenario_history_compass.txt" class="myButtonCSV">Export to CSV</a> + </div> + </div> + <div class="col-md-1"></div> +</div> diff --git a/docs/results/danube/2.0/fuel.html b/docs/results/danube/2.0/fuel.html new file mode 100644 index 00000000..0ee69d3b --- /dev/null +++ b/docs/results/danube/2.0/fuel.html @@ -0,0 +1,1447 @@ + <html> + <head> + <meta charset="utf-8"> + <!-- Bootstrap core CSS --> + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"> + <link href="../../js/default.css" rel="stylesheet"> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> + <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> + <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> + <script type="text/javascript" src="../../js/gauge.js"></script> + <script type="text/javascript" src="../../js/trend.js"></script> + <script> + function onDocumentReady() { + // Gauge management + var gaugeScenario1 = gauge('#gaugeScenario1');var gaugeScenario2 = gauge('#gaugeScenario2');var gaugeScenario3 = gauge('#gaugeScenario3');var gaugeScenario4 = gauge('#gaugeScenario4');var gaugeScenario5 = gauge('#gaugeScenario5');var gaugeScenario6 = gauge('#gaugeScenario6');var gaugeScenario7 = gauge('#gaugeScenario7');var gaugeScenario8 = gauge('#gaugeScenario8');var gaugeScenario9 = gauge('#gaugeScenario9');var gaugeScenario10 = gauge('#gaugeScenario10');var gaugeScenario11 = gauge('#gaugeScenario11');var gaugeScenario12 = gauge('#gaugeScenario12');var gaugeScenario13 = gauge('#gaugeScenario13');var gaugeScenario14 = gauge('#gaugeScenario14');var gaugeScenario15 = gauge('#gaugeScenario15');var gaugeScenario16 = gauge('#gaugeScenario16');var gaugeScenario17 = gauge('#gaugeScenario17');var gaugeScenario18 = gauge('#gaugeScenario18'); + + // assign success rate to the gauge + function updateReadings() { + gaugeScenario1.update(100.0);gaugeScenario2.update(28.5714285714);gaugeScenario3.update(100.0);gaugeScenario4.update(100.0);gaugeScenario5.update(15.3846153846);gaugeScenario6.update(95.2380952381);gaugeScenario7.update(94.8717948718);gaugeScenario8.update(100.0);gaugeScenario9.update(100.0);gaugeScenario10.update(97.4358974359);gaugeScenario11.update(92.8571428571);gaugeScenario12.update(100.0);gaugeScenario13.update(97.4358974359);gaugeScenario14.update(100.0);gaugeScenario15.update(95.2380952381);gaugeScenario16.update(100.0);gaugeScenario17.update(100.0);gaugeScenario18.update(100.0); + } + updateReadings(); + } + + // trend line management + d3.csv("./scenario_history.txt", function(data) { + // *************************************** + // Create the trend line + // for scenario os-nosdn-kvm_ovs_dpdk-noha + // Filter results + var trend1 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm_ovs_dpdk-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend1.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg1",trend1) + // ****************************************// for scenario os-nosdn-kvm_ovs_dpdk_bar-ha + // Filter results + var trend2 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm_ovs_dpdk_bar-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend2.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg2",trend2) + // ****************************************// for scenario os-nosdn-ovs-ha + // Filter results + var trend3 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-ovs-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend3.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg3",trend3) + // ****************************************// for scenario os-nosdn-ovs-noha + // Filter results + var trend4 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-ovs-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend4.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg4",trend4) + // ****************************************// for scenario os-nosdn-kvm_ovs_dpdk-ha + // Filter results + var trend5 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm_ovs_dpdk-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend5.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg5",trend5) + // ****************************************// for scenario os-odl_l2-sfc-noha + // Filter results + var trend6 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-sfc-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend6.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg6",trend6) + // ****************************************// for scenario os-odl_l3-nofeature-ha + // Filter results + var trend7 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-nofeature-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend7.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg7",trend7) + // ****************************************// for scenario os-nosdn-kvm-noha + // Filter results + var trend8 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend8.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg8",trend8) + // ****************************************// for scenario os-odl_l3-nofeature-noha + // Filter results + var trend9 = data.filter(function(row) { + return row["scenario"]=="os-odl_l3-nofeature-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend9.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg9",trend9) + // ****************************************// for scenario os-odl_l2-nofeature-noha + // Filter results + var trend10 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-nofeature-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend10.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg10",trend10) + // ****************************************// for scenario os-odl_l2-bgpvpn-ha + // Filter results + var trend11 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-bgpvpn-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend11.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg11",trend11) + // ****************************************// for scenario os-odl_l2-sfc-ha + // Filter results + var trend12 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-sfc-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend12.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg12",trend12) + // ****************************************// for scenario os-nosdn-kvm_ovs_dpdk_bar-noha + // Filter results + var trend13 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm_ovs_dpdk_bar-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend13.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg13",trend13) + // ****************************************// for scenario os-odl_l2-bgpvpn-noha + // Filter results + var trend14 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-bgpvpn-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend14.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg14",trend14) + // ****************************************// for scenario os-odl_l2-nofeature-ha + // Filter results + var trend15 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-nofeature-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend15.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg15",trend15) + // ****************************************// for scenario os-nosdn-nofeature-noha + // Filter results + var trend16 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-noha" && row["installer"]=="fuel"; + }) + // Parse the date + trend16.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg16",trend16) + // ****************************************// for scenario os-nosdn-kvm-ha + // Filter results + var trend17 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-kvm-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend17.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg17",trend17) + // ****************************************// for scenario os-nosdn-nofeature-ha + // Filter results + var trend18 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-ha" && row["installer"]=="fuel"; + }) + // Parse the date + trend18.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg18",trend18) + // **************************************** + }); + if ( !window.isLoaded ) { + window.addEventListener("load", function() { + onDocumentReady(); + }, false); + } else { + onDocumentReady(); + } +</script> +<script type="text/javascript"> +$(document).ready(function (){ + $(".btn-more").click(function() { + $(this).hide(); + $(this).parent().find(".panel-default").show(); + }); +}) +</script> + + </head> + <body> + <div class="container"> + <div class="masthead"> + <h3 class="text-muted">Functest status page (danube, 2017-05-05 01:45)</h3> + <nav> + <ul class="nav nav-justified"> + <li class="active"><a href="http://testresults.opnfv.org/reporting/index.html">Home</a></li> + <li><a href="apex.html">Apex</a></li> + <li><a href="compass.html">Compass</a></li> + <li><a href="fuel.html">Fuel</a></li> + <li><a href="joid.html">Joid</a></li> + </ul> + </nav> + </div> +<div class="row"> + <div class="col-md-1"></div> + <div class="col-md-10"> + <div class="page-header"> + <h2>fuel</h2> + </div> + + <div class="scenario-overview"> + <div class="panel-heading"><h4><b>List of last scenarios (danube) run over the last 10 days </b></h4></div> + <table class="table"> + <tr> + <th width="40%">Scenario</th> + <th width="20%">Status</th> + <th width="20%">Trend</th> + <th width="10%">Score</th> + <th width="10%">Iteration</th> + </tr> + <tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/368/console>os-nosdn-kvm_ovs_dpdk-noha</a></td> + <td><div id="gaugeScenario1"></div></td> + <td><div id="trend_svg1"></div></td> + <td>36/36</td> + <td>10</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/348/console>os-nosdn-kvm_ovs_dpdk_bar-ha</a></td> + <td><div id="gaugeScenario2"></div></td> + <td><div id="trend_svg2"></div></td> + <td>12/42</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/345/console>os-nosdn-ovs-ha</a></td> + <td><div id="gaugeScenario3"></div></td> + <td><div id="trend_svg3"></div></td> + <td>39/39</td> + <td>7</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/365/console>os-nosdn-ovs-noha</a></td> + <td><div id="gaugeScenario4"></div></td> + <td><div id="trend_svg4"></div></td> + <td>36/36</td> + <td>10</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/341/console>os-nosdn-kvm_ovs_dpdk-ha</a></td> + <td><div id="gaugeScenario5"></div></td> + <td><div id="trend_svg5"></div></td> + <td>6/39</td> + <td>4</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/362/console>os-odl_l2-sfc-noha</a></td> + <td><div id="gaugeScenario6"></div></td> + <td><div id="trend_svg6"></div></td> + <td>40/42</td> + <td>10</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/347/console>os-odl_l3-nofeature-ha</a></td> + <td><div id="gaugeScenario7"></div></td> + <td><div id="trend_svg7"></div></td> + <td>37/39</td> + <td>8</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/364/console>os-nosdn-kvm-noha</a></td> + <td><div id="gaugeScenario8"></div></td> + <td><div id="trend_svg8"></div></td> + <td>36/36</td> + <td>9</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/369/console>os-odl_l3-nofeature-noha</a></td> + <td><div id="gaugeScenario9"></div></td> + <td><div id="trend_svg9"></div></td> + <td>36/36</td> + <td>9</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/367/console>os-odl_l2-nofeature-noha</a></td> + <td><div id="gaugeScenario10"></div></td> + <td><div id="trend_svg10"></div></td> + <td>38/39</td> + <td>11</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/342/console>os-odl_l2-bgpvpn-ha</a></td> + <td><div id="gaugeScenario11"></div></td> + <td><div id="trend_svg11"></div></td> + <td>39/42</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/340/console>os-odl_l2-sfc-ha</a></td> + <td><div id="gaugeScenario12"></div></td> + <td><div id="trend_svg12"></div></td> + <td>45/45</td> + <td>6</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/370/console>os-nosdn-kvm_ovs_dpdk_bar-noha</a></td> + <td><div id="gaugeScenario13"></div></td> + <td><div id="trend_svg13"></div></td> + <td>38/39</td> + <td>11</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/363/console>os-odl_l2-bgpvpn-noha</a></td> + <td><div id="gaugeScenario14"></div></td> + <td><div id="trend_svg14"></div></td> + <td>42/42</td> + <td>10</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/346/console>os-odl_l2-nofeature-ha</a></td> + <td><div id="gaugeScenario15"></div></td> + <td><div id="trend_svg15"></div></td> + <td>40/42</td> + <td>9</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/366/console>os-nosdn-nofeature-noha</a></td> + <td><div id="gaugeScenario16"></div></td> + <td><div id="trend_svg16"></div></td> + <td>36/36</td> + <td>11</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-zte-pod3-daily-danube/55/console>os-nosdn-kvm-ha</a></td> + <td><div id="gaugeScenario17"></div></td> + <td><div id="trend_svg17"></div></td> + <td>39/39</td> + <td>16</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/344/console>os-nosdn-nofeature-ha</a></td> + <td><div id="gaugeScenario18"></div></td> + <td><div id="trend_svg18"></div></td> + <td>39/39</td> + <td>15</td> + </tr> + </table> + </div> + + + <div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm_ovs_dpdk-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm_ovs_dpdk_bar-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th><th> + Barometer + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-ovs-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-ovs-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm_ovs_dpdk-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-sfc-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + SFC + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-overcast.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l3-nofeature-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-nofeature-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-bgpvpn-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + bgpvpn + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-sfc-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + SFC + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm_ovs_dpdk_bar-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th><th> + Barometer + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-bgpvpn-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + bgpvpn + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-kvm-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Doctor + + </th><th> + Parser + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div> + see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring + <div> <br> + <a href="./status-fuel.pdf" class="myButtonPdf">Export to PDF</a> <a href="./scenario_history_fuel.txt" class="myButtonCSV">Export to CSV</a> + </div> + </div> + <div class="col-md-1"></div> +</div> diff --git a/docs/results/danube/2.0/joid.html b/docs/results/danube/2.0/joid.html new file mode 100644 index 00000000..e2231747 --- /dev/null +++ b/docs/results/danube/2.0/joid.html @@ -0,0 +1,421 @@ + <html> + <head> + <meta charset="utf-8"> + <!-- Bootstrap core CSS --> + <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"> + <link href="../../js/default.css" rel="stylesheet"> + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> + <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> + <script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script> + <script type="text/javascript" src="../../js/gauge.js"></script> + <script type="text/javascript" src="../../js/trend.js"></script> + <script> + function onDocumentReady() { + // Gauge management + var gaugeScenario1 = gauge('#gaugeScenario1');var gaugeScenario2 = gauge('#gaugeScenario2');var gaugeScenario3 = gauge('#gaugeScenario3');var gaugeScenario4 = gauge('#gaugeScenario4');var gaugeScenario5 = gauge('#gaugeScenario5'); + + // assign success rate to the gauge + function updateReadings() { + gaugeScenario1.update(75.0);gaugeScenario2.update(96.9696969697);gaugeScenario3.update(25.0);gaugeScenario4.update(96.9696969697);gaugeScenario5.update(70.8333333333); + } + updateReadings(); + } + + // trend line management + d3.csv("./scenario_history.txt", function(data) { + // *************************************** + // Create the trend line + // for scenario os-nosdn-lxd-noha + // Filter results + var trend1 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-lxd-noha" && row["installer"]=="joid"; + }) + // Parse the date + trend1.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg1",trend1) + // ****************************************// for scenario os-nosdn-nofeature-noha + // Filter results + var trend2 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-noha" && row["installer"]=="joid"; + }) + // Parse the date + trend2.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg2",trend2) + // ****************************************// for scenario os-odl_l2-nofeature-ha + // Filter results + var trend3 = data.filter(function(row) { + return row["scenario"]=="os-odl_l2-nofeature-ha" && row["installer"]=="joid"; + }) + // Parse the date + trend3.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg3",trend3) + // ****************************************// for scenario os-nosdn-nofeature-ha + // Filter results + var trend4 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-nofeature-ha" && row["installer"]=="joid"; + }) + // Parse the date + trend4.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg4",trend4) + // ****************************************// for scenario os-nosdn-lxd-ha + // Filter results + var trend5 = data.filter(function(row) { + return row["scenario"]=="os-nosdn-lxd-ha" && row["installer"]=="joid"; + }) + // Parse the date + trend5.forEach(function(d) { + d.date = parseDate(d.date); + d.score = +d.score + }); + // Draw the trend line + var mytrend = trend("#trend_svg5",trend5) + // **************************************** + }); + if ( !window.isLoaded ) { + window.addEventListener("load", function() { + onDocumentReady(); + }, false); + } else { + onDocumentReady(); + } +</script> +<script type="text/javascript"> +$(document).ready(function (){ + $(".btn-more").click(function() { + $(this).hide(); + $(this).parent().find(".panel-default").show(); + }); +}) +</script> + + </head> + <body> + <div class="container"> + <div class="masthead"> + <h3 class="text-muted">Functest status page (danube, 2017-05-05 01:45)</h3> + <nav> + <ul class="nav nav-justified"> + <li class="active"><a href="http://testresults.opnfv.org/reporting/index.html">Home</a></li> + <li><a href="apex.html">Apex</a></li> + <li><a href="compass.html">Compass</a></li> + <li><a href="fuel.html">Fuel</a></li> + <li><a href="joid.html">Joid</a></li> + </ul> + </nav> + </div> +<div class="row"> + <div class="col-md-1"></div> + <div class="col-md-10"> + <div class="page-header"> + <h2>joid</h2> + </div> + + <div class="scenario-overview"> + <div class="panel-heading"><h4><b>List of last scenarios (danube) run over the last 10 days </b></h4></div> + <table class="table"> + <tr> + <th width="40%">Scenario</th> + <th width="20%">Status</th> + <th width="20%">Trend</th> + <th width="10%">Score</th> + <th width="10%">Iteration</th> + </tr> + <tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/167/console>os-nosdn-lxd-noha</a></td> + <td><div id="gaugeScenario1"></div></td> + <td><div id="trend_svg1"></div></td> + <td>18/24</td> + <td>7</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/171/console>os-nosdn-nofeature-noha</a></td> + <td><div id="gaugeScenario2"></div></td> + <td><div id="trend_svg2"></div></td> + <td>32/33</td> + <td>5</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/170/console>os-odl_l2-nofeature-ha</a></td> + <td><div id="gaugeScenario3"></div></td> + <td><div id="trend_svg3"></div></td> + <td>9/36</td> + <td>8</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/169/console>os-nosdn-nofeature-ha</a></td> + <td><div id="gaugeScenario4"></div></td> + <td><div id="trend_svg4"></div></td> + <td>32/33</td> + <td>5</td> + </tr><tr class="tr-ok"> + <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/172/console>os-nosdn-lxd-ha</a></td> + <td><div id="gaugeScenario5"></div></td> + <td><div id="trend_svg5"></div></td> + <td>17/24</td> + <td>8</td> + </tr> + </table> + </div> + + + <div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-lxd-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + vPing (ssh) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + Promise + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-noha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-odl_l2-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + ODL + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-nofeature-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + Health (dhcp) + + </th><th> + vPing (ssh) + + </th><th> + vPing (userdata) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + SNAPS + + </th><th> + Promise + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div><div class="scenario-part"> + <div class="page-header"> + <h3><span class="glyphicon glyphicon-chevron-right"> <b>os-nosdn-lxd-ha</b></h3> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <span class="panel-header-item"> + </span> + </div> + <table class="table"> + <tr> + <th> + Health (connection) + + </th><th> + Health (api) + + </th><th> + vPing (ssh) + + </th><th> + Tempest (smoke) + + </th><th> + Rally (smoke) + + </th><th> + Refstack + + </th><th> + Promise + + </th><th> + Domino + + </th> + </tr> + <tr class="tr-weather-weather"> + <td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-few-clouds.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-storm.png"></td><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-clear.png"></td> + </tr> + </table> + </div> + </div> + see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring + <div> <br> + <a href="./status-joid.pdf" class="myButtonPdf">Export to PDF</a> <a href="./scenario_history_joid.txt" class="myButtonCSV">Export to CSV</a> + </div> + </div> + <div class="col-md-1"></div> +</div> diff --git a/docs/results/danube/2.0/scenario_history.txt b/docs/results/danube/2.0/scenario_history.txt new file mode 100644 index 00000000..c4ca6aad --- /dev/null +++ b/docs/results/danube/2.0/scenario_history.txt @@ -0,0 +1,1454 @@ +date,scenario,installer,detail,score +2017-03-13 10:00,os-odl_l2-fdio-noha,apex,5/33,15.0 +2017-03-13 10:00,os-odl_l2-fdio-ha,apex,1/33,3.0 +2017-03-14 01:45,os-odl_l2-fdio-noha,apex,12/33,36.0 +2017-03-14 01:45,os-odl_l2-fdio-ha,apex,1/33,3.0 +2017-03-15 01:45,os-odl_l2-fdio-noha,apex,29/33,88.0 +2017-03-15 01:45,os-odl_l2-fdio-ha,apex,4/33,12.0 +2017-03-16 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-03-16 01:45,os-odl_l2-fdio-ha,apex,13/36,36.0 +2017-03-16 10:23,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-16 10:23,os-odl_l2-fdio-ha,apex,13/36,36.0 +2017-03-17 01:45,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-17 01:45,os-odl_l2-fdio-ha,apex,20/36,56.0 +2017-03-17 07:33,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-17 07:33,os-odl_l2-fdio-ha,apex,20/36,56.0 +2017-03-17 08:49,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-17 08:49,os-nosdn-nofeature-ha,apex,9/33,27.0 +2017-03-17 08:49,os-odl_l2-fdio-ha,apex,20/36,56.0 +2017-03-18 01:45,os-odl-gluon-noha,apex,12/39,31.0 +2017-03-18 01:45,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-18 01:45,os-odl_l3-fdio-noha,apex,15/30,50.0 +2017-03-18 01:45,os-odl_l3-nofeature-ha,apex,8/33,24.0 +2017-03-18 01:45,os-odl_l2-fdio-ha,apex,19/36,53.0 +2017-03-18 01:45,os-odl-bgpvpn-ha,apex,11/39,28.0 +2017-03-18 01:45,os-nosdn-nofeature-ha,apex,11/33,33.0 +2017-03-19 01:45,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-19 01:45,os-odl_l3-fdio-noha,apex,21/30,70.0 +2017-03-19 01:45,os-odl_l3-nofeature-ha,apex,15/33,45.0 +2017-03-19 01:45,os-odl_l2-fdio-ha,apex,19/36,53.0 +2017-03-19 01:45,os-odl-bgpvpn-ha,apex,14/39,36.0 +2017-03-19 01:45,os-nosdn-kvm-ha,apex,11/33,33.0 +2017-03-19 01:45,os-nosdn-nofeature-ha,apex,22/33,67.0 +2017-03-19 01:45,os-odl-gluon-noha,apex,22/39,56.0 +2017-03-19 01:45,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-19 01:45,os-odl_l3-fdio-noha,apex,21/30,70.0 +2017-03-19 01:45,os-odl_l3-nofeature-ha,apex,15/33,45.0 +2017-03-19 01:45,os-odl_l2-fdio-ha,apex,19/36,53.0 +2017-03-19 01:45,os-odl-bgpvpn-ha,apex,14/39,36.0 +2017-03-19 01:45,os-nosdn-kvm-ha,apex,11/33,33.0 +2017-03-19 01:45,os-nosdn-nofeature-ha,apex,22/33,67.0 +2017-03-20 01:45,os-odl-gluon-noha,apex,23/39,59.0 +2017-03-20 01:45,os-odl_l2-fdio-noha,apex,33/36,92.0 +2017-03-20 01:45,os-odl_l3-fdio-noha,apex,21/30,70.0 +2017-03-20 01:45,os-odl_l3-nofeature-ha,apex,15/33,45.0 +2017-03-20 01:45,os-odl_l2-fdio-ha,apex,19/36,53.0 +2017-03-20 01:45,os-nosdn-fdio-ha,apex,2/30,7.0 +2017-03-20 01:45,os-odl-bgpvpn-ha,apex,14/39,36.0 +2017-03-20 01:45,os-nosdn-kvm-ha,apex,12/33,36.0 +2017-03-20 01:45,os-nosdn-nofeature-ha,apex,22/33,67.0 +2017-03-17 01:45,os-nosdn-nofeature-ha,compass,10/30,33.0 +2017-03-17 07:33,os-ocl-nofeature-ha,compass,1/30,3.0 +2017-03-17 07:33,os-nosdn-nofeature-ha,compass,10/30,33.0 +2017-03-17 08:49,os-ocl-nofeature-ha,compass,1/30,3.0 +2017-03-17 08:49,os-nosdn-nofeature-ha,compass,10/30,33.0 +2017-03-18 01:45,os-ocl-nofeature-ha,compass,1/30,3.0 +2017-03-18 01:45,os-odl_l2-nofeature-ha,compass,20/33,61.0 +2017-03-18 01:45,os-nosdn-openo-ha,compass,10/30,33.0 +2017-03-18 01:45,os-odl_l3-nofeature-ha,compass,16/30,53.0 +2017-03-18 01:45,os-nosdn-nofeature-ha,compass,20/30,67.0 +2017-03-19 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-03-19 01:45,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-19 01:45,os-onos-nofeature-ha,compass,11/33,33.0 +2017-03-19 01:45,os-odl_l2-nofeature-ha,compass,26/33,79.0 +2017-03-19 01:45,os-nosdn-openo-ha,compass,10/30,33.0 +2017-03-19 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-03-20 01:45,os-odl_l3-nofeature-ha,compass,27/30,90.0 +2017-03-20 01:45,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-20 01:45,os-onos-nofeature-ha,compass,22/33,67.0 +2017-03-20 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-20 01:45,os-nosdn-openo-ha,compass,10/30,33.0 +2017-03-20 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-03-19 01:45,os-odl_l2-nofeature-ha,fuel,13/42,31.0 +2017-03-19 01:45,os-odl_l2-nofeature-ha,fuel,13/42,31.0 +2017-03-20 01:45,os-odl_l2-nofeature-ha,fuel,13/42,31.0 +2017-03-20 01:45,os-odl_l2-bgpvpn-ha,fuel,3/42,7.0 +2017-03-16 10:23,os-nosdn-nofeature-ha,joid,10/33,30.0 +2017-03-17 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-17 01:45,os-odl_l2-nofeature-ha,joid,2/36,6.0 +2017-03-17 01:45,os-nosdn-nofeature-ha,joid,10/33,30.0 +2017-03-17 07:33,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-17 07:33,os-odl_l2-nofeature-ha,joid,2/36,6.0 +2017-03-17 07:33,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-17 07:33,os-nosdn-nofeature-noha,joid,11/33,33.0 +2017-03-17 08:49,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-17 08:49,os-odl_l2-nofeature-ha,joid,2/36,6.0 +2017-03-17 08:49,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-17 08:49,os-nosdn-nofeature-noha,joid,11/33,33.0 +2017-03-18 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-18 01:45,os-odl_l2-nofeature-ha,joid,2/36,6.0 +2017-03-18 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-18 01:45,os-nosdn-nofeature-noha,joid,11/33,33.0 +2017-03-19 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-19 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-03-19 01:45,os-nosdn-lxd-ha,joid,1/24,4.0 +2017-03-19 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-19 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-03-20 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-20 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-03-20 01:45,os-nosdn-lxd-ha,joid,1/24,4.0 +2017-03-20 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-20 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-03-21 01:45,os-odl-gluon-noha,apex,23/39,59.0 +2017-03-21 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-21 01:45,os-odl_l3-fdio-noha,apex,27/30,90.0 +2017-03-21 01:45,os-odl_l3-nofeature-ha,apex,15/33,45.0 +2017-03-21 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-21 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-03-21 01:45,os-odl-bgpvpn-ha,apex,22/39,56.0 +2017-03-21 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-03-21 01:45,os-nosdn-nofeature-ha,apex,27/33,82.0 +2017-03-21 01:45,os-odl_l3-nofeature-ha,compass,27/30,90.0 +2017-03-21 01:45,os-ocl-nofeature-ha,compass,7/30,23.0 +2017-03-21 01:45,os-onos-nofeature-ha,compass,31/33,94.0 +2017-03-21 01:45,os-odl_l2-nofeature-ha,compass,30/33,91.0 +2017-03-21 01:45,os-nosdn-openo-ha,compass,20/30,67.0 +2017-03-21 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-03-21 01:45,os-odl_l3-nofeature-noha,fuel,11/36,31.0 +2017-03-21 01:45,os-nosdn-nofeature-noha,fuel,12/36,33.0 +2017-03-21 01:45,os-odl_l2-nofeature-noha,fuel,12/39,31.0 +2017-03-21 01:45,os-odl_l2-bgpvpn-ha,fuel,15/42,36.0 +2017-03-21 01:45,os-nosdn-ovs-ha,fuel,26/39,67.0 +2017-03-21 01:45,os-odl_l2-nofeature-ha,fuel,13/42,31.0 +2017-03-21 01:45,os-nosdn-nofeature-ha,fuel,26/39,67.0 +2017-03-21 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-21 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-03-21 01:45,os-nosdn-lxd-ha,joid,1/24,4.0 +2017-03-21 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-21 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 + +2017-03-22 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-22 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-22 01:45,os-odl_l3-fdio-noha,apex,27/30,90.0 +2017-03-22 01:45,os-odl_l3-nofeature-ha,apex,22/33,67.0 +2017-03-22 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-22 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-03-22 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-22 01:45,os-nosdn-kvm-ha,apex,23/33,70.0 +2017-03-22 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-03-22 01:45,os-odl_l3-nofeature-ha,compass,27/30,90.0 +2017-03-22 01:45,os-ocl-nofeature-ha,compass,7/30,23.0 +2017-03-22 01:45,os-onos-nofeature-ha,compass,31/33,94.0 +2017-03-22 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-03-22 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-22 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-22 01:45,os-nosdn-ovs-noha,fuel,12/36,33.0 +2017-03-22 01:45,os-odl_l3-nofeature-noha,fuel,11/36,31.0 +2017-03-22 01:45,os-odl_l2-bgpvpn-noha,fuel,12/42,29.0 +2017-03-22 01:45,os-odl_l2-sfc-noha,fuel,2/42,5.0 +2017-03-22 01:45,os-odl_l3-nofeature-ha,fuel,19/39,49.0 +2017-03-22 01:45,os-nosdn-nofeature-noha,fuel,24/36,67.0 +2017-03-22 01:45,os-odl_l2-nofeature-noha,fuel,14/39,36.0 +2017-03-22 01:45,os-odl_l2-bgpvpn-ha,fuel,22/42,52.0 +2017-03-22 01:45,os-odl_l2-sfc-ha,fuel,13/45,29.0 +2017-03-22 01:45,os-nosdn-ovs-ha,fuel,26/39,67.0 +2017-03-22 01:45,os-odl_l2-nofeature-ha,fuel,26/42,62.0 +2017-03-22 01:45,os-nosdn-nofeature-ha,fuel,26/39,67.0 +2017-03-22 01:45,os-nosdn-lxd-noha,joid,14/24,58.0 +2017-03-22 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-03-22 01:45,os-nosdn-lxd-ha,joid,2/24,8.0 +2017-03-22 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-22 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-03-23 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-23 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-23 01:45,os-odl_l3-fdio-noha,apex,27/30,90.0 +2017-03-23 01:45,os-odl_l3-nofeature-ha,apex,21/33,64.0 +2017-03-23 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-23 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-03-23 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-23 01:45,os-nosdn-kvm-ha,apex,23/33,70.0 +2017-03-23 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-23 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-03-23 01:45,os-ocl-nofeature-ha,compass,7/30,23.0 +2017-03-23 01:45,os-onos-nofeature-ha,compass,30/33,91.0 +2017-03-23 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-23 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-23 01:45,os-nosdn-nofeature-ha,compass,28/30,93.0 +2017-03-23 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,12/36,33.0 +2017-03-23 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,2/42,5.0 +2017-03-23 01:45,os-nosdn-kvm-noha,fuel,12/36,33.0 +2017-03-23 01:45,os-nosdn-ovs-noha,fuel,24/36,67.0 +2017-03-23 01:45,os-odl_l3-nofeature-noha,fuel,22/36,61.0 +2017-03-23 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,2/39,5.0 +2017-03-23 01:45,os-odl_l2-bgpvpn-noha,fuel,24/42,57.0 +2017-03-23 01:45,os-odl_l2-sfc-noha,fuel,2/42,5.0 +2017-03-23 01:45,os-odl_l3-nofeature-ha,fuel,19/39,49.0 +2017-03-23 01:45,os-nosdn-kvm-ha,fuel,25/39,64.0 +2017-03-23 01:45,os-nosdn-nofeature-noha,fuel,24/36,67.0 +2017-03-23 01:45,os-odl_l2-nofeature-noha,fuel,26/39,67.0 +2017-03-23 01:45,os-odl_l2-bgpvpn-ha,fuel,25/42,60.0 +2017-03-23 01:45,os-odl_l2-sfc-ha,fuel,13/45,29.0 +2017-03-23 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,24/39,62.0 +2017-03-23 01:45,os-nosdn-ovs-ha,fuel,26/39,67.0 +2017-03-23 01:45,os-odl_l2-nofeature-ha,fuel,26/42,62.0 +2017-03-23 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-03-23 01:45,os-nosdn-lxd-noha,joid,20/24,83.0 +2017-03-23 01:45,os-odl_l2-nofeature-ha,joid,7/36,19.0 +2017-03-23 01:45,os-nosdn-lxd-ha,joid,7/24,29.0 +2017-03-23 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-23 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-03-24 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-24 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-24 01:45,os-odl_l3-fdio-noha,apex,27/30,90.0 +2017-03-24 01:45,os-odl_l3-nofeature-ha,apex,21/33,64.0 +2017-03-24 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-24 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-03-24 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-24 01:45,os-nosdn-kvm-ha,apex,31/33,94.0 +2017-03-24 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-24 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-03-24 01:45,os-ocl-nofeature-ha,compass,6/30,20.0 +2017-03-24 01:45,os-onos-nofeature-ha,compass,31/33,94.0 +2017-03-24 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-24 01:45,os-nosdn-openo-ha,compass,25/30,83.0 +2017-03-24 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-24 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,24/36,67.0 +2017-03-24 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,4/42,10.0 +2017-03-24 01:45,os-nosdn-kvm-noha,fuel,24/36,67.0 +2017-03-24 01:45,os-nosdn-ovs-noha,fuel,24/36,67.0 +2017-03-24 01:45,os-odl_l3-nofeature-noha,fuel,23/36,64.0 +2017-03-24 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,4/39,10.0 +2017-03-24 01:45,os-odl_l2-bgpvpn-noha,fuel,24/42,57.0 +2017-03-24 01:45,os-odl_l2-sfc-noha,fuel,14/42,33.0 +2017-03-24 01:45,os-odl_l3-nofeature-ha,fuel,24/39,62.0 +2017-03-24 01:45,os-nosdn-kvm-ha,fuel,25/39,64.0 +2017-03-24 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-24 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-03-24 01:45,os-odl_l2-bgpvpn-ha,fuel,27/42,64.0 +2017-03-24 01:45,os-odl_l2-sfc-ha,fuel,24/45,53.0 +2017-03-24 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,24/39,62.0 +2017-03-24 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-03-24 01:45,os-odl_l2-nofeature-ha,fuel,26/42,62.0 +2017-03-24 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-24 01:45,os-nosdn-lxd-noha,joid,20/24,83.0 +2017-03-24 01:45,os-odl_l2-nofeature-ha,joid,7/36,19.0 +2017-03-24 01:45,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-24 01:45,os-nosdn-nofeature-ha,joid,11/33,33.0 +2017-03-24 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-25 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-25 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-25 01:45,os-odl_l3-fdio-noha,apex,27/30,90.0 +2017-03-25 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-03-25 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-25 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-03-25 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-25 01:45,os-nosdn-kvm-ha,apex,31/33,94.0 +2017-03-25 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-25 01:45,os-odl_l3-nofeature-ha,compass,27/30,90.0 +2017-03-25 01:45,os-ocl-nofeature-ha,compass,6/30,20.0 +2017-03-25 01:45,os-onos-nofeature-ha,compass,27/33,82.0 +2017-03-25 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-25 01:45,os-nosdn-openo-ha,compass,25/30,83.0 +2017-03-25 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-25 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,24/36,67.0 +2017-03-25 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,4/42,10.0 +2017-03-25 01:45,os-nosdn-kvm-noha,fuel,24/36,67.0 +2017-03-25 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-25 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-25 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,4/39,10.0 +2017-03-25 01:45,os-odl_l2-bgpvpn-noha,fuel,26/42,62.0 +2017-03-25 01:45,os-odl_l2-sfc-noha,fuel,24/42,57.0 +2017-03-25 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-25 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-25 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-25 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-03-25 01:45,os-odl_l2-bgpvpn-ha,fuel,35/42,83.0 +2017-03-25 01:45,os-odl_l2-sfc-ha,fuel,25/45,56.0 +2017-03-25 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,24/39,62.0 +2017-03-25 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-03-25 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-03-25 01:45,os-nosdn-nofeature-ha,fuel,35/39,90.0 +2017-03-25 01:45,os-nosdn-lxd-noha,joid,19/24,79.0 +2017-03-25 01:45,os-odl_l2-nofeature-ha,joid,7/36,19.0 +2017-03-25 01:45,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-25 01:45,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-03-25 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-26 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-26 01:45,os-odl_l2-fdio-noha,apex,32/36,89.0 +2017-03-26 01:45,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-26 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-03-26 01:45,os-odl_l2-fdio-ha,apex,22/36,61.0 +2017-03-26 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-26 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-26 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-26 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-26 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-03-26 01:45,os-ocl-nofeature-ha,compass,6/30,20.0 +2017-03-26 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-03-26 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-26 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-26 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-26 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,24/36,67.0 +2017-03-26 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,4/42,10.0 +2017-03-26 01:45,os-nosdn-kvm-noha,fuel,24/36,67.0 +2017-03-26 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-26 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-26 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,4/39,10.0 +2017-03-26 01:45,os-odl_l2-bgpvpn-noha,fuel,26/42,62.0 +2017-03-26 01:45,os-odl_l2-sfc-noha,fuel,24/42,57.0 +2017-03-26 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-26 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-26 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-26 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-03-26 01:45,os-odl_l2-bgpvpn-ha,fuel,35/42,83.0 +2017-03-26 01:45,os-odl_l2-sfc-ha,fuel,25/45,56.0 +2017-03-26 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,24/39,62.0 +2017-03-26 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-03-26 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-03-26 01:45,os-nosdn-nofeature-ha,fuel,35/39,90.0 +2017-03-26 01:45,os-nosdn-lxd-noha,joid,19/24,79.0 +2017-03-26 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-26 01:45,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-26 01:45,os-nosdn-nofeature-ha,joid,22/33,67.0 +2017-03-26 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-27 01:45,os-odl-gluon-noha,apex,34/39,87.0 +2017-03-27 01:45,os-odl_l2-fdio-noha,apex,18/36,50.0 +2017-03-27 01:45,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-27 01:45,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-03-27 01:45,os-odl_l2-fdio-ha,apex,21/36,58.0 +2017-03-27 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-27 01:45,os-odl-bgpvpn-ha,apex,25/39,64.0 +2017-03-27 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-27 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-27 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-03-27 01:45,os-ocl-nofeature-ha,compass,5/30,17.0 +2017-03-27 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-03-27 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-03-27 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-27 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-27 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,24/36,67.0 +2017-03-27 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,4/42,10.0 +2017-03-27 01:45,os-nosdn-kvm-noha,fuel,24/36,67.0 +2017-03-27 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-27 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-27 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,4/39,10.0 +2017-03-27 01:45,os-odl_l2-bgpvpn-noha,fuel,26/42,62.0 +2017-03-27 01:45,os-odl_l2-sfc-noha,fuel,24/42,57.0 +2017-03-27 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-27 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-27 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-27 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-03-27 01:45,os-odl_l2-bgpvpn-ha,fuel,35/42,83.0 +2017-03-27 01:45,os-odl_l2-sfc-ha,fuel,25/45,56.0 +2017-03-27 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,24/39,62.0 +2017-03-27 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-03-27 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-03-27 01:45,os-nosdn-nofeature-ha,fuel,35/39,90.0 +2017-03-27 01:45,os-nosdn-lxd-noha,joid,13/24,54.0 +2017-03-27 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-27 01:45,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-27 01:45,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-03-27 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-28 01:45,os-odl-gluon-noha,apex,33/39,85.0 +2017-03-28 01:45,os-odl_l2-fdio-noha,apex,28/36,78.0 +2017-03-28 01:45,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-28 01:45,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-03-28 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-28 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-28 01:45,os-odl-bgpvpn-ha,apex,24/39,62.0 +2017-03-28 01:45,os-odl_l2-fdio-ha,apex,20/36,56.0 +2017-03-28 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-28 01:45,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-28 01:45,os-ocl-nofeature-ha,compass,5/30,17.0 +2017-03-28 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-03-28 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-28 01:45,os-nosdn-openo-ha,compass,30/30,100.0 +2017-03-28 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-03-28 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-28 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-28 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-28 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-28 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-28 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-28 01:45,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-28 01:45,os-odl_l2-sfc-noha,fuel,27/42,64.0 +2017-03-28 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-28 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-28 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-28 01:45,os-odl_l2-nofeature-noha,fuel,37/39,95.0 +2017-03-28 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-28 01:45,os-odl_l2-sfc-ha,fuel,37/45,82.0 +2017-03-28 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,37/39,95.0 +2017-03-28 01:45,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-28 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-03-28 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-28 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-03-28 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-28 01:45,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-28 01:45,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-03-28 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-28 13:20,os-odl-gluon-noha,apex,30/36,83.0 +2017-03-28 13:20,os-odl_l2-fdio-noha,apex,28/36,78.0 +2017-03-28 13:20,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-28 13:20,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-03-28 13:20,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-28 13:20,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-28 13:20,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-03-28 13:20,os-odl_l2-fdio-ha,apex,25/36,69.0 +2017-03-28 13:20,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-28 13:20,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-28 13:20,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-28 13:20,os-onos-nofeature-ha,compass,27/33,82.0 +2017-03-28 13:20,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-28 13:20,os-nosdn-openo-ha,compass,30/30,100.0 +2017-03-28 13:20,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-28 13:20,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-28 13:20,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-28 13:20,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-28 13:20,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-28 13:20,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-28 13:20,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-28 13:20,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-28 13:20,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-03-28 13:20,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-28 13:20,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-28 13:20,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-28 13:20,os-odl_l2-nofeature-noha,fuel,37/39,95.0 +2017-03-28 13:20,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-28 13:20,os-odl_l2-sfc-ha,fuel,37/45,82.0 +2017-03-28 13:20,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,37/39,95.0 +2017-03-28 13:20,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-28 13:20,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-28 13:20,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-28 13:20,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-03-28 13:20,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-28 13:20,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-28 13:20,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-03-28 13:20,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-28 13:56,os-odl-gluon-noha,apex,30/36,83.0 +2017-03-28 13:56,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-03-28 13:56,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-28 13:56,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-03-28 13:56,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-28 13:56,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-28 13:56,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-03-28 13:56,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-28 13:56,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-03-28 13:56,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-28 13:56,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-28 13:56,os-onos-nofeature-ha,compass,27/33,82.0 +2017-03-28 13:56,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-28 13:56,os-nosdn-openo-ha,compass,30/30,100.0 +2017-03-28 13:56,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-28 13:56,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-28 13:56,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-28 13:56,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-28 13:56,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-28 13:56,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-28 13:56,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-28 13:56,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-28 13:56,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-03-28 13:56,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-28 13:56,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-28 13:56,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-28 13:56,os-odl_l2-nofeature-noha,fuel,37/39,95.0 +2017-03-28 13:56,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-28 13:56,os-odl_l2-sfc-ha,fuel,37/45,82.0 +2017-03-28 13:56,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,37/39,95.0 +2017-03-28 13:56,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-28 13:56,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-28 13:56,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-28 13:56,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-03-28 13:56,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-28 13:56,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-28 13:56,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-03-28 13:56,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-28 16:16,os-odl-gluon-noha,apex,30/36,83.0 +2017-03-28 16:16,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-03-28 16:16,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-28 16:16,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-03-28 16:16,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-28 16:16,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-28 16:16,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-03-28 16:16,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-28 16:16,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-03-28 16:16,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-28 16:16,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-28 16:16,os-onos-nofeature-ha,compass,27/33,82.0 +2017-03-28 16:16,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-28 16:16,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-28 16:16,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-28 16:16,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-28 16:16,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-28 16:16,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-28 16:16,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-28 16:16,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-03-28 16:16,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-28 16:16,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-28 16:16,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-03-28 16:16,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-03-28 16:16,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-28 16:16,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-28 16:16,os-odl_l2-nofeature-noha,fuel,37/39,95.0 +2017-03-28 16:16,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-28 16:16,os-odl_l2-sfc-ha,fuel,40/45,89.0 +2017-03-28 16:16,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,37/39,95.0 +2017-03-28 16:16,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-28 16:16,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-28 16:16,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-28 16:16,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-03-28 16:16,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-28 16:16,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-03-28 16:16,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-03-28 16:16,os-nosdn-lxd-ha,joid,13/24,54.0 +2017-03-29 01:45,os-odl-gluon-noha,apex,30/36,83.0 +2017-03-29 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-03-29 01:45,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-29 01:45,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-03-29 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-29 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-29 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-03-29 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-03-29 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-03-29 01:45,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-29 01:45,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-29 01:45,os-onos-nofeature-ha,compass,27/33,82.0 +2017-03-29 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-29 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-03-29 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-29 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-29 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-29 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-29 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-29 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-29 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-29 01:45,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-29 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-03-29 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-03-29 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-29 01:45,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-03-29 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-03-29 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-29 01:45,os-odl_l2-sfc-ha,fuel,40/45,89.0 +2017-03-29 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,38/39,97.0 +2017-03-29 01:45,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-29 01:45,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-29 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-03-29 01:45,os-nosdn-lxd-noha,joid,17/24,71.0 +2017-03-29 01:45,os-nosdn-nofeature-noha,joid,31/33,94.0 +2017-03-29 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-29 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-03-29 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-03-30 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-03-30 01:45,os-odl-gluon-noha,apex,31/36,86.0 +2017-03-30 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-03-30 01:45,os-odl_l3-fdio-noha,apex,26/30,87.0 +2017-03-30 01:45,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-03-30 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-30 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-30 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-03-30 01:45,os-nosdn-ovs-ha,apex,2/33,6.0 +2017-03-30 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-03-30 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-03-30 01:45,os-odl_l3-nofeature-ha,compass,21/30,70.0 +2017-03-30 01:45,os-ocl-nofeature-ha,compass,4/30,13.0 +2017-03-30 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-03-30 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-30 01:45,os-nosdn-openo-ha,compass,28/30,93.0 +2017-03-30 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-30 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-30 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-30 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-30 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-30 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-30 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-30 01:45,os-odl_l2-bgpvpn-noha,fuel,36/42,86.0 +2017-03-30 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-03-30 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-03-30 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-30 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-30 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-03-30 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-03-30 01:45,os-odl_l2-sfc-ha,fuel,42/45,93.0 +2017-03-30 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,38/39,97.0 +2017-03-30 01:45,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-30 01:45,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-30 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-03-30 01:45,os-nosdn-lxd-noha,joid,17/24,71.0 +2017-03-30 01:45,os-nosdn-nofeature-noha,joid,31/33,94.0 +2017-03-30 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-30 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-03-30 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-03-31 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-03-31 01:45,os-odl-gluon-noha,apex,30/36,83.0 +2017-03-31 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-03-31 01:45,os-odl_l3-fdio-noha,apex,20/30,67.0 +2017-03-31 01:45,os-odl-bgpvpn-ha,apex,21/36,58.0 +2017-03-31 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-03-31 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-03-31 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-03-31 01:45,os-odl_l3-ovs-ha,apex,2/33,6.0 +2017-03-31 01:45,os-nosdn-ovs-ha,apex,2/33,6.0 +2017-03-31 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-03-31 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-03-31 01:45,os-odl_l3-nofeature-ha,compass,23/30,77.0 +2017-03-31 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-03-31 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-03-31 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-03-31 01:45,os-nosdn-openo-ha,compass,28/30,93.0 +2017-03-31 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-03-31 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-03-31 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-03-31 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-03-31 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-03-31 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-03-31 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-03-31 01:45,os-odl_l3-nofeature-ha,fuel,31/39,79.0 +2017-03-31 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-03-31 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-03-31 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-03-31 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-03-31 01:45,os-odl_l2-sfc-ha,fuel,43/45,96.0 +2017-03-31 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-03-31 01:45,os-odl_l2-bgpvpn-noha,fuel,37/42,88.0 +2017-03-31 01:45,os-odl_l2-nofeature-ha,fuel,42/42,100.0 +2017-03-31 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-03-31 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-03-31 01:45,os-nosdn-ovs-ha,fuel,38/39,97.0 +2017-03-31 01:45,os-nosdn-lxd-noha,joid,17/24,71.0 +2017-03-31 01:45,os-nosdn-nofeature-noha,joid,31/33,94.0 +2017-03-31 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-03-31 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-03-31 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-01 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-01 01:45,os-odl-gluon-noha,apex,24/36,67.0 +2017-04-01 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-04-01 01:45,os-odl_l3-fdio-noha,apex,20/30,67.0 +2017-04-01 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-04-01 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-04-01 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-01 01:45,os-odl-bgpvpn-ha,apex,21/36,58.0 +2017-04-01 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-01 01:45,os-nosdn-ovs-ha,apex,2/33,6.0 +2017-04-01 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-04-01 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-04-01 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-01 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-01 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-01 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-04-01 01:45,os-nosdn-openo-ha,compass,28/30,93.0 +2017-04-01 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-01 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-01 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-01 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-01 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-01 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-01 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-01 01:45,os-odl_l3-nofeature-ha,fuel,32/39,82.0 +2017-04-01 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-01 01:45,os-odl_l2-nofeature-ha,fuel,39/42,93.0 +2017-04-01 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-01 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-04-01 01:45,os-odl_l2-bgpvpn-ha,fuel,34/42,81.0 +2017-04-01 01:45,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-04-01 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-01 01:45,os-odl_l2-bgpvpn-noha,fuel,38/42,90.0 +2017-04-01 01:45,os-odl_l2-sfc-ha,fuel,44/45,98.0 +2017-04-01 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-01 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-04-01 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-01 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-01 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-01 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-01 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-04-02 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-02 01:45,os-odl-gluon-noha,apex,24/36,67.0 +2017-04-02 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-04-02 01:45,os-odl_l3-fdio-noha,apex,13/30,43.0 +2017-04-02 01:45,os-odl-bgpvpn-ha,apex,21/36,58.0 +2017-04-02 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-04-02 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-02 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-04-02 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-02 01:45,os-nosdn-ovs-ha,apex,2/33,6.0 +2017-04-02 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-04-02 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-04-02 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-02 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-02 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-02 01:45,os-odl_l2-nofeature-ha,compass,27/33,82.0 +2017-04-02 01:45,os-nosdn-openo-ha,compass,28/30,93.0 +2017-04-02 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-02 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-02 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-02 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-02 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-02 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-02 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-02 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-02 01:45,os-odl_l3-nofeature-ha,fuel,32/39,82.0 +2017-04-02 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-02 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-02 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-02 01:45,os-odl_l2-bgpvpn-ha,fuel,34/42,81.0 +2017-04-02 01:45,os-odl_l2-sfc-ha,fuel,40/45,89.0 +2017-04-02 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-02 01:45,os-odl_l2-bgpvpn-noha,fuel,38/42,90.0 +2017-04-02 01:45,os-odl_l2-nofeature-ha,fuel,37/42,88.0 +2017-04-02 01:45,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-04-02 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-04-02 01:45,os-odl_l2-nofeature-ha,joid,6/36,17.0 +2017-04-02 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-02 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-02 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-02 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-03 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-03 01:45,os-odl-gluon-noha,apex,29/36,81.0 +2017-04-03 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-04-03 01:45,os-odl_l3-fdio-noha,apex,13/30,43.0 +2017-04-03 01:45,os-odl_l3-nofeature-ha,apex,27/33,82.0 +2017-04-03 01:45,os-odl_l2-fdio-ha,apex,26/36,72.0 +2017-04-03 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-03 01:45,os-odl-bgpvpn-ha,apex,21/36,58.0 +2017-04-03 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-03 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-03 01:45,os-nosdn-kvm-ha,apex,33/33,100.0 +2017-04-03 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-04-03 01:45,os-odl_l3-nofeature-ha,compass,23/30,77.0 +2017-04-03 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-03 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-03 01:45,os-odl_l2-nofeature-ha,compass,27/33,82.0 +2017-04-03 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-03 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-03 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-03 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-03 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-03 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-03 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-03 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-03 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-03 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-03 01:45,os-odl_l3-nofeature-ha,fuel,32/39,82.0 +2017-04-03 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-03 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-03 01:45,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-04-03 01:45,os-odl_l2-bgpvpn-ha,fuel,35/42,83.0 +2017-04-03 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-03 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-03 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-03 01:45,os-odl_l2-nofeature-ha,fuel,38/42,90.0 +2017-04-03 01:45,os-nosdn-nofeature-ha,fuel,36/39,92.0 +2017-04-03 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-03 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-03 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-03 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-03 01:45,os-odl_l2-nofeature-ha,joid,6/36,17.0 +2017-04-04 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-04 01:45,os-odl-gluon-noha,apex,30/36,83.0 +2017-04-04 01:45,os-ovn-nofeature-noha,apex,3/33,9.0 +2017-04-04 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-04-04 01:45,os-odl_l3-fdio-noha,apex,6/30,20.0 +2017-04-04 01:45,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-04-04 01:45,os-nosdn-kvm-ha,apex,33/33,100.0 +2017-04-04 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-04 01:45,os-odl-bgpvpn-ha,apex,22/36,61.0 +2017-04-04 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-04 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-04 01:45,os-odl_l2-fdio-ha,apex,26/36,72.0 +2017-04-04 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-04-04 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-04 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-04 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-04 01:45,os-odl_l2-nofeature-ha,compass,27/33,82.0 +2017-04-04 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-04 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-04 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-04 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-04 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-04 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-04 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-04 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-04 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-04 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-04 01:45,os-nosdn-kvm-ha,fuel,36/39,92.0 +2017-04-04 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-04 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-04 01:45,os-odl_l2-bgpvpn-ha,fuel,36/42,86.0 +2017-04-04 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-04-04 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-04 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-04 01:45,os-odl_l2-nofeature-ha,fuel,38/42,90.0 +2017-04-04 01:45,os-odl_l3-nofeature-noha,fuel,34/36,94.0 +2017-04-04 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-04-04 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-04 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-04 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-04 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-04 01:45,os-odl_l2-nofeature-ha,joid,6/36,17.0 +2017-04-05 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-05 01:45,os-odl-gluon-noha,apex,29/36,81.0 +2017-04-05 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-05 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-04-05 01:45,os-odl_l3-fdio-noha,apex,6/30,20.0 +2017-04-05 01:45,os-odl-bgpvpn-ha,apex,21/36,58.0 +2017-04-05 01:45,os-nosdn-kvm-ha,apex,33/33,100.0 +2017-04-05 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-05 01:45,os-odl_l3-nofeature-ha,apex,26/33,79.0 +2017-04-05 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-05 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-05 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-04-05 01:45,os-nosdn-nofeature-ha,apex,33/33,100.0 +2017-04-05 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-05 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-05 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-05 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-04-05 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-05 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-05 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-05 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-05 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-05 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-05 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-05 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-05 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-04-05 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-05 01:45,os-nosdn-kvm-ha,fuel,36/39,92.0 +2017-04-05 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-05 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-05 01:45,os-odl_l2-bgpvpn-ha,fuel,36/42,86.0 +2017-04-05 01:45,os-odl_l3-nofeature-ha,fuel,35/39,90.0 +2017-04-05 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-05 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-05 01:45,os-odl_l2-nofeature-ha,fuel,37/42,88.0 +2017-04-05 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-05 01:45,os-nosdn-nofeature-ha,fuel,36/39,92.0 +2017-04-05 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-05 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-05 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-05 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-05 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-06 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-06 01:45,os-odl-gluon-noha,apex,29/36,81.0 +2017-04-06 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-06 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-04-06 01:45,os-odl_l3-fdio-noha,apex,4/30,13.0 +2017-04-06 01:45,os-odl-bgpvpn-ha,apex,27/36,75.0 +2017-04-06 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-04-06 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-06 01:45,os-odl_l3-nofeature-ha,apex,25/33,76.0 +2017-04-06 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-06 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-06 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-04-06 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-04-06 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-06 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-06 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-06 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-06 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-06 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-06 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-06 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-06 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-06 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-06 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-06 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-06 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-04-06 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-06 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-06 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-06 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-06 01:45,os-odl_l2-bgpvpn-ha,fuel,36/42,86.0 +2017-04-06 01:45,os-odl_l3-nofeature-ha,fuel,35/39,90.0 +2017-04-06 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-06 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-06 01:45,os-odl_l2-nofeature-ha,fuel,38/42,90.0 +2017-04-06 01:45,os-odl_l3-nofeature-noha,fuel,32/36,89.0 +2017-04-06 01:45,os-nosdn-nofeature-ha,fuel,35/39,90.0 +2017-04-06 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-06 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-06 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-06 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-06 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-07 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-07 01:45,os-odl-gluon-noha,apex,27/36,75.0 +2017-04-07 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-07 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-04-07 01:45,os-odl_l3-fdio-noha,apex,6/30,20.0 +2017-04-07 01:45,os-odl-bgpvpn-ha,apex,27/36,75.0 +2017-04-07 01:45,os-odl_l2-fdio-ha,apex,28/36,78.0 +2017-04-07 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-07 01:45,os-odl_l3-nofeature-ha,apex,25/33,76.0 +2017-04-07 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-07 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-04-07 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-04-07 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-04-07 01:45,os-odl_l3-nofeature-ha,compass,23/30,77.0 +2017-04-07 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-07 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-07 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-07 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-07 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-07 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-07 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-07 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-07 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-07 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-07 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-07 01:45,os-odl_l2-nofeature-noha,fuel,33/39,85.0 +2017-04-07 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-04-07 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-04-07 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-07 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-07 01:45,os-odl_l3-nofeature-noha,fuel,32/36,89.0 +2017-04-07 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-04-07 01:45,os-odl_l2-sfc-ha,fuel,42/45,93.0 +2017-04-07 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-07 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-07 01:45,os-odl_l2-nofeature-ha,fuel,37/42,88.0 +2017-04-07 01:45,os-nosdn-nofeature-ha,fuel,36/39,92.0 +2017-04-07 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-04-07 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-04-07 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-07 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-07 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-08 01:45,os-nosdn-fdio-noha,apex,15/30,50.0 +2017-04-08 01:45,os-odl-gluon-noha,apex,27/36,75.0 +2017-04-08 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-08 01:45,os-odl_l2-fdio-noha,apex,30/36,83.0 +2017-04-08 01:45,os-odl_l3-fdio-noha,apex,6/30,20.0 +2017-04-08 01:45,os-odl_l3-nofeature-ha,apex,18/33,55.0 +2017-04-08 01:45,os-nosdn-kvm-ha,apex,32/33,97.0 +2017-04-08 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-08 01:45,os-odl-bgpvpn-ha,apex,19/36,53.0 +2017-04-08 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-08 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-04-08 01:45,os-odl_l2-fdio-ha,apex,27/36,75.0 +2017-04-08 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-04-08 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-04-08 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-08 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-08 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-08 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-08 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-08 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-08 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-08 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-08 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-08 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-08 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-08 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-08 01:45,os-odl_l3-nofeature-ha,fuel,35/39,90.0 +2017-04-08 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-08 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-08 01:45,os-odl_l2-nofeature-noha,fuel,33/39,85.0 +2017-04-08 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-08 01:45,os-odl_l2-sfc-ha,fuel,42/45,93.0 +2017-04-08 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-08 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-08 01:45,os-odl_l2-nofeature-ha,fuel,37/42,88.0 +2017-04-08 01:45,os-odl_l3-nofeature-noha,fuel,32/36,89.0 +2017-04-08 01:45,os-nosdn-nofeature-ha,fuel,35/39,90.0 +2017-04-08 01:45,os-nosdn-lxd-noha,joid,12/24,50.0 +2017-04-08 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-08 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-08 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-04-08 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-09 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-04-09 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-09 01:45,os-odl_l2-fdio-noha,apex,22/36,61.0 +2017-04-09 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-09 01:45,os-odl-bgpvpn-ha,apex,19/36,53.0 +2017-04-09 01:45,os-odl_l2-fdio-ha,apex,27/36,75.0 +2017-04-09 01:45,os-odl_l3-fdio-noha,apex,4/30,13.0 +2017-04-09 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-09 01:45,os-odl_l3-nofeature-ha,apex,18/33,55.0 +2017-04-09 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-09 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-04-09 01:45,os-nosdn-nofeature-ha,apex,32/33,97.0 +2017-04-09 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-09 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-09 01:45,os-onos-nofeature-ha,compass,27/33,82.0 +2017-04-09 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-09 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-09 01:45,os-nosdn-nofeature-ha,compass,28/30,93.0 +2017-04-09 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-09 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-09 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-09 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-09 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-09 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-09 01:45,os-odl_l2-nofeature-noha,fuel,33/39,85.0 +2017-04-09 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-09 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-04-09 01:45,os-nosdn-kvm-ha,fuel,38/39,97.0 +2017-04-09 01:45,os-nosdn-nofeature-noha,fuel,35/36,97.0 +2017-04-09 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-09 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-09 01:45,os-odl_l2-sfc-ha,fuel,40/45,89.0 +2017-04-09 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-09 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-09 01:45,os-odl_l2-nofeature-ha,fuel,39/42,93.0 +2017-04-09 01:45,os-nosdn-nofeature-ha,fuel,36/39,92.0 +2017-04-09 01:45,os-nosdn-lxd-noha,joid,12/24,50.0 +2017-04-09 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-09 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-09 01:45,os-nosdn-nofeature-ha,joid,22/33,67.0 +2017-04-09 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-10 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-04-10 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-10 01:45,os-odl_l2-fdio-noha,apex,22/36,61.0 +2017-04-10 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-04-10 01:45,os-odl-bgpvpn-ha,apex,19/36,53.0 +2017-04-10 01:45,os-odl_l2-fdio-ha,apex,21/36,58.0 +2017-04-10 01:45,os-odl_l3-fdio-noha,apex,4/30,13.0 +2017-04-10 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-04-10 01:45,os-odl_l3-nofeature-ha,apex,18/33,55.0 +2017-04-10 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-10 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-04-10 01:45,os-nosdn-nofeature-ha,apex,22/33,67.0 +2017-04-10 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-10 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-10 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-10 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-04-10 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-10 01:45,os-nosdn-nofeature-ha,compass,28/30,93.0 +2017-04-10 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-10 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-10 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-10 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-10 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-10 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-10 01:45,os-odl_l2-sfc-noha,fuel,32/42,76.0 +2017-04-10 01:45,os-odl_l3-nofeature-ha,fuel,35/39,90.0 +2017-04-10 01:45,os-nosdn-kvm-ha,fuel,38/39,97.0 +2017-04-10 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-10 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-10 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-10 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-10 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-10 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-10 01:45,os-odl_l2-nofeature-ha,fuel,39/42,93.0 +2017-04-10 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-10 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-04-10 01:45,os-nosdn-lxd-noha,joid,12/24,50.0 +2017-04-10 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-10 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-10 01:45,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-04-10 01:45,os-nosdn-lxd-ha,joid,12/24,50.0 +2017-04-11 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-04-11 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-11 01:45,os-odl_l2-fdio-noha,apex,22/36,61.0 +2017-04-11 01:45,os-odl_l3-fdio-noha,apex,4/30,13.0 +2017-04-11 01:45,os-odl-bgpvpn-ha,apex,19/36,53.0 +2017-04-11 01:45,os-odl_l2-fdio-ha,apex,21/36,58.0 +2017-04-11 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-04-11 01:45,os-odl_l3-nofeature-ha,apex,18/33,55.0 +2017-04-11 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-11 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-11 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-04-11 01:45,os-nosdn-nofeature-ha,apex,22/33,67.0 +2017-04-11 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-04-11 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-11 01:45,os-onos-nofeature-ha,compass,29/33,88.0 +2017-04-11 01:45,os-odl_l2-nofeature-ha,compass,30/33,91.0 +2017-04-11 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-11 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-04-11 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-11 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-11 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-11 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-11 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-11 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-11 01:45,os-odl_l2-sfc-noha,fuel,32/42,76.0 +2017-04-11 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-04-11 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-11 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-11 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-11 01:45,os-odl_l2-bgpvpn-ha,fuel,36/42,86.0 +2017-04-11 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-11 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-11 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-11 01:45,os-odl_l2-nofeature-ha,fuel,38/42,90.0 +2017-04-11 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-11 01:45,os-nosdn-nofeature-ha,fuel,39/39,100.0 +2017-04-11 01:45,os-nosdn-lxd-noha,joid,6/24,25.0 +2017-04-11 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-11 01:45,os-nosdn-lxd-ha,joid,6/24,25.0 +2017-04-11 01:45,os-nosdn-nofeature-ha,joid,22/33,67.0 +2017-04-11 01:45,os-odl_l2-nofeature-ha,joid,3/36,8.0 +2017-04-12 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-04-12 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-12 01:45,os-odl_l2-fdio-noha,apex,22/36,61.0 +2017-04-12 01:45,os-odl_l3-fdio-noha,apex,4/30,13.0 +2017-04-12 01:45,os-odl_l3-nofeature-ha,apex,17/33,52.0 +2017-04-12 01:45,os-nosdn-kvm-ha,apex,22/33,67.0 +2017-04-12 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-04-12 01:45,os-odl-bgpvpn-ha,apex,19/36,53.0 +2017-04-12 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-12 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-12 01:45,os-odl_l2-fdio-ha,apex,21/36,58.0 +2017-04-12 01:45,os-nosdn-nofeature-ha,apex,21/33,64.0 +2017-04-12 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-04-12 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-12 01:45,os-onos-nofeature-ha,compass,29/33,88.0 +2017-04-12 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-12 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-04-12 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-12 01:45,os-nosdn-kvm-noha,fuel,35/36,97.0 +2017-04-12 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-12 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-12 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-12 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-12 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-12 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-12 01:45,os-odl_l2-sfc-noha,fuel,34/42,81.0 +2017-04-12 01:45,os-odl_l3-nofeature-ha,fuel,34/39,87.0 +2017-04-12 01:45,os-nosdn-kvm-ha,fuel,37/39,95.0 +2017-04-12 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-12 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-12 01:45,os-odl_l2-bgpvpn-ha,fuel,36/42,86.0 +2017-04-12 01:45,os-odl_l2-sfc-ha,fuel,39/45,87.0 +2017-04-12 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-12 01:45,os-odl_l2-bgpvpn-noha,fuel,39/42,93.0 +2017-04-12 01:45,os-odl_l2-nofeature-ha,fuel,38/42,90.0 +2017-04-12 01:45,os-nosdn-nofeature-ha,fuel,39/39,100.0 +2017-04-12 01:45,os-nosdn-lxd-noha,joid,12/24,50.0 +2017-04-12 01:45,os-nosdn-nofeature-noha,joid,11/33,33.0 +2017-04-12 01:45,os-odl_l2-nofeature-ha,joid,1/36,3.0 +2017-04-12 01:45,os-nosdn-nofeature-ha,joid,12/33,36.0 +2017-04-12 01:45,os-nosdn-lxd-ha,joid,6/24,25.0 +2017-04-28 20:23,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-04-28 20:23,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-28 20:23,os-odl_l2-fdio-noha,apex,19/36,53.0 +2017-04-28 20:23,os-odl_l3-fdio-noha,apex,24/30,80.0 +2017-04-28 20:23,os-odl_l3-nofeature-ha,apex,16/33,48.0 +2017-04-28 20:23,os-nosdn-kvm-ha,apex,20/33,61.0 +2017-04-28 20:23,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-04-28 20:23,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-28 20:23,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-28 20:23,os-odl_l2-fdio-ha,apex,26/36,72.0 +2017-04-28 20:23,os-nosdn-nofeature-ha,apex,20/33,61.0 +2017-04-28 20:23,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-04-28 20:23,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-28 20:23,os-onos-nofeature-ha,compass,29/33,88.0 +2017-04-28 20:23,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-28 20:23,os-nosdn-openo-ha,compass,30/30,100.0 +2017-04-28 20:23,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-28 20:23,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-28 20:23,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-28 20:23,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-28 20:23,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-28 20:23,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-28 20:23,os-odl_l2-bgpvpn-noha,fuel,40/42,95.0 +2017-04-28 20:23,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-04-28 20:23,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-04-28 20:23,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-04-28 20:23,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-28 20:23,os-odl_l2-nofeature-noha,fuel,34/39,87.0 +2017-04-28 20:23,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-28 20:23,os-odl_l2-sfc-ha,fuel,41/45,91.0 +2017-04-28 20:23,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-28 20:23,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-28 20:23,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-04-28 20:23,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-28 20:23,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-04-28 20:23,os-nosdn-lxd-noha,joid,11/24,46.0 +2017-04-28 20:23,os-odl_l2-nofeature-ha,joid,8/36,22.0 +2017-04-28 20:23,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-28 20:23,os-nosdn-nofeature-ha,joid,29/33,88.0 +2017-04-28 20:23,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-29 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-04-29 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-29 01:45,os-odl_l2-fdio-noha,apex,19/36,53.0 +2017-04-29 01:45,os-odl_l3-fdio-noha,apex,24/30,80.0 +2017-04-29 01:45,os-odl_l3-nofeature-ha,apex,16/33,48.0 +2017-04-29 01:45,os-nosdn-kvm-ha,apex,20/33,61.0 +2017-04-29 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-04-29 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-29 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-29 01:45,os-odl_l2-fdio-ha,apex,30/36,83.0 +2017-04-29 01:45,os-nosdn-nofeature-ha,apex,20/33,61.0 +2017-04-29 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-04-29 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-29 01:45,os-onos-nofeature-ha,compass,29/33,88.0 +2017-04-29 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-29 01:45,os-nosdn-openo-ha,compass,30/30,100.0 +2017-04-29 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-29 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-29 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-29 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-29 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-29 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-29 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-29 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-04-29 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-04-29 01:45,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-04-29 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-29 01:45,os-odl_l2-nofeature-noha,fuel,34/39,87.0 +2017-04-29 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-29 01:45,os-odl_l2-sfc-ha,fuel,41/45,91.0 +2017-04-29 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-29 01:45,os-odl_l2-bgpvpn-noha,fuel,40/42,95.0 +2017-04-29 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-04-29 01:45,os-odl_l3-nofeature-noha,fuel,33/36,92.0 +2017-04-29 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-04-29 01:45,os-nosdn-lxd-noha,joid,11/24,46.0 +2017-04-29 01:45,os-odl_l2-nofeature-ha,joid,8/36,22.0 +2017-04-29 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-29 01:45,os-nosdn-nofeature-ha,joid,29/33,88.0 +2017-04-29 01:45,os-nosdn-nofeature-noha,joid,22/33,67.0 +2017-04-30 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-04-30 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-04-30 01:45,os-odl_l2-fdio-noha,apex,19/36,53.0 +2017-04-30 01:45,os-odl_l3-fdio-noha,apex,24/30,80.0 +2017-04-30 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-04-30 01:45,os-nosdn-kvm-ha,apex,20/33,61.0 +2017-04-30 01:45,os-nosdn-fdio-ha,apex,4/30,13.0 +2017-04-30 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-04-30 01:45,os-nosdn-ovs-ha,apex,4/33,12.0 +2017-04-30 01:45,os-odl_l2-fdio-ha,apex,30/36,83.0 +2017-04-30 01:45,os-nosdn-nofeature-ha,apex,20/33,61.0 +2017-04-30 01:45,os-odl_l3-nofeature-ha,compass,24/30,80.0 +2017-04-30 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-04-30 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-04-30 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-04-30 01:45,os-nosdn-openo-ha,compass,30/30,100.0 +2017-04-30 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-04-30 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-04-30 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-04-30 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-04-30 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-04-30 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-04-30 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-04-30 01:45,os-odl_l2-sfc-noha,fuel,35/42,83.0 +2017-04-30 01:45,os-odl_l3-nofeature-ha,fuel,36/39,92.0 +2017-04-30 01:45,os-nosdn-kvm-ha,fuel,38/39,97.0 +2017-04-30 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-04-30 01:45,os-odl_l2-nofeature-noha,fuel,35/39,90.0 +2017-04-30 01:45,os-odl_l2-bgpvpn-ha,fuel,37/42,88.0 +2017-04-30 01:45,os-odl_l2-sfc-ha,fuel,42/45,93.0 +2017-04-30 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-04-30 01:45,os-odl_l2-bgpvpn-noha,fuel,41/42,98.0 +2017-04-30 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-04-30 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-04-30 01:45,os-nosdn-nofeature-ha,fuel,39/39,100.0 +2017-04-30 01:45,os-nosdn-lxd-noha,joid,12/24,50.0 +2017-04-30 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-04-30 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-04-30 01:45,os-nosdn-nofeature-ha,joid,21/33,64.0 +2017-04-30 01:45,os-odl_l2-nofeature-ha,joid,8/36,22.0 +2017-05-01 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-05-01 01:45,os-odl-gluon-noha,apex,9/36,25.0 +2017-05-01 01:45,os-ovn-nofeature-noha,apex,6/33,18.0 +2017-05-01 01:45,os-odl-bgpvpn-ha,apex,8/36,22.0 +2017-05-01 01:45,os-odl_l2-fdio-noha,apex,28/36,78.0 +2017-05-01 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-05-01 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-05-01 01:45,os-nosdn-kvm-ha,apex,30/33,91.0 +2017-05-01 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-05-01 01:45,os-odl_l3-fdio-noha,apex,23/30,77.0 +2017-05-01 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-05-01 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-05-01 01:45,os-nosdn-nofeature-ha,apex,20/33,61.0 +2017-05-01 01:45,os-odl_l3-fdio-ha,apex,24/30,80.0 +2017-05-01 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-05-01 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-05-01 01:45,os-onos-nofeature-ha,compass,27/33,82.0 +2017-05-01 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-05-01 01:45,os-nosdn-openo-ha,compass,30/30,100.0 +2017-05-01 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-05-01 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-05-01 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-05-01 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-05-01 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-05-01 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-05-01 01:45,os-odl_l2-sfc-noha,fuel,36/42,86.0 +2017-05-01 01:45,os-odl_l3-nofeature-ha,fuel,37/39,95.0 +2017-05-01 01:45,os-nosdn-kvm-ha,fuel,38/39,97.0 +2017-05-01 01:45,os-odl_l3-nofeature-noha,fuel,35/36,97.0 +2017-05-01 01:45,os-odl_l2-nofeature-noha,fuel,36/39,92.0 +2017-05-01 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-05-01 01:45,os-odl_l2-sfc-ha,fuel,44/45,98.0 +2017-05-01 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-05-01 01:45,os-odl_l2-bgpvpn-noha,fuel,41/42,98.0 +2017-05-01 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-05-01 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-05-01 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-05-01 01:45,os-nosdn-nofeature-ha,fuel,39/39,100.0 +2017-05-01 01:45,os-nosdn-lxd-noha,joid,17/24,71.0 +2017-05-01 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-05-01 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-05-01 01:45,os-nosdn-nofeature-ha,joid,17/33,52.0 +2017-05-01 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-05-02 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-05-02 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-05-02 01:45,os-ovn-nofeature-noha,apex,9/33,27.0 +2017-05-02 01:45,os-odl-bgpvpn-ha,apex,16/36,44.0 +2017-05-02 01:45,os-odl_l2-fdio-noha,apex,28/36,78.0 +2017-05-02 01:45,os-odl_l3-ovs-ha,apex,4/33,12.0 +2017-05-02 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-05-02 01:45,os-nosdn-kvm-ha,apex,30/33,91.0 +2017-05-02 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-05-02 01:45,os-odl_l3-fdio-noha,apex,23/30,77.0 +2017-05-02 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-05-02 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-05-02 01:45,os-nosdn-nofeature-ha,apex,30/33,91.0 +2017-05-02 01:45,os-odl_l3-fdio-ha,apex,24/30,80.0 +2017-05-02 01:45,os-odl_l3-nofeature-ha,compass,26/30,87.0 +2017-05-02 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-05-02 01:45,os-onos-nofeature-ha,compass,27/33,82.0 +2017-05-02 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-05-02 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-05-02 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-05-02 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-05-02 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-05-02 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-05-02 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-05-02 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-05-02 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-05-02 01:45,os-odl_l2-sfc-noha,fuel,38/42,90.0 +2017-05-02 01:45,os-odl_l3-nofeature-ha,fuel,37/39,95.0 +2017-05-02 01:45,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-05-02 01:45,os-odl_l3-nofeature-noha,fuel,36/36,100.0 +2017-05-02 01:45,os-odl_l2-nofeature-noha,fuel,38/39,97.0 +2017-05-02 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-05-02 01:45,os-odl_l2-sfc-ha,fuel,44/45,98.0 +2017-05-02 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-05-02 01:45,os-odl_l2-bgpvpn-noha,fuel,42/42,100.0 +2017-05-02 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-05-02 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-05-02 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-05-02 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-05-02 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-05-02 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-05-02 01:45,os-nosdn-nofeature-ha,joid,18/33,55.0 +2017-05-02 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-05-03 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-05-03 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-05-03 01:45,os-ovn-nofeature-noha,apex,9/33,27.0 +2017-05-03 01:45,os-odl-bgpvpn-ha,apex,16/36,44.0 +2017-05-03 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-05-03 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-05-03 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-05-03 01:45,os-nosdn-kvm-ha,apex,30/33,91.0 +2017-05-03 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-05-03 01:45,os-odl_l3-fdio-noha,apex,23/30,77.0 +2017-05-03 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-05-03 01:45,os-odl_l2-fdio-ha,apex,30/36,83.0 +2017-05-03 01:45,os-nosdn-nofeature-ha,apex,30/33,91.0 +2017-05-03 01:45,os-odl_l3-fdio-ha,apex,24/30,80.0 +2017-05-03 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-05-03 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-05-03 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-05-03 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-05-03 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-05-03 01:45,os-nosdn-nofeature-ha,compass,30/30,100.0 +2017-05-03 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-05-03 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-05-03 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-05-03 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-05-03 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-05-03 01:45,os-odl_l2-sfc-noha,fuel,39/42,93.0 +2017-05-03 01:45,os-odl_l3-nofeature-ha,fuel,37/39,95.0 +2017-05-03 01:45,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-05-03 01:45,os-odl_l3-nofeature-noha,fuel,36/36,100.0 +2017-05-03 01:45,os-odl_l2-nofeature-noha,fuel,38/39,97.0 +2017-05-03 01:45,os-odl_l2-bgpvpn-ha,fuel,38/42,90.0 +2017-05-03 01:45,os-odl_l2-sfc-ha,fuel,45/45,100.0 +2017-05-03 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,39/39,100.0 +2017-05-03 01:45,os-odl_l2-bgpvpn-noha,fuel,42/42,100.0 +2017-05-03 01:45,os-odl_l2-nofeature-ha,fuel,41/42,98.0 +2017-05-03 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-05-03 01:45,os-nosdn-nofeature-ha,fuel,37/39,95.0 +2017-05-03 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-05-03 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-05-03 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-05-03 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-05-03 01:45,os-nosdn-nofeature-ha,joid,22/33,67.0 +2017-05-03 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-05-04 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-05-04 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-05-04 01:45,os-ovn-nofeature-noha,apex,9/33,27.0 +2017-05-04 01:45,os-odl-bgpvpn-ha,apex,16/36,44.0 +2017-05-04 01:45,os-odl_l2-fdio-noha,apex,29/36,81.0 +2017-05-04 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-05-04 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-05-04 01:45,os-nosdn-kvm-ha,apex,30/33,91.0 +2017-05-04 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-05-04 01:45,os-odl_l3-fdio-noha,apex,23/30,77.0 +2017-05-04 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-05-04 01:45,os-odl_l2-fdio-ha,apex,30/36,83.0 +2017-05-04 01:45,os-nosdn-nofeature-ha,apex,30/33,91.0 +2017-05-04 01:45,os-odl_l3-fdio-ha,apex,24/30,80.0 +2017-05-04 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-05-04 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-05-04 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-05-04 01:45,os-odl_l2-nofeature-ha,compass,29/33,88.0 +2017-05-04 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-05-04 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-05-04 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-05-04 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,6/42,14.0 +2017-05-04 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-05-04 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-05-04 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-05-04 01:45,os-odl_l2-sfc-noha,fuel,39/42,93.0 +2017-05-04 01:45,os-odl_l3-nofeature-ha,fuel,38/39,97.0 +2017-05-04 01:45,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-05-04 01:45,os-odl_l3-nofeature-noha,fuel,36/36,100.0 +2017-05-04 01:45,os-odl_l2-nofeature-noha,fuel,37/39,95.0 +2017-05-04 01:45,os-odl_l2-bgpvpn-ha,fuel,40/42,95.0 +2017-05-04 01:45,os-odl_l2-sfc-ha,fuel,45/45,100.0 +2017-05-04 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,38/39,97.0 +2017-05-04 01:45,os-odl_l2-bgpvpn-noha,fuel,42/42,100.0 +2017-05-04 01:45,os-odl_l2-nofeature-ha,fuel,40/42,95.0 +2017-05-04 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-05-04 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-05-04 01:45,os-nosdn-nofeature-ha,fuel,38/39,97.0 +2017-05-04 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-05-04 01:45,os-nosdn-nofeature-noha,joid,33/33,100.0 +2017-05-04 01:45,os-nosdn-lxd-ha,joid,18/24,75.0 +2017-05-04 01:45,os-nosdn-nofeature-ha,joid,29/33,88.0 +2017-05-04 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 +2017-05-05 01:45,os-nosdn-fdio-noha,apex,28/30,93.0 +2017-05-05 01:45,os-odl-gluon-noha,apex,18/36,50.0 +2017-05-05 01:45,os-ovn-nofeature-noha,apex,9/33,27.0 +2017-05-05 01:45,os-odl-bgpvpn-ha,apex,16/36,44.0 +2017-05-05 01:45,os-odl_l2-fdio-noha,apex,28/36,78.0 +2017-05-05 01:45,os-odl_l3-ovs-ha,apex,6/33,18.0 +2017-05-05 01:45,os-odl_l3-nofeature-ha,apex,23/33,70.0 +2017-05-05 01:45,os-nosdn-kvm-ha,apex,30/33,91.0 +2017-05-05 01:45,os-nosdn-fdio-ha,apex,6/30,20.0 +2017-05-05 01:45,os-odl_l3-fdio-noha,apex,23/30,77.0 +2017-05-05 01:45,os-nosdn-ovs-ha,apex,6/33,18.0 +2017-05-05 01:45,os-odl_l2-fdio-ha,apex,29/36,81.0 +2017-05-05 01:45,os-nosdn-nofeature-ha,apex,30/33,91.0 +2017-05-05 01:45,os-odl_l3-fdio-ha,apex,23/30,77.0 +2017-05-05 01:45,os-odl_l3-nofeature-ha,compass,25/30,83.0 +2017-05-05 01:45,os-ocl-nofeature-ha,compass,3/30,10.0 +2017-05-05 01:45,os-onos-nofeature-ha,compass,28/33,85.0 +2017-05-05 01:45,os-odl_l2-nofeature-ha,compass,28/33,85.0 +2017-05-05 01:45,os-nosdn-openo-ha,compass,29/30,97.0 +2017-05-05 01:45,os-nosdn-nofeature-ha,compass,29/30,97.0 +2017-05-05 01:45,os-nosdn-kvm_ovs_dpdk-noha,fuel,36/36,100.0 +2017-05-05 01:45,os-nosdn-kvm_ovs_dpdk_bar-ha,fuel,12/42,29.0 +2017-05-05 01:45,os-nosdn-kvm-noha,fuel,36/36,100.0 +2017-05-05 01:45,os-nosdn-ovs-noha,fuel,36/36,100.0 +2017-05-05 01:45,os-odl_l3-nofeature-noha,fuel,36/36,100.0 +2017-05-05 01:45,os-nosdn-kvm_ovs_dpdk-ha,fuel,6/39,15.0 +2017-05-05 01:45,os-odl_l2-sfc-noha,fuel,40/42,95.0 +2017-05-05 01:45,os-odl_l3-nofeature-ha,fuel,37/39,95.0 +2017-05-05 01:45,os-nosdn-kvm-ha,fuel,39/39,100.0 +2017-05-05 01:45,os-nosdn-nofeature-noha,fuel,36/36,100.0 +2017-05-05 01:45,os-odl_l2-nofeature-noha,fuel,38/39,97.0 +2017-05-05 01:45,os-odl_l2-bgpvpn-ha,fuel,39/42,93.0 +2017-05-05 01:45,os-odl_l2-sfc-ha,fuel,45/45,100.0 +2017-05-05 01:45,os-nosdn-kvm_ovs_dpdk_bar-noha,fuel,38/39,97.0 +2017-05-05 01:45,os-odl_l2-bgpvpn-noha,fuel,42/42,100.0 +2017-05-05 01:45,os-odl_l2-nofeature-ha,fuel,40/42,95.0 +2017-05-05 01:45,os-nosdn-nofeature-ha,fuel,39/39,100.0 +2017-05-05 01:45,os-nosdn-ovs-ha,fuel,39/39,100.0 +2017-05-05 01:45,os-nosdn-lxd-noha,joid,18/24,75.0 +2017-05-05 01:45,os-nosdn-nofeature-noha,joid,32/33,97.0 +2017-05-05 01:45,os-nosdn-lxd-ha,joid,17/24,71.0 +2017-05-05 01:45,os-nosdn-nofeature-ha,joid,32/33,97.0 +2017-05-05 01:45,os-odl_l2-nofeature-ha,joid,9/36,25.0 diff --git a/docs/results/danube/2.0/validated_scenario_history.txt b/docs/results/danube/2.0/validated_scenario_history.txt new file mode 100644 index 00000000..15ec001e --- /dev/null +++ b/docs/results/danube/2.0/validated_scenario_history.txt @@ -0,0 +1,212 @@ +2017-03-19 02:03;compass;os-nosdn-nofeature-ha +2017-03-20 02:04;compass;os-nosdn-nofeature-ha +2017-03-21 02:03;compass;os-nosdn-nofeature-ha +2017-03-22 02:01;apex;os-nosdn-nofeature-ha +2017-03-23 02:14;joid;os-nosdn-nofeature-noha +2017-03-24 02:09;fuel;os-nosdn-nofeature-noha +2017-03-24 02:11;fuel;os-nosdn-ovs-ha +2017-03-25 02:06;fuel;os-nosdn-ovs-noha +2017-03-25 02:09;fuel;os-nosdn-nofeature-noha +2017-03-25 02:11;fuel;os-nosdn-ovs-ha +2017-03-26 02:06;fuel;os-nosdn-ovs-noha +2017-03-26 02:09;fuel;os-nosdn-nofeature-noha +2017-03-26 02:11;fuel;os-nosdn-ovs-ha +2017-03-27 02:06;fuel;os-nosdn-ovs-noha +2017-03-27 02:09;fuel;os-nosdn-nofeature-noha +2017-03-27 02:11;fuel;os-nosdn-ovs-ha +2017-03-28 02:04;compass;os-nosdn-openo-ha +2017-03-28 02:04;compass;os-nosdn-nofeature-ha +2017-03-28 02:04;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-28 02:05;fuel;os-nosdn-kvm-noha +2017-03-28 02:06;fuel;os-nosdn-ovs-noha +2017-03-28 02:09;fuel;os-nosdn-nofeature-noha +2017-03-28 13:40;compass;os-nosdn-openo-ha +2017-03-28 13:41;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-28 13:42;fuel;os-nosdn-kvm-noha +2017-03-28 13:42;fuel;os-nosdn-ovs-noha +2017-03-28 13:45;fuel;os-nosdn-nofeature-noha +2017-03-28 13:48;fuel;os-odl_l2-nofeature-ha +2017-03-28 14:15;compass;os-nosdn-openo-ha +2017-03-28 14:16;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-28 14:17;fuel;os-nosdn-kvm-noha +2017-03-28 14:18;fuel;os-nosdn-ovs-noha +2017-03-28 14:21;fuel;os-nosdn-nofeature-noha +2017-03-28 14:23;fuel;os-odl_l2-nofeature-ha +2017-03-28 16:33;apex;os-nosdn-nofeature-ha +2017-03-28 16:36;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-28 16:37;fuel;os-nosdn-kvm-noha +2017-03-28 16:38;fuel;os-nosdn-ovs-noha +2017-03-28 16:41;fuel;os-nosdn-nofeature-noha +2017-03-28 16:43;fuel;os-odl_l2-nofeature-ha +2017-03-29 02:02;apex;os-nosdn-nofeature-ha +2017-03-29 02:05;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-29 02:05;fuel;os-nosdn-kvm-noha +2017-03-29 02:06;fuel;os-nosdn-ovs-noha +2017-03-29 02:06;fuel;os-nosdn-nofeature-noha +2017-03-29 02:11;fuel;os-odl_l2-nofeature-ha +2017-03-30 02:02;apex;os-nosdn-nofeature-ha +2017-03-30 02:05;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-30 02:06;fuel;os-nosdn-kvm-noha +2017-03-30 02:06;fuel;os-nosdn-ovs-noha +2017-03-30 02:07;fuel;os-nosdn-nofeature-noha +2017-03-30 02:11;fuel;os-odl_l2-nofeature-ha +2017-03-31 02:04;apex;os-nosdn-nofeature-ha +2017-03-31 02:07;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-03-31 02:08;fuel;os-nosdn-kvm-noha +2017-03-31 02:09;fuel;os-nosdn-ovs-noha +2017-03-31 02:11;fuel;os-nosdn-nofeature-noha +2017-03-31 02:13;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-03-31 02:14;fuel;os-odl_l2-nofeature-ha +2017-04-01 02:04;apex;os-nosdn-nofeature-ha +2017-04-01 02:07;compass;os-nosdn-nofeature-ha +2017-04-01 02:07;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-01 02:08;fuel;os-nosdn-kvm-noha +2017-04-01 02:09;fuel;os-nosdn-ovs-noha +2017-04-01 02:11;fuel;os-nosdn-nofeature-noha +2017-04-01 02:13;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-01 02:15;fuel;os-nosdn-ovs-ha +2017-04-02 02:04;apex;os-nosdn-nofeature-ha +2017-04-02 02:07;compass;os-nosdn-nofeature-ha +2017-04-02 02:07;fuel;os-nosdn-kvm-noha +2017-04-02 02:08;fuel;os-nosdn-ovs-ha +2017-04-02 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-02 02:09;fuel;os-nosdn-ovs-noha +2017-04-02 02:11;fuel;os-nosdn-nofeature-noha +2017-04-02 02:13;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-03 02:04;apex;os-nosdn-kvm-ha +2017-04-03 02:04;apex;os-nosdn-nofeature-ha +2017-04-03 02:07;compass;os-nosdn-nofeature-ha +2017-04-03 02:07;fuel;os-nosdn-kvm-noha +2017-04-03 02:08;fuel;os-nosdn-ovs-ha +2017-04-03 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-03 02:09;fuel;os-nosdn-ovs-noha +2017-04-03 02:12;fuel;os-nosdn-nofeature-noha +2017-04-03 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-04 02:02;apex;os-nosdn-kvm-ha +2017-04-04 02:05;apex;os-nosdn-nofeature-ha +2017-04-04 02:07;compass;os-nosdn-nofeature-ha +2017-04-04 02:09;fuel;os-nosdn-ovs-ha +2017-04-04 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-04 02:10;fuel;os-nosdn-ovs-noha +2017-04-04 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-05 02:00;apex;os-nosdn-kvm-ha +2017-04-05 02:03;apex;os-nosdn-nofeature-ha +2017-04-05 02:06;compass;os-nosdn-nofeature-ha +2017-04-05 02:07;fuel;os-nosdn-ovs-ha +2017-04-05 02:08;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-05 02:08;fuel;os-nosdn-ovs-noha +2017-04-05 02:13;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-06 02:07;compass;os-nosdn-nofeature-ha +2017-04-06 02:08;fuel;os-nosdn-ovs-ha +2017-04-06 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-06 02:09;fuel;os-nosdn-ovs-noha +2017-04-06 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-07 02:08;fuel;os-nosdn-ovs-ha +2017-04-07 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-07 02:09;fuel;os-nosdn-ovs-noha +2017-04-07 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-08 02:08;fuel;os-nosdn-ovs-ha +2017-04-08 02:09;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-08 02:09;fuel;os-nosdn-ovs-noha +2017-04-08 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-09 02:07;fuel;os-nosdn-kvm-noha +2017-04-09 02:08;fuel;os-nosdn-ovs-ha +2017-04-09 02:08;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-09 02:09;fuel;os-nosdn-ovs-noha +2017-04-09 02:14;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-10 02:07;fuel;os-nosdn-kvm-noha +2017-04-10 02:08;fuel;os-nosdn-ovs-ha +2017-04-10 02:08;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-10 02:09;fuel;os-nosdn-ovs-noha +2017-04-10 02:11;fuel;os-nosdn-nofeature-noha +2017-04-10 02:13;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-11 02:06;compass;os-nosdn-nofeature-ha +2017-04-11 02:06;fuel;os-nosdn-kvm-noha +2017-04-11 02:07;fuel;os-nosdn-ovs-ha +2017-04-11 02:08;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-11 02:08;fuel;os-nosdn-ovs-noha +2017-04-11 02:11;fuel;os-nosdn-nofeature-noha +2017-04-11 02:13;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-11 02:15;fuel;os-nosdn-nofeature-ha +2017-04-12 02:07;fuel;os-nosdn-ovs-ha +2017-04-12 02:07;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-12 02:08;fuel;os-nosdn-ovs-noha +2017-04-12 02:11;fuel;os-nosdn-nofeature-noha +2017-04-12 02:13;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-12 02:14;fuel;os-nosdn-nofeature-ha +2017-04-28 20:46;compass;os-nosdn-openo-ha +2017-04-28 20:48;fuel;os-nosdn-kvm-noha +2017-04-28 20:49;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-28 20:49;fuel;os-nosdn-ovs-noha +2017-04-28 20:52;fuel;os-nosdn-kvm-ha +2017-04-28 20:54;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-28 20:55;fuel;os-nosdn-ovs-ha +2017-04-28 20:56;fuel;os-nosdn-nofeature-noha +2017-04-29 02:07;compass;os-nosdn-openo-ha +2017-04-29 02:08;fuel;os-nosdn-kvm-noha +2017-04-29 02:09;fuel;os-nosdn-ovs-ha +2017-04-29 02:10;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-29 02:10;fuel;os-nosdn-ovs-noha +2017-04-29 02:12;fuel;os-nosdn-kvm-ha +2017-04-29 02:13;fuel;os-nosdn-nofeature-noha +2017-04-29 02:15;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-30 02:07;compass;os-nosdn-openo-ha +2017-04-30 02:08;fuel;os-nosdn-kvm-noha +2017-04-30 02:09;fuel;os-nosdn-ovs-ha +2017-04-30 02:10;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-04-30 02:10;fuel;os-nosdn-ovs-noha +2017-04-30 02:13;fuel;os-nosdn-nofeature-noha +2017-04-30 02:15;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-04-30 02:17;fuel;os-nosdn-nofeature-ha +2017-04-30 02:18;joid;os-nosdn-nofeature-noha +2017-05-01 02:09;compass;os-nosdn-openo-ha +2017-05-01 02:10;fuel;os-nosdn-kvm-noha +2017-05-01 02:10;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-05-01 02:11;fuel;os-nosdn-ovs-ha +2017-05-01 02:11;fuel;os-nosdn-ovs-noha +2017-05-01 02:16;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-05-01 02:18;fuel;os-nosdn-nofeature-noha +2017-05-01 02:18;fuel;os-nosdn-nofeature-ha +2017-05-01 02:21;joid;os-nosdn-nofeature-noha +2017-05-02 02:10;fuel;os-nosdn-kvm-noha +2017-05-02 02:11;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-05-02 02:11;fuel;os-nosdn-ovs-ha +2017-05-02 02:12;fuel;os-nosdn-ovs-noha +2017-05-02 02:14;fuel;os-nosdn-kvm-ha +2017-05-02 02:14;fuel;os-odl_l3-nofeature-noha +2017-05-02 02:16;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-05-02 02:17;fuel;os-odl_l2-bgpvpn-noha +2017-05-02 02:18;fuel;os-nosdn-nofeature-noha +2017-05-02 02:19;joid;os-nosdn-nofeature-noha +2017-05-03 02:09;compass;os-nosdn-nofeature-ha +2017-05-03 02:10;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-05-03 02:11;fuel;os-nosdn-kvm-noha +2017-05-03 02:11;fuel;os-nosdn-ovs-noha +2017-05-03 02:13;fuel;os-nosdn-kvm-ha +2017-05-03 02:14;fuel;os-odl_l3-nofeature-noha +2017-05-03 02:15;fuel;os-odl_l2-sfc-ha +2017-05-03 02:16;fuel;os-nosdn-kvm_ovs_dpdk_bar-noha +2017-05-03 02:16;fuel;os-odl_l2-bgpvpn-noha +2017-05-03 02:17;fuel;os-nosdn-nofeature-noha +2017-05-03 02:18;fuel;os-nosdn-ovs-ha +2017-05-03 02:19;joid;os-nosdn-nofeature-noha +2017-05-04 02:10;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-05-04 02:11;fuel;os-nosdn-ovs-ha +2017-05-04 02:11;fuel;os-nosdn-ovs-noha +2017-05-04 02:13;fuel;os-nosdn-kvm-ha +2017-05-04 02:14;fuel;os-odl_l3-nofeature-noha +2017-05-04 02:15;fuel;os-odl_l2-sfc-ha +2017-05-04 02:16;fuel;os-odl_l2-bgpvpn-noha +2017-05-04 02:17;fuel;os-nosdn-nofeature-noha +2017-05-04 02:18;fuel;os-nosdn-kvm-noha +2017-05-04 02:19;joid;os-nosdn-nofeature-noha +2017-05-05 02:10;fuel;os-nosdn-kvm_ovs_dpdk-noha +2017-05-05 02:11;fuel;os-nosdn-kvm-noha +2017-05-05 02:11;fuel;os-nosdn-ovs-noha +2017-05-05 02:12;fuel;os-odl_l3-nofeature-noha +2017-05-05 02:14;fuel;os-nosdn-kvm-ha +2017-05-05 02:14;fuel;os-nosdn-nofeature-noha +2017-05-05 02:16;fuel;os-odl_l2-sfc-ha +2017-05-05 02:17;fuel;os-odl_l2-bgpvpn-noha +2017-05-05 02:18;fuel;os-nosdn-nofeature-ha +2017-05-05 02:18;fuel;os-nosdn-ovs-ha diff --git a/docs/testing/user/configguide/configguide.rst b/docs/testing/user/configguide/configguide.rst index e3485be4..9a174978 100644 --- a/docs/testing/user/configguide/configguide.rst +++ b/docs/testing/user/configguide/configguide.rst @@ -336,6 +336,7 @@ should now be in place:: |-- parser |-- promise |-- rally + |-- refstack-client |-- releng |-- sdnvpn |-- securityscanning diff --git a/docs/testing/user/userguide/index.rst b/docs/testing/user/userguide/index.rst index e050cf14..c1faecda 100644 --- a/docs/testing/user/userguide/index.rst +++ b/docs/testing/user/userguide/index.rst @@ -247,13 +247,125 @@ The Rally testcases are distributed accross two Tiers: NOTE: Test case 'rally_sanity' executes a limited number of Rally smoke test cases. Test case 'rally_full' executes the full defined set of Rally tests. + +Refstack-client to run Defcore testcases +----------------------------------------- + +Refstack-client `[8]`_ is a command line utility that allows you to +execute Tempest test runs based on configurations you specify. +It is the official tool to run Defcore `[9]`_ testcases, +which focuses on testing interoperability between OpenStack clouds. + +Refstack-client is integrated in Functest, consumed by Dovetail, which +intends to define and provide a set of OPNFV related validation criteria +that will provide input for the evaluation of the use of OPNFV trademarks. +This progress is under the guideline of Compliance Verification Program(CVP). + +Defcore testcases +^^^^^^^^^^^^^^^^^^ + +*Danube Release* + +Set of DefCore tempest test cases not flagged and required. +According to `[10]`_, some tests are still flagged due to outstanding bugs +in the Tempest library, particularly tests that require SSH. Refstack developers +are working on correcting these bugs upstream. Please note that although some tests +are flagged because of bugs, there is still an expectation that the capabilities +covered by the tests are available. It only contains Openstack core compute +(no object storage). The approved guidelines (2016.08) are valid for Kilo, +Liberty, Mitaka and Newton releases of OpenStack. +The list can be generated using the Rest API from RefStack project: +https://refstack.openstack.org/api/v1/guidelines/2016.08/tests?target=compute&type=required&alias=true&flag=false + +Running methods +^^^^^^^^^^^^^^^ + +Two running methods are provided after refstack-client integrated into +Functest, Functest command line and manually, respectively. + +By default, for Defcore test cases run by Functest command line, +are run followed with automatically generated +configuration file, i.e., refstack_tempest.conf. In some circumstances, +the automatic configuration file may not quite satisfied with the SUT, +Functest also inherits the refstack-client command line and provides a way +for users to set its configuration file according to its own SUT manually. + +*command line* + +Inside the Functest container, first to prepare Functest environment: + +:: + + cd /home/opnfv/repos/functest + pip install -e . + functest env prepare + +then to run default defcore testcases by using refstack-client: + +:: + + functest testcase run refstack_defcore + +In OPNFV Continuous Integration(CI) system, the command line method is used. + +*manually* + +Inside the Functest container, first to prepare the refstack virtualenv: + +:: + + cd /home/opnfv/repos/refstack-client + source .venv/bin/activate + +then prepare the tempest configuration file and the testcases want to run with the SUT, +run the testcases with: + +:: + + ./refstack-client test -c <Path of the tempest configuration file to use> -v --test-list <Path or URL of test list> + +using help for more information: + +:: + + ./refstack-client --help + ./refstack-client test --help + +Reference tempest configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*command line method* + +When command line method is used, the default tempest configuration file +is generated by Rally. + +*manually* + +When running manually is used, recommended way to generate tempest configuration +file is: + +:: + + cd /home/opnfv/repos/functest/functest/opnfv_tests/openstack/refstack_client + python tempest_conf.py + +a file called tempest.conf is stored in the current path by default, users can do +some adjustment according to the SUT: + +:: + + vim refstack_tempest.conf + +a reference article can be used `[15]`_. + + snaps_smoke ------------ This test case contains tests that setup and destroy environments with VMs with and without Floating IPs with a newly created user and project. Set the config value snaps.use_floating_ips (True|False) to toggle this functionality. When -the config value of snaps.use_keystone is True, functest must have access +the config value of snaps.use_keystone is True, Functest must have access the cloud's private network. This suite consists in 38 tests (test duration < 10 minutes) @@ -362,7 +474,7 @@ The test cases are described as follows: Features -------- -In Danube, functest supports the integration of: +In Danube, Functest supports the integration of: * barometer * bgpvpn @@ -520,10 +632,14 @@ References .. _`[5]`: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater/blob/master/openstack-blueprint.yaml .. _`[6]`: https://scap.nist.gov/ .. _`[7]`: https://github.com/OpenSCAP/openscap +.. _`[8]`: https://github.com/openstack/refstack-client +.. _`[9]`: https://github.com/openstack/defcore +.. _`[10]`: https://github.com/openstack/interop/blob/master/2016.08/procedure.rst .. _`[11]`: http://robotframework.org/ .. _`[12]`: http://artifacts.opnfv.org/parser/colorado/docs/userguide/index.html .. _`[13]`: https://wiki.opnfv.org/display/PROJ/SNAPS-OO .. _`[14]`: https://github.com/oolorg/opnfv-functest-vrouter +.. _`[15]`: https://aptira.com/testing-openstack-tempest-part-1/ `OPNFV main site`_ diff --git a/functest/ci/check_os.sh b/functest/ci/check_os.sh index 83f9f476..ce0bc20c 100755 --- a/functest/ci/check_os.sh +++ b/functest/ci/check_os.sh @@ -86,30 +86,6 @@ if [ $RETVAL -ne 0 ]; then fi echo " ...OK" -adminURL=$(openstack catalog show identity |awk '/admin/ {print $4}') -if [ -z ${adminURL} ]; then - echo "ERROR: Cannot determine the admin URL." - openstack catalog show identity - exit 1 -fi -adminIP=$(echo $adminURL|sed 's/^.*http.*\:\/\///'|sed 's/.[^:]*$//') -adminPort=$(echo $adminURL|grep -Po '(?<=:)\d+') -https_enabled=$(echo $adminURL | grep 'https') -if [[ -n $https_enabled ]]; then - echo ">>Verifying SSL connectivity to the admin endpoint $adminIP:$adminPort..." - verify_SSL_connectivity $adminIP $adminPort -else - echo ">>Verifying connectivity to the admin endpoint $adminIP:$adminPort..." - verify_connectivity $adminIP $adminPort -fi -RETVAL=$? -if [ $RETVAL -ne 0 ]; then - echo "ERROR: Cannot talk to the admin endpoint $adminIP:$adminPort ." - echo "$adminURL" - exit 1 -fi -echo " ...OK" - echo "Checking Required OpenStack services:" for service in $MANDATORY_SERVICES; do diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml index 96dd6212..9b796071 100644 --- a/functest/ci/config_functest.yaml +++ b/functest/ci/config_functest.yaml @@ -34,10 +34,11 @@ general: functest: /home/opnfv/functest functest_test: /home/opnfv/repos/functest/functest/opnfv_tests results: /home/opnfv/functest/results - functest_logging_cfg: /home/opnfv/repos/functest/functest/ci/logging.json + functest_logging_cfg: /home/opnfv/repos/functest/functest/ci/logging.ini functest_conf: /home/opnfv/functest/conf functest_data: /home/opnfv/functest/data ims_data: /home/opnfv/functest/data/ims/ + functest_images: /home/opnfv/functest/images rally_inst: /home/opnfv/.rally repo_kingbird: /home/opnfv/repos/kingbird refstack_client: /home/opnfv/repos/refstack-client @@ -49,6 +50,8 @@ general: image_name: Cirros-0.3.5 image_name_alt: Cirros-0.3.5-1 image_file_name: cirros-0.3.5-x86_64-disk.img + image_url: http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img + image_user: cirros image_disk_format: qcow2 image_username: cirros image_password: cubswin:) @@ -71,14 +74,23 @@ general: functest: testcases_yaml: /home/opnfv/repos/functest/functest/ci/testcases.yaml -healthcheck: - disk_image: /home/opnfv/functest/data/cirros-0.3.5-x86_64-disk.img - disk_format: qcow2 - wait_time: 60 - snaps: use_keystone: True - use_floating_ips: False + use_floating_ips: True +# images: +# cirros: +# disk_url: http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img + # ARM +# disk_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img +# kernel_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-kernel +# ramdisk_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-initramfs +# extra_properties: +# os_command_line: root=/dev/vdb1 rw rootwait console=tty0 console=ttyS0 console=ttyAMA0 +# hw_video_model: vga +# ubuntu: +# disk_url: http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img +# centos: +# disk_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 vping: ping_timeout: 200 @@ -92,6 +104,14 @@ vping: router_name: vping-router sg_name: vPing-sg sg_desc: Security group for vPing test case + keypair_name: vPing-keypair + keypair_priv_file: /tmp/vPing-keypair + keypair_pub_file: /tmp/vPing-keypair.pub + vm_boot_timeout: 180 + vm_delete_timeout: 100 + vm_ssh_connect_timeout: 60 + cleanup_objects: True + unique_names: True onos_sfc: image_base_url: http://artifacts.opnfv.org/sfc/demo @@ -210,3 +230,8 @@ results: # you can also set a file (e.g. /home/opnfv/functest/results/dump.txt) to dump results # test_db_url: file:///home/opnfv/functest/results/dump.txt test_db_url: http://testresults.opnfv.org/test/api/v1/results + +energy_recorder: + api_url: http://161.105.253.100:8888/resources + api_user: "" + api_password: "" diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh new file mode 100644 index 00000000..f3fdef2e --- /dev/null +++ b/functest/ci/download_images.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +CIRROS_REPO_URL=http://download.cirros-cloud.net +CIRROS_AARCH64_TAG=161201 +CIRROS_X86_64_TAG=0.3.5 + +RED='\033[1;31m' +NC='\033[0m' # No Color + +function usage(){ + echo -e "${RED}USAGE: $script <destination_folder>${NC}" + exit 0 +} + +script=`basename "$0"` +IMAGES_FOLDER_DIR=$1 + +if [[ -z $IMAGES_FOLDER_DIR ]]; then usage; fi; + +set -ex +mkdir -p ${IMAGES_FOLDER_DIR} + +wget -nc ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-disk.img -P ${IMAGES_FOLDER_DIR} +wget -nc ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-lxc.tar.gz -P ${IMAGES_FOLDER_DIR} +wget -nc http://artifacts.opnfv.org/sdnvpn/ubuntu-16.04-server-cloudimg-amd64-disk1.img -P ${IMAGES_FOLDER_DIR} + +# Add 3rd-party images for aarch64, since Functest can be run on an x86 machine to test an aarch64 POD +wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-disk.img -P ${IMAGES_FOLDER_DIR} +wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-initramfs -P ${IMAGES_FOLDER_DIR} +wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-kernel -P ${IMAGES_FOLDER_DIR} +set +ex
\ No newline at end of file diff --git a/functest/ci/generate_report.py b/functest/ci/generate_report.py deleted file mode 100755 index 3872a07e..00000000 --- a/functest/ci/generate_report.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python -# -# 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 json -import re -import urllib2 - -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils -from functest.utils.constants import CONST - -COL_1_LEN = 25 -COL_2_LEN = 15 -COL_3_LEN = 12 -COL_4_LEN = 15 -COL_5_LEN = 75 - -# If we run from CI (Jenkins) we will push the results to the DB -# and then we can print the url to the specific test result - - -logger = ft_logger.Logger("generate_report").getLogger() - - -def init(tiers_to_run=[]): - test_cases_arr = [] - for tier in tiers_to_run: - for test in tier.get_tests(): - test_cases_arr.append({'test_name': test.get_name(), - 'tier_name': tier.get_name(), - 'result': 'Not executed', - 'duration': '0', - 'url': ''}) - return test_cases_arr - - -def get_results_from_db(): - url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(), - CONST.BUILD_TAG) - logger.debug("Query to rest api: %s" % url) - try: - data = json.load(urllib2.urlopen(url)) - return data['results'] - except: - logger.error("Cannot read content from the url: %s" % url) - return None - - -def get_data(test, results): - test_result = test['result'] - url = '' - for test_db in results: - if test['test_name'] in test_db['case_name']: - id = test_db['_id'] - url = ft_utils.get_db_url() + '/results/' + id - test_result = test_db['criteria'] - - return {"url": url, "result": test_result} - - -def print_line(w1, w2='', w3='', w4='', w5=''): - str = ('| ' + w1.ljust(COL_1_LEN - 1) + - '| ' + w2.ljust(COL_2_LEN - 1) + - '| ' + w3.ljust(COL_3_LEN - 1) + - '| ' + w4.ljust(COL_4_LEN - 1)) - if CONST.IS_CI_RUN: - str += ('| ' + w5.ljust(COL_5_LEN - 1)) - str += '|\n' - return str - - -def print_line_no_columns(str): - TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN + 2 - if CONST.IS_CI_RUN: - TOTAL_LEN += COL_5_LEN + 1 - return ('| ' + str.ljust(TOTAL_LEN) + "|\n") - - -def print_separator(char="=", delimiter="+"): - str = ("+" + char * COL_1_LEN + - delimiter + char * COL_2_LEN + - delimiter + char * COL_3_LEN + - delimiter + char * COL_4_LEN) - if CONST.IS_CI_RUN: - str += (delimiter + char * COL_5_LEN) - str += '+\n' - return str - - -def main(args=[]): - executed_test_cases = args - - if CONST.IS_CI_RUN: - results = get_results_from_db() - if results is not None: - for test in executed_test_cases: - data = get_data(test, results) - test.update({"url": data['url'], - "result": data['result']}) - - TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN - if CONST.IS_CI_RUN: - TOTAL_LEN += COL_5_LEN - MID = TOTAL_LEN / 2 - - if CONST.BUILD_TAG is not None: - if re.search("daily", CONST.BUILD_TAG) is not None: - CONST.CI_LOOP = "daily" - else: - CONST.CI_LOOP = "weekly" - - str = '' - str += print_separator('=', delimiter="=") - str += print_line_no_columns(' ' * (MID - 8) + 'FUNCTEST REPORT') - str += print_separator('=', delimiter="=") - str += print_line_no_columns(' ') - str += print_line_no_columns(" Deployment description:") - str += print_line_no_columns(" INSTALLER: %s" - % CONST.INSTALLER_TYPE) - if CONST.DEPLOY_SCENARIO is not None: - str += print_line_no_columns(" SCENARIO: %s" - % CONST.DEPLOY_SCENARIO) - if CONST.BUILD_TAG is not None: - str += print_line_no_columns(" BUILD TAG: %s" - % CONST.BUILD_TAG) - if CONST.CI_LOOP is not None: - str += print_line_no_columns(" CI LOOP: %s" - % CONST.CI_LOOP) - str += print_line_no_columns(' ') - str += print_separator('=') - if CONST.IS_CI_RUN: - str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT', 'URL') - else: - str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT') - str += print_separator('=') - for test in executed_test_cases: - str += print_line(test['test_name'], - test['tier_name'], - test['duration'], - test['result'], - test['url']) - str += print_separator('-') - - logger.info("\n\n\n%s" % str) - - -if __name__ == '__main__': - import sys - main(sys.argv[1:]) diff --git a/functest/ci/logging.ini b/functest/ci/logging.ini new file mode 100644 index 00000000..210c8f5f --- /dev/null +++ b/functest/ci/logging.ini @@ -0,0 +1,75 @@ +[loggers] +keys=root,functest,ci,cli,core,energy,opnfv_tests,utils + +[handlers] +keys=console,wconsole,file,null + +[formatters] +keys=standard + +[logger_root] +level=NOTSET +handlers=null + +[logger_functest] +level=NOTSET +handlers=file +qualname=functest + +[logger_ci] +level=NOTSET +handlers=console +qualname=functest.ci + +[logger_cli] +level=NOTSET +handlers=wconsole +qualname=functest.cli + +[logger_core] +level=NOTSET +handlers=console +qualname=functest.core + +[logger_energy] +level=NOTSET +handlers=wconsole +qualname=functest.energy + +[logger_opnfv_tests] +level=NOTSET +handlers=wconsole +qualname=functest.opnfv_tests + +[logger_utils] +level=NOTSET +handlers=wconsole +qualname=functest.utils + +[handler_null] +class=NullHandler +level=NOTSET +formatter=standard +args=() + +[handler_console] +class=StreamHandler +level=INFO +formatter=standard +args=(sys.stdout,) + +[handler_wconsole] +class=StreamHandler +level=WARN +formatter=standard +args=(sys.stdout,) + +[handler_file] +class=FileHandler +level=DEBUG +formatter=standard +args=("/home/opnfv/functest/results/functest.log",) + +[formatter_standard] +format=%(asctime)s - %(name)s - %(levelname)s - %(message)s +datefmt= diff --git a/functest/ci/logging.json b/functest/ci/logging.json deleted file mode 100644 index 2a2399d3..00000000 --- a/functest/ci/logging.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "version": 1, - "disable_existing_loggers": false, - "formatters": { - "standard": { - "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - } - }, - "handlers": { - "console": { - "level": "INFO", - "class": "logging.StreamHandler", - "formatter": "standard" - }, - "file": { - "level": "DEBUG", - "class": "logging.FileHandler", - "formatter": "standard", - "filename": "/home/opnfv/functest/results/functest.log" - } - }, - "loggers": { - "": { - "handlers": ["console", "file"], - "level": "DEBUG", - "propagate": "yes" - } - } -} diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py index e9a470f9..8e17a4fc 100755 --- a/functest/ci/prepare_env.py +++ b/functest/ci/prepare_env.py @@ -8,6 +8,8 @@ import argparse import json +import logging +import logging.config import os import re import subprocess @@ -16,7 +18,6 @@ import fileinput import yaml -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST @@ -27,13 +28,13 @@ from opnfv.deployment import factory actions = ['start', 'check'] """ logging configuration """ -logger = ft_logger.Logger("prepare_env").getLogger() +logger = logging.getLogger('functest.ci.prepare_env') handler = None # set the architecture to default pod_arch = None arch_filter = ['aarch64'] -CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML +CONFIG_FUNCTEST_PATH = CONST.__getattribute__('CONFIG_FUNCTEST_YAML') CONFIG_PATCH_PATH = os.path.join(os.path.dirname( CONFIG_FUNCTEST_PATH), "config_patch.yaml") CONFIG_AARCH64_PATCH_PATH = os.path.join(os.path.dirname( @@ -65,63 +66,70 @@ def check_env_variables(): print_separator() logger.info("Checking environment variables...") - if CONST.INSTALLER_TYPE is None: + if CONST.__getattribute__('INSTALLER_TYPE') is None: logger.warning("The env variable 'INSTALLER_TYPE' is not defined.") - CONST.INSTALLER_TYPE = "undefined" + CONST.__setattr__('INSTALLER_TYPE', 'undefined') else: - if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS: + if (CONST.__getattribute__('INSTALLER_TYPE') not in + opnfv_constants.INSTALLERS): logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. " "Available OPNFV Installers are : %s. " "Setting INSTALLER_TYPE=undefined." - % (CONST.INSTALLER_TYPE, + % (CONST.__getattribute__('INSTALLER_TYPE'), opnfv_constants.INSTALLERS)) - CONST.INSTALLER_TYPE = "undefined" + CONST.__setattr__('INSTALLER_TYPE', 'undefined') else: logger.info(" INSTALLER_TYPE=%s" - % CONST.INSTALLER_TYPE) + % CONST.__getattribute__('INSTALLER_TYPE')) - if CONST.INSTALLER_IP is None: + if CONST.__getattribute__('INSTALLER_IP') is None: logger.warning("The env variable 'INSTALLER_IP' is not defined. " "It is needed to fetch the OpenStack credentials. " "If the credentials are not provided to the " "container as a volume, please add this env variable " "to the 'docker run' command.") else: - logger.info(" INSTALLER_IP=%s" % CONST.INSTALLER_IP) + logger.info(" INSTALLER_IP=%s" % + CONST.__getattribute__('INSTALLER_IP')) - if CONST.DEPLOY_SCENARIO is None: + if CONST.__getattribute__('DEPLOY_SCENARIO') is None: logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. " "Setting CI_SCENARIO=undefined.") - CONST.DEPLOY_SCENARIO = "undefined" + CONST.__setattr__('DEPLOY_SCENARIO', 'undefined') else: - logger.info(" DEPLOY_SCENARIO=%s" % CONST.DEPLOY_SCENARIO) - if CONST.CI_DEBUG: - logger.info(" CI_DEBUG=%s" % CONST.CI_DEBUG) + logger.info(" DEPLOY_SCENARIO=%s" + % CONST.__getattribute__('DEPLOY_SCENARIO')) + if CONST.__getattribute__('CI_DEBUG'): + logger.info(" CI_DEBUG=%s" % CONST.__getattribute__('CI_DEBUG')) - if CONST.NODE_NAME: - logger.info(" NODE_NAME=%s" % CONST.NODE_NAME) + if CONST.__getattribute__('NODE_NAME'): + logger.info(" NODE_NAME=%s" % CONST.__getattribute__('NODE_NAME')) - if CONST.BUILD_TAG: - logger.info(" BUILD_TAG=%s" % CONST.BUILD_TAG) + if CONST.__getattribute__('BUILD_TAG'): + logger.info(" BUILD_TAG=%s" % CONST.__getattribute__('BUILD_TAG')) - if CONST.IS_CI_RUN: - logger.info(" IS_CI_RUN=%s" % CONST.IS_CI_RUN) + if CONST.__getattribute__('IS_CI_RUN'): + logger.info(" IS_CI_RUN=%s" % CONST.__getattribute__('IS_CI_RUN')) def get_deployment_handler(): global handler global pod_arch - installer_params_yaml = os.path.join(CONST.dir_repo_functest, - 'functest/ci/installer_params.yaml') - if (CONST.INSTALLER_IP and CONST.INSTALLER_TYPE and - CONST.INSTALLER_TYPE in opnfv_constants.INSTALLERS): + installer_params_yaml = os.path.join( + CONST.__getattribute__('dir_repo_functest'), + 'functest/ci/installer_params.yaml') + if (CONST.__getattribute__('INSTALLER_IP') and + CONST.__getattribute__('INSTALLER_TYPE') and + CONST.__getattribute__('INSTALLER_TYPE') in + opnfv_constants.INSTALLERS): try: installer_params = ft_utils.get_parameter_from_yaml( - CONST.INSTALLER_TYPE, installer_params_yaml) + CONST.__getattribute__('INSTALLER_TYPE'), + installer_params_yaml) except ValueError as e: logger.debug('Printing deployment info is not supported for %s' % - CONST.INSTALLER_TYPE) + CONST.__getattribute__('INSTALLER_TYPE')) logger.debug(e) else: user = installer_params.get('user', None) @@ -129,8 +137,8 @@ def get_deployment_handler(): pkey = installer_params.get('pkey', None) try: handler = factory.Factory.get_handler( - installer=CONST.INSTALLER_TYPE, - installer_ip=CONST.INSTALLER_IP, + installer=CONST.__getattribute__('INSTALLER_TYPE'), + installer_ip=CONST.__getattribute__('INSTALLER_IP'), installer_user=user, installer_pwd=password, pkey_file=pkey) @@ -143,51 +151,62 @@ def get_deployment_handler(): def create_directories(): print_separator() logger.info("Creating needed directories...") - if not os.path.exists(CONST.dir_functest_conf): - os.makedirs(CONST.dir_functest_conf) - logger.info(" %s created." % CONST.dir_functest_conf) + if not os.path.exists(CONST.__getattribute__('dir_functest_conf')): + os.makedirs(CONST.__getattribute__('dir_functest_conf')) + logger.info(" %s created." % + CONST.__getattribute__('dir_functest_conf')) else: - logger.debug(" %s already exists." - % CONST.dir_functest_conf) + logger.debug(" %s already exists." % + CONST.__getattribute__('dir_functest_conf')) - if not os.path.exists(CONST.dir_functest_data): - os.makedirs(CONST.dir_functest_data) - logger.info(" %s created." % CONST.dir_functest_data) + if not os.path.exists(CONST.__getattribute__('dir_functest_data')): + os.makedirs(CONST.__getattribute__('dir_functest_data')) + logger.info(" %s created." % + CONST.__getattribute__('dir_functest_data')) else: - logger.debug(" %s already exists." - % CONST.dir_functest_data) + logger.debug(" %s already exists." % + CONST.__getattribute__('dir_functest_data')) + if not os.path.exists(CONST.__getattribute__('dir_functest_images')): + os.makedirs(CONST.__getattribute__('dir_functest_images')) + logger.info(" %s created." % + CONST.__getattribute__('dir_functest_images')) + else: + logger.debug(" %s already exists." % + CONST.__getattribute__('dir_functest_images')) def source_rc_file(): print_separator() logger.info("Fetching RC file...") - if CONST.openstack_creds is None: + if CONST.__getattribute__('openstack_creds') is None: logger.warning("The environment variable 'creds' must be set and" "pointing to the local RC file. Using default: " "/home/opnfv/functest/conf/openstack.creds ...") - os.path.join(CONST.dir_functest_conf, 'openstack.creds') + os.path.join( + CONST.__getattribute__('dir_functest_conf'), 'openstack.creds') - if not os.path.isfile(CONST.openstack_creds): + if not os.path.isfile(CONST.__getattribute__('openstack_creds')): logger.info("RC file not provided. " "Fetching it from the installer...") - if CONST.INSTALLER_IP is None: - logger.error("The env variable CI_INSTALLER_IP must be provided in" + if CONST.__getattribute__('INSTALLER_IP')is None: + logger.error("The env variable 'INSTALLER_IP' must be provided in" " order to fetch the credentials from the installer.") raise Exception("Missing CI_INSTALLER_IP.") - if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS: + if (CONST.__getattribute__('INSTALLER_TYPE') not in + opnfv_constants.INSTALLERS): logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is " "not a valid OPNFV installer. Available " "installers are : %s." % - (CONST.INSTALLER_TYPE, + (CONST.__getattribute__('INSTALLER_TYPE'), opnfv_constants.INSTALLERS)) raise Exception("Wrong INSTALLER_TYPE.") cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh " "-d %s -i %s -a %s" - % (CONST.openstack_creds, - CONST.INSTALLER_TYPE, - CONST.INSTALLER_IP)) + % (CONST.__getattribute__('openstack_creds'), + CONST.__getattribute__('INSTALLER_TYPE'), + CONST.__getattribute__('INSTALLER_IP'))) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) output = p.communicate()[0] @@ -196,22 +215,23 @@ def source_rc_file(): raise Exception("Failed to fetch credentials from installer.") else: logger.info("RC file provided in %s." - % CONST.openstack_creds) - if os.path.getsize(CONST.openstack_creds) == 0: - raise Exception("The file %s is empty." % CONST.openstack_creds) + % CONST.__getattribute__('openstack_creds')) + if os.path.getsize(CONST.__getattribute__('openstack_creds')) == 0: + raise Exception("The file %s is empty." % + CONST.__getattribute__('openstack_creds')) logger.info("Sourcing the OpenStack RC file...") - os_utils.source_credentials(CONST.openstack_creds) + os_utils.source_credentials(CONST.__getattribute__('openstack_creds')) for key, value in os.environ.iteritems(): if re.search("OS_", key): if key == 'OS_AUTH_URL': - CONST.OS_AUTH_URL = value + CONST.__setattr__('OS_AUTH_URL', value) elif key == 'OS_USERNAME': - CONST.OS_USERNAME = value + CONST.__setattr__('OS_USERNAME', value) elif key == 'OS_TENANT_NAME': - CONST.OS_TENANT_NAME = value + CONST.__setattr__('OS_TENANT_NAME', value) elif key == 'OS_PASSWORD': - CONST.OS_PASSWORD = value + CONST.__setattr__('OS_PASSWORD', value) def patch_config_file(): @@ -228,7 +248,7 @@ def patch_file(patch_file_path): updated = False for key in patch_file: - if key in CONST.DEPLOY_SCENARIO: + if key in CONST.__getattribute__('DEPLOY_SCENARIO'): new_functest_yaml = dict(ft_utils.merge_dicts( ft_utils.get_functest_yaml(), patch_file[key])) updated = True @@ -243,7 +263,8 @@ def patch_file(patch_file_path): def verify_deployment(): print_separator() logger.info("Verifying OpenStack services...") - cmd = ("%s/functest/ci/check_os.sh" % CONST.dir_repo_functest) + cmd = ("%s/functest/ci/check_os.sh" % + CONST.__getattribute__('dir_repo_functest')) logger.debug("Executing command: %s" % cmd) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) @@ -274,7 +295,7 @@ def install_rally(): cmd = "rally deployment destroy opnfv-rally" ft_utils.execute_command(cmd, error_msg=( "Deployment %s does not exist." - % CONST.rally_deployment_name), + % CONST.__getattribute__('rally_deployment_name')), verbose=False) rally_conf = os_utils.get_credentials_for_rally() @@ -282,7 +303,7 @@ def install_rally(): json.dump(rally_conf, fp) cmd = ("rally deployment create " "--file=rally_conf.json --name={0}" - .format(CONST.rally_deployment_name)) + .format(CONST.__getattribute__('rally_deployment_name'))) error_msg = "Problem while creating Rally deployment" ft_utils.execute_command_raise(cmd, error_msg=error_msg) @@ -304,17 +325,18 @@ def install_rally(): def install_tempest(): logger.info("Installing tempest from existing repo...") cmd = ("rally verify list-verifiers | " - "grep '{0}' | wc -l".format(CONST.tempest_deployment_name)) + "grep '{0}' | wc -l".format( + CONST.__getattribute__('tempest_deployment_name'))) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) while p.poll() is None: line = p.stdout.readline().rstrip() if str(line) == '0': logger.debug("Tempest %s does not exist" % - CONST.tempest_deployment_name) + CONST.__getattribute__('tempest_deployment_name')) cmd = ("rally verify create-verifier --source {0} " "--name {1} --type tempest --system-wide" - .format(CONST.dir_repo_tempest, - CONST.tempest_deployment_name)) + .format(CONST.__getattribute__('dir_repo_tempest'), + CONST.__getattribute__('tempest_deployment_name'))) error_msg = "Problem while installing Tempest." ft_utils.execute_command_raise(cmd, error_msg=error_msg) @@ -331,10 +353,10 @@ def create_flavor(): def check_environment(): msg_not_active = "The Functest environment is not installed." - if not os.path.isfile(CONST.env_active): + if not os.path.isfile(CONST.__getattribute__('env_active')): raise Exception(msg_not_active) - with open(CONST.env_active, "r") as env_file: + with open(CONST.__getattribute__('env_active'), "r") as env_file: s = env_file.read() if not re.search("1", s): raise Exception(msg_not_active) @@ -364,7 +386,7 @@ def main(**kwargs): install_rally() install_tempest() create_flavor() - with open(CONST.env_active, "w") as env_file: + with open(CONST.__getattribute__('env_active'), "w") as env_file: env_file.write("1") check_environment() print_deployment_info() @@ -377,6 +399,8 @@ def main(**kwargs): if __name__ == '__main__': + logging.config.fileConfig( + CONST.__getattribute__('dir_functest_logging_cfg')) parser = PrepareEnvParser() args = parser.parse_args(sys.argv[1:]) sys.exit(main(**args)) diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py index e68901b8..76760096 100755 --- a/functest/ci/run_tests.py +++ b/functest/ci/run_tests.py @@ -9,26 +9,26 @@ # import argparse -import datetime import enum import importlib +import logging +import logging.config import os import re import sys -import functest.ci.generate_report as generate_report +import prettytable + import functest.ci.tier_builder as tb import functest.core.testcase as testcase -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_clean as os_clean import functest.utils.openstack_snapshot as os_snapshot import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST - -""" logging configuration """ -logger = ft_logger.Logger("run_tests").getLogger() +# __name__ cannot be used here +logger = logging.getLogger('functest.ci.run_tests') class Result(enum.Enum): @@ -40,6 +40,10 @@ class BlockingTestFailed(Exception): pass +class TestNotEnabled(Exception): + pass + + class RunTestsParser(object): def __init__(self): @@ -75,7 +79,7 @@ def print_separator(str, count=45): def source_rc_file(): - rc_file = CONST.openstack_creds + rc_file = CONST.__getattribute__('openstack_creds') if not os.path.isfile(rc_file): raise Exception("RC file %s does not exist..." % rc_file) logger.debug("Sourcing the OpenStack RC file...") @@ -83,13 +87,13 @@ def source_rc_file(): for key, value in os.environ.iteritems(): if re.search("OS_", key): if key == 'OS_AUTH_URL': - CONST.OS_AUTH_URL = value + CONST.__setattr__('OS_AUTH_URL', value) elif key == 'OS_USERNAME': - CONST.OS_USERNAME = value + CONST.__setattr__('OS_USERNAME', value) elif key == 'OS_TENANT_NAME': - CONST.OS_TENANT_NAME = value + CONST.__setattr__('OS_TENANT_NAME', value) elif key == 'OS_PASSWORD': - CONST.OS_PASSWORD = value + CONST.__setattr__('OS_PASSWORD', value) def generate_os_snapshot(): @@ -100,13 +104,6 @@ def cleanup(): os_clean.main() -def update_test_info(test_name, result, duration): - for test in GlobalVariables.EXECUTED_TEST_CASES: - if test['test_name'] == test_name: - test.update({"result": result, - "duration": duration}) - - def get_run_dict(testname): try: dict = ft_utils.get_dict_by_test(testname) @@ -121,8 +118,9 @@ def get_run_dict(testname): def run_test(test, tier_name, testcases=None): - result_str = "PASS" - start = datetime.datetime.now() + if not test.is_enabled(): + raise TestNotEnabled("The test case {} is not enabled" + .format(test.get_name())) test_name = test.get_name() logger.info("\n") # blank line print_separator("=") @@ -146,7 +144,7 @@ def run_test(test, tier_name, testcases=None): cls = getattr(module, run_dict['class']) test_dict = ft_utils.get_dict_by_test(test_name) test_case = cls(**test_dict) - + GlobalVariables.EXECUTED_TEST_CASES.append(test_case) try: kwargs = run_dict['args'] result = test_case.run(**kwargs) @@ -155,7 +153,8 @@ def run_test(test, tier_name, testcases=None): if result == testcase.TestCase.EX_OK: if GlobalVariables.REPORT_FLAG: test_case.push_to_db() - result = test_case.check_result() + result = test_case.is_successful() + logger.info("Test result:\n\n%s\n", test_case) except ImportError: logger.exception("Cannot import module {}".format( run_dict['module'])) @@ -167,27 +166,13 @@ def run_test(test, tier_name, testcases=None): if test.needs_clean() and GlobalVariables.CLEAN_FLAG: cleanup() - - end = datetime.datetime.now() - duration = (end - start).seconds - duration_str = ("%02d:%02d" % divmod(duration, 60)) - logger.info("Test execution time: %s" % duration_str) - - if result != 0: + if result != testcase.TestCase.EX_OK: logger.error("The test case '%s' failed. " % test_name) GlobalVariables.OVERALL_RESULT = Result.EX_ERROR - result_str = "FAIL" - if test.is_blocking(): - if not testcases or testcases == "all": - # if it is a single test we don't print the whole results table - update_test_info(test_name, result_str, duration_str) - generate_report.main(GlobalVariables.EXECUTED_TEST_CASES) raise BlockingTestFailed("The test case {} failed and is blocking" .format(test.get_name())) - update_test_info(test_name, result_str, duration_str) - def run_tier(tier): tier_name = tier.get_name() @@ -211,27 +196,24 @@ def run_all(tiers): for tier in tiers.get_tiers(): if (len(tier.get_tests()) != 0 and - re.search(CONST.CI_LOOP, tier.get_ci_loop()) is not None): + re.search(CONST.__getattribute__('CI_LOOP'), + tier.get_ci_loop()) is not None): tiers_to_run.append(tier) summary += ("\n - %s:\n\t %s" % (tier.get_name(), tier.get_test_names())) logger.info("Tests to be executed:%s" % summary) - GlobalVariables.EXECUTED_TEST_CASES = generate_report.init(tiers_to_run) for tier in tiers_to_run: run_tier(tier) - generate_report.main(GlobalVariables.EXECUTED_TEST_CASES) - def main(**kwargs): - CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE - CI_SCENARIO = CONST.DEPLOY_SCENARIO - file = CONST.functest_testcases_yaml - _tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, file) + _tiers = tb.TierBuilder(CONST.__getattribute__('INSTALLER_TYPE'), + CONST.__getattribute__('DEPLOY_SCENARIO'), + file) if kwargs['noclean']: GlobalVariables.CLEAN_FLAG = False @@ -243,12 +225,10 @@ def main(**kwargs): if kwargs['test']: source_rc_file() if _tiers.get_tier(kwargs['test']): - GlobalVariables.EXECUTED_TEST_CASES = generate_report.init( - [_tiers.get_tier(kwargs['test'])]) run_tier(_tiers.get_tier(kwargs['test'])) elif _tiers.get_test(kwargs['test']): run_test(_tiers.get_test(kwargs['test']), - _tiers.get_tier(kwargs['test']), + _tiers.get_tier_name(kwargs['test']), kwargs['test']) elif kwargs['test'] == "all": run_all(_tiers) @@ -256,7 +236,8 @@ def main(**kwargs): logger.error("Unknown test case or tier '%s', " "or not supported by " "the given scenario '%s'." - % (kwargs['test'], CI_SCENARIO)) + % (kwargs['test'], + CONST.__getattribute__('DEPLOY_SCENARIO'))) logger.debug("Available tiers are:\n\n%s" % _tiers) return Result.EX_ERROR @@ -265,11 +246,33 @@ def main(**kwargs): except Exception as e: logger.error(e) GlobalVariables.OVERALL_RESULT = Result.EX_ERROR + + msg = prettytable.PrettyTable( + header_style='upper', padding_width=5, + field_names=['env var', 'value']) + for env_var in ['INSTALLER_TYPE', 'DEPLOY_SCENARIO', 'BUILD_TAG', + 'CI_LOOP']: + msg.add_row([env_var, CONST.__getattribute__(env_var)]) + logger.info("Deployment description: \n\n%s\n", msg) + + msg = prettytable.PrettyTable( + header_style='upper', padding_width=5, + field_names=['test case', 'project', 'tier', 'duration', 'result']) + for test_case in GlobalVariables.EXECUTED_TEST_CASES: + result = 'PASS' if(test_case.is_successful( + ) == test_case.EX_OK) else 'FAIL' + msg.add_row([test_case.case_name, test_case.project_name, + _tiers.get_tier_name(test_case.case_name), + test_case.get_duration(), result]) + logger.info("FUNCTEST REPORT: \n\n%s\n", msg) + logger.info("Execution exit value: %s" % GlobalVariables.OVERALL_RESULT) return GlobalVariables.OVERALL_RESULT if __name__ == '__main__': + logging.config.fileConfig( + CONST.__getattribute__('dir_functest_logging_cfg')) parser = RunTestsParser() args = parser.parse_args(sys.argv[1:]) sys.exit(main(**args).value) diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index 7009e910..d98a2de2 100644 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -19,7 +19,6 @@ tiers: simple queries. When the config value of snaps.use_keystone is True, functest must have access to the cloud's private network. - dependencies: installer: '^((?!netvirt).)*$' scenario: '' @@ -39,13 +38,13 @@ tiers: simple queries. When the config value of snaps.use_keystone is True, functest must have access to the cloud's private network. - dependencies: installer: '^((?!netvirt).)*$' scenario: '' run: module: 'functest.opnfv_tests.openstack.snaps.api_check' class: 'ApiCheck' + - case_name: snaps_health_check project_name: functest @@ -63,6 +62,7 @@ tiers: run: module: 'functest.opnfv_tests.openstack.snaps.health_check' class: 'HealthCheck' + - name: smoke order: 1 @@ -266,6 +266,7 @@ tiers: testcases: - case_name: promise + enabled: false project_name: promise criteria: 100 blocking: false @@ -283,6 +284,7 @@ tiers: - case_name: doctor-notification + enabled: false project_name: doctor criteria: 100 blocking: false @@ -300,6 +302,7 @@ tiers: - case_name: bgpvpn + enabled: false project_name: sdnvpn criteria: 100 blocking: false @@ -317,6 +320,7 @@ tiers: - case_name: security_scan + enabled: false project_name: securityscanning criteria: 100 blocking: false @@ -334,6 +338,7 @@ tiers: - case_name: copper + enabled: false project_name: copper criteria: 100 blocking: false @@ -351,6 +356,7 @@ tiers: - case_name: multisite + enabled: false project_name: multisite criteria: 100 blocking: false @@ -363,8 +369,10 @@ tiers: run: module: 'functest.opnfv_tests.openstack.tempest.tempest' class: 'TempestMultisite' + - case_name: functest-odl-sfc + enabled: false project_name: sfc criteria: 100 blocking: false @@ -379,8 +387,10 @@ tiers: class: 'BashFeature' args: cmd: 'cd /home/opnfv/repos/sfc/sfc/tests/functest && python ./run_tests.py' + - case_name: onos_sfc + enabled: false project_name: functest criteria: 100 blocking: true @@ -393,8 +403,10 @@ tiers: run: module: 'functest.opnfv_tests.sdn.onos.onos' class: 'OnosSfc' + - case_name: parser-basics + enabled: false project_name: parser criteria: 100 blocking: false @@ -409,8 +421,10 @@ tiers: class: 'BashFeature' args: cmd: 'cd /home/opnfv/repos/parser/tests && ./functest_run.sh' + - case_name: domino-multinode + enabled: false project_name: domino criteria: 100 blocking: false @@ -425,8 +439,10 @@ tiers: class: 'BashFeature' args: cmd: 'cd /home/opnfv/repos/domino && ./tests/run_multinode.sh' + - case_name: gluon_vping + enabled: false project_name: netready criteria: 100 blocking: false @@ -441,8 +457,10 @@ tiers: class: 'BashFeature' args: cmd: 'cd /home/opnfv/repos/netready/test/functest && python ./gluon-test-suite.py' + - case_name: barometercollectd + enabled: false project_name: barometer criteria: 100 blocking: false @@ -458,6 +476,7 @@ tiers: run: module: 'functest.opnfv_tests.features.barometer' class: 'BarometerCollectd' + - name: components order: 3 @@ -481,6 +500,7 @@ tiers: run: module: 'functest.opnfv_tests.openstack.tempest.tempest' class: 'TempestFullParallel' + - case_name: tempest_custom project_name: functest @@ -499,6 +519,7 @@ tiers: run: module: 'functest.opnfv_tests.openstack.tempest.tempest' class: 'TempestCustom' + - case_name: rally_full project_name: functest @@ -537,22 +558,26 @@ tiers: run: module: 'functest.opnfv_tests.vnf.ims.cloudify_ims' class: 'CloudifyIms' -# - -# case_name: aaa -# project_name: functest -# criteria: 100 -# blocking: false -# clean_flag: true -# description: >- -# Test suite from Parser project. -# dependencies: -# installer: '' -# scenario: '' -# run: -# module: 'functest.opnfv_tests.vnf.aaa.aaa' -# class: 'AaaVnf' + + - + case_name: aaa + enabled: false + project_name: functest + criteria: 100 + blocking: false + clean_flag: true + description: >- + Test suite from Parser project. + dependencies: + installer: '' + scenario: '' + run: + module: 'functest.opnfv_tests.vnf.aaa.aaa' + class: 'AaaVnf' + - case_name: orchestra_ims + enabled: false project_name: functest criteria: 100 blocking: false @@ -568,6 +593,7 @@ tiers: - case_name: opera_vims + enabled: false project_name: opera criteria: 100 blocking: false @@ -583,6 +609,7 @@ tiers: - case_name: vyos_vrouter + enabled: false project_name: functest criteria: 100 blocking: false diff --git a/functest/ci/tier_builder.py b/functest/ci/tier_builder.py index 44b27258..12562f09 100644 --- a/functest/ci/tier_builder.py +++ b/functest/ci/tier_builder.py @@ -47,12 +47,15 @@ class TierBuilder(object): dep = th.Dependency(installer, scenario) testcase = th.TestCase(name=dic_testcase['case_name'], + enabled=dic_testcase.get( + 'enabled', True), dependency=dep, criteria=dic_testcase['criteria'], blocking=dic_testcase['blocking'], clean_flag=dic_testcase['clean_flag'], description=dic_testcase['description']) - if testcase.is_compatible(self.ci_installer, self.ci_scenario): + if (testcase.is_compatible(self.ci_installer, self.ci_scenario) + and testcase.is_enabled()): tier.add_test(testcase) self.tier_objects.append(tier) @@ -72,6 +75,12 @@ class TierBuilder(object): return self.tier_objects[i] return None + def get_tier_name(self, test_name): + for i in range(0, len(self.tier_objects)): + if self.tier_objects[i].is_test(test_name): + return self.tier_objects[i].name + return None + def get_test(self, test_name): for i in range(0, len(self.tier_objects)): if self.tier_objects[i].is_test(test_name): diff --git a/functest/ci/tier_handler.py b/functest/ci/tier_handler.py index fe7372a3..36ce245e 100644 --- a/functest/ci/tier_handler.py +++ b/functest/ci/tier_handler.py @@ -105,12 +105,14 @@ class Tier(object): class TestCase(object): def __init__(self, name, + enabled, dependency, criteria, blocking, clean_flag, description=""): self.name = name + self.enabled = enabled self.dependency = dependency self.criteria = criteria self.blocking = blocking @@ -138,6 +140,9 @@ class TestCase(object): def get_name(self): return self.name + def is_enabled(self): + return self.enabled + def get_criteria(self): return self.criteria diff --git a/functest/cli/cli_base.py b/functest/cli/cli_base.py index cc697ed7..2104e125 100644 --- a/functest/cli/cli_base.py +++ b/functest/cli/cli_base.py @@ -8,11 +8,14 @@ # import click +import logging.config from functest.cli.commands.cli_env import CliEnv from functest.cli.commands.cli_os import CliOpenStack from functest.cli.commands.cli_testcase import CliTestcase from functest.cli.commands.cli_tier import CliTier +from functest.utils.constants import CONST + CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @@ -20,7 +23,8 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help']) @click.group(context_settings=CONTEXT_SETTINGS) @click.version_option(version='opnfv colorado.0.1 ') def cli(): - pass + logging.config.fileConfig( + CONST.__getattribute__('dir_functest_logging_cfg')) _env = CliEnv() diff --git a/functest/cli/commands/cli_env.py b/functest/cli/commands/cli_env.py index 14ad01bf..f5ba4b34 100644 --- a/functest/cli/commands/cli_env.py +++ b/functest/cli/commands/cli_env.py @@ -28,7 +28,7 @@ class CliEnv(object): "it again? [y|n]\n") while True: if answer.lower() in ["y", "yes"]: - os.remove(CONST.env_active) + os.remove(CONST.__getattribute__('env_active')) break elif answer.lower() in ["n", "no"]: return @@ -36,19 +36,19 @@ class CliEnv(object): answer = raw_input("Invalid answer. Please type [y|n]\n") cmd = ("python %s/functest/ci/prepare_env.py start" % - CONST.dir_repo_functest) + CONST.__getattribute__('dir_repo_functest')) ft_utils.execute_command(cmd) def show(self): def _get_value(attr, default='Unknown'): return attr if attr else default - install_type = _get_value(CONST.INSTALLER_TYPE) - installer_ip = _get_value(CONST.INSTALLER_IP) + install_type = _get_value(CONST.__getattribute__('INSTALLER_TYPE')) + installer_ip = _get_value(CONST.__getattribute__('INSTALLER_IP')) installer_info = ("%s, %s" % (install_type, installer_ip)) - scenario = _get_value(CONST.DEPLOY_SCENARIO) - node = _get_value(CONST.NODE_NAME) - repo_h = git.Repo(CONST.dir_repo_functest).head + scenario = _get_value(CONST.__getattribute__('DEPLOY_SCENARIO')) + node = _get_value(CONST.__getattribute__('NODE_NAME')) + repo_h = git.Repo(CONST.__getattribute__('dir_repo_functest')).head if repo_h.is_detached: git_branch = 'detached from FETCH_HEAD' git_hash = repo_h.commit.hexsha @@ -56,8 +56,8 @@ class CliEnv(object): branch = repo_h.reference git_branch = branch.name git_hash = branch.commit.hexsha - is_debug = _get_value(CONST.CI_DEBUG, 'false') - build_tag = CONST.BUILD_TAG + is_debug = _get_value(CONST.__getattribute__('CI_DEBUG'), 'false') + build_tag = CONST.__getattribute__('BUILD_TAG') if build_tag is not None: build_tag = build_tag.lstrip( "jenkins-").lstrip("functest").lstrip("-") @@ -84,7 +84,7 @@ class CliEnv(object): def status(self, verbose=True): ret_val = 0 - if not os.path.isfile(CONST.env_active): + if not os.path.isfile(CONST.__getattribute__('env_active')): if verbose: click.echo("Functest environment is not installed.\n") ret_val = 1 diff --git a/functest/cli/commands/cli_os.py b/functest/cli/commands/cli_os.py index f85f4041..e54eb423 100644 --- a/functest/cli/commands/cli_os.py +++ b/functest/cli/commands/cli_os.py @@ -21,11 +21,11 @@ import functest.utils.openstack_snapshot as os_snapshot class CliOpenStack(object): def __init__(self): - self.os_auth_url = CONST.OS_AUTH_URL + self.os_auth_url = CONST.__getattribute__('OS_AUTH_URL') self.endpoint_ip = None self.endpoint_port = None - self.openstack_creds = CONST.openstack_creds - self.snapshot_file = CONST.openstack_snapshot_file + self.openstack_creds = CONST.__getattribute__('openstack_creds') + self.snapshot_file = CONST.__getattribute__('openstack_snapshot_file') if self.os_auth_url: self.endpoint_ip = self.os_auth_url.rsplit("/")[2].rsplit(":")[0] self.endpoint_port = self.os_auth_url.rsplit("/")[2].rsplit(":")[1] @@ -59,16 +59,16 @@ class CliOpenStack(object): else: answer = raw_input("Invalid answer. Please type [y|n]\n") - installer_type = CONST.INSTALLER_TYPE + installer_type = CONST.__getattribute__('INSTALLER_TYPE') if installer_type is None: click.echo("The environment variable 'INSTALLER_TYPE' is not" "defined. Please export it") - installer_ip = CONST.INSTALLER_IP + installer_ip = CONST.__getattribute__('INSTALLER_IP') if installer_ip is None: click.echo("The environment variable 'INSTALLER_IP' is not" "defined. Please export it") cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" - % (CONST.dir_repos, + % (CONST.__getattribute__('dir_repos'), self.openstack_creds, installer_type, installer_ip)) @@ -78,7 +78,8 @@ class CliOpenStack(object): def check(self): self.ping_endpoint() - cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh" + cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'), + "functest/ci/check_os.sh") ft_utils.execute_command(cmd, verbose=False) def snapshot_create(self): diff --git a/functest/cli/commands/cli_testcase.py b/functest/cli/commands/cli_testcase.py index 6644a0c2..3d3f1cb3 100644 --- a/functest/cli/commands/cli_testcase.py +++ b/functest/cli/commands/cli_testcase.py @@ -22,9 +22,10 @@ import functest.utils.functest_vacation as vacation class CliTestcase(object): def __init__(self): - self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE, - CONST.DEPLOY_SCENARIO, - CONST.functest_testcases_yaml) + self.tiers = tb.TierBuilder( + CONST.__getattribute__('INSTALLER_TYPE'), + CONST.__getattribute__('DEPLOY_SCENARIO'), + CONST.__getattribute__('functest_testcases_yaml')) def list(self): summary = "" @@ -52,12 +53,14 @@ class CliTestcase(object): if testname == 'vacation': vacation.main() - elif not os.path.isfile(CONST.env_active): + elif not os.path.isfile(CONST.__getattribute__('env_active')): click.echo("Functest environment is not ready. " "Run first 'functest env prepare'") else: tests = testname.split(",") for test in tests: cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, flags, test)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + flags, test)) ft_utils.execute_command(cmd) diff --git a/functest/cli/commands/cli_tier.py b/functest/cli/commands/cli_tier.py index 012b11d0..531f0ff9 100644 --- a/functest/cli/commands/cli_tier.py +++ b/functest/cli/commands/cli_tier.py @@ -21,9 +21,10 @@ import functest.utils.functest_utils as ft_utils class CliTier(object): def __init__(self): - self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE, - CONST.DEPLOY_SCENARIO, - CONST.functest_testcases_yaml) + self.tiers = tb.TierBuilder( + CONST.__getattribute__('INSTALLER_TYPE'), + CONST.__getattribute__('DEPLOY_SCENARIO'), + CONST.__getattribute__('functest_testcases_yaml')) def list(self): summary = "" @@ -62,10 +63,12 @@ class CliTier(object): if report: flags += "-r " - if not os.path.isfile(CONST.env_active): + if not os.path.isfile(CONST.__getattribute__('env_active')): click.echo("Functest environment is not ready. " "Run first 'functest env prepare'") else: cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, flags, tiername)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + flags, tiername)) ft_utils.execute_command(cmd) diff --git a/functest/core/feature.py b/functest/core/feature.py index d65f5a3c..140c9bb2 100644 --- a/functest/core/feature.py +++ b/functest/core/feature.py @@ -13,11 +13,11 @@ Feature is considered as TestCase offered by Third-party. It offers helpers to run any python method or any bash command. """ +import logging import time import functest.core.testcase as base import functest.utils.functest_utils as ft_utils -import functest.utils.functest_logger as ft_logger from functest.utils.constants import CONST __author__ = ("Serena Feng <feng.xiaowei@zte.com.cn>, " @@ -27,11 +27,12 @@ __author__ = ("Serena Feng <feng.xiaowei@zte.com.cn>, " class Feature(base.TestCase): """Base model for single feature.""" + __logger = logging.getLogger(__name__) + def __init__(self, **kwargs): super(Feature, self).__init__(**kwargs) self.result_file = "{}/{}.log".format( - CONST.__getattribute__('dir_results'), self.project_name) - self.logger = ft_logger.Logger(self.project_name).getLogger() + CONST.__getattribute__('dir_results'), self.case_name) def execute(self, **kwargs): """Execute the Python method. @@ -82,10 +83,9 @@ class Feature(base.TestCase): ft_utils.logger_test_results( self.project_name, self.case_name, self.result, self.details) - self.logger.info("%s %s", self.project_name, self.result) except Exception: # pylint: disable=broad-except - self.logger.exception("%s FAILED", self.project_name) - self.logger.info("Test result is stored in '%s'", self.result_file) + self.__logger.exception("%s FAILED", self.project_name) + self.__logger.info("Test result is stored in '%s'", self.result_file) self.stop_time = time.time() return exit_code @@ -93,6 +93,8 @@ class Feature(base.TestCase): class BashFeature(Feature): """Class designed to run any bash command.""" + __logger = logging.getLogger(__name__) + def execute(self, **kwargs): """Execute the cmd passed as arg @@ -108,7 +110,7 @@ class BashFeature(Feature): cmd = kwargs["cmd"] ret = ft_utils.execute_command(cmd, output_file=self.result_file) except KeyError: - self.logger.error("Please give cmd as arg. kwargs: %s", kwargs) + self.__logger.error("Please give cmd as arg. kwargs: %s", kwargs) except Exception: # pylint: disable=broad-except - self.logger.exception("Execute cmd: %s failed", cmd) + self.__logger.exception("Execute cmd: %s failed", cmd) return ret diff --git a/functest/core/pytest_suite_runner.py b/functest/core/pytest_suite_runner.py index 8b5da05e..a6e47660 100644 --- a/functest/core/pytest_suite_runner.py +++ b/functest/core/pytest_suite_runner.py @@ -5,26 +5,46 @@ # # http://www.apache.org/licenses/LICENSE-2.0 -import testcase as base -import unittest +# pylint: disable=missing-docstring + +import logging import time +import unittest +import six -class PyTestSuiteRunner(base.TestCase): +from functest.core import testcase + + +class PyTestSuiteRunner(testcase.TestCase): """ This superclass is designed to execute pre-configured unittest.TestSuite() objects """ + def __init__(self, **kwargs): super(PyTestSuiteRunner, self).__init__(**kwargs) self.suite = None + self.logger = logging.getLogger(__name__) def run(self, **kwargs): """ Starts test execution from the functest framework """ + try: + name = kwargs["name"] + try: + self.suite = unittest.TestLoader().loadTestsFromName(name) + except ImportError: + self.logger.error("Can not import %s", name) + return testcase.TestCase.EX_RUN_ERROR + except KeyError: + pass self.start_time = time.time() - result = unittest.TextTestRunner(verbosity=2).run(self.suite) + stream = six.StringIO() + result = unittest.TextTestRunner( + stream=stream, verbosity=2).run(self.suite) + self.logger.debug("\n\n%s", stream.getvalue()) self.stop_time = time.time() if result.errors: @@ -44,14 +64,14 @@ class PyTestSuiteRunner(base.TestCase): # we shall distinguish Execution Error from FAIL results # TestCase.EX_RUN_ERROR means that the test case was not run # not that it was run but the result was FAIL - exit_code = base.TestCase.EX_OK - if ((result.errors and len(result.errors) > 0) - or (result.failures and len(result.failures) > 0)): - self.logger.info("%s FAILED" % self.case_name) - self.result = 'FAIL' + exit_code = testcase.TestCase.EX_OK + if ((result.errors and len(result.errors) > 0) or + (result.failures and len(result.failures) > 0)): + self.logger.info("%s FAILED", self.case_name) + self.result = 0 else: - self.logger.info("%s OK" % self.case_name) - self.result = 'PASS' + self.logger.info("%s OK", self.case_name) + self.result = 100 self.details = {} return exit_code diff --git a/functest/core/testcase.py b/functest/core/testcase.py index 3f191b40..43161525 100644 --- a/functest/core/testcase.py +++ b/functest/core/testcase.py @@ -9,9 +9,11 @@ """Define the parent class of all Functest TestCases.""" +import logging import os -import functest.utils.functest_logger as ft_logger +import prettytable + import functest.utils.functest_utils as ft_utils __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>" @@ -32,18 +34,53 @@ class TestCase(object): EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2 """results are false""" - logger = ft_logger.Logger(__name__).getLogger() + __logger = logging.getLogger(__name__) def __init__(self, **kwargs): self.details = {} self.project_name = kwargs.get('project_name', 'functest') self.case_name = kwargs.get('case_name', '') self.criteria = kwargs.get('criteria', 100) - self.result = "" - self.start_time = "" - self.stop_time = "" + self.result = 0 + self.start_time = 0 + self.stop_time = 0 + + def __str__(self): + try: + assert self.project_name + assert self.case_name + result = 'PASS' if(self.is_successful( + ) == TestCase.EX_OK) else 'FAIL' + msg = prettytable.PrettyTable( + header_style='upper', padding_width=5, + field_names=['test case', 'project', 'duration', + 'result']) + msg.add_row([self.case_name, self.project_name, + self.get_duration(), result]) + return msg.get_string() + except AssertionError: + self.__logger.error("We cannot print invalid objects") + return super(TestCase, self).__str__() + + def get_duration(self): + """Return the duration of the test case. + + Returns: + duration if start_time and stop_time are set + "XX:XX" otherwise. + """ + try: + assert self.start_time + assert self.stop_time + if self.stop_time < self.start_time: + return "XX:XX" + return "{0[0]:02.0f}:{0[1]:02.0f}".format(divmod( + self.stop_time - self.start_time, 60)) + except Exception: # pylint: disable=broad-except + self.__logger.error("Please run test before getting the duration") + return "XX:XX" - def check_result(self): + def is_successful(self): """Interpret the result of the test case. It allows getting the result of TestCase. It completes run() @@ -57,7 +94,9 @@ class TestCase(object): """ try: assert self.criteria - if isinstance(self.result, int) and isinstance(self.criteria, int): + assert self.result is not None + if (not isinstance(self.result, str) and + not isinstance(self.criteria, str)): if self.result >= self.criteria: return TestCase.EX_OK else: @@ -65,12 +104,12 @@ class TestCase(object): # It must be removed as soon as TestCase subclasses # stop setting result = 'PASS' or 'FAIL'. # In this case criteria is unread. - self.logger.warning( + self.__logger.warning( "Please update result which must be an int!") if self.result == 'PASS': return TestCase.EX_OK except AssertionError: - self.logger.error("Please run test before checking the results") + self.__logger.error("Please run test before checking the results") return TestCase.EX_TESTCASE_FAILED def run(self, **kwargs): @@ -96,7 +135,7 @@ class TestCase(object): TestCase.EX_RUN_ERROR. """ # pylint: disable=unused-argument - self.logger.error("Run must be implemented") + self.__logger.error("Run must be implemented") return TestCase.EX_RUN_ERROR def push_to_db(self): @@ -123,16 +162,17 @@ class TestCase(object): assert self.case_name assert self.start_time assert self.stop_time - pub_result = 'PASS' if self.check_result( + pub_result = 'PASS' if self.is_successful( ) == TestCase.EX_OK else 'FAIL' if ft_utils.push_results_to_db( self.project_name, self.case_name, self.start_time, self.stop_time, pub_result, self.details): - self.logger.info("The results were successfully pushed to DB") + self.__logger.info( + "The results were successfully pushed to DB") return TestCase.EX_OK else: - self.logger.error("The results cannot be pushed to DB") + self.__logger.error("The results cannot be pushed to DB") return TestCase.EX_PUSH_TO_DB_ERROR except Exception: # pylint: disable=broad-except - self.logger.exception("The results cannot be pushed to DB") + self.__logger.exception("The results cannot be pushed to DB") return TestCase.EX_PUSH_TO_DB_ERROR diff --git a/functest/core/vnf_base.py b/functest/core/vnf.py index fe4e427f..5667b299 100644 --- a/functest/core/vnf_base.py +++ b/functest/core/vnf.py @@ -8,30 +8,30 @@ # http://www.apache.org/licenses/LICENSE-2.0 import inspect +import logging import time import functest.core.testcase as base from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils -class VnfOnBoardingBase(base.TestCase): +class VnfOnBoarding(base.TestCase): - logger = ft_logger.Logger(__name__).getLogger() + __logger = logging.getLogger(__name__) def __init__(self, **kwargs): - super(VnfOnBoardingBase, self).__init__(**kwargs) + super(VnfOnBoarding, self).__init__(**kwargs) self.repo = kwargs.get('repo', '') self.cmd = kwargs.get('cmd', '') self.details = {} - self.result_dir = CONST.dir_results + self.result_dir = CONST.__getattribute__('dir_results') self.details_step_mapping = dict( - deploy_orchestrator='orchestrator', - deploy_vnf='vnf', - test_vnf='test_vnf', - prepare='prepare_env') + deploy_orchestrator='orchestrator', + deploy_vnf='vnf', + test_vnf='test_vnf', + prepare='prepare_env') self.details['prepare_env'] = {} self.details['orchestrator'] = {} self.details['vnf'] = {} @@ -44,28 +44,28 @@ class VnfOnBoardingBase(base.TestCase): 'vnf_{}_tenant_description'.format(self.case_name)) except Exception: # raise Exception("Unknown VNF case=" + self.case_name) - self.logger.error("Unknown VNF case={}".format(self.case_name)) + self.__logger.error("Unknown VNF case={}".format(self.case_name)) try: self.images = CONST.__getattribute__( 'vnf_{}_tenant_images'.format(self.case_name)) except Exception: - self.logger.warn("No tenant image defined for this VNF") + self.__logger.warn("No tenant image defined for this VNF") def execute(self): self.start_time = time.time() # Prepare the test (Create Tenant, User, ...) try: - self.logger.info("Create VNF Onboarding environment") + self.__logger.info("Create VNF Onboarding environment") self.prepare() except Exception: - self.logger.error("Error during VNF Onboarding environment" + - "creation", exc_info=True) + self.__logger.error("Error during VNF Onboarding environment" + "creation", exc_info=True) return base.TestCase.EX_TESTCASE_FAILED # Deploy orchestrator try: - self.logger.info("Deploy orchestrator (if necessary)") + self.__logger.info("Deploy orchestrator (if necessary)") orchestrator_ready_time = time.time() res_orchestrator = self.deploy_orchestrator() # orchestrator is not mandatory @@ -77,11 +77,11 @@ class VnfOnBoardingBase(base.TestCase): self.details['orchestrator']['duration'] = round( orchestrator_ready_time - self.start_time, 1) except Exception: - self.logger.warn("Problem with the Orchestrator", exc_info=True) + self.__logger.warn("Problem with the Orchestrator", exc_info=True) # Deploy VNF try: - self.logger.info("Deploy VNF " + self.case_name) + self.__logger.info("Deploy VNF " + self.case_name) res_deploy_vnf = self.deploy_vnf() vnf_ready_time = time.time() self.details['vnf']['status'] = res_deploy_vnf['status'] @@ -89,12 +89,12 @@ class VnfOnBoardingBase(base.TestCase): self.details['vnf']['duration'] = round( vnf_ready_time - orchestrator_ready_time, 1) except Exception: - self.logger.error("Error during VNF deployment", exc_info=True) + self.__logger.error("Error during VNF deployment", exc_info=True) return base.TestCase.EX_TESTCASE_FAILED # Test VNF try: - self.logger.info("Test VNF") + self.__logger.info("Test VNF") res_test_vnf = self.test_vnf() test_vnf_done_time = time.time() self.details['test_vnf']['status'] = res_test_vnf['status'] @@ -102,7 +102,7 @@ class VnfOnBoardingBase(base.TestCase): self.details['test_vnf']['duration'] = round( test_vnf_done_time - vnf_ready_time, 1) except Exception: - self.logger.error("Error when running VNF tests", exc_info=True) + self.__logger.error("Error when running VNF tests", exc_info=True) return base.TestCase.EX_TESTCASE_FAILED # Clean the system @@ -121,12 +121,13 @@ class VnfOnBoardingBase(base.TestCase): self.creds = os_utils.get_credentials() self.keystone_client = os_utils.get_keystone_client() - self.logger.info("Prepare OpenStack plateform(create tenant and user)") + self.__logger.info( + "Prepare OpenStack plateform(create tenant and user)") admin_user_id = os_utils.get_user_id(self.keystone_client, self.creds['username']) if not admin_user_id: self.step_failure("Failed to get id of {0}".format( - self.creds['username'])) + self.creds['username'])) tenant_id = os_utils.get_tenant_id(self.keystone_client, self.tenant_name) @@ -136,7 +137,7 @@ class VnfOnBoardingBase(base.TestCase): self.tenant_description) if not tenant_id: self.step_failure("Failed to get or create {0} tenant".format( - self.tenant_name)) + self.tenant_name)) roles_name = ["admin", "Admin"] role_id = '' for role_name in roles_name: @@ -146,12 +147,12 @@ class VnfOnBoardingBase(base.TestCase): if not role_id: self.step_failure("Failed to get id for {0} role".format( - role_name)) + role_name)) if not os_utils.add_role_user(self.keystone_client, admin_user_id, role_id, tenant_id): self.step_failure("Failed to add {0} on tenant".format( - self.creds['username'])) + self.creds['username'])) user_id = os_utils.get_or_create_user(self.keystone_client, self.tenant_name, @@ -164,7 +165,7 @@ class VnfOnBoardingBase(base.TestCase): os_utils.add_role_user(self.keystone_client, user_id, role_id, tenant_id) - self.logger.info("Update OpenStack creds informations") + self.__logger.info("Update OpenStack creds informations") self.admin_creds = self.creds.copy() self.admin_creds.update({ "tenant": self.tenant_name @@ -183,21 +184,21 @@ class VnfOnBoardingBase(base.TestCase): # TODO see how to use built-in exception from releng module def deploy_vnf(self): - self.logger.error("VNF must be deployed") + self.__logger.error("VNF must be deployed") raise Exception("VNF not deployed") def test_vnf(self): - self.logger.error("VNF must be tested") + self.__logger.error("VNF must be tested") raise Exception("VNF not tested") # clean before openstack clean run def clean(self): - self.logger.info("test cleaning") + self.__logger.info("test cleaning") def parse_results(self): exit_code = self.EX_OK self.result = "PASS" - self.logger.info(self.details) + self.__logger.info(self.details) # The 2 VNF steps must be OK to get a PASS result if (self.details['vnf']['status'] is not "PASS" or self.details['test_vnf']['status'] is not "PASS"): @@ -213,7 +214,7 @@ class VnfOnBoardingBase(base.TestCase): def step_failure(self, error_msg): part = inspect.stack()[1][3] - self.logger.error("Step {0} failed: {1}".format(part, error_msg)) + self.__logger.error("Step {0} failed: {1}".format(part, error_msg)) try: step_name = self.details_step_mapping[part] part_info = self.details[step_name] diff --git a/functest/energy/__init__.py b/functest/energy/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/functest/energy/__init__.py diff --git a/functest/energy/energy.py b/functest/energy/energy.py new file mode 100644 index 00000000..a20c7992 --- /dev/null +++ b/functest/energy/energy.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# Copyright (c) 2017 Orange 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 + +"""This module manages calls to Energy recording API.""" + +import json +import logging +import urllib +import requests + +import functest.utils.functest_utils as ft_utils + + +def enable_recording(method): + """ + Decorator to record energy during "method" exection. + + param method: Method to suround with start and stop + :type method: function + + .. note:: "method" should belong to a class having a "case_name" + attribute + """ + def wrapper(*args): + """Wrapper for decorator to handle method arguments.""" + EnergyRecorder.start(args[0].case_name) + return_value = method(*args) + EnergyRecorder.stop() + return return_value + return wrapper + + +# Class to manage energy recording sessions +class EnergyRecorder(object): + """Manage Energy recording session.""" + + logger = logging.getLogger(__name__) + # Energy recording API connectivity settings + # see load_config method + energy_recorder_api = None + + # Default initial step + INITIAL_STEP = "starting" + + @staticmethod + def load_config(): + """ + Load connectivity settings from yaml. + + Load connectivity settings to Energy recording API + Use functest global config yaml file + (see functest_utils.get_functest_config) + """ + # Singleton pattern for energy_recorder_api static member + # Load only if not previouly done + if EnergyRecorder.energy_recorder_api is None: + environment = ft_utils.get_pod_name() + + # API URL + energy_recorder_uri = ft_utils.get_functest_config( + "energy_recorder.api_url") + assert energy_recorder_uri + assert environment + + energy_recorder_uri += "/recorders/environment/" + energy_recorder_uri += urllib.quote_plus(environment) + EnergyRecorder.logger.debug( + "API recorder at: " + energy_recorder_uri) + + # Creds + user = ft_utils.get_functest_config( + "energy_recorder.api_user") + password = ft_utils.get_functest_config( + "energy_recorder.api_password") + + if user != "" and password != "": + energy_recorder_api_auth = (user, password) + else: + energy_recorder_api_auth = None + + # Final config + EnergyRecorder.energy_recorder_api = { + "uri": energy_recorder_uri, + "auth": energy_recorder_api_auth + } + + @staticmethod + def start(scenario): + """ + Start a recording session for scenario. + + param scenario: Starting scenario + :type scenario: string + """ + return_status = True + try: + EnergyRecorder.logger.debug("Starting recording") + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Create API payload + payload = { + "step": EnergyRecorder.INITIAL_STEP, + "scenario": scenario + } + # Call API to start energy recording + response = requests.post( + EnergyRecorder.energy_recorder_api["uri"], + data=json.dumps(payload), + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while starting energy recording session\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.info(log_msg) + return_status = False + + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while starting energy recorder API" + ) + return_status = False + return return_status + + @staticmethod + def stop(): + """Stop current recording session.""" + EnergyRecorder.logger.debug("Stopping recording") + return_status = True + try: + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Call API to stop energy recording + response = requests.delete( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while stating energy recording session\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.error(log_msg) + return_status = False + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while stoping energy recorder API" + ) + return_status = False + return return_status + + @staticmethod + def set_step(step): + """Notify energy recording service of current step of the testcase.""" + EnergyRecorder.logger.debug("Setting step") + return_status = True + try: + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Create API payload + payload = { + "step": step, + } + + # Call API to define step + response = requests.post( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + data=json.dumps(payload), + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while setting current step of testcase\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.error(log_msg) + return_status = False + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while setting step on energy recorder API" + ) + return_status = False + return return_status diff --git a/functest/opnfv_tests/features/barometer.py b/functest/opnfv_tests/features/barometer.py index 8a409406..cbfe7d9a 100644 --- a/functest/opnfv_tests/features/barometer.py +++ b/functest/opnfv_tests/features/barometer.py @@ -6,6 +6,8 @@ # # http://www.apache.org/licenses/LICENSE-2.0 +import logging + from baro_tests import collectd import functest.core.feature as base @@ -16,5 +18,7 @@ class BarometerCollectd(base.Feature): Class for executing barometercollectd testcase. ''' + __logger = logging.getLogger(__name__) + def execute(self): - return collectd.main(self.logger) + return collectd.main(self.__logger) diff --git a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py b/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py deleted file mode 100755 index b4400864..00000000 --- a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) 2015 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 -# -# This script boots an instance and assigns a floating ip -# - -import argparse -import os -import sys - -from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger -import functest.utils.openstack_utils as os_utils - -parser = argparse.ArgumentParser() - -parser.add_argument("-r", "--report", - help="Create json result file", - action="store_true") - -args = parser.parse_args() - -""" logging configuration """ -logger = ft_logger.Logger("create_instance_and_ip").getLogger() - -HOME = CONST.dir_home + "/" - -VM_BOOT_TIMEOUT = 180 - -EXAMPLE_INSTANCE_NAME = CONST.example_vm_name -EXAMPLE_FLAVOR = CONST.example_flavor -EXAMPLE_IMAGE_NAME = CONST.example_image_name -IMAGE_FILENAME = CONST.openstack_image_file_name -IMAGE_FORMAT = CONST.openstack_image_disk_format -IMAGE_PATH = os.path.join(CONST.dir_functest_data, IMAGE_FILENAME) - -# NEUTRON Private Network parameters - -EXAMPLE_PRIVATE_NET_NAME = CONST.example_private_net_name -EXAMPLE_PRIVATE_SUBNET_NAME = CONST.example_private_subnet_name -EXAMPLE_PRIVATE_SUBNET_CIDR = CONST.example_private_subnet_cidr -EXAMPLE_ROUTER_NAME = CONST.example_router_name - -EXAMPLE_SECGROUP_NAME = CONST.example_sg_name -EXAMPLE_SECGROUP_DESCR = CONST.example_sg_desc - - -def main(): - - nova_client = os_utils.get_nova_client() - neutron_client = os_utils.get_neutron_client() - glance_client = os_utils.get_glance_client() - - image_id = os_utils.create_glance_image(glance_client, - EXAMPLE_IMAGE_NAME, - IMAGE_PATH, - disk=IMAGE_FORMAT, - container="bare", - public=True) - - network_dic = os_utils.create_network_full( - neutron_client, - EXAMPLE_PRIVATE_NET_NAME, - EXAMPLE_PRIVATE_SUBNET_NAME, - EXAMPLE_ROUTER_NAME, - EXAMPLE_PRIVATE_SUBNET_CIDR) - if not network_dic: - logger.error( - "There has been a problem when creating the neutron network") - sys.exit(-1) - - network_id = network_dic["net_id"] - - sg_id = os_utils.create_security_group_full(neutron_client, - EXAMPLE_SECGROUP_NAME, - EXAMPLE_SECGROUP_DESCR) - - # boot INTANCE - logger.info("Creating instance '%s'..." % EXAMPLE_INSTANCE_NAME) - logger.debug( - "Configuration:\n name=%s \n flavor=%s \n image=%s \n " - "network=%s \n" - % (EXAMPLE_INSTANCE_NAME, EXAMPLE_FLAVOR, image_id, network_id)) - instance = os_utils.create_instance_and_wait_for_active( - EXAMPLE_FLAVOR, - image_id, - network_id, - EXAMPLE_INSTANCE_NAME) - - if instance is None: - logger.error("Error while booting instance.") - sys.exit(-1) - # Retrieve IP of INSTANCE - instance_ip = instance.networks.get(EXAMPLE_PRIVATE_NET_NAME)[0] - logger.debug("Instance '%s' got private ip '%s'." % - (EXAMPLE_INSTANCE_NAME, instance_ip)) - - logger.info("Adding '%s' to security group '%s'..." - % (EXAMPLE_INSTANCE_NAME, EXAMPLE_SECGROUP_NAME)) - os_utils.add_secgroup_to_instance(nova_client, instance.id, sg_id) - - logger.info("Creating floating IP for VM '%s'..." % EXAMPLE_INSTANCE_NAME) - floatip_dic = os_utils.create_floating_ip(neutron_client) - floatip = floatip_dic['fip_addr'] - # floatip_id = floatip_dic['fip_id'] - - if floatip is None: - logger.error("Cannot create floating IP.") - sys.exit(-1) - logger.info("Floating IP created: '%s'" % floatip) - - logger.info("Associating floating ip: '%s' to VM '%s' " - % (floatip, EXAMPLE_INSTANCE_NAME)) - if not os_utils.add_floating_ip(nova_client, instance.id, floatip): - logger.error("Cannot associate floating IP to VM.") - sys.exit(-1) - - sys.exit(0) - - -if __name__ == '__main__': - main() diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py index e07e2a8d..40f8386c 100644 --- a/functest/opnfv_tests/openstack/rally/rally.py +++ b/functest/opnfv_tests/openstack/rally/rally.py @@ -8,7 +8,10 @@ # http://www.apache.org/licenses/LICENSE-2.0 # +from __future__ import division + import json +import logging import os import re import subprocess @@ -19,11 +22,9 @@ import yaml from functest.core import testcase from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils -logger = ft_logger.Logger('Rally').getLogger() +logger = logging.getLogger(__name__) class RallyBase(testcase.TestCase): @@ -31,7 +32,7 @@ class RallyBase(testcase.TestCase): 'neutron', 'nova', 'quotas', 'requests', 'vm', 'all'] GLANCE_IMAGE_NAME = CONST.openstack_image_name GLANCE_IMAGE_FILENAME = CONST.openstack_image_file_name - GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data, + GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images, GLANCE_IMAGE_FILENAME) GLANCE_IMAGE_FORMAT = CONST.openstack_image_disk_format FLAVOR_NAME = "m1.tiny" @@ -480,11 +481,12 @@ class RallyBase(testcase.TestCase): total_duration_str2 = "{0:<10}".format(total_duration_str) total_nb_tests_str = "{0:<13}".format(total_nb_tests) - if len(self.summary): - success_rate = total_success / len(self.summary) - else: - success_rate = 100 - success_rate = "{:0.2f}".format(success_rate) + try: + self.result = total_success / len(self.summary) + except ZeroDivisionError: + self.result = 100 + + success_rate = "{:0.2f}".format(self.result) success_rate_str = "{0:<10}".format(str(success_rate) + '%') report += ("+===================+============" "+===============+===========+") @@ -500,12 +502,10 @@ class RallyBase(testcase.TestCase): 'nb tests': total_nb_tests, 'nb success': success_rate}}) - self.result = ft_utils.check_success_rate( - self.case_name, success_rate) self.details = payload - logger.info("Rally '%s' success_rate is %s%%, is marked as %s" - % (self.case_name, success_rate, self.result)) + logger.info("Rally '%s' success_rate is %s%%" + % (self.case_name, success_rate)) def _clean_up(self): if self.volume_type: diff --git a/functest/opnfv_tests/openstack/refstack_client/defcore.txt b/functest/opnfv_tests/openstack/refstack_client/defcore.txt index be8fd899..0a1787ef 100644 --- a/functest/opnfv_tests/openstack/refstack_client/defcore.txt +++ b/functest/opnfv_tests/openstack/refstack_client/defcore.txt @@ -1,4 +1,11 @@ -# Set of DefCore tempest test cases not flagged and required. It only contains OpenStack core (no object storage) +# Set of DefCore tempest test cases not flagged and required. +# According to https://github.com/openstack/interop/blob/master/2016.08/procedure.rst, +# some tests are still flagged due to outstanding bugs in the Tempest library, +# particularly tests that require SSH. Refstack developers +# are working on correcting these bugs upstream. Please note that although some tests +# are flagged because of bugs, there is still an expectation that the capabilities +# covered by the tests are available. +# It only contains Openstack core compute (no object storage) # The approved guidelines (2016.08) are valid for Kilo, Liberty, Mitaka and Newton releases of OpenStack # The list can be generated using the Rest API from RefStack project: # https://refstack.openstack.org/api/v1/guidelines/2016.08/tests?target=compute&type=required&alias=true&flag=false diff --git a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py index 2f2fc00f..2a2718dd 100755 --- a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py +++ b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py @@ -5,7 +5,12 @@ # 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 __future__ import division + + import argparse +import logging import os import re import sys @@ -15,12 +20,11 @@ import time from functest.core import testcase from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils from tempest_conf import TempestConf """ logging configuration """ -logger = ft_logger.Logger("refstack_defcore").getLogger() +logger = logging.getLogger(__name__) class RefstackClient(testcase.TestCase): @@ -123,7 +127,11 @@ class RefstackClient(testcase.TestCase): skipped_testcases += match + ", " num_executed = int(num_tests) - int(num_skipped) - success_rate = 100 * int(num_success) / int(num_executed) + + try: + self.result = 100 * int(num_success) / int(num_executed) + except ZeroDivisionError: + logger.error("No test has been executed") self.details = {"tests": int(num_tests), "failures": int(num_failures), @@ -131,12 +139,10 @@ class RefstackClient(testcase.TestCase): "errors": failed_testcases, "skipped": skipped_testcases} except Exception: - success_rate = 0 + self.result = 0 - self.result = ft_utils.check_success_rate( - self.case_name, success_rate) - logger.info("Testcase %s success_rate is %s%%, is marked as %s" - % (self.case_name, success_rate, self.result)) + logger.info("Testcase %s success_rate is %s%%" + % (self.case_name, self.result)) def run(self): '''used for functest command line, @@ -220,6 +226,7 @@ class RefstackClientParser(object): if __name__ == '__main__': + logging.basicConfig() refstackclient = RefstackClient() parser = RefstackClientParser() args = parser.parse_args(sys.argv[1:]) diff --git a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py index d01f0872..5c04253c 100755 --- a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py +++ b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py @@ -5,15 +5,15 @@ # 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 logging import os from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils import openstack_utils from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger """ logging configuration """ -logger = ft_logger.Logger("refstack_defcore").getLogger() +logger = logging.getLogger(__name__) class TempestConf(object): @@ -48,5 +48,6 @@ class TempestConf(object): if __name__ == '__main__': + logging.basicConfig() tempestconf = TempestConf() tempestconf.main() diff --git a/functest/opnfv_tests/openstack/snaps/health_check.py b/functest/opnfv_tests/openstack/snaps/health_check.py index c057eb2b..0daddcdd 100644 --- a/functest/opnfv_tests/openstack/snaps/health_check.py +++ b/functest/opnfv_tests/openstack/snaps/health_check.py @@ -23,14 +23,15 @@ class HealthCheck(SnapsTestRunner): """ def __init__(self, **kwargs): if "case_name" not in kwargs: - kwargs["case_name"] = "snaps_health_check" + kwargs["case_name"] = "snaps_images_cirros" super(HealthCheck, self).__init__(**kwargs) self.suite = unittest.TestSuite() image_custom_config = None - if hasattr(CONST, 'snaps_health_check'): - image_custom_config = CONST.__getattribute__('snaps_health_check') + + if hasattr(CONST, 'snaps_images_cirros'): + image_custom_config = CONST.__getattribute__('snaps_images_cirros') self.suite.addTest( OSIntegrationTestCase.parameterize( SimpleHealthCheck, os_creds=self.os_creds, diff --git a/functest/opnfv_tests/openstack/snaps/smoke.py b/functest/opnfv_tests/openstack/snaps/smoke.py index 2c6fc255..d9f95e90 100644 --- a/functest/opnfv_tests/openstack/snaps/smoke.py +++ b/functest/opnfv_tests/openstack/snaps/smoke.py @@ -28,11 +28,9 @@ class SnapsSmoke(SnapsTestRunner): self.suite = unittest.TestSuite() - # The snaps smoke test uses the same config as the - # snaps_health_check suite, so reuse it here - image_custom_config = None - if hasattr(CONST, 'snaps_health_check'): - image_custom_config = CONST.__getattribute__('snaps_health_check') + image_config = None + if hasattr(CONST, 'snaps_images_cirros'): + image_config = CONST.__getattribute__('snaps_images_cirros') # Tests requiring floating IPs leverage files contained within the # SNAPS repository and are found relative to that path @@ -47,5 +45,5 @@ class SnapsSmoke(SnapsTestRunner): ext_net_name=self.ext_net_name, use_keystone=self.use_keystone, flavor_metadata=self.flavor_metadata, - image_metadata=image_custom_config, + image_metadata=image_config, use_floating_ips=self.use_fip) diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py index 8a68cad9..94b97551 100644 --- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py +++ b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py @@ -5,6 +5,8 @@ # # http://www.apache.org/licenses/LICENSE-2.0 +import logging + from functest.core.pytest_suite_runner import PyTestSuiteRunner from functest.opnfv_tests.openstack.snaps import snaps_utils from functest.utils import functest_utils @@ -16,12 +18,11 @@ from snaps.openstack.tests import openstack_tests class SnapsTestRunner(PyTestSuiteRunner): """ - This test executes the SNAPS Python Test case SimpleHealthCheck which - creates a VM with a single port with an IPv4 address that is assigned by - DHCP. This test then validates the expected IP with the actual + This test executes the SNAPS Python Tests """ def __init__(self, **kwargs): super(SnapsTestRunner, self).__init__(**kwargs) + self.logger = logging.getLogger(__name__) self.os_creds = openstack_tests.get_credentials( os_env_file=CONST.__getattribute__('openstack_creds'), diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py index f4a94f65..cd6a2a8c 100644 --- a/functest/opnfv_tests/openstack/tempest/conf_utils.py +++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py @@ -8,13 +8,13 @@ # http://www.apache.org/licenses/LICENSE-2.0 # import ConfigParser +import logging import os import re import shutil import subprocess from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils @@ -22,7 +22,7 @@ import functest.utils.openstack_utils as os_utils IMAGE_ID_ALT = None FLAVOR_ID_ALT = None REPO_PATH = CONST.dir_repo_functest -GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data, +GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images, CONST.openstack_image_file_name) TEMPEST_TEST_LIST_DIR = CONST.dir_tempest_cases TEMPEST_RESULTS_DIR = os.path.join(CONST.dir_results, @@ -42,7 +42,7 @@ CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE CI_INSTALLER_IP = CONST.INSTALLER_IP """ logging configuration """ -logger = ft_logger.Logger("Tempest").getLogger() +logger = logging.getLogger(__name__) def create_tempest_resources(use_custom_images=False, @@ -279,12 +279,20 @@ def configure_tempest_update_params(tempest_conf_file, config.set('identity', 'tenant_name', CONST.tempest_identity_tenant_name) config.set('identity', 'username', CONST.tempest_identity_user_name) config.set('identity', 'password', CONST.tempest_identity_user_password) + config.set('identity', 'region', 'RegionOne') config.set( 'validation', 'ssh_timeout', CONST.tempest_validation_ssh_timeout) config.set('object-storage', 'operator_role', CONST.tempest_object_storage_operator_role) if CONST.OS_ENDPOINT_TYPE is not None: + sections = config.sections() + if os_utils.is_keystone_v3(): + config.set('identity', 'v3_endpoint_type', CONST.OS_ENDPOINT_TYPE) + if 'identity-feature-enabled' not in sections: + config.add_section('identity-feature-enabled') + config.set('identity-feature-enabled', 'api_v2', False) + config.set('identity-feature-enabled', 'api_v2_admin', False) services_list = ['compute', 'volume', 'image', @@ -292,7 +300,6 @@ def configure_tempest_update_params(tempest_conf_file, 'data-processing', 'object-storage', 'orchestration'] - sections = config.sections() for service in services_list: if service not in sections: config.add_section(service) diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index e6c6b44f..a41d07c7 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -8,6 +8,9 @@ # http://www.apache.org/licenses/LICENSE-2.0 # +from __future__ import division + +import logging import os import re import shutil @@ -19,11 +22,10 @@ import yaml from functest.core import testcase from functest.opnfv_tests.openstack.tempest import conf_utils from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils """ logging configuration """ -logger = ft_logger.Logger("Tempest").getLogger() +logger = logging.getLogger(__name__) class TempestCommon(testcase.TestCase): @@ -181,7 +183,13 @@ class TempestCommon(testcase.TestCase): try: num_executed = int(num_tests) - int(num_skipped) - success_rate = 100 * int(num_success) / int(num_executed) + try: + self.result = 100 * int(num_success) / int(num_executed) + except ZeroDivisionError: + logger.error("No test has been executed") + self.result = 0 + return + with open(os.path.join(conf_utils.TEMPEST_RESULTS_DIR, "tempest.log"), 'r') as logfile: output = logfile.read() @@ -198,12 +206,10 @@ class TempestCommon(testcase.TestCase): "errors": error_logs, "skipped": skipped_testcase} except Exception: - success_rate = 0 + self.result = 0 - self.result = ft_utils.check_success_rate( - self.case_name, success_rate) - logger.info("Tempest %s success_rate is %s%%, is marked as %s" - % (self.case_name, success_rate, self.result)) + logger.info("Tempest %s success_rate is %s%%" + % (self.case_name, self.result)) def run(self): diff --git a/functest/opnfv_tests/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py index 8bf263eb..8e71bf82 100644 --- a/functest/opnfv_tests/openstack/vping/vping_base.py +++ b/functest/opnfv_tests/openstack/vping/vping_base.py @@ -7,281 +7,194 @@ # # http://www.apache.org/licenses/LICENSE-2.0 +from datetime import datetime +import logging import os -import pprint import time -from datetime import datetime +import uuid -import functest.core.testcase as testcase -import functest.utils.openstack_utils as os_utils +from functest.core.testcase import TestCase +from functest.utils import functest_utils from functest.utils.constants import CONST +from snaps.openstack import create_flavor +from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor +from snaps.openstack.create_network import NetworkSettings, SubnetSettings +from snaps.openstack.tests import openstack_tests +from snaps.openstack.utils import deploy_utils, nova_utils + + +class VPingBase(TestCase): + + """ + Base class for vPing tests that check connectivity between two VMs shared + internal network. + This class is responsible for creating the image, internal network. + """ -class VPingBase(testcase.TestCase): def __init__(self, **kwargs): super(VPingBase, self).__init__(**kwargs) - self.logger = None - self.functest_repo = CONST.dir_repo_functest - self.repo = CONST.dir_vping - self.vm1_name = CONST.vping_vm_name_1 - self.vm2_name = CONST.vping_vm_name_2 - self.vm_boot_timeout = 180 - self.vm_delete_timeout = 100 - self.ping_timeout = CONST.vping_ping_timeout - - self.image_name = CONST.vping_image_name - self.image_filename = CONST.openstack_image_file_name - self.image_format = CONST.openstack_image_disk_format - self.image_username = CONST.openstack_image_username - self.image_password = CONST.openstack_image_password - self.image_path = os.path.join(CONST.dir_functest_data, - self.image_filename) - - self.flavor_name = CONST.vping_vm_flavor + + self.logger = logging.getLogger(self.__class__.__name__) + + self.functest_repo = CONST.__getattribute__('dir_repo_functest') + self.guid = '' + if CONST.__getattribute__('vping_unique_names'): + self.guid = '-' + str(uuid.uuid4()) + + self.os_creds = openstack_tests.get_credentials( + os_env_file=CONST.__getattribute__('openstack_creds')) + + self.repo = CONST.__getattribute__('dir_vping') + + self.creators = list() + self.image_creator = None + self.network_creator = None + self.vm1_creator = None + self.vm2_creator = None + + self.self_cleanup = CONST.__getattribute__('vping_cleanup_objects') + + # Image constants + self.image_name =\ + CONST.__getattribute__('vping_image_name') + self.guid + + # VM constants + self.vm1_name = CONST.__getattribute__('vping_vm_name_1') + self.guid + self.vm2_name = CONST.__getattribute__('vping_vm_name_2') + self.guid + self.vm_boot_timeout = CONST.__getattribute__('vping_vm_boot_timeout') + self.vm_delete_timeout =\ + CONST.__getattribute__('vping_vm_delete_timeout') + self.vm_ssh_connect_timeout = CONST.vping_vm_ssh_connect_timeout + self.ping_timeout = CONST.__getattribute__('vping_ping_timeout') + self.flavor_name = 'vping-flavor' + self.guid # NEUTRON Private Network parameters - self.private_net_name = CONST.vping_private_net_name - self.private_subnet_name = CONST.vping_private_subnet_name - self.private_subnet_cidr = CONST.vping_private_subnet_cidr - self.router_name = CONST.vping_router_name - self.sg_name = CONST.vping_sg_name - self.sg_desc = CONST.vping_sg_desc - self.neutron_client = os_utils.get_neutron_client() - self.glance_client = os_utils.get_glance_client() - self.nova_client = os_utils.get_nova_client() - - def run(self, **kwargs): - if not self.check_repo_exist(): - return testcase.TestCase.EX_RUN_ERROR - - image_id = self.create_image() - if not image_id: - return testcase.TestCase.EX_RUN_ERROR - - flavor = self.get_flavor() - if not flavor: - return testcase.TestCase.EX_RUN_ERROR - - network_id = self.create_network_full() - if not network_id: - return testcase.TestCase.EX_RUN_ERROR - - sg_id = self.create_security_group() - if not sg_id: - return testcase.TestCase.EX_RUN_ERROR - - self.delete_exist_vms() + self.private_net_name =\ + CONST.__getattribute__('vping_private_net_name') + self.guid + self.private_subnet_name =\ + CONST.__getattribute__('vping_private_subnet_name') + self.guid + self.private_subnet_cidr =\ + CONST.__getattribute__('vping_private_subnet_cidr') - self.start_time = time.time() - self.logger.info("vPing Start Time:'%s'" % ( - datetime.fromtimestamp(self.start_time).strftime( - '%Y-%m-%d %H:%M:%S'))) + scenario = functest_utils.get_scenario() - vm1 = self.boot_vm(self.vm1_name, - image_id, - flavor, - network_id, - None, - sg_id) - if not vm1: - return testcase.TestCase.EX_RUN_ERROR - - test_ip = self.get_test_ip(vm1) - vm2 = self.boot_vm(self.vm2_name, - image_id, - flavor, - network_id, - test_ip, - sg_id) - if not vm2: - return testcase.TestCase.EX_RUN_ERROR - - EXIT_CODE = self.do_vping(vm2, test_ip) - if EXIT_CODE == testcase.TestCase.EX_RUN_ERROR: - return EXIT_CODE + self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_ANY + if 'ovs' in scenario or 'fdio' in scenario: + self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE - self.stop_time = time.time() - self.parse_result(EXIT_CODE, - self.start_time, - self.stop_time) - return testcase.TestCase.EX_OK + self.cirros_image_config = None - def boot_vm_preparation(self, config, vmname, test_ip): - pass + # Move this configuration option up for all tests to leverage + if hasattr(CONST, 'snaps_images_cirros'): + self.cirros_image_config = CONST.__getattribute__( + 'snaps_images_cirros') - def do_vping(self, vm, test_ip): - raise NotImplementedError('vping execution is not implemented') + def run(self): + """ + Begins the test execution which should originate from the subclass + """ - def check_repo_exist(self): if not os.path.exists(self.functest_repo): - self.logger.error("Functest repository not found '%s'" - % self.functest_repo) - return False - return True + raise Exception( + "Functest repository not found '%s'" % self.functest_repo) - def create_image(self): - _, image_id = os_utils.get_or_create_image(self.image_name, - self.image_path, - self.image_format) - if not image_id: - return None + self.logger.info('Begin virtual environment setup') - return image_id + self.start_time = time.time() + self.logger.info("vPing Start Time:'%s'" % ( + datetime.fromtimestamp(self.start_time).strftime( + '%Y-%m-%d %H:%M:%S'))) - def get_flavor(self): - try: - flavor = self.nova_client.flavors.find(name=self.flavor_name) - self.logger.info("Using existing Flavor '%s'..." - % self.flavor_name) - return flavor - except: - self.logger.error("Flavor '%s' not found." % self.flavor_name) - self.logger.info("Available flavors are: ") - self.pMsg(self.nova_client.flavor.list()) - return None - - def create_network_full(self): - network_dic = os_utils.create_network_full(self.neutron_client, - self.private_net_name, - self.private_subnet_name, - self.router_name, - self.private_subnet_cidr) - - if not network_dic: - self.logger.error( - "There has been a problem when creating the neutron network") - return None - network_id = network_dic["net_id"] - return network_id - - def create_security_group(self): - sg_id = os_utils.get_security_group_id(self.neutron_client, - self.sg_name) - if sg_id != '': - self.logger.info("Using existing security group '%s'..." - % self.sg_name) + self.__delete_exist_vms() + + image_base_name = self.image_name + '-' + str(self.guid) + os_image_settings = openstack_tests.cirros_image_settings( + image_base_name, image_metadata=self.cirros_image_config) + self.logger.info("Creating image with name: '%s'" % self.image_name) + + self.image_creator = deploy_utils.create_image( + self.os_creds, os_image_settings) + self.creators.append(self.image_creator) + + self.logger.info( + "Creating network with name: '%s'" % self.private_net_name) + self.network_creator = deploy_utils.create_network( + self.os_creds, + NetworkSettings(name=self.private_net_name, + subnet_settings=[SubnetSettings( + name=self.private_subnet_name, + cidr=self.private_subnet_cidr)])) + self.creators.append(self.network_creator) + + self.logger.info( + "Creating flavor with name: '%s'" % self.flavor_name) + flavor_creator = OpenStackFlavor( + self.os_creds, + FlavorSettings(name=self.flavor_name, ram=512, disk=1, vcpus=1, + metadata=self.flavor_metadata)) + flavor_creator.create() + self.creators.append(flavor_creator) + + def _execute(self): + """ + Method called by subclasses after environment has been setup + :return: the exit code + """ + self.logger.info('Begin test execution') + + test_ip = self.vm1_creator.get_port_ip( + self.vm1_creator.instance_settings.port_settings[0].name) + + if self.vm1_creator.vm_active( + block=True) and self.vm2_creator.vm_active(block=True): + result = self._do_vping(self.vm2_creator, test_ip) else: - self.logger.info("Creating security group '%s'..." - % self.sg_name) - SECGROUP = os_utils.create_security_group(self.neutron_client, - self.sg_name, - self.sg_desc) - if not SECGROUP: - self.logger.error("Failed to create the security group...") - return None - - sg_id = SECGROUP['id'] - - self.logger.debug("Security group '%s' with ID=%s created " - "successfully." % (SECGROUP['name'], sg_id)) - - self.logger.debug("Adding ICMP rules in security group '%s'..." - % self.sg_name) - if not os_utils.create_secgroup_rule(self.neutron_client, sg_id, - 'ingress', 'icmp'): - self.logger.error("Failed to create security group rule...") - return None - - self.logger.debug("Adding SSH rules in security group '%s'..." - % self.sg_name) - if not os_utils.create_secgroup_rule(self.neutron_client, sg_id, - 'ingress', 'tcp', - '22', '22'): - self.logger.error("Failed to create security group rule...") - return None - - if not os_utils.create_secgroup_rule( - self.neutron_client, sg_id, 'egress', 'tcp', '22', '22'): - self.logger.error("Failed to create security group rule...") - return None - return sg_id - - def delete_exist_vms(self): - servers = self.nova_client.servers.list() + raise Exception('VMs never became active') + + if result == TestCase.EX_RUN_ERROR: + return TestCase.EX_RUN_ERROR + + self.stop_time = time.time() + self.result = 100 + return TestCase.EX_OK + + def _cleanup(self): + """ + Cleanup all OpenStack objects. Should be called on completion + :return: + """ + if self.self_cleanup: + for creator in reversed(self.creators): + try: + creator.clean() + except Exception as e: + self.logger.error('Unexpected error cleaning - %s', e) + + def _do_vping(self, vm_creator, test_ip): + """ + Method to be implemented by subclasses + Begins the real test after the OpenStack environment has been setup + :param vm_creator: the SNAPS VM instance creator object + :param test_ip: the IP to which the VM needs to issue the ping + :return: T/F + """ + raise NotImplementedError('vping execution is not implemented') + + def __delete_exist_vms(self): + """ + Cleans any existing VMs using the same name. + """ + nova_client = nova_utils.nova_client(self.os_creds) + servers = nova_client.servers.list() for server in servers: if server.name == self.vm1_name or server.name == self.vm2_name: self.logger.info("Deleting instance %s..." % server.name) server.delete() - def boot_vm(self, vmname, image_id, flavor, network_id, test_ip, sg_id): - config = dict() - config['name'] = vmname - config['flavor'] = flavor - config['image'] = image_id - config['nics'] = [{"net-id": network_id}] - self.boot_vm_preparation(config, vmname, test_ip) - self.logger.info("Creating instance '%s'..." % vmname) - self.logger.debug("Configuration: %s" % config) - vm = self.nova_client.servers.create(**config) - - # wait until VM status is active - if not self.waitVmActive(self.nova_client, vm): - vm_status = os_utils.get_instance_status(self.nova_client, vm) - self.logger.error("Instance '%s' cannot be booted. Status is '%s'" - % (vmname, vm_status)) - return None - else: - self.logger.info("Instance '%s' is ACTIVE." % vmname) - - self.add_secgroup(vmname, vm.id, sg_id) - - return vm - - def waitVmActive(self, nova, vm): - # sleep and wait for VM status change - sleep_time = 3 - count = self.vm_boot_timeout / sleep_time - while True: - status = os_utils.get_instance_status(nova, vm) - self.logger.debug("Status: %s" % status) - if status == "ACTIVE": - return True - if status == "ERROR" or status == "error": - return False - if count == 0: - self.logger.debug("Booting a VM timed out...") - return False - count -= 1 - time.sleep(sleep_time) - return False - - def add_secgroup(self, vmname, vm_id, sg_id): - self.logger.info("Adding '%s' to security group '%s'..." % - (vmname, self.sg_name)) - os_utils.add_secgroup_to_instance(self.nova_client, vm_id, sg_id) - - def get_test_ip(self, vm): - test_ip = vm.networks.get(self.private_net_name)[0] - self.logger.debug("Instance '%s' got %s" % (vm.name, test_ip)) - return test_ip - - def parse_result(self, code, start_time, stop_time): - test_status = "FAIL" - if code == 0: - self.logger.info("vPing OK") - duration = round(stop_time - start_time, 1) - self.logger.info("vPing duration:'%s'" % duration) - test_status = "PASS" - elif code == -2: - duration = 0 - self.logger.info("Userdata is not supported in nova boot. " - "Aborting test...") - else: - duration = 0 - self.logger.error("vPing FAILED") - - self.details = {'timestart': start_time, - 'duration': duration, - 'status': test_status} - self.result = test_status - - @staticmethod - def pMsg(msg): - """pretty printing""" - pprint.PrettyPrinter(indent=4).pprint(msg) - class VPingMain(object): + def __init__(self, vping_cls): self.vping = vping_cls() @@ -291,6 +204,6 @@ class VPingMain(object): if result != VPingBase.EX_OK: return result if kwargs['report']: - return self.vping.push_to_db() - except Exception: + return self.vping.publish_report() + except: return VPingBase.EX_RUN_ERROR diff --git a/functest/opnfv_tests/openstack/vping/vping_ssh.py b/functest/opnfv_tests/openstack/vping/vping_ssh.py index c26c4e0c..0ad77402 100755 --- a/functest/opnfv_tests/openstack/vping/vping_ssh.py +++ b/functest/opnfv_tests/openstack/vping/vping_ssh.py @@ -7,124 +7,161 @@ # # http://www.apache.org/licenses/LICENSE-2.0 +import argparse import os -import re +from scp import SCPClient import sys import time -import argparse -import paramiko -from scp import SCPClient - -import functest.utils.functest_logger as ft_logger -import functest.utils.openstack_utils as os_utils +from snaps.openstack.create_instance import FloatingIpSettings, \ + VmInstanceSettings +from snaps.openstack.create_keypairs import KeypairSettings +from snaps.openstack.create_network import PortSettings +from snaps.openstack.create_router import RouterSettings +from snaps.openstack.create_security_group import Direction, Protocol, \ + SecurityGroupSettings, SecurityGroupRuleSettings +from snaps.openstack.utils import deploy_utils + +from functest.core.testcase import TestCase +from functest.opnfv_tests.openstack.snaps import snaps_utils +from functest.utils.constants import CONST import vping_base -import functest.core.testcase as testcase class VPingSSH(vping_base.VPingBase): + """ + Class to execute the vPing test using a Floating IP to connect to one VM + to issue the ping command to the second + """ def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = "vping_ssh" super(VPingSSH, self).__init__(**kwargs) - self.logger = ft_logger.Logger(self.case_name).getLogger() - - def do_vping(self, vm, test_ip): - floatip = self.add_float_ip(vm) - if not floatip: - return testcase.TestCase.EX_RUN_ERROR - ssh = self.establish_ssh(vm, floatip) - if not ssh: - return testcase.TestCase.EX_RUN_ERROR - if not self.transfer_ping_script(ssh, floatip): - return testcase.TestCase.EX_RUN_ERROR - return self.do_vping_ssh(ssh, test_ip) - - def add_float_ip(self, vm): - self.logger.info("Creating floating IP for VM '%s'..." % self.vm2_name) - floatip_dic = os_utils.create_floating_ip(self.neutron_client) - floatip = floatip_dic['fip_addr'] - - if floatip is None: - self.logger.error("Cannot create floating IP.") - return None - self.logger.info("Floating IP created: '%s'" % floatip) - - self.logger.info("Associating floating ip: '%s' to VM '%s' " - % (floatip, self.vm2_name)) - if not os_utils.add_floating_ip(self.nova_client, vm.id, floatip): - self.logger.error("Cannot associate floating IP to VM.") - return None - - return floatip - - def establish_ssh(self, vm, floatip): - self.logger.info("Trying to establish SSH connection to %s..." - % floatip) - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - - timeout = 50 - nolease = False - got_ip = False - discover_count = 0 - cidr_first_octet = self.private_subnet_cidr.split('.')[0] - while timeout > 0: - try: - ssh.connect(floatip, username=self.image_username, - password=self.image_password, timeout=2) - self.logger.debug("SSH connection established to %s." - % floatip) - break - except: - self.logger.debug("Waiting for %s..." % floatip) - time.sleep(6) - timeout -= 1 - - console_log = vm.get_console_output() - - # print each "Sending discover" captured on the console log - if (len(re.findall("Sending discover", console_log)) > - discover_count and not got_ip): - discover_count += 1 - self.logger.debug("Console-log '%s': Sending discover..." - % self.vm2_name) - - # check if eth0 got an ip,the line looks like this: - # "inet addr:192.168.".... - # if the dhcp agent fails to assing ip, this line will not appear - if "inet addr:" + cidr_first_octet in console_log and not got_ip: - got_ip = True - self.logger.debug("The instance '%s' succeeded to get the IP " - "from the dhcp agent." % self.vm2_name) - - # if dhcp not work,it shows "No lease, failing".The test will fail - if ("No lease, failing" in console_log and - not nolease and - not got_ip): - nolease = True - self.logger.debug("Console-log '%s': No lease, failing..." - % self.vm2_name) - self.logger.info("The instance failed to get an IP from DHCP " - "agent. The test will probably timeout...") - - if timeout == 0: # 300 sec timeout (5 min) - self.logger.error("Cannot establish connection to IP '%s'. " - "Aborting" % floatip) - return None - return ssh - - def transfer_ping_script(self, ssh, floatip): - self.logger.info("Trying to transfer ping.sh to %s..." % floatip) + + self.kp_name = CONST.__getattribute__('vping_keypair_name') + self.guid + self.kp_priv_file = CONST.__getattribute__('vping_keypair_priv_file') + self.kp_pub_file = CONST.__getattribute__('vping_keypair_pub_file') + self.router_name =\ + CONST.__getattribute__('vping_router_name') + self.guid + self.sg_name = CONST.__getattribute__('vping_sg_name') + self.guid + self.sg_desc = CONST.__getattribute__('vping_sg_desc') + + self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds) + + def run(self): + """ + Sets up the OpenStack keypair, router, security group, and VM instance + objects then validates the ping. + :return: the exit code from the super.execute() method + """ + try: + super(VPingSSH, self).run() + + self.logger.info("Creating keypair with name: '%s'" % self.kp_name) + kp_creator = deploy_utils.create_keypair( + self.os_creds, + KeypairSettings(name=self.kp_name, + private_filepath=self.kp_priv_file, + public_filepath=self.kp_pub_file)) + self.creators.append(kp_creator) + + # Creating router to external network + self.logger.info("Creating router with name: '%s'" + % self.router_name) + net_set = self.network_creator.network_settings + sub_set = [net_set.subnet_settings[0].name] + router_creator = deploy_utils.create_router( + self.os_creds, + RouterSettings( + name=self.router_name, + external_gateway=self.ext_net_name, + internal_subnets=sub_set)) + self.creators.append(router_creator) + + # Creating Instance 1 + port1_settings = PortSettings( + name=self.vm1_name + '-vPingPort', + network_name=self.network_creator.network_settings.name) + instance1_settings = VmInstanceSettings( + name=self.vm1_name, flavor=self.flavor_name, + vm_boot_timeout=self.vm_boot_timeout, + vm_delete_timeout=self.vm_delete_timeout, + ssh_connect_timeout=self.vm_ssh_connect_timeout, + port_settings=[port1_settings]) + + self.logger.info( + "Creating VM 1 instance with name: '%s'" + % instance1_settings.name) + self.vm1_creator = deploy_utils.create_vm_instance( + self.os_creds, + instance1_settings, + self.image_creator.image_settings, + keypair_creator=kp_creator) + self.creators.append(self.vm1_creator) + + # Creating Instance 2 + sg_creator = self.__create_security_group() + self.creators.append(sg_creator) + + port2_settings = PortSettings( + name=self.vm2_name + '-vPingPort', + network_name=self.network_creator.network_settings.name) + instance2_settings = VmInstanceSettings( + name=self.vm2_name, flavor=self.flavor_name, + vm_boot_timeout=self.vm_boot_timeout, + vm_delete_timeout=self.vm_delete_timeout, + ssh_connect_timeout=self.vm_ssh_connect_timeout, + port_settings=[port2_settings], + security_group_names=[sg_creator.sec_grp_settings.name], + floating_ip_settings=[FloatingIpSettings( + name=self.vm2_name + '-FIPName', + port_name=port2_settings.name, + router_name=router_creator.router_settings.name)]) + + self.logger.info( + "Creating VM 2 instance with name: '%s'" + % instance2_settings.name) + self.vm2_creator = deploy_utils.create_vm_instance( + self.os_creds, + instance2_settings, + self.image_creator.image_settings, + keypair_creator=kp_creator) + self.creators.append(self.vm2_creator) + + return self._execute() + except Exception as e: + self.logger.error('Unexpected error running test - ' + e.message) + return TestCase.EX_RUN_ERROR + finally: + self._cleanup() + + def _do_vping(self, vm_creator, test_ip): + """ + Override from super + """ + if vm_creator.vm_ssh_active(block=True): + ssh = vm_creator.ssh_client() + if not self.__transfer_ping_script(ssh): + return TestCase.EX_RUN_ERROR + return self.__do_vping_ssh(ssh, test_ip) + else: + return -1 + + def __transfer_ping_script(self, ssh): + """ + Uses SCP to copy the ping script via the SSH client + :param ssh: the SSH client + :return: + """ + self.logger.info("Trying to transfer ping.sh") scp = SCPClient(ssh.get_transport()) local_path = self.functest_repo + "/" + self.repo ping_script = os.path.join(local_path, "ping.sh") try: scp.put(ping_script, "~/") except: - self.logger.error("Cannot SCP the file '%s' to VM '%s'" - % (ping_script, floatip)) + self.logger.error("Cannot SCP the file '%s'" % ping_script) return False cmd = 'chmod 755 ~/ping.sh' @@ -134,8 +171,14 @@ class VPingSSH(vping_base.VPingBase): return True - def do_vping_ssh(self, ssh, test_ip): - EXIT_CODE = -1 + def __do_vping_ssh(self, ssh, test_ip): + """ + Pings the test_ip via the SSH client + :param ssh: the SSH client used to issue the ping command + :param test_ip: the IP for the ping command to use + :return: exit_code (int) + """ + exit_code = TestCase.EX_TESTCASE_FAILED self.logger.info("Waiting for ping...") sec = 0 @@ -150,7 +193,7 @@ class VPingSSH(vping_base.VPingBase): for line in output: if "vPing OK" in line: self.logger.info("vPing detected!") - EXIT_CODE = 0 + exit_code = TestCase.EX_OK flag = True break @@ -162,7 +205,35 @@ class VPingSSH(vping_base.VPingBase): break self.logger.debug("Pinging %s. Waiting for response..." % test_ip) sec += 1 - return EXIT_CODE + return exit_code + + def __create_security_group(self): + """ + Configures and deploys an OpenStack security group object + :return: the creator object + """ + sg_rules = list() + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name=self.sg_name, + direction=Direction.ingress, + protocol=Protocol.icmp)) + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name=self.sg_name, + direction=Direction.ingress, + protocol=Protocol.tcp, port_range_min=22, + port_range_max=22)) + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name=self.sg_name, + direction=Direction.egress, + protocol=Protocol.tcp, port_range_min=22, + port_range_max=22)) + + self.logger.info("Security group with name: '%s'" % self.sg_name) + return deploy_utils.create_security_group(self.os_creds, + SecurityGroupSettings( + name=self.sg_name, + description=self.sg_desc, + rule_settings=sg_rules)) if __name__ == '__main__': diff --git a/functest/opnfv_tests/openstack/vping/vping_userdata.py b/functest/opnfv_tests/openstack/vping/vping_userdata.py index 1b00ca23..8ea9be84 100755 --- a/functest/opnfv_tests/openstack/vping/vping_userdata.py +++ b/functest/opnfv_tests/openstack/vping/vping_userdata.py @@ -7,70 +7,141 @@ # # http://www.apache.org/licenses/LICENSE-2.0 +import argparse import sys import time -import argparse +from functest.core.testcase import TestCase + +from snaps.openstack.utils import deploy_utils +from snaps.openstack.create_instance import VmInstanceSettings +from snaps.openstack.create_network import PortSettings -import functest.utils.functest_logger as ft_logger import vping_base class VPingUserdata(vping_base.VPingBase): + """ + Class to execute the vPing test using userdata and the VM's console + """ def __init__(self, **kwargs): if "case_name" not in kwargs: kwargs["case_name"] = "vping_userdata" super(VPingUserdata, self).__init__(**kwargs) - self.logger = ft_logger.Logger(self.case_name).getLogger() - - def boot_vm_preparation(self, config, vmname, test_ip): - config['config_drive'] = True - if vmname == self.vm2_name: - u = ("#!/bin/sh\n\n" - "while true; do\n" - " ping -c 1 %s 2>&1 >/dev/null\n" - " RES=$?\n" - " if [ \"Z$RES\" = \"Z0\" ] ; then\n" - " echo 'vPing OK'\n" - " break\n" - " else\n" - " echo 'vPing KO'\n" - " fi\n" - " sleep 1\n" - "done\n" % test_ip) - config['userdata'] = u - - def do_vping(self, vm, test_ip): + + def run(self): + """ + Sets up the OpenStack VM instance objects then executes the ping and + validates. + :return: the exit code from the super.execute() method + """ + try: + super(VPingUserdata, self).run() + + # Creating Instance 1 + port1_settings = PortSettings( + name=self.vm1_name + '-vPingPort', + network_name=self.network_creator.network_settings.name) + instance1_settings = VmInstanceSettings( + name=self.vm1_name, + flavor=self.flavor_name, + vm_boot_timeout=self.vm_boot_timeout, + port_settings=[port1_settings]) + + self.logger.info( + "Creating VM 1 instance with name: '%s'" + % instance1_settings.name) + self.vm1_creator = deploy_utils.create_vm_instance( + self.os_creds, instance1_settings, + self.image_creator.image_settings) + self.creators.append(self.vm1_creator) + + userdata = _get_userdata( + self.vm1_creator.get_port_ip(port1_settings.name)) + if userdata: + # Creating Instance 2 + port2_settings = PortSettings( + name=self.vm2_name + '-vPingPort', + network_name=self.network_creator.network_settings.name) + instance2_settings = VmInstanceSettings( + name=self.vm2_name, + flavor=self.flavor_name, + vm_boot_timeout=self.vm_boot_timeout, + port_settings=[port2_settings], + userdata=userdata) + + self.logger.info( + "Creating VM 2 instance with name: '%s'" + % instance2_settings.name) + self.vm2_creator = deploy_utils.create_vm_instance( + self.os_creds, instance2_settings, + self.image_creator.image_settings) + self.creators.append(self.vm2_creator) + else: + raise Exception('Userdata is None') + + return self._execute() + + finally: + self._cleanup() + + def _do_vping(self, vm_creator, test_ip): + """ + Override from super + """ self.logger.info("Waiting for ping...") - EXIT_CODE = -1 + exit_code = -1 sec = 0 tries = 0 while True: time.sleep(1) - p_console = vm.get_console_output() + p_console = vm_creator.get_vm_inst().get_console_output() if "vPing OK" in p_console: self.logger.info("vPing detected!") - EXIT_CODE = 0 + exit_code = TestCase.EX_OK break elif "failed to read iid from metadata" in p_console or tries > 5: - EXIT_CODE = -2 + exit_code = TestCase.EX_TESTCASE_FAILED break elif sec == self.ping_timeout: self.logger.info("Timeout reached.") break elif sec % 10 == 0: if "request failed" in p_console: - self.logger.debug("It seems userdata is not supported " - "in nova boot. Waiting a bit...") + self.logger.debug( + "It seems userdata is not supported in nova boot. " + + "Waiting a bit...") tries += 1 else: - self.logger.debug("Pinging %s. Waiting for response..." - % test_ip) + self.logger.debug( + "Pinging %s. Waiting for response..." % test_ip) sec += 1 - return EXIT_CODE + return exit_code + + +def _get_userdata(test_ip): + """ + Returns the post VM creation script to be added into the VM's userdata + :param test_ip: the IP value to substitute into the script + :return: the bash script contents + """ + if test_ip: + return ("#!/bin/sh\n\n" + "while true; do\n" + " ping -c 1 %s 2>&1 >/dev/null\n" + " RES=$?\n" + " if [ \"Z$RES\" = \"Z0\" ] ; then\n" + " echo 'vPing OK'\n" + " break\n" + " else\n" + " echo 'vPing KO'\n" + " fi\n" + " sleep 1\n" + "done\n" % test_ip) + return None if __name__ == '__main__': diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py index 6f4acf6d..6f586b7a 100755 --- a/functest/opnfv_tests/sdn/odl/odl.py +++ b/functest/opnfv_tests/sdn/odl/odl.py @@ -16,21 +16,23 @@ Example: $ python odl.py """ +from __future__ import division + import argparse import errno import fileinput +import logging import os import re import sys -import urlparse import robot.api from robot.errors import RobotError import robot.run from robot.utils.robottime import timestamp_to_secs +from six.moves import urllib from functest.core import testcase -import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as op_utils __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>" @@ -70,7 +72,7 @@ class ODLTests(testcase.TestCase): "csit/suites/integration/basic") default_suites = [basic_suite_dir, neutron_suite_dir] res_dir = '/home/opnfv/functest/results/odl/' - logger = ft_logger.Logger("opendaylight").getLogger() + __logger = logging.getLogger(__name__) @classmethod def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"): @@ -85,13 +87,13 @@ class ODLTests(testcase.TestCase): try: for line in fileinput.input(odl_variables_files, inplace=True): - print re.sub("AUTH = .*", + print(re.sub("AUTH = .*", ("AUTH = [u'" + odlusername + "', u'" + odlpassword + "']"), - line.rstrip()) + line.rstrip())) return True except Exception as ex: # pylint: disable=broad-except - cls.logger.error("Cannot set ODL creds: %s", str(ex)) + cls.__logger.error("Cannot set ODL creds: %s", str(ex)) return False def parse_results(self): @@ -100,7 +102,12 @@ class ODLTests(testcase.TestCase): result = robot.api.ExecutionResult(xml_file) visitor = ODLResultVisitor() result.visit(visitor) - self.result = result.suite.status + try: + self.result = 100 * ( + result.suite.statistics.critical.passed / + result.suite.statistics.critical.total) + except ZeroDivisionError: + self.__logger.error("No test has been ran") self.start_time = timestamp_to_secs(result.suite.starttime) self.stop_time = timestamp_to_secs(result.suite.endtime) self.details = {} @@ -143,7 +150,7 @@ class ODLTests(testcase.TestCase): odlusername = kwargs['odlusername'] odlpassword = kwargs['odlpassword'] osauthurl = kwargs['osauthurl'] - keystoneip = urlparse.urlparse(osauthurl).hostname + keystoneip = urllib.parse.urlparse(osauthurl).hostname variables = ['KEYSTONE:' + keystoneip, 'NEUTRON:' + kwargs['neutronip'], 'OS_AUTH_URL:"' + osauthurl + '"', @@ -154,15 +161,15 @@ class ODLTests(testcase.TestCase): 'PORT:' + kwargs['odlwebport'], 'RESTCONFPORT:' + kwargs['odlrestconfport']] except KeyError as ex: - self.logger.error("Cannot run ODL testcases. Please check " - "%s", str(ex)) + self.__logger.error("Cannot run ODL testcases. Please check " + "%s", str(ex)) return self.EX_RUN_ERROR if self.set_robotframework_vars(odlusername, odlpassword): try: os.makedirs(self.res_dir) except OSError as ex: if ex.errno != errno.EEXIST: - self.logger.exception( + self.__logger.exception( "Cannot create %s", self.res_dir) return self.EX_RUN_ERROR stdout_file = os.path.join(self.res_dir, 'stdout.txt') @@ -174,19 +181,19 @@ class ODLTests(testcase.TestCase): report='NONE', stdout=stdout) stdout.seek(0, 0) - self.logger.info("\n" + stdout.read()) - self.logger.info("ODL results were successfully generated") + self.__logger.info("\n" + stdout.read()) + self.__logger.info("ODL results were successfully generated") try: self.parse_results() - self.logger.info("ODL results were successfully parsed") + self.__logger.info("ODL results were successfully parsed") except RobotError as ex: - self.logger.error("Run tests before publishing: %s", - ex.message) + self.__logger.error("Run tests before publishing: %s", + ex.message) return self.EX_RUN_ERROR try: os.remove(stdout_file) except OSError: - self.logger.warning("Cannot remove %s", stdout_file) + self.__logger.warning("Cannot remove %s", stdout_file) return self.EX_OK else: return self.EX_RUN_ERROR @@ -211,7 +218,7 @@ class ODLTests(testcase.TestCase): except KeyError: pass neutron_url = op_utils.get_endpoint(service_type='network') - kwargs = {'neutronip': urlparse.urlparse(neutron_url).hostname} + kwargs = {'neutronip': urllib.parse.urlparse(neutron_url).hostname} kwargs['odlip'] = kwargs['neutronip'] kwargs['odlwebport'] = '8080' kwargs['odlrestconfport'] = '8181' @@ -237,12 +244,12 @@ class ODLTests(testcase.TestCase): else: kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP'] except KeyError as ex: - self.logger.error("Cannot run ODL testcases. " - "Please check env var: " - "%s", str(ex)) + self.__logger.error("Cannot run ODL testcases. " + "Please check env var: " + "%s", str(ex)) return self.EX_RUN_ERROR except Exception: # pylint: disable=broad-except - self.logger.exception("Cannot run ODL testcases.") + self.__logger.exception("Cannot run ODL testcases.") return self.EX_RUN_ERROR return self.main(suites, **kwargs) @@ -301,6 +308,7 @@ class ODLParser(object): # pylint: disable=too-few-public-methods if __name__ == '__main__': + logging.basicConfig() ODL = ODLTests() PARSER = ODLParser() ARGS = PARSER.parse_args(sys.argv[1:]) diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py index 4d489d67..5dfff036 100644 --- a/functest/opnfv_tests/sdn/onos/onos.py +++ b/functest/opnfv_tests/sdn/onos/onos.py @@ -7,6 +7,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 +import logging import os import re import subprocess @@ -16,7 +17,6 @@ import urlparse from functest.core import testcase from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as openstack_utils @@ -25,12 +25,12 @@ class OnosBase(testcase.TestCase): onos_repo_path = CONST.__getattribute__('dir_repo_onos') onos_sfc_image_name = CONST.__getattribute__('onos_sfc_image_name') onos_sfc_image_path = os.path.join( - CONST.__getattribute__('dir_functest_data'), + CONST.__getattribute__('dir_functest_images'), CONST.__getattribute__('onos_sfc_image_file_name')) onos_sfc_path = os.path.join(CONST.__getattribute__('dir_repo_functest'), CONST.__getattribute__('dir_onos_sfc')) installer_type = CONST.__getattribute__('INSTALLER_TYPE') - logger = ft_logger.Logger(__name__).getLogger() + logger = logging.getLogger(__name__) def __init__(self, **kwargs): if "case_name" not in kwargs: diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc.py b/functest/opnfv_tests/sdn/onos/sfc/sfc.py index 22412270..0155d24d 100755 --- a/functest/opnfv_tests/sdn/onos/sfc/sfc.py +++ b/functest/opnfv_tests/sdn/onos/sfc/sfc.py @@ -1,4 +1,3 @@ -"""Script to Test the SFC scenarios in ONOS.""" # !/usr/bin/python # # Copyright (c) CREATED5 All rights reserved @@ -22,13 +21,14 @@ # Testcase 7 : Cleanup # ########################################################################### # +"""Script to Test the SFC scenarios in ONOS.""" +import logging import time -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils from sfc_onos import SfcOnos -logger = ft_logger.Logger("sfc").getLogger() +logger = logging.getLogger(__name__) Sfc_obj = SfcOnos() OK = 200 @@ -174,4 +174,5 @@ def main(): if __name__ == '__main__': + logging.basicConfig() main() diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py index c2198690..1101f239 100644 --- a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py +++ b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py @@ -1,3 +1,4 @@ +import logging import os import re import time @@ -8,8 +9,6 @@ from multiprocessing import Process from multiprocessing import Queue from pexpect import pxssh -import functest.utils.functest_logger as ft_logger - from functest.utils.constants import CONST OK = 200 @@ -23,7 +22,7 @@ class SfcOnos(object): def __init__(self): """Initialization of variables.""" - self.logger = ft_logger.Logger("sfc_fun").getLogger() + self.logger = logging.getLogger(__name__) self.osver = "v2.0" self.token_id = 0 self.net_id = 0 diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py b/functest/opnfv_tests/sdn/onos/teston/adapters/client.py index 81d5f7d7..a88d2f06 100644 --- a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py +++ b/functest/opnfv_tests/sdn/onos/teston/adapters/client.py @@ -11,17 +11,17 @@ Description: # """ import json +import logging import pexpect import requests import time from environment import Environment -import functest.utils.functest_logger as ft_logger class Client(Environment): - logger = ft_logger.Logger("client").getLogger() + logger = logging.getLogger(__name__) def __init__(self): Environment.__init__(self) diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py b/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py index 3786945d..dfaa5cc1 100644 --- a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py +++ b/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py @@ -13,17 +13,17 @@ Description: # http://www.apache.org/licenses/LICENSE-2.0 # """ +import logging import os import pexpect import re from foundation import Foundation -import functest.utils.functest_logger as ft_logger class Connection(Foundation): - logger = ft_logger.Logger("connection").getLogger() + logger = logging.getLogger(__name__) def __init__(self): Foundation.__init__(self) diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py b/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py index 046a821d..cb75b5c3 100644 --- a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py +++ b/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py @@ -15,6 +15,7 @@ Description: # """ +import logging import pexpect import pxssh import re @@ -23,12 +24,11 @@ import sys import time from connection import Connection -import functest.utils.functest_logger as ft_logger class Environment(Connection): - logger = ft_logger.Logger("environment").getLogger() + logger = logging.getLogger(__name__) def __init__(self): Connection.__init__(self) diff --git a/functest/opnfv_tests/vnf/aaa/aaa.py b/functest/opnfv_tests/vnf/aaa/aaa.py index 9c94cfb1..0030256c 100755 --- a/functest/opnfv_tests/vnf/aaa/aaa.py +++ b/functest/opnfv_tests/vnf/aaa/aaa.py @@ -7,18 +7,18 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 +import logging import sys import argparse import functest.core.testcase as testcase -import functest.core.vnf_base as vnf_base -import functest.utils.functest_logger as ft_logger +import functest.core.vnf as vnf -class AaaVnf(vnf_base.VnfOnBoardingBase): +class AaaVnf(vnf.VnfOnBoarding): - logger = ft_logger.Logger("VNF AAA").getLogger() + logger = logging.getLogger(__name__) def __init__(self, **kwargs): if "case_name" not in kwargs: @@ -60,6 +60,7 @@ class AaaVnf(vnf_base.VnfOnBoardingBase): if __name__ == '__main__': + logging.basicConfig() parser = argparse.ArgumentParser() args = vars(parser.parse_args()) aaa_vnf = AaaVnf() diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py index 494633f4..42d31e3b 100644 --- a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py +++ b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py @@ -7,21 +7,21 @@ # # http://www.apache.org/licenses/LICENSE-2.0 import json +import logging import os import shutil import requests -import functest.core.vnf_base as vnf_base +import functest.core.vnf as vnf from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils -class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase): +class ClearwaterOnBoardingBase(vnf.VnfOnBoarding): def __init__(self, **kwargs): - self.logger = ft_logger.Logger(__name__).getLogger() + self.logger = logging.getLogger(__name__) super(ClearwaterOnBoardingBase, self).__init__(**kwargs) self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf', 'ims') self.data_dir = CONST.dir_ims_data diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py index 0e6d4797..ba4c5790 100644 --- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py +++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py @@ -7,6 +7,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 +import logging import os import sys import time @@ -18,7 +19,6 @@ from functest.opnfv_tests.vnf.ims.clearwater import Clearwater import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base from functest.opnfv_tests.vnf.ims.orchestrator_cloudify import Orchestrator from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils @@ -29,7 +29,7 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase): if "case_name" not in kwargs: kwargs["case_name"] = "cloudify_ims" super(CloudifyIms, self).__init__(**kwargs) - self.logger = ft_logger.Logger(__name__).getLogger() + self.logger = logging.getLogger(__name__) # Retrieve the configuration try: diff --git a/functest/opnfv_tests/vnf/ims/opera_ims.py b/functest/opnfv_tests/vnf/ims/opera_ims.py index a46f9d71..8c33d16e 100644 --- a/functest/opnfv_tests/vnf/ims/opera_ims.py +++ b/functest/opnfv_tests/vnf/ims/opera_ims.py @@ -8,6 +8,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 import json +import logging import os import time @@ -15,16 +16,15 @@ from opera import openo_connect import requests import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base -from functest.utils.constants import CONST -import functest.utils.functest_logger as ft_logger class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase): - def __init__(self, project='functest', case_name='opera_ims', - repo=CONST.dir_repo_opera, cmd=''): - super(OperaIms, self).__init__(project, case_name, repo, cmd) - self.logger = ft_logger.Logger(__name__).getLogger() + def __init__(self, **kwargs): + if "case_name" not in kwargs: + kwargs["case_name"] = "opera_ims" + super(OperaIms, self).__init__(**kwargs) + self.logger = logging.getLogger(__name__) self.ellis_file = os.path.join(self.result_dir, 'ellis.info') self.live_test_file = os.path.join(self.result_dir, 'live_test_report.json') @@ -64,27 +64,27 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase): self.logger.info('VNFM IP: %s', vnfm_ip) vnf_status_url = 'http://{0}:5000/api/v1/model/status'.format(vnfm_ip) vnf_alive = False - retry = 15 + retry = 40 self.logger.info('Check the VNF status') while retry > 0: - rq = requests.get(vnf_status_url) + rq = requests.get(vnf_status_url, timeout=90) response = rq.json() vnf_alive = response['vnf_alive'] msg = response['msg'] self.logger.info(msg) if vnf_alive: break - self.logger.info('check again in one minute...') + self.logger.info('check again in one and half a minute...') retry = retry - 1 - time.sleep(60) + time.sleep(90) if not vnf_alive: raise Exception('VNF failed to start: {0}'.format(msg)) ellis_config_url = ('http://{0}:5000/api/v1/model/ellis/configure' .format(vnfm_ip)) - rq = requests.get(ellis_config_url, timeout=60) + rq = requests.get(ellis_config_url, timeout=90) if rq.json() and not rq.json()['ellis_ok']: self.logger.error(rq.json()['data']) raise Exception('Failed to configure Ellis') @@ -92,7 +92,7 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase): self.logger.info('Get Clearwater deployment detail') vnf_info_url = ('http://{0}:5000/api/v1/model/output' .format(vnfm_ip)) - rq = requests.get(vnf_info_url, timeout=60) + rq = requests.get(vnf_info_url, timeout=90) data = rq.json()['data'] self.logger.info(data) bono_ip = data['bono_ip'] diff --git a/functest/opnfv_tests/vnf/ims/orchestra_ims.py b/functest/opnfv_tests/vnf/ims/orchestra_ims.py index 351c5fbe..6f341970 100755 --- a/functest/opnfv_tests/vnf/ims/orchestra_ims.py +++ b/functest/opnfv_tests/vnf/ims/orchestra_ims.py @@ -8,16 +8,16 @@ # http://www.apache.org/licenses/LICENSE-2.0 import json +import logging +import os import socket import sys import time import yaml -import functest.core.vnf_base as vnf_base -import functest.utils.functest_logger as ft_logger +import functest.core.vnf as vnf import functest.utils.functest_utils as ft_utils import functest.utils.openstack_utils as os_utils -import os from functest.utils.constants import CONST from org.openbaton.cli.agents.agents import MainAgent @@ -76,7 +76,7 @@ def servertest(host, port): return True -class ImsVnf(vnf_base.VnfOnBoardingBase): +class ImsVnf(vnf.VnfOnBoarding): def __init__(self, project='functest', case_name='orchestra_ims', repo='', cmd=''): @@ -87,7 +87,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase): self.ob_port = "8080" self.ob_ip = "localhost" self.ob_instance_id = "" - self.logger = ft_logger.Logger("orchestra_ims").getLogger() + self.logger = logging.getLogger(__name__) self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf/ims/') self.data_dir = CONST.dir_ims_data self.test_dir = CONST.dir_repo_vims_test @@ -495,6 +495,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase): if __name__ == '__main__': + logging.basicConfig() test = ImsVnf() test.deploy_orchestrator() test.deploy_vnf() diff --git a/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py index 82a9dca0..4ceeb25f 100644 --- a/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py +++ b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py @@ -11,6 +11,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 ######################################################################## +import logging import os import shutil import subprocess32 as subprocess @@ -18,8 +19,6 @@ import yaml from git import Repo -import functest.utils.functest_logger as ft_logger - class Orchestrator(object): @@ -29,7 +28,7 @@ class Orchestrator(object): self.input_file = 'inputs.yaml' self.manager_blueprint = False self.config = inputs - self.logger = ft_logger.Logger("Orchestrator").getLogger() + self.logger = logging.getLogger(__name__) self.manager_up = False def set_credentials(self, username, password, tenant_name, auth_url): diff --git a/functest/tests/unit/ci/test_generate_report.py b/functest/tests/unit/ci/test_generate_report.py deleted file mode 100644 index 2225586f..00000000 --- a/functest/tests/unit/ci/test_generate_report.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python - -# 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 logging -import unittest -import urllib2 - -import mock - -from functest.ci import generate_report as gen_report -from functest.tests.unit import test_utils -from functest.utils import functest_utils as ft_utils -from functest.utils.constants import CONST - - -class GenerateReportTesting(unittest.TestCase): - - logging.disable(logging.CRITICAL) - - def test_init(self): - test_array = gen_report.init() - self.assertEqual(test_array, []) - - @mock.patch('functest.ci.generate_report.urllib2.urlopen', - side_effect=urllib2.URLError('no host given')) - def test_get_results_from_db_fail(self, mock_method): - url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(), - CONST.BUILD_TAG) - self.assertIsNone(gen_report.get_results_from_db()) - mock_method.assert_called_once_with(url) - - @mock.patch('functest.ci.generate_report.urllib2.urlopen', - return_value={'results': []}) - def test_get_results_from_db_success(self, mock_method): - url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(), - CONST.BUILD_TAG) - self.assertEqual(gen_report.get_results_from_db(), None) - mock_method.assert_called_once_with(url) - - def test_get_data(self): - self.assertIsInstance(gen_report.get_data({'result': ''}, ''), dict) - - def test_print_line_with_ci_run(self): - CONST.IS_CI_RUN = True - w1 = 'test_print_line' - test_str = ("| %s| %s| %s| %s| %s|\n" - % (w1.ljust(gen_report.COL_1_LEN - 1), - ''.ljust(gen_report.COL_2_LEN - 1), - ''.ljust(gen_report.COL_3_LEN - 1), - ''.ljust(gen_report.COL_4_LEN - 1), - ''.ljust(gen_report.COL_5_LEN - 1))) - self.assertEqual(gen_report.print_line(w1), test_str) - - def test_print_line_without_ci_run(self): - CONST.IS_CI_RUN = False - w1 = 'test_print_line' - test_str = ("| %s| %s| %s| %s|\n" - % (w1.ljust(gen_report.COL_1_LEN - 1), - ''.ljust(gen_report.COL_2_LEN - 1), - ''.ljust(gen_report.COL_3_LEN - 1), - ''.ljust(gen_report.COL_4_LEN - 1))) - self.assertEqual(gen_report.print_line(w1), test_str) - - def test_print_line_no_column_with_ci_run(self): - CONST.IS_CI_RUN = True - TOTAL_LEN = gen_report.COL_1_LEN + gen_report.COL_2_LEN - TOTAL_LEN += gen_report.COL_3_LEN + gen_report.COL_4_LEN + 2 - TOTAL_LEN += gen_report.COL_5_LEN + 1 - test_str = ("| %s|\n" % 'test'.ljust(TOTAL_LEN)) - self.assertEqual(gen_report.print_line_no_columns('test'), test_str) - - def test_print_line_no_column_without_ci_run(self): - CONST.IS_CI_RUN = False - TOTAL_LEN = gen_report.COL_1_LEN + gen_report.COL_2_LEN - TOTAL_LEN += gen_report.COL_3_LEN + gen_report.COL_4_LEN + 2 - test_str = ("| %s|\n" % 'test'.ljust(TOTAL_LEN)) - self.assertEqual(gen_report.print_line_no_columns('test'), test_str) - - def test_print_separator_with_ci_run(self): - CONST.IS_CI_RUN = True - test_str = ("+" + "=" * gen_report.COL_1_LEN + - "+" + "=" * gen_report.COL_2_LEN + - "+" + "=" * gen_report.COL_3_LEN + - "+" + "=" * gen_report.COL_4_LEN + - "+" + "=" * gen_report.COL_5_LEN) - test_str += '+\n' - self.assertEqual(gen_report.print_separator(), test_str) - - def test_print_separator_without_ci_run(self): - CONST.IS_CI_RUN = False - test_str = ("+" + "=" * gen_report.COL_1_LEN + - "+" + "=" * gen_report.COL_2_LEN + - "+" + "=" * gen_report.COL_3_LEN + - "+" + "=" * gen_report.COL_4_LEN) - test_str += "+\n" - self.assertEqual(gen_report.print_separator(), test_str) - - @mock.patch('functest.ci.generate_report.logger.info') - def test_main_with_ci_run(self, mock_method): - CONST.IS_CI_RUN = True - gen_report.main() - mock_method.assert_called_once_with(test_utils.SubstrMatch('URL')) - - @mock.patch('functest.ci.generate_report.logger.info') - def test_main_with_ci_loop(self, mock_method): - CONST.CI_LOOP = 'daily' - gen_report.main() - mock_method.assert_called_once_with(test_utils.SubstrMatch('CI LOOP')) - - @mock.patch('functest.ci.generate_report.logger.info') - def test_main_with_scenario(self, mock_method): - CONST.DEPLOY_SCENARIO = 'test_scenario' - gen_report.main() - mock_method.assert_called_once_with(test_utils.SubstrMatch('SCENARIO')) - - @mock.patch('functest.ci.generate_report.logger.info') - def test_main_with_build_tag(self, mock_method): - CONST.BUILD_TAG = 'test_build_tag' - gen_report.main() - mock_method.assert_called_once_with(test_utils. - SubstrMatch('BUILD TAG')) - - -if __name__ == "__main__": - unittest.main(verbosity=2) diff --git a/functest/tests/unit/ci/test_prepare_env.py b/functest/tests/unit/ci/test_prepare_env.py index 714dd13c..fbb59651 100644 --- a/functest/tests/unit/ci/test_prepare_env.py +++ b/functest/tests/unit/ci/test_prepare_env.py @@ -33,7 +33,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_missing_inst_type(self, mock_logger_warn, mock_logger_info): - CONST.INSTALLER_TYPE = None + CONST.__setattr__('INSTALLER_TYPE', None) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -44,7 +44,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_missing_inst_ip(self, mock_logger_warn, mock_logger_info): - CONST.INSTALLER_IP = None + CONST.__setattr__('INSTALLER_IP', None) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -61,7 +61,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_inst_ip(self, mock_logger_warn, mock_logger_info): - CONST.INSTALLER_IP = mock.Mock() + CONST.__setattr__('INSTALLER_IP', mock.Mock()) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -72,7 +72,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_missing_scenario(self, mock_logger_warn, mock_logger_info): - CONST.DEPLOY_SCENARIO = None + CONST.__setattr__('DEPLOY_SCENARIO', None) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -84,7 +84,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_scenario(self, mock_logger_warn, mock_logger_info): - CONST.DEPLOY_SCENARIO = 'test_scenario' + CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario') prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -95,7 +95,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_ci_debug(self, mock_logger_warn, mock_logger_info): - CONST.CI_DEBUG = mock.Mock() + CONST.__setattr__('CI_DEBUG', mock.Mock()) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -106,7 +106,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_node(self, mock_logger_warn, mock_logger_info): - CONST.NODE_NAME = mock.Mock() + CONST.__setattr__('NODE_NAME', mock.Mock()) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -117,7 +117,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_build_tag(self, mock_logger_warn, mock_logger_info): - CONST.BUILD_TAG = mock.Mock() + CONST.__setattr__('BUILD_TAG', mock.Mock()) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -129,7 +129,7 @@ class PrepareEnvTesting(unittest.TestCase): @mock.patch('functest.ci.prepare_env.logger.warning') def test_check_env_variables_with_is_ci_run(self, mock_logger_warn, mock_logger_info): - CONST.IS_CI_RUN = mock.Mock() + CONST.__setattr__('IS_CI_RUN', mock.Mock()) prepare_env.check_env_variables() mock_logger_info.assert_any_call("Checking environment variables" "...") @@ -140,11 +140,11 @@ class PrepareEnvTesting(unittest.TestCase): def test_get_deployment_handler_missing_const_vars(self): with mock.patch('functest.ci.prepare_env.' 'factory.Factory.get_handler') as m: - CONST.INSTALLER_IP = None + CONST.__setattr__('INSTALLER_IP', None) prepare_env.get_deployment_handler() self.assertFalse(m.called) - CONST.INSTALLER_TYPE = None + CONST.__setattr__('INSTALLER_TYPE', None) prepare_env.get_deployment_handler() self.assertFalse(m.called) @@ -156,8 +156,8 @@ class PrepareEnvTesting(unittest.TestCase): mock.patch('functest.ci.prepare_env.' 'ft_utils.get_parameter_from_yaml', side_effect=ValueError): - CONST.INSTALLER_IP = 'test_ip' - CONST.INSTALLER_TYPE = 'test_inst_type' + CONST.__setattr__('INSTALLER_IP', 'test_ip') + CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type') opnfv_constants.INSTALLERS = ['test_inst_type'] prepare_env.get_deployment_handler() msg = ('Printing deployment info is not supported for ' @@ -172,8 +172,8 @@ class PrepareEnvTesting(unittest.TestCase): side_effect=Exception), \ mock.patch('functest.ci.prepare_env.' 'ft_utils.get_parameter_from_yaml'): - CONST.INSTALLER_IP = 'test_ip' - CONST.INSTALLER_TYPE = 'test_inst_type' + CONST.__setattr__('INSTALLER_IP', 'test_ip') + CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type') opnfv_constants.INSTALLERS = ['test_inst_type'] prepare_env.get_deployment_handler() self.assertTrue(mock_debug.called) @@ -188,12 +188,21 @@ class PrepareEnvTesting(unittest.TestCase): as mock_method: prepare_env.create_directories() mock_logger_info.assert_any_call("Creating needed directories...") - mock_method.assert_any_call(CONST.dir_functest_conf) - mock_method.assert_any_call(CONST.dir_functest_data) + mock_method.assert_any_call( + CONST.__getattribute__('dir_functest_conf')) + mock_method.assert_any_call( + CONST.__getattribute__('dir_functest_data')) + mock_method.assert_any_call( + CONST.__getattribute__('dir_functest_images')) mock_logger_info.assert_any_call(" %s created." % - CONST.dir_functest_conf) + CONST.__getattribute__( + 'dir_functest_conf')) mock_logger_info.assert_any_call(" %s created." % - CONST.dir_functest_data) + CONST.__getattribute__( + 'dir_functest_data')) + mock_logger_info.assert_any_call(" %s created." % + CONST.__getattribute__( + 'dir_functest_images')) @mock.patch('functest.ci.prepare_env.logger.info') @mock.patch('functest.ci.prepare_env.logger.debug') @@ -204,9 +213,14 @@ class PrepareEnvTesting(unittest.TestCase): prepare_env.create_directories() mock_logger_info.assert_any_call("Creating needed directories...") mock_logger_debug.assert_any_call(" %s already exists." % - CONST.dir_functest_conf) + CONST.__getattribute__( + 'dir_functest_conf')) + mock_logger_debug.assert_any_call(" %s already exists." % + CONST.__getattribute__( + 'dir_functest_data')) mock_logger_debug.assert_any_call(" %s already exists." % - CONST.dir_functest_data) + CONST.__getattribute__( + 'dir_functest_images')) def _get_env_cred_dict(self, os_prefix=''): return {'OS_USERNAME': os_prefix + 'username', @@ -230,24 +244,24 @@ class PrepareEnvTesting(unittest.TestCase): mock.patch('functest.ci.prepare_env.os.path.getsize', return_value=0), \ self.assertRaises(Exception): - CONST.openstack_creds = 'test_creds' + CONST.__setattr__('openstack_creds', 'test_creds') prepare_env.source_rc_file() def test_source_rc_missing_installer_ip(self): with mock.patch('functest.ci.prepare_env.os.path.isfile', return_value=False), \ self.assertRaises(Exception): - CONST.INSTALLER_IP = None - CONST.openstack_creds = 'test_creds' + CONST.__setattr__('INSTALLER_IP', None) + CONST.__setattr__('openstack_creds', 'test_creds') prepare_env.source_rc_file() def test_source_rc_missing_installer_type(self): with mock.patch('functest.ci.prepare_env.os.path.isfile', return_value=False), \ self.assertRaises(Exception): - CONST.INSTALLER_IP = 'test_ip' - CONST.openstack_creds = 'test_creds' - CONST.INSTALLER_TYPE = 'test_type' + CONST.__setattr__('INSTALLER_IP', 'test_ip') + CONST.__setattr__('openstack_creds', 'test_creds') + CONST.__setattr__('INSTALLER_TYPE', 'test_type') opnfv_constants.INSTALLERS = [] prepare_env.source_rc_file() @@ -259,9 +273,9 @@ class PrepareEnvTesting(unittest.TestCase): mock.patch('functest.ci.prepare_env.subprocess.Popen') \ as mock_subproc_popen, \ self.assertRaises(Exception): - CONST.openstack_creds = 'test_creds' - CONST.INSTALLER_IP = None - CONST.INSTALLER_TYPE = 'test_type' + CONST.__setattr__('openstack_creds', 'test_creds') + CONST.__setattr__('INSTALLER_IP', None) + CONST.__setattr__('INSTALLER_TYPE', 'test_type') opnfv_constants.INSTALLERS = ['test_type'] process_mock = mock.Mock() @@ -281,7 +295,7 @@ class PrepareEnvTesting(unittest.TestCase): return_value={'tkey1': 'tvalue1'}), \ mock.patch('functest.ci.prepare_env.os.remove') as m, \ mock.patch('functest.ci.prepare_env.yaml.dump'): - CONST.DEPLOY_SCENARIO = 'test_scenario' + CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario') prepare_env.patch_file('test_file') self.assertTrue(m.called) @@ -321,12 +335,12 @@ class PrepareEnvTesting(unittest.TestCase): cmd = "rally deployment destroy opnfv-rally" error_msg = "Deployment %s does not exist." % \ - CONST.rally_deployment_name + CONST.__getattribute__('rally_deployment_name') mock_logger_info.assert_any_call("Creating Rally environment...") mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False) cmd = "rally deployment create --file=rally_conf.json --name=" - cmd += CONST.rally_deployment_name + cmd += CONST.__getattribute__('rally_deployment_name') error_msg = "Problem while creating Rally deployment" mock_exec_raise.assert_any_call(cmd, error_msg=error_msg) @@ -352,7 +366,7 @@ class PrepareEnvTesting(unittest.TestCase): 'stdout.readline.return_value': '0'} mock_popen.configure_mock(**attrs) - CONST.tempest_deployment_name = 'test_dep_name' + CONST.__setattr__('tempest_deployment_name', 'test_dep_name') with mock.patch('functest.ci.prepare_env.' 'ft_utils.execute_command_raise', side_effect=Exception), \ @@ -379,7 +393,7 @@ class PrepareEnvTesting(unittest.TestCase): with mock.patch('functest.ci.prepare_env.os.path.isfile', return_value=False), \ self.assertRaises(Exception): - prepare_env.check_environment() + prepare_env.check_environment() @mock.patch('functest.ci.prepare_env.sys.exit') @mock.patch('functest.ci.prepare_env.logger.error') @@ -431,7 +445,8 @@ class PrepareEnvTesting(unittest.TestCase): self.assertTrue(mock_install_rally.called) self.assertTrue(mock_install_temp.called) self.assertTrue(mock_create_flavor.called) - m.assert_called_once_with(CONST.env_active, "w") + m.assert_called_once_with( + CONST.__getattribute__('env_active'), "w") self.assertTrue(mock_check_env.called) self.assertTrue(mock_print_info.called) diff --git a/functest/tests/unit/ci/test_run_tests.py b/functest/tests/unit/ci/test_run_tests.py index 7d02b1af..d0052392 100644 --- a/functest/tests/unit/ci/test_run_tests.py +++ b/functest/tests/unit/ci/test_run_tests.py @@ -62,24 +62,13 @@ class RunTestsTesting(unittest.TestCase): @mock.patch('functest.ci.run_tests.os_snapshot.main') def test_generate_os_snapshot(self, mock_os_snap): - run_tests.generate_os_snapshot() - self.assertTrue(mock_os_snap.called) + run_tests.generate_os_snapshot() + self.assertTrue(mock_os_snap.called) @mock.patch('functest.ci.run_tests.os_clean.main') def test_cleanup(self, mock_os_clean): - run_tests.cleanup() - self.assertTrue(mock_os_clean.called) - - def test_update_test_info(self): - run_tests.GlobalVariables.EXECUTED_TEST_CASES = [self.test] - run_tests.update_test_info('test_name', - 'test_result', - 'test_duration') - exp = self.test - exp.update({"result": 'test_result', - "duration": 'test_duration'}) - self.assertEqual(run_tests.GlobalVariables.EXECUTED_TEST_CASES, - [exp]) + run_tests.cleanup() + self.assertTrue(mock_os_clean.called) def test_get_run_dict_if_defined_default(self): mock_obj = mock.Mock() @@ -148,10 +137,8 @@ class RunTestsTesting(unittest.TestCase): mock.patch('functest.ci.run_tests.source_rc_file'), \ mock.patch('functest.ci.run_tests.generate_os_snapshot'), \ mock.patch('functest.ci.run_tests.cleanup'), \ - mock.patch('functest.ci.run_tests.update_test_info'), \ mock.patch('functest.ci.run_tests.get_run_dict', return_value=test_run_dict), \ - mock.patch('functest.ci.run_tests.generate_report.main'), \ self.assertRaises(run_tests.BlockingTestFailed) as context: run_tests.GlobalVariables.CLEAN_FLAG = True run_tests.run_test(mock_test, 'tier_name') @@ -176,21 +163,17 @@ class RunTestsTesting(unittest.TestCase): @mock.patch('functest.ci.run_tests.logger.info') def test_run_all_default(self, mock_logger_info): - with mock.patch('functest.ci.run_tests.run_tier') as mock_method, \ - mock.patch('functest.ci.run_tests.generate_report.init'), \ - mock.patch('functest.ci.run_tests.generate_report.main'): - CONST.CI_LOOP = 'test_ci_loop' + with mock.patch('functest.ci.run_tests.run_tier') as mock_method: + CONST.__setattr__('CI_LOOP', 'test_ci_loop') run_tests.run_all(self.tiers) mock_method.assert_any_call(self.tier) self.assertTrue(mock_logger_info.called) @mock.patch('functest.ci.run_tests.logger.info') - def test_run_all__missing_tier(self, mock_logger_info): - with mock.patch('functest.ci.run_tests.generate_report.init'), \ - mock.patch('functest.ci.run_tests.generate_report.main'): - CONST.CI_LOOP = 'loop_re_not_available' - run_tests.run_all(self.tiers) - self.assertTrue(mock_logger_info.called) + def test_run_all_missing_tier(self, mock_logger_info): + CONST.__setattr__('CI_LOOP', 'loop_re_not_available') + run_tests.run_all(self.tiers) + self.assertTrue(mock_logger_info.called) def test_main_failed(self): kwargs = {'test': 'test_name', 'noclean': True, 'report': True} @@ -221,7 +204,6 @@ class RunTestsTesting(unittest.TestCase): with mock.patch('functest.ci.run_tests.tb.TierBuilder', return_value=mock_obj), \ mock.patch('functest.ci.run_tests.source_rc_file'), \ - mock.patch('functest.ci.run_tests.generate_report.init'), \ mock.patch('functest.ci.run_tests.run_tier') as m: self.assertEqual(run_tests.main(**kwargs), run_tests.Result.EX_OK) @@ -234,7 +216,6 @@ class RunTestsTesting(unittest.TestCase): with mock.patch('functest.ci.run_tests.tb.TierBuilder', return_value=mock_obj), \ mock.patch('functest.ci.run_tests.source_rc_file'), \ - mock.patch('functest.ci.run_tests.generate_report.init'), \ mock.patch('functest.ci.run_tests.run_test') as m: self.assertEqual(run_tests.main(**kwargs), run_tests.Result.EX_OK) @@ -248,7 +229,6 @@ class RunTestsTesting(unittest.TestCase): with mock.patch('functest.ci.run_tests.tb.TierBuilder', return_value=mock_obj), \ mock.patch('functest.ci.run_tests.source_rc_file'), \ - mock.patch('functest.ci.run_tests.generate_report.init'), \ mock.patch('functest.ci.run_tests.run_all') as m: self.assertEqual(run_tests.main(**kwargs), run_tests.Result.EX_OK) @@ -262,11 +242,11 @@ class RunTestsTesting(unittest.TestCase): with mock.patch('functest.ci.run_tests.tb.TierBuilder', return_value=mock_obj), \ mock.patch('functest.ci.run_tests.source_rc_file'), \ - mock.patch('functest.ci.run_tests.generate_report.init'), \ mock.patch('functest.ci.run_tests.logger.debug') as m: self.assertEqual(run_tests.main(**kwargs), run_tests.Result.EX_ERROR) self.assertTrue(m.called) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/ci/test_tier_builder.py b/functest/tests/unit/ci/test_tier_builder.py index 438fa7c2..feaf33a8 100644 --- a/functest/tests/unit/ci/test_tier_builder.py +++ b/functest/tests/unit/ci/test_tier_builder.py @@ -22,6 +22,7 @@ class TierBuilderTesting(unittest.TestCase): 'scenario': 'test_scenario'} self.testcase = {'dependencies': self.dependency, + 'enabled': 'true', 'case_name': 'test_name', 'criteria': 'test_criteria', 'blocking': 'test_blocking', @@ -78,6 +79,13 @@ class TierBuilderTesting(unittest.TestCase): self.assertEqual(self.tierbuilder.get_tests('test_tier2'), None) + def test_get_tier_name_ok(self): + self.assertEqual(self.tierbuilder.get_tier_name('test_name'), + 'test_tier') + + def test_get_tier_name_ko(self): + self.assertEqual(self.tierbuilder.get_tier_name('test_name2'), None) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/ci/test_tier_handler.py b/functest/tests/unit/ci/test_tier_handler.py index 21df4098..28006274 100644 --- a/functest/tests/unit/ci/test_tier_handler.py +++ b/functest/tests/unit/ci/test_tier_handler.py @@ -32,6 +32,7 @@ class TierHandlerTesting(unittest.TestCase): 'test_ci_loop', description='test_desc') self.testcase = tier_handler.TestCase('test_name', + 'true', self.mock_depend, 'test_criteria', 'test_blocking', @@ -116,6 +117,10 @@ class TierHandlerTesting(unittest.TestCase): self.assertEqual(self.tier.get_name(), 'test_tier') + def test_testcase_is_enabled(self): + self.assertEqual(self.testcase.is_enabled(), + 'true') + def test_testcase_get_criteria(self): self.assertEqual(self.tier.get_order(), 'test_order') diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py index 4b6ea57a..c3d89ea3 100644 --- a/functest/tests/unit/cli/commands/test_cli_env.py +++ b/functest/tests/unit/cli/commands/test_cli_env.py @@ -28,7 +28,7 @@ class CliEnvTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') def test_prepare_default(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/prepare_env.py start" % - CONST.dir_repo_functest) + CONST.__getattribute__('dir_repo_functest')) self.cli_environ.prepare() mock_ft_utils.assert_called_with(cmd) @@ -40,29 +40,30 @@ class CliEnvTesting(unittest.TestCase): mock.patch('functest.cli.commands.cli_testcase.os.remove') \ as mock_os_remove: cmd = ("python %s/functest/ci/prepare_env.py start" % - CONST.dir_repo_functest) + CONST.__getattribute__('dir_repo_functest')) self.cli_environ.prepare() - mock_os_remove.assert_called_once_with(CONST.env_active) + mock_os_remove.assert_called_once_with( + CONST.__getattribute__('env_active')) mock_ft_utils.assert_called_with(cmd) def _test_show_missing_env_var(self, var, *args): if var == 'INSTALLER_TYPE': - CONST.INSTALLER_TYPE = None + CONST.__setattr__('INSTALLER_TYPE', None) reg_string = "| INSTALLER: Unknown, \S+\s*|" elif var == 'INSTALLER_IP': - CONST.INSTALLER_IP = None + CONST.__setattr__('INSTALLER_IP', None) reg_string = "| INSTALLER: \S+, Unknown\s*|" elif var == 'SCENARIO': - CONST.DEPLOY_SCENARIO = None + CONST.__setattr__('DEPLOY_SCENARIO', None) reg_string = "| SCENARIO: Unknown\s*|" elif var == 'NODE': - CONST.NODE_NAME = None + CONST.__setattr__('NODE_NAME', None) reg_string = "| POD: Unknown\s*|" elif var == 'BUILD_TAG': - CONST.BUILD_TAG = None + CONST.__setattr__('BUILD_TAG', None) reg_string = "| BUILD TAG: None|" elif var == 'DEBUG': - CONST.CI_DEBUG = None + CONST.__setattr__('CI_DEBUG', None) reg_string = "| DEBUG FLAG: false\s*|" elif var == 'STATUS': reg_string = "| STATUS: not ready\s*|" @@ -106,7 +107,7 @@ class CliEnvTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_env.os.path.exists', return_value=False) def test_show_missing_git_repo_dir(self, *args): - CONST.dir_repo_functest = None + CONST.__setattr__('dir_repo_functest', None) self.assertRaises(NoSuchPathError, lambda: self.cli_environ.show()) @mock.patch('functest.cli.commands.cli_env.click.echo') diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py index f0e58c67..54042769 100644 --- a/functest/tests/unit/cli/commands/test_cli_os.py +++ b/functest/tests/unit/cli/commands/test_cli_os.py @@ -69,10 +69,10 @@ class CliOpenStackTesting(unittest.TestCase): def test_fetch_credentials_default(self, mock_click_echo, mock_os_path, mock_ftutils_execute): - CONST.INSTALLER_TYPE = self.installer_type - CONST.INSTALLER_IP = self.installer_ip + CONST.__setattr__('INSTALLER_TYPE', self.installer_type) + CONST.__setattr__('INSTALLER_IP', self.installer_ip) cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" - % (CONST.dir_repos, + % (CONST.__getattribute__('dir_repos'), self.openstack_creds, self.installer_type, self.installer_ip)) @@ -92,15 +92,13 @@ class CliOpenStackTesting(unittest.TestCase): def test_fetch_credentials_missing_installer_type(self, mock_click_echo, mock_os_path, mock_ftutils_execute): - installer_type = None - installer_ip = self.installer_ip - CONST.INSTALLER_TYPE = installer_type - CONST.INSTALLER_IP = installer_ip + CONST.__setattr__('INSTALLER_TYPE', None) + CONST.__setattr__('INSTALLER_IP', self.installer_ip) cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" - % (CONST.dir_repos, + % (CONST.__getattribute__('dir_repos'), self.openstack_creds, - installer_type, - installer_ip)) + None, + self.installer_ip)) self.cli_os.openstack_creds = self.openstack_creds self.cli_os.fetch_credentials() mock_click_echo.assert_any_call("The environment variable " @@ -109,8 +107,8 @@ class CliOpenStackTesting(unittest.TestCase): mock_click_echo.assert_any_call("Fetching credentials from " "installer node '%s' with " "IP=%s.." % - (installer_type, - installer_ip)) + (None, + self.installer_ip)) mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') @@ -122,10 +120,10 @@ class CliOpenStackTesting(unittest.TestCase): mock_ftutils_execute): installer_type = self.installer_type installer_ip = None - CONST.INSTALLER_TYPE = installer_type - CONST.INSTALLER_IP = installer_ip + CONST.__setattr__('INSTALLER_TYPE', installer_type) + CONST.__setattr__('INSTALLER_IP', installer_ip) cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s" - % (CONST.dir_repos, + % (CONST.__getattribute__('dir_repos'), self.openstack_creds, installer_type, installer_ip)) @@ -144,8 +142,9 @@ class CliOpenStackTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command') def test_check(self, mock_ftutils_execute): with mock.patch.object(self.cli_os, 'ping_endpoint'): - CONST.dir_repo_functest = self.dir_repo_functest - cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh" + CONST.__setattr__('dir_repo_functest', self.dir_repo_functest) + cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'), + "functest/ci/check_os.sh") self.cli_os.check() mock_ftutils_execute.assert_called_once_with(cmd, verbose=False) diff --git a/functest/tests/unit/cli/commands/test_cli_testcase.py b/functest/tests/unit/cli/commands/test_cli_testcase.py index 39c8139d..2d09514e 100644 --- a/functest/tests/unit/cli/commands/test_cli_testcase.py +++ b/functest/tests/unit/cli/commands/test_cli_testcase.py @@ -42,7 +42,9 @@ class CliTestCasesTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') def test_run_default(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", self.testname)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-n -r ", self.testname)) self.cli_tests.run(self.testname, noclean=True, report=True) mock_ft_utils.assert_called_with(cmd) @@ -51,7 +53,9 @@ class CliTestCasesTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') def test_run_noclean_missing_report(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-n ", self.testname)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-n ", self.testname)) self.cli_tests.run(self.testname, noclean=True, report=False) mock_ft_utils.assert_called_with(cmd) @@ -60,7 +64,9 @@ class CliTestCasesTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') def test_run_report_missing_noclean(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-r ", self.testname)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-r ", self.testname)) self.cli_tests.run(self.testname, noclean=False, report=True) mock_ft_utils.assert_called_with(cmd) @@ -69,7 +75,9 @@ class CliTestCasesTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command') def test_run_missing_noclean_report(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "", self.testname)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "", self.testname)) self.cli_tests.run(self.testname, noclean=False, report=False) mock_ft_utils.assert_called_with(cmd) diff --git a/functest/tests/unit/cli/commands/test_cli_tier.py b/functest/tests/unit/cli/commands/test_cli_tier.py index 802359f1..fbc75253 100644 --- a/functest/tests/unit/cli/commands/test_cli_tier.py +++ b/functest/tests/unit/cli/commands/test_cli_tier.py @@ -90,8 +90,9 @@ class CliTierTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') def test_run_default(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", - self.tiername)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-n -r ", self.tiername)) self.cli_tier.run(self.tiername, noclean=True, report=True) mock_ft_utils.assert_called_with(cmd) @@ -100,8 +101,9 @@ class CliTierTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') def test_run_report_missing_noclean(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-r ", - self.tiername)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-r ", self.tiername)) self.cli_tier.run(self.tiername, noclean=False, report=True) mock_ft_utils.assert_called_with(cmd) @@ -110,8 +112,9 @@ class CliTierTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') def test_run_noclean_missing_report(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "-n ", - self.tiername)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "-n ", self.tiername)) self.cli_tier.run(self.tiername, noclean=True, report=False) mock_ft_utils.assert_called_with(cmd) @@ -120,8 +123,9 @@ class CliTierTesting(unittest.TestCase): @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command') def test_run_missing_noclean_report(self, mock_ft_utils, mock_os): cmd = ("python %s/functest/ci/run_tests.py " - "%s -t %s" % (CONST.dir_repo_functest, "", - self.tiername)) + "%s -t %s" % + (CONST.__getattribute__('dir_repo_functest'), + "", self.tiername)) self.cli_tier.run(self.tiername, noclean=False, report=False) mock_ft_utils.assert_called_with(cmd) diff --git a/functest/tests/unit/core/test_feature.py b/functest/tests/unit/core/test_feature.py index 993da5a0..8de42ec5 100644 --- a/functest/tests/unit/core/test_feature.py +++ b/functest/tests/unit/core/test_feature.py @@ -28,7 +28,7 @@ class FeatureTestingBase(unittest.TestCase): _project_name = "bar" _repo = "dir_repo_copper" _cmd = "cd /home/opnfv/repos/foo/tests && bash run.sh && cd -" - _output_file = '/home/opnfv/functest/results/bar.log' + _output_file = '/home/opnfv/functest/results/foo.log' feature = None @mock.patch('time.time', side_effect=[1, 2]) diff --git a/functest/tests/unit/core/test_pytest_suite_runner.py b/functest/tests/unit/core/test_pytest_suite_runner.py new file mode 100644 index 00000000..15e5bd73 --- /dev/null +++ b/functest/tests/unit/core/test_pytest_suite_runner.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# 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 + +# pylint: disable=missing-docstring + +import logging +import unittest + +import mock + +from functest.core import pytest_suite_runner +from functest.core import testcase + + +class PyTestSuiteRunnerTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.psrunner = pytest_suite_runner.PyTestSuiteRunner() + self.result = mock.Mock() + attrs = {'errors': [('test1', 'error_msg1')], + 'failures': [('test2', 'failure_msg1')]} + self.result.configure_mock(**attrs) + + self.pass_results = mock.Mock() + attrs = {'errors': None, + 'failures': None} + self.pass_results.configure_mock(**attrs) + + def test_run(self): + self.psrunner.case_name = 'test_case_name' + with mock.patch('functest.core.pytest_suite_runner.' + 'unittest.TextTestRunner.run', + return_value=self.result): + self.assertEqual(self.psrunner.run(), + testcase.TestCase.EX_OK) + + with mock.patch('functest.core.pytest_suite_runner.' + 'unittest.TextTestRunner.run', + return_value=self.pass_results): + self.assertEqual(self.psrunner.run(), + testcase.TestCase.EX_OK) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/core/test_testcase.py b/functest/tests/unit/core/test_testcase.py index cc8446d8..2adf4a6d 100644 --- a/functest/tests/unit/core/test_testcase.py +++ b/functest/tests/unit/core/test_testcase.py @@ -7,7 +7,7 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 -"""Define the classe required to fully cover testcase.""" +"""Define the class required to fully cover testcase.""" import logging import unittest @@ -20,9 +20,8 @@ __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>" class TestCaseTesting(unittest.TestCase): - """The class testing TestCase.""" - # pylint: disable=missing-docstring + # pylint: disable=missing-docstring,too-many-public-methods logging.disable(logging.CRITICAL) @@ -116,12 +115,12 @@ class TestCaseTesting(unittest.TestCase): def test_check_criteria_missing(self): self.test.criteria = None - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_TESTCASE_FAILED) def test_check_result_missing(self): self.test.result = None - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_TESTCASE_FAILED) def test_check_result_failed(self): @@ -129,7 +128,7 @@ class TestCaseTesting(unittest.TestCase): # It must be removed as soon as TestCase subclasses # stop setting result = 'PASS' or 'FAIL'. self.test.result = 'FAIL' - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_TESTCASE_FAILED) def test_check_result_pass(self): @@ -137,31 +136,93 @@ class TestCaseTesting(unittest.TestCase): # It must be removed as soon as TestCase subclasses # stop setting result = 'PASS' or 'FAIL'. self.test.result = 'PASS' - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_OK) def test_check_result_lt(self): self.test.result = 50 - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_TESTCASE_FAILED) def test_check_result_eq(self): self.test.result = 100 - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_OK) def test_check_result_gt(self): self.test.criteria = 50 self.test.result = 100 - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_OK) def test_check_result_zero(self): self.test.criteria = 0 self.test.result = 0 - self.assertEqual(self.test.check_result(), + self.assertEqual(self.test.is_successful(), testcase.TestCase.EX_TESTCASE_FAILED) + def test_get_duration_start_ko(self): + self.test.start_time = None + self.assertEqual(self.test.get_duration(), "XX:XX") + self.test.start_time = 0 + self.assertEqual(self.test.get_duration(), "XX:XX") + + def test_get_duration_end_ko(self): + self.test.stop_time = None + self.assertEqual(self.test.get_duration(), "XX:XX") + self.test.stop_time = 0 + self.assertEqual(self.test.get_duration(), "XX:XX") + + def test_get_invalid_duration(self): + self.test.start_time = 2 + self.test.stop_time = 1 + self.assertEqual(self.test.get_duration(), "XX:XX") + + def test_get_zero_duration(self): + self.test.start_time = 2 + self.test.stop_time = 2 + self.assertEqual(self.test.get_duration(), "00:00") + + def test_get_duration(self): + self.test.start_time = 1 + self.test.stop_time = 180 + self.assertEqual(self.test.get_duration(), "02:59") + + def test_str_project_name_ko(self): + self.test.project_name = None + self.assertIn("<functest.core.testcase.TestCase object at", + str(self.test)) + + def test_str_case_name_ko(self): + self.test.case_name = None + self.assertIn("<functest.core.testcase.TestCase object at", + str(self.test)) + + def test_str_pass(self): + duration = '01:01' + with mock.patch.object(self.test, 'get_duration', + return_value=duration), \ + mock.patch.object(self.test, 'is_successful', + return_value=testcase.TestCase.EX_OK): + message = str(self.test) + self.assertIn(self._project_name, message) + self.assertIn(self._case_name, message) + self.assertIn(duration, message) + self.assertIn('PASS', message) + + def test_str_fail(self): + duration = '00:59' + with mock.patch.object(self.test, 'get_duration', + return_value=duration), \ + mock.patch.object( + self.test, 'is_successful', + return_value=testcase.TestCase.EX_TESTCASE_FAILED): + message = str(self.test) + self.assertIn(self._project_name, message) + self.assertIn(self._case_name, message) + self.assertIn(duration, message) + self.assertIn('FAIL', message) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/tests/unit/core/test_vnf.py b/functest/tests/unit/core/test_vnf.py new file mode 100644 index 00000000..793e9576 --- /dev/null +++ b/functest/tests/unit/core/test_vnf.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python + +# Copyright (c) 2016 Orange 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 + +# pylint: disable=missing-docstring + +import logging +import os +import unittest + +import mock + +from functest.core import vnf +from functest.core import testcase + + +class VnfBaseTesting(unittest.TestCase): + + logging.disable(logging.CRITICAL) + + def setUp(self): + self.test = vnf.VnfOnBoarding( + project='functest', case_name='aaa') + self.test.project = "functest" + self.test.start_time = "1" + self.test.stop_time = "5" + self.test.result = "" + self.test.details = { + "orchestrator": {"status": "PASS", "result": "", "duration": 20}, + "vnf": {"status": "PASS", "result": "", "duration": 15}, + "test_vnf": {"status": "FAIL", "result": "", "duration": 5}} + self.test.keystone_client = 'test_client' + self.test.tenant_name = 'test_tenant_name' + + def test_execute_deploy_vnf_fail(self): + with mock.patch.object(self.test, 'prepare'),\ + mock.patch.object(self.test, 'deploy_orchestrator', + return_value=None), \ + mock.patch.object(self.test, 'deploy_vnf', + side_effect=Exception): + self.assertEqual(self.test.execute(), + testcase.TestCase.EX_TESTCASE_FAILED) + + def test_execute_test_vnf_fail(self): + with mock.patch.object(self.test, 'prepare'),\ + mock.patch.object(self.test, 'deploy_orchestrator', + return_value=None), \ + mock.patch.object(self.test, 'deploy_vnf'), \ + mock.patch.object(self.test, 'test_vnf', + side_effect=Exception): + self.assertEqual(self.test.execute(), + testcase.TestCase.EX_TESTCASE_FAILED) + + @mock.patch('functest.core.vnf.os_utils.get_tenant_id', + return_value='test_tenant_id') + @mock.patch('functest.core.vnf.os_utils.delete_tenant', + return_value=True) + @mock.patch('functest.core.vnf.os_utils.get_user_id', + return_value='test_user_id') + @mock.patch('functest.core.vnf.os_utils.delete_user', + return_value=True) + def test_execute_default(self, *args): + with mock.patch.object(self.test, 'prepare'),\ + mock.patch.object(self.test, 'deploy_orchestrator', + return_value=None), \ + mock.patch.object(self.test, 'deploy_vnf'), \ + mock.patch.object(self.test, 'test_vnf'), \ + mock.patch.object(self.test, 'parse_results', + return_value='ret_exit_code'), \ + mock.patch.object(self.test, 'log_results'): + self.assertEqual(self.test.execute(), + 'ret_exit_code') + + @mock.patch('functest.core.vnf.os_utils.get_credentials') + @mock.patch('functest.core.vnf.os_utils.get_keystone_client') + @mock.patch('functest.core.vnf.os_utils.get_user_id', return_value='') + def test_prepare_missing_userid(self, *args): + with self.assertRaises(Exception): + self.test.prepare() + + @mock.patch('functest.core.vnf.os_utils.get_credentials') + @mock.patch('functest.core.vnf.os_utils.get_keystone_client') + @mock.patch('functest.core.vnf.os_utils.get_user_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.create_tenant', + return_value='') + def test_prepare_missing_tenantid(self, *args): + with self.assertRaises(Exception): + self.test.prepare() + + @mock.patch('functest.core.vnf.os_utils.get_credentials') + @mock.patch('functest.core.vnf.os_utils.get_keystone_client') + @mock.patch('functest.core.vnf.os_utils.get_user_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.create_tenant', + return_value='test_tenantid') + @mock.patch('functest.core.vnf.os_utils.get_role_id', + return_value='') + def test_prepare_missing_roleid(self, *args): + with self.assertRaises(Exception): + self.test.prepare() + + @mock.patch('functest.core.vnf.os_utils.get_credentials') + @mock.patch('functest.core.vnf.os_utils.get_keystone_client') + @mock.patch('functest.core.vnf.os_utils.get_user_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.create_tenant', + return_value='test_tenantid') + @mock.patch('functest.core.vnf.os_utils.get_role_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.add_role_user', + return_value='') + def test_prepare_role_add_failure(self, *args): + with self.assertRaises(Exception): + self.test.prepare() + + @mock.patch('functest.core.vnf.os_utils.get_credentials') + @mock.patch('functest.core.vnf.os_utils.get_keystone_client') + @mock.patch('functest.core.vnf.os_utils.get_user_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.create_tenant', + return_value='test_tenantid') + @mock.patch('functest.core.vnf.os_utils.get_role_id', + return_value='test_roleid') + @mock.patch('functest.core.vnf.os_utils.add_role_user') + @mock.patch('functest.core.vnf.os_utils.create_user', + return_value='') + def test_create_user_failure(self, *args): + with self.assertRaises(Exception): + self.test.prepare() + + def test_log_results_default(self): + with mock.patch('functest.core.vnf.' + 'ft_utils.logger_test_results') \ + as mock_method: + self.test.log_results() + self.assertTrue(mock_method.called) + + def test_step_failures_default(self): + with self.assertRaises(Exception): + self.test.step_failure("error_msg") + + def test_deploy_vnf_unimplemented(self): + with self.assertRaises(Exception) as context: + self.test.deploy_vnf() + self.assertTrue('VNF not deployed' in context.exception) + + def test_test_vnf_unimplemented(self): + with self.assertRaises(Exception) as context: + self.test.test_vnf()() + self.assertTrue('VNF not tested' in context.exception) + + def test_parse_results_ex_ok(self): + self.test.details['test_vnf']['status'] = 'PASS' + self.assertEqual(self.test.parse_results(), os.EX_OK) + + def test_parse_results_ex_run_error(self): + self.test.details['vnf']['status'] = 'FAIL' + self.assertEqual(self.test.parse_results(), os.EX_SOFTWARE) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/core/test_vnf_base.py b/functest/tests/unit/core/test_vnf_base.py deleted file mode 100644 index 540cf610..00000000 --- a/functest/tests/unit/core/test_vnf_base.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2016 Orange 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 logging -import unittest - -from functest.core import vnf_base - - -class VnfBaseTesting(unittest.TestCase): - - logging.disable(logging.CRITICAL) - - def setUp(self): - self.test = vnf_base.VnfOnBoardingBase(project='functest', - case_name='aaa') - self.test.project = "functest" - self.test.start_time = "1" - self.test.stop_time = "5" - self.test.result = "" - self.test.details = {"orchestrator": {"status": "PASS", - "result": "", - "duration": 20}, - "vnf": {"status": "PASS", - "result": "", - "duration": 15}, - "test_vnf": {"status": "FAIL", - "result": "", - "duration": 5}} - - def test_deploy_vnf_unimplemented(self): - with self.assertRaises(Exception) as context: - self.test.deploy_vnf() - self.assertTrue('VNF not deployed' in context.exception) - - def test_test_vnf_unimplemented(self): - with self.assertRaises(Exception) as context: - self.test.test_vnf()() - self.assertTrue('VNF not tested' in context.exception) - - def test_parse_results(self): - self.assertNotEqual(self.test.parse_results(), 0) - - -if __name__ == "__main__": - unittest.main(verbosity=2) diff --git a/functest/tests/unit/energy/__init__.py b/functest/tests/unit/energy/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/functest/tests/unit/energy/__init__.py diff --git a/functest/tests/unit/energy/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py new file mode 100644 index 00000000..ffe044bc --- /dev/null +++ b/functest/tests/unit/energy/test_functest_energy.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python + +# 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 + +"""Unitary test for energy module.""" +# pylint: disable=unused-argument +import logging +import unittest + +import mock + +from functest.energy.energy import EnergyRecorder +import functest.energy.energy as energy + + +CASE_NAME = "UNIT_test_CASE" +STEP_NAME = "UNIT_test_STEP" + +logging.disable(logging.CRITICAL) + + +class MockHttpResponse(object): # pylint: disable=too-few-public-methods + """Mock response for Energy recorder API.""" + + def __init__(self, text, status_code): + """Create an instance of MockHttpResponse.""" + self.text = text + self.status_code = status_code + + +RECORDER_OK = MockHttpResponse( + '{"environment": "UNIT_TEST",' + ' "step": "string",' + ' "scenario": "' + CASE_NAME + '"}', + 200 +) +RECORDER_KO = MockHttpResponse( + '{"message": "An unhandled API exception occurred (MOCK)"}', + 500 +) + + +def config_loader_mock(config_key): + """Return mocked config values.""" + if config_key == "energy_recorder.api_url": + return "http://pod-uri:8888" + elif config_key == "energy_recorder.api_user": + return "user" + elif config_key == "energy_recorder.api_password": + return "password" + else: + raise Exception("Config not mocked") + + +def config_loader_mock_no_creds(config_key): + """Return mocked config values.""" + if config_key == "energy_recorder.api_url": + return "http://pod-uri:8888" + elif config_key == "energy_recorder.api_user": + return "" + elif config_key == "energy_recorder.api_password": + return "" + else: + raise Exception("Config not mocked:" + config_key) + + +class EnergyRecorderTest(unittest.TestCase): + """Energy module unitary test suite.""" + + case_name = CASE_NAME + request_headers = {'content-type': 'application/json'} + returned_value_to_preserve = "value" + exception_message_to_preserve = "exception_message" + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_OK) + def test_start(self, post_mock=None): + """EnergyRecorder.start method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + side_effect=Exception("Internal execution error (MOCK)")) + def test_start_error(self, post_mock=None): + """EnergyRecorder.start method (error in method).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_KO) + def test_start_api_error(self, post_mock=None): + """EnergyRecorder.start method (API error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.start(self.case_name)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_OK) + def test_set_step(self, post_mock=None): + """EnergyRecorder.set_step method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + return_value=RECORDER_KO) + def test_set_step_api_error(self, post_mock=None): + """EnergyRecorder.set_step method (API error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.post', + side_effect=Exception("Internal execution error (MOCK)")) + def test_set_step_error(self, post_mock=None): + """EnergyRecorder.set_step method (method error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.set_step(STEP_NAME)) + post_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + auth=EnergyRecorder.energy_recorder_api["auth"], + data=mock.ANY, + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + return_value=RECORDER_OK) + def test_stop(self, delete_mock=None): + """EnergyRecorder.stop method (regular case).""" + self.test_load_config() + self.assertTrue(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + return_value=RECORDER_KO) + def test_stop_api_error(self, delete_mock=None): + """EnergyRecorder.stop method (API Error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @mock.patch('functest.energy.energy.requests.delete', + side_effect=Exception("Internal execution error (MOCK)")) + def test_stop_error(self, delete_mock=None): + """EnergyRecorder.stop method (method error).""" + self.test_load_config() + self.assertFalse(EnergyRecorder.stop()) + delete_mock.assert_called_once_with( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers=self.request_headers + ) + + @energy.enable_recording + def __decorated_method(self): + """Call with to energy recorder decorators.""" + return self.returned_value_to_preserve + + @energy.enable_recording + def __decorated_method_with_ex(self): + """Call with to energy recorder decorators.""" + raise Exception(self.exception_message_to_preserve) + + @mock.patch("functest.energy.energy.EnergyRecorder") + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock) + def test_decorators(self, + loader_mock=None, + pod_mock=None, + recorder_mock=None): + """Test energy module decorators.""" + self.__decorated_method() + calls = [mock.call.start(self.case_name), + mock.call.stop()] + recorder_mock.assert_has_calls(calls) + + def test_decorator_preserve_return(self): + """Test that decorator preserve method returned value.""" + self.test_load_config() + self.assertTrue( + self.__decorated_method() == self.returned_value_to_preserve + ) + + def test_decorator_preserve_ex(self): + """Test that decorator preserve method exceptions.""" + self.test_load_config() + with self.assertRaises(Exception) as context: + self.__decorated_method_with_ex() + self.assertTrue( + self.exception_message_to_preserve in context.exception + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config(self, loader_mock=None, pod_mock=None): + """Test load config.""" + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals( + EnergyRecorder.energy_recorder_api["auth"], + ("user", "password") + ) + self.assertEquals( + EnergyRecorder.energy_recorder_api["uri"], + "http://pod-uri:8888/recorders/environment/MOCK_POD" + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + side_effect=config_loader_mock_no_creds) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config_no_creds(self, loader_mock=None, pod_mock=None): + """Test load config without creds.""" + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals(EnergyRecorder.energy_recorder_api["auth"], None) + self.assertEquals( + EnergyRecorder.energy_recorder_api["uri"], + "http://pod-uri:8888/recorders/environment/MOCK_POD" + ) + + @mock.patch("functest.utils.functest_utils.get_functest_config", + return_value=None) + @mock.patch("functest.utils.functest_utils.get_pod_name", + return_value="MOCK_POD") + def test_load_config_ex(self, loader_mock=None, pod_mock=None): + """Test load config with exception.""" + with self.assertRaises(AssertionError): + EnergyRecorder.energy_recorder_api = None + EnergyRecorder.load_config() + self.assertEquals(EnergyRecorder.energy_recorder_api, None) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py index 54d6da72..e2778e24 100644 --- a/functest/tests/unit/odl/test_odl.py +++ b/functest/tests/unit/odl/test_odl.py @@ -12,14 +12,14 @@ import errno import logging import os -import StringIO import unittest from keystoneauth1.exceptions import auth_plugins import mock from robot.errors import DataError, RobotError -from robot.result import testcase as result_testcase +from robot.result import model from robot.utils.robottime import timestamp_to_secs +import six from functest.core import testcase from functest.opnfv_tests.sdn.odl import odl @@ -49,11 +49,9 @@ class ODLVisitorTesting(unittest.TestCase): 'elapsedtime': 1000, 'text': 'Hello, World!', 'critical': True} - test = result_testcase.TestCase(name=data['name'], - status=data['status'], - message=data['text'], - starttime=data['starttime'], - endtime=data['endtime']) + test = model.TestCase( + name=data['name'], status=data['status'], message=data['text'], + starttime=data['starttime'], endtime=data['endtime']) test.parent = mock.Mock() config = {'name': data['parent'], 'criticality.test_is_critical.return_value': data[ @@ -109,6 +107,9 @@ class ODLParseResultTesting(ODLTesting): """The class testing ODLTests.parse_results().""" # pylint: disable=missing-docstring + _config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000', + 'endtime': '20161216 16:00:01.000'} + @mock.patch('robot.api.ExecutionResult', side_effect=DataError) def test_raises_exc(self, mock_method): with self.assertRaises(DataError): @@ -116,15 +117,13 @@ class ODLParseResultTesting(ODLTesting): mock_method.assert_called_once_with( os.path.join(odl.ODLTests.res_dir, 'output.xml')) - def test_ok(self): - config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000', - 'endtime': '20161216 16:00:01.000', 'status': 'PASS'} + def _test_result(self, config, result): suite = mock.Mock() suite.configure_mock(**config) with mock.patch('robot.api.ExecutionResult', return_value=mock.Mock(suite=suite)): self.test.parse_results() - self.assertEqual(self.test.result, config['status']) + self.assertEqual(self.test.result, result) self.assertEqual(self.test.start_time, timestamp_to_secs(config['starttime'])) self.assertEqual(self.test.stop_time, @@ -132,6 +131,26 @@ class ODLParseResultTesting(ODLTesting): self.assertEqual(self.test.details, {'description': config['name'], 'tests': []}) + def test_null_passed(self): + self._config.update({'statistics.critical.passed': 0, + 'statistics.critical.total': 20}) + self._test_result(self._config, 0) + + def test_no_test(self): + self._config.update({'statistics.critical.passed': 20, + 'statistics.critical.total': 0}) + self._test_result(self._config, 0) + + def test_half_success(self): + self._config.update({'statistics.critical.passed': 10, + 'statistics.critical.total': 20}) + self._test_result(self._config, 50) + + def test_success(self): + self._config.update({'statistics.critical.passed': 20, + 'statistics.critical.total': 20}) + self._test_result(self._config, 100) + class ODLRobotTesting(ODLTesting): @@ -152,7 +171,7 @@ class ODLRobotTesting(ODLTesting): os.path.join(odl.ODLTests.odl_test_repo, 'csit/variables/Variables.py'), inplace=True) - @mock.patch('sys.stdout', new_callable=StringIO.StringIO) + @mock.patch('sys.stdout', new_callable=six.StringIO) def _test_set_vars(self, msg1, msg2, *args): line = mock.MagicMock() line.__iter__.return_value = [msg1] @@ -170,7 +189,7 @@ class ODLRobotTesting(ODLTesting): def test_set_vars_auth1(self): self._test_set_vars("AUTH1 = []", "AUTH1 = []") - @mock.patch('sys.stdout', new_callable=StringIO.StringIO) + @mock.patch('sys.stdout', new_callable=six.StringIO) def test_set_vars_auth_foo(self, *args): line = mock.MagicMock() line.__iter__.return_value = ["AUTH = []"] @@ -337,9 +356,11 @@ class ODLMainTesting(ODLTesting): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ mock.patch.object(odl, 'open', mock.mock_open(), - create=True), \ + create=True) as mock_open, \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase.TestCase.EX_OK, *args) + mock_open.assert_called_once_with( + os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+') @mock.patch('os.remove') @mock.patch('robot.run', return_value=1) @@ -348,9 +369,11 @@ class ODLMainTesting(ODLTesting): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ mock.patch.object(odl, 'open', mock.mock_open(), - create=True), \ + create=True) as mock_open, \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase.TestCase.EX_OK, *args) + mock_open.assert_called_once_with( + os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+') @mock.patch('os.remove', side_effect=OSError) @mock.patch('robot.run') @@ -359,9 +382,11 @@ class ODLMainTesting(ODLTesting): with mock.patch.object(self.test, 'set_robotframework_vars', return_value=True), \ mock.patch.object(odl, 'open', mock.mock_open(), - create=True), \ + create=True) as mock_open, \ mock.patch.object(self.test, 'parse_results'): self._test_main(testcase.TestCase.EX_OK, *args) + mock_open.assert_called_once_with( + os.path.join(odl.ODLTests.res_dir, 'stdout.txt'), 'w+') class ODLRunTesting(ODLTesting): @@ -552,7 +577,7 @@ class ODLArgParserTesting(ODLTesting): "--odlip={}".format(self._sdn_controller_ip)]), self.defaultargs) - @mock.patch('sys.stderr', new_callable=StringIO.StringIO) + @mock.patch('sys.stderr', new_callable=six.StringIO) def test_fail(self, mock_method): self.defaultargs['foo'] = 'bar' with self.assertRaises(SystemExit): diff --git a/functest/tests/unit/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py index fe25dfcf..c7828618 100644 --- a/functest/tests/unit/openstack/rally/test_rally.py +++ b/functest/tests/unit/openstack/rally/test_rally.py @@ -343,19 +343,6 @@ class OSRallyTesting(unittest.TestCase): self.rally_base._run_tests() self.rally_base._run_task.assert_any_call('test1') - @mock.patch('functest.opnfv_tests.openstack.rally.rally.logger.info') - def test_generate_report(self, mock_logger_info): - summary = [{'test_name': 'test_name', - 'overall_duration': 5, - 'nb_tests': 3, - 'success': 5}] - self.rally_base.summary = summary - with mock.patch('functest.opnfv_tests.openstack.rally.rally.' - 'ft_utils.check_success_rate', - return_value='criteria'): - self.rally_base._generate_report() - self.assertTrue(mock_logger_info.called) - def test_clean_up_default(self): self.rally_base.volume_type = mock.Mock() self.rally_base.cinder_client = mock.Mock() diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py index e05e5dfa..bb75c9ed 100644 --- a/functest/tests/unit/openstack/tempest/test_tempest.py +++ b/functest/tests/unit/openstack/tempest/test_tempest.py @@ -151,24 +151,6 @@ class OSTempestTesting(unittest.TestCase): assert_any_call("Starting Tempest test suite: '%s'." % cmd_line) - @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.logger.info') - def test_parse_verifier_result_default(self, mock_logger_info): - self.tempestcommon.VERIFICATION_ID = 'test_uuid' - self.tempestcommon.case_name = 'test_case_name' - stdout = ['Testscount||2', 'Success||2', 'Skipped||0', 'Failures||0'] - with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' - 'subprocess.Popen') as mock_popen, \ - mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' - 'ft_utils.check_success_rate') as mock_method, \ - mock.patch('__builtin__.open', mock.mock_open()): - mock_stdout = mock.Mock() - attrs = {'stdout': stdout} - mock_stdout.configure_mock(**attrs) - mock_popen.return_value = mock_stdout - - self.tempestcommon.parse_verifier_result() - mock_method.assert_any_call('test_case_name', 100) - @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.' 'os.path.exists', return_value=False) @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs', diff --git a/functest/tests/unit/utils/test_decorators.py b/functest/tests/unit/utils/test_decorators.py new file mode 100644 index 00000000..f8bd9a54 --- /dev/null +++ b/functest/tests/unit/utils/test_decorators.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python + +# Copyright (c) 2017 Orange 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 + +"""Define the class required to fully cover decorators.""" + +from datetime import datetime +import errno +import json +import logging +import os +import unittest + +import mock + +from functest.utils import decorators +from functest.utils import functest_utils + +__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>" + +VERSION = 'master' +DIR = '/dev' +FILE = '{}/null'.format(DIR) +URL = 'file://{}'.format(FILE) + + +class DecoratorsTesting(unittest.TestCase): + # pylint: disable=missing-docstring + + logging.disable(logging.CRITICAL) + + _case_name = 'base' + _project_name = 'functest' + _start_time = 1.0 + _stop_time = 2.0 + _result = 'PASS' + _build_tag = VERSION + _node_name = 'bar' + _deploy_scenario = 'foo' + _installer_type = 'debian' + + def setUp(self): + os.environ['INSTALLER_TYPE'] = self._installer_type + os.environ['DEPLOY_SCENARIO'] = self._deploy_scenario + os.environ['NODE_NAME'] = self._node_name + os.environ['BUILD_TAG'] = self._build_tag + + def test_wraps(self): + self.assertEqual(functest_utils.push_results_to_db.__name__, + "push_results_to_db") + + def _get_json(self): + stop_time = datetime.fromtimestamp(self._stop_time).strftime( + '%Y-%m-%d %H:%M:%S') + start_time = datetime.fromtimestamp(self._start_time).strftime( + '%Y-%m-%d %H:%M:%S') + data = {'project_name': self._project_name, + 'stop_date': stop_time, 'start_date': start_time, + 'case_name': self._case_name, 'build_tag': self._build_tag, + 'pod_name': self._node_name, 'installer': self._installer_type, + 'scenario': self._deploy_scenario, 'version': VERSION, + 'details': {}, 'criteria': self._result} + return json.dumps(data) + + @mock.patch('{}.get_db_url'.format(functest_utils.__name__), + return_value='http://127.0.0.1') + @mock.patch('{}.get_version'.format(functest_utils.__name__), + return_value=VERSION) + @mock.patch('requests.post') + def test_http_shema(self, *args): + self.assertTrue(functest_utils.push_results_to_db( + self._project_name, self._case_name, self._start_time, + self._stop_time, self._result, {})) + args[1].assert_called_once_with() + args[2].assert_called_once_with() + args[0].assert_called_once_with( + 'http://127.0.0.1', data=self._get_json(), + headers={'Content-Type': 'application/json'}) + + @mock.patch('{}.get_db_url'.format(functest_utils.__name__), + return_value="/dev/null") + def test_wrong_shema(self, mock_method=None): + self.assertFalse(functest_utils.push_results_to_db( + self._project_name, self._case_name, self._start_time, + self._stop_time, self._result, {})) + mock_method.assert_called_once_with() + + @mock.patch('{}.get_version'.format(functest_utils.__name__), + return_value=VERSION) + @mock.patch('{}.get_db_url'.format(functest_utils.__name__), + return_value=URL) + def _test_dump(self, *args): + with mock.patch.object(decorators, 'open', mock.mock_open(), + create=True) as mock_open: + self.assertTrue(functest_utils.push_results_to_db( + self._project_name, self._case_name, self._start_time, + self._stop_time, self._result, {})) + mock_open.assert_called_once_with(FILE, 'a') + handle = mock_open() + call_args, _ = handle.write.call_args + self.assertIn('POST', call_args[0]) + self.assertIn(self._get_json(), call_args[0]) + args[0].assert_called_once_with() + args[1].assert_called_once_with() + + @mock.patch('os.makedirs') + def test_default_dump(self, mock_method=None): + self._test_dump() + mock_method.assert_called_once_with(DIR) + + @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, '')) + def test_makedirs_dir_exists(self, mock_method=None): + self._test_dump() + mock_method.assert_called_once_with(DIR) + + @mock.patch('{}.get_db_url'.format(functest_utils.__name__), + return_value=URL) + @mock.patch('os.makedirs', side_effect=OSError) + def test_makedirs_exc(self, *args): + self.assertFalse( + functest_utils.push_results_to_db( + self._project_name, self._case_name, self._start_time, + self._stop_time, self._result, {})) + args[0].assert_called_once_with(DIR) + args[1].assert_called_once_with() + + +if __name__ == "__main__": + logging.basicConfig() + unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_functest_logger.py b/functest/tests/unit/utils/test_functest_logger.py deleted file mode 100644 index 42e41a14..00000000 --- a/functest/tests/unit/utils/test_functest_logger.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# 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 logging -import unittest - -import mock - -from functest.utils import functest_logger -from functest.utils.constants import CONST - - -class OSUtilsLogger(unittest.TestCase): - - logging.disable(logging.CRITICAL) - - def setUp(self): - with mock.patch('__builtin__.open', mock.mock_open()): - with mock.patch('functest.utils.functest_logger.os.path.exists', - return_value=True), \ - mock.patch('functest.utils.functest_logger.' - 'json.load'), \ - mock.patch('functest.utils.functest_logger.' - 'logging.config.dictConfig') as m: - self.logger = functest_logger.Logger('os_utils') - self.assertTrue(m.called) - with mock.patch('functest.utils.functest_logger.os.path.exists', - return_value=False), \ - mock.patch('functest.utils.functest_logger.' - 'logging.basicConfig') as m: - self.logger = functest_logger.Logger('os_utils') - self.assertTrue(m.called) - - def test_is_debug_false(self): - CONST.CI_DEBUG = False - self.assertFalse(self.logger.is_debug()) - - def test_is_debug_true(self): - CONST.CI_DEBUG = "True" - self.assertTrue(self.logger.is_debug()) - - -if __name__ == "__main__": - unittest.main(verbosity=2) diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py index 573fcb70..57e0c465 100644 --- a/functest/tests/unit/utils/test_functest_utils.py +++ b/functest/tests/unit/utils/test_functest_utils.py @@ -11,11 +11,11 @@ import logging import os import time import unittest -import urllib2 from git.exc import NoSuchPathError import mock import requests +from six.moves import urllib from functest.tests.unit import test_utils from functest.utils import functest_utils @@ -62,31 +62,31 @@ class FunctestUtilsTesting(unittest.TestCase): self.file_yaml = {'general': {'openstack': {'image_name': 'test_image_name'}}} - @mock.patch('urllib2.urlopen', - side_effect=urllib2.URLError('no host given')) + @mock.patch('six.moves.urllib.request.urlopen', + side_effect=urllib.error.URLError('no host given')) def test_check_internet_connectivity_failed(self, mock_method): self.assertFalse(functest_utils.check_internet_connectivity()) mock_method.assert_called_once_with(self.url, timeout=self.timeout) - @mock.patch('urllib2.urlopen') + @mock.patch('six.moves.urllib.request.urlopen') def test_check_internet_connectivity_default(self, mock_method): self.assertTrue(functest_utils.check_internet_connectivity()) mock_method.assert_called_once_with(self.url, timeout=self.timeout) - @mock.patch('urllib2.urlopen') + @mock.patch('six.moves.urllib.request.urlopen') def test_check_internet_connectivity_debian(self, mock_method): self.url = "https://www.debian.org/" self.assertTrue(functest_utils.check_internet_connectivity(self.url)) mock_method.assert_called_once_with(self.url, timeout=self.timeout) - @mock.patch('urllib2.urlopen', - side_effect=urllib2.URLError('no host given')) + @mock.patch('six.moves.urllib.request.urlopen', + side_effect=urllib.error.URLError('no host given')) def test_download_url_failed(self, mock_url): self.assertFalse(functest_utils.download_url(self.url, self.dest_path)) - @mock.patch('urllib2.urlopen') + @mock.patch('six.moves.urllib.request.urlopen') def test_download_url_default(self, mock_url): - with mock.patch("__builtin__.open", mock.mock_open()) as m, \ + with mock.patch("six.moves.builtins.open", mock.mock_open()) as m, \ mock.patch('functest.utils.functest_utils.shutil.copyfileobj')\ as mock_sh: name = self.url.rsplit('/')[-1] @@ -371,7 +371,7 @@ class FunctestUtilsTesting(unittest.TestCase): attrs = {'readline.side_effect': self.readline_side} m.configure_mock(**attrs) - with mock.patch("__builtin__.open") as mo: + with mock.patch("six.moves.builtins.open") as mo: mo.return_value = m self.assertEqual(functest_utils.get_resolvconf_ns(), self.test_ip[1:]) @@ -399,7 +399,8 @@ class FunctestUtilsTesting(unittest.TestCase): mock_logger_error): with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ as mock_subproc_open, \ - mock.patch('__builtin__.open', mock.mock_open()) as mopen: + mock.patch('six.moves.builtins.open', + mock.mock_open()) as mopen: FunctestUtilsTesting.readline = 0 @@ -428,7 +429,8 @@ class FunctestUtilsTesting(unittest.TestCase): ): with mock.patch('functest.utils.functest_utils.subprocess.Popen') \ as mock_subproc_open, \ - mock.patch('__builtin__.open', mock.mock_open()) as mopen: + mock.patch('six.moves.builtins.open', + mock.mock_open()) as mopen: FunctestUtilsTesting.readline = 0 @@ -503,7 +505,7 @@ class FunctestUtilsTesting(unittest.TestCase): @mock.patch('functest.utils.functest_utils.logger.error') def test_get_dict_by_test(self, mock_logger_error): - with mock.patch('__builtin__.open', mock.mock_open()), \ + with mock.patch('six.moves.builtins.open', mock.mock_open()), \ mock.patch('functest.utils.functest_utils.yaml.safe_load') \ as mock_yaml, \ mock.patch('functest.utils.functest_utils.get_testcases_' @@ -531,7 +533,7 @@ class FunctestUtilsTesting(unittest.TestCase): def test_get_parameter_from_yaml_failed(self): self.file_yaml['general'] = None - with mock.patch('__builtin__.open', mock.mock_open()), \ + with mock.patch('six.moves.builtins.open', mock.mock_open()), \ mock.patch('functest.utils.functest_utils.yaml.safe_load') \ as mock_yaml, \ self.assertRaises(ValueError) as excep: @@ -543,7 +545,7 @@ class FunctestUtilsTesting(unittest.TestCase): self.parameter) in excep.exception) def test_get_parameter_from_yaml_default(self): - with mock.patch('__builtin__.open', mock.mock_open()), \ + with mock.patch('six.moves.builtins.open', mock.mock_open()), \ mock.patch('functest.utils.functest_utils.yaml.safe_load') \ as mock_yaml: mock_yaml.return_value = self.file_yaml @@ -561,22 +563,6 @@ class FunctestUtilsTesting(unittest.TestCase): assert_called_once_with(self.parameter, self.config_yaml) - def test_check_success_rate_default(self): - with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \ - as mock_criteria: - mock_criteria.return_value = self.criteria - resp = functest_utils.check_success_rate(self.case_name, - self.result) - self.assertEqual(resp, 'PASS') - - def test_check_success_rate_failed(self): - with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \ - as mock_criteria: - mock_criteria.return_value = self.criteria - resp = functest_utils.check_success_rate(self.case_name, - 0) - self.assertEqual(resp, 'FAIL') - # TODO: merge_dicts def test_get_testcases_file_dir(self): @@ -586,7 +572,7 @@ class FunctestUtilsTesting(unittest.TestCase): "functest/ci/testcases.yaml") def test_get_functest_yaml(self): - with mock.patch('__builtin__.open', mock.mock_open()), \ + with mock.patch('six.moves.builtins.open', mock.mock_open()), \ mock.patch('functest.utils.functest_utils.yaml.safe_load') \ as mock_yaml: mock_yaml.return_value = self.file_yaml diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py index 7f3995d0..a7df264c 100644 --- a/functest/tests/unit/utils/test_openstack_utils.py +++ b/functest/tests/unit/utils/test_openstack_utils.py @@ -418,21 +418,45 @@ class OSUtilsTesting(unittest.TestCase): mock_logger_info.assert_called_once_with("OS_IDENTITY_API_VERSION is " "set in env as '%s'", '3') - def test_get_keystone_client(self): + @mock.patch('functest.utils.openstack_utils.get_session') + @mock.patch('functest.utils.openstack_utils.keystoneclient.Client') + @mock.patch('functest.utils.openstack_utils.get_keystone_client_version', + return_value='3') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='public') + def test_get_keystone_client_with_interface(self, mock_os_getenv, + mock_keystoneclient_version, + mock_key_client, + mock_get_session): mock_keystone_obj = mock.Mock() mock_session_obj = mock.Mock() - with mock.patch('functest.utils.openstack_utils' - '.get_keystone_client_version', return_value='3'), \ - mock.patch('functest.utils.openstack_utils' - '.keystoneclient.Client', - return_value=mock_keystone_obj) \ - as mock_key_client, \ - mock.patch('functest.utils.openstack_utils.get_session', - return_value=mock_session_obj): - self.assertEqual(openstack_utils.get_keystone_client(), - mock_keystone_obj) - mock_key_client.assert_called_once_with('3', - session=mock_session_obj) + mock_key_client.return_value = mock_keystone_obj + mock_get_session.return_value = mock_session_obj + self.assertEqual(openstack_utils.get_keystone_client(), + mock_keystone_obj) + mock_key_client.assert_called_once_with('3', + session=mock_session_obj, + interface='public') + + @mock.patch('functest.utils.openstack_utils.get_session') + @mock.patch('functest.utils.openstack_utils.keystoneclient.Client') + @mock.patch('functest.utils.openstack_utils.get_keystone_client_version', + return_value='3') + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value='admin') + def test_get_keystone_client_no_interface(self, mock_os_getenv, + mock_keystoneclient_version, + mock_key_client, + mock_get_session): + mock_keystone_obj = mock.Mock() + mock_session_obj = mock.Mock() + mock_key_client.return_value = mock_keystone_obj + mock_get_session.return_value = mock_session_obj + self.assertEqual(openstack_utils.get_keystone_client(), + mock_keystone_obj) + mock_key_client.assert_called_once_with('3', + session=mock_session_obj, + interface='admin') @mock.patch('functest.utils.openstack_utils.os.getenv', return_value=None) diff --git a/functest/utils/config.py b/functest/utils/config.py index b5b84501..d91f63ac 100755..100644 --- a/functest/utils/config.py +++ b/functest/utils/config.py @@ -1,8 +1,11 @@ -import os +#!/usr/bin/env python +import os import yaml -import env +import six + +from functest.utils import env class Config(object): @@ -16,7 +19,7 @@ class Config(object): self._set_others() def _parse(self, attr_now, left_parametes): - for param_n, param_v in left_parametes.iteritems(): + for param_n, param_v in six.iteritems(left_parametes): attr_further = self._get_attr_further(attr_now, param_n) if attr_further: self.__setattr__(attr_further, param_v) @@ -32,8 +35,3 @@ class Config(object): CONF = Config() - -if __name__ == "__main__": - print CONF.vnf_cloudify_ims - print CONF.vnf_cloudify_ims_tenant_images - print CONF.vnf_cloudify_ims_tenant_images_centos_7 diff --git a/functest/utils/constants.py b/functest/utils/constants.py index 2e8eb3f4..75c97c76 100755..100644 --- a/functest/utils/constants.py +++ b/functest/utils/constants.py @@ -1,20 +1,17 @@ -import config -import env +#!/usr/bin/env python + +import six + +from functest.utils import config +from functest.utils import env class Constants(object): def __init__(self): - for attr_n, attr_v in config.CONF.__dict__.iteritems(): + for attr_n, attr_v in six.iteritems(config.CONF.__dict__): self.__setattr__(attr_n, attr_v) - for env_n, env_v in env.ENV.__dict__.iteritems(): + for env_n, env_v in six.iteritems(env.ENV.__dict__): self.__setattr__(env_n, env_v) CONST = Constants() - -if __name__ == '__main__': - print CONST.__dict__ - print CONST.NODE_NAME - print CONST.vIMS_clearwater_blueprint_url - print CONST.vIMS_clearwater_blueprint_file_name - print CONST.vIMS_clearwater_blueprint_name diff --git a/functest/utils/decorators.py b/functest/utils/decorators.py index 46ffe35d..73e0a352 100644 --- a/functest/utils/decorators.py +++ b/functest/utils/decorators.py @@ -3,18 +3,19 @@ # pylint: disable=missing-docstring import errno +import functools import os -import urlparse import mock import requests.sessions +from six.moves import urllib def can_dump_request_to_file(method): def dump_preparedrequest(request, **kwargs): # pylint: disable=unused-argument - parseresult = urlparse.urlparse(request.url) + parseresult = urllib.parse.urlparse(request.url) if parseresult.scheme == "file": try: dirname = os.path.dirname(parseresult.path) @@ -33,7 +34,7 @@ def can_dump_request_to_file(method): def patch_request(method, url, **kwargs): with requests.sessions.Session() as session: - parseresult = urlparse.urlparse(url) + parseresult = urllib.parse.urlparse(url) if parseresult.scheme == "file": with mock.patch.object(session, 'send', side_effect=dump_preparedrequest): @@ -41,6 +42,7 @@ def can_dump_request_to_file(method): else: return session.request(method=method, url=url, **kwargs) + @functools.wraps(method) def hook(*args, **kwargs): with mock.patch('requests.api.request', side_effect=patch_request): return method(*args, **kwargs) diff --git a/functest/utils/env.py b/functest/utils/env.py index 7e4df2ea..c9629e15 100644 --- a/functest/utils/env.py +++ b/functest/utils/env.py @@ -1,6 +1,11 @@ +#!/usr/bin/env python + import os import re +import six + + default_envs = { 'NODE_NAME': 'unknown_pod', 'CI_DEBUG': 'false', @@ -17,9 +22,9 @@ default_envs = { class Environment(object): def __init__(self): - for k, v in os.environ.iteritems(): + for k, v in six.iteritems(os.environ): self.__setattr__(k, v) - for k, v in default_envs.iteritems(): + for k, v in six.iteritems(default_envs): if k not in os.environ: self.__setattr__(k, v) self._set_ci_run() diff --git a/functest/utils/functest_logger.py b/functest/utils/functest_logger.py deleted file mode 100644 index ba52829f..00000000 --- a/functest/utils/functest_logger.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -# jose.lausuch@ericsson.com -# 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 -# -# Logging levels: -# Level Numeric value -# CRITICAL 50 -# ERROR 40 -# WARNING 30 -# INFO 20 -# DEBUG 10 -# NOTSET 0 -# -# Usage: -# import functest_logger as fl -# logger = fl.Logger("script_name").getLogger() -# logger.info("message to be shown with - INFO - ") -# logger.debug("message to be shown with - DEBUG -") -import logging -import logging.config -import os - -import json - -from functest.utils.constants import CONST - -ignore = ["paramiko", - "stevedore.extension", - "keystoneauth.session", - "keystoneauth.identity.v3.base", - "novaclient.v2.client", - "neutronclient.v2_0.client", - "glanceclient.common.http", - "cinderclient.v2.client", - "cinderclient.client"] - - -class Logger(object): - - instance = None - - def __new__(cls, logger_name): - if cls.instance is None: - cls.instance = object.__new__(cls) - return cls.instance - - def __init__(self, logger_name): - self.setup_logging() - self.logger = logging.getLogger(logger_name) - for module_name in ignore: - logging.getLogger(module_name).setLevel(logging.WARNING) - - def getLogger(self): - return self.logger - - def is_debug(self): - if CONST.CI_DEBUG and CONST.CI_DEBUG.lower() == "true": - return True - return False - - def setup_logging(self, default_path=CONST.dir_functest_logging_cfg, - default_level=logging.INFO, - env_key='LOG_CFG'): - path = default_path - value = os.getenv(env_key, None) - if value: - path = value - if os.path.exists(path): - with open(path, 'rt') as f: - config = json.load(f) - if (config['handlers'] and - config['handlers']['console']): - stream_level = logging.INFO - if self.is_debug(): - stream_level = logging.DEBUG - config['handlers']['console']['level'] = stream_level - logging.config.dictConfig(config) - else: - logging.basicConfig(level=default_level) diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py index 7d993cbf..bf30f56e 100644 --- a/functest/utils/functest_utils.py +++ b/functest/utils/functest_utils.py @@ -9,24 +9,24 @@ # import functools import json +import logging import os import re import shutil import subprocess import sys import time -import urllib2 from datetime import datetime as dt import dns.resolver import requests +from six.moves import urllib import yaml from git import Repo from functest.utils import decorators -import functest.utils.functest_logger as ft_logger -logger = ft_logger.Logger("functest_utils").getLogger() +logger = logging.getLogger(__name__) # ---------------------------------------------------------- @@ -39,9 +39,9 @@ def check_internet_connectivity(url='http://www.opnfv.org/'): Check if there is access to the internet """ try: - urllib2.urlopen(url, timeout=5) + urllib.request.urlopen(url, timeout=5) return True - except urllib2.URLError: + except urllib.error.URLError: return False @@ -52,8 +52,8 @@ def download_url(url, dest_path): name = url.rsplit('/')[-1] dest = dest_path + "/" + name try: - response = urllib2.urlopen(url) - except (urllib2.HTTPError, urllib2.URLError): + response = urllib.request.urlopen(url) + except (urllib.error.HTTPError, urllib.error.URLError): return False with open(dest, 'wb') as f: @@ -318,7 +318,7 @@ def execute_command(cmd, info=False, error_msg="", f.write(line) else: line = line.replace('\n', '') - print line + print(line) sys.stdout.flush() if output_file: f.close() @@ -379,16 +379,6 @@ def get_functest_config(parameter): return get_parameter_from_yaml(parameter, yaml_) -def check_success_rate(case_name, result): - # It should be removed as TestCase tests criteria - # and result. - logger.warning('check_success_rate will be removed soon') - criteria = get_criteria_by_test(case_name) - if type(criteria) == int and result >= criteria: - return 'PASS' - return 'FAIL' - - def merge_dicts(dict1, dict2): for k in set(dict1.keys()).union(dict2.keys()): if k in dict1 and k in dict2: diff --git a/functest/utils/openstack/cinder.py b/functest/utils/openstack/cinder.py deleted file mode 100644 index f966468a..00000000 --- a/functest/utils/openstack/cinder.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# diff --git a/functest/utils/openstack/glance.py b/functest/utils/openstack/glance.py deleted file mode 100644 index f966468a..00000000 --- a/functest/utils/openstack/glance.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# diff --git a/functest/utils/openstack/keystone.py b/functest/utils/openstack/keystone.py deleted file mode 100644 index f966468a..00000000 --- a/functest/utils/openstack/keystone.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# diff --git a/functest/utils/openstack/neutron.py b/functest/utils/openstack/neutron.py deleted file mode 100644 index f966468a..00000000 --- a/functest/utils/openstack/neutron.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# diff --git a/functest/utils/openstack/nova.py b/functest/utils/openstack/nova.py deleted file mode 100644 index f966468a..00000000 --- a/functest/utils/openstack/nova.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -# 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 -# diff --git a/functest/utils/openstack_clean.py b/functest/utils/openstack_clean.py index ce61fcac..29106d9e 100755 --- a/functest/utils/openstack_clean.py +++ b/functest/utils/openstack_clean.py @@ -24,13 +24,13 @@ import time +import logging import yaml -import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST -logger = ft_logger.Logger("openstack_clean").getLogger() +logger = logging.getLogger(__name__) OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file @@ -428,4 +428,5 @@ def main(): if __name__ == '__main__': + logging.basicConfig() main() diff --git a/functest/utils/openstack_snapshot.py b/functest/utils/openstack_snapshot.py index e64030f7..952fb7bb 100755 --- a/functest/utils/openstack_snapshot.py +++ b/functest/utils/openstack_snapshot.py @@ -20,13 +20,13 @@ # http://www.apache.org/licenses/LICENSE-2.0 # +import logging import yaml -import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils from functest.utils.constants import CONST -logger = ft_logger.Logger("openstack_snapshot").getLogger() +logger = logging.getLogger(__name__) OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file @@ -162,4 +162,5 @@ def main(): if __name__ == '__main__': + logging.basicConfig() main() diff --git a/functest/utils/openstack_tacker.py b/functest/utils/openstack_tacker.py index 8327fdbe..9fd9d5c4 100644 --- a/functest/utils/openstack_tacker.py +++ b/functest/utils/openstack_tacker.py @@ -11,13 +11,13 @@ # http://www.apache.org/licenses/LICENSE-2.0 ########################################################################## +import logging from tackerclient.v1_0 import client as tackerclient -import functest.utils.functest_logger as ft_logger import functest.utils.openstack_utils as os_utils import time -logger = ft_logger.Logger("tacker_utils").getLogger() +logger = logging.getLogger(__name__) def get_tacker_client(other_creds={}): diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index 929a761e..8bd95052 100644 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -8,7 +8,7 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -import os +import logging import os.path import re import sys @@ -23,10 +23,9 @@ from novaclient import client as novaclient from keystoneclient import client as keystoneclient from neutronclient.neutron import client as neutronclient -import functest.utils.functest_logger as ft_logger import functest.utils.functest_utils as ft_utils -logger = ft_logger.Logger("openstack_utils").getLogger() +logger = logging.getLogger(__name__) DEFAULT_API_VERSION = '2' DEFAULT_HEAT_API_VERSION = '1' @@ -139,11 +138,11 @@ def get_credentials_for_rally(): endpoint_types = [('internalURL', 'internal'), ('publicURL', 'public'), ('adminURL', 'admin')] - endpoint_type = os.getenv('OS_ENDPOINT_TYPE') + endpoint_type = get_endpoint_type_from_env() if endpoint_type is not None: cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE') for k, v in endpoint_types: - if endpoint_type == k: + if endpoint_type == v: rally_conf[cred_key] = v region_name = os.getenv('OS_REGION_NAME') @@ -158,6 +157,14 @@ def get_credentials_for_rally(): return rally_conf +def get_endpoint_type_from_env(): + endpoint_type = os.environ.get("OS_ENDPOINT_TYPE", + os.environ.get("OS_INTERFACE")) + if endpoint_type and "URL" in endpoint_type: + endpoint_type = endpoint_type.replace("URL", "") + return endpoint_type + + def get_session_auth(other_creds={}): loader = loading.get_plugin_loader('password') creds = get_credentials(other_creds) @@ -198,7 +205,9 @@ def get_keystone_client_version(): def get_keystone_client(other_creds={}): sess = get_session(other_creds) - return keystoneclient.Client(get_keystone_client_version(), session=sess) + return keystoneclient.Client(get_keystone_client_version(), + session=sess, + interface=os.getenv('OS_INTERFACE', 'admin')) def get_nova_client_version(): @@ -277,7 +286,7 @@ def get_instances(nova_client): try: instances = nova_client.servers.list(search_opts={'all_tenants': 1}) return instances - except Exception, e: + except Exception as e: logger.error("Error [get_instances(nova_client)]: %s" % e) return None @@ -286,7 +295,7 @@ def get_instance_status(nova_client, instance): try: instance = nova_client.servers.get(instance.id) return instance.status - except Exception, e: + except Exception as e: logger.error("Error [get_instance_status(nova_client)]: %s" % e) return None @@ -295,7 +304,7 @@ def get_instance_by_name(nova_client, instance_name): try: instance = nova_client.servers.find(name=instance_name) return instance - except Exception, e: + except Exception as e: logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s" % (instance_name, e)) return None @@ -325,7 +334,7 @@ def get_aggregates(nova_client): try: aggregates = nova_client.aggregates.list() return aggregates - except Exception, e: + except Exception as e: logger.error("Error [get_aggregates(nova_client)]: %s" % e) return None @@ -335,7 +344,7 @@ def get_aggregate_id(nova_client, aggregate_name): aggregates = get_aggregates(nova_client) _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0] return _id - except Exception, e: + except Exception as e: logger.error("Error [get_aggregate_id(nova_client, %s)]:" " %s" % (aggregate_name, e)) return None @@ -345,7 +354,7 @@ def get_availability_zones(nova_client): try: availability_zones = nova_client.availability_zones.list() return availability_zones - except Exception, e: + except Exception as e: logger.error("Error [get_availability_zones(nova_client)]: %s" % e) return None @@ -354,7 +363,7 @@ def get_availability_zone_names(nova_client): try: az_names = [az.zoneName for az in get_availability_zones(nova_client)] return az_names - except Exception, e: + except Exception as e: logger.error("Error [get_availability_zone_names(nova_client)]:" " %s" % e) return None @@ -372,7 +381,7 @@ def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True): # flavor extra specs are not configured, therefore skip the update pass - except Exception, e: + except Exception as e: logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', " "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e)) return None @@ -405,7 +414,7 @@ def get_floating_ips(nova_client): try: floating_ips = nova_client.floating_ips.list() return floating_ips - except Exception, e: + except Exception as e: logger.error("Error [get_floating_ips(nova_client)]: %s" % e) return None @@ -418,7 +427,7 @@ def get_hypervisors(nova_client): if hypervisor.state == "up": nodes.append(hypervisor.hypervisor_hostname) return nodes - except Exception, e: + except Exception as e: logger.error("Error [get_hypervisors(nova_client)]: %s" % e) return None @@ -427,7 +436,7 @@ def create_aggregate(nova_client, aggregate_name, av_zone): try: nova_client.aggregates.create(aggregate_name, av_zone) return True - except Exception, e: + except Exception as e: logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s" % (aggregate_name, av_zone, e)) return None @@ -438,7 +447,7 @@ def add_host_to_aggregate(nova_client, aggregate_name, compute_host): aggregate_id = get_aggregate_id(nova_client, aggregate_name) nova_client.aggregates.add_host(aggregate_id, compute_host) return True - except Exception, e: + except Exception as e: logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s" % (aggregate_name, compute_host, e)) return None @@ -450,7 +459,7 @@ def create_aggregate_with_host( create_aggregate(nova_client, aggregate_name, av_zone) add_host_to_aggregate(nova_client, aggregate_name, compute_host) return True - except Exception, e: + except Exception as e: logger.error("Error [create_aggregate_with_host(" "nova_client, %s, %s, %s)]: %s" % (aggregate_name, av_zone, compute_host, e)) @@ -543,7 +552,7 @@ def create_floating_ip(neutron_client): ip_json = neutron_client.create_floatingip({'floatingip': props}) fip_addr = ip_json['floatingip']['floating_ip_address'] fip_id = ip_json['floatingip']['id'] - except Exception, e: + except Exception as e: logger.error("Error [create_floating_ip(neutron_client)]: %s" % e) return None return {'fip_addr': fip_addr, 'fip_id': fip_id} @@ -553,7 +562,7 @@ def add_floating_ip(nova_client, server_id, floatingip_addr): try: nova_client.servers.add_floating_ip(server_id, floatingip_addr) return True - except Exception, e: + except Exception as e: logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s" % (server_id, floatingip_addr, e)) return False @@ -563,7 +572,7 @@ def delete_instance(nova_client, instance_id): try: nova_client.servers.force_delete(instance_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_instance(nova_client, '%s')]: %s" % (instance_id, e)) return False @@ -573,7 +582,7 @@ def delete_floating_ip(nova_client, floatingip_id): try: nova_client.floating_ips.delete(floatingip_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s" % (floatingip_id, e)) return False @@ -584,7 +593,7 @@ def remove_host_from_aggregate(nova_client, aggregate_name, compute_host): aggregate_id = get_aggregate_id(nova_client, aggregate_name) nova_client.aggregates.remove_host(aggregate_id, compute_host) return True - except Exception, e: + except Exception as e: logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:" " %s" % (aggregate_name, compute_host, e)) return False @@ -603,7 +612,7 @@ def delete_aggregate(nova_client, aggregate_name): remove_hosts_from_aggregate(nova_client, aggregate_name) nova_client.aggregates.delete(aggregate_name) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_aggregate(nova_client, %s)]: %s" % (aggregate_name, e)) return False @@ -706,7 +715,7 @@ def create_neutron_net(neutron_client, name): network = neutron_client.create_network(body=json_body) network_dict = network['network'] return network_dict['id'] - except Exception, e: + except Exception as e: logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s" % (name, e)) return None @@ -718,7 +727,7 @@ def create_neutron_subnet(neutron_client, name, cidr, net_id): try: subnet = neutron_client.create_subnet(body=json_body) return subnet['subnets'][0]['id'] - except Exception, e: + except Exception as e: logger.error("Error [create_neutron_subnet(neutron_client, '%s', " "'%s', '%s')]: %s" % (name, cidr, net_id, e)) return None @@ -729,7 +738,7 @@ def create_neutron_router(neutron_client, name): try: router = neutron_client.create_router(json_body) return router['router']['id'] - except Exception, e: + except Exception as e: logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s" % (name, e)) return None @@ -745,7 +754,7 @@ def create_neutron_port(neutron_client, name, network_id, ip): try: port = neutron_client.create_port(body=json_body) return port['port']['id'] - except Exception, e: + except Exception as e: logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', " "'%s')]: %s" % (name, network_id, ip, e)) return None @@ -756,7 +765,7 @@ def update_neutron_net(neutron_client, network_id, shared=False): try: neutron_client.update_network(network_id, body=json_body) return True - except Exception, e: + except Exception as e: logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: " "%s" % (network_id, str(shared), e)) return False @@ -770,7 +779,7 @@ def update_neutron_port(neutron_client, port_id, device_owner): port = neutron_client.update_port(port=port_id, body=json_body) return port['port']['id'] - except Exception, e: + except Exception as e: logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:" " %s" % (port_id, device_owner, e)) return None @@ -781,7 +790,7 @@ def add_interface_router(neutron_client, router_id, subnet_id): try: neutron_client.add_interface_router(router=router_id, body=json_body) return True - except Exception, e: + except Exception as e: logger.error("Error [add_interface_router(neutron_client, '%s', " "'%s')]: %s" % (router_id, subnet_id, e)) return False @@ -793,7 +802,7 @@ def add_gateway_router(neutron_client, router_id): try: neutron_client.add_gateway_router(router_id, router_dict) return True - except Exception, e: + except Exception as e: logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s" % (router_id, e)) return False @@ -803,7 +812,7 @@ def delete_neutron_net(neutron_client, network_id): try: neutron_client.delete_network(network_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s" % (network_id, e)) return False @@ -813,7 +822,7 @@ def delete_neutron_subnet(neutron_client, subnet_id): try: neutron_client.delete_subnet(subnet_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s" % (subnet_id, e)) return False @@ -823,7 +832,7 @@ def delete_neutron_router(neutron_client, router_id): try: neutron_client.delete_router(router=router_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s" % (router_id, e)) return False @@ -833,7 +842,7 @@ def delete_neutron_port(neutron_client, port_id): try: neutron_client.delete_port(port_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s" % (port_id, e)) return False @@ -845,7 +854,7 @@ def remove_interface_router(neutron_client, router_id, subnet_id): neutron_client.remove_interface_router(router=router_id, body=json_body) return True - except Exception, e: + except Exception as e: logger.error("Error [remove_interface_router(neutron_client, '%s', " "'%s')]: %s" % (router_id, subnet_id, e)) return False @@ -855,7 +864,7 @@ def remove_gateway_router(neutron_client, router_id): try: neutron_client.remove_gateway_router(router_id) return True - except Exception, e: + except Exception as e: logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s" % (router_id, e)) return False @@ -985,7 +994,7 @@ def get_security_groups(neutron_client): security_groups = neutron_client.list_security_groups()[ 'security_groups'] return security_groups - except Exception, e: + except Exception as e: logger.error("Error [get_security_groups(neutron_client)]: %s" % e) return None @@ -1006,7 +1015,7 @@ def create_security_group(neutron_client, sg_name, sg_description): try: secgroup = neutron_client.create_security_group(json_body) return secgroup['security_group'] - except Exception, e: + except Exception as e: logger.error("Error [create_security_group(neutron_client, '%s', " "'%s')]: %s" % (sg_name, sg_description, e)) return None @@ -1061,7 +1070,7 @@ def get_security_group_rules(neutron_client, sg_id): security_rules = [rule for rule in security_rules if rule["security_group_id"] == sg_id] return security_rules - except Exception, e: + except Exception as e: logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:" " %s" % e) return None @@ -1080,7 +1089,7 @@ def check_security_group_rules(neutron_client, sg_id, direction, protocol, return True else: return False - except Exception, e: + except Exception as e: logger.error("Error [check_security_group_rules(" " neutron_client, sg_id, direction," " protocol, port_min=None, port_max=None)]: " @@ -1132,7 +1141,7 @@ def add_secgroup_to_instance(nova_client, instance_id, secgroup_id): try: nova_client.servers.add_security_group(instance_id, secgroup_id) return True - except Exception, e: + except Exception as e: logger.error("Error [add_secgroup_to_instance(nova_client, '%s', " "'%s')]: %s" % (instance_id, secgroup_id, e)) return False @@ -1148,7 +1157,7 @@ def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota): neutron_client.update_quota(tenant_id=tenant_id, body=json_body) return True - except Exception, e: + except Exception as e: logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', " "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e)) return False @@ -1158,7 +1167,7 @@ def delete_security_group(neutron_client, secgroup_id): try: neutron_client.delete_security_group(secgroup_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_security_group(neutron_client, '%s')]: %s" % (secgroup_id, e)) return False @@ -1171,7 +1180,7 @@ def get_images(nova_client): try: images = nova_client.images.list() return images - except Exception, e: + except Exception as e: logger.error("Error [get_images]: %s" % e) return None @@ -1207,7 +1216,7 @@ def create_glance_image(glance_client, image_name, file_path, disk="qcow2", with open(file_path) as image_data: glance_client.images.upload(image_id, image_data) return image_id - except Exception, e: + except Exception as e: logger.error("Error [create_glance_image(glance_client, '%s', '%s', " "'%s')]: %s" % (image_name, file_path, public, e)) return None @@ -1237,7 +1246,7 @@ def delete_glance_image(nova_client, image_id): try: nova_client.images.delete(image_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_glance_image(nova_client, '%s')]: %s" % (image_id, e)) return False @@ -1250,7 +1259,7 @@ def get_volumes(cinder_client): try: volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1}) return volumes - except Exception, e: + except Exception as e: logger.error("Error [get_volumes(cinder_client)]: %s" % e) return None @@ -1263,7 +1272,7 @@ def list_volume_types(cinder_client, public=True, private=True): if not private: volume_types = [vt for vt in volume_types if vt.is_public] return volume_types - except Exception, e: + except Exception as e: logger.error("Error [list_volume_types(cinder_client)]: %s" % e) return None @@ -1272,7 +1281,7 @@ def create_volume_type(cinder_client, name): try: volume_type = cinder_client.volume_types.create(name) return volume_type - except Exception, e: + except Exception as e: logger.error("Error [create_volume_type(cinder_client, '%s')]: %s" % (name, e)) return None @@ -1287,7 +1296,7 @@ def update_cinder_quota(cinder_client, tenant_id, vols_quota, try: cinder_client.quotas.update(tenant_id, **quotas_values) return True - except Exception, e: + except Exception as e: logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', " "'%s' '%s')]: %s" % (tenant_id, vols_quota, snapshots_quota, gigabytes_quota, e)) @@ -1305,7 +1314,7 @@ def delete_volume(cinder_client, volume_id, forced=False): else: cinder_client.volumes.delete(volume_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s" % (volume_id, str(forced), e)) return False @@ -1315,7 +1324,7 @@ def delete_volume_type(cinder_client, volume_type): try: cinder_client.volume_types.delete(volume_type) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s" % (volume_type, e)) return False @@ -1331,7 +1340,7 @@ def get_tenants(keystone_client): else: tenants = keystone_client.tenants.list() return tenants - except Exception, e: + except Exception as e: logger.error("Error [get_tenants(keystone_client)]: %s" % e) return None @@ -1340,7 +1349,7 @@ def get_users(keystone_client): try: users = keystone_client.users.list() return users - except Exception, e: + except Exception as e: logger.error("Error [get_users(keystone_client)]: %s" % e) return None @@ -1388,7 +1397,7 @@ def create_tenant(keystone_client, tenant_name, tenant_description): tenant_description, enabled=True) return tenant.id - except Exception, e: + except Exception as e: logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s" % (tenant_name, tenant_description, e)) return None @@ -1419,7 +1428,7 @@ def create_user(keystone_client, user_name, user_password, tenant_id, enabled=True) return user.id - except Exception, e: + except Exception as e: logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'" "'%s')]: %s" % (user_name, user_password, user_email, tenant_id, e)) @@ -1444,7 +1453,7 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id): else: keystone_client.roles.add_user_role(user_id, role_id, tenant_id) return True - except Exception, e: + except Exception as e: logger.error("Error [add_role_user(keystone_client, '%s', '%s'" "'%s')]: %s " % (user_id, role_id, tenant_id, e)) return False @@ -1457,7 +1466,7 @@ def delete_tenant(keystone_client, tenant_id): else: keystone_client.tenants.delete(tenant_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_tenant(keystone_client, '%s')]: %s" % (tenant_id, e)) return False @@ -1467,7 +1476,7 @@ def delete_user(keystone_client, user_id): try: keystone_client.users.delete(user_id) return True - except Exception, e: + except Exception as e: logger.error("Error [delete_user(keystone_client, '%s')]: %s" % (user_id, e)) return False @@ -1480,6 +1489,6 @@ def get_resource(heat_client, stack_id, resource): try: resources = heat_client.resources.get(stack_id, resource) return resources - except Exception, e: + except Exception as e: logger.error("Error [get_resource]: %s" % e) return None diff --git a/requirements.txt b/requirements.txt index 92f16bcc..65b36979 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,17 +14,19 @@ python-keystoneclient==3.5.0 python-neutronclient==6.0.0 python-novaclient==6.0.0 python-congressclient==1.5.0 -virtualenv==15.1.0 +python-tackerclient==0.7.0 pexpect==4.0 requests>=2.8.0 -robotframework==2.9.1 -robotframework-requests==0.3.8 -robotframework-sshlibrary==2.1.1 +robotframework==3.0.2 +robotframework-httplibrary==0.4.2 +robotframework-requests==0.4.7 +robotframework-sshlibrary==2.1.3 +jmespath==0.9.2 configObj==5.0.6 Flask==0.10.1 xmltodict==0.9.2 scp==0.10.2 -paramiko==1.16.0 +paramiko==2.1.2 subprocess32 shyaml dnspython @@ -32,3 +34,6 @@ Pillow==3.3.0 click==6.6 openbaton-cli==2.2.1-beta7 mock==1.3.0 +iniparse==0.4 +PrettyTable>=0.7.1,<0.8 # BSD +six>=1.9.0 # MIT diff --git a/run_unit_tests.sh b/run_unit_tests.sh index 9780de7a..86096fab 100755 --- a/run_unit_tests.sh +++ b/run_unit_tests.sh @@ -14,13 +14,16 @@ fi # *************** echo "Running unit tests..." +sudo apt-get install -y build-essential python-dev python-pip +sudo pip install virtualenv==15.1.0 + # start vitual env virtualenv $WORKSPACE/functest_venv source $WORKSPACE/functest_venv/bin/activate # install python packages -sudo apt-get install -y build-essential python-dev python-pip pip install --upgrade pip +pip install -r $WORKSPACE/requirements.txt pip install -r $WORKSPACE/test-requirements.txt pip install $WORKSPACE diff --git a/test-requirements.txt b/test-requirements.txt index 471e9c30..b0d4ff8d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,24 +5,6 @@ # which accompanies this distribution, and is available at # http://www.apache.org/licenses/LICENSE-2.0 # -click==6.6 coverage==4.1 -dnspython==1.15.0 -gitpython==1.0.1 -iniparse==0.4 mock==1.3.0 nose==1.3.7 -python-ceilometerclient==2.6.2 -python-congressclient==1.5.0 -python-heatclient==1.7.0 -python-keystoneclient==3.5.0 -python-neutronclient==6.0.0 -python-openstackclient==2.3.0 -python-tackerclient==0.7.0 -pyyaml==3.10 -requests==2.8.0 -robotframework==2.9.1 -robotframework-requests==0.3.8 -robotframework-sshlibrary==2.1.1 -subprocess32==3.2.7 -virtualenv==15.1.0 |