diff options
-rw-r--r-- | docs/functest.rst | 269 | ||||
-rwxr-xr-x[-rw-r--r--] | testcases/Controllers/ODL/CI/create_venv.sh | 2 | ||||
-rw-r--r-- | testcases/Controllers/ODL/CI/custom_tests/neutron/040__delete_ports.txt | 37 | ||||
-rw-r--r-- | testcases/Controllers/ODL/CI/custom_tests/neutron/050__delete_subnets.txt | 37 | ||||
-rw-r--r-- | testcases/Controllers/ODL/CI/custom_tests/neutron/060__delete_networks.txt | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | testcases/Controllers/ODL/CI/start_tests.sh | 27 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/libraries/run_rally.py | 77 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/suites/opnfv-cinder.json | 9 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/suites/opnfv-glance.json | 44 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/suites/opnfv-nova.json | 30 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/suites/opnfv-requests.json | 24 | ||||
-rw-r--r-- | testcases/VIM/OpenStack/CI/suites/opnfv-vm.json | 16 | ||||
-rw-r--r-- | testcases/config_functest.py | 355 | ||||
-rw-r--r-- | testcases/config_functest.yaml | 37 | ||||
-rw-r--r-- | testcases/functest.yaml | 30 | ||||
-rw-r--r-- | testcases/vPing/CI/libraries/vPing.py | 213 |
16 files changed, 619 insertions, 625 deletions
diff --git a/docs/functest.rst b/docs/functest.rst index de4c537c..4b3e6db5 100644 --- a/docs/functest.rst +++ b/docs/functest.rst @@ -10,7 +10,7 @@ The goal of this document consists in * a description of the tools needed to perform these tests * the procedure to configure the tools and the scenarios associated with these tests -Functional tests shall be automated and collected results shall be used to improve the robustness and the reliability of the overall system. +Functional tests shall be automated and collected results shall be used to improve the robustness and the reliability of the overall system. Function tests may cover any domain that could lead to improve the OPNFV solution and define "Telco Cloud" KPI. @@ -33,19 +33,18 @@ ETSI NFV defined 9 use cases (ref ETSI_): Most of the use cases are also discussed in upstream projects (e.g. `Openstack Telco Working Group`_ ) -For release 1 (Arno), 5 test suites have been selected: +For release 1 (Arno), 4 test suites have been selected: * Rally Bench test suite for Openstack * Openstack Tempest test suite * OpenDaylight test suite * vPing - * vIMS The 3 first suites are directly inherited from upstream projects. -vPing, that is already present in Tempest suite, has been developped to provided a basic "hellow world" functional test example. +vPing, that is already present in Tempest suite, has been developped to provided a basic "hello world" functional test example. .. _`Continuous Integration`: https://build.opnfv.org/ci/view/functest/ -vEPC, vPE, vHGW, vCDN use cases are not considered for first release. +vIMS, vEPC, vPE, vHGW, vCDN use cases are not considered for first release. It does not mean that such use cases cannot be tested on OPNFV Arno. It means that these use cases have not been integrated in the `Continuous Integration`_ and no specific work (integration or developpment) have been done for R1. @@ -68,9 +67,7 @@ For release 1, the tools are not automatically installed. .. _pharos: https://wiki.opnfv.org/pharos It is recommended to install the different tools on the jump host server as defined in the pharos_ project. -The high level architecture can be described as follow: - -code:: +The high level architecture can be described as follow:: CIMC/Lights+out management Admin Private Public Storage PXE @@ -90,7 +87,7 @@ code:: | | | | | | | | | | | | vPing | | | | | | | | | | | | | | | - | | | vIMS | | | | | | + | | | Tempest | | | | | | | | +----------+ | | | | | | | FuncTests +-----------------------------------------+ | | | | | | | | @@ -129,7 +126,7 @@ Rally bench test suite .. _Rally: https://wiki.openstack.org/wiki/Rally -The OPNFV scenarios are based on the collection of Rally_ default scenarios: +The OPNFV scenarios are based on the collection of Rally_ scenarios: * authenticate * cinder * nova @@ -162,16 +159,17 @@ The goal of this test is to check the OpenStack installation (sanity checks). OpenDaylight ============ +TODO Peter + vPing ===== -The goal of this test can be described as follow: - -code:: +The goal of this test can be described as follow:: vPing testcase +-------------+ +-------------+ | | | | + | | | | | | Boot VM1 | | | +------------------>| | | | | | @@ -180,75 +178,121 @@ code:: | Tester | | System | | | Boot VM2 | Under | | +------------------>| Test | - | | Including Ping | | - | |at the end of boot | | + | | VM2 pings VM1 | | | | | | + | | Check console log | | + | | If ping: | | + | | exit OK | | + | | else (timeout) | | + | | exit KO | | | | | | - | | Check console | | - | | Grep Ping | | - | +------------------>| | | | | | +-------------+ +-------------+ -The vPing test case is already present in Tempest suite. +This example, using OpenStack Python clients can be considered as an "Hello World" example and may be modified for future use. -This example, using OpenStack python clients can be considered as an "hellow World" example and may be modified for future use. +.. _tooling_installation: +---------------------- +Tooling installation +---------------------- -vIMS -==== +2 external tools are needed for the functional tests on Arno: + * Rally + * Robot -vIMS is one of the testcases defined by ETSI. +Rally is used for benching and Tempest. Robot is used for OpenDaylight. -.. figure:: images/Ims_overview.png - :scale: 50 - :alt: IMS (src wikipedia) +A script (config_test.py) has been created to simplify as much as possible the installation of the different suites of tests. -the goal of this test consists in deploying a virtualized IP Multimedia Subsystem (vIMS) on OPNFV, configuring it to deliver services to a set of emulated SIP endpoints, deploying a virtualized test system that implements those emulated SIP endpoints, and performing a series of simple functional tests on the vIMS, including the ability to establish SIP sessions between emulated endpoints. +This script config_test.py_ is hosted in OPNFV git and uses the configuration file functest.yaml_:: -This functional test will verify that - * The OpenStack Nova API can be called to instantiate a set of VMs that together comprise a vIMS network function - * The OpenStack Glance service is capable of serving up the required images - * The virtual networking component of the platform can provide working IP connectivity between and among the VMs - * The platform as a whole is capable of supporting the running of a real virtualized network function that delivers a typical service offered by a network operator, i.e. voice telephony + usage: config_functest.py [-h] [-d] action -Functional testing of vIMS in OPNFV Release 1 will be limited to a basic, non-scalable and non-fault-tolerant deployment of IMS. -Furthermore, in this release the vIMS will perform only control plane functions (i.e. processing of SIP signaling messages) and will not be passing RTP media streams. + positional arguments: + action Possible actions are: 'start|check|clean' -In future releases, the same software elements can be deployed with multiple instances of each VNF component to provide a fault tolerant and dynamically scalable deployment of IMS. With the addition of virtualized Session Border Controller software elements, the scope of vIMS functional testing can be further expanded to include the handling of RTP media. + optional arguments: + -h, --help show this help message and exit + -d, --debug Debug mode -.. _clearwater: http://www.projectclearwater.org/ +Actions + * start: will prepare the functional testing environment + * check: will check the configuration (scenarios available, environment variables properly set, networks,..) + * clean: will clean the functional test environement if existing -The vIMS core function is based on the clearwater_ open source solution. +This script will: + * Install Rally environment + * Install Tempest + * Retrieve test scenarios + * Setup ODL environment + * Create temporary neutron private network + * Create router to connect both + * Create Glance images -.. _tooling_installation: +Useful links: ----------------------- -Tooling installation ----------------------- +.. _`OpenRC`: http://docs.openstack.org/user-guide/common/cli_set_environment_variables_using_openstack_rc.html -2 external tools are needed for the R1 functional tests: - * Rally - * Robot +.. _`Rally installation procedure`: https://rally.readthedocs.org/en/latest/tutorial/step_0_installation.html +.. _`config_test.py` : https://git.opnfv.org/cgit/functest/tree/testcases/config_functest.py -Rally -===== +.. _`functest.yaml` : https://git.opnfv.org/cgit/functest/tree/testcases/functest.yaml -.. _`Rally installation procedure`: https://rally.readthedocs.org/en/latest/tutorial/step_0_installation.html -.. _`OpenRC`: http://docs.openstack.org/user-guide/common/cli_set_environment_variables_using_openstack_rc.html -The Rally creation can be describe as follow (ref: `Rally installation procedure`_): - * Create or enter a folder where you want to check out the tool repos. - * $ git clone https://git.openstack.org/openstack/rally - * $ ./rally/install_rally.sh - * configure your `OpenRC`_ file to let Rally access to your OpenStack, you can either export it from Horizon or build it manually (OpenStack credentials are required) - * $ source Your_OpenRC_file - * $ rally deployment create --fromenv --name=my-opnfv-test - * $ rally-manage tempest install + + + +The procedure to set up functional testing environment can be described as follow:: + + Log on the Jumphost server + Be sure you are no root + $ wget https://git.opnfv.org/cgit/functest/plain/testcases/config_functest.py + $ wget https://git.opnfv.org/cgit/functest/plain/testcases/functest.yaml + Modify and adapt needed parameters in the functest.yaml. Follow the instructions below. + Retrieve OpenStack source file (configure your `OpenRC`_ file to let Rally access to your OpenStack, you can either export it from Horizon or build it manually (OpenStack credentials are required) + $ source Your_OpenRC_file + $ python config_functest.py -d start + +At the end of the executing, a new directory will be created ~/.functest with the following structure:: + + ~/.functest/ODL + ~/.functest/Rally_repo + ~/.functest/Rally_test + ~/.functest/vPing + ~/.functest/functest.yaml + ~/.functest/functest-img.img + +NOTE: the Rally environment will be installed under ~/.rally/ + + +HOWTO configure functest.yaml: + +Do not change the directories structure + * image_name: name of the image that will be created in Glance + * image_url: URL of the image to be downloaded + * image_disk_format: glance image disk format (raw, qcow2, ...) + + * neutron_private_net_name: name of an OpenStack private network. If not existing, it will be created + * neutron_private_subnet_name: private subnet network to be created if not existing + * neutron_private_subnet_cidr: range of the private subnet. + * neutron_private_subnet_start: start IP + * neutron_private_subnet_end: end IP + * neutron_router_name: name of the router between the private and the public networks + + * ping_timeout: time out of the vPing test case + * vm_flavor: name of the flavor used to create the VMs + * vm_name_1: name of the first VM + * vm_name_2: name of the second VM + + +Please note that you need to install this environment only once. Until the credentials of the System Under Test are not changing, the testing environment shall be fine. + +If you need more details on Rally installation, see `Rally installation procedure`_. You can check if the configuration of rally is fine by typing 'rally deployment check', you shall see the list of available services as follow:: @@ -272,7 +316,6 @@ You can check if the configuration of rally is fine by typing 'rally deployment | UUID | Name | Size (B) | +--------------------------------------+----------------------------------------------+------------+ | 0a15951f-6388-4d5d-8531-79e7205eb140 | cirros_2015_04_10_13_13_18 | 13167616 | - | 67734efd-75f6-4919-991e-bba9855f3ae1 | Ubuntu 12.04 64b | 260637184 | | b1504066-045a-4f8f-8919-8c665ef3f400 | Ubuntu 14.04 64b | 253297152 | +--------------------------------------+----------------------------------------------+------------+ @@ -286,55 +329,14 @@ You can check if the configuration of rally is fine by typing 'rally deployment | accdc28c-5e20-4859-a5cc-61cf9009e56d | m1.small | 1 | 512 | | 10 | +--------------------------------------+---------------------+-------+----------+-----------+-----------+ -Robot -===== -Summary: Set up python2.7 virtual environment:: - - mkvirtualenv robot - - pip install requests - pip install robotframework - pip install robotframework-sshlibrary - pip install robotframework-requests - - -vPing -===== - -Make sure that nova services are up:: - - #nova service list - +----+----------------+--------+----------+---------+-------+ - | Id | Binary | Host | Zone | Status | State | - +----+----------------+--------+----------+---------+-------+ - | 1 | nova-conductor | xxxxxx | internal | enabled | up | - | 3 | nova-network | xxxxxx | internal | enabled | up | - | 4 | nova-scheduler | xxxxxx | internal | enabled | up | - | 5 | nova-compute | xxxxxx | nova | enabled | up | - +----+----------------+--------+----------+---------+-------+ - - -.. _vPing.py: https://git.opnfv.org/cgit/functest/tree/testcases/vPing/CI/libraries/vPing.py - -Retrieve vPing.py_ script from OPNFV git repo - -Make sure you have sourced your OpenRC file:: - - # source Your_OpenRC_file - ------------------------------- -Functional test configuration ------------------------------- +-------------- +Manual testing +-------------- Rally bench suite ================= -Rally bench scenarios have been aggregated in json files. -A script has been developed to simplify the management of the tests and the integration in CI, get it from git:: - - # wget https://git.opnfv.org/cgit/functest/tree/testcases/VIM/OpenStack/CI/libraries/run_rally.py - -Several scenarios are available (all based on native Rally scenarios): +Several scenarios are available (mainly based on native Rally scenarios): * glance * nova * authenticate @@ -344,7 +346,8 @@ Several scenarios are available (all based on native Rally scenarios): * quotas * request * tempest - * all (every module except tempest) + * smoke + * all (every module except tempest and smoke) You can run the script as follow:: @@ -376,27 +379,6 @@ ODL wiki page describes system preparation and running tests. See `Integration G .. _`Integration Group CSIT`: https://wiki.opendaylight.org/view/CrossProject:Integration_Group:CSIT -vPing -===== - -By default, the script’s is configured as follow:: - - * OS_USERNAME: admin - * OS_PASSWORD: test - * OS_AUTH_URL: http://192.168.20.71:5000/v2.0 - * OS_TENANT_NAME: invisible_to_admin - * Name of VM: opnfv-vping-1 , opnfv-vping-2 - * Flavor: m1.small - * Image: Ubuntu 14.04 (amd64) - * Network: private - -The script needs to be tuned to your specific system configuration - -vIMS -==== - - - .. _manualtest: -------------- @@ -415,24 +397,53 @@ You can get the results of tempest by typing:: # rally verify list +You shall see the results as follow:: + + Total results of verification: + + +--------------------------------------+--------------------------------------+----------+-------+----------+----------------------------+----------+ + | UUID | Deployment UUID | Set name | Tests | Failures | Created at | Status | + +--------------------------------------+--------------------------------------+----------+-------+----------+----------------------------+----------+ + | 0144c50f-ab03-45fb-9c36-242ad6440b46 | d9e1bb21-8e36-4d89-b137-0c852dbb308e | smoke | 87 | 32 | 2015-05-05 16:36:00.986003 | finished | + +--------------------------------------+--------------------------------------+----------+-------+----------+----------------------------+----------+ + +If you run this test several times, you will see as many lines as test attempts. +You can get more details on the test by typing:: + # rally verify show --uuid <UUID of the test> + # rally verify detailed --uuid <UUID of the test> + +"show" will show you all the restults including the time needed to execute the test. +"detailed" will display additional elements (errors) + +Example of test result display:: + + +------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ + | name | time | status | + +------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+--------+ + | tempest.api.network.test_routers.RoutersTest.test_create_show_list_update_delete_router[id-f64403e2-8483-4b34-8ccd-b09a87bcc68c,smoke] | 0.011466 | FAIL | + | tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_list_update_show_delete_security_group[id-bfd128e5-3c92-44b6-9d66-7fe29d22c802,smoke]| 1.234566 | OK | + | tempest.api.network.test_security_groups.SecGroupIPv6Test.test_create_show_delete_security_group_rule[id-cfb99e0e-7410-4a3d-8a0c-959a63ee77e9,smoke] | 1.060221 | OK | + | tempest.api.network.test_security_groups.SecGroupIPv6Test.test_list_security_groups[id-e30abd17-fef9-4739-8617-dc26da88e686,smoke] | 0.060797 | OK | + | tempest.api.network.test_security_groups.SecGroupTest.test_create_list_update_show_delete_security_group[id-bfd128e5-3c92-44b6-9d66-7fe29d22c802,smoke] | 0.685149 | OK | + | tempest.api.network.test_security_groups.SecGroupTest.test_create_show_delete_security_group_rule[id-cfb99e0e-7410-4a3d-8a0c-959a63ee77e9,smoke] | 0.730561 | OK | + | tempest.api.network.test_security_groups.SecGroupTest.test_list_security_groups[id-e30abd17-fef9-4739-8617-dc26da88e686,smoke] | 0.116862 | OK | + | tempest.api.object_storage.test_account_quotas.AccountQuotasTest | 0.0 | SKIP | + | ... | ... | ... | OpenDaylight ============ Tests can be executed with script *start_test.sh* from directory *functest/testcases/Controllers/ODL/CI*. For usage example see:: - # bash start_test.sh -h + # bash ~./.functest/ODL/start_test.sh -h vPing ===== The test can be executed with command:: - #python vPing.py - -vIMS -==== + #python ~./.functest/vPing.py -d .. _automatictest: diff --git a/testcases/Controllers/ODL/CI/create_venv.sh b/testcases/Controllers/ODL/CI/create_venv.sh index 5d0733a5..19d9b49c 100644..100755 --- a/testcases/Controllers/ODL/CI/create_venv.sh +++ b/testcases/Controllers/ODL/CI/create_venv.sh @@ -13,7 +13,7 @@ function venv_install() { elif command -v virtualenv; then virtualenv $1 else - echo Please make sure virtualenv package is installed. + echo Cannot find virtualenv command. return 1 fi } diff --git a/testcases/Controllers/ODL/CI/custom_tests/neutron/040__delete_ports.txt b/testcases/Controllers/ODL/CI/custom_tests/neutron/040__delete_ports.txt new file mode 100644 index 00000000..1fc3fc41 --- /dev/null +++ b/testcases/Controllers/ODL/CI/custom_tests/neutron/040__delete_ports.txt @@ -0,0 +1,37 @@ +*** Settings *** +Documentation Checking Port deleted in OpenStack are deleted also in OpenDaylight +Suite Setup Create Session OSSession http://${OPENSTACK}:9696 headers=${X-AUTH} +Suite Teardown Delete All Sessions +Library SSHLibrary +Library Collections +Library OperatingSystem +Library ../../../libraries/RequestsLibrary.py +Library ../../../libraries/Common.py +Variables ../../../variables/Variables.py + +*** Variables *** +${ODLREST} /controller/nb/v2/neutron/ports +${OSREST} /v2.0/ports/${PORTID} +${data} {"port":{"network_id":"${NETID}","admin_state_up": true}} + +*** Test Cases *** +Delete New Port + [Documentation] Delete previously created port in OpenStack + [Tags] Delete port OpenStack Neutron + Log ${data} + ${resp} delete OSSession ${OSREST} + Should be Equal As Strings ${resp.status_code} 204 + Log ${resp.content} + sleep 2 + +Check Port Deleted + [Documentation] Check port deleted in OpenDaylight + [Tags] Check port deleted OpenDaylight + Create Session ODLSession http://${CONTROLLER}:${PORT} headers=${HEADERS} auth=${AUTH} + ${resp} get ODLSession ${ODLREST} + Should be Equal As Strings ${resp.status_code} 200 + ${ODLResult} To Json ${resp.content} + Set Suite Variable ${ODLResult} + Log ${ODLResult} + ${resp} get ODLSession ${ODLREST}/${PORTID} + Should be Equal As Strings ${resp.status_code} 204 diff --git a/testcases/Controllers/ODL/CI/custom_tests/neutron/050__delete_subnets.txt b/testcases/Controllers/ODL/CI/custom_tests/neutron/050__delete_subnets.txt new file mode 100644 index 00000000..33878636 --- /dev/null +++ b/testcases/Controllers/ODL/CI/custom_tests/neutron/050__delete_subnets.txt @@ -0,0 +1,37 @@ +*** Settings *** +Documentation Checking Subnets deleted in OpenStack are deleted also in OpenDaylight +Suite Setup Create Session OSSession http://${OPENSTACK}:9696 headers=${X-AUTH} +Suite Teardown Delete All Sessions +Library SSHLibrary +Library Collections +Library OperatingSystem +Library ../../../libraries/RequestsLibrary.py +Library ../../../libraries/Common.py +Variables ../../../variables/Variables.py + +*** Variables *** +${ODLREST} /controller/nb/v2/neutron/subnets +${OSREST} /v2.0/subnets/${SUBNETID} +${data} {"subnet":{"network_id":"${NETID}","ip_version":4,"cidr":"172.16.64.0/24","allocation_pools":[{"start":"172.16.64.20","end":"172.16.64.120"}]}} + +*** Test Cases *** +Delete New subnet + [Documentation] Delete previously created subnet in OpenStack + [Tags] Delete Subnet OpenStack Neutron + Log ${data} + ${resp} delete OSSession ${OSREST} + Should be Equal As Strings ${resp.status_code} 204 + Log ${resp.content} + sleep 2 + +Check New subnet deleted + [Documentation] Check subnet deleted in OpenDaylight + [Tags] Check subnet deleted OpenDaylight + Create Session ODLSession http://${CONTROLLER}:${PORT} headers=${HEADERS} auth=${AUTH} + ${resp} get ODLSession ${ODLREST} + Should be Equal As Strings ${resp.status_code} 200 + ${ODLResult} To Json ${resp.content} + Set Suite Variable ${ODLResult} + Log ${ODLResult} + ${resp} get ODLSession ${ODLREST}/${SUBNETID} + Should be Equal As Strings ${resp.status_code} 204 diff --git a/testcases/Controllers/ODL/CI/custom_tests/neutron/060__delete_networks.txt b/testcases/Controllers/ODL/CI/custom_tests/neutron/060__delete_networks.txt new file mode 100644 index 00000000..106ac80e --- /dev/null +++ b/testcases/Controllers/ODL/CI/custom_tests/neutron/060__delete_networks.txt @@ -0,0 +1,37 @@ +*** Settings *** +Documentation Checking Network deleted in OpenStack are deleted also in OpenDaylight +Suite Setup Create Session OSSession http://${OPENSTACK}:9696 headers=${X-AUTH} +Suite Teardown Delete All Sessions +Library SSHLibrary +Library Collections +Library OperatingSystem +Library ../../../libraries/RequestsLibrary.py +Library ../../../libraries/Common.py +Variables ../../../variables/Variables.py + +*** Variables *** +${ODLREST} /controller/nb/v2/neutron/networks +${OSREST} /v2.0/networks/${NETID} +${postNet} {"network":{"name":"odl_network","admin_state_up":true}} + +*** Test Cases *** +Delete Network + [Documentation] Delete network in OpenStack + [Tags] Delete Network OpenStack Neutron + Log ${postNet} + ${resp} delete OSSession ${OSREST} + Should be Equal As Strings ${resp.status_code} 204 + Log ${resp.content} + sleep 2 + +Check Network deleted + [Documentation] Check Network deleted in OpenDaylight + [Tags] Check Network OpenDaylight + Create Session ODLSession http://${CONTROLLER}:${PORT} headers=${HEADERS} auth=${AUTH} + ${resp} get ODLSession ${ODLREST} + Should be Equal As Strings ${resp.status_code} 200 + ${ODLResult} To Json ${resp.content} + Set Suite Variable ${ODLResult} + Log ${ODLResult} + ${resp} get ODLSession ${ODLREST}/${NetID} + Should be Equal As Strings ${resp.status_code} 204 diff --git a/testcases/Controllers/ODL/CI/start_tests.sh b/testcases/Controllers/ODL/CI/start_tests.sh index 367a075f..7bc0b513 100644..100755 --- a/testcases/Controllers/ODL/CI/start_tests.sh +++ b/testcases/Controllers/ODL/CI/start_tests.sh @@ -17,11 +17,11 @@ usage: where: -h show this help text - var one of the following: OSTACK_IP, ODL_PORT, USR_NAME, USR_PASSWORD + var one of the following: ODL_IP, ODL_PORT, USR_NAME, PASS, NEUTRON_IP value new value for var example: - OSTACK_IP=oscontro1 ODL_PORT=8080 bash $(basename "$0")" + ODL_IP=oscontro1 ODL_PORT=8080 bash $(basename "$0")" while getopts ':h' option; do case "$option" in @@ -38,24 +38,25 @@ done echo -e "${green}Current environment parameters for ODL suite.${nc}" # Following vars might be also specified as CLI params set -x -OSTACK_IP=${OSTACK_IP:-'oscontrol'} +ODL_IP=${ODL_IP:-'192.168.1.5'} ODL_PORT=${ODL_PORT:-8081} -USR_NAME=${USR_NAME:-'admin'} -USR_PASSWORD=${USR_PASSWORD:-'octopus'} +USR_NAME=${USR_NAME:-'neutron'} +PASS=${PASS:-'octopus'} +NEUTRON_IP=${NEUTRON_IP:-192.168.0.68} set +x echo -e "${green}Cloning ODL integration git repo.${nc}" -if [ -d integration ]; then - cd integration +if [ -d ${BASEDIR}/integration ]; then + cd ${BASEDIR}/integration git checkout -- . git pull cd - else - git clone https://github.com/opendaylight/integration.git + git clone https://github.com/opendaylight/integration.git ${BASEDIR}/integration fi # Change openstack password for admin tenant in neutron suite -sed -i "s/\"password\": \"admin\"/\"password\": \"${USR_PASSWORD}\"/" integration/test/csit/suites/openstack/neutron/__init__.robot +sed -i "s/\"password\": \"admin\"/\"password\": \"${PASS}\"/" ${BASEDIR}/integration/test/csit/suites/openstack/neutron/__init__.robot if source $BASEDIR/venv/bin/activate; then echo -e "${green}Python virtualenv activated.${nc}" @@ -64,6 +65,10 @@ else exit 1 fi +# add custom tests to suite, if there are more custom tests needed this will be reworked +echo -e "${green}Copy custom tests to suite.${nc}" +cp -vf $BASEDIR/custom_tests/neutron/* $BASEDIR/integration/test/csit/suites/openstack/neutron/ + # List of tests are specified in test_list.txt # those are relative paths to test directories from integartion suite echo -e "${green}Executing chosen tests.${nc}" @@ -76,13 +81,13 @@ do [[ -z "${line}" ]] && continue echo -e "${light_green}Starting test: $line ${nc}" - pybot -v OPENSTACK:${OSTACK_IP} -v PORT:${ODL_PORT} -v CONTROLLER:${OSTACK_IP} $line + pybot -v OPENSTACK:${NEUTRON_IP} -v PORT:${ODL_PORT} -v CONTROLLER:${ODL_IP} ${BASEDIR}/$line mkdir -p $BASEDIR/logs/${test_num} mv log.html $BASEDIR/logs/${test_num}/ mv report.html $BASEDIR/logs/${test_num}/ mv output.xml $BASEDIR/logs/${test_num}/ ((test_num++)) -done < test_list.txt +done < ${BASEDIR}/test_list.txt echo -e "${green}Deactivate venv.${nc}" deactivate diff --git a/testcases/VIM/OpenStack/CI/libraries/run_rally.py b/testcases/VIM/OpenStack/CI/libraries/run_rally.py index 2bfb8127..341281a2 100644 --- a/testcases/VIM/OpenStack/CI/libraries/run_rally.py +++ b/testcases/VIM/OpenStack/CI/libraries/run_rally.py @@ -10,24 +10,24 @@ # import re, json, os, urllib2, argparse, logging, yaml -with open('../functest.yaml') as f: - functest_yaml = yaml.safe_load(f) -f.close() -HOME = os.environ['HOME']+"/" -SCENARIOS_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_scn") -RESULTS_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_res") + +""" get the date """ +cmd = os.popen("date '+%d%m%Y_%H%M'") +test_date = cmd.read().rstrip() + """ tests configuration """ -tests = ['authenticate', 'glance', 'cinder', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'tempest', 'vm', 'all', 'smoke'] +tests = ['authenticate', 'glance', 'cinder', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'vm', 'tempest', 'all', 'smoke'] parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") parser.add_argument("test_name", help="The name of the test you want to perform with rally. " "Possible values are : " "[ {d[0]} | {d[1]} | {d[2]} | {d[3]} | {d[4]} | {d[5]} | {d[6]} " - "| {d[7]} | {d[8]} | {d[9]} | {d[10]} | {d[11]} | {d[12]}]. The 'all' value performs all the tests scenarios " + "| {d[7]} | {d[8]} | {d[9]} | {d[10]} | {d[11]} | {d[12]}]. The 'all' value performs all the possible tests scenarios" "except 'tempest'".format(d=tests)) - parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") + parser.add_argument("test_mode", help="Tempest test mode", nargs='?', default="smoke") args = parser.parse_args() test_mode=args.test_mode @@ -50,6 +50,17 @@ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(messag ch.setFormatter(formatter) logger.addHandler(ch) +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +HOME = os.environ['HOME']+"/" +REPO_PATH = args.repo_path +SCENARIOS_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_rally_scn") +RESULTS_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_res") + test_date + "/" + + + def get_tempest_id(cmd_raw): """ @@ -95,7 +106,7 @@ def task_succeed(json_raw): return False for result in rally_report.get('result'): - if len(result.get('errors')) > 0: + if len(result.get('error')) > 0: return False return True @@ -108,10 +119,6 @@ def run_tempest(): """ logger.info('starting {} Tempest ...'.format(test_mode)) - """ get the date """ - cmd = os.popen("date '+%d%m%Y_%H%M'") - test_date = cmd.read().rstrip() - cmd_line = "rally verify start {}".format(test_mode) logger.debug('running command line : {}'.format(cmd_line)) cmd = os.popen(cmd_line) @@ -128,7 +135,7 @@ def run_tempest(): os.makedirs(RESULTS_DIR) """ write log report file """ - report_file_name = '{}opnfv-tempest-{}.log'.format(RESULTS_DIR, test_date) + report_file_name = '{}opnfv-tempest.log'.format(RESULTS_DIR) cmd_line = "rally verify detailed {} > {} ".format(task_id, report_file_name) logger.debug('running command line : {}'.format(cmd_line)) os.popen(cmd_line) @@ -142,16 +149,12 @@ def run_task(test_name): """ logger.info('starting {} test ...'.format(test_name)) - """ get the date """ - cmd = os.popen("date '+%d%m%Y_%H%M'") - test_date = cmd.read().rstrip() - """ check directory for scenarios test files or retrieve from git otherwise""" proceed_test = True test_file_name = '{}opnfv-{}.json'.format(SCENARIOS_DIR, test_name) if not os.path.exists(test_file_name): - logger.debug('{} does not exists'.format(test_file_name)) - proceed_test = retrieve_test_cases_file(test_name, SCENARIOS_DIR) + logger.error("The scenario '%s' does not exist." %test_file_name) + exit(-1) """ we do the test only if we have a scenario test file """ if proceed_test: @@ -172,7 +175,7 @@ def run_task(test_name): os.makedirs(RESULTS_DIR) """ write html report file """ - report_file_name = '{}opnfv-{}-{}.html'.format(RESULTS_DIR, test_name, test_date) + report_file_name = '{}opnfv-{}.html'.format(RESULTS_DIR, test_name) cmd_line = "rally task report %s --out %s" % (task_id, report_file_name) logger.debug('running command line : {}'.format(cmd_line)) os.popen(cmd_line) @@ -182,7 +185,7 @@ def run_task(test_name): logger.debug('running command line : {}'.format(cmd_line)) cmd = os.popen(cmd_line) json_results = cmd.read() - with open('{}opnfv-{}-{}.json'.format(RESULTS_DIR, test_name, test_date), 'w') as f: + with open('{}opnfv-{}.json'.format(RESULTS_DIR, test_name), 'w') as f: logger.debug('saving json file') f.write(json_results) logger.debug('saving json file2') @@ -196,32 +199,6 @@ def run_task(test_name): logger.error('{} test failed, unable to fetch a scenario test file'.format(test_name)) -def retrieve_test_cases_file(test_name, tests_path): - """ - Retrieve from github the sample test files - :return: Boolean that indicates the retrieval status - """ - - """ do not add the "/" at the end """ - url_base = "https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/suites" - - test_file_name = 'opnfv-{}.json'.format(test_name) - logger.info('fetching {}/{} ...'.format(url_base, test_file_name)) - - try: - response = urllib2.urlopen('{}/{}'.format(url_base, test_file_name)) - except (urllib2.HTTPError, urllib2.URLError): - return False - file_raw = response.read() - - """ check if the test path exist otherwise we create it """ - if not os.path.exists(tests_path): - os.makedirs(tests_path) - - with open('{}/{}'.format(tests_path, test_file_name), 'w') as f: - f.write(file_raw) - return True - def main(): """ configure script """ @@ -231,7 +208,7 @@ def main(): if args.test_name == "all": for test_name in tests: - if not (test_name == 'all' or test_name == 'tempest'): + if not (test_name == 'all' or test_name == 'tempest' or test_name == 'heat' or test_name == 'smoke' or test_name == 'vm' ): print(test_name) run_task(test_name) else: diff --git a/testcases/VIM/OpenStack/CI/suites/opnfv-cinder.json b/testcases/VIM/OpenStack/CI/suites/opnfv-cinder.json index 95805518..4fc3f769 100644 --- a/testcases/VIM/OpenStack/CI/suites/opnfv-cinder.json +++ b/testcases/VIM/OpenStack/CI/suites/opnfv-cinder.json @@ -4,7 +4,7 @@ "args": { "size": 10, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "flavor": { "name": "m1.tiny" @@ -149,7 +149,7 @@ "args": { "size": 1, "image": { - "name": "^TestVM*" + "name": "^functest-img*" } }, "runner": { @@ -210,7 +210,7 @@ }, "servers": { "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "flavor": { "name": "m1.tiny" @@ -241,7 +241,7 @@ }, "servers": { "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "flavor": { "name": "m1.tiny" @@ -292,4 +292,3 @@ } ] } - diff --git a/testcases/VIM/OpenStack/CI/suites/opnfv-glance.json b/testcases/VIM/OpenStack/CI/suites/opnfv-glance.json index 1359fff5..68d56134 100644 --- a/testcases/VIM/OpenStack/CI/suites/opnfv-glance.json +++ b/testcases/VIM/OpenStack/CI/suites/opnfv-glance.json @@ -1,4 +1,25 @@ { + "GlanceImages.list_images": [ + { + "runner": { + "type": "constant", + "times": 10, + "concurrency": 1 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + }, + "images": { + "image_url": "http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-disk.img", + "image_type": "qcow2", + "image_container": "bare", + "images_per_tenant": 4 + } + } + } + ], "GlanceImages.create_and_delete_image": [ { "args": { @@ -46,7 +67,7 @@ "container_format": "bare", "disk_format": "qcow2", "flavor": { - "name": "m1.nano" + "name": "m1.small" }, "number_instances": 2 }, @@ -62,26 +83,5 @@ } } } - ], - "GlanceImages.list_images": [ - { - "runner": { - "type": "constant", - "times": 10, - "concurrency": 1 - }, - "context": { - "users": { - "tenants": 2, - "users_per_tenant": 2 - }, - "images": { - "image_url": "http://download.cirros-cloud.net/0.3.1/cirros-0.3.1-x86_64-disk.img", - "image_type": "qcow2", - "image_container": "bare", - "images_per_tenant": 4 - } - } - } ] } diff --git a/testcases/VIM/OpenStack/CI/suites/opnfv-nova.json b/testcases/VIM/OpenStack/CI/suites/opnfv-nova.json index 2c56777d..09ca4108 100644 --- a/testcases/VIM/OpenStack/CI/suites/opnfv-nova.json +++ b/testcases/VIM/OpenStack/CI/suites/opnfv-nova.json @@ -6,7 +6,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "force_delete": false }, @@ -30,7 +30,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" } }, "runner": { @@ -56,7 +56,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "security_group_count": 10, "rules_per_security_group": 10 @@ -84,7 +84,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "detailed": true }, @@ -108,7 +108,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "block_migration": false }, @@ -132,7 +132,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" } }, "runner": { @@ -155,7 +155,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "force_delete": false, "actions": [ @@ -185,7 +185,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "volume_size": 10, "force_delete": false @@ -210,7 +210,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "volume_size": 10 }, @@ -234,7 +234,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" } }, "runner": { @@ -256,7 +256,7 @@ "size": 10, "block_migration": false, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "flavor": { "name": "m1.small" @@ -282,7 +282,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "block_migration": false, "volume_size": 10, @@ -308,7 +308,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "force_delete": false }, @@ -413,7 +413,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "servers_per_tenant": 2 } @@ -427,7 +427,7 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "to_flavor": { "name": "m1.small" diff --git a/testcases/VIM/OpenStack/CI/suites/opnfv-requests.json b/testcases/VIM/OpenStack/CI/suites/opnfv-requests.json index 9936e2fd..ead457db 100644 --- a/testcases/VIM/OpenStack/CI/suites/opnfv-requests.json +++ b/testcases/VIM/OpenStack/CI/suites/opnfv-requests.json @@ -1,9 +1,26 @@ { - "Requests.check_response": [ + "HttpRequests.check_random_request": [ { "args": { - "url": "http://www.google.com", - "response": 302 + "requests": [{"url": "http://www.example.com", "method": "GET", + "status_code": 200}, + {"url": "http://www.openstack.org", "method": "GET"}], + "status_code": 200 + }, + "runner": { + "type": "constant", + "times": 20, + "concurrency": 5 + } + } + ], + "HttpRequests.check_request": [ + { + "args": { + "url": "http://www.example.com", + "method": "GET", + "status_code": 200, + "allow_redirects": false }, "runner": { "type": "constant", @@ -13,4 +30,3 @@ } ] } - diff --git a/testcases/VIM/OpenStack/CI/suites/opnfv-vm.json b/testcases/VIM/OpenStack/CI/suites/opnfv-vm.json index f197ef6b..f50cf2b2 100644 --- a/testcases/VIM/OpenStack/CI/suites/opnfv-vm.json +++ b/testcases/VIM/OpenStack/CI/suites/opnfv-vm.json @@ -6,13 +6,13 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, - "floating_network": "public", + "floating_network": "net04_ext", "force_delete": false, - "script": "samples/tasks/support/instance_dd_test.sh", + "script": "../Rally_repo/samples/tasks/support/instance_dd_test.sh", "interpreter": "/bin/sh", - "username": "cirros" + "username": "admin" }, "runner": { "type": "constant", @@ -36,18 +36,18 @@ "name": "m1.small" }, "image": { - "name": "^TestVM*" + "name": "^functest-img*" }, "volume_args": { "size": 2 }, "fixed_network": "private", - "floating_network": "public", + "floating_network": "net04_ext", "use_floatingip": true, "force_delete": false, - "script": "samples/tasks/support/instance_dd_test.sh", + "script": "../Rally_repo/samples/tasks/support/instance_dd_test.sh", "interpreter": "/bin/sh", - "username": "cirros" + "username": "admin" }, "runner": { "type": "constant", diff --git a/testcases/config_functest.py b/testcases/config_functest.py index 05376be2..5a3fcbb3 100644 --- a/testcases/config_functest.py +++ b/testcases/config_functest.py @@ -8,18 +8,17 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -import re, json, os, urllib2, argparse, logging, shutil, subprocess, yaml +import re, json, os, urllib2, argparse, logging, shutil, subprocess, yaml, sys from git import Repo from neutronclient.v2_0 import client actions = ['start', 'check', 'clean'] - - - parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") parser.add_argument("action", help="Possible actions are: '{d[0]}|{d[1]}|{d[2]}' ".format(d=actions)) parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +parser.add_argument("-f", "--force", help="Force", action="store_true") args = parser.parse_args() @@ -37,142 +36,119 @@ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(messag ch.setFormatter(formatter) logger.addHandler(ch) +if not os.path.exists(args.repo_path): + logger.error("Repo directory not found '%s'" % args.repo_path) + exit(-1) - -yaml_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/functest.yaml' -name = yaml_url.rsplit('/')[-1] -dest = "./" + name -if not os.path.exists(dest): - logger.info("Downloading functest.yaml...") - try: - response = urllib2.urlopen(yaml_url) - except (urllib2.HTTPError, urllib2.URLError): - logger.error("Error in fetching %s" %yaml_url) - exit(-1) - with open(dest, 'wb') as f: - f.write(response.read()) - logger.info("functest.yaml stored in %s" % dest) -else: - logger.info("functest.yaml found in %s" % dest) - - -with open('./functest.yaml') as f: +with open(args.repo_path+"testcases/config_functest.yaml") as f: functest_yaml = yaml.safe_load(f) f.close() + + """ global variables """ +# Directories HOME = os.environ['HOME']+"/" -FUNCTEST_BASE_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_functest") +REPO_PATH = args.repo_path +RALLY_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_rally") RALLY_REPO_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_repo") -RALLY_TEST_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally") RALLY_INSTALLATION_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_inst") -BENCH_TESTS_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_scn") -VPING_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_vping") -ODL_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_odl") -NEUTRON_PUBLIC_NAME = functest_yaml.get("general").get("openstack").get("neutron_public_net_name") -NEUTRON_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_net_name") -NEUTRON_SUBNET_NAME = functest_yaml.get("general").get("openstack").get("neutron_subnet_name") -NEUTRON_RANGE = functest_yaml.get("general").get("openstack").get("neutron_subnet_range") +VPING_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_vping") +ODL_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_odl") + +# NEUTRON Private Network parameters +NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_net_name") +NEUTRON_PRIVATE_SUBNET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_name") +NEUTRON_PRIVATE_SUBNET_CIDR = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_cidr") ROUTER_NAME = functest_yaml.get("general").get("openstack").get("neutron_router_name") +#GLANCE image parameters IMAGE_URL = functest_yaml.get("general").get("openstack").get("image_url") IMAGE_DISK_FORMAT = functest_yaml.get("general").get("openstack").get("image_disk_format") IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name") IMAGE_FILE_NAME = IMAGE_URL.rsplit('/')[-1] -IMAGE_DOWNLOAD_PATH = FUNCTEST_BASE_DIR + IMAGE_FILE_NAME +IMAGE_DIR = HOME + functest_yaml.get("general").get("openstack").get("image_download_path") +IMAGE_PATH = IMAGE_DIR + IMAGE_FILE_NAME -def config_functest_start(): +credentials = None +neutron_client = None + +def action_start(): """ Start the functest environment installation """ - #if config_functest_check(): - # logger.info("Functest environment already installed in %s. Nothing to do." %FUNCTEST_BASE_DIR) - # exit(0) if not check_internet_connectivity(): logger.error("There is no Internet connectivity. Please check the network configuration.") exit(-1) - elif not check_credentials(): - logger.error("Please source the openrc credentials and run the script again.") - #TODO: source the credentials in this script - exit(-1) - elif not check_neutron_net(NEUTRON_PUBLIC_NAME): - #The public network is normally created by default, no need to create a new one - logger.debug("Public network '%s' not found." % NEUTRON_PUBLIC_NAME) - logger.error("A public Neutron network is needed for the environment. Please create one.") - #TODO: source the credentials in this script - exit(-1) - else: - # Clean in case there are left overs - config_functest_clean() - logger.info("Starting installationg of functest environment in %s" % FUNCTEST_BASE_DIR) - os.makedirs(FUNCTEST_BASE_DIR) - if not os.path.exists(FUNCTEST_BASE_DIR): - logger.error("There has been a problem while creating the environment directory.") - exit(-1) + if action_check(): + logger.info("Functest environment already installed. Nothing to do.") + exit(0) - logger.info("Donwloading test scripts and scenarios...") - if not download_tests(): - logger.error("There has been a problem while downloading the test scripts and scenarios.") - config_functest_clean() - exit(-1) + else: + # Clean in case there are left overs + logger.debug("Cleaning possible functest environment leftovers.") + action_clean() + logger.info("Starting installation of functest environment") logger.info("Installing Rally...") if not install_rally(): logger.error("There has been a problem while installing Rally.") - config_functest_clean() + action_clean() exit(-1) logger.info("Installing ODL environment...") if not install_odl(): logger.error("There has been a problem while installing Robot.") - config_functest_clean() + action_clean() exit(-1) - logger.info("Creating a private Neutron network...") - logger.debug("Checking if private network '%s' exists..." % NEUTRON_NET_NAME) - #Now: if exists we don't create it again (the clean command does not clean the neutron network) - #TODO: this check will not be needed when cleaning the neutron is implemented - if check_neutron_net(NEUTRON_NET_NAME): - logger.info("Private network '%s' found. No need to create another one." % NEUTRON_NET_NAME) + credentials = get_credentials() + neutron_client = client.Client(**credentials) + + logger.info("Configuring Neutron...") + logger.info("Checking if private network '%s' exists..." % NEUTRON_PRIVATE_NET_NAME) + #Now: if exists we don't create it again (the clean command does not clean the neutron networks yet) + if check_neutron_net(neutron_client, NEUTRON_PRIVATE_NET_NAME): + logger.info("Private network '%s' found. No need to create another one." % NEUTRON_PRIVATE_NET_NAME) else: - logger.info("Private network '%s' not found. Creating..." % NEUTRON_NET_NAME) - if not create_neutron_net(): + logger.info("Private network '%s' not found. Creating..." % NEUTRON_PRIVATE_NET_NAME) + if not create_private_neutron_net(neutron_client): logger.error("There has been a problem while creating the Neutron network.") - #config_functest_clean() + #action_clean() exit(-1) logger.info("Donwloading image...") - if not download_url_with_progress(IMAGE_URL, FUNCTEST_BASE_DIR): + if not download_url(IMAGE_URL, IMAGE_DIR): logger.error("There has been a problem while downloading the image.") - config_functest_clean() + action_clean() exit(-1) logger.info("Creating Glance image: %s ..." %IMAGE_NAME) - if not create_glance_image(IMAGE_DOWNLOAD_PATH,IMAGE_NAME,IMAGE_DISK_FORMAT): + if not create_glance_image(IMAGE_PATH,IMAGE_NAME,IMAGE_DISK_FORMAT): logger.error("There has been a problem while creating the Glance image.") - config_functest_clean() + action_clean() exit(-1) exit(0) - -def config_functest_check(): +def action_check(): """ Check if the functest environment is properly installed """ errors_all = False logger.info("Checking current functest configuration...") - + credentials = get_credentials() + neutron_client = client.Client(**credentials) logger.debug("Checking directories...") errors = False - dirs = [FUNCTEST_BASE_DIR, RALLY_INSTALLATION_DIR, RALLY_REPO_DIR, RALLY_TEST_DIR, BENCH_TESTS_DIR, VPING_DIR, ODL_DIR] + dirs = [RALLY_DIR, RALLY_INSTALLATION_DIR, VPING_DIR, ODL_DIR] for dir in dirs: if not os.path.exists(dir): logger.debug("The directory '%s' does NOT exist." % dir) @@ -188,7 +164,7 @@ def config_functest_check(): logger.debug("Checking Rally deployment...") if not check_rally(): - logger.debug("Rally deployment NOT found.") + logger.debug(" Rally deployment NOT found.") errors_all = True logger.debug("...FAIL") else: @@ -196,35 +172,23 @@ def config_functest_check(): logger.debug("Checking Neutron...") - errors = False - if not check_neutron_net(NEUTRON_NET_NAME): - logger.debug(" Private network '%s' NOT found." % NEUTRON_NET_NAME) - errors = True - errors_all = True - else: - logger.debug(" Private network '%s' found." % NEUTRON_NET_NAME) - - if not check_neutron_net(NEUTRON_PUBLIC_NAME): - logger.debug(" Public network '%s' NOT found." % NEUTRON_PUBLIC_NAME) - errors = True + if not check_neutron_net(neutron_client, NEUTRON_PRIVATE_NET_NAME): + logger.debug(" Private network '%s' NOT found." % NEUTRON_PRIVATE_NET_NAME) + logger.debug("...FAIL") errors_all = True else: - logger.debug(" Public network '%s' found." % NEUTRON_PUBLIC_NAME) - - if not errors: + logger.debug(" Private network '%s' found." % NEUTRON_PRIVATE_NET_NAME) logger.debug("...OK") - else: - logger.debug("...FAIL") logger.debug("Checking Image...") errors = False - if not os.path.isfile(IMAGE_DOWNLOAD_PATH): - logger.debug(" Image file '%s' NOT found." % IMAGE_DOWNLOAD_PATH) + if not os.path.isfile(IMAGE_PATH): + logger.debug(" Image file '%s' NOT found." % IMAGE_PATH) errors = True errors_all = True else: - logger.debug(" Image file found in %s" % IMAGE_DOWNLOAD_PATH) + logger.debug(" Image file found in %s" % IMAGE_PATH) cmd="glance image-list | grep " + IMAGE_NAME FNULL = open(os.devnull, 'w'); @@ -253,25 +217,27 @@ def config_functest_check(): -def config_functest_clean(): +def action_clean(): """ Clean the existing functest environment """ logger.info("Removing current functest environment...") if os.path.exists(RALLY_INSTALLATION_DIR): - logger.debug("Removing rally installation directory %s" % RALLY_INSTALLATION_DIR) + logger.debug("Removing Rally installation directory %s" % RALLY_INSTALLATION_DIR) shutil.rmtree(RALLY_INSTALLATION_DIR,ignore_errors=True) - if os.path.exists(FUNCTEST_BASE_DIR): - logger.debug("Removing functest directory %s" % FUNCTEST_BASE_DIR) - cmd = "sudo rm -rf " + FUNCTEST_BASE_DIR #need to be sudo, not possible with rmtree + if os.path.exists(RALLY_REPO_DIR): + logger.debug("Removing Rally repository %s" % RALLY_REPO_DIR) + cmd = "sudo rm -rf " + RALLY_REPO_DIR #need to be sudo, not possible with rmtree execute_command(cmd) - - #logger.debug("Deleting Neutron network %s" % NEUTRON_NET_NAME) + #logger.debug("Deleting Neutron network %s" % NEUTRON_PRIVATE_NET_NAME) #if not delete_neutron_net() : # logger.error("Error deleting the network. Remove it manually.") logger.debug("Deleting glance images") + if os.path.exists(IMAGE_PATH): + os.remove(IMAGE_PATH) + cmd = "glance image-list | grep "+IMAGE_NAME+" | cut -c3-38" p = os.popen(cmd,"r") @@ -345,6 +311,8 @@ def check_rally(): def install_odl(): + cmd = "chmod +x " + ODL_DIR + "start_tests.sh" + execute_command(cmd) cmd = "chmod +x " + ODL_DIR + "create_venv.sh" execute_command(cmd) cmd = ODL_DIR + "create_venv.sh" @@ -397,55 +365,12 @@ def get_nova_credentials(): return d -def download_tests(): - os.makedirs(VPING_DIR) - os.makedirs(ODL_DIR) - os.makedirs(BENCH_TESTS_DIR) - logger.info("Downloading functest.yaml...") - yaml_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/functest.yaml' - if not download_url(yaml_url,FUNCTEST_BASE_DIR): - logger.error("Unable to download the configuration file functest.yaml") - return False - - logger.info("Downloading vPing test...") - vPing_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/vPing/CI/libraries/vPing.py' - if not download_url(vPing_url,VPING_DIR): - return False - - - logger.info("Downloading Rally bench tests...") - run_rally_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/libraries/run_rally.py' - if not download_url(run_rally_url,RALLY_TEST_DIR): - return False - - rally_bench_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/suites/' - bench_tests = ['authenticate', 'cinder', 'glance', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'tempest', 'vm'] - for i in bench_tests: - rally_bench_url = rally_bench_base_url + "opnfv-" + i + ".json" - logger.debug("Downloading %s" %rally_bench_url) - if not download_url(rally_bench_url,BENCH_TESTS_DIR): - return False - - logger.info("Downloading OLD tests...") - odl_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/Controllers/ODL/CI/' - odl_tests = ['create_venv.sh', 'requirements.pip', 'start_tests.sh', 'test_list.txt'] - for i in odl_tests: - odl_url = odl_base_url + i - logger.debug("Downloading %s" %odl_url) - if not download_url(odl_url,ODL_DIR): - return False - - return True - - -def create_neutron_net(): - credentials = get_credentials() - neutron = client.Client(**credentials) +def create_private_neutron_net(neutron): try: neutron.format = 'json' - logger.debug('Creating Neutron network %s...' % NEUTRON_NET_NAME) - json_body = {'network': {'name': NEUTRON_NET_NAME, + logger.debug('Creating Neutron network %s...' % NEUTRON_PRIVATE_NET_NAME) + json_body = {'network': {'name': NEUTRON_PRIVATE_NET_NAME, 'admin_state_up': True}} netw = neutron.create_network(body=json_body) net_dict = netw['network'] @@ -453,43 +378,34 @@ def create_neutron_net(): logger.debug("Network '%s' created successfully" % network_id) logger.debug('Creating Subnet....') - json_body = {'subnets': [{'cidr': NEUTRON_RANGE, + json_body = {'subnets': [{'name': NEUTRON_PRIVATE_SUBNET_NAME, 'cidr': NEUTRON_PRIVATE_SUBNET_CIDR, 'ip_version': 4, 'network_id': network_id}]} + subnet = neutron.create_subnet(body=json_body) - logger.debug("Subnet '%s' created successfully" % subnet) + subnet_id = subnet['subnets'][0]['id'] + logger.debug("Subnet '%s' created successfully" % subnet_id) + logger.debug('Creating Router...') json_body = {'router': {'name': ROUTER_NAME, 'admin_state_up': True}} router = neutron.create_router(json_body) - logger.debug("Router '%s' created successfully" % router) router_id = router['router']['id'] + logger.debug("Router '%s' created successfully" % router_id) + + logger.debug('Adding router to subnet...') + json_body = {"subnet_id": subnet_id} + neutron.add_interface_router(router=router_id, body=json_body) + logger.debug("Interface added successfully.") - logger.debug('Creating Port') - json_body = {'port': { - 'admin_state_up': True, - 'device_id': router_id, - 'name': 'port1', - 'network_id': network_id, - }} - response = neutron.create_port(body=json_body) - logger.debug("Port created successfully.") - - logger.debug('Setting up gateway...') - public_network_id = get_network_id(neutron,NEUTRON_PUBLIC_NAME) - json_body = {'network_id': public_network_id, 'enable_snat' : True} - gateway = neutron.add_gateway_router(router_id,body=json_body) - logger.debug("Gateway '%s' added successfully" % gateway) except: - logger.error("There has been a problem when creating the Neutron network.") + print "Error:", sys.exc_info()[0] return False - finally: - logger.info("Neutron network created successfully.") - return True - return False + logger.info("Private Neutron network created successfully.") + return True -def get_network_id(neutron_client, network_name): - networks = neutron_client.list_networks()['networks'] +def get_network_id(neutron, network_name): + networks = neutron.list_networks()['networks'] id = '' for n in networks: if n['name'] == network_name: @@ -497,23 +413,19 @@ def get_network_id(neutron_client, network_name): break return id -def check_neutron_net(net_name): - credentials = get_credentials() - neutron = client.Client(**credentials) +def check_neutron_net(neutron, net_name): for network in neutron.list_networks()['networks']: if network['name'] == net_name : for subnet in network['subnets']: return True return False -def delete_neutron_net(): +def delete_neutron_net(neutron): #TODO: remove router, ports - credentials = get_credentials() - neutron = client.Client(**credentials) try: #https://github.com/isginf/openstack_tools/blob/master/openstack_remove_tenant.py for network in neutron.list_networks()['networks']: - if network['name'] == NEUTRON_NET_NAME : + if network['name'] == NEUTRON_PRIVATE_NET_NAME : for subnet in network['subnets']: print "Deleting subnet " + subnet neutron.delete_subnet(subnet) @@ -556,40 +468,6 @@ def download_url(url, dest_path): return True -def download_url_with_progress(url, dest_path): - """ - Download a file to a destination path given a URL showing the progress - """ - name = url.rsplit('/')[-1] - dest = dest_path + name - try: - response = urllib2.urlopen(url) - except (urllib2.HTTPError, urllib2.URLError): - logger.error("Error in fetching %s" %url) - return False - - f = open(dest, 'wb') - meta = response.info() - file_size = int(meta.getheaders("Content-Length")[0]) - logger.info("Downloading: %s Bytes: %s" %(dest, file_size)) - - file_size_dl = 0 - block_sz = 8192 - while True: - buffer = response.read(block_sz) - if not buffer: - break - - file_size_dl += len(buffer) - f.write(buffer) - status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size) - status = status + chr(8)*(len(status)+1) - print status, - - f.close() - print("\n") - return True - def check_internet_connectivity(url='http://www.google.com/'): """ @@ -608,12 +486,14 @@ def execute_command(cmd): logger.debug('Executing command : {}'.format(cmd)) #p = os.popen(cmd,"r") #logger.debug(p.read()) - output_file = "/tmp/output.txt" + output_file = "output.txt" f = open(output_file, 'w+') p = subprocess.call(cmd,shell=True, stdout=f, stderr=subprocess.STDOUT) f.close() f = open(output_file, 'r') - logger.debug(f.read()) + result = f.read() + if result != "": + logger.debug(result) #p = subprocess.call(cmd,shell=True); if p == 0 : return True @@ -629,26 +509,35 @@ def main(): logger.error('argument not valid') exit(-1) + + if not check_credentials(): + logger.error("Please source the openrc credentials and run the script again.") + #TODO: source the credentials in this script + exit(-1) + if args.action == "start": - config_functest_start() + action_start() if args.action == "check": - if config_functest_check(): + if action_check(): logger.info("Functest environment correctly installed") else: - logger.info("Functest environment not found or faulty") + logger.info("Functest environment faulty") if args.action == "clean": - while True: - print("Are you sure? [y|n]") - answer = raw_input("") - if answer == "y": - config_functest_clean() - break - elif answer == "n": - break - else: - print("Invalid option.") + if args.force : + action_clean() + else : + while True: + print("Are you sure? [y|n]") + answer = raw_input("") + if answer == "y": + action_clean() + break + elif answer == "n": + break + else: + print("Invalid option.") exit(0) diff --git a/testcases/config_functest.yaml b/testcases/config_functest.yaml new file mode 100644 index 00000000..eb1c9a2c --- /dev/null +++ b/testcases/config_functest.yaml @@ -0,0 +1,37 @@ +--- +general: + directories: + # Relative to the path where the repo is cloned: + dir_vping: testcases/vPing/CI/libraries/ + dir_odl: testcases/Controllers/ODL/CI/ + dir_rally: testcases/VIM/OpenStack/CI/libraries/ + dir_rally_scn: testcases/VIM/OpenStack/CI/suites/ + # Relative to $HOME: + dir_rally_res: functest/results/ # $HOME/functest/results + dir_rally_repo: functest/Rally_repo/ # $HOME/Rally_repo/ + dir_rally_inst: .rally/ # $HOME/.rally/ usually + + openstack: + image_name: functest-img + image_url: http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-disk.img + image_disk_format: qcow2 + image_download_path: functest/ # $HOME/functest/ + #Public network. Optional + neutron_public_net_name: net04_ext + neutron_public_subnet_name: net04_ext__subnet + neutron_public_subnet_cidr: 172.16.9.0/24 + neutron_public_subnet_start: 172.16.9.130 + neutron_public_subnet_end: 172.16.9.254 + #Private network for functest. Will be created by config_functest.py + neutron_private_net_name: functest-net + neutron_private_subnet_name: functest-subnet + neutron_private_subnet_cidr: 192.168.120.0/24 + neutron_private_subnet_start: 192.168.120.2 + neutron_private_subnet_end: 192.168.120.254 + neutron_private_subnet_gateway: 192.168.120.254 + neutron_router_name: functest-router +vping: + ping_timeout: 200 + vm_flavor: m1.small #adapt to your environment + vm_name_1: opnfv-vping-1 + vm_name_2: opnfv-vping-2 diff --git a/testcases/functest.yaml b/testcases/functest.yaml deleted file mode 100644 index 2f349499..00000000 --- a/testcases/functest.yaml +++ /dev/null @@ -1,30 +0,0 @@ ---- -general: - directories: - dir_functest: .functest/ #DONT CHANGE - dir_rally_repo: .functest/Rally_repo/ - dir_rally: .functest/Rally_test/ - dir_rally_scn: .functest/Rally_test/scenarios/ - dir_rally_res: .functest/Rally_test/results/ - dir_vping: .functest/vPing/ - dir_odl: .functest/ODL/ - dir_rally_inst: .rally/ - openstack: - image_name: Ubuntu14.04 - image_url: https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img - image_disk_format: raw - #Public network. Must exist already. - neutron_public_net_name: net04_ext - #Private network for functest. Will be created by config_functest.py - neutron_net_name: functest-net - neutron_subnet_name: functest-subnet - neutron_subnet_range: 192.168.120.0/24 - neutron_subnet_start: 192.168.120.2 - neutron_subnet_end: 192.168.120.254 - neutron_subnet_gateway: 192.168.120.254 - neutron_router_name: functest-router -vping: - ping_timeout: 200 - vm_flavor: m1.small #adapt to your environment - vm_name_1: opnfv-vping-1 - vm_name_2: opnfv-vping-2 diff --git a/testcases/vPing/CI/libraries/vPing.py b/testcases/vPing/CI/libraries/vPing.py index b81ebb88..e1415535 100644 --- a/testcases/vPing/CI/libraries/vPing.py +++ b/testcases/vPing/CI/libraries/vPing.py @@ -16,26 +16,11 @@ import os, time, subprocess, logging, argparse, yaml import pprint import novaclient.v2.client as novaclient -import neutronclient.client as neutronclient -#import novaclient.v1_1.client as novaclient -import cinderclient.v1.client as cinderclient pp = pprint.PrettyPrinter(indent=4) -EXIT_CODE = -1 -HOME = os.environ['HOME']+"/" -with open(HOME+'.functest/functest.yaml') as f: - functest_yaml = yaml.safe_load(f) -f.close() - -PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout") -NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1") -NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2") -GLANCE_IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name") -NEUTRON_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_net_name") -FLAVOR = functest_yaml.get("vping").get("vm_flavor") - parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") args = parser.parse_args() @@ -53,6 +38,19 @@ ch.setFormatter(formatter) logger.addHandler(ch) +HOME = os.environ['HOME']+"/" +with open(args.repo_path+"testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +VM_BOOT_TIMEOUT = 180 +PING_TIMEOUT = functest_yaml.get("vping").get("ping_timeout") +NAME_VM_1 = functest_yaml.get("vping").get("vm_name_1") +NAME_VM_2 = functest_yaml.get("vping").get("vm_name_2") +GLANCE_IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name") +NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_net_name") +FLAVOR = functest_yaml.get("vping").get("vm_flavor") + def pMsg(value): """pretty printing""" @@ -101,10 +99,18 @@ def get_server(creds, servername): def waitVmActive(nova,vm): # sleep and wait for VM status change - while get_status(nova,vm) != "ACTIVE": - time.sleep(3) - logger.debug("Status: %s" % vm.status) - logger.debug("Status: %s" % vm.status) + sleep_time = 3 + count = VM_BOOT_TIMEOUT / sleep_time + while True: + status = get_status(nova,vm) + logger.debug("Status: %s" % status) + if status == "ACTIVE": + return True + if status == "ERROR" or count == 0: + return False + count-=1 + time.sleep(sleep_time) + return False def get_status(nova,vm): vm = nova.servers.get(vm.id) @@ -114,42 +120,43 @@ def get_status(nova,vm): def main(): creds = get_credentials("nova") nova = novaclient.Client(**creds) - cinder = cinderclient.Client(**creds) - - """ - # print images and server resources - # print nova_images - print_title("images list") - pMsg(nova.images.list()) - print_title("servers list") - pMsg(nova.servers.list()) - """ - # Check if the given image is created - images=nova.images.list() - image_found = False - for image in images: - if image.name == GLANCE_IMAGE_NAME: - logger.info("Glance image found '%s'" %image.name) - image_found = True - if not image_found: - logger.error("ERROR: Glance image %s not found." % GLANCE_IMAGE_NAME) + EXIT_CODE = -1 + image = None + network = None + flavor = None + + # Check if the given image exists + try: + image = nova.images.find(name = GLANCE_IMAGE_NAME) + logger.info("Glance image found '%s'" % GLANCE_IMAGE_NAME) + except: + logger.error("ERROR: Glance image '%s' not found." % GLANCE_IMAGE_NAME) logger.info("Available images are: ") pMsg(nova.images.list()) exit(-1) - # Check if the given neutron network is created - networks=nova.networks.list() - network_found = False - for net in networks: - if net.human_id == NEUTRON_NET_NAME: - logger.info("Network found '%s'" %net.human_id) - network_found = True - if not network_found: - logger.error("Neutron network %s not found." % NEUTRON_NET_NAME) + # Check if the given neutron network exists + try: + network = nova.networks.find(label = NEUTRON_PRIVATE_NET_NAME) + logger.info("Network found '%s'" % NEUTRON_PRIVATE_NET_NAME) + except: + logger.error("Neutron network '%s' not found." % NEUTRON_PRIVATE_NET_NAME) logger.info("Available networks are: ") pMsg(nova.networks.list()) exit(-1) + # Check if the given flavor exists + try: + flavor = nova.flavors.find(name = FLAVOR) + logger.info("Flavor found '%s'" % FLAVOR) + except: + logger.error("Flavor '%s' not found." % FLAVOR) + logger.info("Available flavors are: ") + pMsg(nova.flavor.list()) + exit(-1) + + + # Deleting instances if they exist servers=nova.servers.list() for server in servers: if server.name == NAME_VM_1 or server.name == NAME_VM_2: @@ -160,106 +167,75 @@ def main(): # boot VM 1 # basic boot - # tune (e.g. flavor, images, network) to your specific openstack configuration here - m = NAME_VM_1 - f = nova.flavors.find(name = FLAVOR) - i = nova.images.find(name = GLANCE_IMAGE_NAME) - n = nova.networks.find(label = NEUTRON_NET_NAME) - u = "#cloud-config\npassword: opnfv\nchpasswd: { expire: False }\nssh_pwauth: True" - #k = "demo-key" + # tune (e.g. flavor, images, network) to your specific openstack configuration here # create VM - logger.info("Creating instance '%s'..." %m) - logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u)) + logger.info("Creating instance '%s'..." % NAME_VM_1) + logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n" %(NAME_VM_1,flavor,image,network)) vm1 = nova.servers.create( - name = m, - flavor = f, - image = i, - nics = [{"net-id": n.id}], - #key_name = k, - userdata = u, + name = NAME_VM_1, + flavor = flavor, + image = image, + nics = [{"net-id": network.id}] ) - #pMsg(vm1) - #wait until VM status is active - waitVmActive(nova,vm1) + if not waitVmActive(nova,vm1): + logger.error("Instance '%s' cannot be booted. Status is '%s'" % (NAME_VM_1,get_status(nova,vm1))) + return (EXIT_CODE) + else: + logger.info("Instance '%s' is ACTIVE." % NAME_VM_1) #retrieve IP of first VM logger.debug("Fetching IP...") - server = get_server(creds, m) - #pMsg(server.networks) + server = get_server(creds, NAME_VM_1) # theoretically there is only one IP address so we take the first element of the table # Dangerous! To be improved! - test_ip = server.networks.get(NEUTRON_NET_NAME)[0] - logger.debug("Instance '%s' got %s" %(m,test_ip)) - test_cmd = '/tmp/vping.sh %s'%test_ip - + test_ip = server.networks.get(NEUTRON_PRIVATE_NET_NAME)[0] + logger.debug("Instance '%s' got %s" %(NAME_VM_1,test_ip)) # boot VM 2 # we will boot then execute a ping script with cloud-init # the long chain corresponds to the ping procedure converted with base 64 - # tune (e.g. flavor, images, network) to your specific openstack configuration here - m = NAME_VM_2 - f = nova.flavors.find(name = FLAVOR) - i = nova.images.find(name = GLANCE_IMAGE_NAME) - n = nova.networks.find(label = NEUTRON_NET_NAME) - # use base 64 format becaus bad surprises with sh script with cloud-init but script is just pinging - #k = "demo-key" - u = "#cloud-config\npassword: opnfv\nchpasswd: { expire: False }\nssh_pwauth: True\nwrite_files:\n- encoding: b64\n path: /tmp/vping.sh\n permissions: '0777'\n owner: root:root\n content: IyEvYmluL2Jhc2gKCndoaWxlIHRydWU7IGRvCiBwaW5nIC1jIDEgJDEgMj4mMSA+L2Rldi9udWxsCiBSRVM9JD8KIGlmIFsgIlokUkVTIiA9ICJaMCIgXSA7IHRoZW4KICBlY2hvICJ2UGluZyBPSyIKICBzbGVlcCAxMAogIHN1ZG8gc2h1dGRvd24gLWggbm93CiAgYnJlYWsKIGVsc2UKICBlY2hvICJ2UGluZyBLTyIKIGZpCiBzbGVlcCAxCmRvbmUK\nruncmd:\n - [ sh, -c, %s]"%test_cmd + # tune (e.g. flavor, images, network) to your specific openstack configuration here + u = "#!/bin/sh\n\nwhile 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\ndone\n"%test_ip + # create VM - logger.info("Creating instance '%s'..." %m) - logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(m,f,i,n,u)) + logger.info("Creating instance '%s'..." % NAME_VM_2) + logger.debug("Configuration:\n name=%s \n flavor=%s \n image=%s \n network=%s \n userdata= \n%s" %(NAME_VM_2,flavor,image,network,u)) vm2 = nova.servers.create( - name = m, - flavor = f, - image = i, - nics = [{"net-id": n.id}], - #key_name = k, + name = NAME_VM_2, + flavor = flavor, + image = image, + nics = [{"net-id": network.id}], userdata = u, - #security_groups = s, - #config_drive = v.id ) - # The injected script will shutdown the VM2 when the ping works - # The console-log method is more consistent but doesn't work yet - - waitVmActive(nova,vm2) - logger.info("Waiting for ping, timeout is %d sec..." % PING_TIMEOUT) - sec = 0 - while True: - status = get_status(nova, vm2) - #print status - if status == "SHUTOFF" : - EXIT_CODE = 0 - logger.info("vPing SUCCESSFUL after %d sec" % sec) - break - if sec == PING_TIMEOUT: - logger.info("Timeout. vPing UNSUCCESSFUL.") - break - time.sleep(1) - sec+=1 + if not waitVmActive(nova,vm2): + logger.error("Instance '%s' cannot be booted. Status is '%s'" % (NAME_VM_2,get_status(nova,vm2))) + return (EXIT_CODE) + else: + logger.info("Instance '%s' is ACTIVE." % NAME_VM_2) - """ - # I leave this here until we fix the console-log output sec = 0 console_log = vm2.get_console_output() - while not ("vPing" in console_log): + while True: time.sleep(1) console_log = vm2.get_console_output() - print "--"+console_log - + #print "--"+console_log # report if the test is failed - if "vPing" in console_log: - pMsg("vPing is OK") + if "vPing OK" in console_log: + logger.info("vPing is OK") + EXIT_CODE = 0 break else: - pMsg("no vPing detected....") + logger.info("No vPing detected...") sec+=1 if sec == PING_TIMEOUT: + logger.info("Timeout reached.") break - """ + # delete both VMs logger.debug("Deleting Instances...") @@ -268,8 +244,11 @@ def main(): nova.servers.delete(vm2) logger.debug("Instance %s terminated." % NAME_VM_2) + if EXIT_CODE == 0: + logger.info("vPing OK") + else: + logger.error("vPing FAILED") - logger.debug("EXIT_CODE=%s" % EXIT_CODE) exit(EXIT_CODE) |