Merge "Documentation for unit test project"
authorMorgan Richomme <morgan.richomme@orange.com>
Fri, 19 May 2017 08:37:34 +0000 (08:37 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Fri, 19 May 2017 08:37:34 +0000 (08:37 +0000)
167 files changed:
.gitignore
INFO
docker/Dockerfile
docker/Dockerfile.aarch64
docker/add_images.sh
docs/api/Makefile [new file with mode: 0644]
docs/api/apidoc/functest.core.feature.rst [new file with mode: 0644]
docs/api/apidoc/functest.core.rst [new file with mode: 0644]
docs/api/apidoc/functest.core.testcase.rst [new file with mode: 0644]
docs/api/apidoc/functest.core.vnf_base.rst [new file with mode: 0644]
docs/api/apidoc/functest.opnfv_tests.rst [new file with mode: 0644]
docs/api/apidoc/functest.opnfv_tests.sdn.odl.odl.rst [new file with mode: 0644]
docs/api/apidoc/functest.opnfv_tests.sdn.odl.rst [new file with mode: 0644]
docs/api/apidoc/functest.opnfv_tests.sdn.rst [new file with mode: 0644]
docs/api/apidoc/functest.rst [new file with mode: 0644]
docs/api/apidoc/modules.rst [new file with mode: 0644]
docs/api/conf.py [new file with mode: 0644]
docs/api/index.rst [new file with mode: 0644]
docs/com/pres/framework/framework.html [new file with mode: 0644]
docs/com/pres/framework/framework.md [new file with mode: 0644]
docs/results/danube/1.0/apex.html [new file with mode: 0644]
docs/results/danube/1.0/compass.html [new file with mode: 0644]
docs/results/danube/1.0/fuel.html [new file with mode: 0644]
docs/results/danube/1.0/joid.html [new file with mode: 0644]
docs/results/danube/1.0/scenario_history.txt [new file with mode: 0644]
docs/results/danube/1.0/validated_scenario_history.txt [new file with mode: 0644]
docs/results/danube/2.0/apex.html [new file with mode: 0644]
docs/results/danube/2.0/compass.html [new file with mode: 0644]
docs/results/danube/2.0/fuel.html [new file with mode: 0644]
docs/results/danube/2.0/joid.html [new file with mode: 0644]
docs/results/danube/2.0/scenario_history.txt [new file with mode: 0644]
docs/results/danube/2.0/validated_scenario_history.txt [new file with mode: 0644]
docs/results/img/weather-clear.png [new file with mode: 0644]
docs/results/img/weather-few-clouds.png [new file with mode: 0644]
docs/results/img/weather-overcast.png [new file with mode: 0644]
docs/results/img/weather-storm.png [new file with mode: 0644]
docs/results/js/default.css [new file with mode: 0644]
docs/results/js/gauge.js [new file with mode: 0644]
docs/results/js/trend.js [new file with mode: 0644]
docs/testing/user/configguide/configguide.rst
docs/testing/user/userguide/index.rst
docs/testing/user/userguide/runfunctest.rst
functest/ci/check_os.sh
functest/ci/config_aarch64_patch.yaml
functest/ci/config_functest.yaml [changed mode: 0755->0644]
functest/ci/config_patch.yaml [changed mode: 0755->0644]
functest/ci/download_images.sh [new file with mode: 0644]
functest/ci/generate_report.py [deleted file]
functest/ci/installer_params.yaml
functest/ci/logging.ini [new file with mode: 0644]
functest/ci/logging.json [deleted file]
functest/ci/prepare_env.py
functest/ci/rally_aarch64_patch.conf
functest/ci/run_tests.py
functest/ci/testcases.yaml [changed mode: 0755->0644]
functest/ci/tier_builder.py
functest/ci/tier_handler.py
functest/cli/cli_base.py
functest/cli/commands/cli_env.py
functest/cli/commands/cli_os.py
functest/cli/commands/cli_testcase.py
functest/cli/commands/cli_tier.py
functest/core/feature.py
functest/core/pytest_suite_runner.py
functest/core/testcase.py
functest/core/vnf.py [moved from functest/core/vnf_base.py with 53% similarity]
functest/energy/__init__.py [moved from functest/opnfv_tests/vnf/rnc/__init__.py with 100% similarity]
functest/energy/energy.py [new file with mode: 0644]
functest/opnfv_tests/features/barometer.py
functest/opnfv_tests/features/copper.py [deleted file]
functest/opnfv_tests/features/doctor.py [deleted file]
functest/opnfv_tests/features/domino.py [deleted file]
functest/opnfv_tests/features/netready.py [deleted file]
functest/opnfv_tests/features/odl_sfc.py [deleted file]
functest/opnfv_tests/features/promise.py [deleted file]
functest/opnfv_tests/features/sdnvpn.py [deleted file]
functest/opnfv_tests/features/security_scan.py [deleted file]
functest/opnfv_tests/mano/orchestra.py
functest/opnfv_tests/openstack/examples/create_instance_and_ip.py [deleted file]
functest/opnfv_tests/openstack/rally/rally.py
functest/opnfv_tests/openstack/refstack_client/defcore.txt
functest/opnfv_tests/openstack/refstack_client/refstack_client.py
functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
functest/opnfv_tests/openstack/snaps/api_check.py
functest/opnfv_tests/openstack/snaps/connection_check.py
functest/opnfv_tests/openstack/snaps/health_check.py
functest/opnfv_tests/openstack/snaps/smoke.py
functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
functest/opnfv_tests/openstack/snaps/snaps_utils.py
functest/opnfv_tests/openstack/tempest/conf_utils.py
functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
functest/opnfv_tests/openstack/tempest/tempest.py
functest/opnfv_tests/openstack/vping/vping_base.py
functest/opnfv_tests/openstack/vping/vping_ssh.py
functest/opnfv_tests/openstack/vping/vping_userdata.py
functest/opnfv_tests/sdn/odl/odl.py
functest/opnfv_tests/sdn/onos/onos.py
functest/opnfv_tests/sdn/onos/sfc/sfc.py
functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
functest/opnfv_tests/sdn/onos/teston/adapters/client.py
functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
functest/opnfv_tests/vnf/aaa/aaa.py
functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
functest/opnfv_tests/vnf/ims/cloudify_ims.py
functest/opnfv_tests/vnf/ims/opera_ims.py
functest/opnfv_tests/vnf/ims/orchestra_ims.py
functest/opnfv_tests/vnf/ims/orchestra_ims.yaml
functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py
functest/opnfv_tests/vnf/rnc/parser.py [deleted file]
functest/opnfv_tests/vnf/router/vyos_vrouter.py
functest/tests/unit/ci/test_generate_report.py [deleted file]
functest/tests/unit/ci/test_prepare_env.py
functest/tests/unit/ci/test_run_tests.py
functest/tests/unit/ci/test_tier_builder.py
functest/tests/unit/ci/test_tier_handler.py
functest/tests/unit/cli/commands/test_cli_env.py
functest/tests/unit/cli/commands/test_cli_os.py
functest/tests/unit/cli/commands/test_cli_testcase.py
functest/tests/unit/cli/commands/test_cli_tier.py
functest/tests/unit/core/test_feature.py [new file with mode: 0644]
functest/tests/unit/core/test_pytest_suite_runner.py [new file with mode: 0644]
functest/tests/unit/core/test_testcase.py
functest/tests/unit/core/test_vnf.py [new file with mode: 0644]
functest/tests/unit/core/test_vnf_base.py [deleted file]
functest/tests/unit/energy/__init__.py [moved from functest/tests/unit/opnfv_tests/__init__.py with 100% similarity]
functest/tests/unit/energy/test_functest_energy.py [new file with mode: 0644]
functest/tests/unit/features/__init__.py [moved from functest/tests/unit/opnfv_tests/openstack/__init__.py with 100% similarity]
functest/tests/unit/features/test_barometer.py [new file with mode: 0644]
functest/tests/unit/odl/test_odl.py
functest/tests/unit/openstack/__init__.py [moved from functest/tests/unit/opnfv_tests/openstack/rally/__init__.py with 100% similarity]
functest/tests/unit/openstack/rally/__init__.py [moved from functest/tests/unit/opnfv_tests/openstack/refstack_client/__init__.py with 100% similarity]
functest/tests/unit/openstack/rally/test_rally.py [moved from functest/tests/unit/opnfv_tests/openstack/rally/test_rally.py with 96% similarity]
functest/tests/unit/openstack/refstack_client/__init__.py [moved from functest/tests/unit/opnfv_tests/openstack/tempest/__init__.py with 100% similarity]
functest/tests/unit/openstack/refstack_client/test_refstack_client.py [moved from functest/tests/unit/opnfv_tests/openstack/refstack_client/test_refstack_client.py with 100% similarity]
functest/tests/unit/openstack/tempest/__init__.py [moved from functest/tests/unit/opnfv_tests/vnf/__init__.py with 100% similarity]
functest/tests/unit/openstack/tempest/test_conf_utils.py [moved from functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py with 100% similarity]
functest/tests/unit/openstack/tempest/test_tempest.py [moved from functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py with 55% similarity]
functest/tests/unit/utils/test_decorators.py [new file with mode: 0644]
functest/tests/unit/utils/test_functest_logger.py [deleted file]
functest/tests/unit/utils/test_functest_utils.py
functest/tests/unit/utils/test_openstack_utils.py
functest/tests/unit/vnf/__init__.py [moved from functest/tests/unit/opnfv_tests/vnf/ims/__init__.py with 100% similarity]
functest/tests/unit/vnf/ims/__init__.py [new file with mode: 0644]
functest/tests/unit/vnf/ims/test_clearwater.py [moved from functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py with 100% similarity]
functest/tests/unit/vnf/ims/test_cloudify_ims.py [moved from functest/tests/unit/opnfv_tests/vnf/ims/test_cloudify_ims.py with 100% similarity]
functest/tests/unit/vnf/ims/test_ims_base.py [moved from functest/tests/unit/opnfv_tests/vnf/ims/test_ims_base.by with 89% similarity]
functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py [moved from functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py with 100% similarity]
functest/tests/unit/vnf/rnc/__init__.py [new file with mode: 0644]
functest/utils/config.py [changed mode: 0755->0644]
functest/utils/constants.py [changed mode: 0755->0644]
functest/utils/decorators.py
functest/utils/env.py
functest/utils/functest_logger.py [deleted file]
functest/utils/functest_utils.py
functest/utils/openstack/cinder.py [deleted file]
functest/utils/openstack/glance.py [deleted file]
functest/utils/openstack/keystone.py [deleted file]
functest/utils/openstack/neutron.py [deleted file]
functest/utils/openstack/nova.py [deleted file]
functest/utils/openstack_clean.py
functest/utils/openstack_snapshot.py
functest/utils/openstack_tacker.py
functest/utils/openstack_utils.py
requirements.txt
run_unit_tests.sh
test-requirements.txt

index 0bb8500..d8ba0a9 100644 (file)
@@ -5,6 +5,7 @@
 .pydevproject
 rally_conf.json
 /docs_build/
+_build
 /docs_output/
 /releng/
 .idea
diff --git a/INFO b/INFO
index 6f8963e..c38b3c6 100644 (file)
--- a/INFO
+++ b/INFO
@@ -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
 
index 6137cc9..202eb5c 100644 (file)
@@ -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
 
index 83df2d0..b03c6d9 100644 (file)
@@ -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
 
index af2956c..919cecd 100755 (executable)
@@ -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/api/Makefile b/docs/api/Makefile
new file mode 100644 (file)
index 0000000..ca9cfdc
--- /dev/null
@@ -0,0 +1,225 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help
+help:
+       @echo "Please use \`make <target>' where <target> is one of"
+       @echo "  html       to make standalone HTML files"
+       @echo "  dirhtml    to make HTML files named index.html in directories"
+       @echo "  singlehtml to make a single large HTML file"
+       @echo "  pickle     to make pickle files"
+       @echo "  json       to make JSON files"
+       @echo "  htmlhelp   to make HTML files and a HTML help project"
+       @echo "  qthelp     to make HTML files and a qthelp project"
+       @echo "  applehelp  to make an Apple Help Book"
+       @echo "  devhelp    to make HTML files and a Devhelp project"
+       @echo "  epub       to make an epub"
+       @echo "  epub3      to make an epub3"
+       @echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+       @echo "  latexpdf   to make LaTeX files and run them through pdflatex"
+       @echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+       @echo "  text       to make text files"
+       @echo "  man        to make manual pages"
+       @echo "  texinfo    to make Texinfo files"
+       @echo "  info       to make Texinfo files and run them through makeinfo"
+       @echo "  gettext    to make PO message catalogs"
+       @echo "  changes    to make an overview of all changed/added/deprecated items"
+       @echo "  xml        to make Docutils-native XML files"
+       @echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
+       @echo "  linkcheck  to check all external links for integrity"
+       @echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
+       @echo "  coverage   to run coverage check of the documentation (if enabled)"
+       @echo "  dummy      to check syntax errors of document sources"
+
+.PHONY: clean
+clean:
+       rm -rf $(BUILDDIR)/*
+
+.PHONY: html
+html:
+       $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+.PHONY: dirhtml
+dirhtml:
+       $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+       @echo
+       @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+.PHONY: singlehtml
+singlehtml:
+       $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+       @echo
+       @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+.PHONY: pickle
+pickle:
+       $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+       @echo
+       @echo "Build finished; now you can process the pickle files."
+
+.PHONY: json
+json:
+       $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+       @echo
+       @echo "Build finished; now you can process the JSON files."
+
+.PHONY: htmlhelp
+htmlhelp:
+       $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+       @echo
+       @echo "Build finished; now you can run HTML Help Workshop with the" \
+             ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+.PHONY: qthelp
+qthelp:
+       $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+       @echo
+       @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+             ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+       @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/OPNFVFunctest.qhcp"
+       @echo "To view the help file:"
+       @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/OPNFVFunctest.qhc"
+
+.PHONY: applehelp
+applehelp:
+       $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+       @echo
+       @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+       @echo "N.B. You won't be able to view it unless you put it in" \
+             "~/Library/Documentation/Help or install it in your application" \
+             "bundle."
+
+.PHONY: devhelp
+devhelp:
+       $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+       @echo
+       @echo "Build finished."
+       @echo "To view the help file:"
+       @echo "# mkdir -p $$HOME/.local/share/devhelp/OPNFVFunctest"
+       @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/OPNFVFunctest"
+       @echo "# devhelp"
+
+.PHONY: epub
+epub:
+       $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+       @echo
+       @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+.PHONY: epub3
+epub3:
+       $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+       @echo
+       @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+
+.PHONY: latex
+latex:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo
+       @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+       @echo "Run \`make' in that directory to run these through (pdf)latex" \
+             "(use \`make latexpdf' here to do that automatically)."
+
+.PHONY: latexpdf
+latexpdf:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo "Running LaTeX files through pdflatex..."
+       $(MAKE) -C $(BUILDDIR)/latex all-pdf
+       @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: latexpdfja
+latexpdfja:
+       $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+       @echo "Running LaTeX files through platex and dvipdfmx..."
+       $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+       @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+.PHONY: text
+text:
+       $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+       @echo
+       @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+.PHONY: man
+man:
+       $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+       @echo
+       @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+.PHONY: texinfo
+texinfo:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo
+       @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+       @echo "Run \`make' in that directory to run these through makeinfo" \
+             "(use \`make info' here to do that automatically)."
+
+.PHONY: info
+info:
+       $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+       @echo "Running Texinfo files through makeinfo..."
+       make -C $(BUILDDIR)/texinfo info
+       @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+.PHONY: gettext
+gettext:
+       $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+       @echo
+       @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+.PHONY: changes
+changes:
+       $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+       @echo
+       @echo "The overview file is in $(BUILDDIR)/changes."
+
+.PHONY: linkcheck
+linkcheck:
+       $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+       @echo
+       @echo "Link check complete; look for any errors in the above output " \
+             "or in $(BUILDDIR)/linkcheck/output.txt."
+
+.PHONY: doctest
+doctest:
+       $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+       @echo "Testing of doctests in the sources finished, look at the " \
+             "results in $(BUILDDIR)/doctest/output.txt."
+
+.PHONY: coverage
+coverage:
+       $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+       @echo "Testing of coverage in the sources finished, look at the " \
+             "results in $(BUILDDIR)/coverage/python.txt."
+
+.PHONY: xml
+xml:
+       $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+       @echo
+       @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+.PHONY: pseudoxml
+pseudoxml:
+       $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+       @echo
+       @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+
+.PHONY: dummy
+dummy:
+       $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+       @echo
+       @echo "Build finished. Dummy builder generates no files."
diff --git a/docs/api/apidoc/functest.core.feature.rst b/docs/api/apidoc/functest.core.feature.rst
new file mode 100644 (file)
index 0000000..a80e38d
--- /dev/null
@@ -0,0 +1,7 @@
+functest.core.feature module
+============================
+
+.. automodule:: functest.core.feature
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/api/apidoc/functest.core.rst b/docs/api/apidoc/functest.core.rst
new file mode 100644 (file)
index 0000000..29c67e4
--- /dev/null
@@ -0,0 +1,17 @@
+functest.core package
+=====================
+
+.. automodule:: functest.core
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+
+   functest.core.feature
+   functest.core.testcase
+   functest.core.vnf_base
+
diff --git a/docs/api/apidoc/functest.core.testcase.rst b/docs/api/apidoc/functest.core.testcase.rst
new file mode 100644 (file)
index 0000000..2f947a1
--- /dev/null
@@ -0,0 +1,7 @@
+functest.core.testcase module
+=============================
+
+.. automodule:: functest.core.testcase
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/api/apidoc/functest.core.vnf_base.rst b/docs/api/apidoc/functest.core.vnf_base.rst
new file mode 100644 (file)
index 0000000..94b2eaa
--- /dev/null
@@ -0,0 +1,7 @@
+functest.core.vnf_base module
+=============================
+
+.. automodule:: functest.core.vnf_base
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/api/apidoc/functest.opnfv_tests.rst b/docs/api/apidoc/functest.opnfv_tests.rst
new file mode 100644 (file)
index 0000000..52c2d45
--- /dev/null
@@ -0,0 +1,14 @@
+functest.opnfv_tests package
+============================
+
+.. automodule:: functest.opnfv_tests
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+    functest.opnfv_tests.sdn
diff --git a/docs/api/apidoc/functest.opnfv_tests.sdn.odl.odl.rst b/docs/api/apidoc/functest.opnfv_tests.sdn.odl.odl.rst
new file mode 100644 (file)
index 0000000..e6f8c73
--- /dev/null
@@ -0,0 +1,7 @@
+functest.opnfv_tests.sdn.odl.odl module
+=======================================
+
+.. automodule:: functest.opnfv_tests.sdn.odl.odl
+    :members:
+    :undoc-members:
+    :show-inheritance:
diff --git a/docs/api/apidoc/functest.opnfv_tests.sdn.odl.rst b/docs/api/apidoc/functest.opnfv_tests.sdn.odl.rst
new file mode 100644 (file)
index 0000000..60659a1
--- /dev/null
@@ -0,0 +1,15 @@
+functest.opnfv_tests.sdn.odl package
+====================================
+
+.. automodule:: functest.opnfv_tests.sdn.odl
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Submodules
+----------
+
+.. toctree::
+
+   functest.opnfv_tests.sdn.odl.odl
+
diff --git a/docs/api/apidoc/functest.opnfv_tests.sdn.rst b/docs/api/apidoc/functest.opnfv_tests.sdn.rst
new file mode 100644 (file)
index 0000000..ca8ae77
--- /dev/null
@@ -0,0 +1,14 @@
+functest.opnfv_tests.sdn package
+================================
+
+.. automodule:: functest.opnfv_tests.sdn
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+    functest.opnfv_tests.sdn.odl
diff --git a/docs/api/apidoc/functest.rst b/docs/api/apidoc/functest.rst
new file mode 100644 (file)
index 0000000..63860f8
--- /dev/null
@@ -0,0 +1,15 @@
+functest package
+================
+
+.. automodule:: functest
+    :members:
+    :undoc-members:
+    :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+    functest.core
+    functest.opnfv_tests
diff --git a/docs/api/apidoc/modules.rst b/docs/api/apidoc/modules.rst
new file mode 100644 (file)
index 0000000..b8f3330
--- /dev/null
@@ -0,0 +1,7 @@
+functest
+========
+
+.. toctree::
+   :maxdepth: 4
+
+   functest
diff --git a/docs/api/conf.py b/docs/api/conf.py
new file mode 100644 (file)
index 0000000..746a90f
--- /dev/null
@@ -0,0 +1,340 @@
+# -*- coding: utf-8 -*-
+#
+# OPNFV Functest documentation build configuration file, created by
+# sphinx-quickstart on Mon Apr 17 10:03:43 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'OPNFV Functest'
+copyright = u'2017, #opnfv-functest (chat.freenode.net)'
+author = u'#opnfv-functest (chat.freenode.net)'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = u'master'
+# The full version, including alpha/beta/rc tags.
+release = u'master'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = 'en'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#
+# today = ''
+#
+# Else, today_fmt is used as the format for a strftime call.
+#
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents.
+# "<project> v<release> documentation" by default.
+#
+# html_title = u'OPNFV Functest vmaster'
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#
+# html_logo = None
+
+# The name of an image file (relative to this directory) to use as a favicon of
+# the docs.  This file should be a Windows icon file (.ico) being 16x16 or
+# 32x32 pixels large.
+#
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#
+# html_extra_path = []
+
+# If not None, a 'Last updated on:' timestamp is inserted at every page
+# bottom, using the given strftime format.
+# The empty string is equivalent to '%b %d, %Y'.
+#
+# html_last_updated_fmt = None
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+#
+# html_domain_indices = True
+
+# If false, no index is generated.
+#
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
+#
+# html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# 'ja' uses this config value.
+# 'zh' user can custom change `jieba` dictionary path.
+#
+# html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#
+# html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'OPNFVFunctestdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+     # The paper size ('letterpaper' or 'a4paper').
+     #
+     # 'papersize': 'letterpaper',
+
+     # The font size ('10pt', '11pt' or '12pt').
+     #
+     # 'pointsize': '10pt',
+
+     # Additional stuff for the LaTeX preamble.
+     #
+     # 'preamble': '',
+
+     # Latex figure (float) alignment
+     #
+     # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'OPNFVFunctest.tex', u'OPNFV Functest Documentation',
+     u'\\#opnfv-functest (chat.freenode.net)', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#
+# latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+#
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#
+# latex_appendices = []
+
+# It false, will not define \strong, \code,    itleref, \crossref ... but only
+# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
+# packages.
+#
+# latex_keep_old_macro_names = True
+
+# If false, no module index is generated.
+#
+# latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'opnfvfunctest', u'OPNFV Functest Documentation',
+     [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#
+# man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'OPNFVFunctest', u'OPNFV Functest Documentation',
+     author, 'OPNFVFunctest', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#
+# texinfo_appendices = []
+
+# If false, no module index is generated.
+#
+# texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#
+# texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#
+# texinfo_no_detailmenu = False
diff --git a/docs/api/index.rst b/docs/api/index.rst
new file mode 100644 (file)
index 0000000..db22343
--- /dev/null
@@ -0,0 +1,18 @@
+Welcome to OPNFV Functest's documentation!
+==========================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   apidoc/modules
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/docs/com/pres/framework/framework.html b/docs/com/pres/framework/framework.html
new file mode 100644 (file)
index 0000000..950c2be
--- /dev/null
@@ -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 (file)
index 0000000..3c1aae1
--- /dev/null
@@ -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/1.0/apex.html b/docs/results/danube/1.0/apex.html
new file mode 100644 (file)
index 0000000..2ef0a19
--- /dev/null
@@ -0,0 +1,919 @@
+ <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');
+
+       // assign success rate to the gauge
+       function updateReadings() {
+           gaugeScenario1.update(50.0);gaugeScenario2.update(83.3333333333);gaugeScenario3.update(83.3333333333);gaugeScenario4.update(66.6666666667);gaugeScenario5.update(58.3333333333);gaugeScenario6.update(96.9696969697);gaugeScenario7.update(20.0);gaugeScenario8.update(81.8181818182);gaugeScenario9.update(6.06060606061);gaugeScenario10.update(6.06060606061);gaugeScenario11.update(80.5555555556);gaugeScenario12.update(100.0);
+       }
+       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-odl_l2-fdio-noha
+       // Filter results
+        var trend3 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l2-fdio-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_l3-fdio-noha
+       // Filter results
+        var trend4 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l3-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-bgpvpn-ha
+       // Filter results
+        var trend5 = data.filter(function(row) {
+            return row["scenario"]=="os-odl-bgpvpn-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-nosdn-kvm-ha
+       // Filter results
+        var trend6 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-kvm-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-fdio-ha
+       // Filter results
+        var trend7 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-fdio-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-nofeature-ha
+       // Filter results
+        var trend8 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l3-nofeature-ha" && 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-odl_l3-ovs-ha
+       // Filter results
+        var trend9 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l3-ovs-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-nosdn-ovs-ha
+       // Filter results
+        var trend10 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-ovs-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-odl_l2-fdio-ha
+       // Filter results
+        var trend11 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l2-fdio-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-nosdn-nofeature-ha
+       // Filter results
+        var trend12 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-nofeature-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)
+        // ****************************************
+    });
+    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 Danube 1.0 status page (2017-03-31 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>15/30</td>
+                                <td>2</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/71/console>os-odl-gluon-noha</a></td>
+                                <td><div id="gaugeScenario2"></div></td>
+                                <td><div id="trend_svg2"></div></td>
+                                <td>30/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/72/console>os-odl_l2-fdio-noha</a></td>
+                                <td><div id="gaugeScenario3"></div></td>
+                                <td><div id="trend_svg3"></div></td>
+                                <td>30/36</td>
+                                <td>14</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/75/console>os-odl_l3-fdio-noha</a></td>
+                                <td><div id="gaugeScenario4"></div></td>
+                                <td><div id="trend_svg4"></div></td>
+                                <td>20/30</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/70/console>os-odl-bgpvpn-ha</a></td>
+                                <td><div id="gaugeScenario5"></div></td>
+                                <td><div id="trend_svg5"></div></td>
+                                <td>21/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/74/console>os-nosdn-kvm-ha</a></td>
+                                <td><div id="gaugeScenario6"></div></td>
+                                <td><div id="trend_svg6"></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-apex-apex-daily-danube-daily-danube/76/console>os-nosdn-fdio-ha</a></td>
+                                <td><div id="gaugeScenario7"></div></td>
+                                <td><div id="trend_svg7"></div></td>
+                                <td>6/30</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/69/console>os-odl_l3-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario8"></div></td>
+                                <td><div id="trend_svg8"></div></td>
+                                <td>27/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/78/console>os-odl_l3-ovs-ha</a></td>
+                                <td><div id="gaugeScenario9"></div></td>
+                                <td><div id="trend_svg9"></div></td>
+                                <td>2/33</td>
+                                <td>1</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/77/console>os-nosdn-ovs-ha</a></td>
+                                <td><div id="gaugeScenario10"></div></td>
+                                <td><div id="trend_svg10"></div></td>
+                                <td>2/33</td>
+                                <td>1</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=http://testresultS.opnfv.org/reporting>os-odl_l2-fdio-ha</a></td>
+                                <td><div id="gaugeScenario11"></div></td>
+                                <td><div id="trend_svg11"></div></td>
+                                <td>29/36</td>
+                                <td>8</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-apex-apex-daily-danube-daily-danube/79/console>os-nosdn-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario12"></div></td>
+                                <td><div id="trend_svg12"></div></td>
+                                <td>33/33</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-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-few-clouds.png"></td><td><img src="../../img/weather-overcast.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><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-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-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-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-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-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-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-storm.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-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-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-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-few-clouds.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-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-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-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-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-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>
+                        </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-overcast.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>
+                        </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-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><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>
+                            Doctor
+
+                             </th><th>
+                            Domino
+
+                             </th>
+                        </tr>
+                        <tr class="tr-weather-weather">
+                            <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><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-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-storm.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-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>
+                            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>
+                        </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>
+    <div class="col-md-1"></div>
+</div>
diff --git a/docs/results/danube/1.0/compass.html b/docs/results/danube/1.0/compass.html
new file mode 100644 (file)
index 0000000..9547930
--- /dev/null
@@ -0,0 +1,490 @@
+ <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(76.6666666667);gaugeScenario2.update(10.0);gaugeScenario3.update(84.8484848485);gaugeScenario4.update(84.8484848485);gaugeScenario5.update(93.3333333333);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 Danube 1.0 status page (2017-03-31 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-baremetal-daily-danube/79/console>os-odl_l3-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario1"></div></td>
+                                <td><div id="trend_svg1"></div></td>
+                                <td>23/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/71/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>8</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/67/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>20</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/69/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>20</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-baremetal-daily-danube/77/console>os-nosdn-openo-ha</a></td>
+                                <td><div id="gaugeScenario5"></div></td>
+                                <td><div id="trend_svg5"></div></td>
+                                <td>28/30</td>
+                                <td>19</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-compass-virtual-daily-danube/70/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>19</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-clear.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-overcast.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-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><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-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-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-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>
+    see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring
+  </div>
+    <div class="col-md-1"></div>
+</div>
diff --git a/docs/results/danube/1.0/fuel.html b/docs/results/danube/1.0/fuel.html
new file mode 100644 (file)
index 0000000..3d08e7d
--- /dev/null
@@ -0,0 +1,1444 @@
+ <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(14.2857142857);gaugeScenario3.update(97.4358974359);gaugeScenario4.update(100.0);gaugeScenario5.update(15.3846153846);gaugeScenario6.update(83.3333333333);gaugeScenario7.update(79.4871794872);gaugeScenario8.update(100.0);gaugeScenario9.update(100.0);gaugeScenario10.update(92.3076923077);gaugeScenario11.update(88.0952380952);gaugeScenario12.update(95.5555555556);gaugeScenario13.update(100.0);gaugeScenario14.update(88.0952380952);gaugeScenario15.update(100.0);gaugeScenario16.update(94.8717948718);gaugeScenario17.update(97.2222222222);gaugeScenario18.update(97.4358974359);
+       }
+       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-nosdn-nofeature-noha
+       // Filter results
+        var trend9 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-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-kvm-ha
+       // Filter results
+        var trend16 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-kvm-ha" && 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-odl_l3-nofeature-noha
+       // Filter results
+        var trend17 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l3-nofeature-noha" && 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 Danube 1.0 status page (2017-03-31 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/66/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>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/67/console>os-nosdn-kvm_ovs_dpdk_bar-ha</a></td>
+                                <td><div id="gaugeScenario2"></div></td>
+                                <td><div id="trend_svg2"></div></td>
+                                <td>6/42</td>
+                                <td>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/73/console>os-nosdn-ovs-ha</a></td>
+                                <td><div id="gaugeScenario3"></div></td>
+                                <td><div id="trend_svg3"></div></td>
+                                <td>38/39</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/64/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>8</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/69/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>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/61/console>os-odl_l2-sfc-noha</a></td>
+                                <td><div id="gaugeScenario6"></div></td>
+                                <td><div id="trend_svg6"></div></td>
+                                <td>35/42</td>
+                                <td>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/66/console>os-odl_l3-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario7"></div></td>
+                                <td><div id="trend_svg7"></div></td>
+                                <td>31/39</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/63/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>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/65/console>os-nosdn-nofeature-noha</a></td>
+                                <td><div id="gaugeScenario9"></div></td>
+                                <td><div id="trend_svg9"></div></td>
+                                <td>36/36</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/57/console>os-odl_l2-nofeature-noha</a></td>
+                                <td><div id="gaugeScenario10"></div></td>
+                                <td><div id="trend_svg10"></div></td>
+                                <td>36/39</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/70/console>os-odl_l2-bgpvpn-ha</a></td>
+                                <td><div id="gaugeScenario11"></div></td>
+                                <td><div id="trend_svg11"></div></td>
+                                <td>37/42</td>
+                                <td>8</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/68/console>os-odl_l2-sfc-ha</a></td>
+                                <td><div id="gaugeScenario12"></div></td>
+                                <td><div id="trend_svg12"></div></td>
+                                <td>43/45</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/68/console>os-nosdn-kvm_ovs_dpdk_bar-noha</a></td>
+                                <td><div id="gaugeScenario13"></div></td>
+                                <td><div id="trend_svg13"></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/62/console>os-odl_l2-bgpvpn-noha</a></td>
+                                <td><div id="gaugeScenario14"></div></td>
+                                <td><div id="trend_svg14"></div></td>
+                                <td>37/42</td>
+                                <td>8</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-zte-pod1-daily-danube/6/console>os-odl_l2-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario15"></div></td>
+                                <td><div id="trend_svg15"></div></td>
+                                <td>42/42</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/71/console>os-nosdn-kvm-ha</a></td>
+                                <td><div id="gaugeScenario16"></div></td>
+                                <td><div id="trend_svg16"></div></td>
+                                <td>37/39</td>
+                                <td>12</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-virtual-daily-danube/67/console>os-odl_l3-nofeature-noha</a></td>
+                                <td><div id="gaugeScenario17"></div></td>
+                                <td><div id="trend_svg17"></div></td>
+                                <td>35/36</td>
+                                <td>7</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-fuel-baremetal-daily-danube/72/console>os-nosdn-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario18"></div></td>
+                                <td><div id="trend_svg18"></div></td>
+                                <td>38/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-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><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-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-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-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><td><img src="../../img/weather-clear.png"></td><td><img src="../../img/weather-storm.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-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-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-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-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-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-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><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>
+                        </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-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><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><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-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-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-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-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-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-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><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><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-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-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>
+                        </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-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><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-few-clouds.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>
+    <div class="col-md-1"></div>
+</div>
diff --git a/docs/results/danube/1.0/joid.html b/docs/results/danube/1.0/joid.html
new file mode 100644 (file)
index 0000000..98c1e0a
--- /dev/null
@@ -0,0 +1,418 @@
+ <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(70.8333333333);gaugeScenario2.update(93.9393939394);gaugeScenario3.update(75.0);gaugeScenario4.update(96.9696969697);gaugeScenario5.update(25.0);
+       }
+       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-nosdn-lxd-ha
+       // Filter results
+        var trend3 = data.filter(function(row) {
+            return row["scenario"]=="os-nosdn-lxd-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-odl_l2-nofeature-ha
+       // Filter results
+        var trend5 = data.filter(function(row) {
+            return row["scenario"]=="os-odl_l2-nofeature-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 Danube 1.0 status page (2017-03-31 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/57/console>os-nosdn-lxd-noha</a></td>
+                                <td><div id="gaugeScenario1"></div></td>
+                                <td><div id="trend_svg1"></div></td>
+                                <td>17/24</td>
+                                <td>6</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/55/console>os-nosdn-nofeature-noha</a></td>
+                                <td><div id="gaugeScenario2"></div></td>
+                                <td><div id="trend_svg2"></div></td>
+                                <td>31/33</td>
+                                <td>6</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/56/console>os-nosdn-lxd-ha</a></td>
+                                <td><div id="gaugeScenario3"></div></td>
+                                <td><div id="trend_svg3"></div></td>
+                                <td>18/24</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/62/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>6</td>
+                            </tr><tr class="tr-ok">
+                                <td><a href=https://build.opnfv.org/ci/view/functest/job/functest-joid-baremetal-daily-danube/46/console>os-odl_l2-nofeature-ha</a></td>
+                                <td><div id="gaugeScenario5"></div></td>
+                                <td><div id="trend_svg5"></div></td>
+                                <td>9/36</td>
+                                <td>4</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-few-clouds.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-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>
+                        </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-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-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-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>
+    see <a href="https://wiki.opnfv.org/pages/viewpage.action?pageId=6828617">Functest scoring wiki page</a> for details on scenario scoring
+    </div>
+    <div class="col-md-1"></div>
+</div>
diff --git a/docs/results/danube/1.0/scenario_history.txt b/docs/results/danube/1.0/scenario_history.txt
new file mode 100644 (file)
index 0000000..078258e
--- /dev/null
@@ -0,0 +1,622 @@
+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
+
diff --git a/docs/results/danube/1.0/validated_scenario_history.txt b/docs/results/danube/1.0/validated_scenario_history.txt
new file mode 100644 (file)
index 0000000..e867e37
--- /dev/null
@@ -0,0 +1,60 @@
+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
+
diff --git a/docs/results/danube/2.0/apex.html b/docs/results/danube/2.0/apex.html
new file mode 100644 (file)
index 0000000..4460087
--- /dev/null
@@ -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 (file)
index 0000000..cde6635
--- /dev/null
@@ -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 (file)
index 0000000..0ee69d3
--- /dev/null
@@ -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 (file)
index 0000000..e223174
--- /dev/null
@@ -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 (file)
index 0000000..c4ca6aa
--- /dev/null
@@ -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 (file)
index 0000000..15ec001
--- /dev/null
@@ -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/results/img/weather-clear.png b/docs/results/img/weather-clear.png
new file mode 100644 (file)
index 0000000..a0d9677
Binary files /dev/null and b/docs/results/img/weather-clear.png differ
diff --git a/docs/results/img/weather-few-clouds.png b/docs/results/img/weather-few-clouds.png
new file mode 100644 (file)
index 0000000..acfa783
Binary files /dev/null and b/docs/results/img/weather-few-clouds.png differ
diff --git a/docs/results/img/weather-overcast.png b/docs/results/img/weather-overcast.png
new file mode 100644 (file)
index 0000000..4296246
Binary files /dev/null and b/docs/results/img/weather-overcast.png differ
diff --git a/docs/results/img/weather-storm.png b/docs/results/img/weather-storm.png
new file mode 100644 (file)
index 0000000..956f0e2
Binary files /dev/null and b/docs/results/img/weather-storm.png differ
diff --git a/docs/results/js/default.css b/docs/results/js/default.css
new file mode 100644 (file)
index 0000000..e32fa5f
--- /dev/null
@@ -0,0 +1,194 @@
+.panel-header-item {
+    position: relative;
+    display: inline-block;
+    padding-left: 17px;
+    padding-right: 17px;
+}
+
+.panel-pod-name {
+    margin-top: 10px;
+    margin-right: 27px;
+    float:right;
+    padding: 6px;
+}
+
+.panel-default > .panel-heading .badge {
+    background-color: #007e88;
+    position: relative;
+    display: inline-block;
+}
+
+.panel-default > .panel-heading .progress-bar {
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    background-color: #0095a2
+}
+.panel-default > .panel-heading h4 {
+    color: white;
+}
+
+.panel-default > .panel-heading {
+    background-color: #00ADBB;
+    overflow: hidden;
+    position: relative;
+    width: 100%;
+}
+
+th{
+    text-align: center;
+}
+
+td{
+    text-align: center;
+}
+
+.tr-danger {
+    background-color: #177870;
+    color: white;
+}
+
+.btn-more {
+    color: white;
+    background-color: #0095a2;
+}
+
+h1 { 
+    display: block;
+    font-size: 2em;
+    margin-top: 0.67em;
+    margin-bottom: 0.67em;
+    margin-left: 0;
+    margin-right: 0;
+    font-weight: bold;
+}
+
+h2 {
+    display: block;
+    font-size: 1.5em;
+    margin-top: 0.83em;
+    margin-bottom: 0.83em;
+    margin-left: 0;
+    margin-right: 0;
+    font-weight: bold;
+    color:rgb(128, 128, 128)
+}
+
+#power-gauge g.arc {
+       fill: steelblue;
+}
+
+#power-gauge g.pointer {
+       fill: #e85116;
+       stroke: #b64011;
+}
+
+#power-gauge g.label text {
+       text-anchor: middle;
+       font-size: 14px;
+       font-weight: bold;
+       fill: #666;
+}
+
+#power-gauge path {
+
+}
+
+.axis path,
+.axis line {
+  fill: none;
+  stroke: #000;
+  shape-rendering: crispEdges;
+}
+
+.dot {
+  fill: steelblue;
+  stroke: steelblue;
+  stroke-width: 1.5px;
+}
+
+.myButtonPdf {
+       -moz-box-shadow:inset 0px 1px 0px 0px #f29c93;
+       -webkit-box-shadow:inset 0px 1px 0px 0px #f29c93;
+       box-shadow:inset 0px 1px 0px 0px #f29c93;
+       background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #fe1a00), color-stop(1, #ce0100));
+       background:-moz-linear-gradient(top, #fe1a00 5%, #ce0100 100%);
+       background:-webkit-linear-gradient(top, #fe1a00 5%, #ce0100 100%);
+       background:-o-linear-gradient(top, #fe1a00 5%, #ce0100 100%);
+       background:-ms-linear-gradient(top, #fe1a00 5%, #ce0100 100%);
+       background:linear-gradient(to bottom, #fe1a00 5%, #ce0100 100%);
+       filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fe1a00', endColorstr='#ce0100',GradientType=0);
+       background-color:#fe1a00;
+       -moz-border-radius:6px;
+       -webkit-border-radius:6px;
+       border-radius:6px;
+       border:1px solid #d83526;
+       display:inline-block;
+       cursor:pointer;
+       color:#ffffff;
+       font-family:Arial;
+       font-size:15px;
+       font-weight:bold;
+       padding:6px 24px;
+       text-decoration:none;
+       text-shadow:0px 1px 0px #b23e35;
+}
+.myButtonPdf:hover {
+       background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ce0100), color-stop(1, #fe1a00));
+       background:-moz-linear-gradient(top, #ce0100 5%, #fe1a00 100%);
+       background:-webkit-linear-gradient(top, #ce0100 5%, #fe1a00 100%);
+       background:-o-linear-gradient(top, #ce0100 5%, #fe1a00 100%);
+       background:-ms-linear-gradient(top, #ce0100 5%, #fe1a00 100%);
+       background:linear-gradient(to bottom, #ce0100 5%, #fe1a00 100%);
+       filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ce0100', endColorstr='#fe1a00',GradientType=0);
+       background-color:#ce0100;
+}
+.myButtonPdf:active {
+       position:relative;
+       top:1px;
+}
+
+
+.myButtonCSV {
+       -moz-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
+       -webkit-box-shadow:inset 0px 1px 0px 0px #bbdaf7;
+       box-shadow:inset 0px 1px 0px 0px #bbdaf7;
+       background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #79bbff), color-stop(1, #378de5));
+       background:-moz-linear-gradient(top, #79bbff 5%, #378de5 100%);
+       background:-webkit-linear-gradient(top, #79bbff 5%, #378de5 100%);
+       background:-o-linear-gradient(top, #79bbff 5%, #378de5 100%);
+       background:-ms-linear-gradient(top, #79bbff 5%, #378de5 100%);
+       background:linear-gradient(to bottom, #79bbff 5%, #378de5 100%);
+       filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#79bbff', endColorstr='#378de5',GradientType=0);
+       background-color:#79bbff;
+       -moz-border-radius:6px;
+       -webkit-border-radius:6px;
+       border-radius:6px;
+       border:1px solid #84bbf3;
+       display:inline-block;
+       cursor:pointer;
+       color:#ffffff;
+       font-family:Arial;
+       font-size:15px;
+       font-weight:bold;
+       padding:6px 24px;
+       text-decoration:none;
+       text-shadow:0px 1px 0px #528ecc;
+}
+.myButtonCSV:hover {
+       background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #378de5), color-stop(1, #79bbff));
+       background:-moz-linear-gradient(top, #378de5 5%, #79bbff 100%);
+       background:-webkit-linear-gradient(top, #378de5 5%, #79bbff 100%);
+       background:-o-linear-gradient(top, #378de5 5%, #79bbff 100%);
+       background:-ms-linear-gradient(top, #378de5 5%, #79bbff 100%);
+       background:linear-gradient(to bottom, #378de5 5%, #79bbff 100%);
+       filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#378de5', endColorstr='#79bbff',GradientType=0);
+       background-color:#378de5;
+}
+.myButtonCSV:active {
+       position:relative;
+       top:1px;
+}
+
diff --git a/docs/results/js/gauge.js b/docs/results/js/gauge.js
new file mode 100644 (file)
index 0000000..4cad16c
--- /dev/null
@@ -0,0 +1,165 @@
+// ******************************************
+// Gauge for reporting
+// Each scenario has a score
+// We use a gauge to indicate the trust level
+// ******************************************
+var gauge = function(container) {
+  var that = {};
+  var config = {
+    size                                               : 150,
+    clipWidth                                  : 250,
+    clipHeight                                 : 100,
+    ringInset                                  : 20,
+    ringWidth                                  : 40,
+
+    pointerWidth                               : 7,
+    pointerTailLength                  : 5,
+    pointerHeadLengthPercent   : 0.8,
+
+    minValue                                   : 0,
+    maxValue                                   : 100,
+
+    minAngle                                   : -90,
+    maxAngle                                   : 90,
+
+    transitionMs                               : 4000,
+
+    majorTicks                                 : 7,
+    labelFormat                                        : d3.format(',g'),
+    labelInset                                 : 10,
+
+    arcColorFn                                 : d3.interpolateHsl(d3.rgb('#ff0000'), d3.rgb('#00ff00'))
+  };
+
+
+var range = undefined;
+var r = undefined;
+var pointerHeadLength = undefined;
+var value = 0;
+
+var svg = undefined;
+var arc = undefined;
+var scale = undefined;
+var ticks = undefined;
+var tickData = undefined;
+var pointer = undefined;
+
+var donut = d3.layout.pie();
+
+function deg2rad(deg) {
+  return deg * Math.PI / 180;
+}
+
+function newAngle(d) {
+  var ratio = scale(d);
+  var newAngle = config.minAngle + (ratio * range);
+  return newAngle;
+}
+
+function configure() {
+  range = config.maxAngle - config.minAngle;
+  r = config.size / 2;
+  pointerHeadLength = Math.round(r * config.pointerHeadLengthPercent);
+
+  // a linear scale that maps domain values to a percent from 0..1
+  scale = d3.scale.linear()
+    .range([0,1])
+    .domain([config.minValue, config.maxValue]);
+
+  ticks = scale.ticks(config.majorTicks);
+  tickData = d3.range(config.majorTicks).map(function() {return 1/config.majorTicks;});
+
+  arc = d3.svg.arc()
+    .innerRadius(r - config.ringWidth - config.ringInset)
+    .outerRadius(r - config.ringInset)
+    .startAngle(function(d, i) {
+      var ratio = d * i;
+      return deg2rad(config.minAngle + (ratio * range));
+    })
+    .endAngle(function(d, i) {
+      var ratio = d * (i+1);
+      return deg2rad(config.minAngle + (ratio * range));
+    });
+}
+that.configure = configure;
+
+function centerTranslation() {
+  return 'translate('+r +','+ r +')';
+}
+
+function isRendered() {
+  return (svg !== undefined);
+}
+that.isRendered = isRendered;
+
+function render(newValue) {
+  svg = d3.select(container)
+    .append('svg:svg')
+      .attr('class', 'gauge')
+      .attr('width', config.clipWidth)
+      .attr('height', config.clipHeight);
+
+  var centerTx = centerTranslation();
+
+  var arcs = svg.append('g')
+      .attr('class', 'arc')
+      .attr('transform', centerTx);
+
+  arcs.selectAll('path')
+      .data(tickData)
+    .enter().append('path')
+      .attr('fill', function(d, i) {
+        return config.arcColorFn(d * i);
+      })
+      .attr('d', arc);
+
+  var lg = svg.append('g')
+      .attr('class', 'label')
+      .attr('transform', centerTx);
+  lg.selectAll('text')
+      .data(ticks)
+    .enter().append('text')
+      .attr('transform', function(d) {
+        var ratio = scale(d);
+        var newAngle = config.minAngle + (ratio * range);
+        return 'rotate(' +newAngle +') translate(0,' +(config.labelInset - r) +')';
+      })
+      .text(config.labelFormat);
+
+  var lineData = [ [config.pointerWidth / 2, 0],
+          [0, -pointerHeadLength],
+          [-(config.pointerWidth / 2), 0],
+          [0, config.pointerTailLength],
+          [config.pointerWidth / 2, 0] ];
+  var pointerLine = d3.svg.line().interpolate('monotone');
+  var pg = svg.append('g').data([lineData])
+      .attr('class', 'pointer')
+      .attr('transform', centerTx);
+
+  pointer = pg.append('path')
+    .attr('d', pointerLine/*function(d) { return pointerLine(d) +'Z';}*/ )
+    .attr('transform', 'rotate(' +config.minAngle +')');
+
+  update(newValue === undefined ? 0 : newValue);
+}
+that.render = render;
+
+function update(newValue, newConfiguration) {
+  if ( newConfiguration  !== undefined) {
+    configure(newConfiguration);
+  }
+  var ratio = scale(newValue);
+  var newAngle = config.minAngle + (ratio * range);
+  pointer.transition()
+    .duration(config.transitionMs)
+    .ease('elastic')
+    .attr('transform', 'rotate(' +newAngle +')');
+}
+that.update = update;
+
+configure();
+
+render();
+
+return that;
+};
diff --git a/docs/results/js/trend.js b/docs/results/js/trend.js
new file mode 100644 (file)
index 0000000..f242133
--- /dev/null
@@ -0,0 +1,75 @@
+// ******************************************
+// Trend line for reporting
+// based on scenario_history.txt
+// where data looks like
+// date,scenario,installer,detail,score
+// 2016-09-22 13:12,os-nosdn-fdio-noha,apex,4/12,33.0
+// 2016-09-22 13:13,os-odl_l2-fdio-noha,apex,12/15,80.0
+// 2016-09-22 13:13,os-odl_l2-sfc-noha,apex,18/24,75.0
+// .....
+// ******************************************
+// Set the dimensions of the canvas / graph
+var trend_margin = {top: 20, right: 30, bottom: 50, left: 40},
+  trend_width = 300 - trend_margin.left - trend_margin.right,
+  trend_height = 130 - trend_margin.top - trend_margin.bottom;
+
+// Parse the date / time
+var parseDate = d3.time.format("%Y-%m-%d %H:%M").parse;
+
+// Set the ranges
+var trend_x = d3.time.scale().range([0, trend_width]);
+var trend_y = d3.scale.linear().range([trend_height, 0]);
+
+// Define the axes
+var trend_xAxis = d3.svg.axis().scale(trend_x)
+  .orient("bottom").ticks(2).tickFormat(d3.time.format("%m-%d"));
+
+var trend_yAxis = d3.svg.axis().scale(trend_y)
+  .orient("left").ticks(2);
+
+// Define the line
+var valueline = d3.svg.line()
+  .x(function(d) { return trend_x(d.date); })
+  .y(function(d) { return trend_y(d.score); });
+
+var trend = function(container, trend_data) {
+
+    var trend_svg = d3.select(container)
+    .append("svg")
+      .attr("width", trend_width + trend_margin.left + trend_margin.right)
+      .attr("height", trend_height + trend_margin.top + trend_margin.bottom)
+    .append("g")
+            .attr("transform",
+              "translate(" + trend_margin.left + "," + trend_margin.top + ")");
+
+    // Scale the range of the data
+    trend_x.domain(d3.extent(trend_data, function(d) { return d.date; }));
+    trend_y.domain([0, d3.max(trend_data, function(d) { return d.score; })]);
+
+    // Add the X Axis
+    trend_svg.append("g")
+        .attr("class", "x axis")
+        .attr("transform", "translate(0," + trend_height + ")")
+        .call(trend_xAxis);
+
+    // Add the Y Axis
+    trend_svg.append("g")
+        .attr("class", "y axis")
+        .call(trend_yAxis);
+
+    // Add the valueline path.
+    trend_svg.append("path")
+        .attr("class", "line")
+        .attr("d", valueline(trend_data))
+    .attr("stroke", "steelblue")
+    .attr("fill", "none");
+    trend_svg.selectAll(".dot")
+      .data(trend_data)
+      .enter().append("circle")
+      .attr("r", 2.5)
+        .attr("cx", function(d) { return trend_x(d.date); })
+        .attr("cy", function(d) { return trend_y(d.score); });   
+
+     return trend;
+}
index e3485be..9a17497 100644 (file)
@@ -336,6 +336,7 @@ should now be in place::
             |-- parser
             |-- promise
             |-- rally
