diff options
38 files changed, 544 insertions, 598 deletions
diff --git a/docker/add_images.sh b/docker/add_images.sh index a43e0ba4..af2956c2 100755 --- a/docker/add_images.sh +++ b/docker/add_images.sh @@ -4,14 +4,14 @@ # and places them in the functest docker image CIRROS_REPO_URL=http://download.cirros-cloud.net -CIRROS_AARCH64_TAG=daily/20161201 +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 +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/ # 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/${CIRROS_AARCH64_TAG}/cirros-$(basename ${CIRROS_AARCH64_TAG})-aarch64-disk.img -P ${FUNCTEST_BASE_DIR}/data/ -wget ${CIRROS_REPO_URL}/daily/${CIRROS_AARCH64_TAG}/cirros-$(basename ${CIRROS_AARCH64_TAG})-aarch64-initramfs -P ${FUNCTEST_BASE_DIR}/data/ -wget ${CIRROS_REPO_URL}/daily/${CIRROS_AARCH64_TAG}/cirros-$(basename ${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_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/ diff --git a/docs/com/pres/Summit/Berlin-2016/summit-Berlin.html b/docs/com/pres/Summit/Berlin-2016/summit-Berlin.html index 4173a86a..8369443f 100755 --- a/docs/com/pres/Summit/Berlin-2016/summit-Berlin.html +++ b/docs/com/pres/Summit/Berlin-2016/summit-Berlin.html @@ -230,7 +230,7 @@ ## What's new? * Slicing of the tests (healthcheck / Smoke / SDN controllers / Features / Components / VNFs) * Better Test duration management - * Refactoring (repo, case management, test API) + * Refactoring (repo, case management, TestAPI) * Automatic reporting * Dashboard evolution to ELK * CLI diff --git a/docs/com/pres/Summit/Berlin-2016/testapi.html b/docs/com/pres/Summit/Berlin-2016/testapi.html index 7035d71d..16f97c44 100755 --- a/docs/com/pres/Summit/Berlin-2016/testapi.html +++ b/docs/com/pres/Summit/Berlin-2016/testapi.html @@ -6,7 +6,7 @@ <title>OPNFV presentation</title> - <meta name="description" content="Test API"> + <meta name="description" content="TestAPI"> <meta name="author" content="Serena Feng"> <meta name="apple-mobile-web-app-capable" content="yes" /> @@ -42,7 +42,7 @@ <section data-background="../../../img/title-bg-berlin.png" data-background-transition="none"> <br><br><br><br><br> - <h1>Test API</h1> + <h1>TestAPI</h1> <h3>Clean, Easy, Complete</h3> <br> <h4>OPNFV testing community</h4> @@ -52,7 +52,7 @@ <section data-markdown> # Agenda - * testAPI: what for? + * TestAPI: what for? * API overview * API evolution * Roadmap @@ -60,7 +60,7 @@ <section> <section data-markdown> - # test API: what for? + # TestAPI: what for? </section> <section data-markdown> ## Consistant view for @@ -78,12 +78,12 @@ </section> <section data-markdown> <script type='text/template'> - ## Achieve using testAPI - * Uniform API: testAPI + ## Achieve using TestAPI + * Uniform API: TestAPI * Uniform format: JSON * Universal Location: http://testresults.opnfv.org <aside class='notes'> - By using testAPI, we hope to provide a uniform way of collection and saving test results to a universal location + By using TestAPI, we hope to provide a uniform way of collection and saving test results to a universal location </aside> </script> </section> @@ -101,11 +101,11 @@ </section> <section data-markdown> ## Storage structure - ![testapi](https://wiki.opnfv.org/download/attachments/2926452/results_collection_structure.png?version=1&modificationDate=1459196347000&api=v2 "OPNFV API page") + ![TestAPI](https://wiki.opnfv.org/download/attachments/2926452/results_collection_structure.png?version=1&modificationDate=1459196347000&api=v2 "OPNFV API page") </section> <section data-markdown> ## API in Brahmaputra - ![testapi](../../../img/testapi0.png) + ![TestAPI](../../../img/testapi0.png) https://wiki.opnfv.org/display/functest/Collection+Of+Test+Results </section> @@ -137,7 +137,7 @@ <aside class='notes'> So you can discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection, - and also you can interact with the testAPI directly through swagger website. + and also you can interact with the TestAPI directly through swagger website. </aside> </ul> <p class="fragment fade-up"><b>All done in Colorado!</b></p> @@ -152,7 +152,7 @@ <section> <h2> URI changes...</h2> <div style="text-align:left""> - <p> testresults.opnfv.org/<span style="color:lightblue">testapi</span> => <br>testresults.opnfv.org/<span style="color:yellow">test/api/v1</span> </p> + <p> testresults.opnfv.org/<span style="color:lightblue">TestAPI</span> => <br>testresults.opnfv.org/<span style="color:yellow">test/api/v1</span> </p> <p> /test/api/v1/<b>pods</b></p> <p> /test/api/v1/<b>projects</b></p> @@ -195,7 +195,7 @@ </section> <section data-markdown> http://testresults.opnfv.org/test/swagger/spec.html - ![alt text](../../../img/testapi1.png "Test API swagger interface") + ![alt text](../../../img/testapi1.png "TestAPI swagger interface") </section> <section> <h2>unit tests</h2> @@ -223,8 +223,8 @@ OK </section> <section data-markdown> ## Roadmap - * Dockerize testAPI - * Automatic update of testAPI + * Dockerize TestAPI + * Automatic update of TestAPI * Command Line Interface * Automatic update for pods/projects/testcases </section> diff --git a/docs/release-notes/functest-release.rst b/docs/release/release-notes/functest-release.rst index 07389bb5..ce03047f 100644 --- a/docs/release-notes/functest-release.rst +++ b/docs/release/release-notes/functest-release.rst @@ -32,7 +32,7 @@ Version history +------------+----------+------------------+------------------------+ OPNFV Colorado Release -========================= +====================== Functest deals with functional testing of the OPNFV solution. It includes test cases developed within the project and test cases developed in @@ -99,7 +99,7 @@ Software - The Functest Docker image: https://hub.docker.com/r/opnfv/functest (tag: colorado.1.0) - - The testapi Docker image: https://hub.docker.com/r/opnfv/testapi (tag:colorado.1.0) + - The TestAPI Docker image: https://hub.docker.com/r/opnfv/testapi (tag:colorado.1.0) Documents @@ -120,7 +120,7 @@ Feature evolution - refactoring of ODL functional tests (with upstream modifications) - - refactoring of testapi (update, swagger documentation, dockerization) + - refactoring of TestAPI (update, swagger documentation, dockerization) - jenkins logs improvement diff --git a/docs/release-notes/index.rst b/docs/release/release-notes/index.rst index 6c6d1810..6c6d1810 100644 --- a/docs/release-notes/index.rst +++ b/docs/release/release-notes/index.rst diff --git a/docs/devguide/index.rst b/docs/testing/developer/devguide/index.rst index eee01367..11ca241b 100644 --- a/docs/devguide/index.rst +++ b/docs/testing/developer/devguide/index.rst @@ -14,7 +14,7 @@ Introduction Functest is a project dealing with functional testing. Functest produces its own internal test cases but can also be considered as a framework to support feature and VNF onboarding project testing. -Functest developed a test API and defined a test collection framework +Functest developed a TestAPI and defined a test collection framework that can be used by any OPNFV project. Therefore there are many ways to contribute to Functest. You can: @@ -260,9 +260,9 @@ The Test result management can be summarized as follows:: | | +----------------------+ -Test API description --------------------- -The Test API is used to declare pods, projects, test cases and test +TestAPI description +------------------- +The TestAPI is used to declare pods, projects, test cases and test results. Pods are the pods used to run the tests. The results pushed in the database are related to pods, projects and cases. If you try to push results of test done on non referenced pod, @@ -500,21 +500,21 @@ Scenarios: The code of the API is hosted in the releng repository `[6]`_. The static documentation of the API can be found at `[17]`_. -The test API has been dockerized and may be installed locally in your +The TestAPI has been dockerized and may be installed locally in your lab. See `[15]`_ for details. -The deployment of the test API has been automated. +The deployment of the TestAPI has been automated. A jenkins job manages: - * the unit tests of the test api + * the unit tests of the TestAPI * the creation of a new docker file - * the deployment of the new test api - * the archive of the old test api + * the deployment of the new TestAPI + * the archive of the old TestAPI * the backup of the Mongo DB -Test API Authorization -~~~~~~~~~~~~~~~~~~~~~~ +TestAPI Authorization +~~~~~~~~~~~~~~~~~~~~~ -PUT/DELETE/POST operations of the testapi now require token based authorization. The token needs +PUT/DELETE/POST operations of the TestAPI now require token based authorization. The token needs to be added in the request using a header 'X-Auth-Token' for access to the database. e.g:: @@ -627,7 +627,7 @@ script can be found in `[16]`_. For next versions, it was decided to integrated bitergia dashboard. Bitergia already provides a dashboard for code and infrastructure. A new Test tab will be added. The dataset will be built by consuming -the test API. +the TestAPI. ======= diff --git a/docs/internship/security_group/index.rst b/docs/testing/developer/internship/security_group/index.rst index d1cdbdd8..d1cdbdd8 100644 --- a/docs/internship/security_group/index.rst +++ b/docs/testing/developer/internship/security_group/index.rst diff --git a/docs/internship/testapi_evolution/index.rst b/docs/testing/developer/internship/testapi_evolution/index.rst index 9cca9ebc..3038d0ac 100644 --- a/docs/internship/testapi_evolution/index.rst +++ b/docs/testing/developer/internship/testapi_evolution/index.rst @@ -7,9 +7,9 @@ International License. You should have received a copy of the license along with this. If not, see <http://creativecommons.org/licenses/by/4.0/>. -================== -Test API evolution -================== +================= +TestAPI evolution +================= Author: Sakala Venkata Krishna Rohit Mentors: S. Feng, J.Lausuch, M.Richomme @@ -17,10 +17,10 @@ Mentors: S. Feng, J.Lausuch, M.Richomme Abstract ======== -The testapi is used by all the test opnfv projects to report results. +The TestAPI is used by all the test opnfv projects to report results. It is also used to declare projects, test cases and labs. A major refactoring -has been done in Colorado with the introduction of swagger. The testapi is defined in Functest -developer guide. The purpose of this project is to add more features to the testapi that automate +has been done in Colorado with the introduction of swagger. The TestAPI is defined in Functest +developer guide. The purpose of this project is to add more features to the TestAPI that automate the tasks that are done manually now, though there are tasks other than automation. Version history @@ -48,33 +48,33 @@ documentation is as follows. Problem Statement: ------------------ -The problem statement could be divided into pending features that needed to be added into testapi +The problem statement could be divided into pending features that needed to be added into TestAPI repo. The following were to be accomplished within the internship time frame. -* **Add verification jenkins job for the testapi code** +* **Add verification jenkins job for the TestAPI code** The purpose of this job is to verify whehter the unit tests are successful or not with the inclusion of the patchset submitted. * **Automatic update of opnfv/testapi docker image** - The docker image of testapi is hosted in the opnfv docker hub. To ensure that the testapi image + The docker image of TestAPI is hosted in the opnfv docker hub. To ensure that the TestAPI image is always updated with the repository, automatic updation of the image is necessary and a job is triggered whenever a new patch gets merged. * **Automation deployment of testresults.opnfv.org/test/ website** - In the same manner as the docker image of testapi is updated, the testapi website needs to be + In the same manner as the docker image of TestAPI is updated, the TestAPI website needs to be in sync with the repository code. So, a job has been added to the opnfv jenkins ci for the updation of the testresults website. -* **Generate static documentation of testapi calls** - The purpose of this is to give an static/offline view of testapi. If someone wants to have a - look at the Restful apis of testapi, he/she does't need to go to the website, he can download +* **Generate static documentation of TestAPI calls** + The purpose of this is to give an static/offline view of TestAPI. If someone wants to have a + look at the Restful APIs of TestAPI, he/she does't need to go to the website, he can download a html page and view it anytime. -* **Backup MongoDB of testapi** +* **Backup MongoDB of TestAPI** The mongoDB needs to be backed up every week. Till now it was done manually, but due to this internship, it is now automated using a jenkins job. -* **Add token based authorization to the testapi calls** +* **Add token based authorization to the TestAPI calls** The token based authorization was implemented to ensure that only ci_pods could access the database. Authentication has been added to only delete/put/post requests. @@ -82,7 +82,7 @@ Curation Phase: --------------- The curation phase was the first 3 to 4 weeks of the internship. This phase was to get familiar -with the testapi code and functionality and propose the solutions/tools for the tasks mentioned +with the TestAPI code and functionality and propose the solutions/tools for the tasks mentioned above. Swagger codegen was choosen out of the four tools proposed `[3]`_ for generating static documentaion. @@ -107,7 +107,7 @@ The progress and completion of the tasks is described in the below table. | **Date** | **Comment** | | | | +--------------------------+------------------------------------------+ -| Nov 14th - Dec 31st | Understand Testapi code and the | +| Nov 14th - Dec 31st | Understand TestAPI code and the | | | requirements. | +--------------------------+------------------------------------------+ | Jan 1st - Jan 7th | Add jenkins job to create static | @@ -134,8 +134,8 @@ the internship. This section may help other developers in solving any errors cas code written as a part of this internship. -Test Api --------- +TestAPI +------- What is the difference between defining data_file as "/etc/.." and "etc/.." in setup.cfg ? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -216,7 +216,7 @@ defined. What job style should be used when there is a situation like one build should trigger other builds ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ or when different build scripts need to be run on different machines ? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MultiJob style should be used as it has phases where each phase can be taken as a build scipt and can have its own parameters by which one can define the SLAVE_LABEL parameter. @@ -234,4 +234,4 @@ _`[4]` : http://artifacts.opnfv.org/testapibackup.html _`[5]` : http://artifacts.opnfv.org/releng/docs/testapi.html -_`[6]` : http://artifacts.opnfv.org/functest/review/26047/devguide/index.html#test-api-authorization +_`[6]` : http://artifacts.opnfv.org/functest/docs/devguide/index.html#test-api-authorization diff --git a/docs/internship/unit_tests/index.rst b/docs/testing/developer/internship/unit_tests/index.rst index f969aa72..f969aa72 100644 --- a/docs/internship/unit_tests/index.rst +++ b/docs/testing/developer/internship/unit_tests/index.rst diff --git a/docs/internship/vnf_catalog/index.rst b/docs/testing/developer/internship/vnf_catalog/index.rst index df763339..df763339 100644 --- a/docs/internship/vnf_catalog/index.rst +++ b/docs/testing/developer/internship/vnf_catalog/index.rst diff --git a/docs/configguide/configguide.rst b/docs/testing/user/configguide/configguide.rst index 08e089c2..1bb8358a 100644 --- a/docs/configguide/configguide.rst +++ b/docs/testing/user/configguide/configguide.rst @@ -392,7 +392,6 @@ follows:: | |-- check_os.sh | |-- config_functest.yaml | |-- config_patch.yaml - | |-- exec_test.sh | |-- generate_report.py | |-- prepare_env.py | |-- run_tests.py diff --git a/docs/configguide/index.rst b/docs/testing/user/configguide/index.rst index f12739e3..f12739e3 100644 --- a/docs/configguide/index.rst +++ b/docs/testing/user/configguide/index.rst diff --git a/docs/userguide/index.rst b/docs/testing/user/userguide/index.rst index 9436de2b..9436de2b 100644 --- a/docs/userguide/index.rst +++ b/docs/testing/user/userguide/index.rst diff --git a/docs/userguide/introduction.rst b/docs/testing/user/userguide/introduction.rst index 4dfe7937..4dfe7937 100644 --- a/docs/userguide/introduction.rst +++ b/docs/testing/user/userguide/introduction.rst diff --git a/docs/userguide/runfunctest.rst b/docs/testing/user/userguide/runfunctest.rst index b5c7191c..e7ab84b2 100644 --- a/docs/userguide/runfunctest.rst +++ b/docs/testing/user/userguide/runfunctest.rst @@ -174,7 +174,7 @@ To execute a Test Tier or Test Case, the 'run' command is used:: 2016-06-30 11:50:31,865 - run_tests - INFO - ============================================ 2016-06-30 11:50:31,865 - run_tests - INFO - Running test case 'vping_ssh'... 2016-06-30 11:50:31,865 - run_tests - INFO - ============================================ - 2016-06-30 11:50:32,977 - vping_ssh - INFO - Creating image 'functest-vping' from '/home/opnfv/functest/data/cirros-0.3.4-x86_64-disk.img'... + 2016-06-30 11:50:32,977 - vping_ssh - INFO - Creating image 'functest-vping' from '/home/opnfv/functest/data/cirros-0.3.5-x86_64-disk.img'... 2016-06-30 11:50:45,470 - vping_ssh - INFO - Creating neutron network vping-net... 2016-06-30 11:50:47,645 - vping_ssh - INFO - Creating security group 'vPing-sg'... 2016-06-30 11:50:48,843 - vping_ssh - INFO - Using existing Flavor 'm1.small'... diff --git a/docs/userguide/troubleshooting.rst b/docs/testing/user/userguide/troubleshooting.rst index 1b7bf9b3..84550191 100644 --- a/docs/userguide/troubleshooting.rst +++ b/docs/testing/user/userguide/troubleshooting.rst @@ -100,7 +100,7 @@ In this case, proceed to create it manually. These are some hints:: --protocol tcp --port-range-min 80 --port-range-max 80 --remote-ip-prefix 0.0.0.0/0 The next step is to create the instances. The image used is located in -*/home/opnfv/functest/data/cirros-0.3.4-x86_64-disk.img* and a Glance image is created +*/home/opnfv/functest/data/cirros-0.3.5-x86_64-disk.img* and a Glance image is created with the name **functest-vping**. If booting the instances fails (i.e. the status is not **ACTIVE**), you can check why it failed by doing:: diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml index 489c395f..402e2999 100755 --- a/functest/ci/config_functest.yaml +++ b/functest/ci/config_functest.yaml @@ -5,8 +5,8 @@ general: dir_odl: functest/opnfv_tests/sdn/odl rally: functest/opnfv_tests/openstack/rally tempest_cases: functest/opnfv_tests/openstack/tempest/custom_tests - dir_onos: functest/opnfv_tests/sdn/onos/teston - dir_onos_sfc: functest/opnfv_tests/sdn/onos/sfc + onos: functest/opnfv_tests/sdn/onos/teston + onos_sfc: functest/opnfv_tests/sdn/onos/sfc # Absolute path home: /home/opnfv @@ -18,7 +18,7 @@ general: repo_vims_test: /home/opnfv/repos/vnfs/vims-test repo_sdnvpn: /home/opnfv/repos/sdnvpn repo_sfc: /home/opnfv/repos/sfc - dir_repo_onos: /home/opnfv/repos/onos + repo_onos: /home/opnfv/repos/onos repo_promise: /home/opnfv/repos/promise repo_netready: /home/opnfv/repos/netready repo_barometer: /home/opnfv/repos/barometer @@ -43,8 +43,8 @@ general: creds: /home/opnfv/functest/conf/openstack.creds snapshot_file: /home/opnfv/functest/conf/openstack_snapshot.yaml - image_name: Cirros-0.3.4 - image_file_name: cirros-0.3.4-x86_64-disk.img + image_name: Cirros-0.3.5 + image_file_name: cirros-0.3.5-x86_64-disk.img image_disk_format: qcow2 image_username: cirros image_password: cubswin:) @@ -67,7 +67,7 @@ general: testcases_yaml: /home/opnfv/repos/functest/functest/ci/testcases.yaml healthcheck: - disk_image: /home/opnfv/functest/data/cirros-0.3.4-x86_64-disk.img + disk_image: /home/opnfv/functest/data/cirros-0.3.5-x86_64-disk.img disk_format: qcow2 wait_time: 60 diff --git a/functest/ci/config_patch.yaml b/functest/ci/config_patch.yaml index 46064a07..d984a3f4 100755 --- a/functest/ci/config_patch.yaml +++ b/functest/ci/config_patch.yaml @@ -1,12 +1,12 @@ lxd: general: openstack: - image_name: Cirros-0.3.4 - image_file_name: cirros-0.3.4-x86_64-lxc.tar.gz + image_name: Cirros-0.3.5 + image_file_name: cirros-0.3.5-x86_64-lxc.tar.gz image_disk_format: raw healthcheck: - disk_image: /home/opnfv/functest/data/cirros-0.3.4-x86_64-lxc.tar.gz + disk_image: /home/opnfv/functest/data/cirros-0.3.5-x86_64-lxc.tar.gz disk_format: raw fdio: general: diff --git a/functest/ci/exec_test.sh b/functest/ci/exec_test.sh deleted file mode 100755 index aa0cfaf7..00000000 --- a/functest/ci/exec_test.sh +++ /dev/null @@ -1,154 +0,0 @@ -#!/bin/bash - -# -# Author: Jose Lausuch (jose.lausuch@ericsson.com) -# Morgan Richomme (morgan.richomme@orange.com) -# Installs the Functest framework within the Docker container -# and run the tests automatically -# -# -# 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 -# - -usage="Script to trigger the tests automatically. - -usage: - bash $(basename "$0") [-h|--help] [-t <test_name>] - -where: - -h|--help show this help text - -r|--report push results to database (false by default) - -s|--serial run Tempest tests in one thread - -t|--test run specific test case - <test_name>" - - -report="" -serial=false - -# Get the list of runnable tests -# Check if we are in CI mode -debug="" -if [[ "${CI_DEBUG,,}" == "true" ]];then - debug="--debug" -fi - -FUNCTEST_REPO_DIR=${REPOS_DIR}/functest -FUNCTEST_TEST_DIR=${REPOS_DIR}/functest/functest/opnfv_tests -FUNCTEST_CONF_DIR=/home/opnfv/functest/conf - -export PYTHONUNBUFFERED=1 - -function odl_tests(){ - keystone_ip=$(openstack catalog show identity |grep publicURL| cut -f3 -d"/" | cut -f1 -d":") - neutron_ip=$(openstack catalog show network | grep publicURL | cut -f3 -d"/" | cut -f1 -d":") - odl_ip=${neutron_ip} - odl_port=8080 - odl_restport=8181 - if [ "$INSTALLER_TYPE" == "fuel" ]; then - odl_port=8282 - elif [ "$INSTALLER_TYPE" == "apex" ]; then - odl_ip=$SDN_CONTROLLER_IP - odl_port=8081 - odl_restport=8081 - elif [ "$INSTALLER_TYPE" == "netvirt" ]; then - odl_ip=$SDN_CONTROLLER_IP - odl_port=8081 - odl_restport=8081 - elif [ "$INSTALLER_TYPE" == "joid" ]; then - odl_ip=$SDN_CONTROLLER - elif [ "$INSTALLER_TYPE" == "compass" ]; then - odl_port=8181 - else - odl_ip=$SDN_CONTROLLER_IP - fi -} - - - -function run_test(){ - test_name=$1 - serial_flag="" - if [ $serial == "true" ]; then - serial_flag="-s" - fi - - case $test_name in - "healthcheck") - ${FUNCTEST_TEST_DIR}/openstack/healthcheck/healthcheck.sh - ;; - "odl") - odl_tests - [[ "$report" == "-r" ]] && args=-p - ${FUNCTEST_TEST_DIR}/sdn/odl/odl.py \ - --keystoneip $keystone_ip \ - --neutronip $neutron_ip \ - --odlip $odl_ip \ - --odlrestconfport $odl_restport \ - --odlwebport $odl_port \ - --ospassword ${OS_PASSWORD} \ - --ostenantname ${OS_TENANT_NAME} \ - --osusername ${OS_USERNAME} \ - ${args} - ;; - "onos") - python ${FUNCTEST_TEST_DIR}/sdn/onos/teston/onos.py - ;; - "onos_sfc") - python ${FUNCTEST_TEST_DIR}/sdn/onos/teston/onos.py -t sfc - ;; - "ovno") - # suite under rewritting for colorado - # no need to run anything until refactoring done - # ${REPOS_DIR}/ovno/Testcases/RunTests.sh - ;; - *) - echo "The test case '${test_name}' does not exist." - exit 1 - esac - - if [[ $? != 0 ]]; then exit 1 - else exit 0 - fi -} - - -# Parse parameters -while [[ $# > 0 ]] - do - key="$1" - case $key in - -h|--help) - echo "$usage" - exit 0 - shift - ;; - -r|--report) - report="-r" - ;; - -s|--serial) - serial=true - ;; - -t|--test|--tests) - TEST="$2" - shift - ;; - *) - echo "unknown option $1 $2" - exit 1 - ;; - esac - shift # past argument or value -done - - -# Source credentials -echo "Sourcing Credentials ${creds} to run the test.." -source ${creds} - - -# Run test -run_test $TEST diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py index f5bae6a0..724ea14d 100755 --- a/functest/ci/prepare_env.py +++ b/functest/ci/prepare_env.py @@ -31,6 +31,7 @@ logger = ft_logger.Logger("prepare_env").getLogger() handler = None # set the architecture to default pod_arch = None +arch_filter = ['aarch64'] CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML CONFIG_PATCH_PATH = os.path.join(os.path.dirname( @@ -115,24 +116,28 @@ def get_deployment_handler(): 'functest/ci/installer_params.yaml') if (CONST.INSTALLER_IP and CONST.INSTALLER_TYPE and CONST.INSTALLER_TYPE in opnfv_constants.INSTALLERS): - installer_params = ft_utils.get_parameter_from_yaml( - CONST.INSTALLER_TYPE, installer_params_yaml) - - user = installer_params.get('user', None) - password = installer_params.get('password', None) - pkey = installer_params.get('pkey', None) - try: - handler = factory.Factory.get_handler( - installer=CONST.INSTALLER_TYPE, - installer_ip=CONST.INSTALLER_IP, - installer_user=user, - installer_pwd=password, - pkey_file=pkey) - if handler: - pod_arch = handler.get_arch() - except Exception as e: - logger.debug("Cannot get deployment information. %s" % e) + installer_params = ft_utils.get_parameter_from_yaml( + CONST.INSTALLER_TYPE, installer_params_yaml) + except ValueError as e: + logger.debug('Printing deployment info is not supported for %s' % + CONST.INSTALLER_TYPE) + logger.debug(e) + else: + user = installer_params.get('user', None) + password = installer_params.get('password', None) + pkey = installer_params.get('pkey', None) + try: + handler = factory.Factory.get_handler( + installer=CONST.INSTALLER_TYPE, + installer_ip=CONST.INSTALLER_IP, + installer_user=user, + installer_pwd=password, + pkey_file=pkey) + if handler: + pod_arch = handler.get_arch() + except Exception as e: + logger.debug("Cannot get deployment information. %s" % e) def create_directories(): @@ -196,8 +201,7 @@ def source_rc_file(): raise Exception("The file %s is empty." % CONST.openstack_creds) logger.info("Sourcing the OpenStack RC file...") - os_utils.source_credentials( - CONST.openstack_creds) + os_utils.source_credentials(CONST.openstack_creds) for key, value in os.environ.iteritems(): if re.search("OS_", key): if key == 'OS_AUTH_URL': @@ -210,10 +214,15 @@ def source_rc_file(): CONST.OS_PASSWORD = value -def patch_config_file(patch_file_path, arch_filter=None): - if arch_filter and pod_arch not in arch_filter: - return +def patch_config_file(): + patch_file(CONFIG_PATCH_PATH) + + if pod_arch and pod_arch in arch_filter: + patch_file(CONFIG_AARCH64_PATCH_PATH) + +def patch_file(patch_file_path): + logger.debug('Updating file: %s', patch_file_path) with open(patch_file_path) as f: patch_file = yaml.safe_load(f) @@ -250,7 +259,7 @@ def verify_deployment(): def install_rally(): print_separator() - if 'aarch64' in pod_arch: + if pod_arch and pod_arch in arch_filter: logger.info("Apply aarch64 specific to rally config...") with open(RALLY_AARCH64_PATCH_PATH, "r") as f: rally_patch_conf = f.read() @@ -350,8 +359,7 @@ def main(**kwargs): get_deployment_handler() create_directories() source_rc_file() - patch_config_file(CONFIG_PATCH_PATH) - patch_config_file(CONFIG_AARCH64_PATCH_PATH, 'aarch64') + patch_config_file() verify_deployment() install_rally() install_tempest() diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py index f920e70d..0e951eff 100755 --- a/functest/ci/run_tests.py +++ b/functest/ci/run_tests.py @@ -32,13 +32,6 @@ from functest.utils.constants import CONST logger = ft_logger.Logger("run_tests").getLogger() -""" global variables """ -EXEC_SCRIPT = ("%s/functest/ci/exec_test.sh" % CONST.dir_repo_functest) - -# This will be the return code of this script. If any of the tests fails, -# this variable will change to Result.EX_ERROR - - class Result(enum.Enum): EX_OK = os.EX_OK EX_ERROR = -1 @@ -119,7 +112,7 @@ def update_test_info(test_name, result, duration): "duration": duration}) -def get_run_dict_if_defined(testname): +def get_run_dict(testname): try: dict = ft_utils.get_dict_by_test(testname) if not dict: @@ -143,7 +136,7 @@ def run_test(test, tier_name, testcases=None): logger.debug("\n%s" % test) source_rc_file() - if GlobalVariables.CLEAN_FLAG: + if test.needs_clean() and GlobalVariables.CLEAN_FLAG: generate_os_snapshot() flags = (" -t %s" % (test_name)) @@ -151,12 +144,13 @@ def run_test(test, tier_name, testcases=None): flags += " -r" result = testcase_base.TestcaseBase.EX_RUN_ERROR - run_dict = get_run_dict_if_defined(test_name) + run_dict = get_run_dict(test_name) if run_dict: try: module = importlib.import_module(run_dict['module']) cls = getattr(module, run_dict['class']) test_case = cls() + try: kwargs = run_dict['args'] result = test_case.run(**kwargs) @@ -173,14 +167,11 @@ def run_test(test, tier_name, testcases=None): logger.exception("Cannot get class {}".format( run_dict['class'])) else: - cmd = ("%s%s" % (EXEC_SCRIPT, flags)) - logger.info("Executing command {} because {} " - "doesn't implement the new framework".format( - cmd, test_name)) - result = ft_utils.execute_command(cmd) + raise Exception("Cannot import the class for the test case.") - if GlobalVariables.CLEAN_FLAG: + if test.needs_clean() and GlobalVariables.CLEAN_FLAG: cleanup() + end = datetime.datetime.now() duration = (end - start).seconds duration_str = ("%02d:%02d" % divmod(duration, 60)) diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml index eea1f518..1a1d0f4b 100755 --- a/functest/ci/testcases.yaml +++ b/functest/ci/testcases.yaml @@ -11,6 +11,7 @@ tiers: name: snaps_health_check criteria: 'status == "PASS"' blocking: true + clean_flag: false description: >- This test case creates executes the SimpleHealthCheck Python test class which creates an, image, flavor, network, @@ -26,6 +27,7 @@ tiers: name: connection_check criteria: 'status == "PASS"' blocking: true + clean_flag: false description: >- This test case verifies the retrieval of OpenStack clients: Keystone, Glance, Neutron and Nova and may perform some @@ -44,6 +46,7 @@ tiers: name: api_check criteria: 'status == "PASS"' blocking: true + clean_flag: false description: >- This test case verifies the retrieval of OpenStack clients: Keystone, Glance, Neutron and Nova and may perform some @@ -68,13 +71,14 @@ tiers: name: vping_ssh criteria: 'status == "PASS"' blocking: true + clean_flag: true description: >- This test case verifies: 1) SSH to an instance using floating IPs over the public network. 2) Connectivity between 2 instances over a private network. dependencies: installer: '' - scenario: '^((?!bgpvpn|odl_l3).)*$' + scenario: '^((?!odl_l3).)*$' run: module: 'functest.opnfv_tests.openstack.vping.vping_ssh' class: 'VPingSSH' @@ -83,6 +87,7 @@ tiers: name: vping_userdata criteria: 'status == "PASS"' blocking: true + clean_flag: true description: >- This test case verifies: 1) Boot a VM with given userdata. 2) Connectivity between 2 instances over a private network. @@ -97,6 +102,7 @@ tiers: name: tempest_smoke_serial criteria: 'success_rate == 100%' blocking: false + clean_flag: false description: >- This test case runs the smoke subset of the OpenStack Tempest suite. The list of test cases is generated by @@ -113,12 +119,13 @@ tiers: name: rally_sanity criteria: 'success_rate == 100%' blocking: false + clean_flag: false description: >- This test case runs a sub group of tests of the OpenStack Rally suite in smoke mode. dependencies: installer: '' - scenario: '^((?!bgpvpn).)*$' + scenario: '' run: module: 'functest.opnfv_tests.openstack.rally.rally' class: 'RallySanity' @@ -127,6 +134,7 @@ tiers: name: odl criteria: 'success_rate == 100%' blocking: true + clean_flag: false description: >- Test Suite for the OpenDaylight SDN Controller. It integrates some test suites from upstream using @@ -146,6 +154,7 @@ tiers: name: odl_netvirt criteria: 'success_rate == 100%' blocking: true + clean_flag: false description: >- Test Suite for the OpenDaylight SDN Controller when the NetVirt features are installed. It integrates @@ -167,6 +176,7 @@ tiers: name: onos criteria: 'status == "PASS"' blocking: true + clean_flag: true description: >- Test Suite for the ONOS SDN Controller. It integrates some test suites from upstream using TestON as the test @@ -174,12 +184,15 @@ tiers: dependencies: installer: '' scenario: 'onos' - + run: + module: 'functest.opnfv_tests.sdn.onos.onos' + class: 'Onos' - name: snaps_smoke criteria: 'status == "PASS"' blocking: false + clean_flag: false description: >- This test case contains tests that setup and destroy environments with VMs with and without Floating IPs @@ -208,6 +221,7 @@ tiers: name: promise criteria: 'success_rate == 100%' blocking: false + clean_flag: true description: >- Test suite from Promise project. dependencies: @@ -221,6 +235,7 @@ tiers: name: doctor criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite from Doctor project. dependencies: @@ -234,6 +249,7 @@ tiers: name: bgpvpn criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite from SDNVPN project. dependencies: @@ -247,6 +263,7 @@ tiers: name: security_scan criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Simple Security Scan dependencies: @@ -259,6 +276,7 @@ tiers: # name: copper # criteria: 'status == "PASS"' # blocking: false +# clean_flag: true # description: >- # Test suite for policy management based on OpenStack Congress # dependencies: @@ -271,6 +289,7 @@ tiers: name: multisite criteria: 'success_rate == 100%' blocking: false + clean_flag: false description: >- Test suite from kingbird dependencies: @@ -283,6 +302,7 @@ tiers: name: odl-sfc criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite for odl-sfc to test two chains and two SFs dependencies: @@ -295,15 +315,20 @@ tiers: name: onos_sfc criteria: 'status == "PASS"' blocking: true + clean_flag: true description: >- Test Suite for onos-sfc to test sfc function. dependencies: installer: '' scenario: 'onos-sfc' + run: + module: 'functest.opnfv_tests.sdn.onos.onos' + class: 'OnosSfc' - name: parser criteria: 'ret == 0' blocking: false + clean_flag: true description: >- Test suite from Parser project. dependencies: @@ -316,6 +341,7 @@ tiers: name: domino criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite from Domino project. dependencies: @@ -328,6 +354,7 @@ tiers: name: orchestra criteria: 'ret == 0' blocking: false + clean_flag: true description: >- Test OpenBaton (Orchestra) stack dependencies: @@ -340,6 +367,7 @@ tiers: name: netready criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite from Netready project. dependencies: @@ -352,6 +380,7 @@ tiers: name: barometer criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- Test suite for the Barometer project. Separate tests verify the proper configuration and functionality of the following @@ -374,6 +403,7 @@ tiers: # name: tempest_full_parallel # criteria: 'success_rate >= 80%' # blocking: false +# clean_flag: false # description: >- # The list of test cases is generated by # Tempest automatically and depends on the parameters of @@ -388,6 +418,7 @@ tiers: name: tempest_defcore criteria: 'success_rate == 100%' blocking: false + clean_flag: false description: >- This is the set of Tempest test cases created by OpenStack Interop Working Group for certification purposes. @@ -397,10 +428,28 @@ tiers: run: module: 'functest.opnfv_tests.openstack.tempest.tempest' class: 'TempestDefcore' + - + name: tempest_custom + criteria: 'success_rate == 100%' + blocking: false + clean_flag: false + description: >- + The test case allows running a customized list of tempest + test cases defined in a file under + <dir_functest_repo>/functest/opnfv_tests/openstack/ + /tempest/custom_tests/test_list.txt + The file is empty and can be customized with the desired tests. + dependencies: + installer: 'unknown' + scenario: 'unknown' + run: + module: 'functest.opnfv_tests.openstack.tempest.tempest' + class: 'TempestCustom' # - # name: rally_full # criteria: 'success_rate >= 90%' # blocking: false +# clean_flag: false # description: >- # This test case runs the full suite of scenarios of the OpenStack # Rally suite using several threads and iterations. @@ -422,6 +471,7 @@ tiers: name: cloudify_ims criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- This test case deploys an OpenSource vIMS solution from Clearwater using the Cloudify orchestrator. It also runs some signaling traffic. @@ -435,6 +485,7 @@ tiers: name: aaa criteria: 'ret == 0' blocking: false + clean_flag: true description: >- Test suite from Parser project. dependencies: @@ -448,6 +499,7 @@ tiers: name: juju_epc criteria: 'ret == 0' blocking: false + clean_flag: true description: >- Test suite from OAI project, vEPC deployed with Juju. dependencies: @@ -461,6 +513,7 @@ tiers: name: orchestra_ims criteria: 'ret == 0' blocking: false + clean_flag: true description: >- VNF deployment with OpenBaton (Orchestra) dependencies: @@ -474,6 +527,7 @@ tiers: name: opera_ims criteria: 'ret == 0' blocking: false + clean_flag: true description: >- Evolution of vIMS dependencies: @@ -487,6 +541,7 @@ tiers: name: vyos_vrouter criteria: 'status == "PASS"' blocking: false + clean_flag: true description: >- This test case is vRouter testing. dependencies: diff --git a/functest/ci/tier_builder.py b/functest/ci/tier_builder.py index dae7c73e..f4c6f70f 100755 --- a/functest/ci/tier_builder.py +++ b/functest/ci/tier_builder.py @@ -50,6 +50,7 @@ class TierBuilder(object): 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): tier.add_test(testcase) diff --git a/functest/ci/tier_handler.py b/functest/ci/tier_handler.py index 127986bf..6b4864b5 100755 --- a/functest/ci/tier_handler.py +++ b/functest/ci/tier_handler.py @@ -104,12 +104,18 @@ class Tier(object): class TestCase(object): - def __init__(self, name, dependency, criteria, blocking, description=""): + def __init__(self, name, + dependency, + criteria, + blocking, + clean_flag, + description=""): self.name = name self.dependency = dependency - self.description = description self.criteria = criteria self.blocking = blocking + self.clean_flag = clean_flag + self.description = description @staticmethod def is_none(item): @@ -138,6 +144,9 @@ class TestCase(object): def is_blocking(self): return self.blocking + def needs_clean(self): + return self.clean_flag + def __str__(self): lines = split_text(self.description, LINE_LENGTH - 6) diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template index 909f45d2..ed5e61fe 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template +++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_ports.yaml.template @@ -7,7 +7,7 @@ parameters: default: public image: type: string - default: cirros-0.3.4-x86_64-uec + default: cirros-0.3.5-x86_64-uec flavor: type: string default: m1.tiny diff --git a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template index 826ca9da..116b5bb6 100644 --- a/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template +++ b/functest/opnfv_tests/openstack/rally/scenario/templates/server_with_volume.yaml.template @@ -4,7 +4,7 @@ parameters: # set all correct defaults for parameters before launch test image: type: string - default: cirros-0.3.4-x86_64-uec + default: cirros-0.3.5-x86_64-uec flavor: type: string default: m1.tiny diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt index 0a4256ce..fcdfe225 100644 --- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt @@ -1,22 +1,3 @@ -- - scenarios: - - os-odl_l2-bgpvpn-ha - - os-odl_l2-bgpvpn-noha - installers: - - fuel - - apex - tests: - - tempest.api.compute.servers.test_create_server.ServersTestJSON.test_list_servers - - tempest.api.compute.servers.test_create_server.ServersTestJSON.test_verify_server_details - - tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_list_servers - - tempest.api.compute.servers.test_create_server.ServersTestManualDisk.test_verify_server_details - - tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard - - tempest.api.network.test_floating_ips.FloatingIPTestJSON.test_create_list_show_update_delete_floating_ip - - tempest.api.network.test_floating_ips.FloatingIPTestJSON.test_create_floating_ip_specifying_a_fixed_ip_address - - tempest.scenario.test_network_basic_ops.TestNetworkBasicOps.test_network_basic_ops - - tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops - - tempest.scenario.test_volume_boot_pattern.TestVolumeBootPattern.test_volume_boot_pattern - - tempest.scenario.test_volume_boot_pattern.TestVolumeBootPatternV2.test_volume_boot_pattern - scenarios: diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/test_list.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/test_list.txt new file mode 100644 index 00000000..ac4e3728 --- /dev/null +++ b/functest/opnfv_tests/openstack/tempest/custom_tests/test_list.txt @@ -0,0 +1,4 @@ +# This is an empty file to be filled up with the desired tempest test cases +# Examples: +#tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops +#tempest.scenario.test_network_basic_ops.TestNetworkBasicOps.test_network_basic_ops
\ No newline at end of file diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py index 37b5c0ee..4c96500d 100644 --- a/functest/opnfv_tests/openstack/tempest/tempest.py +++ b/functest/opnfv_tests/openstack/tempest/tempest.py @@ -324,11 +324,11 @@ class TempestMultisite(TempestCommon): class TempestCustom(TempestCommon): - def __init__(self, mode, option): + def __init__(self): TempestCommon.__init__(self) self.case_name = "tempest_custom" - self.MODE = mode - self.OPTION = option + self.MODE = "custom" + self.OPTION = "--concurrency 1" class TempestDefcore(TempestCommon): diff --git a/functest/opnfv_tests/sdn/onos/__init__.py b/functest/opnfv_tests/sdn/onos/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/functest/opnfv_tests/sdn/onos/__init__.py diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py new file mode 100644 index 00000000..8bc73832 --- /dev/null +++ b/functest/opnfv_tests/sdn/onos/onos.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python + +# Copyright (c) 2017 HUAWEI TECHNOLOGIES CO.,LTD 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 os +import re +import subprocess +import shutil +import time +import urlparse + +from functest.core import testcase_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 openstack_utils + + +logger = ft_logger.Logger(__name__).getLogger() + + +class OnosBase(testcase_base.TestcaseBase): + 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__() + + def run(self): + self.start_time = time.time() + try: + self._run() + res = testcase_base.TestcaseBase.EX_OK + except Exception as e: + logger.error('Error with run: %s', e) + res = testcase_base.TestcaseBase.EX_RUN_ERROR + + self.stop_time = time.time() + return res + + def _run(self): + raise NotImplementedError('_run is not implemented') + + +class Onos(OnosBase): + def __init__(self): + super(Onos, self).__init__() + self.case_name = 'onos' + 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'): + 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) + + 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) + ft_utils.execute_command_raise( + cmd, + error_msg=('Error when running ONOS script: %s' + % (testname))) + + def clean_existing_logs(self): + log_dir = [f for f in os.listdir(self.log_path)] + for log in log_dir: + try: + if os.path.isdir(log): + shutil.rmtree(log) + elif os.path.isfile(log): + os.remove(log) + except OSError as e: + logger.error('Error with deleting file %s: %s', + log, e.strerror) + + def get_result(self): + cmd = 'grep -rnh Fail {0}'.format(self.log_path) + p = subprocess.Popen(cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + + for line in p.stdout: + logger.debug(line) + if re.search("\s+[1-9]+\s+", line): + logger.debug("Testcase Fails\n" + line) + + cmd = "grep -rnh 'Execution Time' {0}".format(self.log_path) + result_buffer = os.popen(cmd).read() + time1 = result_buffer[114:128] + time2 = result_buffer[28:42] + cmd = "grep -rnh 'Success Percentage' {0}".format( + os.path.join(self.log_path, "FUNCvirNetNB_*")) + result_buffer = os.popen(cmd).read() + if result_buffer.find('100%') >= 0: + result1 = 'Success' + else: + result1 = 'Failed' + cmd = "grep -rnh 'Success Percentage' {0}".format( + os.path.join(self.log_path, "FUNCvirNetNBL3*")) + result_buffer = os.popen(cmd).read() + if result_buffer.find('100%') >= 0: + result2 = 'Success' + else: + result2 = 'Failed' + status1 = [] + status2 = [] + cmd = "grep -rnh 'h3' {0}".format( + os.path.join(self.log_path, "FUNCvirNetNB_*")) + result_buffer = os.popen(cmd).read() + pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>") + # res = pattern.search(result_buffer).groups() + res = pattern.findall(result_buffer) + i = 0 + for index in range(len(res)): + status1.append({'Case name:': res[i][0] + res[i][1], + 'Case result': res[i][2]}) + i = i + 1 + cmd = "grep -rnh 'h3' {0}".format( + os.path.join(self.log_path, "FUNCvirNetNBL3*")) + result_buffer = os.popen(cmd).read() + pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>") + res = pattern.findall(result_buffer) + i = 0 + for index in range(len(res)): + status2.append({'Case name:': res[i][0] + res[i][1], + 'Case result': res[i][2]}) + i = i + 1 + payload = {'FUNCvirNet': {'duration': time1, + 'result': result1, + 'status': status1}, + 'FUNCvirNetL3': {'duration': time2, + 'result': result2, + 'status': status2}} + return payload + + def parse_result(self): + result = self.get_result() + status = "FAIL" + try: + if (result['FUNCvirNet']['result'] == "Success" and + result['FUNCvirNetL3']['result'] == "Success"): + status = "PASS" + except: + logger.error("Unable to set ONOS criteria") + + self.criteria = status + self.details = result + + def _run(self): + self.clean_existing_logs() + self.set_onos_ip() + self.run_onos_script('FUNCvirNetNB') + self.run_onos_script('FUNCvirNetNBL3') + self.parse_result() + + +class OnosSfc(OnosBase): + def __init__(self): + super(OnosSfc, self).__init__() + self.case_name = 'onos_sfc' + + def get_ip(type): + url = openstack_utils.get_endpoint(service_type=type) + logger.debug('get_ip for %s: %s' % (type, url)) + return urlparse.urlparse(url).hostname + + def update_sfc_onos_file(self, before, after): + file_dir = os.path.join(self.onos_sfc_path, "sfc_onos.py") + cmd = "sed -i 's/{0}/{1}/g' {2}".format(before, + after, + file_dir) + ft_utils.execute_command_raise( + cmd, + error_msg=('Error with replacing %s with %s' + % (before, after))) + + def create_image(self): + glance_client = openstack_utils.get_glance_client() + image_id = openstack_utils.create_glance_image( + glance_client, + self.onos_sfc_image_name, + self.onos_sfc_image_path) + 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)) + + 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) + 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") + + def sfc_test(self): + cmd = 'python {0}'.format(os.path.join(self.onos_sfc_path, 'sfc.py')) + ft_utils.execute_command_raise(cmd, + error_msg='Error with testing SFC') + + def _run(self): + self.create_image() + self.set_sfc_conf() + self.sfc_test() diff --git a/functest/opnfv_tests/sdn/onos/teston/onos.py b/functest/opnfv_tests/sdn/onos/teston/onos.py deleted file mode 100755 index 2537e18d..00000000 --- a/functest/opnfv_tests/sdn/onos/teston/onos.py +++ /dev/null @@ -1,261 +0,0 @@ -""" -Description: This test is to run onos Teston VTN scripts - -List of test cases: -CASE1 - Northbound NBI test network/subnet/ports -CASE2 - Ovsdb test&Default configuration&Vm go online - -lanqinglong@huawei.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 -# -""" - -import datetime -import os -import re -import time -import urlparse - -import argparse -from neutronclient.v2_0 import client as neutronclient - -import functest.utils.functest_constants as ft_constants -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils -import functest.utils.openstack_utils as openstack_utils - - -parser = argparse.ArgumentParser() -parser.add_argument("-t", "--testcase", help="Testcase name") -args = parser.parse_args() - - -""" logging configuration """ -logger = ft_logger.Logger("onos").getLogger() - -# onos parameters -ONOSCI_PATH = ft_constants.REPOS_DIR + "/" -starttime = datetime.datetime.now() - -INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE -ONOS_SFC_IMAGE_NAME = ft_constants.ONOS_SFC_IMAGE_NAME -ONOS_SFC_IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR, - ft_constants.ONOS_SFC_IMAGE_FILENAME) -ONOS_SFC_PATH = os.path.join(ft_constants.FUNCTEST_REPO_DIR, - ft_constants.ONOS_SFC_RELATIVE_PATH) - - -def RunScript(testname): - """ - Run ONOS Test Script - Parameters: - testname: ONOS Testcase Name - """ - runtest = ONOSCI_PATH + "onos/TestON/bin/cli.py run " + testname - logger.debug("Run script " + testname) - os.system(runtest) - - -def DownloadCodes(url="https://github.com/wuwenbin2/OnosSystemTest.git"): - """ - Download Onos Teston codes - Parameters: - url: github url - """ - downloadcode = "git clone " + url + " " + ONOSCI_PATH + "OnosSystemTest" - logger.debug("Download Onos Teston codes " + url) - os.system(downloadcode) - - -def GetResult(): - LOGPATH = ONOSCI_PATH + "onos/TestON/logs" - cmd = "grep -rnh " + "Fail" + " " + LOGPATH - Resultbuffer = os.popen(cmd).read() - # duration = datetime.datetime.now() - starttime - time.sleep(2) - - if re.search("\s+[1-9]+\s+", Resultbuffer): - logger.debug("Testcase Fails\n" + Resultbuffer) - # Result = "Failed" - else: - logger.debug("Testcases Success") - # Result = "Success" - # payload={'timestart': str(starttime), - # 'duration': str(duration), - # 'status': Result} - cmd = "grep -rnh 'Execution Time' " + LOGPATH - Resultbuffer = os.popen(cmd).read() - time1 = Resultbuffer[114:128] - time2 = Resultbuffer[28:42] - cmd = "grep -rnh 'Success Percentage' " + LOGPATH + "/FUNCvirNetNB_*" - Resultbuffer = os.popen(cmd).read() - if Resultbuffer.find('100%') >= 0: - result1 = 'Success' - else: - result1 = 'Failed' - cmd = "grep -rnh 'Success Percentage' " + LOGPATH + "/FUNCvirNetNBL3*" - Resultbuffer = os.popen(cmd).read() - if Resultbuffer.find('100%') >= 0: - result2 = 'Success' - else: - result2 = 'Failed' - status1 = [] - status2 = [] - cmd = "grep -rnh 'h3' " + LOGPATH + "/FUNCvirNetNB_*" - Resultbuffer = os.popen(cmd).read() - pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>") - # res = pattern.search(Resultbuffer).groups() - res = pattern.findall(Resultbuffer) - i = 0 - for index in range(len(res)): - status1.append({'Case name:': res[i][0] + res[i][1], - 'Case result': res[i][2]}) - i = i + 1 - cmd = "grep -rnh 'h3' " + LOGPATH + "/FUNCvirNetNBL3*" - Resultbuffer = os.popen(cmd).read() - pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>") - # res = pattern.search(Resultbuffer).groups() - res = pattern.findall(Resultbuffer) - i = 0 - for index in range(len(res)): - status2.append({'Case name:': res[i][0] + res[i][1], - 'Case result': res[i][2]}) - i = i + 1 - payload = {'timestart': str(starttime), - 'FUNCvirNet': {'duration': time1, - 'result': result1, - 'status': status1}, - 'FUNCvirNetL3': {'duration': time2, - 'result': result2, - 'status': status2}} - return payload - - -def SetOnosIp(): - # cmd = "openstack catalog show network | grep publicURL" - neutron_url = openstack_utils.get_endpoint(service_type='network') - OC1 = urlparse.urlparse(neutron_url).hostname - os.environ['OC1'] = OC1 - time.sleep(2) - logger.debug("ONOS IP is " + OC1) - - -def SetOnosIpForJoid(): - cmd = "env | grep SDN_CONTROLLER" - cmd_output = os.popen(cmd).read() - OC1 = re.search(r"\d+\.\d+\.\d+\.\d+", cmd_output).group() - os.environ['OC1'] = OC1 - time.sleep(2) - logger.debug("ONOS IP is " + OC1) - - -def CleanOnosTest(): - TESTONPATH = ONOSCI_PATH + "onos/" - cmd = "rm -rf " + TESTONPATH - os.system(cmd) - time.sleep(2) - logger.debug("Clean ONOS Teston") - - -def CreateImage(): - glance_client = openstack_utils.get_glance_client() - image_id = openstack_utils.create_glance_image(glance_client, - ONOS_SFC_IMAGE_NAME, - ONOS_SFC_IMAGE_PATH) - EXIT_CODE = -1 - if not image_id: - logger.error("Failed to create a Glance image...") - return(EXIT_CODE) - logger.debug("Image '%s' with ID=%s created successfully." - % (ONOS_SFC_IMAGE_NAME, image_id)) - - -def SfcTest(): - cmd = "python " + ONOS_SFC_PATH + "/sfc.py" - logger.debug("Run sfc tests") - os.system(cmd) - - -def GetIp(type): - # cmd = "openstack catalog show " + type + " | grep publicURL" - url = openstack_utils.get_endpoint(service_type=type) - return urlparse.urlparse(url).hostname - - -def Replace(before, after): - file = "/sfc_onos.py" - cmd = "sed -i 's/" + before + "/" + after + "/g' " + ONOS_SFC_PATH + file - os.system(cmd) - - -def SetSfcConf(): - Replace("keystone_ip", GetIp("keystone")) - Replace("neutron_ip", GetIp("neutron")) - Replace("nova_ip", GetIp("nova")) - Replace("glance_ip", GetIp("glance")) - pwd = ft_constants.OS_PASSWORD - Replace("console", pwd) - creds_neutron = openstack_utils.get_credentials() - neutron_client = neutronclient.Client(**creds_neutron) - ext_net = openstack_utils.get_external_net(neutron_client) - Replace("admin_floating_net", ext_net) - logger.info("Modify configuration for SFC") - - -def OnosTest(): - start_time = time.time() - stop_time = start_time - if INSTALLER_TYPE == "joid": - logger.debug("Installer is Joid") - SetOnosIpForJoid() - else: - SetOnosIp() - RunScript("FUNCvirNetNB") - RunScript("FUNCvirNetNBL3") - try: - logger.debug("Push ONOS results into DB") - # TODO check path result for the file - result = GetResult() - stop_time = time.time() - - # ONOS success criteria = all tests OK - # i.e. FUNCvirNet & FUNCvirNetL3 - status = "FAIL" - try: - if (result['FUNCvirNet']['result'] == "Success" and - result['FUNCvirNetL3']['result'] == "Success"): - status = "PASS" - except: - logger.error("Unable to set ONOS criteria") - - ft_utils.push_results_to_db("functest", - "onos", - start_time, - stop_time, - status, - result) - - except: - logger.error("Error pushing results into Database") - - if status == "FAIL": - EXIT_CODE = -1 - exit(EXIT_CODE) - - -def main(): - - if args.testcase == "sfc": - CreateImage() - SetSfcConf() - SfcTest() - else: - OnosTest() - - -if __name__ == '__main__': - main() diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py index 447271fc..ef3764cc 100644 --- a/functest/tests/unit/utils/test_openstack_utils.py +++ b/functest/tests/unit/utils/test_openstack_utils.py @@ -104,7 +104,6 @@ class OSUtilsTesting(unittest.TestCase): 'servers.create.return_value': self.instance, 'flavors.list.return_value': [self.flavor], 'flavors.find.return_value': self.flavor, - 'flavors.list.return_value': [self.flavor], 'servers.add_floating_ip.return_value': mock.Mock(), 'servers.force_delete.return_value': mock.Mock(), 'aggregates.list.return_value': [self.aggregate], @@ -162,6 +161,15 @@ class OSUtilsTesting(unittest.TestCase): } self.cinder_client.configure_mock(**attrs) + self.resource = mock.Mock() + attrs = {'id': 'resource_test_id', + 'name': 'resource_test_name' + } + + self.heat_client = mock.Mock() + attrs = {'resources.get.return_value': self.resource} + self.heat_client.configure_mock(**attrs) + mock_obj = mock.Mock() attrs = {'id': 'tenant_id', 'name': 'test_tenant'} @@ -543,6 +551,36 @@ class OSUtilsTesting(unittest.TestCase): mock_glan_client.assert_called_once_with('3', session=mock_session_obj) + @mock.patch('functest.utils.openstack_utils.os.getenv', + return_value=None) + def test_get_heat_client_version_missing_env(self, mock_os_getenv): + self.assertEqual(openstack_utils.get_heat_client_version(), + openstack_utils.DEFAULT_HEAT_API_VERSION) + + @mock.patch('functest.utils.openstack_utils.logger.info') + @mock.patch('functest.utils.openstack_utils.os.getenv', return_value='1') + def test_get_heat_client_version_default(self, mock_os_getenv, + mock_logger_info): + self.assertEqual(openstack_utils.get_heat_client_version(), '1') + mock_logger_info.assert_called_once_with( + "OS_ORCHESTRATION_API_VERSION is set in env as '%s'", '1') + + def test_get_heat_client(self): + mock_heat_obj = mock.Mock() + mock_session_obj = mock.Mock() + with mock.patch('functest.utils.openstack_utils' + '.get_heat_client_version', return_value='1'), \ + mock.patch('functest.utils.openstack_utils' + '.heatclient.Client', + return_value=mock_heat_obj) \ + as mock_heat_client, \ + mock.patch('functest.utils.openstack_utils.get_session', + return_value=mock_session_obj): + self.assertEqual(openstack_utils.get_heat_client(), + mock_heat_obj) + mock_heat_client.assert_called_once_with('1', + session=mock_session_obj) + def test_get_instances_default(self): self.assertEqual(openstack_utils.get_instances(self.nova_client), [self.instance]) @@ -1700,6 +1738,24 @@ class OSUtilsTesting(unittest.TestCase): 'user_id')) self.assertTrue(mock_logger_error.called) + def test_get_resource_default(self): + with mock.patch('functest.utils.openstack_utils.' + 'is_keystone_v3', return_value=True): + self.assertEqual(openstack_utils. + get_resource(self.heat_client, + 'stack_id', + 'resource'), + self.resource) + + @mock.patch('functest.utils.openstack_utils.logger.error') + def test_get_resource_exception(self, mock_logger_error): + self.assertEqual(openstack_utils. + get_resource(Exception, + 'stack_id', + 'resource'), + None) + self.assertTrue(mock_logger_error.called) + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/functest/utils/config.py b/functest/utils/config.py index 84166c1d..b5b84501 100644..100755 --- a/functest/utils/config.py +++ b/functest/utils/config.py @@ -2,26 +2,25 @@ import os import yaml +import env + class Config(object): def __init__(self): - if 'CONFIG_FUNCTEST_YAML' not in os.environ: - raise Exception('CONFIG_FUNCTEST_YAML not configed') - self.config_functest = os.environ['CONFIG_FUNCTEST_YAML'] try: - with open(self.config_functest) as f: + with open(env.ENV.CONFIG_FUNCTEST_YAML) as f: self.functest_yaml = yaml.safe_load(f) self._parse(None, self.functest_yaml) - except: - raise Exception('Parse {} failed'.format(self.config_functest)) + except Exception as error: + raise Exception('Parse config failed: {}'.format(str(error))) self._set_others() def _parse(self, attr_now, left_parametes): for param_n, param_v in left_parametes.iteritems(): attr_further = self._get_attr_further(attr_now, param_n) - if not isinstance(param_v, dict): + if attr_further: self.__setattr__(attr_further, param_v) - else: + if isinstance(param_v, dict): self._parse(attr_further, param_v) def _get_attr_further(self, attr_now, next): @@ -33,3 +32,8 @@ class Config(object): CONF = Config() + +if __name__ == "__main__": + print CONF.vnf_cloudify_ims + print CONF.vnf_cloudify_ims_tenant_images + print CONF.vnf_cloudify_ims_tenant_images_centos_7 diff --git a/functest/utils/functest_constants.py b/functest/utils/functest_constants.py index 0a9a03b1..9fae9a9c 100644 --- a/functest/utils/functest_constants.py +++ b/functest/utils/functest_constants.py @@ -94,15 +94,6 @@ SDNVPN_REPO_DIR = get_value('general.dir.repo_sdnvpn', 'SDNVPN_REPO_DIR') SFC_REPO_DIR = get_value('general.dir.repo_sfc', 'SFC_REPO_DIR') - -ONOS_SFC_IMAGE_NAME = get_value('onos_sfc.image_name', - 'ONOS_SFC_IMAGE_NAME') -ONOS_SFC_IMAGE_FILENAME = get_value('onos_sfc.image_file_name', - 'ONOS_SFC_IMAGE_FILENAME') -ONOS_SFC_RELATIVE_PATH = get_value('general.dir.dir_onos_sfc', - 'ONOS_SFC_RELATIVE_PATH') -ONOS_SFC_IMAGE_BASE_URL = get_value('onos_sfc.image_base_url', - 'ONOS_SFC_IMAGE_BASE_URL') RALLY_RELATIVE_PATH = get_value('general.dir.rally', 'RALLY_RELATIVE_PATH') RALLY_PRIVATE_NET_NAME = get_value('rally.network_name', diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index 3093cb55..e33af63b 100755 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -18,6 +18,7 @@ from keystoneauth1 import loading from keystoneauth1 import session from cinderclient import client as cinderclient from glanceclient import client as glanceclient +from heatclient import client as heatclient from novaclient import client as novaclient from keystoneclient import client as keystoneclient from neutronclient.neutron import client as neutronclient @@ -28,6 +29,7 @@ import functest.utils.functest_utils as ft_utils logger = ft_logger.Logger("openstack_utils").getLogger() DEFAULT_API_VERSION = '2' +DEFAULT_HEAT_API_VERSION = '1' # ********************************************* @@ -241,6 +243,20 @@ def get_glance_client(other_creds={}): return glanceclient.Client(get_glance_client_version(), session=sess) +def get_heat_client_version(): + api_version = os.getenv('OS_ORCHESTRATION_API_VERSION') + if api_version is not None: + logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'", + api_version) + return api_version + return DEFAULT_HEAT_API_VERSION + + +def get_heat_client(other_creds={}): + sess = get_session(other_creds) + return heatclient.Client(get_heat_client_version(), session=sess) + + # ********************************************* # NOVA # ********************************************* @@ -985,36 +1001,43 @@ def create_security_group(neutron_client, sg_name, sg_description): def create_secgroup_rule(neutron_client, sg_id, direction, protocol, port_range_min=None, port_range_max=None): - if port_range_min is None and port_range_max is None: - json_body = {'security_group_rule': {'direction': direction, - 'security_group_id': sg_id, - 'protocol': protocol}} - elif port_range_min is not None and port_range_max is not None: - json_body = {'security_group_rule': {'direction': direction, - 'security_group_id': sg_id, - 'port_range_min': port_range_min, - 'port_range_max': port_range_max, - 'protocol': protocol}} + # We create a security group in 2 steps + # 1 - we check the format and set the json body accordingly + # 2 - we call neturon client to create the security group + + # Format check + json_body = {'security_group_rule': {'direction': direction, + 'security_group_id': sg_id, + 'protocol': protocol}} + # parameters may be + # - both None => we do nothing + # - both Not None => we add them to the json description + # but one cannot be None is the other is not None + if (port_range_min is not None and port_range_max is not None): + # add port_range in json description + json_body['security_group_rule']['port_range_min'] = port_range_min + json_body['security_group_rule']['port_range_max'] = port_range_max + logger.debug("Security_group format set (port range included)") else: - logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', " - "'%s', '%s', '%s', '%s')]:" % (neutron_client, - sg_id, direction, - port_range_min, - port_range_max, - protocol), - " Invalid values for port_range_min, port_range_max") - return False + # either both port range are set to None => do nothing + # or one is set but not the other => log it and return False + if port_range_min is None and port_range_max is None: + logger.debug("Security_group format set (no port range mentioned)") + else: + logger.error("Bad security group format." + "One of the port range is not properly set:" + "range min: {}," + "range max: {}".format(port_range_min, + port_range_max)) + return False + + # Create security group using neutron client try: neutron_client.create_security_group_rule(json_body) return True - except Exception, e: - logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', " - "'%s', '%s', '%s', '%s')]: %s" % (neutron_client, - sg_id, - direction, - port_range_min, - port_range_max, - protocol, e)) + except: + logger.exception("Impossible to create_security_group_rule," + "security group rule probably already exists") return False @@ -1383,3 +1406,15 @@ def delete_user(keystone_client, user_id): logger.error("Error [delete_user(keystone_client, '%s')]: %s" % (user_id, e)) return False + + +# ********************************************* +# HEAT +# ********************************************* +def get_resource(heat_client, stack_id, resource): + try: + resources = heat_client.resources.get(stack_id, resource) + return resources + except Exception, e: + logger.error("Error [get_resource]: %s" % e) + return None diff --git a/requirements.txt b/requirements.txt index 68b889b3..ee629eab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,6 +9,7 @@ pyyaml==3.10 gitpython==1.0.1 python-openstackclient==2.3.0 python-ceilometerclient==2.6.2 +python-heatclient==1.7.0 python-keystoneclient==3.5.0 python-neutronclient==6.0.0 python-novaclient==6.0.0 diff --git a/test-requirements.txt b/test-requirements.txt index 16466b8a..471e9c30 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -14,6 +14,7 @@ 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 |