+            |-- refstack-client
             |-- releng
             |-- sdnvpn
             |-- securityscanning
index 6c9c2de..c1faecd 100644 (file)
@@ -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,16 +632,20 @@ 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`_
 
 `Functest page`_
 
-IRC support chan: #opnfv-testperf
+IRC support chan: #opnfv-functest
 
 .. _`OPNFV main site`: http://www.opnfv.org
 .. _`Functest page`: https://wiki.opnfv.org/functest
index 8a3ba8c..07b5b8a 100644 (file)
@@ -118,14 +118,35 @@ More specific details on specific Tiers or Test Cases can be seen wih the
 To execute a Test Tier or Test Case, the 'run' command is used::
 
   root@22e436918db0:~/repos/functest/ci# functest tier run healthcheck
-  2017-03-21 13:34:21,400 - run_tests - INFO - ############################################
-  2017-03-21 13:34:21,400 - run_tests - INFO - Running tier 'healthcheck'
-  2017-03-21 13:34:21,400 - run_tests - INFO - ############################################
-  2017-03-21 13:34:21,401 - run_tests - INFO -
-
-  2017-03-21 13:34:21,401 - run_tests - INFO - ============================================
-  2017-03-21 13:34:21,401 - run_tests - INFO - Running test case 'connection_check'...
-  2017-03-21 13:34:21,401 - run_tests - INFO - ============================================
+  2017-03-30 05:36:19,752 - run_tests - INFO - ############################################
+  2017-03-30 05:36:19,752 - run_tests - INFO - Running tier 'healthcheck'
+  2017-03-30 05:36:19,753 - run_tests - INFO - ############################################
+  2017-03-30 05:36:19,753 - run_tests - INFO -
+
+  2017-03-30 05:36:19,753 - run_tests - INFO - ============================================
+  2017-03-30 05:36:19,753 - run_tests - INFO - Running test case 'connection_check'...
+  2017-03-30 05:36:19,753 - run_tests - INFO - ============================================
+  2017-03-30 05:36:20,046 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,046 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,775 - functest - INFO - Using flavor metatdata '{'hw:mem_page_size': 'any'}'
+  2017-03-30 05:36:20,777 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,777 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,777 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,778 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,778 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,779 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,779 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,779 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,780 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,780 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,781 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,781 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,781 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,782 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,782 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,783 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:20,783 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:20,784 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
   test_glance_connect_fail (snaps.openstack.utils.tests.glance_utils_tests.GlanceSmokeTests) ... ok
   test_glance_connect_success (snaps.openstack.utils.tests.glance_utils_tests.GlanceSmokeTests) ... ok
   test_keystone_connect_fail (snaps.openstack.utils.tests.keystone_utils_tests.KeystoneSmokeTests) ... ok
@@ -137,241 +158,341 @@ To execute a Test Tier or Test Case, the 'run' command is used::
   test_nova_connect_success (snaps.openstack.utils.tests.nova_utils_tests.NovaSmokeTests) ... ok
 
   ----------------------------------------------------------------------
-  Ran 9 tests in 3.768s
+  Ran 9 tests in 1.332s
 
   OK
-  2017-03-21 13:34:26,570 - functest.core.testcase_base - INFO - connection_check OK
-  2017-03-21 13:34:26,918 - functest.core.testcase_base - INFO - The results were successfully pushed to DB
-  2017-03-21 13:34:26,918 - run_tests - INFO - Test execution time: 00:05
-  2017-03-21 13:34:26,918 - run_tests - INFO -
-
-  2017-03-21 13:34:26,918 - run_tests - INFO - ============================================
-  2017-03-21 13:34:26,918 - run_tests - INFO - Running test case 'api_check'...
-  2017-03-21 13:34:26,919 - run_tests - INFO - ============================================
+  2017-03-30 05:36:22,116 - functest - INFO - connection_check OK
+  2017-03-30 05:36:22,483 - functest - INFO - The results were successfully pushed to DB
+  2017-03-30 05:36:22,483 - run_tests - INFO - Test execution time: 00:02
+  2017-03-30 05:36:22,484 - run_tests - INFO -
+
+  2017-03-30 05:36:22,484 - run_tests - INFO - ============================================
+  2017-03-30 05:36:22,484 - run_tests - INFO - Running test case 'api_check'...
+  2017-03-30 05:36:22,484 - run_tests - INFO - ============================================
+  2017-03-30 05:36:22,590 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:22,591 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,361 - functest - INFO - Using flavor metatdata '{'hw:mem_page_size': 'any'}'
+  2017-03-30 05:36:23,362 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,362 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,363 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,364 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,364 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,365 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,365 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,365 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,366 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,366 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,367 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,367 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,368 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,368 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,368 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,369 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,370 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,370 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,370 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,371 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,372 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,372 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,372 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,373 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,373 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,374 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,374 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,374 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,375 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,376 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,376 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,376 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,376 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,377 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,377 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,377 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,377 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,377 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,378 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,378 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,378 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,378 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,379 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,379 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,379 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,380 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,380 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,380 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,380 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,380 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,381 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,381 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,381 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,381 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,381 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,382 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,382 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,382 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,382 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,382 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,383 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,383 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,383 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,384 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,384 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,384 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,384 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,384 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,385 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,385 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,385 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,385 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,386 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,386 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,386 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,386 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,387 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,387 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,387 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,388 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,388 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,388 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,388 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,388 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,420 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,420 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,420 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,420 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,421 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,421 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,421 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,421 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,422 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,422 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:36:23,422 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:36:23,422 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
   test_create_project_minimal (snaps.openstack.utils.tests.keystone_utils_tests.KeystoneUtilsTests) ... ok
   test_create_user_minimal (snaps.openstack.utils.tests.keystone_utils_tests.KeystoneUtilsTests) ... ok
   test_create_delete_user (snaps.openstack.tests.create_user_tests.CreateUserSuccessTests) ... ok
   test_create_user (snaps.openstack.tests.create_user_tests.CreateUserSuccessTests) ... ok
-  test_create_user_2x (snaps.openstack.tests.create_user_tests.CreateUserSuccessTests) ...
-  2017-03-21 13:34:32,684 - create_user - INFO - Found user with name - CreateUserSuccessTests-7e741e11-c9fd-489-name ok
+  test_create_user_2x (snaps.openstack.tests.create_user_tests.CreateUserSuccessTests) ... 2017-03-30 05:36:27,257 - create_user - INFO - Found user with name - CreateUserSuccessTests-5ff765c1-56bd-4c4-name
+  ok
   test_create_delete_project (snaps.openstack.tests.create_project_tests.CreateProjectSuccessTests) ... ok
   test_create_project (snaps.openstack.tests.create_project_tests.CreateProjectSuccessTests) ... ok
-  test_create_project_2x (snaps.openstack.tests.create_project_tests.CreateProjectSuccessTests) ...
-  2017-03-21 13:34:35,922 - create_image - INFO - Found project with name - CreateProjectSuccessTests-b38e08ce-2862-48a-name ok
-  test_create_project_sec_grp_one_user (snaps.openstack.tests.create_project_tests.CreateProjectUserTests) ...
-  2017-03-21 13:34:37,907 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-ab8801f6-dad8-4f9-name...
-  2017-03-21 13:34:37,907 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-ab8801f6-dad8-4f9-name
-  2017-03-21 13:34:38,376 - neutron_utils - INFO - Creating security group with name - CreateProjectUserTests-ab8801f6-dad8-4f9-name
-  2017-03-21 13:34:38,716 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-ab8801f6-dad8-4f9-name
-  2017-03-21 13:34:38,762 - neutron_utils - INFO - Retrieving security group with ID - 821419cb-c54c-41b4-a61b-fb30e5dd2ec5
-  2017-03-21 13:34:38,886 - neutron_utils - INFO - Retrieving security group with ID - 821419cb-c54c-41b4-a61b-fb30e5dd2ec5
-  2017-03-21 13:34:39,000 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-ab8801f6-dad8-4f9-name
-  2017-03-21 13:34:39,307 - neutron_utils - INFO - Deleting security group rule with ID - d85fafc0-9649-45c9-a00e-452f3d5c09a6
-  2017-03-21 13:34:39,531 - neutron_utils - INFO - Deleting security group rule with ID - 69d79c09-bc3b-4975-9353-5f43aca51237
-  2017-03-21 13:34:39,762 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-ab8801f6-dad8-4f9-name ok
-  test_create_project_sec_grp_two_users (snaps.openstack.tests.create_project_tests.CreateProjectUserTests) ...
-  2017-03-21 13:34:43,511 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-4d9261a6-e008-44b-name...
-  2017-03-21 13:34:43,511 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:44,090 - neutron_utils - INFO - Creating security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:44,784 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:44,864 - neutron_utils - INFO - Retrieving security group with ID - 780193e4-9bd2-4f2e-a14d-b01abf74c832
-  2017-03-21 13:34:45,233 - neutron_utils - INFO - Retrieving security group with ID - 780193e4-9bd2-4f2e-a14d-b01abf74c832
-  2017-03-21 13:34:45,332 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:45,779 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-4d9261a6-e008-44b-name...
-  2017-03-21 13:34:45,779 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:46,112 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:46,184 - neutron_utils - INFO - Retrieving security group with ID - 780193e4-9bd2-4f2e-a14d-b01abf74c832
-  2017-03-21 13:34:46,296 - neutron_utils - INFO - Retrieving security group with ID - 780193e4-9bd2-4f2e-a14d-b01abf74c832
-  2017-03-21 13:34:46,387 - neutron_utils - INFO - Deleting security group rule with ID - 2320a573-ec56-47c5-a1ba-ec514d30114b
-  2017-03-21 13:34:46,636 - neutron_utils - INFO - Deleting security group rule with ID - 6186282b-db37-4e47-becc-a3886079c069
-  2017-03-21 13:34:46,780 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:47,006 - neutron_utils - INFO - Deleting security group rule with ID - 2320a573-ec56-47c5-a1ba-ec514d30114b
-  2017-03-21 13:34:47,072 - OpenStackSecurityGroup - WARNING - Rule not found, cannot delete - Security group rule 2320a573-ec56-47c5-a1ba-ec514d30114b does not exist
-  Neutron server returns request_ids: ['req-d74eb2e2-b26f-4236-87dc-7255866141d9']
-  2017-03-21 13:34:47,072 - neutron_utils - INFO - Deleting security group rule with ID - 6186282b-db37-4e47-becc-a3886079c069
-  2017-03-21 13:34:47,118 - OpenStackSecurityGroup - WARNING - Rule not found, cannot delete - Security group rule 6186282b-db37-4e47-becc-a3886079c069 does not exist
-  Neutron server returns request_ids: ['req-8c0a5a24-be90-4844-a9ed-2a85cc6f59a5']
-  2017-03-21 13:34:47,118 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-4d9261a6-e008-44b-name
-  2017-03-21 13:34:47,172 - OpenStackSecurityGroup - WARNING - Security Group not found, cannot delete - Security group 780193e4-9bd2-4f2e-a14d-b01abf74c832 does not exist
-  Neutron server returns request_ids: ['req-c6e1a6b5-43e0-4d46-bb68-c2e1672d4d21'] ok
+  test_create_project_2x (snaps.openstack.tests.create_project_tests.CreateProjectSuccessTests) ... 2017-03-30 05:36:29,798 - create_image - INFO - Found project with name - CreateProjectSuccessTests-1b2fce89-dd5e-471-name
+  ok
+  test_create_project_sec_grp_one_user (snaps.openstack.tests.create_project_tests.CreateProjectUserTests) ... 2017-03-30 05:36:31,327 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-34aa7d96-f19c-4db-name...
+  2017-03-30 05:36:31,327 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-34aa7d96-f19c-4db-name
+  2017-03-30 05:36:31,705 - neutron_utils - INFO - Creating security group with name - CreateProjectUserTests-34aa7d96-f19c-4db-name
+  2017-03-30 05:36:31,878 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-34aa7d96-f19c-4db-name
+  2017-03-30 05:36:31,915 - neutron_utils - INFO - Retrieving security group with ID - 4dc3e8e4-3dc8-4dda-9c7e-03d08171e17a
+  2017-03-30 05:36:31,980 - neutron_utils - INFO - Retrieving security group with ID - 4dc3e8e4-3dc8-4dda-9c7e-03d08171e17a
+  2017-03-30 05:36:32,048 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-34aa7d96-f19c-4db-name
+  2017-03-30 05:36:32,108 - neutron_utils - INFO - Deleting security group rule with ID - 81cca252-45fe-4052-adb9-819191693618
+  2017-03-30 05:36:32,257 - neutron_utils - INFO - Deleting security group rule with ID - 8900647f-1587-4068-bd2e-7b77677d12ed
+  2017-03-30 05:36:32,367 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-34aa7d96-f19c-4db-name
+  ok
+  test_create_project_sec_grp_two_users (snaps.openstack.tests.create_project_tests.CreateProjectUserTests) ... 2017-03-30 05:36:34,950 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-6664b595-4657-4f9-name...
+  2017-03-30 05:36:34,950 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:35,337 - neutron_utils - INFO - Creating security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:35,528 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:35,566 - neutron_utils - INFO - Retrieving security group with ID - ea8b1da3-0e3d-45aa-b63f-68d2e7b57e48
+  2017-03-30 05:36:35,831 - neutron_utils - INFO - Retrieving security group with ID - ea8b1da3-0e3d-45aa-b63f-68d2e7b57e48
+  2017-03-30 05:36:36,118 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:36,474 - OpenStackSecurityGroup - INFO - Creating security group CreateProjectUserTests-6664b595-4657-4f9-name...
+  2017-03-30 05:36:36,475 - neutron_utils - INFO - Retrieving security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:36,717 - neutron_utils - INFO - Retrieving security group rules associate with the security group - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:36,768 - neutron_utils - INFO - Retrieving security group with ID - ea8b1da3-0e3d-45aa-b63f-68d2e7b57e48
+  2017-03-30 05:36:36,831 - neutron_utils - INFO - Retrieving security group with ID - ea8b1da3-0e3d-45aa-b63f-68d2e7b57e48
+  2017-03-30 05:36:36,902 - neutron_utils - INFO - Deleting security group rule with ID - f6e50aea-e6d2-4ba9-ab78-0674cdcd5415
+  2017-03-30 05:36:37,054 - neutron_utils - INFO - Deleting security group rule with ID - a32d9c1d-7ae0-4fe9-b4c9-8b039008f836
+  2017-03-30 05:36:37,204 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:37,350 - neutron_utils - INFO - Deleting security group rule with ID - f6e50aea-e6d2-4ba9-ab78-0674cdcd5415
+  2017-03-30 05:36:37,387 - OpenStackSecurityGroup - WARNING - Rule not found, cannot delete - Security group rule f6e50aea-e6d2-4ba9-ab78-0674cdcd5415 does not exist
+  Neutron server returns request_ids: ['req-e740871d-34c4-4b95-a76c-6b84028954e6']
+  2017-03-30 05:36:37,387 - neutron_utils - INFO - Deleting security group rule with ID - a32d9c1d-7ae0-4fe9-b4c9-8b039008f836
+  2017-03-30 05:36:37,426 - OpenStackSecurityGroup - WARNING - Rule not found, cannot delete - Security group rule a32d9c1d-7ae0-4fe9-b4c9-8b039008f836 does not exist
+  Neutron server returns request_ids: ['req-8121308e-d7d3-4ccc-961f-5fa794fccc83']
+  2017-03-30 05:36:37,427 - neutron_utils - INFO - Deleting security group with name - CreateProjectUserTests-6664b595-4657-4f9-name
+  2017-03-30 05:36:37,470 - OpenStackSecurityGroup - WARNING - Security Group not found, cannot delete - Security group ea8b1da3-0e3d-45aa-b63f-68d2e7b57e48 does not exist
+  Neutron server returns request_ids: ['req-09424914-a32d-4bcb-9d90-0ad307ec4c56']
+  ok
   test_create_image_minimal_file (snaps.openstack.utils.tests.glance_utils_tests.GlanceUtilsTests) ... ok
   test_create_image_minimal_url (snaps.openstack.utils.tests.glance_utils_tests.GlanceUtilsTests) ... ok
-  test_create_network (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsNetworkTests) ...
-  2017-03-21 13:35:22,275 - neutron_utils - INFO - Creating network with name NeutronUtilsNetworkTests-c06c20e0-d78f-4fa4-8401-099a7a6cab2e-pub-net
-  2017-03-21 13:35:23,965 - neutron_utils - INFO - Deleting network with name NeutronUtilsNetworkTests-c06c20e0-d78f-4fa4-8401-099a7a6cab2e-pub-net ok
+  test_create_network (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsNetworkTests) ... 2017-03-30 05:37:02,330 - neutron_utils - INFO - Creating network with name NeutronUtilsNetworkTests-9dc31d5e-be87-480d-af6e-d89f0608e459-pub-net
+  2017-03-30 05:37:04,307 - neutron_utils - INFO - Deleting network with name NeutronUtilsNetworkTests-9dc31d5e-be87-480d-af6e-d89f0608e459-pub-net
+  ok
   test_create_network_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsNetworkTests) ... ok
   test_create_network_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsNetworkTests) ... ok
-  test_create_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ...
-  2017-03-21 13:35:25,495 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-4f440a5f-54e3-4455-ab9b-39dfe06f6d21-pub-net
-  2017-03-21 13:35:26,841 - neutron_utils - INFO - Creating subnet with name NeutronUtilsSubnetTests-4f440a5f-54e3-4455-ab9b-39dfe06f6d21-pub-subnet
-  2017-03-21 13:35:28,311 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsSubnetTests-4f440a5f-54e3-4455-ab9b-39dfe06f6d21-pub-subnet
-  2017-03-21 13:35:29,585 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-4f440a5f-54e3-4455-ab9b-39dfe06f6d21-pub-net ok
-  test_create_subnet_empty_cidr (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ...
-  2017-03-21 13:35:31,013 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-41fc0db4-71ee-47e6-bec9-316273e5bcc0-pub-net
-  2017-03-21 13:35:31,652 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-41fc0db4-71ee-47e6-bec9-316273e5bcc0-pub-net ok
-  test_create_subnet_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ...
-  2017-03-21 13:35:32,379 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-1030e0cb-1714-4d18-8619-a03bac0d0257-pub-net
-  2017-03-21 13:35:33,516 - neutron_utils - INFO - Creating subnet with name NeutronUtilsSubnetTests-1030e0cb-1714-4d18-8619-a03bac0d0257-pub-subnet
-  2017-03-21 13:35:34,160 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-1030e0cb-1714-4d18-8619-a03bac0d0257-pub-net ok
-  test_create_subnet_null_cidr (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ...
-  2017-03-21 13:35:35,784 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-1d7522fd-3fb5-4b1c-8741-97d7c47a5f7d-pub-net
-  2017-03-21 13:35:36,367 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-1d7522fd-3fb5-4b1c-8741-97d7c47a5f7d-pub-net ok
-  test_create_subnet_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ...
-  2017-03-21 13:35:37,055 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-0a8ac1b2-e5d4-4522-a079-7e17945e482e-pub-net
-  2017-03-21 13:35:37,691 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-0a8ac1b2-e5d4-4522-a079-7e17945e482e-pub-net ok
-  test_add_interface_router (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:35:38,994 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-net
-  2017-03-21 13:35:40,311 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-subnet
-  2017-03-21 13:35:41,713 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-router
-  2017-03-21 13:35:44,131 - neutron_utils - INFO - Adding interface to router with name NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-router
-  2017-03-21 13:35:45,725 - neutron_utils - INFO - Removing router interface from router named NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-router
-  2017-03-21 13:35:47,464 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-router
-  2017-03-21 13:35:48,670 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-subnet
-  2017-03-21 13:35:50,921 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-433818c9-4472-49a8-9241-791ad0a71d3f-pub-net ok
-  test_add_interface_router_null_router (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:35:52,230 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-1fc2de16-2d3e-497b-b947-022b1bf9d90c-pub-net
-  2017-03-21 13:35:53,662 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-1fc2de16-2d3e-497b-b947-022b1bf9d90c-pub-subnet
-  2017-03-21 13:35:55,203 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-1fc2de16-2d3e-497b-b947-022b1bf9d90c-pub-subnet
-  2017-03-21 13:35:55,694 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-1fc2de16-2d3e-497b-b947-022b1bf9d90c-pub-net ok
-  test_add_interface_router_null_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:35:57,392 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-2e4fb9f3-312b-4954-8015-435464fdc8b0-pub-net
-  2017-03-21 13:35:58,215 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-2e4fb9f3-312b-4954-8015-435464fdc8b0-pub-router
-  2017-03-21 13:36:00,369 - neutron_utils - INFO - Adding interface to router with name NeutronUtilsRouterTests-2e4fb9f3-312b-4954-8015-435464fdc8b0-pub-router
-  2017-03-21 13:36:00,369 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-2e4fb9f3-312b-4954-8015-435464fdc8b0-pub-router
-  2017-03-21 13:36:02,742 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-2e4fb9f3-312b-4954-8015-435464fdc8b0-pub-net ok
-  test_create_port (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:05,010 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-pub-net
-  2017-03-21 13:36:05,996 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-pub-subnet
-  2017-03-21 13:36:09,103 - neutron_utils - INFO - Creating port for network with name - NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-pub-net
-  2017-03-21 13:36:10,312 - neutron_utils - INFO - Deleting port with name NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-port
-  2017-03-21 13:36:11,045 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-pub-subnet
-  2017-03-21 13:36:14,265 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-dde05ce1-a2f8-4c5e-a028-e1ca0e11a05b-pub-net ok
-  test_create_port_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:16,250 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-pub-net
-  2017-03-21 13:36:16,950 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-pub-subnet
-  2017-03-21 13:36:17,798 - neutron_utils - INFO - Creating port for network with name - NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-pub-net
-  2017-03-21 13:36:18,544 - neutron_utils - INFO - Deleting port with name NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-port
-  2017-03-21 13:36:19,582 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-pub-subnet
-  2017-03-21 13:36:21,606 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-b986a259-e873-431c-bde4-b2771ace4549-pub-net ok
-  test_create_port_invalid_ip (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:23,779 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-7ab3a329-9dd8-4e6f-9d52-aafb47ea5122-pub-net
-  2017-03-21 13:36:25,201 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-7ab3a329-9dd8-4e6f-9d52-aafb47ea5122-pub-subnet
-  2017-03-21 13:36:25,599 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-7ab3a329-9dd8-4e6f-9d52-aafb47ea5122-pub-subnet
-  2017-03-21 13:36:26,220 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-7ab3a329-9dd8-4e6f-9d52-aafb47ea5122-pub-net ok
-  test_create_port_invalid_ip_to_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:27,112 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-c016821d-cd4f-4e0f-8f8c-d5cef3392e64-pub-net
-  2017-03-21 13:36:28,720 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-c016821d-cd4f-4e0f-8f8c-d5cef3392e64-pub-subnet
-  2017-03-21 13:36:29,457 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-c016821d-cd4f-4e0f-8f8c-d5cef3392e64-pub-subnet
-  2017-03-21 13:36:29,909 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-c016821d-cd4f-4e0f-8f8c-d5cef3392e64-pub-net ok
-  test_create_port_null_ip (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:31,037 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-9a86227f-6041-4b04-86a7-1701fb86baa3-pub-net
-  2017-03-21 13:36:31,695 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-9a86227f-6041-4b04-86a7-1701fb86baa3-pub-subnet
-  2017-03-21 13:36:32,305 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-9a86227f-6041-4b04-86a7-1701fb86baa3-pub-subnet
-  2017-03-21 13:36:33,553 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-9a86227f-6041-4b04-86a7-1701fb86baa3-pub-net ok
-  test_create_port_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:34,593 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-42efa897-4f65-4d9b-b19d-fbc61f97c966-pub-net
-  2017-03-21 13:36:35,217 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-42efa897-4f65-4d9b-b19d-fbc61f97c966-pub-subnet
-  2017-03-21 13:36:36,648 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-42efa897-4f65-4d9b-b19d-fbc61f97c966-pub-subnet
-  2017-03-21 13:36:37,251 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-42efa897-4f65-4d9b-b19d-fbc61f97c966-pub-net ok
-  test_create_port_null_network_object (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:37,885 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-617f4110-45c1-4900-bad1-a6204f34dd64-pub-net
-  2017-03-21 13:36:38,468 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-617f4110-45c1-4900-bad1-a6204f34dd64-pub-subnet
-  2017-03-21 13:36:40,005 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-617f4110-45c1-4900-bad1-a6204f34dd64-pub-subnet
-  2017-03-21 13:36:41,637 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-617f4110-45c1-4900-bad1-a6204f34dd64-pub-net ok
+  test_create_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ... 2017-03-30 05:37:04,953 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-127e135b-f050-4e85-8c9f-b4f72fb1b028-pub-net
+  2017-03-30 05:37:06,108 - neutron_utils - INFO - Creating subnet with name NeutronUtilsSubnetTests-127e135b-f050-4e85-8c9f-b4f72fb1b028-pub-subnet
+  2017-03-30 05:37:07,544 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsSubnetTests-127e135b-f050-4e85-8c9f-b4f72fb1b028-pub-subnet
+  2017-03-30 05:37:07,944 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-127e135b-f050-4e85-8c9f-b4f72fb1b028-pub-net
+  ok
+  test_create_subnet_empty_cidr (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ... 2017-03-30 05:37:08,594 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-4edb48fe-2532-409b-8dc7-dcb344068a20-pub-net
+  2017-03-30 05:37:09,862 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-4edb48fe-2532-409b-8dc7-dcb344068a20-pub-net
+  ok
+  test_create_subnet_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ... 2017-03-30 05:37:10,962 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-bb15908a-a475-45e9-9777-8b5d3faaaea8-pub-net
+  2017-03-30 05:37:11,973 - neutron_utils - INFO - Creating subnet with name NeutronUtilsSubnetTests-bb15908a-a475-45e9-9777-8b5d3faaaea8-pub-subnet
+  2017-03-30 05:37:13,088 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-bb15908a-a475-45e9-9777-8b5d3faaaea8-pub-net
+  ok
+  test_create_subnet_null_cidr (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ... 2017-03-30 05:37:14,032 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-701278ff-f4b6-478f-b16f-1d3fdfb43ed7-pub-net
+  2017-03-30 05:37:15,100 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-701278ff-f4b6-478f-b16f-1d3fdfb43ed7-pub-net
+  ok
+  test_create_subnet_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSubnetTests) ... 2017-03-30 05:37:15,658 - neutron_utils - INFO - Creating network with name NeutronUtilsSubnetTests-2dad9c37-c892-494b-a8dc-51963ce11cd8-pub-net
+  2017-03-30 05:37:16,184 - neutron_utils - INFO - Deleting network with name NeutronUtilsSubnetTests-2dad9c37-c892-494b-a8dc-51963ce11cd8-pub-net
+  ok
+  test_add_interface_router (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:17,438 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-net
+  2017-03-30 05:37:18,624 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-subnet
+  2017-03-30 05:37:20,041 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-router
+  2017-03-30 05:37:22,518 - neutron_utils - INFO - Adding interface to router with name NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-router
+  2017-03-30 05:37:23,883 - neutron_utils - INFO - Removing router interface from router named NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-router
+  2017-03-30 05:37:25,345 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-router
+  2017-03-30 05:37:27,019 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-subnet
+  2017-03-30 05:37:28,570 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-5f1f0b29-1148-4628-8626-f2aa63b17914-pub-net
+  ok
+  test_add_interface_router_null_router (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:29,583 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-021a41c7-e2b2-45df-bb6d-630ddba2b776-pub-net
+  2017-03-30 05:37:30,234 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-021a41c7-e2b2-45df-bb6d-630ddba2b776-pub-subnet
+  2017-03-30 05:37:30,724 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-021a41c7-e2b2-45df-bb6d-630ddba2b776-pub-subnet
+  2017-03-30 05:37:31,128 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-021a41c7-e2b2-45df-bb6d-630ddba2b776-pub-net
+  ok
+  test_add_interface_router_null_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:32,229 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-e52f96b6-92c9-49a3-ac7f-6a4a61a82c7e-pub-net
+  2017-03-30 05:37:32,833 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-e52f96b6-92c9-49a3-ac7f-6a4a61a82c7e-pub-router
+  2017-03-30 05:37:34,002 - neutron_utils - INFO - Adding interface to router with name NeutronUtilsRouterTests-e52f96b6-92c9-49a3-ac7f-6a4a61a82c7e-pub-router
+  2017-03-30 05:37:34,003 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-e52f96b6-92c9-49a3-ac7f-6a4a61a82c7e-pub-router
+  2017-03-30 05:37:35,238 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-e52f96b6-92c9-49a3-ac7f-6a4a61a82c7e-pub-net
+  ok
+  test_create_port (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:35,898 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-pub-net
+  2017-03-30 05:37:36,426 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-pub-subnet
+  2017-03-30 05:37:37,725 - neutron_utils - INFO - Creating port for network with name - NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-pub-net
+  2017-03-30 05:37:38,511 - neutron_utils - INFO - Deleting port with name NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-port
+  2017-03-30 05:37:39,036 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-pub-subnet
+  2017-03-30 05:37:41,326 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-842cf533-4886-4539-86e4-15bcd8c77b63-pub-net
+  ok
+  test_create_port_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:42,725 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-pub-net
+  2017-03-30 05:37:43,246 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-pub-subnet
+  2017-03-30 05:37:43,945 - neutron_utils - INFO - Creating port for network with name - NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-pub-net
+  2017-03-30 05:37:45,674 - neutron_utils - INFO - Deleting port with name NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-port
+  2017-03-30 05:37:46,197 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-pub-subnet
+  2017-03-30 05:37:48,252 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-303b5eae-374a-4da9-a905-aa39a7d5f026-pub-net
+  ok
+  test_create_port_invalid_ip (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:49,864 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-bd7a4489-79e8-4328-8519-5ad1951c0b5d-pub-net
+  2017-03-30 05:37:50,322 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-bd7a4489-79e8-4328-8519-5ad1951c0b5d-pub-subnet
+  2017-03-30 05:37:50,803 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-bd7a4489-79e8-4328-8519-5ad1951c0b5d-pub-subnet
+  2017-03-30 05:37:51,240 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-bd7a4489-79e8-4328-8519-5ad1951c0b5d-pub-net
+  ok
+  test_create_port_invalid_ip_to_subnet (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:51,767 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-ef2c3474-7b51-483b-b269-05fc4532f294-pub-net
+  2017-03-30 05:37:52,246 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-ef2c3474-7b51-483b-b269-05fc4532f294-pub-subnet
+  2017-03-30 05:37:52,795 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-ef2c3474-7b51-483b-b269-05fc4532f294-pub-subnet
+  2017-03-30 05:37:53,199 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-ef2c3474-7b51-483b-b269-05fc4532f294-pub-net
+  ok
+  test_create_port_null_ip (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:53,806 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-f5829764-e1ff-4a43-b24e-52c0107f12b2-pub-net
+  2017-03-30 05:37:54,326 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-f5829764-e1ff-4a43-b24e-52c0107f12b2-pub-subnet
+  2017-03-30 05:37:55,475 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-f5829764-e1ff-4a43-b24e-52c0107f12b2-pub-subnet
+  2017-03-30 05:37:55,932 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-f5829764-e1ff-4a43-b24e-52c0107f12b2-pub-net
+  ok
+  test_create_port_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:37:57,121 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-194aff34-e0e6-4218-8c17-33a9d9b34816-pub-net
+  2017-03-30 05:37:57,611 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-194aff34-e0e6-4218-8c17-33a9d9b34816-pub-subnet
+  2017-03-30 05:37:58,880 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-194aff34-e0e6-4218-8c17-33a9d9b34816-pub-subnet
+  2017-03-30 05:37:59,638 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-194aff34-e0e6-4218-8c17-33a9d9b34816-pub-net
+  ok
+  test_create_port_null_network_object (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:38:01,037 - neutron_utils - INFO - Creating network with name NeutronUtilsRouterTests-3a49f710-5292-411b-83df-42bb176a5020-pub-net
+  2017-03-30 05:38:01,609 - neutron_utils - INFO - Creating subnet with name NeutronUtilsRouterTests-3a49f710-5292-411b-83df-42bb176a5020-pub-subnet
+  2017-03-30 05:38:02,095 - neutron_utils - INFO - Deleting subnet with name NeutronUtilsRouterTests-3a49f710-5292-411b-83df-42bb176a5020-pub-subnet
+  2017-03-30 05:38:03,034 - neutron_utils - INFO - Deleting network with name NeutronUtilsRouterTests-3a49f710-5292-411b-83df-42bb176a5020-pub-net
+  ok
   test_create_router_empty_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... ok
   test_create_router_null_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... ok
-  test_create_router_simple (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:43,424 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-b6a2dafc-38d4-4c46-bb41-2ba9e1c0084e-pub-router
-  2017-03-21 13:36:45,013 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-b6a2dafc-38d4-4c46-bb41-2ba9e1c0084e-pub-router ok
-  test_create_router_with_public_interface (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ...
-  2017-03-21 13:36:47,829 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-d268dda2-7a30-4d3d-a008-e5aa4592637d-pub-router
-  2017-03-21 13:36:49,448 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-d268dda2-7a30-4d3d-a008-e5aa4592637d-pub-router ok
-  test_create_delete_simple_sec_grp (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ...
-  2017-03-21 13:36:51,067 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-1543e861-ea38-4fbe-9723-c27552e3eb7aname
-  2017-03-21 13:36:51,493 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-1543e861-ea38-4fbe-9723-c27552e3eb7aname
-  2017-03-21 13:36:51,568 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-1543e861-ea38-4fbe-9723-c27552e3eb7aname
-  2017-03-21 13:36:51,772 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-1543e861-ea38-4fbe-9723-c27552e3eb7aname ok
+  test_create_router_simple (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:38:03,973 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-54c3eaf0-00c8-4726-a248-b57f98a37999-pub-router
+  2017-03-30 05:38:05,749 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-54c3eaf0-00c8-4726-a248-b57f98a37999-pub-router
+  ok
+  test_create_router_with_public_interface (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsRouterTests) ... 2017-03-30 05:38:07,392 - neutron_utils - INFO - Creating router with name - NeutronUtilsRouterTests-a4e93ee5-781e-4e9d-9b55-b4d8fb3f0e7b-pub-router
+  2017-03-30 05:38:09,164 - neutron_utils - INFO - Deleting router with name - NeutronUtilsRouterTests-a4e93ee5-781e-4e9d-9b55-b4d8fb3f0e7b-pub-router
+  ok
+  test_create_delete_simple_sec_grp (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ... 2017-03-30 05:38:10,643 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-0b62acfe-fc43-4c9f-bd30-2ce350c73c57name
+  2017-03-30 05:38:11,020 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-0b62acfe-fc43-4c9f-bd30-2ce350c73c57name
+  2017-03-30 05:38:11,084 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-0b62acfe-fc43-4c9f-bd30-2ce350c73c57name
+  2017-03-30 05:38:11,230 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-0b62acfe-fc43-4c9f-bd30-2ce350c73c57name
+  ok
   test_create_sec_grp_no_name (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ... ok
-  test_create_sec_grp_no_rules (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ...
-  2017-03-21 13:36:52,253 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-57c60864-f46c-4391-ba99-6acc4dd123ddname
-  2017-03-21 13:36:52,634 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-57c60864-f46c-4391-ba99-6acc4dd123ddname
-  2017-03-21 13:36:52,718 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-57c60864-f46c-4391-ba99-6acc4dd123ddname ok
-  test_create_sec_grp_one_rule (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ...
-  2017-03-21 13:36:53,082 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,483 - neutron_utils - INFO - Retrieving security group rules associate with the security group - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,548 - neutron_utils - INFO - Creating security group to security group - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,548 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,871 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,944 - neutron_utils - INFO - Retrieving security group rules associate with the security group - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:53,991 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name
-  2017-03-21 13:36:54,069 - neutron_utils - INFO - Deleting security group rule with ID - 7f76046c-d043-46e0-9d12-4b983525810b
-  2017-03-21 13:36:54,185 - neutron_utils - INFO - Deleting security group rule with ID - f18a9ed1-466f-4373-a6b2-82bd317bc838
-  2017-03-21 13:36:54,338 - neutron_utils - INFO - Deleting security group rule with ID - fe34a3d0-948e-47c1-abad-c3ec8d33b2fb
-  2017-03-21 13:36:54,444 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-a3ac62bb-a7e8-4fc2-ba4c-e656f1f3c9a1name ok
-  test_create_delete_keypair (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ...
-  2017-03-21 13:36:54,637 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-5ce69b6f-d8d0-4b66-bd25-30a22cf3bda0 ok
-  test_create_key_from_file (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ...
-  2017-03-21 13:36:58,989 - nova_utils - INFO - Saved public key to - tmp/NovaUtilsKeypairTests-df3e848d-a467-4cc4-99d5-022eb67eee94.pub
-  2017-03-21 13:36:58,990 - nova_utils - INFO - Saved private key to - tmp/NovaUtilsKeypairTests-df3e848d-a467-4cc4-99d5-022eb67eee94
-  2017-03-21 13:36:58,990 - nova_utils - INFO - Saving keypair to - tmp/NovaUtilsKeypairTests-df3e848d-a467-4cc4-99d5-022eb67eee94.pub
-  2017-03-21 13:36:58,990 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-df3e848d-a467-4cc4-99d5-022eb67eee94 ok
-  test_create_keypair (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ...
-  2017-03-21 13:36:59,807 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-fc7f7ffd-80f6-43df-bd41-a3c014ba8c3d ok
-  test_floating_ips (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ...
-  2017-03-21 13:37:02,765 - nova_utils - INFO - Creating floating ip to external network - admin_floating_net ok
+  test_create_sec_grp_no_rules (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ... 2017-03-30 05:38:11,653 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-19dc66ba-630d-4ef5-87e1-b0461971ef8ename
+  2017-03-30 05:38:11,960 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-19dc66ba-630d-4ef5-87e1-b0461971ef8ename
+  2017-03-30 05:38:12,047 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-19dc66ba-630d-4ef5-87e1-b0461971ef8ename
+  ok
+  test_create_sec_grp_one_rule (snaps.openstack.utils.tests.neutron_utils_tests.NeutronUtilsSecurityGroupTests) ... 2017-03-30 05:38:12,321 - neutron_utils - INFO - Creating security group with name - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:12,676 - neutron_utils - INFO - Retrieving security group rules associate with the security group - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:12,735 - neutron_utils - INFO - Creating security group to security group - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:12,736 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:12,948 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:13,024 - neutron_utils - INFO - Retrieving security group rules associate with the security group - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:13,054 - neutron_utils - INFO - Retrieving security group with name - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  2017-03-30 05:38:13,121 - neutron_utils - INFO - Deleting security group rule with ID - 07b4bfbe-c632-496b-95f7-b42de9293519
+  2017-03-30 05:38:13,238 - neutron_utils - INFO - Deleting security group rule with ID - c5e58c9f-6cc8-4543-ae39-aa1960b9a3e1
+  2017-03-30 05:38:13,387 - neutron_utils - INFO - Deleting security group rule with ID - 184d29e8-b460-4f80-858f-7915b9bafe9b
+  2017-03-30 05:38:13,492 - neutron_utils - INFO - Deleting security group with name - NeutronUtilsSecurityGroupTests-cf3022e5-dc6e-4cc1-8fe0-41c8c1c56defname
+  ok
+  test_create_delete_keypair (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ... 2017-03-30 05:38:13,664 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-cb36f8f9-ceca-4802-8735-a1dc846ad2a8
+  ok
+  test_create_key_from_file (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ... 2017-03-30 05:38:18,337 - nova_utils - INFO - Saved public key to - tmp/NovaUtilsKeypairTests-a7eba01b-9615-4271-b5f9-8fe915972f16.pub
+  2017-03-30 05:38:18,338 - nova_utils - INFO - Saved private key to - tmp/NovaUtilsKeypairTests-a7eba01b-9615-4271-b5f9-8fe915972f16
+  2017-03-30 05:38:18,338 - nova_utils - INFO - Saving keypair to - tmp/NovaUtilsKeypairTests-a7eba01b-9615-4271-b5f9-8fe915972f16.pub
+  2017-03-30 05:38:18,338 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-a7eba01b-9615-4271-b5f9-8fe915972f16
+  ok
+  test_create_keypair (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ... 2017-03-30 05:38:21,492 - nova_utils - INFO - Creating keypair with name - NovaUtilsKeypairTests-74535dab-d450-47b1-8814-c0b3f48b7643
+  ok
+  test_floating_ips (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsKeypairTests) ... 2017-03-30 05:38:23,509 - nova_utils - INFO - Creating floating ip to external network - admin_floating_net
+  ok
   test_create_delete_flavor (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsFlavorTests) ... ok
   test_create_flavor (snaps.openstack.utils.tests.nova_utils_tests.NovaUtilsFlavorTests) ... ok
   test_create_clean_flavor (snaps.openstack.tests.create_flavor_tests.CreateFlavorTests) ... ok
   test_create_delete_flavor (snaps.openstack.tests.create_flavor_tests.CreateFlavorTests) ... ok
   test_create_flavor (snaps.openstack.tests.create_flavor_tests.CreateFlavorTests) ... ok
-  test_create_flavor_existing (snaps.openstack.tests.create_flavor_tests.CreateFlavorTests) ...
-  2017-03-21 13:37:18,545 - create_image - INFO - Found flavor with name - CreateFlavorTests-3befc152-4319-4f9c-82d4-75f8941d9533name ok
+  test_create_flavor_existing (snaps.openstack.tests.create_flavor_tests.CreateFlavorTests) ... 2017-03-30 05:38:34,855 - create_image - INFO - Found flavor with name - CreateFlavorTests-3e389b6c-ee95-4f2d-bf74-78d324722ef2name
+  ok
 
   ----------------------------------------------------------------------
-  Ran 48 tests in 171.000s
+  Ran 48 tests in 131.483s
 
   OK
-  2017-03-21 13:37:18,620 - functest.core.testcase_base - INFO - api_check OK
-  2017-03-21 13:37:18,977 - functest.core.testcase_base - INFO - The results were successfully pushed to DB
-  2017-03-21 13:37:18,977 - run_tests - INFO - Test execution time: 02:52
-  2017-03-21 13:37:18,981 - run_tests - INFO -
-
-  2017-03-21 13:37:18,981 - run_tests - INFO - ============================================
-  2017-03-21 13:37:18,981 - run_tests - INFO - Running test case 'snaps_health_check'...
-  2017-03-21 13:37:18,981 - run_tests - INFO - ============================================
-  2017-03-21 13:37:19,098 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
-  2017-03-21 13:37:19,099 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.7:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
-  2017-03-21 13:37:19,434 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
-  2017-03-21 13:37:19,435 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.7:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
-  test_check_vm_ip_dhcp (snaps.openstack.tests.create_instance_tests.SimpleHealthCheck) ...
-  2017-03-21 13:37:26,082 - create_image - INFO - Creating image
-  2017-03-21 13:37:28,793 - create_image - INFO - Image is active with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-image
-  2017-03-21 13:37:28,793 - create_image - INFO - Image is now active with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-image
-  2017-03-21 13:37:28,794 - OpenStackNetwork - INFO - Creating neutron network SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-priv-net...
-  2017-03-21 13:37:29,308 - neutron_utils - INFO - Creating network with name SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-priv-net
-  2017-03-21 13:37:30,771 - neutron_utils - INFO - Creating subnet with name SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-priv-subnet
-  2017-03-21 13:37:36,974 - neutron_utils - INFO - Creating port for network with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-priv-net
-  2017-03-21 13:37:38,188 - create_instance - INFO - Creating VM with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-inst
-  2017-03-21 13:37:41,538 - create_instance - INFO - Created instance with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-inst
-  2017-03-21 13:37:59,577 - create_instance - INFO - VM is - ACTIVE
-  2017-03-21 13:37:59,577 - create_instance_tests - INFO - Looking for expression Lease of.*obtained in the console log
-  2017-03-21 13:37:59,830 - create_instance_tests - INFO - DHCP lease obtained logged in console
-  2017-03-21 13:37:59,830 - create_instance_tests - INFO - With correct IP address
-  2017-03-21 13:37:59,830 - create_instance - INFO - Deleting Port - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5dport-1
-  2017-03-21 13:37:59,830 - neutron_utils - INFO - Deleting port with name SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5dport-1
-  2017-03-21 13:38:00,705 - create_instance - INFO - Deleting VM instance - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-inst
-  2017-03-21 13:38:01,412 - create_instance - INFO - Checking deletion status
-  2017-03-21 13:38:04,938 - create_instance - INFO - VM has been properly deleted VM with name - SimpleHealthCheck-23244728-5a5a-4545-9b16-50257a595e5d-inst
+  2017-03-30 05:38:34,905 - functest - INFO - api_check OK
+  2017-03-30 05:38:35,259 - functest - INFO - The results were successfully pushed to DB
+  2017-03-30 05:38:35,259 - run_tests - INFO - Test execution time: 02:12
+  2017-03-30 05:38:35,267 - run_tests - INFO -
+
+  2017-03-30 05:38:35,268 - run_tests - INFO - ============================================
+  2017-03-30 05:38:35,268 - run_tests - INFO - Running test case 'snaps_health_check'...
+  2017-03-30 05:38:35,268 - run_tests - INFO - ============================================
+  2017-03-30 05:38:35,383 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:38:35,384 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  2017-03-30 05:38:35,855 - functest - INFO - Using flavor metatdata '{'hw:mem_page_size': 'any'}'
+  2017-03-30 05:38:35,856 - file_utils - INFO - Attempting to read OS environment file - /home/opnfv/functest/conf/openstack.creds
+  2017-03-30 05:38:35,856 - openstack_tests - INFO - OS Credentials = OSCreds - username=admin, password=admin, auth_url=http://192.168.10.2:5000/v3, project_name=admin, identity_api_version=3, image_api_version=1, network_api_version=2, compute_api_version=2, user_domain_id=default, proxy_settings=None
+  test_check_vm_ip_dhcp (snaps.openstack.tests.create_instance_tests.SimpleHealthCheck) ... 2017-03-30 05:38:39,896 - create_image - INFO - Creating image
+  2017-03-30 05:38:41,843 - create_image - INFO - Image is active with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-image
+  2017-03-30 05:38:41,843 - create_image - INFO - Image is now active with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-image
+  2017-03-30 05:38:41,845 - OpenStackNetwork - INFO - Creating neutron network SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-priv-net...
+  2017-03-30 05:38:42,140 - neutron_utils - INFO - Creating network with name SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-priv-net
+  2017-03-30 05:38:42,480 - neutron_utils - INFO - Creating subnet with name SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-priv-subnet
+  2017-03-30 05:38:44,166 - neutron_utils - INFO - Creating port for network with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-priv-net
+  2017-03-30 05:38:45,173 - create_instance - INFO - Creating VM with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-inst
+  2017-03-30 05:38:48,419 - create_instance - INFO - Created instance with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-inst
+  2017-03-30 05:39:05,164 - create_instance - INFO - VM is - ACTIVE
+  2017-03-30 05:39:05,164 - create_instance_tests - INFO - Looking for expression Lease of.*obtained in the console log
+  2017-03-30 05:39:06,547 - create_instance_tests - INFO - DHCP lease obtained logged in console
+  2017-03-30 05:39:06,548 - create_instance_tests - INFO - With correct IP address
+  2017-03-30 05:39:06,548 - create_instance - INFO - Deleting Port - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181port-1
+  2017-03-30 05:39:06,548 - neutron_utils - INFO - Deleting port with name SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181port-1
+  2017-03-30 05:39:07,178 - create_instance - INFO - Deleting VM instance - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-inst
+  2017-03-30 05:39:07,693 - create_instance - INFO - Checking deletion status
+  2017-03-30 05:39:11,088 - create_instance - INFO - VM has been properly deleted VM with name - SimpleHealthCheck-85a41a34-a9b3-463d-a12c-4bd057d70181-inst
   ok
 
   ----------------------------------------------------------------------
-  Ran 1 test in 46.982s
+  Ran 1 test in 36.376s
 
   OK
-  2017-03-21 13:38:06,417 - functest.core.testcase_base - INFO - snaps_health_check OK
-  2017-03-21 13:38:06,778 - functest.core.testcase_base - INFO - The results were successfully pushed to DB
-  2017-03-21 13:38:06,779 - run_tests - INFO - Test execution time: 00:47
-  2017-03-21 13:38:06,779 - run_tests - INFO -
+  2017-03-30 05:39:12,233 - functest - INFO - snaps_health_check OK
+  2017-03-30 05:39:12,598 - functest - INFO - The results were successfully pushed to DB
+  2017-03-30 05:39:12,598 - run_tests - INFO - Test execution time: 00:37
+  2017-03-30 05:39:12,599 - run_tests - INFO -
+
   and
 
   root@22e436918db0:~/repos/functest/ci# functest testcase run vping_ssh
index 3920b7a..ce0bc20 100755 (executable)
@@ -69,7 +69,7 @@ fi
 echo "Checking OpenStack endpoints:"
 publicURL=$(openstack catalog show  identity |awk '/public/ {print $4}')
 publicIP=$(echo $publicURL|sed 's/^.*http.*\:\/\///'|sed 's/.[^:]*$//')
-publicPort=$(echo $publicURL|sed 's/^.*://'|sed 's/\/.*$//')
+publicPort=$(echo $publicURL|grep -Po '(?<=:)\d+')
 https_enabled=$(echo $publicURL | grep 'https')
 if [[ -n $https_enabled ]]; then
     echo ">>Verifying SSL connectivity to the public endpoint $publicIP:$publicPort..."
@@ -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|sed 's/^.*://'|sed 's/.[^\/]*$//')
-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
index b43b5a7..cd395ab 100644 (file)
@@ -16,5 +16,13 @@ os:
     vping:
         image_name: TestVM
 
+    odl_sfc:
+        image_base_url: "http://artifacts.opnfv.org/sfc/demo"
+        image_name: sfc_nsh_danube
+        image_file_name: sf_nsh_danube_arm64.img
+        image_initrd: sf_nsh_danube_arm64-initrd
+        image_kernel: sf_nsh_danube_arm64-kernel
+        image_format: ami
+        os_cmd_line: 'root=LABEL=cloudimg-rootfs ro'
     doctor:
         image_name: TestVM
old mode 100755 (executable)
new mode 100644 (file)
index 95a4408..9b79607
@@ -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,12 +104,26 @@ 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
     image_name: TestSfcVm
     image_file_name: firewall_block_image.img
 
+odl_sfc:
+    image_base_url: "http://artifacts.opnfv.org/sfc/images"
+    image_name: sfc_nsh_danube
+    image_file_name: sfc_nsh_danube.qcow2
+    image_format: qcow2
+
 tempest:
     deployment_name: opnfv-tempest
     identity:
@@ -125,7 +151,7 @@ rally:
     router_name: rally-router
 
 refstack:
-    tempest_conf_path: openstack/refstack_client/tempest.conf
+    tempest_conf_path: openstack/refstack_client/refstack_tempest.conf
     defcore_list: openstack/refstack_client/defcore.txt
 
 vnf:
@@ -201,6 +227,11 @@ example:
     sg_desc: Example Security group
 
 results:
-    # you can also set a dir (e.g. /home/opnfv/db) to dump results
-    # test_db_url: file:///home/opnfv/db
-    test_db_url: http://testresults.opnfv.org/test/api/v1
+    # 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: ""
old mode 100755 (executable)
new mode 100644 (file)
index d984a3f..d47766b
@@ -22,3 +22,7 @@ ovs:
     tempest:
         use_custom_images: True
         use_custom_flavors: True
+multisite:
+    tempest:
+        use_custom_images: True
+        use_custom_flavors: True
diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh
new file mode 100644 (file)
index 0000000..f3fdef2
--- /dev/null
@@ -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 (executable)
index 3872a07..0000000
+++ /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:])
index 26aff9b..77e9355 100644 (file)
@@ -2,10 +2,10 @@ apex:
     ip: ''
     user: 'stack'
     pkey: '/root/.ssh/id_rsa'
-compass:
-    ip: '192.168.200.2'
-    user: 'root'
-    password: 'root'
+compass:
+    ip: '192.168.200.2'
+    user: 'root'
+    password: 'root'
 fuel:
     ip: '10.20.0.2'
     user: 'root'
diff --git a/functest/ci/logging.ini b/functest/ci/logging.ini
new file mode 100644 (file)
index 0000000..210c8f5
--- /dev/null
@@ -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 (file)
index 2a2399d..0000000
+++ /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"
-        }
-    }
-}
index e9a470f..8e17a4f 100755 (executable)
@@ -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))
index a49588b..e5cae81 100644 (file)
@@ -1,5 +1,5 @@
 img_name_regex = ^TestVM$
 img_url = http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img
-flavor_ref_ram = 128
+flavor_ref_ram = 256
 flavor_ref_alt_ram = 256
-heat_instance_type_ram = 128
+heat_instance_type_ram = 256
index 37b90f9..7676009 100755 (executable)
@@ -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("=")
@@ -144,8 +142,9 @@ def run_test(test, tier_name, testcases=None):
         try:
             module = importlib.import_module(run_dict['module'])
             cls = getattr(module, run_dict['class'])
-            test_case = cls()
-
+            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)
@@ -154,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_criteria()
+                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']))
@@ -166,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()
@@ -210,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
@@ -242,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)
@@ -255,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
@@ -264,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)
old mode 100755 (executable)
new mode 100644 (file)
index 23b214b..d98a2de
@@ -8,8 +8,9 @@ tiers:
             operations in the VIM.
         testcases:
             -
-                name: connection_check
-                criteria: 'status == "PASS"'
+                case_name: connection_check
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: false
                 description: >-
@@ -18,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: ''
@@ -27,8 +27,9 @@ tiers:
                     class: 'ConnectionCheck'
 
             -
-                name: api_check
-                criteria: 'status == "PASS"'
+                case_name: api_check
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: false
                 description: >-
@@ -37,16 +38,17 @@ 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'
+
             -
-                name: snaps_health_check
-                criteria: 'status == "PASS"'
+                case_name: snaps_health_check
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: false
                 description: >-
@@ -60,6 +62,7 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.openstack.snaps.health_check'
                     class: 'HealthCheck'
+
     -
         name: smoke
         order: 1
@@ -68,8 +71,9 @@ tiers:
             Set of basic Functional tests to validate the OPNFV scenarios.
         testcases:
             -
-                name: vping_ssh
-                criteria: 'status == "PASS"'
+                case_name: vping_ssh
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: true
                 description: >-
@@ -84,8 +88,9 @@ tiers:
                     class: 'VPingSSH'
 
             -
-                name: vping_userdata
-                criteria: 'status == "PASS"'
+                case_name: vping_userdata
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: true
                 description: >-
@@ -99,8 +104,9 @@ tiers:
                     class: 'VPingUserdata'
 
             -
-                name: tempest_smoke_serial
-                criteria: 'success_rate == 100%'
+                case_name: tempest_smoke_serial
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -116,8 +122,9 @@ tiers:
                     class: 'TempestSmokeSerial'
 
             -
-                name: rally_sanity
-                criteria: 'success_rate == 100%'
+                case_name: rally_sanity
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -131,8 +138,9 @@ tiers:
                     class: 'RallySanity'
 
             -
-                name: refstack_defcore
-                criteria: 'success_rate == 100%'
+                case_name: refstack_defcore
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -146,8 +154,9 @@ tiers:
                     class: 'RefstackClient'
 
             -
-                name: odl
-                criteria: 'success_rate == 100%'
+                case_name: odl
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: false
                 description: >-
@@ -166,8 +175,9 @@ tiers:
                             -  /home/opnfv/repos/odl_test/csit/suites/openstack/neutron
 
             -
-                name: odl_netvirt
-                criteria: 'success_rate == 100%'
+                case_name: odl_netvirt
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -188,8 +198,9 @@ tiers:
                             -  /home/opnfv/repos/odl_test/csit/suites/openstack/connectivity
 
             -
-                name: fds
-                criteria: 'success_rate == 100%'
+                case_name: fds
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -207,8 +218,9 @@ tiers:
                             -  /home/opnfv/repos/fds/testing/robot
 
             -
-                name: onos
-                criteria: 'status == "PASS"'
+                case_name: onos
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: true
                 description: >-
@@ -223,8 +235,9 @@ tiers:
                     class: 'Onos'
 
             -
-                name: snaps_smoke
-                criteria: 'status == "PASS"'
+                case_name: snaps_smoke
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -252,8 +265,10 @@ tiers:
             integrated in functest
         testcases:
             -
-                name: promise
-                criteria: 'success_rate == 100%'
+                case_name: promise
+                enabled: false
+                project_name: promise
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -262,12 +277,16 @@ tiers:
                     installer: '(fuel)|(joid)'
                     scenario: ''
                 run:
-                     module: 'functest.opnfv_tests.features.promise'
-                     class: 'Promise'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/promise/promise/test/functest && python ./run_tests.py'
 
             -
-                name: doctor
-                criteria: 'status == "PASS"'
+                case_name: doctor-notification
+                enabled: false
+                project_name: doctor
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -276,12 +295,16 @@ tiers:
                     installer: '(apex)|(fuel)'
                     scenario: '^((?!fdio).)*$'
                 run:
-                    module: 'functest.opnfv_tests.features.doctor'
-                    class: 'Doctor'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/doctor/tests && ./run.sh'
 
             -
-                name: bgpvpn
-                criteria: 'status == "PASS"'
+                case_name: bgpvpn
+                enabled: false
+                project_name: sdnvpn
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -290,12 +313,16 @@ tiers:
                     installer: '(fuel)|(apex)|(netvirt)'
                     scenario: 'bgpvpn'
                 run:
-                    module: 'functest.opnfv_tests.features.sdnvpn'
-                    class: 'SdnVpnTests'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/sdnvpn/sdnvpn/test/functest && python ./run_tests.py'
 
             -
-                name: security_scan
-                criteria: 'status == "PASS"'
+                case_name: security_scan
+                enabled: false
+                project_name: securityscanning
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -304,12 +331,34 @@ tiers:
                     installer: 'apex'
                     scenario: '^((?!fdio).)*$'
                 run:
-                    module: 'functest.opnfv_tests.features.security_scan'
-                    class: 'SecurityScan'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: '. /home/opnfv/functest/conf/stackrc && cd /home/opnfv/repos/securityscanning && python security_scan.py --config config.ini && cd -'
+
+            -
+                case_name: copper
+                enabled: false
+                project_name: copper
+                criteria: 100
+                blocking: false
+                clean_flag: true
+                description: >-
+                    Test suite for policy management based on OpenStack Congress
+                dependencies:
+                    installer: 'apex'
+                    scenario: '^((?!fdio).)*$'
+                run:
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/copper/tests && bash run.sh && cd -'
 
             -
-                name: multisite
-                criteria: 'success_rate == 100%'
+                case_name: multisite
+                enabled: false
+                project_name: multisite
+                criteria: 100
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -320,9 +369,12 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.openstack.tempest.tempest'
                     class: 'TempestMultisite'
+
             -
-                name: odl-sfc
-                criteria: 'status == "PASS"'
+                case_name: functest-odl-sfc
+                enabled: false
+                project_name: sfc
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -331,11 +383,16 @@ tiers:
                     installer: '(apex)|(fuel)'
                     scenario: 'odl_l2-sfc'
                 run:
-                    module: 'functest.opnfv_tests.features.odl_sfc'
-                    class: 'OpenDaylightSFC'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/sfc/sfc/tests/functest && python ./run_tests.py'
+
             -
-                name: onos_sfc
-                criteria: 'status == "PASS"'
+                case_name: onos_sfc
+                enabled: false
+                project_name: functest
+                criteria: 100
                 blocking: true
                 clean_flag: true
                 description: >-
@@ -346,9 +403,12 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.sdn.onos.onos'
                     class: 'OnosSfc'
+
             -
-                name: parser
-                criteria: 'ret == 0'
+                case_name: parser-basics
+                enabled: false
+                project_name: parser
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -357,11 +417,16 @@ tiers:
                     installer: 'fuel'
                     scenario: '^((?!bgpvpn|noha).)*$'
                 run:
-                    module: 'functest.opnfv_tests.vnf.rnc.parser'
-                    class: 'Parser'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/parser/tests && ./functest_run.sh'
+
             -
-                name: domino
-                criteria: 'status == "PASS"'
+                case_name: domino-multinode
+                enabled: false
+                project_name: domino
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -370,11 +435,16 @@ tiers:
                     installer: ''
                     scenario: ''
                 run:
-                    module: 'functest.opnfv_tests.features.domino'
-                    class: 'Domino'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/domino && ./tests/run_multinode.sh'
+
             -
-                name: netready
-                criteria: 'status == "PASS"'
+                case_name: gluon_vping
+                enabled: false
+                project_name: netready
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -383,11 +453,16 @@ tiers:
                     installer: 'apex'
                     scenario: 'gluon'
                 run:
-                     module: 'functest.opnfv_tests.features.netready'
-                     class: 'GluonVping'
+                    module: 'functest.core.feature'
+                    class: 'BashFeature'
+                    args:
+                        cmd: 'cd /home/opnfv/repos/netready/test/functest && python ./gluon-test-suite.py'
+
             -
-                name: barometer
-                criteria: 'status == "PASS"'
+                case_name: barometercollectd
+                enabled: false
+                project_name: barometer
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -401,6 +476,7 @@ tiers:
                 run:
                      module: 'functest.opnfv_tests.features.barometer'
                      class: 'BarometerCollectd'
+
     -
         name: components
         order: 3
@@ -409,8 +485,9 @@ tiers:
             Extensive testing of OpenStack API.
         testcases:
             -
-                name: tempest_full_parallel
-                criteria: 'success_rate >= 80%'
+                case_name: tempest_full_parallel
+                project_name: functest
+                criteria: 80
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -423,9 +500,11 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.openstack.tempest.tempest'
                     class: 'TempestFullParallel'
+
             -
-                name: tempest_custom
-                criteria: 'success_rate == 100%'
+                case_name: tempest_custom
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -440,9 +519,11 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.openstack.tempest.tempest'
                     class: 'TempestCustom'
+
             -
-                name: rally_full
-                criteria: 'success_rate >= 90%'
+                case_name: rally_full
+                project_name: functest
+                criteria: 90
                 blocking: false
                 clean_flag: false
                 description: >-
@@ -463,8 +544,9 @@ tiers:
             Collection of VNF test cases.
         testcases:
             -
-                name: cloudify_ims
-                criteria: 'status == "PASS"'
+                case_name: cloudify_ims
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
@@ -476,22 +558,28 @@ tiers:
                 run:
                     module: 'functest.opnfv_tests.vnf.ims.cloudify_ims'
                     class: 'CloudifyIms'
-#          -
-#               name: aaa
-#               criteria: 'ret == 0'
-#               blocking: false
-#               clean_flag: true
-#               description: >-
-#                   Test suite from Parser project.
-#               dependencies:
-#                   installer: ''
-#                   scenario: ''
-#               run:
-#                   module: 'functest.opnfv_tests.vnf.aaa.aaa'
-#                   class: 'AaaVnf'
-            -
-                name: orchestra_ims
-                criteria: 'ret == 0'
+
+            -
+                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
                 clean_flag: true
                 description: >-
@@ -504,22 +592,26 @@ tiers:
                     class: 'ImsVnf'
 
             -
-                name: opera_ims
-                criteria: 'status == "PASS"'
+                case_name: opera_vims
+                enabled: false
+                project_name: opera
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
                     VNF deployment with OPEN-O
                 dependencies:
-                    installer: 'unknown'
-                    scenario: 'unknown'
+                    installer: 'compass'
+                    scenario: 'os-nosdn-openo-ha'
                 run:
                     module: 'functest.opnfv_tests.vnf.ims.opera_ims'
                     class: 'OperaIms'
 
             -
-                name: vyos_vrouter
-                criteria: 'status == "PASS"'
+                case_name: vyos_vrouter
+                enabled: false
+                project_name: functest
+                criteria: 100
                 blocking: false
                 clean_flag: true
                 description: >-
index f4c6f70..12562f0 100644 (file)
@@ -46,13 +46,16 @@ class TierBuilder(object):
                 scenario = dic_testcase['dependencies']['scenario']
                 dep = th.Dependency(installer, scenario)
 
-                testcase = th.TestCase(name=dic_testcase['name'],
+                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):
index 6b4864b..36ce245 100644 (file)
@@ -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
 
@@ -158,7 +163,7 @@ class TestCase(object):
         for line in lines:
             out += ("|    " + line.ljust(LINE_LENGTH - 7) + " |\n")
         out += ("| Criteria:  " +
-                self.criteria.ljust(LINE_LENGTH - 14) + "|\n")
+                str(self.criteria).ljust(LINE_LENGTH - 14) + "|\n")
         out += ("| Dependencies:".ljust(LINE_LENGTH - 1) + "|\n")
         installer = self.dependency.get_installer()
         scenario = self.dependency.get_scenario()
index cc697ed..2104e12 100644 (file)
@@ -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()
index 14ad01b..f5ba4b3 100644 (file)
@@ -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
index f85f404..e54eb42 100644 (file)
@@ -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):
index 6644a0c..3d3f1cb 100644 (file)
@@ -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)
index 012b11d..531f0ff 100644 (file)
@@ -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)
index 325c10d..140c9bb 100644 (file)
+#!/usr/bin/env python
+
+# Copyright (c) 2016 ZTE Corp and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the parent class of all Functest Features.
+
+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 testcase as base
+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>, "
+              "Cedric Ollivier <cedric.ollivier@orange.com>")
+
 
 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.case_name)
+
+    def execute(self, **kwargs):
+        """Execute the Python method.
+
+        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.
+
+        Args:
+            kwargs: Arbitrary keyword arguments.
 
-    def __init__(self, project='functest', case='', repo='', cmd=''):
-        super(Feature, self).__init__()
-        self.project_name = project
-        self.case_name = case
-        self.cmd = cmd
-        self.repo = CONST.__getattribute__(repo)
-        self.result_file = self.get_result_file()
-        self.logger = ft_logger.Logger(project).getLogger()
+        Returns:
+            -1.
+        """
+        # pylint: disable=unused-argument,no-self-use
+        return -1
 
     def run(self, **kwargs):
-        self.prepare()
+        """Run the feature.
+
+        It allows executing any Python method by calling execute().
+
+        It sets the following attributes required to push the results
+        to DB:
+
+            * result,
+            * start_time,
+            * stop_time.
+
+        It doesn't fulfill details when pushing the results to the DB.
+
+        Args:
+            kwargs: Arbitrary keyword arguments.
+
+        Returns:
+            TestCase.EX_OK if execute() returns 0,
+            TestCase.EX_RUN_ERROR otherwise.
+        """
         self.start_time = time.time()
-        ret = self.execute()
+        exit_code = base.TestCase.EX_RUN_ERROR
+        self.result = 0
+        try:
+            if self.execute(**kwargs) == 0:
+                exit_code = base.TestCase.EX_OK
+                self.result = 100
+            ft_utils.logger_test_results(
+                self.project_name, self.case_name,
+                self.result, self.details)
+        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.stop_time = time.time()
-        self.post()
-        self.parse_results(ret)
-        self.log_results()
-        self.logger.info("Test result is stored in '%s'" % self.result_file)
-        return base.TestCase.EX_OK
-
-    def execute(self):
-        '''
-        Executer method that can be overwritten
-        By default it executes a shell command.
-        '''
-        return ft_utils.execute_command(self.cmd, output_file=self.result_file)
-
-    def prepare(self, **kwargs):
-        pass
-
-    def post(self, **kwargs):
-        pass
-
-    def parse_results(self, ret):
-        exit_code = base.TestCase.EX_OK
-        if ret == 0:
-            self.logger.info("{} OK".format(self.project_name))
-            self.criteria = 'PASS'
-        else:
-            self.logger.info("{} FAILED".format(self.project_name))
-            exit_code = base.TestCase.EX_RUN_ERROR
-            self.criteria = "FAIL"
-
         return exit_code
 
-    def get_result_file(self):
-        return "{}/{}.log".format(CONST.dir_results, self.project_name)
 
-    def log_results(self):
-        ft_utils.logger_test_results(self.project_name,
-                                     self.case_name,
-                                     self.criteria,
-                                     self.details)
+class BashFeature(Feature):
+    """Class designed to run any bash command."""
+
+    __logger = logging.getLogger(__name__)
+
+    def execute(self, **kwargs):
+        """Execute the cmd passed as arg
+
+        Args:
+            kwargs: Arbitrary keyword arguments.
+
+        Returns:
+            0 if cmd returns 0,
+            -1 otherwise.
+        """
+        ret = -1
+        try:
+            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)
+        except Exception:  # pylint: disable=broad-except
+            self.__logger.exception("Execute cmd: %s failed", cmd)
+        return ret
index 4f77762..a6e4766 100644 (file)
@@ -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):
-        super(PyTestSuiteRunner, self).__init__()
+
+    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.criteria = '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.criteria = 'PASS'
+            self.logger.info("%s OK", self.case_name)
+            self.result = 100
 
         self.details = {}
         return exit_code
index b540cfb..4316152 100644 (file)
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 
-"""Define the parent class of Functest TestCase."""
+"""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>"
 
 
 class TestCase(object):
-    """Parent class of Functest TestCase."""
+    """Base model for single test case."""
 
     EX_OK = os.EX_OK
+    """everything is OK"""
+
     EX_RUN_ERROR = os.EX_SOFTWARE
+    """run() failed"""
+
     EX_PUSH_TO_DB_ERROR = os.EX_SOFTWARE - 1
+    """push_to_db() failed"""
+
     EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2
+    """results are false"""
 
-    logger = ft_logger.Logger(__name__).getLogger()
+    __logger = logging.getLogger(__name__)
 
-    def __init__(self):
+    def __init__(self, **kwargs):
         self.details = {}
-        self.project_name = "functest"
-        self.case_name = ""
-        self.criteria = ""
-        self.start_time = ""
-        self.stop_time = ""
+        self.project_name = kwargs.get('project_name', 'functest')
+        self.case_name = kwargs.get('case_name', '')
+        self.criteria = kwargs.get('criteria', 100)
+        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 check_criteria(self):
-        """Interpret the results of TestCase.
+    def get_duration(self):
+        """Return the duration of the test case.
 
-        It allows getting the results of TestCase. It completes run()
+        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 is_successful(self):
+        """Interpret the result of the test case.
+
+        It allows getting the result of TestCase. It completes run()
         which only returns the execution status.
 
-        It can be overriden if checking criteria is not suitable.
+        It can be overriden if checking result is not suitable.
 
         Returns:
-            TestCase.EX_OK if criteria is 'PASS'.
+            TestCase.EX_OK if result is 'PASS'.
             TestCase.EX_TESTCASE_FAILED otherwise.
         """
         try:
             assert self.criteria
-            if self.criteria == 'PASS':
-                return TestCase.EX_OK
+            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:
+                # Backward compatibility
+                # It must be removed as soon as TestCase subclasses
+                # stop setting result = 'PASS' or 'FAIL'.
+                # In this case criteria is unread.
+                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):
-        """Run TestCase.
+        """Run the test case.
 
         It allows running TestCase and getting its execution
         status.
 
         The subclasses must override the default implementation which
-        is false on purpose. The only prerequisite is to set the
-        following attributes to push the results to DB:
-            * case_name,
-            * criteria,
+        is false on purpose.
+
+        The new implementation must set the following attributes to
+        push the results to DB:
+
+            * result,
             * start_time,
             * stop_time.
 
         Args:
-            **kwargs: Arbitrary keyword arguments.
+            kwargs: Arbitrary keyword arguments.
 
         Returns:
             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):
-        """Push the results of TestCase to the DB.
+        """Push the results of the test case to the DB.
 
         It allows publishing the results and to check the status.
 
         It could be overriden if the common implementation is not
         suitable. The following attributes must be set before pushing
         the results to DB:
+
+            * project_name,
             * case_name,
-            * criteria,
+            * result,
             * start_time,
             * stop_time.
 
@@ -99,17 +160,19 @@ class TestCase(object):
         try:
             assert self.project_name
             assert self.case_name
-            assert self.criteria
             assert self.start_time
             assert self.stop_time
+            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, self.criteria, self.details):
-                self.logger.info("The results were successfully pushed to DB")
+                    self.stop_time, pub_result, self.details):
+                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
similarity index 53%
rename from functest/core/vnf_base.py
rename to functest/core/vnf.py
index 3f0adcc..5667b29 100644 (file)
@@ -8,27 +8,31 @@
 # 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, project='functest', case='', repo='', cmd=''):
-        super(VnfOnBoardingBase, self).__init__()
-        self.repo = repo
-        self.project_name = project
-        self.case_name = case
-        self.cmd = cmd
+    def __init__(self, **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')
+        self.details['prepare_env'] = {}
         self.details['orchestrator'] = {}
         self.details['vnf'] = {}
         self.details['test_vnf'] = {}
@@ -40,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
@@ -73,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']
@@ -85,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']
@@ -98,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
@@ -111,59 +115,57 @@ class VnfOnBoardingBase(base.TestCase):
 
     # prepare state could consist in the creation of the resources
     # a dedicated user
-    # a dedictaed tenant
+    # a dedicated tenant
     # dedicated images
     def prepare(self):
         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 admin_user_id == '':
-            self.step_failure("Failed to get id of " +
-                              self.creds['username'])
+        if not admin_user_id:
+            self.step_failure("Failed to get id of {0}".format(
+                self.creds['username']))
 
-        tenant_id = os_utils.create_tenant(
-            self.keystone_client, self.tenant_name, self.tenant_description)
+        tenant_id = os_utils.get_tenant_id(self.keystone_client,
+                                           self.tenant_name)
         if not tenant_id:
-            self.step_failure("Failed to create " +
-                              self.tenant_name + " tenant")
-
-        roles_name = ["admin", "Admin"]
-        role_id = ''
-        for role_name in roles_name:
-            if role_id == '':
-                role_id = os_utils.get_role_id(self.keystone_client, role_name)
-
-        if role_id == '':
-            self.logger.error("Failed to get id for %s role" % role_name)
-            self.step_failure("Failed to get role id of " + role_name)
-
-        if not os_utils.add_role_user(self.keystone_client, admin_user_id,
-                                      role_id, tenant_id):
-            self.logger.error("Failed to add %s on tenant" %
-                              self.creds['username'])
-            self.step_failure("Failed to add %s on tenant" %
-                              self.creds['username'])
-
-        user_id = os_utils.create_user(self.keystone_client,
-                                       self.tenant_name,
-                                       self.tenant_name,
-                                       None,
-                                       tenant_id)
+            tenant_id = os_utils.create_tenant(self.keystone_client,
+                                               self.tenant_name,
+                                               self.tenant_description)
+            if not tenant_id:
+                self.step_failure("Failed to get or create {0} tenant".format(
+                    self.tenant_name))
+            roles_name = ["admin", "Admin"]
+            role_id = ''
+            for role_name in roles_name:
+                if not role_id:
+                    role_id = os_utils.get_role_id(self.keystone_client,
+                                                   role_name)
+
+            if not role_id:
+                self.step_failure("Failed to get id for {0} role".format(
+                    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']))
+
+        user_id = os_utils.get_or_create_user(self.keystone_client,
+                                              self.tenant_name,
+                                              self.tenant_name,
+                                              tenant_id)
         if not user_id:
-            self.logger.error("Failed to create %s user" % self.tenant_name)
-            self.step_failure("Failed to create user ")
+            self.step_failure("Failed to get or create {0} user".format(
+                              self.tenant_name))
 
-        if not os_utils.add_role_user(self.keystone_client, user_id,
-                                      role_id, tenant_id):
-            self.logger.error("Failed to add %s on tenant" %
-                              self.tenant_name)
-            self.step_failure("Failed to add %s on tenant" %
-                              self.tenant_name)
+        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
@@ -176,66 +178,46 @@ class VnfOnBoardingBase(base.TestCase):
             "password": self.tenant_name,
         })
 
-    # orchestrator is not mandatory to dpeloy and test VNF
+    # orchestrator is not mandatory to deploy and test VNF
     def deploy_orchestrator(self, **kwargs):
         pass
 
     # 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("Removing %s tenant .." % self.tenant_name)
-        tenant_id = os_utils.get_tenant_id(self.keystone_client,
-                                           self.tenant_name)
-        if tenant_id == '':
-            self.logger.error("Error : Failed to get id of %s tenant" %
-                              self.tenant_name)
-        else:
-            if not os_utils.delete_tenant(self.keystone_client, tenant_id):
-                self.logger.error("Error : Failed to remove %s tenant" %
-                                  self.tenant_name)
-
-        self.logger.info("Removing %s user .." % self.tenant_name)
-        user_id = os_utils.get_user_id(
-            self.keystone_client, self.tenant_name)
-        if user_id == '':
-            self.logger.error("Error : Failed to get id of %s user" %
-                              self.tenant_name)
-        else:
-            if not os_utils.delete_user(self.keystone_client, user_id):
-                self.logger.error("Error : Failed to remove %s user" %
-                                  self.tenant_name)
+        self.__logger.info("test cleaning")
 
     def parse_results(self):
         exit_code = self.EX_OK
-        self.criteria = "PASS"
-        self.logger.info(self.details)
+        self.result = "PASS"
+        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"):
             exit_code = self.EX_RUN_ERROR
-            self.criteria = "FAIL"
+            self.result = "FAIL"
         return exit_code
 
     def log_results(self):
         ft_utils.logger_test_results(self.project_name,
                                      self.case_name,
-                                     self.criteria,
+                                     self.result,
                                      self.details)
 
     def step_failure(self, error_msg):
         part = inspect.stack()[1][3]
-        self.logger.error("Step '%s' failed: %s", part, error_msg)
+        self.__logger.error("Step {0} failed: {1}".format(part, error_msg))
         try:
-            part_info = self.details[part]
+            step_name = self.details_step_mapping[part]
+            part_info = self.details[step_name]
         except KeyError:
             self.details[part] = {}
             part_info = self.details[part]
diff --git a/functest/energy/energy.py b/functest/energy/energy.py
new file mode 100644 (file)
index 0000000..a20c799
--- /dev/null
@@ -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
index 6011340..cbfe7d9 100644 (file)
@@ -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,10 +18,7 @@ class BarometerCollectd(base.Feature):
     Class for executing barometercollectd testcase.
     '''
 
-    def __init__(self):
-        super(BarometerCollectd, self).__init__(project='barometer',
-                                                case='barometercollectd',
-                                                repo='dir_repo_barometer')
+    __logger = logging.getLogger(__name__)
 
     def execute(self):
-        return collectd.main(self.logger)
+        return collectd.main(self.__logger)
diff --git a/functest/opnfv_tests/features/copper.py b/functest/opnfv_tests/features/copper.py
deleted file mode 100644 (file)
index 689341e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 AT&T Intellectual Property, Inc
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import functest.core.feature as base
-
-
-class Copper(base.Feature):
-    def __init__(self):
-        super(Copper, self).__init__(project='copper',
-                                     case='copper-notification',
-                                     repo='dir_repo_copper')
-        self.cmd = 'cd %s/tests && bash run.sh && cd -' % self.repo
diff --git a/functest/opnfv_tests/features/doctor.py b/functest/opnfv_tests/features/doctor.py
deleted file mode 100644 (file)
index d32bbfc..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2017 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
-#
-# 0.1: This script boots the VM1 and allocates IP address from Nova
-# Later, the VM2 boots then execute cloud-init to ping VM1.
-# After successful ping, both the VMs are deleted.
-# 0.2: measure test duration and publish results under json format
-#
-#
-import functest.core.feature as base
-
-
-class Doctor(base.Feature):
-    def __init__(self):
-        super(Doctor, self).__init__(project='doctor',
-                                     case='doctor-notification',
-                                     repo='dir_repo_doctor')
-        self.cmd = 'cd %s/tests && ./run.sh' % self.repo
diff --git a/functest/opnfv_tests/features/domino.py b/functest/opnfv_tests/features/domino.py
deleted file mode 100644 (file)
index e34429b..0000000
+++ /dev/null
@@ -1,25 +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
-#
-# 0.1: This script boots the VM1 and allocates IP address from Nova
-# Later, the VM2 boots then execute cloud-init to ping VM1.
-# After successful ping, both the VMs are deleted.
-# 0.2: measure test duration and publish results under json format
-# 0.3: add report flag to push results when needed
-# 0.4: refactoring to match Test abstraction class
-
-import functest.core.feature as base
-
-
-class Domino(base.Feature):
-    def __init__(self):
-        super(Domino, self).__init__(project='domino',
-                                     case='domino-multinode',
-                                     repo='dir_repo_domino')
-        self.cmd = 'cd %s && ./tests/run_multinode.sh' % self.repo
diff --git a/functest/opnfv_tests/features/netready.py b/functest/opnfv_tests/features/netready.py
deleted file mode 100644 (file)
index 88f377c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-
-#
-import functest.core.feature as base
-
-
-class GluonVping(base.Feature):
-
-    def __init__(self):
-        super(GluonVping, self).__init__(project='netready',
-                                         case='gluon_vping',
-                                         repo='dir_repo_netready')
-        dir_netready_functest = '{}/test/functest'.format(self.repo)
-        self.cmd = ('cd %s && python ./gluon-test-suite.py' %
-                    dir_netready_functest)
diff --git a/functest/opnfv_tests/features/odl_sfc.py b/functest/opnfv_tests/features/odl_sfc.py
deleted file mode 100644 (file)
index fff7f2b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 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 functest.core.feature as base
-
-
-class OpenDaylightSFC(base.Feature):
-
-    def __init__(self):
-        super(OpenDaylightSFC, self).__init__(project='sfc',
-                                              case='functest-odl-sfc',
-                                              repo='dir_repo_sfc')
-        dir_sfc_functest = '{}/sfc/tests/functest'.format(self.repo)
-        self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
diff --git a/functest/opnfv_tests/features/promise.py b/functest/opnfv_tests/features/promise.py
deleted file mode 100644 (file)
index a7f4e62..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import functest.core.feature as base
-
-
-class Promise(base.Feature):
-    def __init__(self):
-        super(Promise, self).__init__(project='promise',
-                                      case='promise',
-                                      repo='dir_repo_promise')
-        dir_promise_functest = '{}/promise/test/functest'.format(self.repo)
-        self.cmd = 'cd %s && python ./run_tests.py' % dir_promise_functest
diff --git a/functest/opnfv_tests/features/sdnvpn.py b/functest/opnfv_tests/features/sdnvpn.py
deleted file mode 100644 (file)
index 10e3146..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 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 functest.core.feature as base
-
-
-class SdnVpnTests(base.Feature):
-
-    def __init__(self):
-        super(SdnVpnTests, self).__init__(project='sdnvpn',
-                                          case='bgpvpn',
-                                          repo='dir_repo_sdnvpn')
-        dir_sfc_functest = '{}/sdnvpn/test/functest'.format(self.repo)
-        self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
diff --git a/functest/opnfv_tests/features/security_scan.py b/functest/opnfv_tests/features/security_scan.py
deleted file mode 100644 (file)
index 2374b39..0000000
+++ /dev/null
@@ -1,24 +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
-#
-
-import functest.core.feature as base
-from functest.utils.constants import CONST
-
-
-class SecurityScan(base.Feature):
-    def __init__(self):
-        super(SecurityScan, self).__init__(project='securityscanning',
-                                           case='security_scan',
-                                           repo='dir_repo_securityscan')
-        self.cmd = ('. {0}/stackrc && '
-                    'cd {1} && '
-                    'python security_scan.py --config config.ini && '
-                    'cd -'.format(CONST.dir_functest_conf,
-                                  self.repo))
index a9cf0ae..dea26ef 100644 (file)
@@ -16,9 +16,12 @@ import functest.core.feature as base
 
 
 class Orchestra(base.Feature):
-    def __init__(self):
-        super(Orchestra, self).__init__(project='orchestra',
-                                        case='orchestra',
-                                        repo='dir_repo_orchestra')
+    def __init__(self, **kwargs):
+        if "project_name" not in kwargs:
+            kwargs["project_name"] = "orchestra"
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "orchestra"
+        kwargs['repo'] = 'dir_repo_orchestra'
+        super(Orchestra, self).__init__(**kwargs)
         # TODO
         # self.cmd = "%s/tests/run.sh %s/tests" % (self.repo, self.repo)
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 (executable)
index b440086..0000000
+++ /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()
index 8c6abc1..40f8386 100644 (file)
@@ -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"
@@ -56,8 +57,8 @@ class RallyBase(testcase.TestCase):
     RALLY_PRIVATE_SUBNET_CIDR = CONST.rally_subnet_cidr
     RALLY_ROUTER_NAME = CONST.rally_router_name
 
-    def __init__(self):
-        super(RallyBase, self).__init__()
+    def __init__(self, **kwargs):
+        super(RallyBase, self).__init__(**kwargs)
         self.mode = ''
         self.summary = []
         self.scenario_dir = ''
@@ -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.criteria = 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.criteria))
+        logger.info("Rally '%s' success_rate is %s%%"
+                    % (self.case_name, success_rate))
 
     def _clean_up(self):
         if self.volume_type:
@@ -536,9 +536,10 @@ class RallyBase(testcase.TestCase):
 
 
 class RallySanity(RallyBase):
-    def __init__(self):
-        super(RallySanity, self).__init__()
-        self.case_name = 'rally_sanity'
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "rally_sanity"
+        super(RallySanity, self).__init__(**kwargs)
         self.mode = 'sanity'
         self.test_name = 'all'
         self.smoke = True
@@ -546,9 +547,10 @@ class RallySanity(RallyBase):
 
 
 class RallyFull(RallyBase):
-    def __init__(self):
-        super(RallyFull, self).__init__()
-        self.case_name = 'rally_full'
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "rally_full"
+        super(RallyFull, self).__init__(**kwargs)
         self.mode = 'full'
         self.test_name = 'all'
         self.smoke = False
index be8fd89..0a1787e 100644 (file)
@@ -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
index 37aa9e3..2a2718d 100755 (executable)
@@ -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,19 +20,19 @@ 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):
 
-    def __init__(self):
-        super(RefstackClient, self).__init__()
-        self.case_name = "refstack_defcore"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "refstack_defcore"
+        super(RefstackClient, self).__init__(**kwargs)
         self.FUNCTEST_TEST = CONST.dir_functest_test
         self.CONF_PATH = CONST.refstack_tempest_conf_path
         self.DEFCORE_LIST = CONST.refstack_defcore_list
@@ -122,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),
@@ -130,12 +139,10 @@ class RefstackClient(testcase.TestCase):
                             "errors": failed_testcases,
                             "skipped": skipped_testcases}
         except Exception:
-            success_rate = 0
+            self.result = 0
 
-        self.criteria = 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.criteria))
+        logger.info("Testcase %s success_rate is %s%%"
+                    % (self.case_name, self.result))
 
     def run(self):
         '''used for functest command line,
@@ -170,7 +177,7 @@ class RefstackClient(testcase.TestCase):
         '''used for manually running,
            python refstack_client.py -c <tempest_conf_path>
            --testlist <testlist_path>
-           can generate a reference tempest.conf by
+           can generate a reference refstack_tempest.conf by
            python tempest_conf.py
         '''
         try:
@@ -192,10 +199,9 @@ class RefstackClient(testcase.TestCase):
         return res
 
 
-class RefstackClientParser(testcase.TestCase):
+class RefstackClientParser(object):
 
     def __init__(self):
-        super(RefstackClientParser, self).__init__()
         self.FUNCTEST_TEST = CONST.dir_functest_test
         self.CONF_PATH = CONST.refstack_tempest_conf_path
         self.DEFCORE_LIST = CONST.refstack_defcore_list
@@ -206,7 +212,7 @@ class RefstackClientParser(testcase.TestCase):
         self.parser = argparse.ArgumentParser()
         self.parser.add_argument(
             '-c', '--config',
-            help='the file path of tempest.conf',
+            help='the file path of refstack_tempest.conf',
             default=self.confpath)
         self.parser.add_argument(
             '-t', '--testlist',
@@ -220,6 +226,7 @@ class RefstackClientParser(testcase.TestCase):
 
 
 if __name__ == '__main__':
+    logging.basicConfig()
     refstackclient = RefstackClient()
     parser = RefstackClientParser()
     args = parser.parse_args(sys.argv[1:])
index 5624ed7..5c04253 100755 (executable)
@@ -5,16 +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 sys
+import logging
+import os
 
-from functest.core import testcase
 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):
@@ -25,6 +24,8 @@ class TempestConf(object):
         self.DEPLOYMENT_ID = conf_utils.get_verifier_deployment_id()
         self.DEPLOYMENT_DIR = conf_utils.get_verifier_deployment_dir(
             self.VERIFIER_ID, self.DEPLOYMENT_ID)
+        self.confpath = os.path.join(CONST.dir_functest_test,
+                                     CONST.refstack_tempest_conf_path)
 
     def generate_tempestconf(self):
         try:
@@ -33,21 +34,20 @@ class TempestConf(object):
                 use_custom_images=True, use_custom_flavors=True)
             conf_utils.configure_tempest_defcore(
                 self.DEPLOYMENT_DIR, img_flavor_dict)
-        except KeyError as e:
-            logger.error("defcore prepare env error with: %s", e)
+        except Exception as e:
+            logger.error("error with generating refstack client "
+                         "reference tempest conf file: %s", e)
 
     def main(self):
         try:
             self.generate_tempestconf()
-            res = testcase.TestCase.EX_OK
+            logger.info("a reference tempest conf file generated "
+                        "at %s", self.confpath)
         except Exception as e:
             logger.error('Error with run: %s', e)
-            res = testcase.TestCase.EX_RUN_ERROR
 
-        return res
 
 if __name__ == '__main__':
+    logging.basicConfig()
     tempestconf = TempestConf()
-    result = tempestconf.main()
-    if result != testcase.TestCase.EX_OK:
-        sys.exit(result)
+    tempestconf.main()
index ad77d9b..50f6709 100644 (file)
@@ -11,7 +11,6 @@ from snaps import test_suite_builder
 
 from functest.opnfv_tests.openstack.snaps.snaps_test_runner import \
     SnapsTestRunner
-from functest.utils.constants import CONST
 
 
 class ApiCheck(SnapsTestRunner):
@@ -20,14 +19,15 @@ class ApiCheck(SnapsTestRunner):
     that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
     and Nova
     """
-    def __init__(self):
-        super(ApiCheck, self).__init__()
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "api_check"
+        super(ApiCheck, self).__init__(**kwargs)
 
         self.suite = unittest.TestSuite()
-        self.case_name = "api_check"
 
         test_suite_builder.add_openstack_api_tests(
-            self.suite,
-            CONST.openstack_creds,
-            self.ext_net_name,
-            use_keystone=CONST.snaps_use_keystone)
+            suite=self.suite,
+            os_creds=self.os_creds,
+            ext_net_name=self.ext_net_name,
+            use_keystone=self.use_keystone)
index 0637bcf..f2753ae 100644 (file)
@@ -11,7 +11,6 @@ from snaps import test_suite_builder
 
 from functest.opnfv_tests.openstack.snaps.snaps_test_runner import \
     SnapsTestRunner
-from functest.utils.constants import CONST
 
 
 class ConnectionCheck(SnapsTestRunner):
@@ -20,14 +19,15 @@ class ConnectionCheck(SnapsTestRunner):
     that simply obtain the different OpenStack clients and may perform
     simple queries
     """
-    def __init__(self):
-        super(ConnectionCheck, self).__init__()
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "connection_check"
+        super(ConnectionCheck, self).__init__(**kwargs)
 
         self.suite = unittest.TestSuite()
-        self.case_name = "connection_check"
 
         test_suite_builder.add_openstack_client_tests(
-            self.suite,
-            CONST.openstack_creds,
-            self.ext_net_name,
-            use_keystone=CONST.snaps_use_keystone)
+            suite=self.suite,
+            os_creds=self.os_creds,
+            ext_net_name=self.ext_net_name,
+            use_keystone=self.use_keystone)
index 8fece74..0daddcd 100644 (file)
@@ -21,19 +21,21 @@ class HealthCheck(SnapsTestRunner):
     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
     """
-    def __init__(self):
-        super(HealthCheck, self).__init__()
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "snaps_images_cirros"
+        super(HealthCheck, self).__init__(**kwargs)
 
         self.suite = unittest.TestSuite()
-        self.case_name = "snaps_health_check"
 
         image_custom_config = None
-        if hasattr(CONST, 'snaps_health_check'):
-            image_custom_config = CONST.snaps_health_check
 
+        if hasattr(CONST, 'snaps_images_cirros'):
+            image_custom_config = CONST.__getattribute__('snaps_images_cirros')
         self.suite.addTest(
             OSIntegrationTestCase.parameterize(
-                SimpleHealthCheck, CONST.openstack_creds, self.ext_net_name,
-                use_keystone=CONST.snaps_use_keystone,
+                SimpleHealthCheck, os_creds=self.os_creds,
+                ext_net_name=self.ext_net_name,
+                use_keystone=self.use_keystone,
                 flavor_metadata=self.flavor_metadata,
                 image_metadata=image_custom_config))
index 45fa6de..d9f95e9 100644 (file)
@@ -21,30 +21,29 @@ class SnapsSmoke(SnapsTestRunner):
     that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
     and Nova
     """
-    def __init__(self):
-        super(SnapsSmoke, self).__init__()
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "snaps_smoke"
+        super(SnapsSmoke, self).__init__(**kwargs)
 
         self.suite = unittest.TestSuite()
-        self.case_name = "snaps_smoke"
-        use_fip = CONST.snaps_use_floating_ips
 
-        # 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.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
-        if use_fip:
-            snaps_dir = CONST.dir_repo_snaps + '/snaps'
+        if self.use_fip:
+            snaps_dir = os.path.join(CONST.__getattribute__('dir_repo_snaps'),
+                                     'snaps')
             os.chdir(snaps_dir)
 
         test_suite_builder.add_openstack_integration_tests(
-            self.suite,
-            CONST.openstack_creds,
-            self.ext_net_name,
-            use_keystone=CONST.snaps_use_keystone,
+            suite=self.suite,
+            os_creds=self.os_creds,
+            ext_net_name=self.ext_net_name,
+            use_keystone=self.use_keystone,
             flavor_metadata=self.flavor_metadata,
-            image_metadata=image_custom_config,
-            use_floating_ips=use_fip)
+            image_metadata=image_config,
+            use_floating_ips=self.use_fip)
index 9d72390..94b9755 100644 (file)
@@ -5,29 +5,36 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-from functest.utils import functest_logger as ft_logger
+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
+from functest.utils.constants import CONST
 
 from snaps.openstack import create_flavor
+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):
-        super(SnapsTestRunner, self).__init__()
+    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'),
+            proxy_settings_str=None, ssh_proxy_cmd=None)
 
-        self.ext_net_name = snaps_utils.get_ext_net_name()
-        self.logger = ft_logger.Logger(self.project_name).getLogger()
+        self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds)
+        self.use_fip = CONST.__getattribute__('snaps_use_floating_ips')
+        self.use_keystone = CONST.__getattribute__('snaps_use_keystone')
         scenario = functest_utils.get_scenario()
 
         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.logger.info("Using flavor metatdata '%s'" % self.flavor_metadata)
+        self.logger.info("Using flavor metadata '%s'", self.flavor_metadata)
index 4ea1a04..327ba07 100644 (file)
@@ -5,19 +5,15 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-from snaps.openstack.tests import openstack_tests
 from snaps.openstack.utils import neutron_utils
 
-from functest.utils.constants import CONST
 
-
-def get_ext_net_name():
+def get_ext_net_name(os_creds):
     """
     Returns the first external network name
+    :param: os_creds: an instance of snaps OSCreds object
     :return:
     """
-    os_env_file = CONST.openstack_creds
-    os_creds = openstack_tests.get_credentials(os_env_file=os_env_file)
     neutron = neutron_utils.neutron_client(os_creds)
     ext_nets = neutron_utils.get_external_networks(neutron)
     return ext_nets[0]['network']['name']
index f4a94f6..cd6a2a8 100644 (file)
@@ -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)
index 0da92cd..026b24f 100644 (file)
@@ -52,7 +52,7 @@
     tests:
         - tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops
 
-
+-
     # https://bugs.opendaylight.org/show_bug.cgi?id=5586
     scenarios:
         - os-odl-bgpvpn-ha
@@ -60,6 +60,5 @@
         - os-odl_l2-bgpvpn-ha
     installers:
         - apex
-        - fuel
     tests:
         - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard
index 0addbd1..a41d07c 100644 (file)
@@ -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,17 +22,16 @@ 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):
 
-    def __init__(self):
-        super(TempestCommon, self).__init__()
+    def __init__(self, **kwargs):
+        super(TempestCommon, self).__init__(**kwargs)
         self.MODE = ""
         self.OPTION = ""
         self.VERIFIER_ID = conf_utils.get_verifier_id()
@@ -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,21 +206,17 @@ class TempestCommon(testcase.TestCase):
                             "errors": error_logs,
                             "skipped": skipped_testcase}
         except Exception:
-            success_rate = 0
+            self.result = 0
 
-        self.criteria = 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.criteria))
+        logger.info("Tempest %s success_rate is %s%%"
+                    % (self.case_name, self.result))
 
     def run(self):
 
         self.start_time = time.time()
-
-        if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
-            os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
-
         try:
+            if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
+                os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
             image_and_flavor = conf_utils.create_tempest_resources()
             conf_utils.configure_tempest(
                 self.DEPLOYMENT_DIR,
@@ -234,35 +238,39 @@ class TempestCommon(testcase.TestCase):
 
 class TempestSmokeSerial(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "tempest_smoke_serial"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'tempest_smoke_serial'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "smoke"
         self.OPTION = "--concurrency 1"
 
 
 class TempestSmokeParallel(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "tempest_smoke_parallel"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'tempest_smoke_parallel'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "smoke"
         self.OPTION = ""
 
 
 class TempestFullParallel(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "tempest_full_parallel"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'tempest_full_parallel'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "full"
 
 
 class TempestMultisite(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "multisite"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'multisite'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "feature_multisite"
         self.OPTION = "--concurrency 1"
         conf_utils.install_verifier_ext(CONST.dir_repo_kingbird)
@@ -270,17 +278,19 @@ class TempestMultisite(TempestCommon):
 
 class TempestCustom(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "tempest_custom"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'tempest_custom'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "custom"
         self.OPTION = "--concurrency 1"
 
 
 class TempestDefcore(TempestCommon):
 
-    def __init__(self):
-        TempestCommon.__init__(self)
-        self.case_name = "tempest_defcore"
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = 'tempest_defcore'
+        TempestCommon.__init__(self, **kwargs)
         self.MODE = "defcore"
         self.OPTION = "--concurrency 1"
index 584ded3..8e71bf8 100644 (file)
 #
 # 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.
+    """
+
+    def __init__(self, **kwargs):
+        super(VPingBase, self).__init__(**kwargs)
+
+        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')
 
-class VPingBase(testcase.TestCase):
-    def __init__(self):
-        super(VPingBase, self).__init__()
-        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.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.criteria = 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
index fc2f01c..0ad7740 100755 (executable)
 #
 # 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):
-
-    def __init__(self):
-        super(VPingSSH, self).__init__()
-        self.case_name = 'vping_ssh'
-        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)
+    """
+    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.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'
@@ -133,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
@@ -149,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
 
@@ -161,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__':
index fa91c12..8ea9be8 100755 (executable)
 #
 # 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)
+
+    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)
 
-    def __init__(self):
-        super(VPingUserdata, self).__init__()
-        self.case_name = 'vping_userdata'
-        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):
+            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__':
index ccc1101..2f3dd74 100755 (executable)
@@ -16,21 +16,24 @@ 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 import StringIO
+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,11 +73,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()
-
-    def __init__(self):
-        testcase.TestCase.__init__(self)
-        self.case_name = "odl"
+    __logger = logging.getLogger(__name__)
 
     @classmethod
     def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"):
@@ -89,13 +88,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):
@@ -104,7 +103,12 @@ class ODLTests(testcase.TestCase):
         result = robot.api.ExecutionResult(xml_file)
         visitor = ODLResultVisitor()
         result.visit(visitor)
-        self.criteria = 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 = {}
@@ -116,6 +120,7 @@ class ODLTests(testcase.TestCase):
 
         It has been designed to be called in any context.
         It requires the following keyword arguments:
+
            * odlusername,
            * odlpassword,
            * osauthurl,
@@ -134,7 +139,7 @@ class ODLTests(testcase.TestCase):
            * delete temporary files.
 
         Args:
-            **kwargs: Arbitrary keyword arguments.
+            kwargs: Arbitrary keyword arguments.
 
         Returns:
             EX_OK if all suites ran well.
@@ -146,7 +151,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 + '"',
@@ -157,39 +162,30 @@ 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')
             output_dir = os.path.join(self.res_dir, 'output.xml')
-            with open(stdout_file, 'w+') as stdout:
-                robot.run(*suites, variable=variables,
-                          output=output_dir,
-                          log='NONE',
-                          report='NONE',
-                          stdout=stdout)
-                stdout.seek(0, 0)
-                self.logger.info("\n" + stdout.read())
-            self.logger.info("ODL results were successfully generated")
+            stream = StringIO()
+            robot.run(*suites, variable=variables, output=output_dir,
+                      log='NONE', report='NONE', stdout=stream)
+            self.__logger.info("\n" + stream.getvalue())
+            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)
             return self.EX_OK
         else:
             return self.EX_RUN_ERROR
@@ -201,7 +197,7 @@ class ODLTests(testcase.TestCase):
         required.
 
         Args:
-            **kwargs: Arbitrary keyword arguments.
+            kwargs: Arbitrary keyword arguments.
 
         Returns:
             EX_OK if all suites ran well.
@@ -214,7 +210,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'
@@ -240,12 +236,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)
@@ -304,6 +300,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:])
index d482ae3..5dfff03 100644 (file)
@@ -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,24 +17,25 @@ 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
 
 
-logger = ft_logger.Logger(__name__).getLogger()
-
-
 class OnosBase(testcase.TestCase):
-    onos_repo_path = CONST.dir_repo_onos
-    onos_sfc_image_name = CONST.onos_sfc_image_name
-    onos_sfc_image_path = os.path.join(CONST.dir_functest_data,
-                                       CONST.onos_sfc_image_file_name)
-    onos_sfc_path = os.path.join(CONST.dir_repo_functest,
-                                 CONST.dir_onos_sfc)
-
-    def __init__(self):
-        super(OnosBase, self).__init__()
+    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_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 = logging.getLogger(__name__)
+
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "onos_base"
+        super(OnosBase, self).__init__(**kwargs)
 
     def run(self):
         self.start_time = time.time()
@@ -41,7 +43,7 @@ class OnosBase(testcase.TestCase):
             self._run()
             res = testcase.TestCase.EX_OK
         except Exception as e:
-            logger.error('Error with run: %s', e)
+            self.logger.error('Error with run: %s', e)
             res = testcase.TestCase.EX_RUN_ERROR
 
         self.stop_time = time.time()
@@ -52,26 +54,27 @@ class OnosBase(testcase.TestCase):
 
 
 class Onos(OnosBase):
-    def __init__(self):
-        super(Onos, self).__init__()
-        self.case_name = 'onos'
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "onos"
+        super(Onos, self).__init__(**kwargs)
         self.log_path = os.path.join(self.onos_repo_path, 'TestON/logs')
 
     def set_onos_ip(self):
-        if (CONST.INSTALLER_TYPE and
-                CONST.INSTALLER_TYPE.lower() == 'joid'):
+        if (self.installer_type and
+                self.installer_type.lower() == 'joid'):
             sdn_controller_env = os.getenv('SDN_CONTROLLER')
             OC1 = re.search(r"\d+\.\d+\.\d+\.\d+", sdn_controller_env).group()
         else:
             neutron_url = openstack_utils.get_endpoint(service_type='network')
             OC1 = urlparse.urlparse(neutron_url).hostname
         os.environ['OC1'] = OC1
-        logger.debug("ONOS IP is %s" % OC1)
+        self.logger.debug("ONOS IP is %s", OC1)
 
     def run_onos_script(self, testname):
         cli_dir = os.path.join(self.onos_repo_path, 'TestON/bin/cli.py')
         cmd = '{0} run {1}'.format(cli_dir, testname)
-        logger.debug("Run script: %s" % testname)
+        self.logger.debug("Run script: %s", testname)
         ft_utils.execute_command_raise(
             cmd,
             error_msg=('Error when running ONOS script: %s'
@@ -86,8 +89,8 @@ class Onos(OnosBase):
                 elif os.path.isfile(log):
                     os.remove(log)
             except OSError as e:
-                logger.error('Error with deleting file %s: %s',
-                             log, e.strerror)
+                self.logger.error('Error with deleting file %s: %s',
+                                  log, e.strerror)
 
     def get_result(self):
         cmd = 'grep -rnh Fail {0}'.format(self.log_path)
@@ -97,9 +100,9 @@ class Onos(OnosBase):
                              stderr=subprocess.STDOUT)
 
         for line in p.stdout:
-            logger.debug(line)
+            self.logger.debug(line)
             if re.search("\s+[1-9]+\s+", line):
-                logger.debug("Testcase Fails\n" + line)
+                self.logger.debug("Testcase Fails\n" + line)
 
         cmd = "grep -rnh 'Execution Time' {0}".format(self.log_path)
         result_buffer = os.popen(cmd).read()
@@ -157,10 +160,10 @@ class Onos(OnosBase):
             if (result['FUNCvirNet']['result'] == "Success" and
                     result['FUNCvirNetL3']['result'] == "Success"):
                 status = "PASS"
-        except:
-            logger.error("Unable to set ONOS criteria")
+        except Exception:
+            self.logger.error("Unable to set ONOS result")
 
-        self.criteria = status
+        self.result = status
         self.details = result
 
     def _run(self):
@@ -172,13 +175,14 @@ class Onos(OnosBase):
 
 
 class OnosSfc(OnosBase):
-    def __init__(self):
-        super(OnosSfc, self).__init__()
-        self.case_name = 'onos_sfc'
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "onos_sfc"
+        super(OnosSfc, self).__init__(**kwargs)
 
-    def get_ip(type):
+    def get_ip(self, type):
         url = openstack_utils.get_endpoint(service_type=type)
-        logger.debug('get_ip for %s: %s' % (type, url))
+        self.logger.debug('get_ip for %s: %s', type, url)
         return urlparse.urlparse(url).hostname
 
     def update_sfc_onos_file(self, before, after):
@@ -192,6 +196,7 @@ class OnosSfc(OnosBase):
                        % (before, after)))
 
     def create_image(self):
+        self.logger.warn('inside create_image')
         glance_client = openstack_utils.get_glance_client()
         image_id = openstack_utils.create_glance_image(
             glance_client,
@@ -200,19 +205,20 @@ class OnosSfc(OnosBase):
         if image_id is None:
             raise Exception('Failed to create image')
 
-        logger.debug("Image '%s' with ID=%s is created successfully."
-                     % (self.onos_sfc_image_name, image_id))
+        self.logger.debug("Image '%s' with ID=%s is created successfully.",
+                          self.onos_sfc_image_name, image_id)
 
     def set_sfc_conf(self):
         self.update_sfc_onos_file("keystone_ip", self.get_ip("keystone"))
         self.update_sfc_onos_file("neutron_ip", self.get_ip("neutron"))
         self.update_sfc_onos_file("nova_ip", self.get_ip("nova"))
         self.update_sfc_onos_file("glance_ip", self.get_ip("glance"))
-        self.update_sfc_onos_file("console", CONST.OS_PASSWORD)
+        self.update_sfc_onos_file("console",
+                                  CONST.__getattribute__('OS_PASSWORD'))
         neutron_client = openstack_utils.get_neutron_client()
         ext_net = openstack_utils.get_external_net(neutron_client)
         self.update_sfc_onos_file("admin_floating_net", ext_net)
-        logger.debug("SFC configuration is modified")
+        self.logger.debug("SFC configuration is modified")
 
     def sfc_test(self):
         cmd = 'python {0}'.format(os.path.join(self.onos_sfc_path, 'sfc.py'))
index 2241227..0155d24 100755 (executable)
@@ -1,4 +1,3 @@
-"""Script to Test the SFC scenarios in ONOS."""
 # !/usr/bin/python
 #
 # Copyright (c) CREATED5 All rights reserved
 # 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()
index c219869..1101f23 100644 (file)
@@ -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
index 81d5f7d..a88d2f0 100644 (file)
@@ -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)
index 3786945..dfaa5cc 100644 (file)
@@ -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)
index 046a821..cb75b5c 100644 (file)
@@ -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)
index bdedcf7..0030256 100755 (executable)
@@ -7,21 +7,23 @@
 # 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):
-        super(AaaVnf, self).__init__(case="aaa")
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "aaa"
+        super(AaaVnf, self).__init__(**kwargs)
 
     def deploy_orchestrator(self):
         self.logger.info("No VNFM needed to deploy a free radius here")
@@ -47,7 +49,7 @@ class AaaVnf(vnf_base.VnfOnBoardingBase):
     def main(self, **kwargs):
         self.logger.info("AAA VNF onboarding")
         self.execute()
-        if self.criteria is "PASS":
+        if self.result is "PASS":
             return self.EX_OK
         else:
             return self.EX_RUN_ERROR
@@ -56,7 +58,9 @@ class AaaVnf(vnf_base.VnfOnBoardingBase):
         kwargs = {}
         return self.main(**kwargs)
 
+
 if __name__ == '__main__':
+    logging.basicConfig()
     parser = argparse.ArgumentParser()
     args = vars(parser.parse_args())
     aaa_vnf = AaaVnf()
index f21ce3f..42d31e3 100644 (file)
@@ -7,26 +7,25 @@
 #
 # 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, project='functest', case='', repo='', cmd=''):
-        self.logger = ft_logger.Logger(__name__).getLogger()
-        super(ClearwaterOnBoardingBase, self).__init__(
-            project, case, repo, cmd)
+    def __init__(self, **kwargs):
+        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
-        self.result_dir = os.path.join(CONST.dir_results, case)
+        self.result_dir = os.path.join(CONST.dir_results, self.case_name)
         self.test_dir = CONST.dir_repo_vims_test
 
         if not os.path.exists(self.data_dir):
@@ -46,8 +45,7 @@ class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase):
         rq = requests.post(account_url, data=params)
         output_dict['login'] = params
         if rq.status_code != 201 and rq.status_code != 409:
-            raise Exception("Unable to create an account for number"
-                            " provision: %s" % rq.json()['reason'])
+            raise Exception("Unable to create an account for number provision")
         self.logger.info('Account is created on Ellis: %s', params)
 
         session_url = 'http://{0}/session'.format(ellis_ip)
index 404f208..ba4c579 100644 (file)
@@ -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,17 +19,17 @@ 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
 
 
 class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
 
-    def __init__(self, project='functest', case='cloudify_ims',
-                 repo='', cmd=''):
-        super(CloudifyIms, self).__init__(project, case, repo, cmd)
-        self.logger = ft_logger.Logger(__name__).getLogger()
+    def __init__(self, **kwargs):
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "cloudify_ims"
+        super(CloudifyIms, self).__init__(**kwargs)
+        self.logger = logging.getLogger(__name__)
 
         # Retrieve the configuration
         try:
@@ -276,7 +277,7 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
         self.logger.info("Cloudify IMS VNF onboarding test starting")
         self.execute()
         self.logger.info("Cloudify IMS VNF onboarding test executed")
-        if self.criteria is "PASS":
+        if self.result is "PASS":
             return self.EX_OK
         else:
             return self.EX_RUN_ERROR
index d022b3c..8c33d16 100644 (file)
@@ -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='opera_ims',
-                 repo=CONST.dir_repo_opera, cmd=''):
-        super(OperaIms, self).__init__(project, case, 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']
@@ -119,7 +119,7 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
         self.logger.info("Start to run Opera vIMS VNF onboarding test")
         self.execute()
         self.logger.info("Opera vIMS VNF onboarding test finished")
-        if self.criteria is "PASS":
+        if self.result is "PASS":
             return self.EX_OK
         else:
             return self.EX_RUN_ERROR
index 5c19be0..6f34197 100755 (executable)
@@ -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,18 +76,18 @@ def servertest(host, port):
             return True
 
 
-class ImsVnf(vnf_base.VnfOnBoardingBase):
+class ImsVnf(vnf.VnfOnBoarding):
 
-    def __init__(self, project='functest', case='orchestra_ims',
+    def __init__(self, project='functest', case_name='orchestra_ims',
                  repo='', cmd=''):
-        super(ImsVnf, self).__init__(project, case, repo, cmd)
+        super(ImsVnf, self).__init__(project, case_name, repo, cmd)
         self.ob_password = "openbaton"
         self.ob_username = "admin"
         self.ob_https = False
         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
@@ -103,7 +103,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
         try:
             self.config = CONST.__getattribute__(
                 'vnf_{}_config'.format(self.case_name))
-        except:
+        except BaseException:
             raise Exception("Orchestra VNF config file not found")
         config_file = self.case_dir + self.config
         self.imagename = get_config("openbaton.imagename", config_file)
@@ -115,6 +115,8 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
                                       config_file)
         self.images = get_config("tenant_images", config_file)
         self.ims_conf = get_config("vIMS", config_file)
+        self.userdata_file = get_config("openbaton.userdata.file",
+                                        config_file)
 
     def deploy_orchestrator(self, **kwargs):
         self.logger.info("Additional pre-configuration steps")
@@ -132,7 +134,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
                 image_id = os_utils.get_image_id(glance_client,
                                                  image_name)
                 self.logger.info("image_id: %s" % image_id)
-            except:
+            except BaseException:
                 self.logger.error("Unexpected error: %s" % sys.exc_info()[0])
 
             if image_id == '':
@@ -153,7 +155,8 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
                                                    "192.168.100.0/24")
 
         # orchestrator VM flavor
-        self.logger.info("Check if Flavor is available, if not create one")
+        self.logger.info(
+            "Check if orchestra Flavor is available, if not create one")
         flavor_exist, flavor_id = os_utils.get_or_create_flavor(
             "orchestra",
             "4096",
@@ -210,8 +213,13 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
         bootstrap = "sh ./bootstrap release -configFile=./config_file"
         userdata += bootstrap + "\n"
         userdata += "echo \"Setting 'nfvo.plugin.timeout' to '300000'\"\n"
-        userdata += ("echo \"nfvo.plugin.timeout=300000\" >> "
+        userdata += ("echo \"nfvo.plugin.timeout=600000\" >> "
                      "/etc/openbaton/openbaton-nfvo.properties\n")
+        userdata += (
+            "wget %s -O /etc/openbaton/openbaton-vnfm-generic-user-data.sh\n" %
+            self.userdata_file)
+        userdata += "sed -i '113i\ \ \ \ sleep 60' " \
+                    "/etc/openbaton/openbaton-vnfm-generic-user-data.sh\n"
         userdata += "echo \"Starting NFVO\"\n"
         userdata += "service openbaton-nfvo restart\n"
         userdata += "echo \"Starting Generic VNFM\"\n"
@@ -283,7 +291,10 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
         self.ob_username = "admin"
         self.ob_https = False
         self.ob_port = "8080"
-
+        self.logger.info("Waiting for all components up and running...")
+        time.sleep(60)
+        self.details["orchestrator"] = {
+            'status': "PASS", 'result': "Deploy Open Baton NFVO: OK"}
         self.logger.info("Deploy Open Baton NFVO: OK")
 
     def deploy_vnf(self):
@@ -296,6 +307,16 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
                                     username=self.ob_username,
                                     password=self.ob_password)
 
+        self.logger.info(
+            "Check if openims Flavor is available, if not create one")
+        flavor_exist, flavor_id = os_utils.get_or_create_flavor(
+            "m1.small",
+            "2048",
+            '20',
+            '1',
+            public=True)
+        self.logger.debug("Flavor id: %s" % flavor_id)
+
         self.logger.info("Getting project 'default'...")
         project_agent = self.main_agent.get_agent("project", self.ob_projectid)
         for p in json.loads(project_agent.find()):
@@ -311,9 +332,16 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
         creds = os_utils.get_credentials()
         self.logger.info("PoP creds: %s" % creds)
 
-        project_id = os_utils.get_tenant_id(
-            os_utils.get_keystone_client(),
-            creds.get("project_name"))
+        if os_utils.is_keystone_v3():
+            self.logger.info(
+                "Using v3 API of OpenStack... -> Using OS_PROJECT_ID")
+            project_id = os_utils.get_tenant_id(
+                os_utils.get_keystone_client(),
+                creds.get("project_name"))
+        else:
+            self.logger.info(
+                "Using v2 API of OpenStack... -> Using OS_TENANT_NAME")
+            project_id = creds.get("tenant_name")
 
         self.logger.debug("project id: %s" % project_id)
 
@@ -381,16 +409,17 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
             self.nsr = json.loads(nsr_agent.find(self.nsr.get('id')))
 
         if self.nsr.get("status") == 'ACTIVE':
-            deploy_vnf = {'status': "PASS", 'result': self.nsr}
+            self.details["vnf"] = {'status': "PASS", 'result': self.nsr}
             self.logger.info("Deploy VNF: OK")
         else:
-            deploy_vnf = {'status': "FAIL", 'result': self.nsr}
+            self.details["vnf"] = {'status': "FAIL", 'result': self.nsr}
+            self.logger.error(self.nsr)
             self.step_failure("Deploy VNF: ERROR")
         self.ob_nsr_id = self.nsr.get("id")
         self.logger.info(
             "Sleep for 60s to ensure that all services are up and running...")
         time.sleep(60)
-        return deploy_vnf
+        return self.details.get("vnf")
 
     def test_vnf(self):
         # Adaptations probably needed
@@ -427,9 +456,18 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
                                     "VNFC instance %s is not reachable "
                                     "at %s:%s" % (vnfci.get('hostname'),
                                                   floatingIp.get('ip'), port))
+                                self.details["test_vnf"] = {
+                                    'status': "FAIL", 'result': (
+                                        "Port %s of server %s -> %s is "
+                                        "not reachable" %
+                                        (port, vnfci.get('hostname'),
+                                         floatingIp.get('ip')))}
                                 self.step_failure("Test VNF: ERROR")
+        self.details["test_vnf"] = {
+            'status': "PASS",
+            'result': "All tests have been executed successfully"}
         self.logger.info("Test VNF: OK")
-        return
+        return self.details.get('test_vnf')
 
     def clean(self):
         self.main_agent.get_agent(
@@ -446,7 +484,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
         self.logger.info("Orchestra IMS VNF onboarding test starting")
         self.execute()
         self.logger.info("Orchestra IMS VNF onboarding test executed")
-        if self.criteria is "PASS":
+        if self.result is "PASS":
             return self.EX_OK
         else:
             return self.EX_RUN_ERROR
@@ -457,6 +495,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
 
 
 if __name__ == '__main__':
+    logging.basicConfig()
     test = ImsVnf()
     test.deploy_orchestrator()
     test.deploy_vnf()
index 5923a77..5b25d3c 100644 (file)
@@ -4,6 +4,8 @@ tenant_images:
 openbaton:
     bootstrap_link: http://get.openbaton.org/bootstraps/bootstrap_3.2.0_opnfv/bootstrap
     bootstrap_config_link: http://get.openbaton.org/bootstraps/bootstrap_3.2.0_opnfv/bootstrap-config-file
+    userdata:
+        file: https://raw.githubusercontent.com/openbaton/generic-vnfm/3.2.0/src/main/resources/user-data.sh
     marketplace_link: http://marketplace.openbaton.org:8082/api/v1/nsds/fokus/OpenImsCore/3.2.0/json
     imagename: ubuntu_14.04
 vIMS:
index 82a9dca..4ceeb25 100644 (file)
@@ -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/opnfv_tests/vnf/rnc/parser.py b/functest/opnfv_tests/vnf/rnc/parser.py
deleted file mode 100644 (file)
index 133145d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 ZTE Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import functest.core.feature as base
-
-
-class Parser(base.Feature):
-    def __init__(self):
-        super(Parser, self).__init__(project='parser',
-                                     case='parser-basics',
-                                     repo='dir_repo_parser')
-        self.cmd = 'cd %s/tests && ./functest_run.sh' % self.repo
index e188c3f..5654278 100644 (file)
@@ -14,10 +14,11 @@ RESULT_DETAILS_FILE = "test_result.json"
 
 
 class VrouterVnf(base.Feature):
-    def __init__(self):
-        super(VrouterVnf, self).__init__(project='functest',
-                                         case='vyos_vrouter',
-                                         repo='dir_repo_vrouter')
+    def __init__(self, **kwargs):
+        kwargs["repo"] = 'dir_repo_vrouter'
+        if "case_name" not in kwargs:
+            kwargs["case_name"] = "vyos_vrouter"
+        super(VrouterVnf, self).__init__(**kwargs)
         self.cmd = 'cd %s && ./run.sh' % self.repo
 
     def set_result_details(self):
@@ -28,6 +29,6 @@ class VrouterVnf(base.Feature):
             f.close()
 
     def log_results(self):
-        if self.criteria == 'PASS':
+        if self.result == 'PASS':
             self.set_result_details()
         super(VrouterVnf, self).log_results()
diff --git a/functest/tests/unit/ci/test_generate_report.py b/functest/tests/unit/ci/test_generate_report.py
deleted file mode 100644 (file)
index 2225586..0000000
+++ /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)
index 714dd13..fbb5965 100644 (file)
@@ -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)
 
index 7d02b1a..d005239 100644 (file)
@@ -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)
index 48c94a5..feaf33a 100644 (file)
@@ -22,7 +22,8 @@ class TierBuilderTesting(unittest.TestCase):
                            'scenario': 'test_scenario'}
 
         self.testcase = {'dependencies': self.dependency,
-                         'name': 'test_name',
+                         'enabled': 'true',
+                         'case_name': 'test_name',
                          'criteria': 'test_criteria',
                          'blocking': 'test_blocking',
                          'clean_flag': 'test_clean_flag',
@@ -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)
index 21df409..2800627 100644 (file)
@@ -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')
index 4b6ea57..c3d89ea 100644 (file)
@@ -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')
index f0e58c6..5404276 100644 (file)
@@ -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)
 
index 39c8139..2d09514 100644 (file)
@@ -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)
 
index 802359f..fbc7525 100644 (file)
@@ -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
new file mode 100644 (file)
index 0000000..8de42ec
--- /dev/null
@@ -0,0 +1,98 @@
+#!/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
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from functest.core import feature
+from functest.core import testcase
+
+# logging must be disabled else it calls time.time()
+# what will break these unit tests.
+logging.disable(logging.CRITICAL)
+
+
+class FeatureTestingBase(unittest.TestCase):
+
+    _case_name = "foo"
+    _project_name = "bar"
+    _repo = "dir_repo_copper"
+    _cmd = "cd /home/opnfv/repos/foo/tests && bash run.sh && cd -"
+    _output_file = '/home/opnfv/functest/results/foo.log'
+    feature = None
+
+    @mock.patch('time.time', side_effect=[1, 2])
+    def _test_run(self, status, mock_method=None):
+        self.assertEqual(self.feature.run(cmd=self._cmd), status)
+        if status == testcase.TestCase.EX_OK:
+            self.assertEqual(self.feature.result, 100)
+        else:
+            self.assertEqual(self.feature.result, 0)
+        mock_method.assert_has_calls([mock.call(), mock.call()])
+        self.assertEqual(self.feature.start_time, 1)
+        self.assertEqual(self.feature.stop_time, 2)
+
+
+class FeatureTesting(FeatureTestingBase):
+
+    def setUp(self):
+        self.feature = feature.Feature(
+            project_name=self._project_name, case_name=self._case_name)
+
+    def test_run_exc(self):
+        # pylint: disable=bad-continuation
+        with mock.patch.object(
+                self.feature, 'execute',
+                side_effect=Exception) as mock_method:
+            self._test_run(testcase.TestCase.EX_RUN_ERROR)
+            mock_method.assert_called_once_with(cmd=self._cmd)
+
+    def test_run(self):
+        self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+
+class BashFeatureTesting(FeatureTestingBase):
+
+    def setUp(self):
+        self.feature = feature.BashFeature(
+            project_name=self._project_name, case_name=self._case_name)
+
+    @mock.patch("functest.utils.functest_utils.execute_command")
+    def test_run_no_cmd(self, mock_method=None):
+        self.assertEqual(self.feature.run(), testcase.TestCase.EX_RUN_ERROR)
+        mock_method.assert_not_called()
+
+    @mock.patch("functest.utils.functest_utils.execute_command",
+                return_value=1)
+    def test_run_ko(self, mock_method=None):
+        self._test_run(testcase.TestCase.EX_RUN_ERROR)
+        mock_method.assert_called_once_with(
+            self._cmd, output_file=self._output_file)
+
+    @mock.patch("functest.utils.functest_utils.execute_command",
+                side_effect=Exception)
+    def test_run_exc(self, mock_method=None):
+        self._test_run(testcase.TestCase.EX_RUN_ERROR)
+        mock_method.assert_called_once_with(
+            self._cmd, output_file=self._output_file)
+
+    @mock.patch("functest.utils.functest_utils.execute_command",
+                return_value=0)
+    def test_run(self, mock_method):
+        self._test_run(testcase.TestCase.EX_OK)
+        mock_method.assert_called_once_with(
+            self._cmd, output_file=self._output_file)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=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 (file)
index 0000000..15e5bd7
--- /dev/null
@@ -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)
index 3210419..2adf4a6 100644 (file)
@@ -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,19 +20,21 @@ __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)
 
+    _case_name = "base"
+    _project_name = "functest"
+    _published_result = "PASS"
+
     def setUp(self):
-        self.test = testcase.TestCase()
-        self.test.project = "functest"
-        self.test.case_name = "base"
+        self.test = testcase.TestCase(case_name=self._case_name,
+                                      project_name=self._project_name)
         self.test.start_time = "1"
         self.test.stop_time = "2"
-        self.test.criteria = "PASS"
+        self.test.result = 100
         self.test.details = {"Hello": "World"}
 
     def test_run_unimplemented(self):
@@ -46,12 +48,12 @@ class TestCaseTesting(unittest.TestCase):
                          testcase.TestCase.EX_PUSH_TO_DB_ERROR)
         mock_function.assert_not_called()
 
-    def test_missing_case_name(self):
-        self.test.case_name = None
+    def test_missing_project_name(self):
+        self.test.project_name = None
         self._test_missing_attribute()
 
-    def test_missing_criteria(self):
-        self.test.criteria = None
+    def test_missing_case_name(self):
+        self.test.case_name = None
         self._test_missing_attribute()
 
     def test_missing_start_time(self):
@@ -69,8 +71,8 @@ class TestCaseTesting(unittest.TestCase):
         self.assertEqual(self.test.push_to_db(),
                          testcase.TestCase.EX_OK)
         mock_function.assert_called_once_with(
-            self.test.project, self.test.case_name, self.test.start_time,
-            self.test.stop_time, self.test.criteria, self.test.details)
+            self._project_name, self._case_name, self.test.start_time,
+            self.test.stop_time, self._published_result, self.test.details)
 
     @mock.patch('functest.utils.functest_utils.push_results_to_db',
                 return_value=False)
@@ -78,8 +80,8 @@ class TestCaseTesting(unittest.TestCase):
         self.assertEqual(self.test.push_to_db(),
                          testcase.TestCase.EX_PUSH_TO_DB_ERROR)
         mock_function.assert_called_once_with(
-            self.test.project, self.test.case_name, self.test.start_time,
-            self.test.stop_time, self.test.criteria, self.test.details)
+            self._project_name, self._case_name, self.test.start_time,
+            self.test.stop_time, self._published_result, self.test.details)
 
     @mock.patch('functest.utils.functest_utils.push_results_to_db',
                 return_value=True)
@@ -87,24 +89,140 @@ class TestCaseTesting(unittest.TestCase):
         self.assertEqual(self.test.push_to_db(),
                          testcase.TestCase.EX_OK)
         mock_function.assert_called_once_with(
-            self.test.project, self.test.case_name, self.test.start_time,
-            self.test.stop_time, self.test.criteria, self.test.details)
+            self._project_name, self._case_name, self.test.start_time,
+            self.test.stop_time, self._published_result, self.test.details)
+
+    @mock.patch('functest.utils.functest_utils.push_results_to_db',
+                return_value=True)
+    def test_push_to_db_res_ko(self, mock_function=None):
+        self.test.result = 0
+        self.assertEqual(self.test.push_to_db(),
+                         testcase.TestCase.EX_OK)
+        mock_function.assert_called_once_with(
+            self._project_name, self._case_name, self.test.start_time,
+            self.test.stop_time, 'FAIL', self.test.details)
+
+    @mock.patch('functest.utils.functest_utils.push_results_to_db',
+                return_value=True)
+    def test_push_to_db_both_ko(self, mock_function=None):
+        self.test.result = 0
+        self.test.criteria = 0
+        self.assertEqual(self.test.push_to_db(),
+                         testcase.TestCase.EX_OK)
+        mock_function.assert_called_once_with(
+            self._project_name, self._case_name, self.test.start_time,
+            self.test.stop_time, 'FAIL', self.test.details)
 
     def test_check_criteria_missing(self):
         self.test.criteria = None
-        self.assertEqual(self.test.check_criteria(),
+        self.assertEqual(self.test.is_successful(),
                          testcase.TestCase.EX_TESTCASE_FAILED)
 
-    def test_check_criteria_failed(self):
-        self.test.criteria = 'FAILED'
-        self.assertEqual(self.test.check_criteria(),
+    def test_check_result_missing(self):
+        self.test.result = None
+        self.assertEqual(self.test.is_successful(),
                          testcase.TestCase.EX_TESTCASE_FAILED)
 
-    def test_check_criteria_pass(self):
-        self.test.criteria = 'PASS'
-        self.assertEqual(self.test.check_criteria(),
+    def test_check_result_failed(self):
+        # Backward compatibility
+        # It must be removed as soon as TestCase subclasses
+        # stop setting result = 'PASS' or 'FAIL'.
+        self.test.result = 'FAIL'
+        self.assertEqual(self.test.is_successful(),
+                         testcase.TestCase.EX_TESTCASE_FAILED)
+
+    def test_check_result_pass(self):
+        # Backward compatibility
+        # It must be removed as soon as TestCase subclasses
+        # stop setting result = 'PASS' or 'FAIL'.
+        self.test.result = 'PASS'
+        self.assertEqual(self.test.is_successful(),
                          testcase.TestCase.EX_OK)
 
+    def test_check_result_lt(self):
+        self.test.result = 50
+        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.is_successful(),
+                         testcase.TestCase.EX_OK)
+
+    def test_check_result_gt(self):
+        self.test.criteria = 50
+        self.test.result = 100
+        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.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 (file)
index 0000000..793e957
--- /dev/null
@@ -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 (file)
index 1680f03..0000000
+++ /dev/null
@@ -1,53 +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='aaa')
-        self.test.project = "functest"
-        self.test.case_name = "aaa"
-        self.test.start_time = "1"
-        self.test.stop_time = "5"
-        self.test.criteria = ""
-        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/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py
new file mode 100644 (file)
index 0000000..ffe044b
--- /dev/null
@@ -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/features/test_barometer.py b/functest/tests/unit/features/test_barometer.py
new file mode 100644 (file)
index 0000000..8ca463b
--- /dev/null
@@ -0,0 +1,50 @@
+#!/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
+
+# pylint: disable=missing-docstring
+
+import logging
+import sys
+import unittest
+
+import mock
+
+from functest.core import testcase
+sys.modules['baro_tests'] = mock.Mock()  # noqa
+# pylint: disable=wrong-import-position
+from functest.opnfv_tests.features import barometer
+
+
+class BarometerTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    _case_name = "barometercollectd"
+    _project_name = "barometer"
+
+    def setUp(self):
+        self.barometer = barometer.BarometerCollectd(
+            case_name=self._case_name, project_name=self._project_name)
+
+    def test_init(self):
+        self.assertEqual(self.barometer.project_name, self._project_name)
+        self.assertEqual(self.barometer.case_name, self._case_name)
+
+    def test_run_ko(self):
+        sys.modules['baro_tests'].collectd.main = mock.Mock(return_value=1)
+        self.assertEqual(self.barometer.run(),
+                         testcase.TestCase.EX_RUN_ERROR)
+
+    def test_run(self):
+        sys.modules['baro_tests'].collectd.main = mock.Mock(return_value=0)
+        self.assertEqual(self.barometer.run(), testcase.TestCase.EX_OK)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
index e08deb2..6e2e9b1 100644 (file)
 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[
@@ -90,7 +88,7 @@ class ODLTesting(unittest.TestCase):
         os.environ["OS_USERNAME"] = self._os_username
         os.environ["OS_PASSWORD"] = self._os_password
         os.environ["OS_TENANT_NAME"] = self._os_tenantname
-        self.test = odl.ODLTests()
+        self.test = odl.ODLTests(case_name='odl', project_name='functest')
         self.defaultargs = {'odlusername': self._odl_username,
                             'odlpassword': self._odl_password,
                             'neutronip': self._keystone_ip,
@@ -109,21 +107,23 @@ 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):
             self.test.parse_results()
-            mock_method.assert_called_once_with()
+        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.criteria, 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,
@@ -131,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):
 
@@ -151,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]
@@ -169,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 = []"]
@@ -292,8 +312,6 @@ class ODLMainTesting(ODLTesting):
     def test_run_ko(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
                 self.assertRaises(RobotError):
             self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
 
@@ -302,63 +320,31 @@ class ODLMainTesting(ODLTesting):
     def test_parse_results_ko(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
                 mock.patch.object(self.test, 'parse_results',
                                   side_effect=RobotError):
             self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
 
-    @mock.patch('os.remove', side_effect=Exception)
-    @mock.patch('robot.run')
-    @mock.patch('os.makedirs')
-    def test_remove_exc(self, *args):
-        with mock.patch.object(self.test, 'set_robotframework_vars',
-                               return_value=True), \
-                mock.patch.object(self.test, 'parse_results'), \
-                self.assertRaises(Exception):
-            self._test_main(testcase.TestCase.EX_OK, *args)
-
-    @mock.patch('os.remove')
     @mock.patch('robot.run')
     @mock.patch('os.makedirs')
     def test_ok(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
                 mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase.TestCase.EX_OK, *args)
 
-    @mock.patch('os.remove')
     @mock.patch('robot.run')
     @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
     def test_makedirs_oserror17(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
                 mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase.TestCase.EX_OK, *args)
 
-    @mock.patch('os.remove')
     @mock.patch('robot.run', return_value=1)
     @mock.patch('os.makedirs')
     def test_testcases_in_failure(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
-                mock.patch.object(self.test, 'parse_results'):
-            self._test_main(testcase.TestCase.EX_OK, *args)
-
-    @mock.patch('os.remove', side_effect=OSError)
-    @mock.patch('robot.run')
-    @mock.patch('os.makedirs')
-    def test_remove_oserror(self, *args):
-        with mock.patch.object(self.test, 'set_robotframework_vars',
-                               return_value=True), \
-                mock.patch.object(odl, 'open', mock.mock_open(),
-                                  create=True), \
                 mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase.TestCase.EX_OK, *args)
 
@@ -368,19 +354,10 @@ class ODLRunTesting(ODLTesting):
     """The class testing ODLTests.run()."""
     # pylint: disable=missing-docstring
 
-    @classmethod
-    def _fake_url_for(cls, service_type='identity'):
-        if service_type == 'identity':
-            return "http://{}:5000/v2.0".format(
-                ODLTesting._keystone_ip)
-        elif service_type == 'network':
-            return "http://{}:9696".format(ODLTesting._neutron_ip)
-        else:
-            return None
-
     def _test_no_env_var(self, var):
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             del os.environ[var]
             self.assertEqual(self.test.run(),
                              testcase.TestCase.EX_RUN_ERROR)
@@ -393,7 +370,8 @@ class ODLRunTesting(ODLTesting):
                            if 'odlrestconfport' in kwargs else '8181')
 
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             if exception:
                 self.test.main = mock.Mock(side_effect=exception)
             else:
@@ -410,18 +388,15 @@ class ODLRunTesting(ODLTesting):
                 osusername=self._os_username)
 
     def _test_multiple_suites(self, suites,
-                              status=testcase.TestCase.EX_OK,
-                              exception=None, **kwargs):
+                              status=testcase.TestCase.EX_OK, **kwargs):
         odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
         odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
         odlrestconfport = (kwargs['odlrestconfport']
                            if 'odlrestconfport' in kwargs else '8181')
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
-            if exception:
-                self.test.main = mock.Mock(side_effect=exception)
-            else:
-                self.test.main = mock.Mock(return_value=status)
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
+            self.test.main = mock.Mock(return_value=status)
             self.assertEqual(self.test.run(suites=suites), status)
             self.test.main.assert_called_once_with(
                 suites,
@@ -467,7 +442,8 @@ class ODLRunTesting(ODLTesting):
 
     def test_no_sdn_controller_ip(self):
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             self.assertEqual(self.test.run(),
                              testcase.TestCase.EX_RUN_ERROR)
 
@@ -492,7 +468,8 @@ class ODLRunTesting(ODLTesting):
 
     def test_apex_no_controller_ip(self):
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             os.environ["INSTALLER_TYPE"] = "apex"
             self.assertEqual(self.test.run(),
                              testcase.TestCase.EX_RUN_ERROR)
@@ -506,7 +483,8 @@ class ODLRunTesting(ODLTesting):
 
     def test_netvirt_no_controller_ip(self):
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             os.environ["INSTALLER_TYPE"] = "netvirt"
             self.assertEqual(self.test.run(),
                              testcase.TestCase.EX_RUN_ERROR)
@@ -520,7 +498,8 @@ class ODLRunTesting(ODLTesting):
 
     def test_joid_no_controller_ip(self):
         with mock.patch('functest.utils.openstack_utils.get_endpoint',
-                        side_effect=self._fake_url_for):
+                        return_value="http://{}:9696".format(
+                            ODLTesting._neutron_ip)):
             os.environ["INSTALLER_TYPE"] = "joid"
             self.assertEqual(self.test.run(),
                              testcase.TestCase.EX_RUN_ERROR)
@@ -558,12 +537,12 @@ 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):
             self.parser.parse_args(["--foo=bar"])
-            mock_method.assert_called_once_with()
+        self.assertTrue(mock_method.getvalue().startswith("usage:"))
 
     def _test_arg(self, arg, value):
         self.defaultargs[arg] = value
@@ -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()
@@ -105,7 +105,7 @@ class OSTempestTesting(unittest.TestCase):
         self._test_generate_test_list_mode_default('full')
 
     def test_parse_verifier_result_missing_verification_uuid(self):
-        self.tempestcommon.VERIFICATION_ID = ''
+        self.tempestcommon.VERIFICATION_ID = None
         with self.assertRaises(Exception):
             self.tempestcommon.parse_verifier_result()
 
@@ -151,118 +151,82 @@ 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)
-
-    def test_run_missing_create_tempest_dir(self):
-        ret = testcase.TestCase.EX_RUN_ERROR
-        with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                        'os.path.exists', return_value=False), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'os.makedirs') as mock_os_makedirs, \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.create_tempest_resources',
-                       return_value="image_and_flavor"):
-            self.assertEqual(self.tempestcommon.run(),
-                             ret)
-            self.assertTrue(mock_os_makedirs.called)
-
-    def test_run_missing_configure_tempest(self):
-        ret = testcase.TestCase.EX_RUN_ERROR
-        ret_ok = testcase.TestCase.EX_OK
-        with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                        'os.path.exists', return_value=False), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'os.makedirs') as mock_os_makedirs, \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.create_tempest_resources',
-                       return_value=ret_ok), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.configure_tempest',
-                       return_value=ret):
-            self.assertEqual(self.tempestcommon.run(),
-                             ret)
-            self.assertTrue(mock_os_makedirs.called)
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'os.path.exists', return_value=False)
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs',
+                side_effect=Exception)
+    def test_run_makedirs_ko(self, *args):
+        self.assertEqual(self.tempestcommon.run(),
+                         testcase.TestCase.EX_RUN_ERROR)
+
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'os.path.exists', return_value=False)
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'conf_utils.create_tempest_resources', side_effect=Exception)
+    def test_run_create_tempest_resources_ko(self, *args):
+        self.assertEqual(self.tempestcommon.run(),
+                         testcase.TestCase.EX_RUN_ERROR)
+
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'os.path.exists', return_value=False)
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'conf_utils.create_tempest_resources', return_value={})
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'conf_utils.configure_tempest', side_effect=Exception)
+    def test_run_configure_tempest_ko(self, *args):
+        self.assertEqual(self.tempestcommon.run(),
+                         testcase.TestCase.EX_RUN_ERROR)
+
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'os.path.exists', return_value=False)
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'conf_utils.create_tempest_resources', return_value={})
+    @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+                'conf_utils.configure_tempest')
+    def _test_run(self, status, *args):
+        self.assertEqual(self.tempestcommon.run(), status)
 
     def test_run_missing_generate_test_list(self):
-        ret = testcase.TestCase.EX_RUN_ERROR
-        ret_ok = testcase.TestCase.EX_OK
-        with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                        'os.path.exists', return_value=False), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'os.makedirs') as mock_os_makedirs, \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.create_tempest_resources',
-                       return_value=ret_ok), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.configure_tempest',
-                       return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'generate_test_list',
-                              return_value=ret):
-            self.assertEqual(self.tempestcommon.run(),
-                             ret)
-            self.assertTrue(mock_os_makedirs.called)
-
-    def test_run_missing_apply_tempest_blacklist(self):
-        ret = testcase.TestCase.EX_RUN_ERROR
-        ret_ok = testcase.TestCase.EX_OK
-        with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                        'os.path.exists', return_value=False), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'os.makedirs') as mock_os_makedirs, \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.create_tempest_resources',
-                       return_value=ret_ok), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.configure_tempest',
-                       return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'generate_test_list',
-                              return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'apply_tempest_blacklist',
-                              return_value=ret):
-            self.assertEqual(self.tempestcommon.run(),
-                             ret)
-            self.assertTrue(mock_os_makedirs.called)
-
-    def test_run_missing_parse_verifier_result(self):
-        ret = testcase.TestCase.EX_RUN_ERROR
-        ret_ok = testcase.TestCase.EX_OK
-        with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                        'os.path.exists', return_value=False), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'os.makedirs') as mock_os_makedirs, \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.create_tempest_resources',
-                       return_value=ret_ok), \
-            mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
-                       'conf_utils.configure_tempest',
-                       return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'generate_test_list',
-                              return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'apply_tempest_blacklist',
-                              return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'run_verifier_tests',
-                              return_value=ret_ok), \
-            mock.patch.object(self.tempestcommon, 'parse_verifier_result',
-                              return_value=ret):
-            self.assertEqual(self.tempestcommon.run(),
-                             ret)
-            self.assertTrue(mock_os_makedirs.called)
+        with mock.patch.object(self.tempestcommon, 'generate_test_list',
+                               side_effect=Exception):
+            self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+    def test_run_apply_tempest_blacklist_ko(self):
+        with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+                    mock.patch.object(self.tempestcommon,
+                                      'apply_tempest_blacklist',
+                                      side_effect=Exception()):
+            self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+    def test_run_verifier_tests_ko(self, *args):
+        with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+                mock.patch.object(self.tempestcommon,
+                                  'apply_tempest_blacklist'), \
+                mock.patch.object(self.tempestcommon, 'run_verifier_tests',
+                                  side_effect=Exception()), \
+                mock.patch.object(self.tempestcommon, 'parse_verifier_result',
+                                  side_effect=Exception):
+            self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+    def test_run_parse_verifier_result_ko(self, *args):
+        with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+                mock.patch.object(self.tempestcommon,
+                                  'apply_tempest_blacklist'), \
+                mock.patch.object(self.tempestcommon, 'run_verifier_tests'), \
+                mock.patch.object(self.tempestcommon, 'parse_verifier_result',
+                                  side_effect=Exception):
+            self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+    def test_run(self, *args):
+        with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+                mock.patch.object(self.tempestcommon,
+                                  'apply_tempest_blacklist'), \
+                mock.patch.object(self.tempestcommon, 'run_verifier_tests'), \
+                mock.patch.object(self.tempestcommon, 'parse_verifier_result'):
+            self._test_run(testcase.TestCase.EX_OK)
 
 
 if __name__ == "__main__":
diff --git a/functest/tests/unit/utils/test_decorators.py b/functest/tests/unit/utils/test_decorators.py
new file mode 100644 (file)
index 0000000..f8bd9a5
--- /dev/null
@@ -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 (file)
index 42e41a1..0000000
+++ /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)
index eb241e5..57e0c46 100644 (file)
@@ -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
@@ -41,8 +41,8 @@ class FunctestUtilsTesting(unittest.TestCase):
         self.status = 'test_status'
         self.details = 'test_details'
         self.db_url = 'test_db_url'
-        self.success_rate = 2.0
-        self.criteria = 'test_criteria==2.0'
+        self.criteria = 50
+        self.result = 75
         self.start_date = 1482624000
         self.stop_date = 1482624000
         self.start_time = time.time()
@@ -54,38 +54,39 @@ class FunctestUtilsTesting(unittest.TestCase):
         self.cmd = 'test_cmd'
         self.output_file = 'test_output_file'
         self.testname = 'testname'
-        self.testcase_dict = {'name': 'testname', 'criteria': self.criteria}
+        self.testcase_dict = {'case_name': 'testname',
+                              'criteria': self.criteria}
         self.parameter = 'general.openstack.image_name'
         self.config_yaml = 'test_config_yaml-'
         self.db_url_env = 'http://foo/testdb'
         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]
@@ -278,7 +279,7 @@ class FunctestUtilsTesting(unittest.TestCase):
                 as mock_logger_error:
             functest_utils.push_results_to_db(self.project, self.case_name,
                                               self.start_date, self.stop_date,
-                                              self.criteria, self.details)
+                                              self.result, self.details)
             mock_logger_error.assert_called_once_with("Please set env var: " +
                                                       str("\'" + env_var +
                                                           "\'"))
@@ -310,7 +311,7 @@ class FunctestUtilsTesting(unittest.TestCase):
                              push_results_to_db(self.project, self.case_name,
                                                 self.start_date,
                                                 self.stop_date,
-                                                self.criteria, self.details))
+                                                self.result, self.details))
             mock_logger_error.assert_called_once_with(test_utils.
                                                       RegexMatch("Pushing "
                                                                  "Result to"
@@ -333,7 +334,7 @@ class FunctestUtilsTesting(unittest.TestCase):
                              push_results_to_db(self.project, self.case_name,
                                                 self.start_date,
                                                 self.stop_date,
-                                                self.criteria, self.details))
+                                                self.result, self.details))
             self.assertTrue(mock_logger_error.called)
 
     def test_push_results_to_db_default(self):
@@ -348,7 +349,7 @@ class FunctestUtilsTesting(unittest.TestCase):
                             push_results_to_db(self.project, self.case_name,
                                                self.start_date,
                                                self.stop_date,
-                                               self.criteria, self.details))
+                                               self.result, self.details))
     readline = 0
     test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
 
@@ -370,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:])
@@ -398,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
 
@@ -427,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
 
@@ -502,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_'
@@ -530,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:
@@ -542,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
@@ -560,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.success_rate)
-            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,
-                                                     3.0)
-            self.assertEqual(resp, 'FAIL')
-
     # TODO: merge_dicts
 
     def test_get_testcases_file_dir(self):
@@ -585,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
index 7f3995d..a7df264 100644 (file)
@@ -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/tests/unit/vnf/ims/__init__.py b/functest/tests/unit/vnf/ims/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
@@ -10,7 +10,7 @@ import unittest
 
 import mock
 
-from functest.opnfv_tests.vnf.ims import ims_base
+from functest.opnfv_tests.vnf.ims import clearwater_ims_base as ims_base
 
 
 class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
@@ -38,8 +38,8 @@ class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
         self.mock_post_200.configure_mock(**attrs)
 
     def test_create_ellis_number_failure(self):
-        with mock.patch('functest.opnfv_tests.vnf.ims.ims_base.'
-                        'requests.post',
+        with mock.patch('functest.opnfv_tests.vnf.ims.'
+                        'clearwater_ims_base.requests.post',
                         return_value=self.mock_post_500), \
                 self.assertRaises(Exception) as context:
             self.ims_vnf.create_ellis_number()
diff --git a/functest/tests/unit/vnf/rnc/__init__.py b/functest/tests/unit/vnf/rnc/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
old mode 100755 (executable)
new mode 100644 (file)
index b5b8450..d91f63a
@@ -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
old mode 100755 (executable)
new mode 100644 (file)
index 2e8eb3f..75c97c7
@@ -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
index 276235d..73e0a35 100644 (file)
@@ -1,41 +1,48 @@
 #!/usr/bin/env python
 
+# pylint: disable=missing-docstring
+
 import errno
-import mock
+import functools
 import os
+
+import mock
 import requests.sessions
-import urlparse
+from six.moves import urllib
 
 
 def can_dump_request_to_file(method):
 
     def dump_preparedrequest(request, **kwargs):
-        parseresult = urlparse.urlparse(request.url)
+        # pylint: disable=unused-argument
+        parseresult = urllib.parse.urlparse(request.url)
         if parseresult.scheme == "file":
             try:
-                os.makedirs(parseresult.path)
-            except OSError as e:
-                if e.errno != errno.EEXIST:
+                dirname = os.path.dirname(parseresult.path)
+                os.makedirs(dirname)
+            except OSError as ex:
+                if ex.errno != errno.EEXIST:
                     raise
-            with open(os.path.join(parseresult.path, 'dump.txt'), 'a') as f:
+            with open(parseresult.path, 'a') as dumpfile:
                 headers = ""
                 for key in request.headers:
                     headers += key + " " + request.headers[key] + "\n"
                 message = "{} {}\n{}\n{}\n\n\n".format(
                     request.method, request.url, headers, request.body)
-                f.write(message)
+                dumpfile.write(message)
         return mock.Mock()
 
     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):
+                with mock.patch.object(session, 'send',
+                                       side_effect=dump_preparedrequest):
                     return session.request(method=method, url=url, **kwargs)
             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)
index 7e4df2e..c9629e1 100644 (file)
@@ -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 (file)
index 555e9c2..0000000
+++ /dev/null
@@ -1,76 +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):
-
-    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)
index 7cc5029..bf30f56 100644 (file)
@@ -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:
@@ -192,12 +192,12 @@ def logger_test_results(project, case_name, status, details):
 
 @decorators.can_dump_request_to_file
 def push_results_to_db(project, case_name,
-                       start_date, stop_date, criteria, details):
+                       start_date, stop_date, result, details):
     """
     POST results to the Result target DB
     """
     # Retrieve params from CI and conf
-    url = get_db_url() + "/results"
+    url = get_db_url()
 
     try:
         installer = os.environ['INSTALLER_TYPE']
@@ -213,7 +213,7 @@ def push_results_to_db(project, case_name,
 
     params = {"project_name": project, "case_name": case_name,
               "pod_name": pod_name, "installer": installer,
-              "version": version, "scenario": scenario, "criteria": criteria,
+              "version": version, "scenario": scenario, "criteria": result,
               "build_tag": build_tag, "start_date": test_start,
               "stop_date": test_stop, "details": details}
 
@@ -248,7 +248,7 @@ def push_results_to_db(project, case_name,
                      'pod': pod_name,
                      'v': version,
                      's': scenario,
-                     'c': criteria,
+                     'c': result,
                      't': build_tag,
                      'd': details,
                      'error': e
@@ -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()
@@ -337,7 +337,7 @@ def get_dict_by_test(testname):
 
     for dic_tier in testcases_yaml.get("tiers"):
         for dic_testcase in dic_tier['testcases']:
-            if dic_testcase['name'] == testname:
+            if dic_testcase['case_name'] == testname:
                 return dic_testcase
 
     logger.error('Project %s is not defined in testcases.yaml' % testname)
@@ -379,25 +379,6 @@ def get_functest_config(parameter):
     return get_parameter_from_yaml(parameter, yaml_)
 
 
-def check_success_rate(case_name, success_rate):
-    success_rate = float(success_rate)
-    criteria = get_criteria_by_test(case_name)
-
-    def get_criteria_value(op):
-        return float(criteria.split(op)[1].rstrip('%'))
-
-    status = 'FAIL'
-    ops = ['==', '>=']
-    for op in ops:
-        if op in criteria:
-            c_value = get_criteria_value(op)
-            if eval("%s %s %s" % (success_rate, op, c_value)):
-                status = 'PASS'
-            break
-
-    return status
-
-
 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 (file)
index f966468..0000000
+++ /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 (file)
index f966468..0000000
+++ /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 (file)
index f966468..0000000
+++ /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 (file)
index f966468..0000000
+++ /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 (file)
index f966468..0000000
+++ /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
-#
index ce61fca..29106d9 100755 (executable)
 
 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()
index e64030f..952fb7b 100755 (executable)
 # 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()
index 8327fdb..9fd9d5c 100644 (file)
 # 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={}):
index 4663f7b..8bd9505 100644 (file)
@@ -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,12 +1397,21 @@ 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
 
 
+def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
+    tenant_id = get_tenant_id(keystone_client, tenant_name)
+    if not tenant_id:
+        tenant_id = create_tenant(keystone_client, tenant_name,
+                                  tenant_description)
+
+    return tenant_id
+
+
 def create_user(keystone_client, user_name, user_password,
                 user_email, tenant_id):
     try:
@@ -1410,13 +1428,22 @@ 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))
         return None
 
 
+def get_or_create_user(keystone_client, user_name, user_password,
+                       tenant_id, user_email=None):
+    user_id = get_user_id(keystone_client, user_name)
+    if not user_id:
+        user_id = create_user(keystone_client, user_name, user_password,
+                              user_email, tenant_id)
+    return user_id
+
+
 def add_role_user(keystone_client, user_id, role_id, tenant_id):
     try:
         if is_keystone_v3():
@@ -1426,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
@@ -1439,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
@@ -1449,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
@@ -1462,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
index ee629ea..65b3697 100644 (file)
@@ -14,20 +14,26 @@ 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
 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
index 3de9b36..86096fa 100755 (executable)
@@ -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
 
@@ -31,20 +34,10 @@ pip install releng-unittests/modules/
 rm -fr releng-unittests
 
 export CONFIG_FUNCTEST_YAML=$(pwd)/functest/ci/config_functest.yaml
-# unit tests
-# TODO: remove cover-erase
-# To be deleted when all functest packages will be listed
 nosetests --with-xunit \
          --with-coverage \
-         --cover-erase \
          --cover-tests \
-         --cover-package=functest.ci \
-         --cover-package=functest.cli \
-         --cover-package=functest.core.testcase \
-         --cover-package=functest.opnfv_tests.sdn.odl.odl \
-         --cover-package=functest.opnfv_tests.vnf.ims \
-         --cover-package=functest.utils \
-         --cover-package=functest.opnfv_tests.openstack \
+         --cover-package=functest \
          --cover-xml \
          --cover-html \
          --log-config=$(pwd)/functest/tests/unit/test_logging.ini \
index 471e9c3..b0d4ff8 100644 (file)
@@ -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