Merge "[FUNCTEST] Correct right ip is used for public endpoint"
authorJose Lausuch <jose.lausuch@ericsson.com>
Wed, 11 Jan 2017 13:06:56 +0000 (13:06 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 11 Jan 2017 13:06:56 +0000 (13:06 +0000)
69 files changed:
.coveragerc [new file with mode: 0644]
INFO
docker/Dockerfile
docker/docker_remote_api/docs/TLS-intro.rst
docker/docker_remote_api/enable_remote_api.sh [changed mode: 0644->0755]
docs/internship/security_group/index.rst [new file with mode: 0644]
docs/internship/testapi_evolution/index.rst [new file with mode: 0644]
docs/internship/unit_tests/index.rst [new file with mode: 0644]
docs/internship/vnf_catalog/index.rst [new file with mode: 0644]
functest/ci/config_functest.yaml
functest/ci/exec_test.sh
functest/ci/generate_report.py
functest/ci/prepare_env.py
functest/ci/run_tests.py [changed mode: 0644->0755]
functest/ci/testcases.yaml
functest/cli/cli_base.py
functest/cli/commands/cli_env.py
functest/cli/commands/cli_os.py
functest/cli/commands/cli_testcase.py
functest/cli/commands/cli_tier.py
functest/core/feature_base.py
functest/core/pytest_suite_runner.py [changed mode: 0644->0755]
functest/core/testcase_base.py
functest/opnfv_tests/features/copper.py
functest/opnfv_tests/features/domino.py
functest/opnfv_tests/features/odl_sfc.py [new file with mode: 0644]
functest/opnfv_tests/features/sdnvpn.py [changed mode: 0644->0755]
functest/opnfv_tests/openstack/examples/create_instance_and_ip.py
functest/opnfv_tests/openstack/healthcheck/healthcheck.sh
functest/opnfv_tests/openstack/rally/run_rally-cert.py
functest/opnfv_tests/openstack/snaps/api_check.py
functest/opnfv_tests/openstack/snaps/connection_check.py
functest/opnfv_tests/openstack/snaps/smoke.py
functest/opnfv_tests/openstack/snaps/snaps_utils.py
functest/opnfv_tests/openstack/tempest/__init__.py [new file with mode: 0644]
functest/opnfv_tests/openstack/tempest/conf_utils.py [new file with mode: 0644]
functest/opnfv_tests/openstack/tempest/gen_tempest_conf.py [deleted file]
functest/opnfv_tests/openstack/tempest/run_tempest.py [deleted file]
functest/opnfv_tests/openstack/tempest/tempest.py [new file with mode: 0644]
functest/opnfv_tests/openstack/vping/vping_base.py [changed mode: 0644->0755]
functest/opnfv_tests/openstack/vping/vping_ssh.py [changed mode: 0644->0755]
functest/opnfv_tests/openstack/vping/vping_userdata.py [changed mode: 0644->0755]
functest/opnfv_tests/sdn/odl/odl.py
functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
functest/opnfv_tests/vnf/ims/vims.py
functest/tests/unit/cli/__init__.py [new file with mode: 0644]
functest/tests/unit/cli/commands/__init__.py [new file with mode: 0644]
functest/tests/unit/cli/commands/test_cli_env.py [new file with mode: 0644]
functest/tests/unit/cli/commands/test_cli_os.py [new file with mode: 0644]
functest/tests/unit/cli/commands/test_cli_testcase.py [new file with mode: 0644]
functest/tests/unit/cli/commands/test_cli_tier.py [new file with mode: 0644]
functest/tests/unit/cli/test_cli_base.py [new file with mode: 0644]
functest/tests/unit/core/test_testcase_base.py
functest/tests/unit/odl/test_odl.py
functest/tests/unit/test_utils.py [new file with mode: 0644]
functest/tests/unit/utils/test_functest_utils.py [new file with mode: 0644]
functest/tests/unit/utils/test_utils.py [deleted file]
functest/utils/config.py [new file with mode: 0644]
functest/utils/constants.py [new file with mode: 0644]
functest/utils/env.py [new file with mode: 0644]
functest/utils/functest_constants.py
functest/utils/functest_utils.py
functest/utils/openstack_clean.py
functest/utils/openstack_snapshot.py
functest/utils/openstack_tacker.py [changed mode: 0644->0755]
functest/utils/openstack_utils.py
run_unit_tests.sh
setup.py
test-requirements.txt

diff --git a/.coveragerc b/.coveragerc
new file mode 100644 (file)
index 0000000..fe258c6
--- /dev/null
@@ -0,0 +1,3 @@
+[report]
+exclude_lines =
+    if __name__ == .__main__.:
diff --git a/INFO b/INFO
index 1f34d8c..6f8963e 100644 (file)
--- a/INFO
+++ b/INFO
@@ -3,15 +3,16 @@ Project Creation Date: January 20, 2015
 Project Category: Integration & Testing
 Lifecycle State: Incubation
 Primary Contact: Jose Lausuch (jose.lausuch@ericsson.com)
-Project Lead: Jose lausuch (jose.lausuch@ericsson.com) 
+Project Lead: Jose lausuch (jose.lausuch@ericsson.com)
 Jira Project Name: Base System Functionality Testing Project
 Jira Project Prefix: FUNCTEST
 Mailing list tag: [functest]
-IRC: Server:freenode.net Channel:#opnfv-testperf
+IRC: Server:freenode.net Channel:#opnfv-functest
 Repository: functest
 
 Committers:
-serena.feng.711@gmail.com
+yaohelan@huawei.com
+feng.xiaowei@zte.com.cn
 ollivier.cedric@gmail.com
 jose.lausuch@ericsson.com
 morgan.richomme@orange.com
index f76dd79..5105fbb 100644 (file)
@@ -32,7 +32,7 @@ LABEL version="0.1" description="OPNFV Functest Docker container"
 ARG BRANCH=master
 ARG TEMPEST_TAG=12.2.0
 ARG RALLY_TAG=0.7.0
-ARG ODL_TAG=release/beryllium-sr3
+ARG ODL_TAG=release/beryllium-sr4
 ARG OPENSTACK_TAG=stable/mitaka
 ARG KINGBIRD_TAG=0.2.2
 ARG VIMS_TAG=stable
@@ -125,7 +125,7 @@ RUN pip install -r ${REPOS_DIR}/rally/requirements.txt
 RUN pip install -r ${REPOS_DIR}/tempest/requirements.txt
 
 RUN find ${FUNCTEST_REPO_DIR} -name "*.py" \
-    -not -path *unit_tests* |xargs grep __main__ |cut -d\: -f 1 |xargs chmod -c 755 \
+    -not -path "*tests/unit*" |xargs grep __main__ |cut -d\: -f 1 |xargs chmod -c 755 \
     && find ${FUNCTEST_REPO_DIR} -name "*.sh" |xargs grep \#\! |cut -d\:  -f 1 |xargs chmod -c 755
 
 RUN /bin/bash ${REPOS_DIR}/parser/tests/parser_install.sh ${REPOS_DIR}
@@ -142,7 +142,13 @@ RUN curl -L https://get.rvm.io | bash -s stable
 RUN git clone --depth 1 https://gerrit.cablelabs.com/snaps-provisioning ${REPOS_DIR}/snaps
 RUN pip install -e ${REPOS_DIR}/snaps/
 
-RUN /bin/bash -c ". ${REPOS_DIR}/sfc/tests/functest/odl-sfc/tacker_client_install.sh"
+# SFC integration
+RUN /bin/bash -c ". ${REPOS_DIR}/sfc/sfc/tests/functest/setup_scripts/tacker_client_install.sh"
+RUN cd ${REPOS_DIR}/sfc && pip install .
+
+# SDNVPN integration
+RUN cd ${REPOS_DIR}/sdnvpn && pip install .
+
 RUN cd ${REPOS_DIR}/bgpvpn && pip install .
 #RUN cd ${REPOS_DIR}/kingbird && pip install -e .
 RUN cd ${REPOS_DIR}/moon/moonclient/ && python setup.py install
index 934f99a..44fdd4a 100644 (file)
-Encrypt the docker remote API via TLS for Ubuntu and CentOS\r
-\r
-[Introduction]\r
-The Docker daemon can listen to Docker Remote API requests via three types of\r
-Socket: unix, tcp and fd. By default, a unix domain socket (or IPC socket) is\r
-created at /var/run/docker.sock, requiring either root permission, or docker\r
-group membership.\r
-\r
-Port 2375 is conventionally used for un-encrypted communition with Docker daemon\r
-remotely, where docker server can be accessed by any docker client via tcp socket\r
-in local area network. You can listen to port 2375 on all network interfaces with\r
--H tcp://0.0.0.0:2375, where 0.0.0.0 means any available IP address on host, and\r
-tcp://0.0.0.0:2375 indicates that port 2375 is listened on any IP of daemon host.\r
-If we want to make docker server open on the Internet via TCP port, and only trusted\r
-clients have the right to access the docker server in a safe manner, port 2376 for\r
-encrypted communication with the daemon should be listened. It can be achieved to\r
-create certificate and distribute it to the trusted clients.\r
-\r
-Through creating self-signed certificate, and using --tlsverify command when running\r
-Docker daemon, Docker daemon opens the TLS authentication. Thus only the clients\r
-with related private key files can have access to the Docker daemon's server. As\r
-long as the key files for encryption are secure between docker server and client,\r
-the Docker daemon can keep secure.\r
-In summary,\r
-Firstly we should create docker server certificate and related key files, which\r
-are distributed to the trusted clients.\r
-Then the clients with related key files can access docker server.\r
-\r
-[Steps]\r
-1.0. Create a CA, server and client keys with OpenSSL.\r
-    OpenSSL is used to generate certificate, and can be installed as follows.\r
-    apt-get install openssl openssl-devel\r
-\r
-1.1 First generate CA private and public keys.\r
-    openssl genrsa -aes256 -out ca-key.pem 4096\r
-    openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem\r
-\r
-    You are about to be asked to enter information that will be incorporated\r
-    into your certificate request, where the instance of $HOST should be replaced\r
-    with the DNS name of your Docker daemon's host, here the DNS name of my Docker\r
-    daemon is ly.\r
-       Common Name (e.g. server FQDN or YOUR name) []:$HOST\r
-\r
-1.2 Now we have a CA (ca-key.pem and ca.pem), you can create a server key and\r
-certificate signing request.\r
-    openssl genrsa -out server-key.pem 4096\r
-    openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr\r
-\r
-1.3 Sign the public key with our CA.\r
-    TLS connections can be made via IP address as well as DNS name, they need to be\r
-    specified when creating the certificate.\r
-\r
-    echo subjectAltName = IP:172.16.10.121,IP:127.0.0.1 > extfile.cnf\r
-    openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \\r
-    -CAcreateserial -out server-cert.pem -extfile extfile.cnf\r
-\r
-1.4 For client authentication, create a client key and certificate signing request.\r
-    openssl genrsa -out key.pem 4096\r
-    openssl req -subj '/CN=client' -new -key key.pem -out client.csr\r
-\r
-1.5 To make the key suitable for client authentication, create an extensions config file.\r
-    echo extendedKeyUsage = clientAuth > extfile.cnf\r
-\r
-1.6 Sign the public key and after generating cert.pem and server-cert.pem, two certificate\r
-    signing requests can be removed.\r
-    openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \\r
-    -CAcreateserial -out cert.pem -extfile extfile.cnf\r
-\r
-1.7 In order to protect your keys from accidental damage, you may change file modes to\r
-    be only readable.\r
-    chmod -v 0400 ca-key.pem key.pem server-key.pem\r
-    chmod -v 0444 ca.pem server-cert.pem cert.pem\r
-\r
-1.8 Build docker server\r
-    dockerd --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem \\r
-    -H=0.0.0.0:2376\r
-    Then, it can be seen from the command 'netstat -ntlp' that port 2376 has been listened\r
-    and the Docker daemon only accept connections from clients providing a certificate\r
-    trusted by our CA.\r
-\r
-1.9 Distribute the keys to the client\r
-    scp /etc/docker/ca.pem wwl@172.16.10.121:/etc/docker\r
-    scp /etc/docker/cert.pem wwl@172.16.10.121:/etc/docker\r
-    scp /etc/docker/key.pem wwl@172.16.10.121:/etc/docker\r
-    Where, wwl and 172.16.10.121 is the username and IP of the client respectively.\r
-    And the password of the client is needed when you distribute the keys to the client.\r
-\r
-1.10 To access Docker daemon from the client via keys.\r
-    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \\r
-    -H=$HOST:2376 version\r
-\r
-    Then we can operate docker in the Docker daemon from the client vis keys, for example:\r
-    1) create container from the client\r
-    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 run -d \\r
-    -it --name w1 grafana/grafana\r
-    2) list containers from the client\r
-    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 pa -a\r
-    3) stop/start containers from the client\r
-    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 stop w1\r
-    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 start w1\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
+Encrypt the docker remote API via TLS for Ubuntu and CentOS
+
+[Introduction]
+The Docker daemon can listen to Docker Remote API requests via three types of
+Socket: unix, tcp and fd. By default, a unix domain socket (or IPC socket) is
+created at /var/run/docker.sock, requiring either root permission, or docker
+group membership.
+
+Port 2375 is conventionally used for un-encrypted communition with Docker daemon
+remotely, where docker server can be accessed by any docker client via tcp socket
+in local area network. You can listen to port 2375 on all network interfaces with
+-H tcp://0.0.0.0:2375, where 0.0.0.0 means any available IP address on host, and
+tcp://0.0.0.0:2375 indicates that port 2375 is listened on any IP of daemon host.
+If we want to make docker server open on the Internet via TCP port, and only trusted
+clients have the right to access the docker server in a safe manner, port 2376 for
+encrypted communication with the daemon should be listened. It can be achieved to
+create certificate and distribute it to the trusted clients.
+
+Through creating self-signed certificate, and using --tlsverify command when running
+Docker daemon, Docker daemon opens the TLS authentication. Thus only the clients
+with related private key files can have access to the Docker daemon's server. As
+long as the key files for encryption are secure between docker server and client,
+the Docker daemon can keep secure.
+In summary,
+Firstly we should create docker server certificate and related key files, which
+are distributed to the trusted clients.
+Then the clients with related key files can access docker server.
+
+[Steps]
+1.0. Create a CA, server and client keys with OpenSSL.
+    OpenSSL is used to generate certificate, and can be installed as follows.
+    apt-get install openssl openssl-devel
+
+1.1 First generate CA private and public keys.
+    openssl genrsa -aes256 -out ca-key.pem 4096
+    openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
+
+    You are about to be asked to enter information that will be incorporated
+    into your certificate request, where the instance of $HOST should be replaced
+    with the DNS name of your Docker daemon's host, here the DNS name of my Docker
+    daemon is ly.
+       Common Name (e.g. server FQDN or YOUR name) []:$HOST
+
+1.2 Now we have a CA (ca-key.pem and ca.pem), you can create a server key and
+certificate signing request.
+    openssl genrsa -out server-key.pem 4096
+    openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
+
+1.3 Sign the public key with our CA.
+    TLS connections can be made via IP address as well as DNS name, they need to be
+    specified when creating the certificate.
+
+    echo subjectAltName = IP:172.16.10.121,IP:127.0.0.1 > extfile.cnf
+    openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
+    -CAcreateserial -out server-cert.pem -extfile extfile.cnf
+
+1.4 For client authentication, create a client key and certificate signing request.
+    openssl genrsa -out key.pem 4096
+    openssl req -subj '/CN=client' -new -key key.pem -out client.csr
+
+1.5 To make the key suitable for client authentication, create an extensions config file.
+    echo extendedKeyUsage = clientAuth > extfile.cnf
+
+1.6 Sign the public key and after generating cert.pem and server-cert.pem, two certificate
+    signing requests can be removed.
+    openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
+    -CAcreateserial -out cert.pem -extfile extfile.cnf
+
+1.7 In order to protect your keys from accidental damage, you may change file modes to
+    be only readable.
+    chmod -v 0400 ca-key.pem key.pem server-key.pem
+    chmod -v 0444 ca.pem server-cert.pem cert.pem
+
+1.8 Build docker server
+    dockerd --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem \
+    -H=0.0.0.0:2376
+    Then, it can be seen from the command 'netstat -ntlp' that port 2376 has been listened
+    and the Docker daemon only accept connections from clients providing a certificate
+    trusted by our CA.
+
+1.9 Distribute the keys to the client
+    scp /etc/docker/ca.pem wwl@172.16.10.121:/etc/docker
+    scp /etc/docker/cert.pem wwl@172.16.10.121:/etc/docker
+    scp /etc/docker/key.pem wwl@172.16.10.121:/etc/docker
+    Where, wwl and 172.16.10.121 is the username and IP of the client respectively.
+    And the password of the client is needed when you distribute the keys to the client.
+
+1.10 To access Docker daemon from the client via keys.
+    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
+    -H=$HOST:2376 version
+
+    Then we can operate docker in the Docker daemon from the client vis keys, for example:
+    1) create container from the client
+    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 run -d \
+    -it --name w1 grafana/grafana
+    2) list containers from the client
+    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 pa -a
+    3) stop/start containers from the client
+    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 stop w1
+    docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=ly:2376 start w1
+
+
+
+
+
+
+
old mode 100644 (file)
new mode 100755 (executable)
index 6867eed..76e59b8
@@ -1,51 +1,51 @@
-#!/bin/bash\r
-# SPDX-license-identifier: Apache-2.0\r
-\r
-# ******************************\r
-# Script to update the docker host configuration\r
-# to enable Docker Remote API\r
-# ******************************\r
-\r
-if [ -f /etc/lsb-release ]; then\r
-    #tested on ubuntu 14.04 and 16.04\r
-    if grep -q "#DOCKER_OPTS=" "/etc/default/docker"; then\r
-        cp /etc/default/docker /etc/default/docker.bak\r
-        sed -i 's/^#DOCKER_OPTS.*$/DOCKER_OPTS=\"-H unix:\/\/\/var\/run\/docker.sock -H tcp:\/\/0.0.0.0:2375\"/g' /etc/default/docker\r
-    else\r
-        echo DOCKER_OPTS=\"-H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375\" >> /etc/default/docker\r
-    fi\r
-    service docker restart\r
-    #docker start $(docker ps -aq)\r
-elif [ -f /etc/system-release ]; then\r
-        #tested on centos 7.2\r
-    if grep -q "ExecStart=\/usr\/bin\/docker-current daemon" "/lib/systemd/system/docker.service"; then\r
-            cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak\r
-            sed -i 's/^ExecStart=.*$/ExecStart=\/usr\/bin\/docker daemon -H tcp:\/\/0.0.0.0:2375 -H unix:\/\/\/var\/run\/docker.sock  \\/g' /lib/systemd/system/docker.service\r
-            systemctl daemon-reload\r
-            systemctl restart docker\r
-        else\r
-            echo "to be implemented"\r
-    fi\r
-else\r
-    echo "OS is not supported"\r
-fi\r
-\r
-# Issue Note for Ubuntu\r
-# 1. If the configuration of the file /etc/default/docker does not take effect after restarting docker service,\r
-#    you may try to modify /lib/systemd/system/docker.service\r
-#    commands:\r
-#    cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak\r
-#    sed -i '/^ExecStart/i\EnvironmentFile=-/etc/default/docker' /lib/systemd/system/docker.service\r
-#    sed -i '/ExecStart=\/usr\/bin\/dockerd/{;s/$/ \$DOCKER_OPTS/}' /lib/systemd/system/docker.service\r
-#    systemctl daemon-reload\r
-#    service docker restart\r
-# 2. Systemd is a system and session manager for Linux, where systemctl is one tool for systemd to view and control systemd.\r
-#    If the file /lib/systemd/system/docker.service is modified, systemd has to be reloaded to scan new or changed units.\r
-#    1) systemd and related packages are available on the PPA. To use the PPA, first add it to your software sources list as follows.\r
-#       add-apt-repository ppa:pitti/systemd\r
-#       apt-get update\r
-#    2) system can be installed from the PPS as follows.\r
-#       apt-get install systemd libpam-systemd systemd-ui\r
-\r
-\r
-\r
+#!/bin/bash
+# SPDX-license-identifier: Apache-2.0
+
+# ******************************
+# Script to update the docker host configuration
+# to enable Docker Remote API
+# ******************************
+
+if [ -f /etc/lsb-release ]; then
+    #tested on ubuntu 14.04 and 16.04
+    if grep -q "#DOCKER_OPTS=" "/etc/default/docker"; then
+        cp /etc/default/docker /etc/default/docker.bak
+        sed -i 's/^#DOCKER_OPTS.*$/DOCKER_OPTS=\"-H unix:\/\/\/var\/run\/docker.sock -H tcp:\/\/0.0.0.0:2375\"/g' /etc/default/docker
+    else
+        echo DOCKER_OPTS=\"-H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375\" >> /etc/default/docker
+    fi
+    service docker restart
+    #docker start $(docker ps -aq)
+elif [ -f /etc/system-release ]; then
+        #tested on centos 7.2
+    if grep -q "ExecStart=\/usr\/bin\/docker-current daemon" "/lib/systemd/system/docker.service"; then
+            cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak
+            sed -i 's/^ExecStart=.*$/ExecStart=\/usr\/bin\/docker daemon -H tcp:\/\/0.0.0.0:2375 -H unix:\/\/\/var\/run\/docker.sock  \\/g' /lib/systemd/system/docker.service
+            systemctl daemon-reload
+            systemctl restart docker
+        else
+            echo "to be implemented"
+    fi
+else
+    echo "OS is not supported"
+fi
+
+# Issue Note for Ubuntu
+# 1. If the configuration of the file /etc/default/docker does not take effect after restarting docker service,
+#    you may try to modify /lib/systemd/system/docker.service
+#    commands:
+#    cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak
+#    sed -i '/^ExecStart/i\EnvironmentFile=-/etc/default/docker' /lib/systemd/system/docker.service
+#    sed -i '/ExecStart=\/usr\/bin\/dockerd/{;s/$/ \$DOCKER_OPTS/}' /lib/systemd/system/docker.service
+#    systemctl daemon-reload
+#    service docker restart
+# 2. Systemd is a system and session manager for Linux, where systemctl is one tool for systemd to view and control systemd.
+#    If the file /lib/systemd/system/docker.service is modified, systemd has to be reloaded to scan new or changed units.
+#    1) systemd and related packages are available on the PPA. To use the PPA, first add it to your software sources list as follows.
+#       add-apt-repository ppa:pitti/systemd
+#       apt-get update
+#    2) system can be installed from the PPS as follows.
+#       apt-get install systemd libpam-systemd systemd-ui
+
+
+
diff --git a/docs/internship/security_group/index.rst b/docs/internship/security_group/index.rst
new file mode 100644 (file)
index 0000000..d1cdbdd
--- /dev/null
@@ -0,0 +1,70 @@
+=======
+License
+=======
+
+Functest Docs are licensed under a Creative Commons Attribution 4.0
+International License.
+You should have received a copy of the license along with this.
+If not, see <http://creativecommons.org/licenses/by/4.0/>.
+
+==================================
+Functest Security group test cases
+==================================
+
+Author: Girish Sukhatankar
+mentors: D.Blaisonneau, J.Lausuch, M.Richomme
+
+Abstract
+========
+
+
+Version history
+===============
+
++------------+----------+------------------+------------------------+
+| **Date**   | **Ver.** | **Author**       | **Comment**            |
+|            |          |                  |                        |
++------------+----------+------------------+------------------------+
+| 2016-??-?? | 0.0.1    | Morgan Richomme  | Beginning of the       |
+|            |          | (Orange)         | Internship             |
++------------+----------+------------------+------------------------+
+
+
+Overview:
+=========
+
+
+
+
+Problem Statement:
+------------------
+
+
+
+Curation Phase
+--------------
+
+
+
+
+
+Schedule:
+=========
+
+
+
++--------------------------+------------------------------------------+
+| **Date**                 | **Comment**                              |
+|                          |                                          |
++--------------------------+------------------------------------------+
+| December  - January      | ........                                 |
++--------------------------+------------------------------------------+
+| January  - february      | ........                                 |
++--------------------------+------------------------------------------+
+
+
+References:
+===========
+
+.. _`[1]` : https://wiki.opnfv.org/display/DEV/Intern+Project%3A+Security+groups+test+case+in+Functest
+
diff --git a/docs/internship/testapi_evolution/index.rst b/docs/internship/testapi_evolution/index.rst
new file mode 100644 (file)
index 0000000..f2583e2
--- /dev/null
@@ -0,0 +1,70 @@
+=======
+License
+=======
+
+Functest Docs are licensed under a Creative Commons Attribution 4.0
+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
+==================
+
+Author: Rohit Sakala
+Mentors: S. Feng, J.Lausuch, M.Richomme
+
+Abstract
+========
+
+
+Version history
+===============
+
++------------+----------+------------------+------------------------+
+| **Date**   | **Ver.** | **Author**       | **Comment**            |
+|            |          |                  |                        |
++------------+----------+------------------+------------------------+
+| 2016-??-?? | 0.0.1    | Morgan Richomme  | Beginning of the       |
+|            |          | (Orange)         | Internship             |
++------------+----------+------------------+------------------------+
+
+
+Overview:
+=========
+
+
+
+
+Problem Statement:
+------------------
+
+
+
+Curation Phase
+--------------
+
+
+
+
+
+Schedule:
+=========
+
+
+
++--------------------------+------------------------------------------+
+| **Date**                 | **Comment**                              |
+|                          |                                          |
++--------------------------+------------------------------------------+
+| December  - January      | ........                                 |
++--------------------------+------------------------------------------+
+| January  - february      | ........                                 |
++--------------------------+------------------------------------------+
+
+
+References:
+===========
+
+.. _`[1]` : https://wiki.opnfv.org/display/DEV/Intern+Project%3A+testapi+evolution
+
diff --git a/docs/internship/unit_tests/index.rst b/docs/internship/unit_tests/index.rst
new file mode 100644 (file)
index 0000000..f969aa7
--- /dev/null
@@ -0,0 +1,70 @@
+=======
+License
+=======
+
+Functest Docs are licensed under a Creative Commons Attribution 4.0
+International License.
+You should have received a copy of the license along with this.
+If not, see <http://creativecommons.org/licenses/by/4.0/>.
+
+===================
+Functest Unit tests
+===================
+
+Author: Ashish Kumar
+Mentors: H.Yao, J.Lausuch, M.Richomme
+
+Abstract
+========
+
+
+Version history
+===============
+
++------------+----------+------------------+------------------------+
+| **Date**   | **Ver.** | **Author**       | **Comment**            |
+|            |          |                  |                        |
++------------+----------+------------------+------------------------+
+| 2016-??-?? | 0.0.1    | Morgan Richomme  | Beginning of the       |
+|            |          | (Orange)         | Internship             |
++------------+----------+------------------+------------------------+
+
+
+Overview:
+=========
+
+
+
+
+Problem Statement:
+------------------
+
+
+
+Curation Phase
+--------------
+
+
+
+
+
+Schedule:
+=========
+
+
+
++--------------------------+------------------------------------------+
+| **Date**                 | **Comment**                              |
+|                          |                                          |
++--------------------------+------------------------------------------+
+| December  - January      | ........                                 |
++--------------------------+------------------------------------------+
+| January  - february      | ........                                 |
++--------------------------+------------------------------------------+
+
+
+References:
+===========
+
+.. _`[1]` : https://wiki.opnfv.org/display/DEV/Intern+Project%3A+Functest+unit+tests
+
diff --git a/docs/internship/vnf_catalog/index.rst b/docs/internship/vnf_catalog/index.rst
new file mode 100644 (file)
index 0000000..df76333
--- /dev/null
@@ -0,0 +1,170 @@
+=======
+License
+=======
+
+Functest Docs are licensed under a Creative Commons Attribution 4.0
+International License.
+You should have received a copy of the license along with this.
+If not, see <http://creativecommons.org/licenses/by/4.0/>.
+
+=======================
+Open Source VNF Catalog
+=======================
+
+Author: Kumar Rishabh
+Mentors: B.Souville, M.Richomme, J.Lausuch
+
+Abstract
+========
+
+
+
+Version hissory
+===============
+
++------------+----------+------------------+------------------------+
+| **Date**   | **Ver.** | **Author**       | **Comment**            |
+|            |          |                  |                        |
++------------+----------+------------------+------------------------+
+| 2016-12-12 | 0.0.1    | Morgan Richomme  | Beginning of the       |
+|            |          | (Orange)         | Internship             |
++------------+----------+------------------+------------------------+
+
+
+Overview:
+=========
+
+
+This project aims to create an Open Source catalog for reference and
+classification of Virtual Network Functions (VNFs)s available on
+Internet. The classification method proposed will be in sync with the
+requirements of Telcos active in NFV landscape. The project aims to have
+running web platform similar to [1] by the mid of internship (2nd week
+of March). By the penultimate month of internship I aim to have fully
+functional implementation of an Open Source VNF in functest.
+
+
+Problem Statement:
+------------------
+
+OPNFV aims to be the reference platform for development,
+standardization and integration of Open Source NFV components across
+various Open Source Platforms. It mainly deals with the infrastructure
+through the Network Function Virtualization Infrastructure (NFVI) and
+Virtual Infrastructure manager (VIM). The MANO (Management and
+orchestration) stacks have been introduced recently. VNFs are not
+directly in OPNFV scope, however VNFs are needed to test and qualify the
+infrastructure. In this regard having a common curated Open Source
+Reference VNF catalog would be of immense importance to community.
+
+Since major focus of OPNFV is Telcos, a curated platform targeted from
+industry point of view would be very useful. We plan to divide the
+entire project into three major phases(with some iterative improvements
+and overlaps)
+
+
+Curation Phase
+--------------
+This phase pertains to studying various Open Source VNFs available and
+classification of them based on certain parameters. The parameters that
+I currently have in mind are:
+ * Developer Metrics: These pertain to repo characteristics of VNF under
+ study
+  * Usage Statistics - Activity, Number of Commits, stars
+  * Maturity Statistics - For instance if an NFV community decides code
+  coverage is important for them, it shows the NFV community is serious
+  about taking the project forward
+ * Technical Tagging: These are the tags that pertain to technical
+ characteristics of a VNF
+  * Broad Use Cases - Whether the VNF fits strictly in IaaS, PaaS or
+  SaaS layer or is an hybrid of two/all.
+  * Generic Use Cases - This in my opinion is the broadest
+  classification category. For instance a VNF could be built with a
+  broad idea of powering IOT devices at home or from usage perspective
+  of Telco Operators (vFW, vEPC, vIMS, vCDN, vAAA, vCPE,...).`[2]`_
+  * Fields of Application
+  * Library Status - Whether APIs are standardized, support RESTful
+  services.
+  * Dependency Forwarding Graph - This is pretty complex tagging
+  mechanism. It essentially tries to establish a graph relationship
+  between the VNFs (elementary VNFs are used in Service Function
+  Chaining chains such as Firewall, DPI, content enrichment,..). In my
+  opinion this is useful immensely. This will allow users to go to
+  platform and ask a question like - â€œI have this X tech stack to
+  support, Y and Z are my use cases, which NFVs should I use to support
+  this.
+  * Visitor Score - Based on `[1]`_ I plan to evolve a visitor score for
+  the platform. This will allow users to score an NFV on certain
+  parameters, may be post comments.
+
+**I plan to use the above three scores and evolve cumulative score which
+will be displayed next to each of the NFV on the platform.**
+
+ * Platform building phase - This will involve erecting a Web Platform
+ which will be similar to this  `[1]`_. I am decently familiar with
+ Django and hence I will write the platform in Django. There are two
+ action plans that I have in mind right now. Either I can start writing
+ the platform simultaneously which will help keep track of my progress
+ or I can write the platform after 1.5 - 2 months into the internship.
+ Either way I aim to have the Web Platform ready by March 12.
+
+ * Functest VNF implementation phase - This is the last phase that will
+ involve writing a fully functional implementation of an Open Source VNF
+ into Functest. I will undertake this after I am 3 months into the
+ internship. I have a decent familiarity with python and hence I think
+ it shouldn’t be too difficult. I need to decide how complex the VNFI
+ should undertake this exercise for (e.g. AAA such as free radius sounds
+ relatively easy, vCDN is much more challenging).
+ This will be decided in consent with my mentors.
+
+
+
+
+Schedule:
+=========
+I plan to take this project in 6 months time frame as I want to use it
+as a chance to read more about NFVs in particular and SDN in general
+
+
++--------------------------+------------------------------------------+
+| **Date**                 | **Comment**                              |
+|                          |                                          |
++--------------------------+------------------------------------------+
+| December 12 - January 12 | Study the above mentioned metrics        |
+|                          | Decide which of them are important for   |
+|                          | community (and which are not).           |
++--------------------------+------------------------------------------+
+| January 12 - January 27  | Make a database for the above studied    |
+|                          | metrics and evolve it further based on   |
+|                          | Mentors’ input. + associated API         |
++--------------------------+------------------------------------------+
+| January 27 - February 5  | Compile the data collected above and make|
+|                          | it public. Although I can keep everything|
+|                          | public from the beginning too. My        |
+|                          | rationale of not making the entire data  |
+|                          | public in initial stage as the errors    |
+|                          | caused by me could be misleading for     |
+|                          | developers.                              |
++--------------------------+------------------------------------------+
+| February 5 - March 5     | Erect the Web Platform and release it    |
+|                          | for restricted group for alpha testing.  |
++--------------------------+------------------------------------------+
+| March 5 - March 12       | Make it public. Release it to public for |
+|                          | beta testing. Fix Bugs.                  |
++--------------------------+------------------------------------------+
+| March 12 - April 12      | Start working on implementation of an    |
+|                          | Open Source VNF in Functest.             |
++--------------------------+------------------------------------------+
+| April 12 - May 12        | I will decided what to do here based on  |
+|                          | discussion with mentors.                 |
++--------------------------+------------------------------------------+
+
+
+References:
+===========
+
+.. _`[1]` : Openhub: https://www.openhub.net/explore/projects
+
+.. _`[2]` : ETSI NFV White Paper: https://portal.etsi.org/Portals/0/TBpages/NFV/Docs/NFV_White_Paper3.pdf
+
+.. _`[3]` : https://wiki.opnfv.org/display/DEV/Intern+Project%3A+Open+Source+VNF+catalog
index 0da2bb8..15e0d3a 100755 (executable)
-general:\r
-    directories:\r
-        # Relative to the path where the repo is cloned:\r
-        dir_vping:         functest/opnfv_tests/openstack/vping\r
-        dir_odl:           functest/opnfv_tests/sdn/odl\r
-        dir_rally:         functest/opnfv_tests/openstack/rally\r
-        dir_tempest_cases: functest/opnfv_tests/openstack/tempest/custom_tests\r
-        dir_vIMS:          functest/opnfv_tests/vnf/ims\r
-        dir_onos:          functest/opnfv_tests/sdn/onos/teston\r
-        dir_onos_sfc:      functest/opnfv_tests/sdn/onos/sfc\r
-\r
-        # Absolute path\r
-        dir_home:           /home/opnfv\r
-        dir_repos:          /home/opnfv/repos\r
-        dir_repo_functest:  /home/opnfv/repos/functest\r
-        dir_repo_rally:     /home/opnfv/repos/rally\r
-        dir_repo_tempest:   /home/opnfv/repos/tempest\r
-        dir_repo_releng:    /home/opnfv/repos/releng\r
-        dir_repo_vims_test: /home/opnfv/repos/vims-test\r
-        dir_repo_sdnvpn:    /home/opnfv/repos/sdnvpn\r
-        dir_repo_sfc:       /home/opnfv/repos/sfc\r
-        dir_repo_onos:      /home/opnfv/repos/onos\r
-        dir_repo_promise:   /home/opnfv/repos/promise\r
-        dir_repo_doctor:    /home/opnfv/repos/doctor\r
-        dir_repo_copper:    /home/opnfv/repos/copper\r
-        dir_repo_ovno:      /home/opnfv/repos/ovno\r
-        dir_repo_parser:    /home/opnfv/repos/parser\r
-        dir_repo_domino:    /home/opnfv/repos/domino\r
-        dir_repo_snaps:     /home/opnfv/repos/snaps\r
-        dir_functest:       /home/opnfv/functest\r
-        dir_functest_test:  /home/opnfv/repos/functest/functest/opnfv_tests\r
-        dir_results:        /home/opnfv/functest/results\r
-        dir_functest_conf:  /home/opnfv/functest/conf\r
-        dir_functest_data:  /home/opnfv/functest/data\r
-        dir_vIMS_data:      /home/opnfv/functest/data/vIMS/\r
-        dir_rally_inst:     /home/opnfv/.rally\r
-\r
-    openstack:\r
-        creds: /home/opnfv/functest/conf/openstack.creds\r
-        snapshot_file: /home/opnfv/functest/conf/openstack_snapshot.yaml\r
-\r
-        image_name: Cirros-0.3.4\r
-        image_file_name:  cirros-0.3.4-x86_64-disk.img\r
-        image_disk_format:  qcow2\r
-\r
-        flavor_name: opnfv_flavor\r
-        flavor_ram: 512\r
-        flavor_disk: 1\r
-        flavor_vcpus: 1\r
-\r
-        # Private network for functest. Will be created by config_functest.py\r
-        neutron_private_net_name: functest-net\r
-        neutron_private_subnet_name: functest-subnet\r
-        neutron_private_subnet_cidr: 192.168.120.0/24\r
-        neutron_private_subnet_start: 192.168.120.2\r
-        neutron_private_subnet_end: 192.168.120.254\r
-        neutron_private_subnet_gateway: 192.168.120.254\r
-        neutron_router_name: functest-router\r
-\r
-    functest:\r
-        testcases_yaml: /home/opnfv/repos/functest/functest/ci/testcases.yaml\r
-\r
-healthcheck:\r
-    disk_image: /home/opnfv/functest/data/cirros-0.3.4-x86_64-disk.img\r
-    disk_format: qcow2\r
-    wait_time: 60\r
-\r
-snaps:\r
-    use_keystone: True\r
-    use_floating_ips: False\r
-\r
-vping:\r
-    ping_timeout:   200\r
-    vm_flavor: m1.tiny # adapt to your environment\r
-    vm_name_1: opnfv-vping-1\r
-    vm_name_2: opnfv-vping-2\r
-    image_name: functest-vping\r
-    vping_private_net_name: vping-net\r
-    vping_private_subnet_name: vping-subnet\r
-    vping_private_subnet_cidr: 192.168.130.0/24\r
-    vping_router_name: vping-router\r
-    vping_sg_name: vPing-sg\r
-    vping_sg_descr: Security group for vPing test case\r
-\r
-onos_sfc:\r
-    image_base_url: http://artifacts.opnfv.org/sfc/demo\r
-    image_name: TestSfcVm\r
-    image_file_name: firewall_block_image.img\r
-\r
-tempest:\r
-    identity:\r
-        tenant_name: tempest\r
-        tenant_description: Tenant for Tempest test suite\r
-        user_name: tempest\r
-        user_password: tempest\r
-    validation:\r
-        ssh_timeout: 130\r
-    private_net_name: tempest-net\r
-    private_subnet_name: tempest-subnet\r
-    private_subnet_cidr: 192.168.150.0/24\r
-    router_name: tempest-router\r
-    use_custom_images: False\r
-    use_custom_flavors: False\r
-\r
-rally:\r
-    deployment_name: opnfv-rally\r
-    network_name: rally-net\r
-    subnet_name: rally-subnet\r
-    subnet_cidr: 192.168.140.0/24\r
-    router_name: rally-router\r
-\r
-vIMS:\r
-    general:\r
-        tenant_name: vIMS\r
-        tenant_description: vIMS Functionality Testing\r
-        images:\r
-            ubuntu:\r
-                image_url: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img\r
-                image_name: ubuntu_14.04\r
-            centos:\r
-                image_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2\r
-                image_name: centos_7\r
-    cloudify:\r
-        blueprint:\r
-            url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git\r
-            branch: "3.3.1-build"\r
-        requierments:\r
-            ram_min: 3000\r
-            os_image: centos_7\r
-        inputs:\r
-            keystone_username: ""\r
-            keystone_password: ""\r
-            keystone_tenant_name: ""\r
-            keystone_url: ""\r
-            manager_public_key_name: 'manager-kp'\r
-            agent_public_key_name: 'agent-kp'\r
-            image_id: ""\r
-            flavor_id: "3"\r
-            external_network_name: ""\r
-            ssh_user: centos\r
-            agents_user: ubuntu\r
-    clearwater:\r
-        blueprint:\r
-            file_name: 'openstack-blueprint.yaml'\r
-            name: "clearwater-opnfv"\r
-            destination_folder: "opnfv-cloudify-clearwater"\r
-            url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git\r
-            branch: "stable"\r
-        deployment-name: 'clearwater-opnfv'\r
-        requierments:\r
-            ram_min: 1700\r
-            os_image: ubuntu_14.04\r
-        inputs:\r
-            image_id: ''\r
-            flavor_id: ''\r
-            agent_user: 'ubuntu'\r
-            external_network_name: ''\r
-            public_domain: clearwater.opnfv\r
-ONOS:\r
-    general:\r
-        onosbench_username: 'root'\r
-        onosbench_password: 'root'\r
-        onoscli_username: 'root'\r
-        onoscli_password: 'root'\r
-        runtimeout: 300\r
-    environment:\r
-        OCT: '10.20.0.1'\r
-        OC1: '10.20.0.7'\r
-        OC2: '10.20.0.7'\r
-        OC3: '10.20.0.7'\r
-        OCN: '10.20.0.4'\r
-        OCN2: '10.20.0.5'\r
-        installer_master: '10.20.0.2'\r
-        installer_master_username: 'root'\r
-        installer_master_password: 'r00tme'\r
-multisite:\r
-    fuel_environment:\r
-        installer_username: 'root'\r
-        installer_password: 'r00tme'\r
-    compass_environment:\r
-        installer_username: 'root'\r
-        installer_password: 'root'\r
-        multisite_controller_ip: '10.1.0.50'\r
-promise:\r
-    tenant_name: promise\r
-    tenant_description: promise Functionality Testing\r
-    user_name: promiser\r
-    user_pwd: test\r
-    image_name: promise-img\r
-    flavor_name: promise-flavor\r
-    flavor_vcpus: 1\r
-    flavor_ram: 128\r
-    flavor_disk: 0\r
-    network_name: promise-net\r
-    subnet_name: promise-subnet\r
-    subnet_cidr: 192.168.121.0/24\r
-    router_name: promise-router\r
-\r
-example:\r
-    example_vm_name: example-vm\r
-    example_flavor: m1.small\r
-    example_image_name: functest-example-vm\r
-    example_private_net_name: example-net\r
-    example_private_subnet_name: example-subnet\r
-    example_private_subnet_cidr: 192.168.170.0/24\r
-    example_router_name: example-router\r
-    example_sg_name: example-sg\r
-    example_sg_descr: Example Security group\r
-\r
-results:\r
-    test_db_url: http://testresults.opnfv.org/test/api/v1\r
+general:
+    dir:
+        # Relative to the path where the repo is cloned:
+        vping:             functest/opnfv_tests/openstack/vping
+        dir_odl:           functest/opnfv_tests/sdn/odl
+        rally:             functest/opnfv_tests/openstack/rally
+        tempest_cases:     functest/opnfv_tests/openstack/tempest/custom_tests
+        dir_vIMS:          functest/opnfv_tests/vnf/ims
+        dir_onos:          functest/opnfv_tests/sdn/onos/teston
+        dir_onos_sfc:      functest/opnfv_tests/sdn/onos/sfc
+
+        # Absolute path
+        home:               /home/opnfv
+        repos:              /home/opnfv/repos
+        repo_functest:      /home/opnfv/repos/functest
+        dir_repo_rally:     /home/opnfv/repos/rally
+        repo_tempest:       /home/opnfv/repos/tempest
+        dir_repo_releng:    /home/opnfv/repos/releng
+        dir_repo_vims_test: /home/opnfv/repos/vims-test
+        repo_sdnvpn:        /home/opnfv/repos/sdnvpn
+        repo_sfc:           /home/opnfv/repos/sfc
+        dir_repo_onos:      /home/opnfv/repos/onos
+        dir_repo_promise:   /home/opnfv/repos/promise
+        dir_repo_doctor:    /home/opnfv/repos/doctor
+        repo_copper:        /home/opnfv/repos/copper
+        dir_repo_ovno:      /home/opnfv/repos/ovno
+        repo_parser:        /home/opnfv/repos/parser
+        repo_domino:        /home/opnfv/repos/domino
+        repo_snaps:         /home/opnfv/repos/snaps
+        functest:           /home/opnfv/functest
+        functest_test:      /home/opnfv/repos/functest/functest/opnfv_tests
+        results:            /home/opnfv/functest/results
+        functest_conf:      /home/opnfv/functest/conf
+        functest_data:      /home/opnfv/functest/data
+        dir_vIMS_data:      /home/opnfv/functest/data/vIMS/
+        rally_inst:         /home/opnfv/.rally
+
+    openstack:
+        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_disk_format:  qcow2
+
+        flavor_name: opnfv_flavor
+        flavor_ram: 512
+        flavor_disk: 1
+        flavor_vcpus: 1
+
+        # 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
+
+    functest:
+        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_format: qcow2
+    wait_time: 60
+
+snaps:
+    use_keystone: True
+    use_floating_ips: False
+
+vping:
+    ping_timeout:   200
+    vm_flavor: m1.tiny # adapt to your environment
+    vm_name_1: opnfv-vping-1
+    vm_name_2: opnfv-vping-2
+    image_name: functest-vping
+    private_net_name: vping-net
+    private_subnet_name: vping-subnet
+    private_subnet_cidr: 192.168.130.0/24
+    router_name: vping-router
+    sg_name: vPing-sg
+    sg_desc: Security group for vPing test case
+
+onos_sfc:
+    image_base_url: http://artifacts.opnfv.org/sfc/demo
+    image_name: TestSfcVm
+    image_file_name: firewall_block_image.img
+
+tempest:
+    identity:
+        tenant_name: tempest
+        tenant_description: Tenant for Tempest test suite
+        user_name: tempest
+        user_password: tempest
+    validation:
+        ssh_timeout: 130
+    private_net_name: tempest-net
+    private_subnet_name: tempest-subnet
+    private_subnet_cidr: 192.168.150.0/24
+    router_name: tempest-router
+    use_custom_images: False
+    use_custom_flavors: False
+
+rally:
+    deployment_name: opnfv-rally
+    network_name: rally-net
+    subnet_name: rally-subnet
+    subnet_cidr: 192.168.140.0/24
+    router_name: rally-router
+
+vIMS:
+    general:
+        tenant_name: vIMS
+        tenant_description: vIMS Functionality Testing
+        images:
+            ubuntu:
+                image_url: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
+                image_name: ubuntu_14.04
+            centos:
+                image_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-1510.qcow2
+                image_name: centos_7
+    cloudify:
+        blueprint:
+            url: https://github.com/boucherv-orange/cloudify-manager-blueprints.git
+            branch: "3.3.1-build"
+        requierments:
+            ram_min: 3000
+            os_image: centos_7
+        inputs:
+            keystone_username: ""
+            keystone_password: ""
+            keystone_tenant_name: ""
+            keystone_url: ""
+            manager_public_key_name: 'manager-kp'
+            agent_public_key_name: 'agent-kp'
+            image_id: ""
+            flavor_id: "3"
+            external_network_name: ""
+            ssh_user: centos
+            agents_user: ubuntu
+    clearwater:
+        blueprint:
+            file_name: 'openstack-blueprint.yaml'
+            name: "clearwater-opnfv"
+            destination_folder: "opnfv-cloudify-clearwater"
+            url: https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git
+            branch: "stable"
+        deployment-name: 'clearwater-opnfv'
+        requierments:
+            ram_min: 1700
+            os_image: ubuntu_14.04
+        inputs:
+            image_id: ''
+            flavor_id: ''
+            agent_user: 'ubuntu'
+            external_network_name: ''
+            public_domain: clearwater.opnfv
+ONOS:
+    general:
+        onosbench_username: 'root'
+        onosbench_password: 'root'
+        onoscli_username: 'root'
+        onoscli_password: 'root'
+        runtimeout: 300
+    environment:
+        OCT: '10.20.0.1'
+        OC1: '10.20.0.7'
+        OC2: '10.20.0.7'
+        OC3: '10.20.0.7'
+        OCN: '10.20.0.4'
+        OCN2: '10.20.0.5'
+        installer_master: '10.20.0.2'
+        installer_master_username: 'root'
+        installer_master_password: 'r00tme'
+multisite:
+    fuel:
+        installer_username: 'root'
+        installer_password: 'r00tme'
+    compass:
+        installer_username: 'root'
+        installer_password: 'root'
+        multisite_controller_ip: '10.1.0.50'
+promise:
+    tenant_name: promise
+    tenant_description: promise Functionality Testing
+    user_name: promiser
+    user_pwd: test
+    image_name: promise-img
+    flavor_name: promise-flavor
+    flavor_vcpus: 1
+    flavor_ram: 128
+    flavor_disk: 0
+    network_name: promise-net
+    subnet_name: promise-subnet
+    subnet_cidr: 192.168.121.0/24
+    router_name: promise-router
+
+example:
+    vm_name: example-vm
+    flavor: m1.small
+    image_name: functest-example-vm
+    private_net_name: example-net
+    private_subnet_name: example-subnet
+    private_subnet_cidr: 192.168.170.0/24
+    router_name: example-router
+    sg_name: example-sg
+    sg_desc: Example Security group
+
+results:
+    test_db_url: http://testresults.opnfv.org/test/api/v1
index 913ce08..109de07 100755 (executable)
@@ -61,17 +61,7 @@ function odl_tests(){
     fi
 }
 
-function sfc_prepare(){
-    ids=($(neutron security-group-list|grep default|awk '{print $2}'))
-    for id in ${ids[@]}; do
-        if ! neutron security-group-show $id|grep "22/tcp" &>/dev/null; then
-            neutron security-group-rule-create --protocol tcp \
-                --port-range-min 22 --port-range-max 22 --direction ingress $id
-            neutron security-group-rule-create --protocol tcp \
-                --port-range-min 22 --port-range-max 22 --direction egress $id
-        fi
-    done
-}
+
 
 function run_test(){
     test_name=$1
@@ -93,14 +83,6 @@ function run_test(){
                 --ospassword ${OS_PASSWORD} \
                 --odlip $odl_ip --odlwebport $odl_port ${args}
         ;;
-        "tempest_smoke_serial")
-            python ${FUNCTEST_TEST_DIR}/openstack/tempest/run_tempest.py \
-                $clean_flag -s -m smoke $report
-        ;;
-        "tempest_full_parallel")
-            python ${FUNCTEST_TEST_DIR}/openstack/tempest/run_tempest.py \
-                $serial_flag $clean_flag -m full $report
-        ;;
         "vims")
             python ${FUNCTEST_TEST_DIR}/vnf/ims/vims.py $clean_flag $report
         ;;
@@ -132,7 +114,7 @@ function run_test(){
         "security_scan")
             echo "Sourcing Credentials ${FUNCTEST_CONF_DIR}/stackrc for undercloud .."
             source ${FUNCTEST_CONF_DIR}/stackrc
-            python ${REPOS_DIR}/securityscanning/security_scan.py --config ${REPOS_DIR}/securityscanning/config.ini
+            python ${FUNCTEST_TEST_DIR}/security_scan/security_scan.py --config ${FUNCTEST_TEST_DIR}/security_scan/config.ini
         ;;
         "copper")
             python ${FUNCTEST_TEST_DIR}/features/copper.py $report
@@ -140,19 +122,6 @@ function run_test(){
         "moon")
             python ${REPOS_DIR}/moon/tests/run_tests.py $report
         ;;
-        "multisite")
-            python ${FUNCTEST_TEST_DIR}/openstack/tempest/gen_tempest_conf.py
-            python ${FUNCTEST_TEST_DIR}/openstack/tempest/run_tempest.py \
-                $clean_flag -s -m feature_multisite $report \
-                -c ${FUNCTEST_TEST_DIR}/openstack/tempest/tempest_multisite.conf
-        ;;
-        "odl-sfc")
-            ODL_SFC_DIR=${REPOS_DIR}/sfc/tests/functest/odl-sfc
-            # pass FUNCTEST_REPO_DIR inside prepare_odl_sfc.bash
-            FUNCTEST_REPO_DIR=${FUNCTEST_REPO_DIR} python ${ODL_SFC_DIR}/prepare_odl_sfc.py || exit $?
-            source ${ODL_SFC_DIR}/tackerc
-            python ${ODL_SFC_DIR}/sfc.py $report
-        ;;
         *)
             echo "The test case '${test_name}' does not exist."
             exit 1
@@ -197,10 +166,6 @@ done
 echo "Sourcing Credentials ${creds} to run the test.."
 source ${creds}
 
-# ODL Boron workaround to create additional flow rules to allow port 22 TCP
-if [[ $DEPLOY_SCENARIO == *"odl_l2-sfc"* ]]; then
-    sfc_prepare
-fi
 
 # Run test
 run_test $TEST
index a90bc55..89d8fc6 100755 (executable)
@@ -1,11 +1,17 @@
+#!/usr/bin/env python
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+#
 import json
 import re
 import urllib2
 
 import functest.utils.functest_logger as ft_logger
 import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_constants as ft_constants
-
+from functest.utils.constants import CONST
 
 COL_1_LEN = 25
 COL_2_LEN = 15
@@ -17,14 +23,6 @@ COL_5_LEN = 75
 # and then we can print the url to the specific test result
 
 
-class GlobalVariables:
-    IS_CI_RUN = ft_constants.IS_CI_RUN
-    BUILD_TAG = ft_constants.CI_BUILD_TAG
-    INSTALLER = ft_constants.CI_INSTALLER_TYPE
-    CI_LOOP = ft_constants.CI_LOOP
-    SCENARIO = ft_constants.CI_SCENARIO
-
-
 logger = ft_logger.Logger("generate_report").getLogger()
 
 
@@ -42,7 +40,7 @@ def init(tiers_to_run):
 
 def get_results_from_db():
     url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(),
-                                       GlobalVariables.BUILD_TAG)
+                                       CONST.BUILD_TAG)
     logger.debug("Query to rest api: %s" % url)
     try:
         data = json.load(urllib2.urlopen(url))
@@ -69,7 +67,7 @@ def print_line(w1, w2='', w3='', w4='', w5=''):
            '| ' + w2.ljust(COL_2_LEN - 1) +
            '| ' + w3.ljust(COL_3_LEN - 1) +
            '| ' + w4.ljust(COL_4_LEN - 1))
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         str += ('| ' + w5.ljust(COL_5_LEN - 1))
     str += '|\n'
     return str
@@ -77,7 +75,7 @@ def print_line(w1, w2='', w3='', w4='', w5=''):
 
 def print_line_no_columns(str):
     TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN + 2
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         TOTAL_LEN += COL_5_LEN + 1
     return ('| ' + str.ljust(TOTAL_LEN) + "|\n")
 
@@ -87,7 +85,7 @@ def print_separator(char="=", delimiter="+"):
            delimiter + char * COL_2_LEN +
            delimiter + char * COL_3_LEN +
            delimiter + char * COL_4_LEN)
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         str += (delimiter + char * COL_5_LEN)
     str += '+\n'
     return str
@@ -96,7 +94,7 @@ def print_separator(char="=", delimiter="+"):
 def main(args):
     executed_test_cases = args
 
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         results = get_results_from_db()
         if results is not None:
             for test in executed_test_cases:
@@ -105,15 +103,15 @@ def main(args):
                              "result": data['result']})
 
     TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         TOTAL_LEN += COL_5_LEN
     MID = TOTAL_LEN / 2
 
-    if GlobalVariables.BUILD_TAG is not None:
-        if re.search("daily", GlobalVariables.BUILD_TAG) is not None:
-            GlobalVariables.CI_LOOP = "daily"
+    if CONST.BUILD_TAG is not None:
+        if re.search("daily", CONST.BUILD_TAG) is not None:
+            CONST.CI_LOOP = "daily"
         else:
-            GlobalVariables.CI_LOOP = "weekly"
+            CONST.CI_LOOP = "weekly"
 
     str = ''
     str += print_separator('=', delimiter="=")
@@ -122,19 +120,19 @@ def main(args):
     str += print_line_no_columns(' ')
     str += print_line_no_columns(" Deployment description:")
     str += print_line_no_columns("   INSTALLER: %s"
-                                 % GlobalVariables.INSTALLER)
-    if GlobalVariables.SCENARIO is not None:
+                                 % CONST.INSTALLER_TYPE)
+    if CONST.DEPLOY_SCENARIO is not None:
         str += print_line_no_columns("   SCENARIO:  %s"
-                                     % GlobalVariables.SCENARIO)
-    if GlobalVariables.BUILD_TAG is not None:
+                                     % CONST.DEPLOY_SCENARIO)
+    if CONST.BUILD_TAG is not None:
         str += print_line_no_columns("   BUILD TAG: %s"
-                                     % GlobalVariables.BUILD_TAG)
-    if GlobalVariables.CI_LOOP is not None:
+                                     % CONST.BUILD_TAG)
+    if CONST.CI_LOOP is not None:
         str += print_line_no_columns("   CI LOOP:   %s"
-                                     % GlobalVariables.CI_LOOP)
+                                     % CONST.CI_LOOP)
     str += print_line_no_columns(' ')
     str += print_separator('=')
-    if GlobalVariables.IS_CI_RUN:
+    if CONST.IS_CI_RUN:
         str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT', 'URL')
     else:
         str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT')
index 3a99d3b..3df3a0e 100755 (executable)
 #
 
 
+import argparse
 import json
 import os
 import re
 import subprocess
 import sys
 
-import argparse
 import yaml
+from opnfv.utils import constants as opnfv_constants
 
 import functest.utils.functest_logger as ft_logger
 import functest.utils.functest_utils as ft_utils
 import functest.utils.openstack_utils as os_utils
-import functest.utils.functest_constants as ft_constants
+from functest.utils.constants import CONST
 
 actions = ['start', 'check']
 parser = argparse.ArgumentParser()
@@ -39,7 +40,7 @@ args = parser.parse_args()
 logger = ft_logger.Logger("prepare_env").getLogger()
 
 
-CONFIG_FUNCTEST_PATH = ft_constants.CONFIG_FUNCTEST_YAML
+CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML
 CONFIG_PATCH_PATH = os.path.join(os.path.dirname(
     CONFIG_FUNCTEST_PATH), "config_patch.yaml")
 
@@ -55,95 +56,97 @@ def check_env_variables():
     print_separator()
     logger.info("Checking environment variables...")
 
-    if ft_constants.CI_INSTALLER_TYPE is None:
+    if CONST.INSTALLER_TYPE is None:
         logger.warning("The env variable 'INSTALLER_TYPE' is not defined.")
-        ft_constants.CI_INSTALLER_TYPE = "undefined"
+        CONST.INSTALLER_TYPE = "undefined"
     else:
-        if ft_constants.CI_INSTALLER_TYPE not in ft_constants.INSTALLERS:
+        if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
             logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. "
                            "Available OPNFV Installers are : %s. "
                            "Setting INSTALLER_TYPE=undefined."
-                           % (ft_constants.CI_INSTALLER_TYPE,
-                              ft_constants.INSTALLERS))
-            ft_constants.CI_INSTALLER_TYPE = "undefined"
+                           % (CONST.INSTALLER_TYPE,
+                              opnfv_constants.INSTALLERS))
+            CONST.INSTALLER_TYPE = "undefined"
         else:
             logger.info("    INSTALLER_TYPE=%s"
-                        % ft_constants.CI_INSTALLER_TYPE)
+                        % CONST.INSTALLER_TYPE)
 
-    if ft_constants.CI_INSTALLER_IP is None:
+    if CONST.INSTALLER_IP is None:
         logger.warning("The env variable 'INSTALLER_IP' is not defined. "
                        "It is needed to fetch the OpenStack credentials. "
                        "If the credentials are not provided to the "
                        "container as a volume, please add this env variable "
                        "to the 'docker run' command.")
     else:
-        logger.info("    INSTALLER_IP=%s" % ft_constants.CI_INSTALLER_IP)
+        logger.info("    INSTALLER_IP=%s" % CONST.INSTALLER_IP)
 
-    if ft_constants.CI_SCENARIO is None:
+    if CONST.DEPLOY_SCENARIO is None:
         logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. "
                        "Setting CI_SCENARIO=undefined.")
-        ft_constants.CI_SCENARIO = "undefined"
+        CONST.DEPLOY_SCENARIO = "undefined"
     else:
-        logger.info("    DEPLOY_SCENARIO=%s" % ft_constants.CI_SCENARIO)
-    if ft_constants.CI_DEBUG:
-        logger.info("    CI_DEBUG=%s" % ft_constants.CI_DEBUG)
+        logger.info("    DEPLOY_SCENARIO=%s" % CONST.DEPLOY_SCENARIO)
+    if CONST.CI_DEBUG:
+        logger.info("    CI_DEBUG=%s" % CONST.CI_DEBUG)
 
-    if ft_constants.CI_NODE:
-        logger.info("    NODE_NAME=%s" % ft_constants.CI_NODE)
+    if CONST.NODE_NAME:
+        logger.info("    NODE_NAME=%s" % CONST.NODE_NAME)
 
-    if ft_constants.CI_BUILD_TAG:
-        logger.info("    BUILD_TAG=%s" % ft_constants.CI_BUILD_TAG)
+    if CONST.BUILD_TAG:
+        logger.info("    BUILD_TAG=%s" % CONST.BUILD_TAG)
 
-    if ft_constants.IS_CI_RUN:
-        logger.info("    IS_CI_RUN=%s" % ft_constants.IS_CI_RUN)
+    if CONST.IS_CI_RUN:
+        logger.info("    IS_CI_RUN=%s" % CONST.IS_CI_RUN)
 
 
 def create_directories():
     print_separator()
     logger.info("Creating needed directories...")
-    if not os.path.exists(ft_constants.FUNCTEST_CONF_DIR):
-        os.makedirs(ft_constants.FUNCTEST_CONF_DIR)
-        logger.info("    %s created." % ft_constants.FUNCTEST_CONF_DIR)
+    if not os.path.exists(CONST.dir_functest_conf):
+        os.makedirs(CONST.dir_functest_conf)
+        logger.info("    %s created." % CONST.dir_functest_conf)
     else:
         logger.debug("   %s already exists."
-                     % ft_constants.FUNCTEST_CONF_DIR)
+                     % CONST.dir_functest_conf)
 
-    if not os.path.exists(ft_constants.FUNCTEST_DATA_DIR):
-        os.makedirs(ft_constants.FUNCTEST_DATA_DIR)
-        logger.info("    %s created." % ft_constants.FUNCTEST_DATA_DIR)
+    if not os.path.exists(CONST.dir_functest_data):
+        os.makedirs(CONST.dir_functest_data)
+        logger.info("    %s created." % CONST.dir_functest_data)
     else:
         logger.debug("   %s already exists."
-                     % ft_constants.FUNCTEST_DATA_DIR)
+                     % CONST.dir_functest_data)
 
 
 def source_rc_file():
     print_separator()
     logger.info("Fetching RC file...")
 
-    if ft_constants.OPENSTACK_CREDS is None:
+    if CONST.openstack_creds is None:
         logger.warning("The environment variable 'creds' must be set and"
                        "pointing to the local RC file. Using default: "
                        "/home/opnfv/functest/conf/openstack.creds ...")
-        os.path.join(ft_constants.FUNCTEST_CONF_DIR, 'openstack.creds')
+        os.path.join(CONST.dir_functest_conf, 'openstack.creds')
 
-    if not os.path.isfile(ft_constants.OPENSTACK_CREDS):
+    if not os.path.isfile(CONST.openstack_creds):
         logger.info("RC file not provided. "
                     "Fetching it from the installer...")
-        if ft_constants.CI_INSTALLER_IP is None:
+        if CONST.INSTALLER_IP is None:
             logger.error("The env variable CI_INSTALLER_IP must be provided in"
                          " order to fetch the credentials from the installer.")
             sys.exit("Missing CI_INSTALLER_IP.")
-        if ft_constants.CI_INSTALLER_TYPE not in ft_constants.INSTALLERS:
+        if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
             logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is "
                          "not a valid OPNFV installer. Available "
-                         "installers are : %s." % ft_constants.INSTALLERS)
+                         "installers are : %s." %
+                         (CONST.INSTALLER_TYPE,
+                          opnfv_constants.INSTALLERS))
             sys.exit("Wrong INSTALLER_TYPE.")
 
         cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh "
                "-d %s -i %s -a %s"
-               % (ft_constants.OPENSTACK_CREDS,
-                  ft_constants.CI_INSTALLER_TYPE,
-                  ft_constants.CI_INSTALLER_IP))
+               % (CONST.openstack_creds,
+                  CONST.INSTALLER_TYPE,
+                  CONST.INSTALLER_IP))
         logger.debug("Executing command: %s" % cmd)
         p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
         output = p.communicate()[0]
@@ -153,38 +156,38 @@ def source_rc_file():
             sys.exit(1)
     else:
         logger.info("RC file provided in %s."
-                    % ft_constants.OPENSTACK_CREDS)
-        if os.path.getsize(ft_constants.OPENSTACK_CREDS) == 0:
+                    % CONST.openstack_creds)
+        if os.path.getsize(CONST.openstack_creds) == 0:
             logger.error("The file %s is empty."
-                         % ft_constants.OPENSTACK_CREDS)
+                         % CONST.openstack_creds)
             sys.exit(1)
 
     logger.info("Sourcing the OpenStack RC file...")
     creds = os_utils.source_credentials(
-        ft_constants.OPENSTACK_CREDS)
+        CONST.openstack_creds)
     str = ""
     for key, value in creds.iteritems():
         if re.search("OS_", key):
             str += "\n\t\t\t\t\t\t   " + key + "=" + value
             if key == 'OS_AUTH_URL':
-                ft_constants.OS_AUTH_URL = value
+                CONST.OS_AUTH_URL = value
             elif key == 'OS_USERNAME':
-                ft_constants.OS_USERNAME = value
+                CONST.OS_USERNAME = value
             elif key == 'OS_TENANT_NAME':
-                ft_constants.OS_TENANT_NAME = value
+                CONST.OS_TENANT_NAME = value
             elif key == 'OS_PASSWORD':
-                ft_constants.OS_PASSWORD = value
+                CONST.OS_PASSWORD = value
     logger.debug("Used credentials: %s" % str)
-    logger.debug("OS_AUTH_URL:%s" % ft_constants.OS_AUTH_URL)
-    logger.debug("OS_USERNAME:%s" % ft_constants.OS_USERNAME)
-    logger.debug("OS_TENANT_NAME:%s" % ft_constants.OS_TENANT_NAME)
-    logger.debug("OS_PASSWORD:%s" % ft_constants.OS_PASSWORD)
+    logger.debug("OS_AUTH_URL:%s" % CONST.OS_AUTH_URL)
+    logger.debug("OS_USERNAME:%s" % CONST.OS_USERNAME)
+    logger.debug("OS_TENANT_NAME:%s" % CONST.OS_TENANT_NAME)
+    logger.debug("OS_PASSWORD:%s" % CONST.OS_PASSWORD)
 
 
 def patch_config_file():
     updated = False
     for key in functest_patch_yaml:
-        if key in ft_constants.CI_SCENARIO:
+        if key in CONST.DEPLOY_SCENARIO:
             new_functest_yaml = dict(ft_utils.merge_dicts(
                 ft_utils.get_functest_yaml(), functest_patch_yaml[key]))
             updated = True
@@ -199,7 +202,7 @@ def patch_config_file():
 def verify_deployment():
     print_separator()
     logger.info("Verifying OpenStack services...")
-    cmd = ("%s/functest/ci/check_os.sh" % ft_constants.FUNCTEST_REPO_DIR)
+    cmd = ("%s/functest/ci/check_os.sh" % CONST.dir_repo_functest)
 
     logger.debug("Executing command: %s" % cmd)
     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
@@ -219,19 +222,19 @@ def install_rally():
     cmd = "rally deployment destroy opnfv-rally"
     ft_utils.execute_command(cmd, error_msg=(
         "Deployment %s does not exist."
-        % ft_constants.RALLY_DEPLOYMENT_NAME),
+        % CONST.rally_deployment_name),
         verbose=False)
     rally_conf = os_utils.get_credentials_for_rally()
     with open('rally_conf.json', 'w') as fp:
         json.dump(rally_conf, fp)
     cmd = "rally deployment create --file=rally_conf.json --name="
-    cmd += ft_constants.RALLY_DEPLOYMENT_NAME
+    cmd += CONST.rally_deployment_name
     ft_utils.execute_command(cmd,
                              error_msg="Problem creating Rally deployment")
 
     logger.info("Installing tempest from existing repo...")
     cmd = ("rally verify install --source " +
-           ft_constants.TEMPEST_REPO_DIR +
+           CONST.dir_repo_tempest +
            " --system-wide")
     ft_utils.execute_command(cmd,
                              error_msg="Problem installing Tempest.")
@@ -254,11 +257,11 @@ def install_rally():
 
 def check_environment():
     msg_not_active = "The Functest environment is not installed."
-    if not os.path.isfile(ft_constants.ENV_FILE):
+    if not os.path.isfile(CONST.env_active):
         logger.error(msg_not_active)
         sys.exit(1)
 
-    with open(ft_constants.ENV_FILE, "r") as env_file:
+    with open(CONST.env_active, "r") as env_file:
         s = env_file.read()
         if not re.search("1", s):
             logger.error(msg_not_active)
@@ -281,7 +284,7 @@ def main():
         verify_deployment()
         install_rally()
 
-        with open(ft_constants.ENV_FILE, "w") as env_file:
+        with open(CONST.env_active, "w") as env_file:
             env_file.write("1")
 
         check_environment()
old mode 100644 (file)
new mode 100755 (executable)
index 3f02c87..7aac9d2
@@ -8,24 +8,23 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 
+import argparse
 import datetime
 import importlib
 import os
 import re
 import sys
 
-import argparse
-
 import functest.ci.generate_report as generate_report
 import functest.ci.tier_builder as tb
 import functest.core.testcase_base as testcase_base
+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.functest_constants as ft_constants
 import functest.utils.openstack_clean as os_clean
 import functest.utils.openstack_snapshot as os_snapshot
 import functest.utils.openstack_utils as os_utils
-
+from functest.utils.constants import CONST
 
 parser = argparse.ArgumentParser()
 parser.add_argument("-t", "--test", dest="test", action='store',
@@ -44,7 +43,7 @@ logger = ft_logger.Logger("run_tests").getLogger()
 
 
 """ global variables """
-EXEC_SCRIPT = ("%s/functest/ci/exec_test.sh" % ft_constants.FUNCTEST_REPO_DIR)
+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 -1
@@ -65,7 +64,7 @@ def print_separator(str, count=45):
 
 
 def source_rc_file():
-    rc_file = ft_constants.OPENSTACK_CREDS
+    rc_file = CONST.openstack_creds
     if not os.path.isfile(rc_file):
         logger.error("RC file %s does not exist..." % rc_file)
         sys.exit(1)
@@ -75,16 +74,20 @@ def source_rc_file():
         if re.search("OS_", key):
             if key == 'OS_AUTH_URL':
                 ft_constants.OS_AUTH_URL = value
+                CONST.OS_AUTH_URL = value
             elif key == 'OS_USERNAME':
                 ft_constants.OS_USERNAME = value
+                CONST.OS_USERNAME = value
             elif key == 'OS_TENANT_NAME':
                 ft_constants.OS_TENANT_NAME = value
+                CONST.OS_TENANT_NAME = value
             elif key == 'OS_PASSWORD':
                 ft_constants.OS_PASSWORD = value
-    logger.debug("OS_AUTH_URL:%s" % ft_constants.OS_AUTH_URL)
-    logger.debug("OS_USERNAME:%s" % ft_constants.OS_USERNAME)
-    logger.debug("OS_TENANT_NAME:%s" % ft_constants.OS_TENANT_NAME)
-    logger.debug("OS_PASSWORD:%s" % ft_constants.OS_PASSWORD)
+                CONST.OS_PASSWORD = value
+    logger.debug("OS_AUTH_URL:%s" % CONST.OS_AUTH_URL)
+    logger.debug("OS_USERNAME:%s" % CONST.OS_USERNAME)
+    logger.debug("OS_TENANT_NAME:%s" % CONST.OS_TENANT_NAME)
+    logger.debug("OS_PASSWORD:%s" % CONST.OS_PASSWORD)
 
 
 def generate_os_snapshot():
@@ -124,6 +127,7 @@ def run_test(test, tier_name):
     logger.info("Running test case '%s'..." % test_name)
     print_separator("=")
     logger.debug("\n%s" % test)
+    source_rc_file()
 
     if GlobalVariables.CLEAN_FLAG:
         generate_os_snapshot()
@@ -140,9 +144,10 @@ def run_test(test, tier_name):
             cls = getattr(module, run_dict['class'])
             test_case = cls()
             result = test_case.run()
-            if (result == testcase_base.TestcaseBase.EX_OK and
-                    GlobalVariables.REPORT_FLAG):
-                test_case.push_to_db()
+            if result == testcase_base.TestcaseBase.EX_OK:
+                if GlobalVariables.REPORT_FLAG:
+                    test_case.push_to_db()
+                result = test_case.check_criteria()
         except ImportError:
             logger.exception("Cannot import module {}".format(
                 run_dict['module']))
@@ -199,17 +204,11 @@ def run_tier(tier):
 
 def run_all(tiers):
     summary = ""
-    BUILD_TAG = ft_constants.CI_BUILD_TAG
-    if BUILD_TAG is not None and re.search("daily", BUILD_TAG) is not None:
-        CI_LOOP = "daily"
-    else:
-        CI_LOOP = "weekly"
-
     tiers_to_run = []
 
     for tier in tiers.get_tiers():
         if (len(tier.get_tests()) != 0 and
-                re.search(CI_LOOP, tier.get_ci_loop()) is not None):
+                re.search(CONST.CI_LOOP, tier.get_ci_loop()) is not None):
             tiers_to_run.append(tier)
             summary += ("\n    - %s:\n\t   %s"
                         % (tier.get_name(),
@@ -225,10 +224,10 @@ def run_all(tiers):
 
 def main():
 
-    CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-    CI_SCENARIO = ft_constants.CI_SCENARIO
+    CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE
+    CI_SCENARIO = CONST.DEPLOY_SCENARIO
 
-    file = ft_constants.FUNCTEST_TESTCASES_YAML
+    file = CONST.functest_testcases_yaml
     _tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, file)
 
     if args.noclean:
index 6a11a03..6f57c70 100755 (executable)
@@ -67,7 +67,9 @@ tiers:
                 dependencies:
                     installer: ''
                     scenario: ''
-
+                run:
+                    module: 'functest.opnfv_tests.openstack.tempest.tempest'
+                    class: 'TempestSmokeSerial'
             -
                 name: rally_sanity
                 criteria: 'success_rate == 100%'
@@ -109,7 +111,7 @@ tiers:
             -
                 name: connection_check
                 criteria: 'status == "PASS"'
-                blocking: true
+                blocking: false
                 description: >-
                     This test case verifies the retrieval of OpenStack clients:
                     Keystone, Glance, Neutron and Nova and may perform some
@@ -127,7 +129,7 @@ tiers:
             -
                 name: api_check
                 criteria: 'status == "PASS"'
-                blocking: true
+                blocking: false
                 description: >-
                     This test case verifies the retrieval of OpenStack clients:
                     Keystone, Glance, Neutron and Nova and may perform some
@@ -145,7 +147,7 @@ tiers:
             -
                 name: snaps_smoke
                 criteria: 'status == "PASS"'
-                blocking: true
+                blocking: false
                 description: >-
                     This test case contains tests that setup and destroy
                     environments with VMs with and without Floating IPs
@@ -222,6 +224,10 @@ tiers:
                 dependencies:
                     installer: '(apex)|(joid)'
                     scenario: '^((?!fdio|lxd).)*$'
+                run:
+                    module: 'functest.opnfv_tests.features.copper'
+                    class: 'Copper'
+
             -
                 name: moon
                 criteria: 'status == "PASS"'
@@ -240,6 +246,9 @@ tiers:
                 dependencies:
                     installer: '(fuel)|(compass)'
                     scenario: 'multisite'
+                run:
+                    module: 'functest.opnfv_tests.openstack.tempest.tempest'
+                    class: 'TempestMultisite'
             -
                 name: odl-sfc
                 criteria: 'status == "PASS"'
@@ -249,6 +258,9 @@ tiers:
                 dependencies:
                     installer: '(apex)|(fuel)'
                     scenario: 'odl_l2-sfc'
+                run:
+                    module: 'functest.opnfv_tests.features.odl_sfc'
+                    class: 'OpenDaylightSFC'
             -
                 name: onos_sfc
                 criteria: 'status == "PASS"'
@@ -271,7 +283,7 @@ tiers:
                     module: 'functest.opnfv_tests.vnf.rnc.parser'
                     class: 'Parser'
     -
-        name: openstack
+        name: components
         order: 3
         ci_loop: 'weekly'
         description : >-
@@ -288,6 +300,9 @@ tiers:
                 dependencies:
                     installer: ''
                     scenario: ''
+                run:
+                    module: 'functest.opnfv_tests.openstack.tempest.tempest'
+                    class: 'TempestFullParallel'
 
             -
                 name: rally_full
index 3b14fa3..cc697ed 100644 (file)
@@ -121,8 +121,11 @@ def testcase_show(testname):
 @click.option('-n', '--noclean', is_flag=True, default=False,
               help='The created openstack resources by the test'
               'will not be cleaned after the execution.')
-def testcase_run(testname, noclean):
-    _testcase.run(testname, noclean)
+@click.option('-r', '--report', is_flag=True, default=False,
+              help='Push results to the results DataBase. Only CI Pods'
+              'have rights to do that.')
+def testcase_run(testname, noclean, report):
+    _testcase.run(testname, noclean, report)
 
 
 @tier.command('list', help="Lists the available tiers.")
@@ -147,5 +150,8 @@ def tier_gettests(tiername):
 @click.option('-n', '--noclean', is_flag=True, default=False,
               help='The created openstack resources by the tests'
               'will not be cleaned after the execution.')
-def tier_run(tiername, noclean):
-    _tier.run(tiername, noclean)
+@click.option('-r', '--report', is_flag=True, default=False,
+              help='Push results to the results DataBase. Only CI Pods'
+              'have rights to do that.')
+def tier_run(tiername, noclean, report):
+    _tier.run(tiername, noclean, report)
index 9f793e7..9423631 100644 (file)
@@ -12,8 +12,8 @@ import os
 import click
 import git
 
+from functest.utils.constants import CONST
 import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_constants as ft_constants
 
 
 class CliEnv:
@@ -28,7 +28,7 @@ class CliEnv:
                                "it again? [y|n]\n")
             while True:
                 if answer.lower() in ["y", "yes"]:
-                    os.remove(ft_constants.ENV_FILE)
+                    os.remove(CONST.env_active)
                     break
                 elif answer.lower() in ["n", "no"]:
                     return
@@ -36,40 +36,32 @@ class CliEnv:
                     answer = raw_input("Invalid answer. Please type [y|n]\n")
 
         cmd = ("python %s/functest/ci/prepare_env.py start" %
-               ft_constants.FUNCTEST_REPO_DIR)
+               CONST.dir_repo_functest)
         ft_utils.execute_command(cmd)
 
     def show(self):
-        CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-        if CI_INSTALLER_TYPE is None:
-            CI_INSTALLER_TYPE = "Unknown"
-        CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP
-        if CI_INSTALLER_IP is None:
-            CI_INSTALLER_IP = "Unknown"
-        CI_INSTALLER = ("%s, %s" % (CI_INSTALLER_TYPE, CI_INSTALLER_IP))
-
-        CI_SCENARIO = ft_constants.CI_SCENARIO
-        if CI_SCENARIO is None:
-            CI_SCENARIO = "Unknown"
-
-        CI_NODE = ft_constants.CI_NODE
-        if CI_NODE is None:
-            CI_NODE = "Unknown"
-
-        repo = git.Repo(ft_constants.FUNCTEST_REPO_DIR)
-        branch = repo.head.reference
-        GIT_BRANCH = branch.name
-        GIT_HASH = branch.commit.hexsha
-
-        CI_BUILD_TAG = ft_constants.CI_BUILD_TAG
-        if CI_BUILD_TAG is not None:
-            CI_BUILD_TAG = CI_BUILD_TAG.lstrip(
+        def _get_value(attr, default='Unknown'):
+            return attr if attr else default
+
+        install_type = _get_value(CONST.INSTALLER_TYPE)
+        installer_ip = _get_value(CONST.INSTALLER_IP)
+        installer_info = ("%s, %s" % (install_type, installer_ip))
+        scenario = _get_value(CONST.DEPLOY_SCENARIO)
+        node = _get_value(CONST.NODE_NAME)
+        repo_h = git.Repo(CONST.dir_repo_functest).head
+        if repo_h.is_detached:
+            git_branch = 'detached from FETCH_HEAD'
+            git_hash = repo_h.commit.hexsha
+        else:
+            branch = repo_h.reference
+            git_branch = branch.name
+            git_hash = branch.commit.hexsha
+        is_debug = _get_value(CONST.CI_DEBUG, 'false')
+        build_tag = CONST.BUILD_TAG
+        if build_tag is not None:
+            build_tag = build_tag.lstrip(
                 "jenkins-").lstrip("functest").lstrip("-")
 
-        CI_DEBUG = ft_constants.CI_DEBUG
-        if CI_DEBUG is None:
-            CI_DEBUG = "false"
-
         STATUS = "not ready"
         if self.status(verbose=False) == 0:
             STATUS = "ready"
@@ -77,14 +69,14 @@ class CliEnv:
         click.echo("+======================================================+")
         click.echo("| Functest Environment info                            |")
         click.echo("+======================================================+")
-        click.echo("|  INSTALLER: %s|" % CI_INSTALLER.ljust(41))
-        click.echo("|   SCENARIO: %s|" % CI_SCENARIO.ljust(41))
-        click.echo("|        POD: %s|" % CI_NODE.ljust(41))
-        click.echo("| GIT BRACNH: %s|" % GIT_BRANCH.ljust(41))
-        click.echo("|   GIT HASH: %s|" % GIT_HASH.ljust(41))
-        if CI_BUILD_TAG:
-            click.echo("|  BUILD TAG: %s|" % CI_BUILD_TAG.ljust(41))
-        click.echo("| DEBUG FLAG: %s|" % CI_DEBUG.ljust(41))
+        click.echo("|  INSTALLER: %s|" % installer_info.ljust(41))
+        click.echo("|   SCENARIO: %s|" % scenario.ljust(41))
+        click.echo("|        POD: %s|" % node.ljust(41))
+        click.echo("| GIT BRACNH: %s|" % git_branch.ljust(41))
+        click.echo("|   GIT HASH: %s|" % git_hash.ljust(41))
+        if build_tag:
+            click.echo("|  BUILD TAG: %s|" % build_tag.ljust(41))
+        click.echo("| DEBUG FLAG: %s|" % is_debug.ljust(41))
         click.echo("+------------------------------------------------------+")
         click.echo("|     STATUS: %s|" % STATUS.ljust(41))
         click.echo("+------------------------------------------------------+")
@@ -92,7 +84,7 @@ class CliEnv:
 
     def status(self, verbose=True):
         ret_val = 0
-        if not os.path.isfile(ft_constants.ENV_FILE):
+        if not os.path.isfile(CONST.env_active):
             if verbose:
                 click.echo("Functest environment is not installed.\n")
             ret_val = 1
index bb85921..aeb3497 100644 (file)
@@ -12,23 +12,21 @@ import os
 
 import click
 
+from functest.utils.constants import CONST
 import functest.utils.functest_utils as ft_utils
 import functest.utils.openstack_clean as os_clean
 import functest.utils.openstack_snapshot as os_snapshot
-import functest.utils.functest_constants as ft_constants
-
-
-OPENSTACK_RC_FILE = ft_constants.OPENSTACK_CREDS
-OPENSTACK_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE
 
 
 class CliOpenStack:
 
     def __init__(self):
-        self.os_auth_url = ft_constants.OS_AUTH_URL
+        self.os_auth_url = CONST.OS_AUTH_URL
         self.endpoint_ip = None
         self.endpoint_port = None
-        if self.os_auth_url is not None:
+        self.openstack_creds = CONST.openstack_creds
+        self.snapshot_file = CONST.openstack_snapshot_file
+        if self.os_auth_url:
             self.endpoint_ip = self.os_auth_url.rsplit("/")[2].rsplit(":")[0]
             self.endpoint_port = self.os_auth_url.rsplit("/")[2].rsplit(":")[1]
 
@@ -43,13 +41,14 @@ class CliOpenStack:
             click.echo("Cannot talk to the endpoint %s\n" % self.endpoint_ip)
             exit(0)
 
-    def show_credentials(self):
+    @staticmethod
+    def show_credentials():
         for key, value in os.environ.items():
             if key.startswith('OS_'):
                 click.echo("{}={}".format(key, value))
 
     def fetch_credentials(self):
-        if os.path.isfile(OPENSTACK_RC_FILE):
+        if os.path.isfile(self.openstack_creds):
             answer = raw_input("It seems the RC file is already present. "
                                "Do you want to overwrite it? [y|n]\n")
             while True:
@@ -60,31 +59,31 @@ class CliOpenStack:
                 else:
                     answer = raw_input("Invalid answer. Please type [y|n]\n")
 
-        CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-        if CI_INSTALLER_TYPE is None:
+        installer_type = CONST.INSTALLER_TYPE
+        if installer_type is None:
             click.echo("The environment variable 'INSTALLER_TYPE' is not"
                        "defined. Please export it")
-        CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP
-        if CI_INSTALLER_IP is None:
+        installer_ip = CONST.INSTALLER_IP
+        if installer_ip is None:
             click.echo("The environment variable 'INSTALLER_IP' is not"
                        "defined. Please export it")
         cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
-               % (ft_constants.REPOS_DIR,
-                  OPENSTACK_RC_FILE,
-                  CI_INSTALLER_TYPE,
-                  CI_INSTALLER_IP))
+               % (CONST.dir_repos,
+                  self.openstack_creds,
+                  installer_type,
+                  installer_ip))
         click.echo("Fetching credentials from installer node '%s' with IP=%s.."
-                   % (CI_INSTALLER_TYPE, CI_INSTALLER_IP))
+                   % (installer_type, installer_ip))
         ft_utils.execute_command(cmd, verbose=False)
 
     def check(self):
         self.ping_endpoint()
-        cmd = ft_constants.FUNCTEST_REPO_DIR + "/functest/ci/check_os.sh"
+        cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
         ft_utils.execute_command(cmd, verbose=False)
 
     def snapshot_create(self):
         self.ping_endpoint()
-        if os.path.isfile(OPENSTACK_SNAPSHOT_FILE):
+        if os.path.isfile(self.snapshot_file):
             answer = raw_input("It seems there is already an OpenStack "
                                "snapshot. Do you want to overwrite it with "
                                "the current OpenStack status? [y|n]\n")
@@ -100,18 +99,18 @@ class CliOpenStack:
         os_snapshot.main()
 
     def snapshot_show(self):
-        if not os.path.isfile(OPENSTACK_SNAPSHOT_FILE):
+        if not os.path.isfile(self.snapshot_file):
             click.echo("There is no OpenStack snapshot created. To create "
                        "one run the command "
                        "'functest openstack snapshot-create'")
             return
-        with open(OPENSTACK_SNAPSHOT_FILE, 'r') as yaml_file:
+        with open(self.snapshot_file, 'r') as yaml_file:
             click.echo("\n%s"
                        % yaml_file.read())
 
     def clean(self):
         self.ping_endpoint()
-        if not os.path.isfile(OPENSTACK_SNAPSHOT_FILE):
+        if not os.path.isfile(self.snapshot_file):
             click.echo("Not possible to clean OpenStack without a snapshot. "
                        "This could cause problems. "
                        "Run first the command "
index efe177d..b656624 100644 (file)
@@ -14,19 +14,17 @@ import os
 import click
 
 import functest.ci.tier_builder as tb
+from functest.utils.constants import CONST
 import functest.utils.functest_utils as ft_utils
 import functest.utils.functest_vacation as vacation
-import functest.utils.functest_constants as ft_constants
 
 
 class CliTestcase:
 
     def __init__(self):
-        CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-        CI_SCENARIO = ft_constants.CI_SCENARIO
-        testcases = ft_constants.FUNCTEST_TESTCASES_YAML
-
-        self.tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, testcases)
+        self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
+                                    CONST.DEPLOY_SCENARIO,
+                                    CONST.functest_testcases_yaml)
 
     def list(self):
         summary = ""
@@ -43,17 +41,23 @@ class CliTestcase:
 
         click.echo(description)
 
-    def run(self, testname, noclean=False):
+    @staticmethod
+    def run(testname, noclean=False, report=False):
+
+        flags = ""
+        if noclean:
+            flags += "-n "
+        if report:
+            flags += "-r "
+
         if testname == 'vacation':
             vacation.main()
-        elif not os.path.isfile(ft_constants.ENV_FILE):
+        elif not os.path.isfile(CONST.env_active):
             click.echo("Functest environment is not ready. "
                        "Run first 'functest env prepare'")
         else:
-            if noclean:
-                cmd = ("python %s/functest/ci/run_tests.py "
-                       "-n -t %s" % (ft_constants.FUNCTEST_REPO_DIR, testname))
-            else:
+            tests = testname.split(",")
+            for test in tests:
                 cmd = ("python %s/functest/ci/run_tests.py "
-                       "-t %s" % (ft_constants.FUNCTEST_REPO_DIR, testname))
-            ft_utils.execute_command(cmd)
+                       "%s -t %s" % (CONST.dir_repo_functest, flags, test))
+                ft_utils.execute_command(cmd)
index 9da5107..b9d25b6 100644 (file)
@@ -14,17 +14,16 @@ import os
 import click
 
 import functest.ci.tier_builder as tb
+from functest.utils.constants import CONST
 import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_constants as ft_constants
 
 
 class CliTier:
 
     def __init__(self):
-        CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-        CI_SCENARIO = ft_constants.CI_SCENARIO
-        testcases = ft_constants.FUNCTEST_TESTCASES_YAML
-        self.tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, testcases)
+        self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
+                                    CONST.DEPLOY_SCENARIO,
+                                    CONST.functest_testcases_yaml)
 
     def list(self):
         summary = ""
@@ -54,15 +53,19 @@ class CliTier:
             tests = tier.get_test_names()
             click.echo("Test cases in tier '%s':\n %s\n" % (tiername, tests))
 
-    def run(self, tiername, noclean=False):
-        if not os.path.isfile(ft_constants.ENV_FILE):
+    @staticmethod
+    def run(tiername, noclean=False, report=False):
+
+        flags = ""
+        if noclean:
+            flags += "-n "
+        if report:
+            flags += "-r "
+
+        if not os.path.isfile(CONST.env_active):
             click.echo("Functest environment is not ready. "
                        "Run first 'functest env prepare'")
         else:
-            if noclean:
-                cmd = ("python %s/functest/ci/run_tests.py "
-                       "-n -t %s" % (ft_constants.FUNCTEST_REPO_DIR, tiername))
-            else:
-                cmd = ("python %s/functest/ci/run_tests.py "
-                       "-t %s" % (ft_constants.FUNCTEST_REPO_DIR, tiername))
+            cmd = ("python %s/functest/ci/run_tests.py "
+                   "%s -t %s" % (CONST.dir_repo_functest, flags, tiername))
             ft_utils.execute_command(cmd)
index 01a27f3..873e21d 100644 (file)
@@ -3,6 +3,7 @@ import time
 import testcase_base as base
 import functest.utils.functest_utils as ft_utils
 import functest.utils.functest_logger as ft_logger
+from functest.utils.constants import CONST
 
 
 class FeatureBase(base.TestcaseBase):
@@ -11,7 +12,7 @@ class FeatureBase(base.TestcaseBase):
         self.project_name = project
         self.case_name = case
         self.cmd = cmd
-        self.repo = self.get_conf('general.directories.{}'.format(repo))
+        self.repo = CONST.__getattribute__(repo)
         self.result_file = self.get_result_file()
         self.logger = ft_logger.Logger(project).getLogger()
 
@@ -44,15 +45,10 @@ class FeatureBase(base.TestcaseBase):
         return exit_code
 
     def get_result_file(self):
-        dir = self.get_conf('general.directories.dir_results')
-        return "{}/{}.log".format(dir, self.project_name)
+        return "{}/{}.log".format(CONST.dir_results, self.project_name)
 
     def log_results(self):
         ft_utils.logger_test_results(self.project_name,
                                      self.case_name,
                                      self.criteria,
                                      self.details)
-
-    @staticmethod
-    def get_conf(parameter):
-        return ft_utils.get_functest_config(parameter)
old mode 100644 (file)
new mode 100755 (executable)
index 2d5b266..1eed92b
@@ -41,8 +41,8 @@ class PyTestSuiteRunner(base.TestcaseBase):
             for test, message in result.failures:
                 self.logger.error(str(test) + " FAILED with " + message)
 
-        if (result.errors and len(result.errors) > 0) \
-                or (result.failures and len(result.failures) > 0):
+        if ((result.errors and len(result.errors) > 0)
+                or (result.failures and len(result.failures) > 0)):
             self.logger.info("%s FAILED" % self.case_name)
             self.criteria = 'FAIL'
             exit_code = base.TestcaseBase.EX_RUN_ERROR
index e869803..838b639 100644 (file)
@@ -18,6 +18,7 @@ class TestcaseBase(object):
     EX_OK = os.EX_OK
     EX_RUN_ERROR = os.EX_SOFTWARE
     EX_PUSH_TO_DB_ERROR = os.EX_SOFTWARE - 1
+    EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2
 
     logger = ft_logger.Logger(__name__).getLogger()
 
@@ -29,6 +30,15 @@ class TestcaseBase(object):
         self.start_time = ""
         self.stop_time = ""
 
+    def check_criteria(self):
+        try:
+            assert self.criteria
+            if self.criteria == 'PASS':
+                return TestcaseBase.EX_OK
+        except:
+            self.logger.error("Please run test before checking the results")
+        return TestcaseBase.EX_TESTCASE_FAILED
+
     def run(self, **kwargs):
         self.logger.error("Run must be implemented")
         return TestcaseBase.EX_RUN_ERROR
index d003779..8d5393c 100755 (executable)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-import argparse
-import sys
-import time
+import functest.core.feature_base as base
 
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as functest_utils
-import functest.utils.functest_constants as ft_constants
 
-parser = argparse.ArgumentParser()
-parser.add_argument("-r", "--report",
-                    help="Create json result file",
-                    action="store_true")
-args = parser.parse_args()
-
-COPPER_REPO_DIR = ft_constants.COPPER_REPO_DIR
-RESULTS_DIR = ft_constants.FUNCTEST_RESULTS_DIR
-
-logger = ft_logger.Logger("copper").getLogger()
-
-
-def main():
-    cmd = "%s/tests/run.sh %s/tests" % (COPPER_REPO_DIR, COPPER_REPO_DIR)
-
-    start_time = time.time()
-
-    log_file = RESULTS_DIR + "/copper.log"
-    ret_val = functest_utils.execute_command(cmd,
-                                             output_file=log_file)
-
-    stop_time = time.time()
-    duration = round(stop_time - start_time, 1)
-    if ret_val == 0:
-        logger.info("COPPER PASSED")
-        test_status = 'PASS'
-    else:
-        logger.info("COPPER FAILED")
-        test_status = 'FAIL'
-
-    details = {
-        'timestart': start_time,
-        'duration': duration,
-        'status': test_status,
-    }
-    functest_utils.logger_test_results("Copper",
-                                       "copper-notification",
-                                       details['status'], details)
-    try:
-        if args.report:
-            functest_utils.push_results_to_db("copper",
-                                              "copper-notification",
-                                              start_time,
-                                              stop_time,
-                                              details['status'],
-                                              details)
-            logger.info("COPPER results pushed to DB")
-    except:
-        logger.error("Error pushing results into Database '%s'"
-                     % sys.exc_info()[0])
-
-    if ret_val != 0:
-        sys.exit(-1)
-
-    sys.exit(0)
-
-
-if __name__ == '__main__':
-    main()
+class Copper(base.FeatureBase):
+    def __init__(self):
+        super(Copper, self).__init__(project='copper',
+                                     case='copper-notification',
+                                     repo='dir_repo_copper')
+        self.cmd = "%s/tests/run.sh %s/tests" % (self.repo, self.repo)
index 341648f..b36220f 100755 (executable)
 # 0.3: add report flag to push results when needed
 # 0.4: refactoring to match Test abstraction class
 
-import argparse
-import os
-import sys
-import time
+import functest.core.feature_base as base
 
-import functest.core.testcase_base as testcase_base
-import functest.utils.functest_constants as ft_constants
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
-
-
-class DominoCases(testcase_base.TestcaseBase):
-    DOMINO_REPO = ft_constants.DOMINO_REPO_DIR
-    RESULTS_DIR = ft_constants.FUNCTEST_RESULTS_DIR
-    logger = ft_logger.Logger("domino").getLogger()
 
+class Domino(base.FeatureBase):
     def __init__(self):
-        super(DominoCases, self).__init__()
-        self.project_name = "domino"
-        self.case_name = "domino-multinode"
-
-    def main(self, **kwargs):
-        cmd = 'cd %s && ./tests/run_multinode.sh' % self.DOMINO_REPO
-        log_file = os.path.join(self.RESULTS_DIR, "domino.log")
-        start_time = time.time()
-
-        ret = ft_utils.execute_command(cmd,
-                                       output_file=log_file)
-
-        stop_time = time.time()
-        if ret == 0:
-            self.logger.info("domino OK")
-            status = 'PASS'
-        else:
-            self.logger.info("domino FAILED")
-            status = "FAIL"
-
-        # report status only if tests run (FAIL OR PASS)
-        self.criteria = status
-        self.start_time = start_time
-        self.stop_time = stop_time
-        self.details = {}
-
-    def run(self):
-        kwargs = {}
-        return self.main(**kwargs)
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-    parser.add_argument("-r", "--report",
-                        help="Create json result file",
-                        action="store_true")
-    args = vars(parser.parse_args())
-    domino = DominoCases()
-    try:
-        result = domino.main(**args)
-        if result != testcase_base.TestcaseBase.EX_OK:
-            sys.exit(result)
-        if args['report']:
-            sys.exit(domino.push_to_db())
-    except Exception:
-        sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR)
+        super(Domino, self).__init__(project='domino',
+                                     case='domino-multinode',
+                                     repo='dir_repo_domino')
+        self.cmd = 'cd %s && ./tests/run_multinode.sh' % self.repo
diff --git a/functest/opnfv_tests/features/odl_sfc.py b/functest/opnfv_tests/features/odl_sfc.py
new file mode 100644 (file)
index 0000000..3b68d42
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2016 All rights reserved
+# This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+import functest.core.feature_base as base
+
+
+class OpenDaylightSFC(base.FeatureBase):
+
+    def __init__(self):
+        super(OpenDaylightSFC, self).__init__(project='sfc',
+                                              case='functest-odl-sfc"',
+                                              repo='dir_repo_sfc')
+        dir_sfc_functest = '{}/sfc/tests/functest'.format(self.repo)
+        self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
old mode 100644 (file)
new mode 100755 (executable)
index 451299e..1919a03
@@ -7,70 +7,14 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 #
+import functest.core.feature_base as base
 
 
-import argparse
-import os
-import sys
-import time
-
-import functest.core.testcase_base as testcase_base
-import functest.utils.functest_constants as ft_constants
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
-
-
-class SdnVpnTests(testcase_base.TestcaseBase):
-    SDNVPN_REPO_TESTS = os.path.join(
-        ft_constants.SDNVPN_REPO_DIR, "tests/functest")
-    logger = ft_logger.Logger("sdnvpn").getLogger()
+class SdnVpnTests(base.FeatureBase):
 
     def __init__(self):
-        super(SdnVpnTests, self).__init__()
-        self.project_name = "sdnvpn"
-        self.case_name = "bgpvpn"
-
-    def main(self, **kwargs):
-        os.chdir(self.SDNVPN_REPO_TESTS)
-        cmd = 'run_tests.py'
-        log_file = os.path.join(
-            ft_constants.FUNCTEST_RESULTS_DIR, "sdnvpn.log")
-        start_time = time.time()
-
-        ret = ft_utils.execute_command(cmd,
-                                       output_file=log_file)
-
-        stop_time = time.time()
-        if ret == 0:
-            self.logger.info("%s OK" % self.case_name)
-            status = 'PASS'
-        else:
-            self.logger.info("%s FAILED" % self.case_name)
-            status = "FAIL"
-
-        # report status only if tests run (FAIL OR PASS)
-        self.criteria = status
-        self.start_time = start_time
-        self.stop_time = stop_time
-        self.details = {}
-
-    def run(self):
-        kwargs = {}
-        return self.main(**kwargs)
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-    parser.add_argument("-r", "--report",
-                        help="Create json result file",
-                        action="store_true")
-    args = vars(parser.parse_args())
-    sdnvpn = SdnVpnTests()
-    try:
-        result = sdnvpn.main(**args)
-        if result != testcase_base.TestcaseBase.EX_OK:
-            sys.exit(result)
-        if args['report']:
-            sys.exit(sdnvpn.push_to_db())
-    except Exception:
-        sys.exit(testcase_base.TestcaseBase.EX_RUN_ERROR)
+        super(SdnVpnTests, self).__init__(project='sdnvpn',
+                                          case='bgpvpn',
+                                          repo='dir_repo_sdnvpn')
+        dir_sfc_functest = '{}/sdnvpn/test/functest'.format(self.repo)
+        self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
index b4e2e51..b440086 100755 (executable)
@@ -14,9 +14,9 @@ import argparse
 import os
 import sys
 
+from functest.utils.constants import CONST
 import functest.utils.functest_logger as ft_logger
 import functest.utils.openstack_utils as os_utils
-import functest.utils.functest_constants as ft_constants
 
 parser = argparse.ArgumentParser()
 
@@ -29,26 +29,26 @@ args = parser.parse_args()
 """ logging configuration """
 logger = ft_logger.Logger("create_instance_and_ip").getLogger()
 
-HOME = ft_constants.HOME + "/"
+HOME = CONST.dir_home + "/"
 
 VM_BOOT_TIMEOUT = 180
 
-EXAMPLE_INSTANCE_NAME = ft_constants.EXAMPLE_INSTANCE_NAME
-EXAMPLE_FLAVOR = ft_constants.EXAMPLE_FLAVOR
-EXAMPLE_IMAGE_NAME = ft_constants.EXAMPLE_IMAGE_NAME
-IMAGE_FILENAME = ft_constants.GLANCE_IMAGE_FILENAME
-IMAGE_FORMAT = ft_constants.GLANCE_IMAGE_FORMAT
-IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR, IMAGE_FILENAME)
+EXAMPLE_INSTANCE_NAME = CONST.example_vm_name
+EXAMPLE_FLAVOR = CONST.example_flavor
+EXAMPLE_IMAGE_NAME = CONST.example_image_name
+IMAGE_FILENAME = CONST.openstack_image_file_name
+IMAGE_FORMAT = CONST.openstack_image_disk_format
+IMAGE_PATH = os.path.join(CONST.dir_functest_data, IMAGE_FILENAME)
 
 # NEUTRON Private Network parameters
 
-EXAMPLE_PRIVATE_NET_NAME = ft_constants.EXAMPLE_PRIVATE_NET_NAME
-EXAMPLE_PRIVATE_SUBNET_NAME = ft_constants.EXAMPLE_PRIVATE_SUBNET_NAME
-EXAMPLE_PRIVATE_SUBNET_CIDR = ft_constants.EXAMPLE_PRIVATE_SUBNET_CIDR
-EXAMPLE_ROUTER_NAME = ft_constants.EXAMPLE_ROUTER_NAME
+EXAMPLE_PRIVATE_NET_NAME = CONST.example_private_net_name
+EXAMPLE_PRIVATE_SUBNET_NAME = CONST.example_private_subnet_name
+EXAMPLE_PRIVATE_SUBNET_CIDR = CONST.example_private_subnet_cidr
+EXAMPLE_ROUTER_NAME = CONST.example_router_name
 
-EXAMPLE_SECGROUP_NAME = ft_constants.EXAMPLE_SECGROUP_NAME
-EXAMPLE_SECGROUP_DESCR = ft_constants.EXAMPLE_SECGROUP_DESCR
+EXAMPLE_SECGROUP_NAME = CONST.example_sg_name
+EXAMPLE_SECGROUP_DESCR = CONST.example_sg_desc
 
 
 def main():
@@ -64,11 +64,12 @@ def main():
                                             container="bare",
                                             public=True)
 
-    network_dic = os_utils.create_network_full(neutron_client,
-                                               EXAMPLE_PRIVATE_NET_NAME,
-                                               EXAMPLE_PRIVATE_SUBNET_NAME,
-                                               EXAMPLE_ROUTER_NAME,
-                                               EXAMPLE_PRIVATE_SUBNET_CIDR)
+    network_dic = os_utils.create_network_full(
+                    neutron_client,
+                    EXAMPLE_PRIVATE_NET_NAME,
+                    EXAMPLE_PRIVATE_SUBNET_NAME,
+                    EXAMPLE_ROUTER_NAME,
+                    EXAMPLE_PRIVATE_SUBNET_CIDR)
     if not network_dic:
         logger.error(
             "There has been a problem when creating the neutron network")
@@ -86,11 +87,11 @@ def main():
         "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
         "network=%s \n"
         % (EXAMPLE_INSTANCE_NAME, EXAMPLE_FLAVOR, image_id, network_id))
-    instance = \
-        os_utils.create_instance_and_wait_for_active(EXAMPLE_FLAVOR,
-                                                     image_id,
-                                                     network_id,
-                                                     EXAMPLE_INSTANCE_NAME)
+    instance = os_utils.create_instance_and_wait_for_active(
+                EXAMPLE_FLAVOR,
+                image_id,
+                network_id,
+                EXAMPLE_INSTANCE_NAME)
 
     if instance is None:
         logger.error("Error while booting instance.")
index e27cf4b..57aa0c7 100755 (executable)
@@ -228,10 +228,11 @@ sleep ${wait_time}
 
 
 # Check if flavor exists
-if [[ -z $(nova flavor-list|grep $flavor) ]]; then
+if [[ -z $(openstack flavor list -f value -c Name | fgrep -x $flavor) ]]; then
     # if given flavor doesn't exist, we create one
     debug "Flavor $flavor doesn't exist. Creating a new flavor."
-    nova flavor-create --is-public false ${flavor} auto 512 1 1 --is-public True
+    openstack flavor create ${flavor} --id auto --ram 512 --disk 1 --vcpus 1
+    openstack flavor set ${flavor} --property hw:mem_page_size=any
 fi
 debug "Using flavor $flavor to boot the instances."
 
index 6d8f016..ec22b52 100755 (executable)
 #
 """ tests configuration """
 
+import argparse
 import json
 import os
 import re
 import subprocess
 import time
 
-import argparse
 import iniparse
 import yaml
 
+from functest.utils.constants import CONST
 import functest.utils.functest_logger as ft_logger
 import functest.utils.functest_utils as ft_utils
 import functest.utils.openstack_utils as os_utils
-import functest.utils.functest_constants as ft_constants
 
 tests = ['authenticate', 'glance', 'cinder', 'heat', 'keystone',
          'neutron', 'nova', 'quotas', 'requests', 'vm', 'all']
@@ -71,8 +71,7 @@ else:
 """ logging configuration """
 logger = ft_logger.Logger("run_rally-cert").getLogger()
 
-RALLY_DIR = os.path.join(ft_constants.FUNCTEST_REPO_DIR,
-                         ft_constants.RALLY_RELATIVE_PATH)
+RALLY_DIR = os.path.join(CONST.dir_repo_functest, CONST.dir_rally)
 RALLY_SCENARIO_DIR = os.path.join(RALLY_DIR, "scenario")
 SANITY_MODE_DIR = os.path.join(RALLY_SCENARIO_DIR, "sanity")
 FULL_MODE_DIR = os.path.join(RALLY_SCENARIO_DIR, "full")
@@ -87,19 +86,19 @@ TENANTS_AMOUNT = 3
 ITERATIONS_AMOUNT = 10
 CONCURRENCY = 4
 
-RESULTS_DIR = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, 'rally')
-TEMPEST_CONF_FILE = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR,
+RESULTS_DIR = os.path.join(CONST.dir_results, 'rally')
+TEMPEST_CONF_FILE = os.path.join(CONST.dir_results,
                                  'tempest/tempest.conf')
 
-RALLY_PRIVATE_NET_NAME = ft_constants.RALLY_PRIVATE_NET_NAME
-RALLY_PRIVATE_SUBNET_NAME = ft_constants.RALLY_PRIVATE_SUBNET_NAME
-RALLY_PRIVATE_SUBNET_CIDR = ft_constants.RALLY_PRIVATE_SUBNET_CIDR
-RALLY_ROUTER_NAME = ft_constants.RALLY_ROUTER_NAME
+RALLY_PRIVATE_NET_NAME = CONST.rally_network_name
+RALLY_PRIVATE_SUBNET_NAME = CONST.rally_subnet_name
+RALLY_PRIVATE_SUBNET_CIDR = CONST.rally_subnet_cidr
+RALLY_ROUTER_NAME = CONST.rally_router_name
 
-GLANCE_IMAGE_NAME = ft_constants.GLANCE_IMAGE_NAME
-GLANCE_IMAGE_FILENAME = ft_constants.GLANCE_IMAGE_FILENAME
-GLANCE_IMAGE_FORMAT = ft_constants.GLANCE_IMAGE_FORMAT
-GLANCE_IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR,
+GLANCE_IMAGE_NAME = CONST.openstack_image_name
+GLANCE_IMAGE_FILENAME = CONST.openstack_image_file_name
+GLANCE_IMAGE_FORMAT = CONST.openstack_image_disk_format
+GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data,
                                  GLANCE_IMAGE_FILENAME)
 CINDER_VOLUME_TYPE_NAME = "volume_test"
 
@@ -181,7 +180,7 @@ def build_task_args(test_file_name):
     net_id = GlobalVariables.network_dict['net_id']
     task_args['netid'] = str(net_id)
 
-    auth_url = ft_constants.OS_AUTH_URL
+    auth_url = CONST.OS_AUTH_URL
     if auth_url is not None:
         task_args['request_url'] = auth_url.rsplit(":", 1)[0]
     else:
@@ -271,8 +270,8 @@ def excl_scenario():
         with open(BLACKLIST_FILE, 'r') as black_list_file:
             black_list_yaml = yaml.safe_load(black_list_file)
 
-        installer_type = ft_constants.CI_INSTALLER_TYPE
-        deploy_scenario = ft_constants.CI_SCENARIO
+        installer_type = CONST.INSTALLER_TYPE
+        deploy_scenario = CONST.DEPLOY_SCENARIO
         if (bool(installer_type) * bool(deploy_scenario)):
             if 'scenario' in black_list_yaml.keys():
                 for item in black_list_yaml['scenario']:
index e6ee81e..17d05b9 100644 (file)
@@ -5,11 +5,13 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-import functest.utils.functest_utils as ft_utils
+import unittest
+
+from snaps import test_suite_builder
+
 from functest.core.pytest_suite_runner import PyTestSuiteRunner
 from functest.opnfv_tests.openstack.snaps import snaps_utils
-from snaps import test_suite_builder
-import unittest
+from functest.utils.constants import CONST
 
 
 class ApiCheck(PyTestSuiteRunner):
@@ -22,10 +24,11 @@ class ApiCheck(PyTestSuiteRunner):
         super(ApiCheck, self).__init__()
 
         self.suite = unittest.TestSuite()
-        creds_file = ft_utils.get_functest_config('general.openstack.creds')
-        use_key = ft_utils.get_functest_config('snaps.use_keystone')
+        self.case_name = "api_check"
         ext_net_name = snaps_utils.get_ext_net_name()
 
-        test_suite_builder.add_openstack_api_tests(self.suite, creds_file,
-                                                   ext_net_name,
-                                                   use_keystone=use_key)
+        test_suite_builder.add_openstack_api_tests(
+            self.suite,
+            CONST.openstack_creds,
+            ext_net_name,
+            use_keystone=CONST.snaps_use_keystone)
index 42e38d6..11f8ad0 100644 (file)
@@ -5,11 +5,13 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-import functest.utils.functest_utils as ft_utils
+import unittest
+
+from snaps import test_suite_builder
+
 from functest.core.pytest_suite_runner import PyTestSuiteRunner
 from functest.opnfv_tests.openstack.snaps import snaps_utils
-from snaps import test_suite_builder
-import unittest
+from functest.utils.constants import CONST
 
 
 class ConnectionCheck(PyTestSuiteRunner):
@@ -22,10 +24,11 @@ class ConnectionCheck(PyTestSuiteRunner):
         super(ConnectionCheck, self).__init__()
 
         self.suite = unittest.TestSuite()
-        creds_file = ft_utils.get_functest_config('general.openstack.creds')
-        use_key = ft_utils.get_functest_config('snaps.use_keystone')
+        self.case_name = "connection_check"
         ext_net_name = snaps_utils.get_ext_net_name()
 
-        test_suite_builder.add_openstack_client_tests(self.suite, creds_file,
-                                                      ext_net_name,
-                                                      use_keystone=use_key)
+        test_suite_builder.add_openstack_client_tests(
+            self.suite,
+            CONST.openstack_creds,
+            ext_net_name,
+            use_keystone=CONST.snaps_use_keystone)
index 25433a3..83eb660 100644 (file)
@@ -5,12 +5,14 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-import functest.utils.functest_utils as ft_utils
+import os
+import unittest
+
+from snaps import test_suite_builder
+
 from functest.core.pytest_suite_runner import PyTestSuiteRunner
 from functest.opnfv_tests.openstack.snaps import snaps_utils
-from snaps import test_suite_builder
-import unittest
-import os
+from functest.utils.constants import CONST
 
 
 class SnapsSmoke(PyTestSuiteRunner):
@@ -23,18 +25,19 @@ class SnapsSmoke(PyTestSuiteRunner):
         super(SnapsSmoke, self).__init__()
 
         self.suite = unittest.TestSuite()
-        creds_file = ft_utils.get_functest_config('general.openstack.creds')
-        use_key = ft_utils.get_functest_config('snaps.use_keystone')
-        use_fip = ft_utils.get_functest_config('snaps.use_floating_ips')
+        self.case_name = "snaps_smoke"
+        use_fip = CONST.snaps_use_floating_ips
         ext_net_name = snaps_utils.get_ext_net_name()
 
         # Tests requiring floating IPs leverage files contained within the
         # SNAPS repository and are found relative to that path
         if use_fip:
-            snaps_dir = ft_utils.get_functest_config(
-                'general.directories.dir_repo_snaps') + '/snaps'
+            snaps_dir = CONST.dir_repo_snaps + '/snaps'
             os.chdir(snaps_dir)
 
         test_suite_builder.add_openstack_integration_tests(
-            self.suite, creds_file, ext_net_name, use_keystone=use_key,
+            self.suite,
+            CONST.openstack_creds,
+            ext_net_name,
+            use_keystone=CONST.snaps_use_keystone,
             use_floating_ips=use_fip)
index a25ad3e..4ea1a04 100644 (file)
@@ -5,17 +5,18 @@
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 
-import functest.utils.functest_utils as ft_utils
 from snaps.openstack.tests import openstack_tests
 from snaps.openstack.utils import neutron_utils
 
+from functest.utils.constants import CONST
+
 
 def get_ext_net_name():
     """
     Returns the first external network name
     :return:
     """
-    os_env_file = ft_utils.get_functest_config('general.openstack.creds')
+    os_env_file = CONST.openstack_creds
     os_creds = openstack_tests.get_credentials(os_env_file=os_env_file)
     neutron = neutron_utils.neutron_client(os_creds)
     ext_nets = neutron_utils.get_external_networks(neutron)
diff --git a/functest/opnfv_tests/openstack/tempest/__init__.py b/functest/opnfv_tests/openstack/tempest/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
new file mode 100644 (file)
index 0000000..5295ff3
--- /dev/null
@@ -0,0 +1,190 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2015 All rights reserved
+# This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+import ConfigParser
+import os
+import re
+import shutil
+
+import opnfv.utils.constants as releng_constants
+
+import functest.utils.functest_utils as ft_utils
+from functest.utils.constants import CONST
+
+IMAGE_ID_ALT = None
+FLAVOR_ID_ALT = None
+REPO_PATH = CONST.dir_repo_functest
+GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data,
+                                 CONST.openstack_image_file_name)
+TEMPEST_TEST_LIST_DIR = CONST.dir_tempest_cases
+TEMPEST_RESULTS_DIR = os.path.join(CONST.dir_results,
+                                   'tempest')
+TEMPEST_CUSTOM = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
+                              'test_list.txt')
+TEMPEST_BLACKLIST = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
+                                 'blacklist.txt')
+TEMPEST_DEFCORE = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
+                               'defcore_req.txt')
+TEMPEST_RAW_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_raw_list.txt')
+TEMPEST_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_list.txt')
+
+CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE
+CI_INSTALLER_IP = CONST.INSTALLER_IP
+
+
+def configure_tempest(logger, deployment_dir, IMAGE_ID=None, FLAVOR_ID=None):
+    """
+    Add/update needed parameters into tempest.conf file generated by Rally
+    """
+    tempest_conf_file = deployment_dir + "/tempest.conf"
+    if os.path.isfile(tempest_conf_file):
+        logger.debug("Deleting old tempest.conf file...")
+        os.remove(tempest_conf_file)
+
+    logger.debug("Generating new tempest.conf file...")
+    cmd = "rally verify genconfig"
+    ft_utils.execute_command(cmd)
+
+    logger.debug("Finding tempest.conf file...")
+    if not os.path.isfile(tempest_conf_file):
+        logger.error("Tempest configuration file %s NOT found."
+                     % tempest_conf_file)
+        return releng_constants.EXIT_RUN_ERROR
+
+    logger.debug("Updating selected tempest.conf parameters...")
+    config = ConfigParser.RawConfigParser()
+    config.read(tempest_conf_file)
+    config.set(
+        'compute',
+        'fixed_network_name',
+        CONST.tempest_private_net_name)
+    if CONST.tempest_use_custom_images:
+        if IMAGE_ID is not None:
+            config.set('compute', 'image_ref', IMAGE_ID)
+        if IMAGE_ID_ALT is not None:
+            config.set('compute', 'image_ref_alt', IMAGE_ID_ALT)
+    if CONST.tempest_use_custom_flavors:
+        if FLAVOR_ID is not None:
+            config.set('compute', 'flavor_ref', FLAVOR_ID)
+        if FLAVOR_ID_ALT is not None:
+            config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT)
+    config.set('identity', 'tenant_name', CONST.tempest_identity_tenant_name)
+    config.set('identity', 'username', CONST.tempest_identity_user_name)
+    config.set('identity', 'password', CONST.tempest_identity_user_password)
+    config.set(
+        'validation', 'ssh_timeout', CONST.tempest_validation_ssh_timeout)
+
+    if CONST.OS_ENDPOINT_TYPE is not None:
+        services_list = ['compute',
+                         'volume',
+                         'image',
+                         'network',
+                         'data-processing',
+                         'object-storage',
+                         'orchestration']
+        sections = config.sections()
+        for service in services_list:
+            if service not in sections:
+                config.add_section(service)
+            config.set(service, 'endpoint_type',
+                       CONST.OS_ENDPOINT_TYPE)
+
+    with open(tempest_conf_file, 'wb') as config_file:
+        config.write(config_file)
+
+    # Copy tempest.conf to /home/opnfv/functest/results/tempest/
+    shutil.copyfile(
+        tempest_conf_file, TEMPEST_RESULTS_DIR + '/tempest.conf')
+
+    return releng_constants.EXIT_OK
+
+
+def configure_tempest_multisite(logger, deployment_dir):
+    """
+    Add/update needed parameters into tempest.conf file generated by Rally
+    """
+    logger.debug("configure the tempest")
+    configure_tempest(logger, deployment_dir)
+
+    logger.debug("Finding tempest.conf file...")
+    tempest_conf_old = os.path.join(deployment_dir, '/tempest.conf')
+    if not os.path.isfile(tempest_conf_old):
+        logger.error("Tempest configuration file %s NOT found."
+                     % tempest_conf_old)
+        return releng_constants.EXIT_RUN_ERROR
+
+    # Copy tempest.conf to /home/opnfv/functest/results/tempest/
+    cur_path = os.path.split(os.path.realpath(__file__))[0]
+    tempest_conf_file = os.path.join(cur_path, '/tempest_multisite.conf')
+    shutil.copyfile(tempest_conf_old, tempest_conf_file)
+
+    logger.debug("Updating selected tempest.conf parameters...")
+    config = ConfigParser.RawConfigParser()
+    config.read(tempest_conf_file)
+
+    config.set('service_available', 'kingbird', 'true')
+    cmd = ("openstack endpoint show kingbird | grep publicurl |"
+           "awk '{print $4}' | awk -F '/' '{print $4}'")
+    kingbird_api_version = os.popen(cmd).read()
+    if CI_INSTALLER_TYPE == 'fuel':
+        # For MOS based setup, the service is accessible
+        # via bind host
+        kingbird_conf_path = "/etc/kingbird/kingbird.conf"
+        installer_type = CI_INSTALLER_TYPE
+        installer_ip = CI_INSTALLER_IP
+        installer_username = CONST.__getattribute__(
+            'multisite_{}_installer_username'.format(installer_type))
+        installer_password = CONST.__getattribute__(
+            'multisite_{}_installer_password'.format(installer_type))
+
+        ssh_options = ("-o UserKnownHostsFile=/dev/null -o "
+                       "StrictHostKeyChecking=no")
+
+        # Get the controller IP from the fuel node
+        cmd = 'sshpass -p %s ssh 2>/dev/null %s %s@%s \
+                \'fuel node --env 1| grep controller | grep "True\|  1" \
+                | awk -F\| "{print \$5}"\'' % (installer_password,
+                                               ssh_options,
+                                               installer_username,
+                                               installer_ip)
+        multisite_controller_ip = "".join(os.popen(cmd).read().split())
+
+        # Login to controller and get bind host details
+        cmd = 'sshpass -p %s ssh 2>/dev/null  %s %s@%s "ssh %s \\" \
+            grep -e "^bind_" %s  \\""' % (installer_password,
+                                          ssh_options,
+                                          installer_username,
+                                          installer_ip,
+                                          multisite_controller_ip,
+                                          kingbird_conf_path)
+        bind_details = os.popen(cmd).read()
+        bind_details = "".join(bind_details.split())
+        # Extract port number from the bind details
+        bind_port = re.findall(r"\D(\d{4})", bind_details)[0]
+        # Extract ip address from the bind details
+        bind_host = re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",
+                               bind_details)[0]
+        kingbird_endpoint_url = "http://%s:%s/" % (bind_host, bind_port)
+    else:
+        cmd = "openstack endpoint show kingbird | grep publicurl |\
+               awk '{print $4}' | awk -F '/' '{print $3}'"
+        kingbird_endpoint_url = os.popen(cmd).read()
+
+    try:
+        config.add_section("kingbird")
+    except Exception:
+        logger.info('kingbird section exist')
+    config.set('kingbird', 'endpoint_type', 'publicURL')
+    config.set('kingbird', 'TIME_TO_SYNC', '20')
+    config.set('kingbird', 'endpoint_url', kingbird_endpoint_url)
+    config.set('kingbird', 'api_version', kingbird_api_version)
+    with open(tempest_conf_file, 'wb') as config_file:
+        config.write(config_file)
+
+    return releng_constants.EXIT_OK
diff --git a/functest/opnfv_tests/openstack/tempest/gen_tempest_conf.py b/functest/opnfv_tests/openstack/tempest/gen_tempest_conf.py
deleted file mode 100755 (executable)
index 1216a67..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Execute Multisite Tempest test cases
-##
-
-import ConfigParser
-import os
-import re
-import shutil
-import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_logger as ft_logger
-from run_tempest import configure_tempest
-from run_tempest import TEMPEST_RESULTS_DIR
-import functest.utils.functest_constants as ft_constants
-
-logger = ft_logger.Logger("gen_tempest_conf").getLogger()
-
-CI_INSTALLER_TYPE = ft_constants.CI_INSTALLER_TYPE
-CI_INSTALLER_IP = ft_constants.CI_INSTALLER_IP
-
-
-def configure_tempest_multisite(deployment_dir):
-    """
-    Add/update needed parameters into tempest.conf file generated by Rally
-    """
-    logger.debug("configure the tempest")
-    configure_tempest(deployment_dir)
-
-    logger.debug("Finding tempest.conf file...")
-    tempest_conf_old = os.path.join(deployment_dir, '/tempest.conf')
-    if not os.path.isfile(tempest_conf_old):
-        logger.error("Tempest configuration file %s NOT found."
-                     % tempest_conf_old)
-        exit(-1)
-
-    # Copy tempest.conf to /home/opnfv/functest/results/tempest/
-    cur_path = os.path.split(os.path.realpath(__file__))[0]
-    tempest_conf_file = os.path.join(cur_path, '/tempest_multisite.conf')
-    shutil.copyfile(tempest_conf_old, tempest_conf_file)
-
-    logger.debug("Updating selected tempest.conf parameters...")
-    config = ConfigParser.RawConfigParser()
-    config.read(tempest_conf_file)
-
-    config.set('service_available', 'kingbird', 'true')
-    cmd = ("openstack endpoint show kingbird | grep publicurl |"
-           "awk '{print $4}' | awk -F '/' '{print $4}'")
-    kingbird_api_version = os.popen(cmd).read()
-    if CI_INSTALLER_TYPE == 'fuel':
-        # For MOS based setup, the service is accessible
-        # via bind host
-        kingbird_conf_path = "/etc/kingbird/kingbird.conf"
-        installer_type = CI_INSTALLER_TYPE
-        installer_ip = CI_INSTALLER_IP
-        installer_username = ft_utils.get_functest_config(
-            "multisite." + installer_type +
-            "_environment.installer_username")
-        installer_password = ft_utils.get_functest_config(
-            "multisite." + installer_type +
-            "_environment.installer_password")
-
-        ssh_options = ("-o UserKnownHostsFile=/dev/null -o "
-                       "StrictHostKeyChecking=no")
-
-        # Get the controller IP from the fuel node
-        cmd = 'sshpass -p %s ssh 2>/dev/null %s %s@%s \
-                \'fuel node --env 1| grep controller | grep "True\|  1" \
-                | awk -F\| "{print \$5}"\'' % (installer_password,
-                                               ssh_options,
-                                               installer_username,
-                                               installer_ip)
-        multisite_controller_ip = "".join(os.popen(cmd).read().split())
-
-        # Login to controller and get bind host details
-        cmd = 'sshpass -p %s ssh 2>/dev/null  %s %s@%s "ssh %s \\" \
-            grep -e "^bind_" %s  \\""' % (installer_password,
-                                          ssh_options,
-                                          installer_username,
-                                          installer_ip,
-                                          multisite_controller_ip,
-                                          kingbird_conf_path)
-        bind_details = os.popen(cmd).read()
-        bind_details = "".join(bind_details.split())
-        # Extract port number from the bind details
-        bind_port = re.findall(r"\D(\d{4})", bind_details)[0]
-        # Extract ip address from the bind details
-        bind_host = re.findall(r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}",
-                               bind_details)[0]
-        kingbird_endpoint_url = "http://%s:%s/" % (bind_host, bind_port)
-    else:
-        cmd = "openstack endpoint show kingbird | grep publicurl |\
-               awk '{print $4}' | awk -F '/' '{print $3}'"
-        kingbird_endpoint_url = os.popen(cmd).read()
-
-    try:
-        config.add_section("kingbird")
-    except Exception:
-        logger.info('kingbird section exist')
-    config.set('kingbird', 'endpoint_type', 'publicURL')
-    config.set('kingbird', 'TIME_TO_SYNC', '20')
-    config.set('kingbird', 'endpoint_url', kingbird_endpoint_url)
-    config.set('kingbird', 'api_version', kingbird_api_version)
-    with open(tempest_conf_file, 'wb') as config_file:
-        config.write(config_file)
-
-    return True
-
-
-def main():
-
-    if not os.path.exists(TEMPEST_RESULTS_DIR):
-        os.makedirs(TEMPEST_RESULTS_DIR)
-
-    deployment_dir = ft_utils.get_deployment_dir()
-    configure_tempest_multisite(deployment_dir)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/functest/opnfv_tests/openstack/tempest/run_tempest.py b/functest/opnfv_tests/openstack/tempest/run_tempest.py
deleted file mode 100755 (executable)
index 6406cd1..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-#!/usr/bin/env python
-#
-# Description:
-#    Runs tempest and pushes the results to the DB
-#
-# Authors:
-#    morgan.richomme@orange.com
-#    jose.lausuch@ericsson.com
-#    viktor.tikkanen@nokia.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 ConfigParser
-import os
-import re
-import shutil
-import subprocess
-import sys
-import time
-
-import argparse
-import yaml
-
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
-import functest.utils.openstack_utils as os_utils
-import functest.utils.functest_constants as ft_constants
-
-modes = ['full', 'smoke', 'baremetal', 'compute', 'data_processing',
-         'identity', 'image', 'network', 'object_storage', 'orchestration',
-         'telemetry', 'volume', 'custom', 'defcore', 'feature_multisite']
-
-""" tests configuration """
-parser = argparse.ArgumentParser()
-parser.add_argument("-d", "--debug",
-                    help="Debug mode",
-                    action="store_true")
-parser.add_argument("-s", "--serial",
-                    help="Run tests in one thread",
-                    action="store_true")
-parser.add_argument("-m", "--mode",
-                    help="Tempest test mode [smoke, all]",
-                    default="smoke")
-parser.add_argument("-r", "--report",
-                    help="Create json result file",
-                    action="store_true")
-parser.add_argument("-n", "--noclean",
-                    help="Don't clean the created resources for this test.",
-                    action="store_true")
-parser.add_argument("-c", "--conf",
-                    help="User-specified Tempest config file location",
-                    default="")
-
-args = parser.parse_args()
-
-""" logging configuration """
-logger = ft_logger.Logger("run_tempest").getLogger()
-
-GLANCE_IMAGE_NAME = ft_constants.GLANCE_IMAGE_NAME
-GLANCE_IMAGE_FILENAME = ft_constants.GLANCE_IMAGE_FILENAME
-GLANCE_IMAGE_FORMAT = ft_constants.GLANCE_IMAGE_FORMAT
-GLANCE_IMAGE_PATH = os.path.join(ft_constants.FUNCTEST_DATA_DIR,
-                                 GLANCE_IMAGE_FILENAME)
-
-IMAGE_ID_ALT = None
-
-FLAVOR_NAME = ft_constants.FLAVOR_NAME
-FLAVOR_RAM = ft_constants.FLAVOR_RAM
-FLAVOR_DISK = ft_constants.FLAVOR_DISK
-FLAVOR_VCPUS = ft_constants.FLAVOR_VCPUS
-FLAVOR_ID_ALT = None
-
-TEMPEST_PRIVATE_NET_NAME = ft_constants.TEMPEST_PRIVATE_NET_NAME
-TEMPEST_PRIVATE_SUBNET_NAME = ft_constants.TEMPEST_PRIVATE_SUBNET_NAME
-TEMPEST_PRIVATE_SUBNET_CIDR = ft_constants.TEMPEST_PRIVATE_SUBNET_CIDR
-TEMPEST_ROUTER_NAME = ft_constants.TEMPEST_ROUTER_NAME
-TEMPEST_TENANT_NAME = ft_constants.TEMPEST_TENANT_NAME
-TEMPEST_TENANT_DESCRIPTION = ft_constants.TEMPEST_TENANT_DESCRIPTION
-TEMPEST_USER_NAME = ft_constants.TEMPEST_USER_NAME
-TEMPEST_USER_PASSWORD = ft_constants.TEMPEST_USER_PASSWORD
-TEMPEST_SSH_TIMEOUT = ft_constants.TEMPEST_SSH_TIMEOUT
-TEMPEST_USE_CUSTOM_IMAGES = ft_constants.TEMPEST_USE_CUSTOM_IMAGES
-TEMPEST_USE_CUSTOM_FLAVORS = ft_constants.TEMPEST_USE_CUSTOM_FLAVORS
-
-RESULTS_DIR = ft_constants.FUNCTEST_RESULTS_DIR
-TEMPEST_RESULTS_DIR = os.path.join(RESULTS_DIR, 'tempest')
-
-REPO_PATH = ft_constants.FUNCTEST_REPO_DIR
-TEMPEST_TEST_LIST_DIR = ft_constants.TEMPEST_TEST_LIST_DIR
-TEMPEST_CUSTOM = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
-                              'test_list.txt')
-TEMPEST_BLACKLIST = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
-                                 'blacklist.txt')
-TEMPEST_DEFCORE = os.path.join(REPO_PATH, TEMPEST_TEST_LIST_DIR,
-                               'defcore_req.txt')
-TEMPEST_RAW_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_raw_list.txt')
-TEMPEST_LIST = os.path.join(TEMPEST_RESULTS_DIR, 'test_list.txt')
-
-
-class GlobalVariables:
-    IMAGE_ID = None
-    FLAVOR_ID = None
-    MODE = "smoke"
-
-
-def get_info(file_result):
-    test_run = ""
-    duration = ""
-    test_failed = ""
-
-    p = subprocess.Popen('cat tempest.log',
-                         shell=True, stdout=subprocess.PIPE,
-                         stderr=subprocess.STDOUT)
-    for line in p.stdout.readlines():
-        # print line,
-        if (len(test_run) < 1):
-            test_run = re.findall("[0-9]*\.[0-9]*s", line)
-        if (len(duration) < 1):
-            duration = re.findall("[0-9]*\ tests", line)
-        regexp = r"(failures=[0-9]+)"
-        if (len(test_failed) < 1):
-            test_failed = re.findall(regexp, line)
-
-    logger.debug("test_run:" + test_run)
-    logger.debug("duration:" + duration)
-
-
-def create_tempest_resources():
-    keystone_client = os_utils.get_keystone_client()
-
-    logger.debug("Creating tenant and user for Tempest suite")
-    tenant_id = os_utils.create_tenant(keystone_client,
-                                       TEMPEST_TENANT_NAME,
-                                       TEMPEST_TENANT_DESCRIPTION)
-    if not tenant_id:
-        logger.error("Error : Failed to create %s tenant"
-                     % TEMPEST_TENANT_NAME)
-
-    user_id = os_utils.create_user(keystone_client, TEMPEST_USER_NAME,
-                                   TEMPEST_USER_PASSWORD,
-                                   None, tenant_id)
-    if not user_id:
-        logger.error("Error : Failed to create %s user" % TEMPEST_USER_NAME)
-
-    logger.debug("Creating private network for Tempest suite")
-    network_dic = \
-        os_utils.create_shared_network_full(TEMPEST_PRIVATE_NET_NAME,
-                                            TEMPEST_PRIVATE_SUBNET_NAME,
-                                            TEMPEST_ROUTER_NAME,
-                                            TEMPEST_PRIVATE_SUBNET_CIDR)
-    if not network_dic:
-        exit(1)
-
-    if TEMPEST_USE_CUSTOM_IMAGES:
-        # adding alternative image should be trivial should we need it
-        logger.debug("Creating image for Tempest suite")
-        _, GlobalVariables.IMAGE_ID = os_utils.get_or_create_image(
-            GLANCE_IMAGE_NAME, GLANCE_IMAGE_PATH, GLANCE_IMAGE_FORMAT)
-        if not GlobalVariables.IMAGE_ID:
-            exit(-1)
-
-    if TEMPEST_USE_CUSTOM_FLAVORS:
-        # adding alternative flavor should be trivial should we need it
-        logger.debug("Creating flavor for Tempest suite")
-        _, GlobalVariables.FLAVOR_ID = os_utils.get_or_create_flavor(
-            FLAVOR_NAME, FLAVOR_RAM, FLAVOR_DISK, FLAVOR_VCPUS)
-        if not GlobalVariables.FLAVOR_ID:
-            exit(-1)
-
-
-def configure_tempest(deployment_dir):
-    """
-    Add/update needed parameters into tempest.conf file generated by Rally
-    """
-
-    tempest_conf_file = deployment_dir + "/tempest.conf"
-    if os.path.isfile(tempest_conf_file):
-        logger.debug("Deleting old tempest.conf file...")
-        os.remove(tempest_conf_file)
-
-    logger.debug("Generating new tempest.conf file...")
-    cmd = "rally verify genconfig"
-    ft_utils.execute_command(cmd)
-
-    logger.debug("Finding tempest.conf file...")
-    if not os.path.isfile(tempest_conf_file):
-        logger.error("Tempest configuration file %s NOT found."
-                     % tempest_conf_file)
-        exit(-1)
-
-    logger.debug("Updating selected tempest.conf parameters...")
-    config = ConfigParser.RawConfigParser()
-    config.read(tempest_conf_file)
-    config.set('compute', 'fixed_network_name', TEMPEST_PRIVATE_NET_NAME)
-    if TEMPEST_USE_CUSTOM_IMAGES:
-        if GlobalVariables.IMAGE_ID is not None:
-            config.set('compute', 'image_ref', GlobalVariables.IMAGE_ID)
-        if IMAGE_ID_ALT is not None:
-            config.set('compute', 'image_ref_alt', IMAGE_ID_ALT)
-    if TEMPEST_USE_CUSTOM_FLAVORS:
-        if GlobalVariables.FLAVOR_ID is not None:
-            config.set('compute', 'flavor_ref', GlobalVariables.FLAVOR_ID)
-        if FLAVOR_ID_ALT is not None:
-            config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT)
-    config.set('identity', 'tenant_name', TEMPEST_TENANT_NAME)
-    config.set('identity', 'username', TEMPEST_USER_NAME)
-    config.set('identity', 'password', TEMPEST_USER_PASSWORD)
-    config.set('validation', 'ssh_timeout', TEMPEST_SSH_TIMEOUT)
-
-    if ft_constants.OS_ENDPOINT_TYPE is not None:
-        services_list = ['compute', 'volume', 'image', 'network',
-                         'data-processing', 'object-storage', 'orchestration']
-        sections = config.sections()
-        for service in services_list:
-            if service not in sections:
-                config.add_section(service)
-            config.set(service, 'endpoint_type',
-                       ft_constants.OS_ENDPOINT_TYPE)
-
-    with open(tempest_conf_file, 'wb') as config_file:
-        config.write(config_file)
-
-    # Copy tempest.conf to /home/opnfv/functest/results/tempest/
-    shutil.copyfile(tempest_conf_file, TEMPEST_RESULTS_DIR + '/tempest.conf')
-    return True
-
-
-def read_file(filename):
-    with open(filename) as src:
-        return [line.strip() for line in src.readlines()]
-
-
-def generate_test_list(deployment_dir, mode):
-    logger.debug("Generating test case list...")
-    if mode == 'defcore':
-        shutil.copyfile(TEMPEST_DEFCORE, TEMPEST_RAW_LIST)
-    elif mode == 'custom':
-        if os.path.isfile(TEMPEST_CUSTOM):
-            shutil.copyfile(TEMPEST_CUSTOM, TEMPEST_RAW_LIST)
-        else:
-            logger.error("Tempest test list file %s NOT found."
-                         % TEMPEST_CUSTOM)
-            exit(-1)
-    else:
-        if mode == 'smoke':
-            testr_mode = "smoke"
-        elif mode == 'feature_multisite':
-            testr_mode = " | grep -i kingbird "
-        elif mode == 'full':
-            testr_mode = ""
-        else:
-            testr_mode = 'tempest.api.' + mode
-        cmd = ("cd " + deployment_dir + ";" + "testr list-tests " +
-               testr_mode + ">" + TEMPEST_RAW_LIST + ";cd")
-        ft_utils.execute_command(cmd)
-
-
-def apply_tempest_blacklist():
-    logger.debug("Applying tempest blacklist...")
-    cases_file = read_file(TEMPEST_RAW_LIST)
-    result_file = open(TEMPEST_LIST, 'w')
-    black_tests = []
-    try:
-        installer_type = ft_constants.CI_INSTALLER_TYPE
-        deploy_scenario = ft_constants.CI_SCENARIO
-        if (bool(installer_type) * bool(deploy_scenario)):
-            # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the file
-            black_list_file = open(TEMPEST_BLACKLIST)
-            black_list_yaml = yaml.safe_load(black_list_file)
-            black_list_file.close()
-            for item in black_list_yaml:
-                scenarios = item['scenarios']
-                installers = item['installers']
-                if (deploy_scenario in scenarios and
-                        installer_type in installers):
-                    tests = item['tests']
-                    for test in tests:
-                        black_tests.append(test)
-                    break
-    except:
-        black_tests = []
-        logger.debug("Tempest blacklist file does not exist.")
-
-    for cases_line in cases_file:
-        for black_tests_line in black_tests:
-            if black_tests_line in cases_line:
-                break
-        else:
-            result_file.write(str(cases_line) + '\n')
-    result_file.close()
-
-
-def run_tempest(OPTION):
-    #
-    # the "main" function of the script which launches Rally to run Tempest
-    # :param option: tempest option (smoke, ..)
-    # :return: void
-    #
-    logger.info("Starting Tempest test suite: '%s'." % OPTION)
-    start_time = time.time()
-    stop_time = start_time
-    cmd_line = "rally verify start " + OPTION + " --system-wide"
-
-    header = ("Tempest environment:\n"
-              "  Installer: %s\n  Scenario: %s\n  Node: %s\n  Date: %s\n" %
-              (ft_constants.CI_INSTALLER_TYPE,
-               ft_constants.CI_SCENARIO,
-               ft_constants.CI_NODE,
-               time.strftime("%a %b %d %H:%M:%S %Z %Y")))
-
-    f_stdout = open(TEMPEST_RESULTS_DIR + "/tempest.log", 'w+')
-    f_stderr = open(TEMPEST_RESULTS_DIR + "/tempest-error.log", 'w+')
-    f_env = open(TEMPEST_RESULTS_DIR + "/environment.log", 'w+')
-    f_env.write(header)
-
-    # subprocess.call(cmd_line, shell=True, stdout=f_stdout, stderr=f_stderr)
-    p = subprocess.Popen(
-        cmd_line, shell=True,
-        stdout=subprocess.PIPE,
-        stderr=f_stderr,
-        bufsize=1)
-
-    with p.stdout:
-        for line in iter(p.stdout.readline, b''):
-            if re.search("\} tempest\.", line):
-                logger.info(line.replace('\n', ''))
-            f_stdout.write(line)
-    p.wait()
-
-    f_stdout.close()
-    f_stderr.close()
-    f_env.close()
-
-    cmd_line = "rally verify show"
-    output = ""
-    p = subprocess.Popen(
-        cmd_line, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-    for line in p.stdout:
-        if re.search("Tests\:", line):
-            break
-        output += line
-    logger.info(output)
-
-    cmd_line = "rally verify list"
-    cmd = os.popen(cmd_line)
-    output = (((cmd.read()).splitlines()[-2]).replace(" ", "")).split("|")
-    # Format:
-    # | UUID | Deployment UUID | smoke | tests | failures | Created at |
-    # Duration | Status  |
-    num_tests = output[4]
-    num_failures = output[5]
-    time_start = output[6]
-    duration = output[7]
-    # Compute duration (lets assume it does not take more than 60 min)
-    dur_min = int(duration.split(':')[1])
-    dur_sec_float = float(duration.split(':')[2])
-    dur_sec_int = int(round(dur_sec_float, 0))
-    dur_sec_int = dur_sec_int + 60 * dur_min
-    stop_time = time.time()
-
-    try:
-        diff = (int(num_tests) - int(num_failures))
-        success_rate = 100 * diff / int(num_tests)
-    except:
-        success_rate = 0
-
-    if 'smoke' in args.mode:
-        case_name = 'tempest_smoke_serial'
-    elif 'feature' in args.mode:
-        case_name = args.mode.replace("feature_", "")
-    else:
-        case_name = 'tempest_full_parallel'
-
-    status = ft_utils.check_success_rate(case_name, success_rate)
-    logger.info("Tempest %s success_rate is %s%%, is marked as %s"
-                % (case_name, success_rate, status))
-
-    # Push results in payload of testcase
-    if args.report:
-        # add the test in error in the details sections
-        # should be possible to do it during the test
-        logger.debug("Pushing tempest results into DB...")
-        with open(TEMPEST_RESULTS_DIR + "/tempest.log", 'r') as myfile:
-            output = myfile.read()
-        error_logs = ""
-
-        for match in re.findall('(.*?)[. ]*FAILED', output):
-            error_logs += match
-
-        # Generate json results for DB
-        json_results = {"timestart": time_start, "duration": dur_sec_int,
-                        "tests": int(num_tests), "failures": int(num_failures),
-                        "errors": error_logs}
-        logger.info("Results: " + str(json_results))
-        # split Tempest smoke and full
-
-        try:
-            ft_utils.push_results_to_db("functest",
-                                        case_name,
-                                        start_time,
-                                        stop_time,
-                                        status,
-                                        json_results)
-        except:
-            logger.error("Error pushing results into Database '%s'"
-                         % sys.exc_info()[0])
-
-    if status == "PASS":
-        return 0
-    else:
-        return -1
-
-
-def main():
-
-    if not (args.mode in modes):
-        logger.error("Tempest mode not valid. "
-                     "Possible values are:\n" + str(modes))
-        exit(-1)
-
-    if not os.path.exists(TEMPEST_RESULTS_DIR):
-        os.makedirs(TEMPEST_RESULTS_DIR)
-
-    deployment_dir = ft_utils.get_deployment_dir()
-    create_tempest_resources()
-
-    if "" == args.conf:
-        GlobalVariables.MODE = ""
-        configure_tempest(deployment_dir)
-    else:
-        GlobalVariables.MODE = " --tempest-config " + args.conf
-
-    generate_test_list(deployment_dir, args.mode)
-    apply_tempest_blacklist()
-
-    GlobalVariables.MODE += " --tests-file " + TEMPEST_LIST
-    if args.serial:
-        GlobalVariables.MODE += " --concur 1"
-
-    ret_val = run_tempest(GlobalVariables.MODE)
-    if ret_val != 0:
-        sys.exit(-1)
-
-    sys.exit(0)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
new file mode 100644 (file)
index 0000000..20b1ebb
--- /dev/null
@@ -0,0 +1,331 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2015 All rights reserved
+# This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+
+import os
+import re
+import shutil
+import subprocess
+import time
+
+import yaml
+
+import conf_utils
+import functest.core.testcase_base as 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 os_utils
+
+""" logging configuration """
+logger = ft_logger.Logger("Tempest").getLogger()
+
+
+class TempestCommon(testcase_base.TestcaseBase):
+
+    def __init__(self):
+        super(TempestCommon, self).__init__()
+        self.MODE = ""
+        self.OPTION = ""
+        self.FLAVOR_ID = None
+        self.IMAGE_ID = None
+        self.DEPLOYMENT_DIR = self.get_deployment_dir()
+
+    @staticmethod
+    def get_deployment_dir():
+        """
+        Returns current Rally deployment directory
+        """
+        cmd = ("rally deployment list | awk '/" +
+               CONST.rally_deployment_name +
+               "/ {print $2}'")
+        p = subprocess.Popen(cmd, shell=True,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.STDOUT)
+        deployment_uuid = p.stdout.readline().rstrip()
+        if deployment_uuid == "":
+            logger.error("Rally deployment not found.")
+            exit(-1)
+        return os.path.join(CONST.dir_rally_inst,
+                            "tempest/for-deployment-" + deployment_uuid)
+
+    @staticmethod
+    def read_file(filename):
+        with open(filename) as src:
+            return [line.strip() for line in src.readlines()]
+
+    def create_tempest_resources(self):
+        keystone_client = os_utils.get_keystone_client()
+
+        logger.debug("Creating tenant and user for Tempest suite")
+        tenant_id = os_utils.create_tenant(
+            keystone_client,
+            CONST.tempest_identity_tenant_name,
+            CONST.tempest_identity_tenant_description)
+        if not tenant_id:
+            logger.error("Error : Failed to create %s tenant"
+                         % CONST.tempest_identity_tenant_name)
+
+        user_id = os_utils.create_user(keystone_client,
+                                       CONST.tempest_identity_user_name,
+                                       CONST.tempest_identity_user_password,
+                                       None, tenant_id)
+        if not user_id:
+            logger.error("Error : Failed to create %s user" %
+                         CONST.tempest_identity_user_name)
+
+        logger.debug("Creating private network for Tempest suite")
+        network_dic = \
+            os_utils.create_shared_network_full(
+                CONST.tempest_private_net_name,
+                CONST.tempest_private_subnet_name,
+                CONST.tempest_router_name,
+                CONST.tempest_private_subnet_cidr)
+        if not network_dic:
+            return testcase_base.TestcaseBase.EX_RUN_ERROR
+
+        if CONST.tempest_use_custom_images:
+            # adding alternative image should be trivial should we need it
+            logger.debug("Creating image for Tempest suite")
+            _, self.IMAGE_ID = os_utils.get_or_create_image(
+                CONST.openstack_image_name, conf_utils.GLANCE_IMAGE_PATH,
+                CONST.openstack_image_disk_format)
+            if not self.IMAGE_ID:
+                return testcase_base.TestcaseBase.EX_RUN_ERROR
+
+        if CONST.tempest_use_custom_flavors:
+            # adding alternative flavor should be trivial should we need it
+            logger.debug("Creating flavor for Tempest suite")
+            _, self.FLAVOR_ID = os_utils.get_or_create_flavor(
+                CONST.openstack_flavor_name,
+                CONST.openstack_flavor_ram,
+                CONST.openstack_flavor_disk,
+                CONST.openstack_flavor_vcpus)
+            if not self.FLAVOR_ID:
+                return testcase_base.TestcaseBase.EX_RUN_ERROR
+
+        return testcase_base.TestcaseBase.EX_OK
+
+    def generate_test_list(self, DEPLOYMENT_DIR):
+        logger.debug("Generating test case list...")
+        if self.MODE == 'defcore':
+            shutil.copyfile(
+                conf_utils.TEMPEST_DEFCORE, conf_utils.TEMPEST_RAW_LIST)
+        elif self.MODE == 'custom':
+            if os.path.isfile(conf_utils.TEMPEST_CUSTOM):
+                shutil.copyfile(
+                    conf_utils.TEMPEST_CUSTOM, conf_utils.TEMPEST_RAW_LIST)
+            else:
+                logger.error("Tempest test list file %s NOT found."
+                             % conf_utils.TEMPEST_CUSTOM)
+                return testcase_base.TestcaseBase.EX_RUN_ERROR
+        else:
+            if self.MODE == 'smoke':
+                testr_mode = "smoke"
+            elif self.MODE == 'feature_multisite':
+                testr_mode = " | grep -i kingbird "
+            elif self.MODE == 'full':
+                testr_mode = ""
+            else:
+                testr_mode = 'tempest.api.' + self.MODE
+            cmd = ("cd " + DEPLOYMENT_DIR + ";" + "testr list-tests " +
+                   testr_mode + ">" + conf_utils.TEMPEST_RAW_LIST + ";cd")
+            ft_utils.execute_command(cmd)
+
+        return testcase_base.TestcaseBase.EX_OK
+
+    def apply_tempest_blacklist(self):
+        logger.debug("Applying tempest blacklist...")
+        cases_file = self.read_file(conf_utils.TEMPEST_RAW_LIST)
+        result_file = open(conf_utils.TEMPEST_LIST, 'w')
+        black_tests = []
+        try:
+            installer_type = CONST.INSTALLER_TYPE
+            deploy_scenario = CONST.DEPLOY_SCENARIO
+            if (bool(installer_type) * bool(deploy_scenario)):
+                # if INSTALLER_TYPE and DEPLOY_SCENARIO are set we read the
+                # file
+                black_list_file = open(conf_utils.TEMPEST_BLACKLIST)
+                black_list_yaml = yaml.safe_load(black_list_file)
+                black_list_file.close()
+                for item in black_list_yaml:
+                    scenarios = item['scenarios']
+                    installers = item['installers']
+                    if (deploy_scenario in scenarios and
+                            installer_type in installers):
+                        tests = item['tests']
+                        for test in tests:
+                            black_tests.append(test)
+                        break
+        except:
+            black_tests = []
+            logger.debug("Tempest blacklist file does not exist.")
+
+        for cases_line in cases_file:
+            for black_tests_line in black_tests:
+                if black_tests_line in cases_line:
+                    break
+            else:
+                result_file.write(str(cases_line) + '\n')
+        result_file.close()
+        return testcase_base.TestcaseBase.EX_OK
+
+    def run(self):
+
+        self.start_time = time.time()
+
+        if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
+            os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
+
+        # Pre-configuration
+        res = self.create_tempest_resources()
+        if res != testcase_base.TestcaseBase.EX_OK:
+            return res
+
+        res = conf_utils.configure_tempest(logger,
+                                           self.DEPLOYMENT_DIR,
+                                           self.IMAGE_ID,
+                                           self.FLAVOR_ID)
+        if res != testcase_base.TestcaseBase.EX_OK:
+            return res
+
+        res = self.generate_test_list(self.DEPLOYMENT_DIR)
+        if res != testcase_base.TestcaseBase.EX_OK:
+            return res
+
+        res = self.apply_tempest_blacklist()
+        if res != testcase_base.TestcaseBase.EX_OK:
+            return res
+
+        self.OPTION += (" --tests-file %s " % conf_utils.TEMPEST_LIST)
+
+        cmd_line = "rally verify start " + self.OPTION + " --system-wide"
+        logger.info("Starting Tempest test suite: '%s'." % cmd_line)
+
+        header = ("Tempest environment:\n"
+                  "  Installer: %s\n  Scenario: %s\n  Node: %s\n  Date: %s\n" %
+                  (CONST.INSTALLER_TYPE,
+                   CONST.DEPLOY_SCENARIO,
+                   CONST.NODE_NAME,
+                   time.strftime("%a %b %d %H:%M:%S %Z %Y")))
+
+        f_stdout = open(conf_utils.TEMPEST_RESULTS_DIR + "/tempest.log", 'w+')
+        f_stderr = open(
+            conf_utils.TEMPEST_RESULTS_DIR + "/tempest-error.log", 'w+')
+        f_env = open(conf_utils.TEMPEST_RESULTS_DIR + "/environment.log", 'w+')
+        f_env.write(header)
+
+        # subprocess.call(cmd_line, shell=True,
+        # stdout=f_stdout, stderr=f_stderr)
+        p = subprocess.Popen(
+            cmd_line, shell=True,
+            stdout=subprocess.PIPE,
+            stderr=f_stderr,
+            bufsize=1)
+
+        with p.stdout:
+            for line in iter(p.stdout.readline, b''):
+                if re.search("\} tempest\.", line):
+                    logger.info(line.replace('\n', ''))
+                f_stdout.write(line)
+        p.wait()
+
+        f_stdout.close()
+        f_stderr.close()
+        f_env.close()
+
+        cmd_line = "rally verify show"
+        output = ""
+        p = subprocess.Popen(cmd_line,
+                             shell=True,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+        for line in p.stdout:
+            if re.search("Tests\:", line):
+                break
+            output += line
+        logger.info(output)
+
+        cmd_line = "rally verify list"
+        cmd = os.popen(cmd_line)
+        output = (((cmd.read()).splitlines()[-2]).replace(" ", "")).split("|")
+        # Format:
+        # | UUID | Deployment UUID | smoke | tests | failures | Created at |
+        # Duration | Status  |
+        num_tests = output[4]
+        num_failures = output[5]
+        duration = output[7]
+        # Compute duration (lets assume it does not take more than 60 min)
+        dur_min = int(duration.split(':')[1])
+        dur_sec_float = float(duration.split(':')[2])
+        dur_sec_int = int(round(dur_sec_float, 0))
+        dur_sec_int = dur_sec_int + 60 * dur_min
+
+        try:
+            diff = (int(num_tests) - int(num_failures))
+            success_rate = 100 * diff / int(num_tests)
+        except:
+            success_rate = 0
+
+        self.criteria = ft_utils.check_success_rate(
+            self.case_name, success_rate)
+        logger.info("Tempest %s success_rate is %s%%, is marked as %s"
+                    % (self.case_name, success_rate, self.criteria))
+
+        self.stop_time = time.time()
+
+        if self.criteria == "PASS":
+            return testcase_base.TestcaseBase.EX_OK
+        else:
+            return testcase_base.TestcaseBase.EX_TESTCASE_FAILED
+
+
+class TempestSmokeSerial(TempestCommon):
+
+    def __init__(self):
+        TempestCommon.__init__(self)
+        self.case_name = "tempest_smoke_serial"
+        self.MODE = "smoke"
+        self.OPTION = "--concur 1"
+
+
+class TempestSmokeParallel(TempestCommon):
+
+    def __init__(self):
+        TempestCommon.__init__(self)
+        self.case_name = "tempest_smoke_parallel"
+        self.MODE = "smoke"
+        self.OPTION = ""
+
+
+class TempestFullParallel(TempestCommon):
+
+    def __init__(self):
+        TempestCommon.__init__(self)
+        self.case_name = "tempest_full_parallel"
+        self.MODE = "full"
+
+
+class TempestMultisite(TempestCommon):
+
+    def __init__(self):
+        TempestCommon.__init__(self)
+        self.case_name = "multisite"
+        self.MODE = "feature_multisite"
+        self.OPTION = "--concur 1"
+        conf_utils.configure_tempest_multisite(logger, self.DEPLOYMENT_DIR)
+
+
+class TempestCustom(TempestCommon):
+
+    def __init__(self, mode, option):
+        TempestCommon.__init__(self)
+        self.case_name = "tempest_custom"
+        self.MODE = mode
+        self.OPTION = option
old mode 100644 (file)
new mode 100755 (executable)
index 213b79f..a5309bd
@@ -12,43 +12,38 @@ import pprint
 import time
 from datetime import datetime
 
-import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_constants as ft_constants
-import functest.utils.openstack_utils as os_utils
 import functest.core.testcase_base as testcase_base
+import functest.utils.openstack_utils as os_utils
+from functest.utils.constants import CONST
 
 
 class VPingBase(testcase_base.TestcaseBase):
     def __init__(self):
-        def get_conf(parameter):
-            return ft_utils.get_functest_config(parameter)
-
         super(VPingBase, self).__init__()
         self.logger = None
-        self.functest_repo = ft_constants.FUNCTEST_REPO_DIR
-        self.repo = get_conf('general.directories.dir_vping')
-        self.vm1_name = get_conf('vping.vm_name_1')
-        self.vm2_name = get_conf('vping.vm_name_2')
+        self.functest_repo = CONST.dir_repo_functest
+        self.repo = CONST.dir_vping
+        self.vm1_name = CONST.vping_vm_name_1
+        self.vm2_name = CONST.vping_vm_name_2
         self.vm_boot_timeout = 180
         self.vm_delete_timeout = 100
-        self.ping_timeout = get_conf('vping.ping_timeout')
+        self.ping_timeout = CONST.vping_ping_timeout
 
-        self.image_name = get_conf('vping.image_name')
-        self.image_filename = get_conf('general.openstack.image_file_name')
-        self.image_format = get_conf('general.openstack.image_disk_format')
-        self.image_path = \
-            "%s/%s" % (get_conf('general.directories.dir_functest_data'),
-                       self.image_filename)
+        self.image_name = CONST.vping_image_name
+        self.image_filename = CONST.openstack_image_file_name
+        self.image_format = CONST.openstack_image_disk_format
+        self.image_path = os.path.join(CONST.dir_functest_data,
+                                       self.image_filename)
 
-        self.flavor_name = get_conf('vping.vm_flavor')
+        self.flavor_name = CONST.vping_vm_flavor
 
         # NEUTRON Private Network parameters
-        self.private_net_name = get_conf('vping.vping_private_net_name')
-        self.private_subnet_name = get_conf('vping.vping_private_subnet_name')
-        self.private_subnet_cidr = get_conf('vping.vping_private_subnet_cidr')
-        self.router_name = get_conf('vping.vping_router_name')
-        self.sg_name = get_conf('vping.vping_sg_name')
-        self.sg_desc = get_conf('vping.vping_sg_descr')
+        self.private_net_name = CONST.vping_private_net_name
+        self.private_subnet_name = CONST.vping_private_subnet_name
+        self.private_subnet_cidr = CONST.vping_private_subnet_cidr
+        self.router_name = CONST.vping_router_name
+        self.sg_name = CONST.vping_sg_name
+        self.sg_desc = CONST.vping_sg_desc
         self.neutron_client = os_utils.get_neutron_client()
         self.glance_client = os_utils.get_glance_client()
         self.nova_client = os_utils.get_nova_client()
old mode 100644 (file)
new mode 100755 (executable)
index 8ae590e..b032c30
@@ -101,9 +101,9 @@ class VPingSSH(vping_base.VPingBase):
                                   "from the dhcp agent." % self.vm2_name)
 
             # if dhcp not work,it shows "No lease, failing".The test will fail
-            if "No lease, failing" in console_log \
-                    and not nolease \
-                    and not got_ip:
+            if ("No lease, failing" in console_log and
+                not nolease and
+                    not got_ip):
                 nolease = True
                 self.logger.debug("Console-log '%s': No lease, failing..."
                                   % self.vm2_name)
index 9544074..45b313d 100755 (executable)
@@ -15,18 +15,17 @@ import re
 import sys
 import urlparse
 
-from robot.api import ExecutionResult, ResultVisitor
+import robot.api
 from robot.errors import RobotError
 import robot.run
 from robot.utils.robottime import timestamp_to_secs
 
-import functest.core.testcase_base as testcase_base
+from functest.core import testcase_base
 import functest.utils.functest_logger as ft_logger
 import functest.utils.openstack_utils as op_utils
-import functest.utils.functest_constants as ft_constants
 
 
-class ODLResultVisitor(ResultVisitor):
+class ODLResultVisitor(robot.api.ResultVisitor):
 
     def __init__(self):
         self._data = []
@@ -36,7 +35,7 @@ class ODLResultVisitor(ResultVisitor):
         output['name'] = test.name
         output['parent'] = test.parent.name
         output['status'] = test.status
-        output['startime'] = test.starttime
+        output['starttime'] = test.starttime
         output['endtime'] = test.endtime
         output['critical'] = test.critical
         output['text'] = test.message
@@ -49,17 +48,17 @@ class ODLResultVisitor(ResultVisitor):
 
 class ODLTests(testcase_base.TestcaseBase):
 
-    repos = ft_constants.REPOS_DIR
+    repos = "/home/opnfv/repos/"
     odl_test_repo = os.path.join(repos, "odl_test")
     neutron_suite_dir = os.path.join(odl_test_repo,
                                      "csit/suites/openstack/neutron")
     basic_suite_dir = os.path.join(odl_test_repo,
                                    "csit/suites/integration/basic")
-    res_dir = os.path.join(ft_constants.FUNCTEST_RESULTS_DIR, "odl")
-
+    res_dir = '/home/opnfv/functest/results/odl/'
     logger = ft_logger.Logger("opendaylight").getLogger()
 
     def __init__(self):
+        testcase_base.TestcaseBase.__init__(self)
         self.case_name = "odl"
 
     @classmethod
@@ -79,8 +78,8 @@ class ODLTests(testcase_base.TestcaseBase):
             return False
 
     def parse_results(self):
-        output_dir = os.path.join(self.res_dir, 'output.xml')
-        result = ExecutionResult(output_dir)
+        xml_file = os.path.join(self.res_dir, 'output.xml')
+        result = robot.api.ExecutionResult(xml_file)
         visitor = ODLResultVisitor()
         result.visit(visitor)
         self.criteria = result.suite.status
@@ -89,7 +88,6 @@ class ODLTests(testcase_base.TestcaseBase):
         self.details = {}
         self.details['description'] = result.suite.name
         self.details['tests'] = visitor.get_data()
-        return self.criteria
 
     def main(self, **kwargs):
         dirs = [self.basic_suite_dir, self.neutron_suite_dir]
@@ -128,10 +126,8 @@ class ODLTests(testcase_base.TestcaseBase):
                 self.logger.info("\n" + stdout.read())
             self.logger.info("ODL results were successfully generated")
             try:
-                test_res = self.parse_results()
+                self.parse_results()
                 self.logger.info("ODL results were successfully parsed")
-                if test_res is not "PASS":
-                    return self.EX_RUN_ERROR
             except RobotError as e:
                 self.logger.error("Run tests before publishing: %s" %
                                   e.message)
@@ -146,11 +142,8 @@ class ODLTests(testcase_base.TestcaseBase):
 
     def run(self):
         try:
-            kclient = op_utils.get_keystone_client()
-            keystone_url = kclient.service_catalog.url_for(
-                service_type='identity', endpoint_type='publicURL')
-            neutron_url = kclient.service_catalog.url_for(
-                service_type='network', endpoint_type='publicURL')
+            keystone_url = op_utils.get_endpoint(service_type='identity')
+            neutron_url = op_utils.get_endpoint(service_type='network')
             kwargs = {'keystoneip': urlparse.urlparse(keystone_url).hostname}
             kwargs['neutronip'] = urlparse.urlparse(neutron_url).hostname
             kwargs['odlip'] = kwargs['neutronip']
@@ -158,29 +151,23 @@ class ODLTests(testcase_base.TestcaseBase):
             kwargs['odlrestconfport'] = '8181'
             kwargs['odlusername'] = 'admin'
             kwargs['odlpassword'] = 'admin'
-
-            installer_type = ft_constants.CI_INSTALLER_TYPE
-            kwargs['osusername'] = ft_constants.OS_USERNAME
-            kwargs['ostenantname'] = ft_constants.OS_TENANT_NAME
-            kwargs['ospassword'] = ft_constants.OS_PASSWORD
-
+            installer_type = None
+            if 'INSTALLER_TYPE' in os.environ:
+                installer_type = os.environ['INSTALLER_TYPE']
+            kwargs['osusername'] = os.environ['OS_USERNAME']
+            kwargs['ostenantname'] = os.environ['OS_TENANT_NAME']
+            kwargs['ospassword'] = os.environ['OS_PASSWORD']
             if installer_type == 'fuel':
                 kwargs['odlwebport'] = '8282'
             elif installer_type == 'apex':
-                if ft_constants.SDN_CONTROLLER_IP is None:
-                    return self.EX_RUN_ERROR
-                kwargs['odlip'] = ft_constants.SDN_CONTROLLER_IP
+                kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
                 kwargs['odlwebport'] = '8181'
             elif installer_type == 'joid':
-                if ft_constants.SDN_CONTROLLER is None:
-                    return self.EX_RUN_ERROR
-                kwargs['odlip'] = ft_constants.SDN_CONTROLLER
+                kwargs['odlip'] = os.environ['SDN_CONTROLLER']
             elif installer_type == 'compass':
                 kwargs['odlwebport'] = '8181'
             else:
-                if ft_constants.SDN_CONTROLLER_IP is None:
-                    return self.EX_RUN_ERROR
-                kwargs['odlip'] = ft_constants.SDN_CONTROLLER_IP
+                kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
         except KeyError as e:
             self.logger.error("Cannot run ODL testcases. "
                               "Please check env var: "
@@ -193,44 +180,52 @@ class ODLTests(testcase_base.TestcaseBase):
         return self.main(**kwargs)
 
 
+class ODLParser():
+
+    def __init__(self):
+        self.parser = argparse.ArgumentParser()
+        self.parser.add_argument(
+            '-k', '--keystoneip', help='Keystone IP',
+            default='127.0.0.1')
+        self.parser.add_argument(
+            '-n', '--neutronip', help='Neutron IP',
+            default='127.0.0.1')
+        self.parser.add_argument(
+            '-a', '--osusername', help='Username for OpenStack',
+            default='admin')
+        self.parser.add_argument(
+            '-b', '--ostenantname', help='Tenantname for OpenStack',
+            default='admin')
+        self.parser.add_argument(
+            '-c', '--ospassword', help='Password for OpenStack',
+            default='admin')
+        self.parser.add_argument(
+            '-o', '--odlip', help='OpenDaylight IP',
+            default='127.0.0.1')
+        self.parser.add_argument(
+            '-w', '--odlwebport', help='OpenDaylight Web Portal Port',
+            default='8080')
+        self.parser.add_argument(
+            '-r', '--odlrestconfport', help='OpenDaylight RESTConf Port',
+            default='8181')
+        self.parser.add_argument(
+            '-d', '--odlusername', help='Username for ODL',
+            default='admin')
+        self.parser.add_argument(
+            '-e', '--odlpassword', help='Password for ODL',
+            default='admin')
+        self.parser.add_argument(
+            '-p', '--pushtodb', help='Push results to DB',
+            action='store_true')
+
+    def parse_args(self, argv=[]):
+        return vars(self.parser.parse_args(argv))
+
+
 if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-    parser.add_argument('-k', '--keystoneip',
-                        help='Keystone IP',
-                        default='127.0.0.1')
-    parser.add_argument('-n', '--neutronip',
-                        help='Neutron IP',
-                        default='127.0.0.1')
-    parser.add_argument('-a', '--osusername',
-                        help='Username for OpenStack',
-                        default='admin')
-    parser.add_argument('-b', '--ostenantname',
-                        help='Tenantname for OpenStack',
-                        default='admin')
-    parser.add_argument('-c', '--ospassword',
-                        help='Password for OpenStack',
-                        default='admin')
-    parser.add_argument('-o', '--odlip',
-                        help='OpenDaylight IP',
-                        default='127.0.0.1')
-    parser.add_argument('-w', '--odlwebport',
-                        help='OpenDaylight Web Portal Port',
-                        default='8080')
-    parser.add_argument('-r', '--odlrestconfport',
-                        help='OpenDaylight RESTConf Port',
-                        default='8181')
-    parser.add_argument('-d', '--odlusername',
-                        help='Username for ODL',
-                        default='admin')
-    parser.add_argument('-e', '--odlpassword',
-                        help='Password for ODL',
-                        default='admin')
-    parser.add_argument('-p', '--pushtodb',
-                        help='Push results to DB',
-                        action='store_true')
-
-    args = vars(parser.parse_args())
     odl = ODLTests()
+    parser = ODLParser()
+    args = parser.parse_args(sys.argv[1:])
     try:
         result = odl.main(**args)
         if result != testcase_base.TestcaseBase.EX_OK:
index fe888b6..15981f5 100755 (executable)
@@ -19,10 +19,7 @@ import subprocess
 import time
 
 import argparse
-import keystoneclient.v2_0.client as ksclient
-import novaclient.client as nvclient
 import requests
-from neutronclient.v2_0 import client as ntclient
 
 import functest.utils.functest_logger as ft_logger
 import functest.utils.functest_utils as ft_utils
@@ -242,17 +239,15 @@ def main():
     if not os.path.exists(VIMS_DATA_DIR):
         os.makedirs(VIMS_DATA_DIR)
 
-    ks_creds = os_utils.get_credentials("keystone")
-    nv_creds = os_utils.get_credentials("nova")
-    nt_creds = os_utils.get_credentials("neutron")
+    creds = os_utils.get_credentials()
 
     logger.info("Prepare OpenStack plateform (create tenant and user)")
-    keystone = ksclient.Client(**ks_creds)
+    keystone = os_utils.get_keystone_client()
 
-    user_id = os_utils.get_user_id(keystone, ks_creds['username'])
+    user_id = os_utils.get_user_id(keystone, creds['username'])
     if user_id == '':
         step_failure("init", "Error : Failed to get id of " +
-                     ks_creds['username'])
+                     creds['username'])
 
     tenant_id = os_utils.create_tenant(
         keystone, VIMS_TENANT_NAME, VIMS_TENANT_DESCRIPTION)
@@ -271,7 +266,7 @@ def main():
 
     if not os_utils.add_role_user(keystone, user_id, role_id, tenant_id):
         logger.error("Error : Failed to add %s on tenant" %
-                     ks_creds['username'])
+                     creds['username'])
 
     user_id = os_utils.create_user(
         keystone, VIMS_TENANT_NAME, VIMS_TENANT_NAME, None, tenant_id)
@@ -279,18 +274,10 @@ def main():
         logger.error("Error : Failed to create %s user" % VIMS_TENANT_NAME)
 
     logger.info("Update OpenStack creds informations")
-    ks_creds.update({
+    creds.update({
         "username": VIMS_TENANT_NAME,
         "password": VIMS_TENANT_NAME,
-        "tenant_name": VIMS_TENANT_NAME,
-    })
-
-    nt_creds.update({
-        "tenant_name": VIMS_TENANT_NAME,
-    })
-
-    nv_creds.update({
-        "project_id": VIMS_TENANT_NAME,
+        "tenant": VIMS_TENANT_NAME,
     })
 
     logger.info("Upload some OS images if it doesn't exist")
@@ -314,10 +301,8 @@ def main():
                 "Error : Failed to find or upload required OS "
                 "image for this deployment")
 
-    nova = nvclient.Client("2", **nv_creds)
-
     logger.info("Update security group quota for this tenant")
-    neutron = ntclient.Client(**nt_creds)
+    neutron = os_utils.get_neutron_client(creds)
     if not os_utils.update_sg_quota(neutron, tenant_id, 50, 100):
         step_failure(
             "init",
@@ -325,17 +310,22 @@ def main():
             VIMS_TENANT_NAME)
 
     # ############### CLOUDIFY INITIALISATION ################
-    public_auth_url = keystone.service_catalog.url_for(
-        service_type='identity', endpoint_type='publicURL')
+    public_auth_url = os_utils.get_endpoint('identity')
 
     cfy = Orchestrator(VIMS_DATA_DIR, CFY_INPUTS)
 
-    cfy.set_credentials(username=ks_creds['username'], password=ks_creds[
-                        'password'], tenant_name=ks_creds['tenant_name'],
+    if 'tenant_name' in creds.keys():
+        tenant_name = creds['tenant_name']
+    elif 'project_name' in creds.keys():
+        tenant_name = creds['project_name']
+
+    cfy.set_credentials(username=creds['username'],
+                        password=creds['password'],
+                        tenant_name=tenant_name,
                         auth_url=public_auth_url)
 
     logger.info("Collect flavor id for cloudify manager server")
-    nova = nvclient.Client("2", **nv_creds)
+    nova = os_utils.get_nova_client(creds)
 
     flavor_name = "m1.large"
     flavor_id = os_utils.get_flavor_id(nova, flavor_name)
@@ -416,7 +406,6 @@ def main():
     cw = Clearwater(CW_INPUTS, cfy, logger)
 
     logger.info("Collect flavor id for all clearwater vm")
-    nova = nvclient.Client("2", **nv_creds)
 
     flavor_name = "m1.small"
     flavor_id = os_utils.get_flavor_id(nova, flavor_name)
@@ -490,10 +479,6 @@ def main():
     if args.noclean:
         exit(0)
 
-    ks_creds = os_utils.get_credentials("keystone")
-
-    keystone = ksclient.Client(**ks_creds)
-
     logger.info("Removing %s tenant .." % CFY_INPUTS['keystone_tenant_name'])
     tenant_id = os_utils.get_tenant_id(
         keystone, CFY_INPUTS['keystone_tenant_name'])
diff --git a/functest/tests/unit/cli/__init__.py b/functest/tests/unit/cli/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/functest/tests/unit/cli/commands/__init__.py b/functest/tests/unit/cli/commands/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py
new file mode 100644 (file)
index 0000000..f70761d
--- /dev/null
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import logging
+import unittest
+
+from git.exc import NoSuchPathError
+import mock
+
+mock.patch('logging.FileHandler').start()  # noqa
+from functest.cli.commands import cli_env
+from functest.utils.constants import CONST
+from functest.tests.unit import test_utils
+
+
+class CliEnvTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.cli_environ = cli_env.CliEnv()
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_prepare_default(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/prepare_env.py start" %
+               CONST.dir_repo_functest)
+        self.cli_environ.prepare()
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_prepare_missing_status(self, mock_ft_utils, mock_os):
+        with mock.patch('__builtin__.raw_input', return_value="y"), \
+                mock.patch('functest.cli.commands.cli_testcase.os.remove') \
+                as mock_os_remove:
+            cmd = ("python %s/functest/ci/prepare_env.py start" %
+                   CONST.dir_repo_functest)
+            self.cli_environ.prepare()
+            mock_os_remove.assert_called_once_with(CONST.env_active)
+            mock_ft_utils.assert_called_with(cmd)
+
+    def _test_show_missing_env_var(self, var, *args):
+        if var == 'INSTALLER_TYPE':
+            CONST.INSTALLER_TYPE = None
+            reg_string = "|  INSTALLER: Unknown, \S+\s*|"
+        elif var == 'INSTALLER_IP':
+            CONST.INSTALLER_IP = None
+            reg_string = "|  INSTALLER: \S+, Unknown\s*|"
+        elif var == 'SCENARIO':
+            CONST.DEPLOY_SCENARIO = None
+            reg_string = "|   SCENARIO: Unknown\s*|"
+        elif var == 'NODE':
+            CONST.NODE_NAME = None
+            reg_string = "|        POD: Unknown\s*|"
+        elif var == 'BUILD_TAG':
+            CONST.BUILD_TAG = None
+            reg_string = "|  BUILD TAG: None|"
+        elif var == 'DEBUG':
+            CONST.CI_DEBUG = None
+            reg_string = "| DEBUG FLAG: false\s*|"
+        elif var == 'STATUS':
+            reg_string = "|     STATUS: not ready\s*|"
+
+        with mock.patch('functest.cli.commands.cli_env.click.echo') \
+                as mock_click_echo:
+            self.cli_environ.show()
+            mock_click_echo.assert_called_with(test_utils.
+                                               RegexMatch(reg_string))
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_installer_type(self, *args):
+        self._test_show_missing_env_var('INSTALLER_TYPE', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_installer_ip(self, *args):
+        self._test_show_missing_env_var('INSTALLER_IP', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_scenario(self, *args):
+        self._test_show_missing_env_var('SCENARIO', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_node(self, *args):
+        self._test_show_missing_env_var('NODE', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_build_tag(self, *args):
+        self._test_show_missing_env_var('BUILD_TAG', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    def test_show_missing_ci_debug(self, *args):
+        self._test_show_missing_env_var('DEBUG', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.git.Repo')
+    @mock.patch('functest.cli.commands.cli_env.os.path.isfile',
+                return_value=False)
+    def test_show_missing_environment(self, *args):
+        self._test_show_missing_env_var('STATUS', *args)
+
+    @mock.patch('functest.cli.commands.cli_env.os.path.exists',
+                return_value=False)
+    def test_show_missing_git_repo_dir(self, *args):
+        CONST.dir_repo_functest = None
+        self.assertRaises(NoSuchPathError, lambda: self.cli_environ.show())
+
+    @mock.patch('functest.cli.commands.cli_env.click.echo')
+    @mock.patch('functest.cli.commands.cli_env.os.path.isfile',
+                return_value=True)
+    def test_status_environment_present(self, mock_path, mock_click_echo):
+        self.assertEqual(self.cli_environ.status(), 0)
+        mock_click_echo.assert_called_with("Functest environment"
+                                           " ready to run tests.\n")
+
+    @mock.patch('functest.cli.commands.cli_env.click.echo')
+    @mock.patch('functest.cli.commands.cli_env.os.path.isfile',
+                return_value=False)
+    def test_status_environment_absent(self, mock_path, mock_click_echo):
+        self.assertEqual(self.cli_environ.status(), 1)
+        mock_click_echo.assert_called_with("Functest environment"
+                                           " is not installed.\n")
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py
new file mode 100644 (file)
index 0000000..f0e58c6
--- /dev/null
@@ -0,0 +1,238 @@
+#!/usr/bin/env python
+#
+# jose.lausuch@ericsson.com
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+
+import logging
+import unittest
+import os
+
+import mock
+
+from functest.cli.commands import cli_os
+from functest.utils.constants import CONST
+
+
+class CliOpenStackTesting(unittest.TestCase):
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.endpoint_ip = 'test_ip'
+        self.os_auth_url = 'http://test_ip:test_port/v2.0'
+        self.installer_type = 'test_installer_type'
+        self.installer_ip = 'test_installer_ip'
+        self.openstack_creds = 'test_openstack_creds'
+        self.dir_repo_functest = 'test_dir_repo_functest'
+        self.snapshot_file = 'test_snapshot_file'
+        self.cli_os = cli_os.CliOpenStack()
+
+    def test_ping_endpoint_default(self):
+        self.cli_os.os_auth_url = self.os_auth_url
+        self.cli_os.endpoint_ip = self.endpoint_ip
+        with mock.patch('functest.cli.commands.cli_os.os.system',
+                        return_value=0):
+            self.assertEqual(self.cli_os.ping_endpoint(), 0)
+
+    @mock.patch('functest.cli.commands.cli_os.exit', side_effect=Exception)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_ping_endpoint_missing_auth_url(self, mock_click_echo,
+                                            mock_exit):
+        with self.assertRaises(Exception):
+            self.cli_os.os_auth_url = None
+            self.cli_os.ping_endpoint()
+            mock_click_echo.assert_called_once_with("Source the OpenStack "
+                                                    "credentials first '. "
+                                                    "$creds'")
+
+    @mock.patch('functest.cli.commands.cli_os.exit')
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_ping_endpoint_os_system_fails(self, mock_click_echo,
+                                           mock_exit):
+        self.cli_os.os_auth_url = self.os_auth_url
+        self.cli_os.endpoint_ip = self.endpoint_ip
+        with mock.patch('functest.cli.commands.cli_os.os.system',
+                        return_value=1):
+            self.cli_os.ping_endpoint()
+            mock_click_echo.assert_called_once_with("Cannot talk to the "
+                                                    "endpoint %s\n" %
+                                                    self.endpoint_ip)
+            mock_exit.assert_called_once_with(0)
+
+    @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_fetch_credentials_default(self, mock_click_echo,
+                                       mock_os_path,
+                                       mock_ftutils_execute):
+        CONST.INSTALLER_TYPE = self.installer_type
+        CONST.INSTALLER_IP = self.installer_ip
+        cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
+               % (CONST.dir_repos,
+                  self.openstack_creds,
+                  self.installer_type,
+                  self.installer_ip))
+        self.cli_os.openstack_creds = self.openstack_creds
+        self.cli_os.fetch_credentials()
+        mock_click_echo.assert_called_once_with("Fetching credentials from "
+                                                "installer node '%s' with "
+                                                "IP=%s.." %
+                                                (self.installer_type,
+                                                 self.installer_ip))
+        mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
+
+    @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_fetch_credentials_missing_installer_type(self, mock_click_echo,
+                                                      mock_os_path,
+                                                      mock_ftutils_execute):
+        installer_type = None
+        installer_ip = self.installer_ip
+        CONST.INSTALLER_TYPE = installer_type
+        CONST.INSTALLER_IP = installer_ip
+        cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
+               % (CONST.dir_repos,
+                  self.openstack_creds,
+                  installer_type,
+                  installer_ip))
+        self.cli_os.openstack_creds = self.openstack_creds
+        self.cli_os.fetch_credentials()
+        mock_click_echo.assert_any_call("The environment variable "
+                                        "'INSTALLER_TYPE' is not"
+                                        "defined. Please export it")
+        mock_click_echo.assert_any_call("Fetching credentials from "
+                                        "installer node '%s' with "
+                                        "IP=%s.." %
+                                        (installer_type,
+                                         installer_ip))
+        mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
+
+    @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_fetch_credentials_missing_installer_ip(self, mock_click_echo,
+                                                    mock_os_path,
+                                                    mock_ftutils_execute):
+        installer_type = self.installer_type
+        installer_ip = None
+        CONST.INSTALLER_TYPE = installer_type
+        CONST.INSTALLER_IP = installer_ip
+        cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
+               % (CONST.dir_repos,
+                  self.openstack_creds,
+                  installer_type,
+                  installer_ip))
+        self.cli_os.openstack_creds = self.openstack_creds
+        self.cli_os.fetch_credentials()
+        mock_click_echo.assert_any_call("The environment variable "
+                                        "'INSTALLER_IP' is not"
+                                        "defined. Please export it")
+        mock_click_echo.assert_any_call("Fetching credentials from "
+                                        "installer node '%s' with "
+                                        "IP=%s.." %
+                                        (installer_type,
+                                         installer_ip))
+        mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
+
+    @mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
+    def test_check(self, mock_ftutils_execute):
+        with mock.patch.object(self.cli_os, 'ping_endpoint'):
+            CONST.dir_repo_functest = self.dir_repo_functest
+            cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
+            self.cli_os.check()
+            mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_snapshot_create(self, mock_click_echo, mock_os_path):
+        with mock.patch.object(self.cli_os, 'ping_endpoint'), \
+                mock.patch('functest.cli.commands.cli_os.os_snapshot.main') \
+                as mock_os_snapshot:
+            self.cli_os.snapshot_create()
+            mock_click_echo.assert_called_once_with("Generating Openstack "
+                                                    "snapshot...")
+            self.assertTrue(mock_os_snapshot.called)
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_snapshot_create_overwrite(self, mock_click_echo, mock_os_path):
+        with mock.patch('__builtin__.raw_input', return_value="y") \
+                as mock_raw_input, \
+                mock.patch.object(self.cli_os, 'ping_endpoint'), \
+                mock.patch('functest.cli.commands.cli_os.os_snapshot.main') \
+                as mock_os_snapshot:
+            self.cli_os.snapshot_create()
+            mock_click_echo.assert_called_once_with("Generating Openstack "
+                                                    "snapshot...")
+            mock_raw_input.assert_any_call("It seems there is already an "
+                                           "OpenStack snapshot. Do you want "
+                                           "to overwrite it with the current "
+                                           "OpenStack status? [y|n]\n")
+            self.assertTrue(mock_os_snapshot.called)
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_snapshot_show_missing_snap(self, mock_click_echo, mock_os_path):
+        self.cli_os.snapshot_show()
+        mock_click_echo.assert_called_once_with("There is no OpenStack "
+                                                "snapshot created. To create "
+                                                "one run the command "
+                                                "'functest openstack "
+                                                "snapshot-create'")
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_snapshot_show_default(self, mock_click_echo, mock_os_path):
+        with mock.patch('__builtin__.open', mock.mock_open(read_data='0')) \
+                as m:
+            self.cli_os.snapshot_file = self.snapshot_file
+            self.cli_os.snapshot_show()
+            m.assert_called_once_with(self.snapshot_file, 'r')
+            mock_click_echo.assert_called_once_with("\n0")
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_clean(self, mock_click_echo, mock_os_path):
+        with mock.patch.object(self.cli_os, 'ping_endpoint'), \
+                mock.patch('functest.cli.commands.cli_os.os_clean.main') \
+                as mock_os_clean:
+            self.cli_os.clean()
+            self.assertTrue(mock_os_clean.called)
+
+    @mock.patch('functest.cli.commands.cli_os.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_clean_missing_file(self, mock_click_echo, mock_os_path):
+        with mock.patch.object(self.cli_os, 'ping_endpoint'):
+            self.cli_os.clean()
+            mock_click_echo.assert_called_once_with("Not possible to clean "
+                                                    "OpenStack without a "
+                                                    "snapshot. This could "
+                                                    "cause problems. "
+                                                    "Run first the command "
+                                                    "'functest openstack "
+                                                    "snapshot-create'")
+
+    @mock.patch('functest.cli.commands.cli_os.click.echo')
+    def test_show_credentials(self, mock_click_echo):
+        key = 'OS_KEY'
+        value = 'OS_VALUE'
+        with mock.patch.dict(os.environ, {key: value}):
+            self.cli_os.show_credentials()
+            mock_click_echo.assert_any_call("{}={}".format(key, value))
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_testcase.py b/functest/tests/unit/cli/commands/test_cli_testcase.py
new file mode 100644 (file)
index 0000000..39c8139
--- /dev/null
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+
+import logging
+import unittest
+
+import mock
+
+from functest.cli.commands import cli_testcase
+from functest.utils.constants import CONST
+
+
+class CliTestCasesTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.testname = 'testname'
+        with mock.patch('functest.cli.commands.cli_testcase.tb'):
+            self.cli_tests = cli_testcase.CliTestcase()
+
+    @mock.patch('functest.cli.commands.cli_testcase.vacation.main')
+    def test_run_vacation(self, mock_method):
+        self.cli_tests.run('vacation')
+        self.assertTrue(mock_method.called)
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_testcase.click.echo')
+    def test_run_missing_env_file(self, mock_click_echo, mock_os):
+        self.cli_tests.run(self.testname)
+        mock_click_echo.assert_called_with("Functest environment is not ready."
+                                           " Run first 'functest env prepare'")
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_run_default(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", self.testname))
+        self.cli_tests.run(self.testname, noclean=True, report=True)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-n ", self.testname))
+        self.cli_tests.run(self.testname, noclean=True, report=False)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-r ", self.testname))
+        self.cli_tests.run(self.testname, noclean=False, report=True)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_testcase.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
+    def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "", self.testname))
+        self.cli_tests.run(self.testname, noclean=False, report=False)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_testcase.click.echo')
+    def test_list(self, mock_click_echo):
+        with mock.patch.object(self.cli_tests.tiers, 'get_tiers',
+                               return_value=[]):
+            self.cli_tests.list()
+            mock_click_echo.assert_called_with("")
+
+    @mock.patch('functest.cli.commands.cli_testcase.click.echo')
+    def test_show_default_desc_none(self, mock_click_echo):
+        with mock.patch.object(self.cli_tests.tiers, 'get_test',
+                               return_value=None):
+            self.cli_tests.show(self.testname)
+            mock_click_echo.assert_any_call("The test case '%s' "
+                                            "does not exist or is"
+                                            " not supported."
+                                            % self.testname)
+
+    @mock.patch('functest.cli.commands.cli_testcase.click.echo')
+    def test_show_default(self, mock_click_echo):
+        mock_obj = mock.Mock()
+        with mock.patch.object(self.cli_tests.tiers, 'get_test',
+                               return_value=mock_obj):
+            self.cli_tests.show(self.testname)
+            mock_click_echo.assert_called_with(mock_obj)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/commands/test_cli_tier.py b/functest/tests/unit/cli/commands/test_cli_tier.py
new file mode 100644 (file)
index 0000000..802359f
--- /dev/null
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+
+import logging
+import unittest
+
+import mock
+
+from functest.cli.commands import cli_tier
+from functest.utils.constants import CONST
+
+
+class CliTierTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.tiername = 'tiername'
+        self.testnames = 'testnames'
+        with mock.patch('functest.cli.commands.cli_tier.tb'):
+            self.cli_tier = cli_tier.CliTier()
+
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_list(self, mock_click_echo):
+        with mock.patch.object(self.cli_tier.tiers, 'get_tiers',
+                               return_value=[]):
+            self.cli_tier.list()
+            mock_click_echo.assert_called_with("")
+
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_show_default(self, mock_click_echo):
+        with mock.patch.object(self.cli_tier.tiers, 'get_tier',
+                               return_value=self.tiername):
+            self.cli_tier.show(self.tiername)
+            mock_click_echo.assert_called_with(self.tiername)
+
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_show_missing_tier(self, mock_click_echo):
+        with mock.patch.object(self.cli_tier.tiers, 'get_tier',
+                               return_value=None), \
+            mock.patch.object(self.cli_tier.tiers, 'get_tier_names',
+                              return_value='tiernames'):
+            self.cli_tier.show(self.tiername)
+            mock_click_echo.assert_called_with("The tier with name '%s' does "
+                                               "not exist. Available tiers are"
+                                               ":\n  %s\n" % (self.tiername,
+                                                              'tiernames'))
+
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_gettests_default(self, mock_click_echo):
+        mock_obj = mock.Mock()
+        attrs = {'get_test_names.return_value': self.testnames}
+        mock_obj.configure_mock(**attrs)
+
+        with mock.patch.object(self.cli_tier.tiers, 'get_tier',
+                               return_value=mock_obj):
+            self.cli_tier.gettests(self.tiername)
+            mock_click_echo.assert_called_with("Test cases in tier "
+                                               "'%s':\n %s\n" % (self.tiername,
+                                                                 self.testnames
+                                                                 ))
+
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_gettests_missing_tier(self, mock_click_echo):
+        with mock.patch.object(self.cli_tier.tiers, 'get_tier',
+                               return_value=None), \
+            mock.patch.object(self.cli_tier.tiers, 'get_tier_names',
+                              return_value='tiernames'):
+            self.cli_tier.gettests(self.tiername)
+            mock_click_echo.assert_called_with("The tier with name '%s' does "
+                                               "not exist. Available tiers are"
+                                               ":\n  %s\n" % (self.tiername,
+                                                              'tiernames'))
+
+    @mock.patch('functest.cli.commands.cli_tier.os.path.isfile',
+                return_value=False)
+    @mock.patch('functest.cli.commands.cli_tier.click.echo')
+    def test_run_missing_env_file(self, mock_click_echo, mock_os):
+        self.cli_tier.run(self.tiername)
+        mock_click_echo.assert_called_with("Functest environment is not ready."
+                                           " Run first 'functest env prepare'")
+
+    @mock.patch('functest.cli.commands.cli_tier.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
+    def test_run_default(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-n -r ",
+                             self.tiername))
+        self.cli_tier.run(self.tiername, noclean=True, report=True)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_tier.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
+    def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-r ",
+                             self.tiername))
+        self.cli_tier.run(self.tiername, noclean=False, report=True)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_tier.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
+    def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "-n ",
+                             self.tiername))
+        self.cli_tier.run(self.tiername, noclean=True, report=False)
+        mock_ft_utils.assert_called_with(cmd)
+
+    @mock.patch('functest.cli.commands.cli_tier.os.path.isfile',
+                return_value=True)
+    @mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
+    def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
+        cmd = ("python %s/functest/ci/run_tests.py "
+               "%s -t %s" % (CONST.dir_repo_functest, "",
+                             self.tiername))
+        self.cli_tier.run(self.tiername, noclean=False, report=False)
+        mock_ft_utils.assert_called_with(cmd)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/cli/test_cli_base.py b/functest/tests/unit/cli/test_cli_base.py
new file mode 100644 (file)
index 0000000..fe065c2
--- /dev/null
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import logging
+import unittest
+
+import mock
+from click.testing import CliRunner
+
+with mock.patch('functest.cli.commands.cli_testcase.CliTestcase.__init__',
+                mock.Mock(return_value=None)), \
+    mock.patch('functest.cli.commands.cli_tier.CliTier.__init__',
+               mock.Mock(return_value=None)):
+    from functest.cli import cli_base
+
+
+class CliBaseTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.runner = CliRunner()
+        self._openstack = cli_base._openstack
+        self._env = cli_base._env
+        self._testcase = cli_base._testcase
+        self._tier = cli_base._tier
+
+    def test_os_check(self):
+        with mock.patch.object(self._openstack, 'check') as mock_method:
+            result = self.runner.invoke(cli_base.os_check)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_os_snapshot_create(self):
+        with mock.patch.object(self._openstack, 'snapshot_create') \
+                as mock_method:
+            result = self.runner.invoke(cli_base.os_snapshot_create)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_os_snapshot_show(self):
+        with mock.patch.object(self._openstack, 'snapshot_show') \
+                as mock_method:
+            result = self.runner.invoke(cli_base.os_snapshot_show)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_os_clean(self):
+        with mock.patch.object(self._openstack, 'clean') as mock_method:
+            result = self.runner.invoke(cli_base.os_clean)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_os_show_credentials(self):
+        with mock.patch.object(self._openstack, 'show_credentials') \
+                as mock_method:
+            result = self.runner.invoke(cli_base.os_show_credentials)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_os_fetch_rc(self):
+        with mock.patch.object(self._openstack, 'fetch_credentials') \
+                as mock_method:
+            result = self.runner.invoke(cli_base.os_fetch_rc)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_env_prepare(self):
+        with mock.patch.object(self._env, 'prepare') as mock_method:
+            result = self.runner.invoke(cli_base.env_prepare)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_env_show(self):
+        with mock.patch.object(self._env, 'show') as mock_method:
+            result = self.runner.invoke(cli_base.env_show)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_env_status(self):
+        with mock.patch.object(self._env, 'status') as mock_method:
+            result = self.runner.invoke(cli_base.env_status)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_testcase_list(self):
+        with mock.patch.object(self._testcase, 'list') as mock_method:
+            result = self.runner.invoke(cli_base.testcase_list)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_testcase_show(self):
+        with mock.patch.object(self._testcase, 'show') as mock_method:
+            result = self.runner.invoke(cli_base.testcase_show, ['testname'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_testcase_run(self):
+        with mock.patch.object(self._testcase, 'run') as mock_method:
+            result = self.runner.invoke(cli_base.testcase_run,
+                                        ['testname', '--noclean'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_tier_list(self):
+        with mock.patch.object(self._tier, 'list') as mock_method:
+            result = self.runner.invoke(cli_base.tier_list)
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_tier_show(self):
+        with mock.patch.object(self._tier, 'show') as mock_method:
+            result = self.runner.invoke(cli_base.tier_show, ['tiername'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_tier_gettests(self):
+        with mock.patch.object(self._tier, 'gettests') as mock_method:
+            result = self.runner.invoke(cli_base.tier_gettests, ['tiername'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+    def test_tier_run(self):
+        with mock.patch.object(self._tier, 'run') as mock_method:
+            result = self.runner.invoke(cli_base.tier_run,
+                                        ['tiername', '--noclean'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertTrue(mock_method.called)
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
index fe7b0d0..b6efa40 100644 (file)
@@ -11,7 +11,8 @@ import logging
 import mock
 import unittest
 
-import functest.core.testcase_base as testcase_base
+mock.patch('logging.FileHandler').start()  # noqa
+from functest.core import testcase_base
 
 
 class TestcaseBaseTesting(unittest.TestCase):
@@ -24,7 +25,7 @@ class TestcaseBaseTesting(unittest.TestCase):
         self.test.case_name = "base"
         self.test.start_time = "1"
         self.test.stop_time = "2"
-        self.test.criteria = "100"
+        self.test.criteria = "PASS"
         self.test.details = {"Hello": "World"}
 
     def test_run_unimplemented(self):
@@ -82,6 +83,21 @@ class TestcaseBaseTesting(unittest.TestCase):
             self.test.project, self.test.case_name, self.test.start_time,
             self.test.stop_time, self.test.criteria, self.test.details)
 
+    def test_check_criteria_missing(self):
+        self.test.criteria = None
+        self.assertEqual(self.test.check_criteria(),
+                         testcase_base.TestcaseBase.EX_TESTCASE_FAILED)
+
+    def test_check_criteria_failed(self):
+        self.test.criteria = 'FAILED'
+        self.assertEqual(self.test.check_criteria(),
+                         testcase_base.TestcaseBase.EX_TESTCASE_FAILED)
+
+    def test_check_criteria_pass(self):
+        self.test.criteria = 'PASS'
+        self.assertEqual(self.test.check_criteria(),
+                         testcase_base.TestcaseBase.EX_OK)
+
 
 if __name__ == "__main__":
     unittest.main(verbosity=2)
index ef18016..d45d562 100644 (file)
@@ -11,13 +11,17 @@ import errno
 import logging
 import mock
 import os
+import StringIO
 import unittest
 
-from robot.errors import RobotError
+from keystoneauth1.exceptions import auth_plugins
+from robot.errors import DataError, RobotError
+from robot.result import testcase
+from robot.utils.robottime import timestamp_to_secs
 
-import functest.core.testcase_base as testcase_base
+mock.patch('logging.FileHandler').start()  # noqa
+from functest.core import testcase_base
 from functest.opnfv_tests.sdn.odl import odl
-from functest.utils import functest_constants as ft_constants
 
 
 class ODLTesting(unittest.TestCase):
@@ -36,19 +40,111 @@ class ODLTesting(unittest.TestCase):
     _odl_password = "admin"
 
     def setUp(self):
-        ft_constants.OS_USERNAME = self._os_username
-        ft_constants.OS_PASSWORD = self._os_password
-        ft_constants.OS_TENANT_NAME = self._os_tenantname
+        for var in ("INSTALLER_TYPE", "SDN_CONTROLLER", "SDN_CONTROLLER_IP"):
+            if var in os.environ:
+                del os.environ[var]
+        os.environ["OS_USERNAME"] = self._os_username
+        os.environ["OS_PASSWORD"] = self._os_password
+        os.environ["OS_TENANT_NAME"] = self._os_tenantname
         self.test = odl.ODLTests()
+        self.defaultargs = {'odlusername': self._odl_username,
+                            'odlpassword': self._odl_password,
+                            'keystoneip': self._keystone_ip,
+                            'neutronip': self._keystone_ip,
+                            'osusername': self._os_username,
+                            'ostenantname': self._os_tenantname,
+                            'ospassword': self._os_password,
+                            'odlip': self._keystone_ip,
+                            'odlwebport': self._odl_webport,
+                            'odlrestconfport': self._odl_restconfport,
+                            'pushtodb': False}
+
+    def test_empty_visitor(self):
+        visitor = odl.ODLResultVisitor()
+        self.assertFalse(visitor.get_data())
+
+    def test_visitor(self):
+        visitor = odl.ODLResultVisitor()
+        data = {'name': 'foo',
+                'parent': 'bar',
+                'status': 'PASS',
+                'starttime': "20161216 16:00:00.000",
+                'endtime': "20161216 16:00:01.000",
+                'elapsedtime': 1000,
+                'text': 'Hello, World!',
+                'critical': True}
+        test = testcase.TestCase(name=data['name'],
+                                 status=data['status'],
+                                 message=data['text'],
+                                 starttime=data['starttime'],
+                                 endtime=data['endtime'])
+        test.parent = mock.Mock()
+        config = {'name': data['parent'],
+                  'criticality.test_is_critical.return_value': data[
+                      'critical']}
+        test.parent.configure_mock(**config)
+        visitor.visit_test(test)
+        self.assertEqual(visitor.get_data(), [data])
+
+    @mock.patch('robot.api.ExecutionResult', side_effect=DataError)
+    def test_parse_results_raises_exceptions(self, *args):
+        with self.assertRaises(DataError):
+            self.test.parse_results()
+
+    def test_parse_results(self, *args):
+        config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000',
+                  'endtime': '20161216 16:00:01.000', 'status': 'PASS'}
+        suite = mock.Mock()
+        suite.configure_mock(**config)
+        with mock.patch('robot.api.ExecutionResult',
+                        return_value=mock.Mock(suite=suite)):
+            self.test.parse_results()
+            self.assertEqual(self.test.criteria, config['status'])
+            self.assertEqual(self.test.start_time,
+                             timestamp_to_secs(config['starttime']))
+            self.assertEqual(self.test.stop_time,
+                             timestamp_to_secs(config['endtime']))
+            self.assertEqual(self.test.details,
+                             {'description': config['name'], 'tests': []})
 
     @mock.patch('fileinput.input', side_effect=Exception())
     def test_set_robotframework_vars_failed(self, *args):
         self.assertFalse(self.test.set_robotframework_vars())
 
     @mock.patch('fileinput.input', return_value=[])
-    def test_set_robotframework_vars(self, args):
+    def test_set_robotframework_vars_empty(self, args):
         self.assertTrue(self.test.set_robotframework_vars())
 
+    @mock.patch('sys.stdout', new_callable=StringIO.StringIO)
+    def _test_set_robotframework_vars(self, msg1, msg2, *args):
+        line = mock.MagicMock()
+        line.__iter__.return_value = [msg1]
+        with mock.patch('fileinput.input', return_value=line) as mock_method:
+            self.assertTrue(self.test.set_robotframework_vars())
+            mock_method.assert_called_once_with(
+                os.path.join(odl.ODLTests.odl_test_repo,
+                             'csit/variables/Variables.py'), inplace=True)
+            self.assertEqual(args[0].getvalue(), "{}\n".format(msg2))
+
+    def test_set_robotframework_vars_auth_default(self):
+        self._test_set_robotframework_vars("AUTH = []",
+                                           "AUTH = [u'admin', u'admin']")
+
+    def test_set_robotframework_vars_auth1(self):
+        self._test_set_robotframework_vars("AUTH1 = []", "AUTH1 = []")
+
+    @mock.patch('sys.stdout', new_callable=StringIO.StringIO)
+    def test_set_robotframework_vars_auth_foo(self, *args):
+        line = mock.MagicMock()
+        line.__iter__.return_value = ["AUTH = []"]
+        with mock.patch('fileinput.input', return_value=line) as mock_method:
+            self.assertTrue(self.test.set_robotframework_vars('foo', 'bar'))
+            mock_method.assert_called_once_with(
+                os.path.join(odl.ODLTests.odl_test_repo,
+                             'csit/variables/Variables.py'), inplace=True)
+            self.assertEqual(args[0].getvalue(),
+                             "AUTH = [u'{}', u'{}']\n".format('foo', 'bar'))
+
     @classmethod
     def _fake_url_for(cls, service_type='identity', **kwargs):
         if service_type == 'identity':
@@ -59,14 +155,6 @@ class ODLTesting(unittest.TestCase):
         else:
             return None
 
-    @classmethod
-    def _get_fake_keystone_client(cls):
-        kclient = mock.Mock()
-        kclient.service_catalog = mock.Mock()
-        kclient.service_catalog.url_for = mock.Mock(
-            side_effect=cls._fake_url_for)
-        return kclient
-
     def _get_main_kwargs(self, key=None):
         kwargs = {'odlusername': self._odl_username,
                   'odlpassword': self._odl_password,
@@ -85,9 +173,9 @@ class ODLTesting(unittest.TestCase):
     def _test_main(self, status, *args):
         kwargs = self._get_main_kwargs()
         self.assertEqual(self.test.main(**kwargs), status)
-        odl_res_dir = odl.ODLTests.res_dir
         if len(args) > 0:
-            args[0].assert_called_once_with(odl_res_dir)
+            args[0].assert_called_once_with(
+                odl.ODLTests.res_dir)
         if len(args) > 1:
             variable = ['KEYSTONE:{}'.format(self._keystone_ip),
                         'NEUTRON:{}'.format(self._neutron_ip),
@@ -97,18 +185,17 @@ class ODLTesting(unittest.TestCase):
                         'ODL_SYSTEM_IP:{}'.format(self._sdn_controller_ip),
                         'PORT:{}'.format(self._odl_webport),
                         'RESTCONFPORT:{}'.format(self._odl_restconfport)]
-            output_file = os.path.join(odl_res_dir, 'output.xml')
             args[1].assert_called_once_with(
                 odl.ODLTests.basic_suite_dir,
                 odl.ODLTests.neutron_suite_dir,
                 log='NONE',
-                output=output_file,
+                output=os.path.join(odl.ODLTests.res_dir, 'output.xml'),
                 report='NONE',
                 stdout=mock.ANY,
                 variable=variable)
         if len(args) > 2:
-            stdout_file = os.path.join(odl_res_dir, 'stdout.txt')
-            args[2].assert_called_with(stdout_file)
+            args[2].assert_called_with(
+                os.path.join(odl.ODLTests.res_dir, 'stdout.txt'))
 
     def _test_main_missing_keyword(self, key):
         kwargs = self._get_main_kwargs(key)
@@ -172,6 +259,8 @@ class ODLTesting(unittest.TestCase):
     def test_main_robot_run_failed(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
                 self.assertRaises(RobotError):
             self._test_main(testcase_base.TestcaseBase.EX_RUN_ERROR, *args)
 
@@ -180,6 +269,8 @@ class ODLTesting(unittest.TestCase):
     def test_main_parse_results_failed(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
                 mock.patch.object(self.test, 'parse_results',
                                   side_effect=RobotError):
             self._test_main(testcase_base.TestcaseBase.EX_RUN_ERROR, *args)
@@ -200,8 +291,9 @@ class ODLTesting(unittest.TestCase):
     def test_main(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(self.test, 'parse_results',
-                                  return_value="PASS"):
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
+                mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase_base.TestcaseBase.EX_OK, *args)
 
     @mock.patch('os.remove')
@@ -210,8 +302,9 @@ class ODLTesting(unittest.TestCase):
     def test_main_makedirs_oserror17(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(self.test, 'parse_results',
-                                  return_value="PASS"):
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
+                mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase_base.TestcaseBase.EX_OK, *args)
 
     @mock.patch('os.remove')
@@ -220,8 +313,9 @@ class ODLTesting(unittest.TestCase):
     def test_main_testcases_in_failure(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(self.test, 'parse_results',
-                                  return_value="PASS"):
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
+                mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase_base.TestcaseBase.EX_OK, *args)
 
     @mock.patch('os.remove', side_effect=OSError)
@@ -230,25 +324,22 @@ class ODLTesting(unittest.TestCase):
     def test_main_remove_oserror(self, *args):
         with mock.patch.object(self.test, 'set_robotframework_vars',
                                return_value=True), \
-                mock.patch.object(self.test, 'parse_results',
-                                  return_value="PASS"):
+                mock.patch.object(odl, 'open', mock.mock_open(),
+                                  create=True), \
+                mock.patch.object(self.test, 'parse_results'):
             self._test_main(testcase_base.TestcaseBase.EX_OK, *args)
 
     def _test_run_missing_env_var(self, var):
-        if var == 'OS_USERNAME':
-            ft_constants.OS_USERNAME = None
-        elif var == 'OS_PASSWORD':
-            ft_constants.OS_PASSWORD = None
-        elif var == 'OS_TENANT_NAME':
-            ft_constants.OS_TENANT_NAME = None
-
-        self.assertEqual(self.test.run(),
-                         testcase_base.TestcaseBase.EX_RUN_ERROR)
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=self._fake_url_for):
+            del os.environ[var]
+            self.assertEqual(self.test.run(),
+                             testcase_base.TestcaseBase.EX_RUN_ERROR)
 
     def _test_run(self, status=testcase_base.TestcaseBase.EX_OK,
                   exception=None, odlip="127.0.0.3", odlwebport="8080"):
-        with mock.patch('functest.utils.openstack_utils.get_keystone_client',
-                        return_value=self._get_fake_keystone_client()):
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=self._fake_url_for):
             if exception:
                 self.test.main = mock.Mock(side_effect=exception)
             else:
@@ -262,6 +353,12 @@ class ODLTesting(unittest.TestCase):
                 ospassword=self._os_password, ostenantname=self._os_tenantname,
                 osusername=self._os_username)
 
+    def test_run_exception(self):
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=auth_plugins.MissingAuthPlugin()):
+            self.assertEqual(self.test.run(),
+                             testcase_base.TestcaseBase.EX_RUN_ERROR)
+
     def test_run_missing_os_username(self):
         self._test_run_missing_env_var("OS_USERNAME")
 
@@ -272,75 +369,138 @@ class ODLTesting(unittest.TestCase):
         self._test_run_missing_env_var("OS_TENANT_NAME")
 
     def test_run_main_false(self):
-        ft_constants.CI_INSTALLER_TYPE = None
-        ft_constants.SDN_CONTROLLER_IP = self._sdn_controller_ip
+        os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
         self._test_run(testcase_base.TestcaseBase.EX_RUN_ERROR,
                        odlip=self._sdn_controller_ip,
                        odlwebport=self._odl_webport)
 
     def test_run_main_exception(self):
-        ft_constants.CI_INSTALLER_TYPE = None
-        ft_constants.SDN_CONTROLLER_IP = self._sdn_controller_ip
         with self.assertRaises(Exception):
+            os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
             self._test_run(status=testcase_base.TestcaseBase.EX_RUN_ERROR,
                            exception=Exception(),
                            odlip=self._sdn_controller_ip,
                            odlwebport=self._odl_webport)
 
     def test_run_missing_sdn_controller_ip(self):
-        with mock.patch('functest.utils.openstack_utils.get_keystone_client',
-                        return_value=self._get_fake_keystone_client()):
-            ft_constants.CI_INSTALLER_TYPE = None
-            ft_constants.SDN_CONTROLLER_IP = None
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=self._fake_url_for):
             self.assertEqual(self.test.run(),
                              testcase_base.TestcaseBase.EX_RUN_ERROR)
 
     def test_run_without_installer_type(self):
-        ft_constants.SDN_CONTROLLER_IP = self._sdn_controller_ip
-        ft_constants.CI_INSTALLER_TYPE = None
+        os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
         self._test_run(testcase_base.TestcaseBase.EX_OK,
                        odlip=self._sdn_controller_ip,
                        odlwebport=self._odl_webport)
 
     def test_run_fuel(self):
-        ft_constants.CI_INSTALLER_TYPE = "fuel"
+        os.environ["INSTALLER_TYPE"] = "fuel"
         self._test_run(testcase_base.TestcaseBase.EX_OK,
                        odlip=self._neutron_ip, odlwebport='8282')
 
     def test_run_apex_missing_sdn_controller_ip(self):
-        with mock.patch('functest.utils.openstack_utils.get_keystone_client',
-                        return_value=self._get_fake_keystone_client()):
-            ft_constants.CI_INSTALLER_TYPE = "apex"
-            ft_constants.SDN_CONTROLLER_IP = None
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=self._fake_url_for):
+            os.environ["INSTALLER_TYPE"] = "apex"
             self.assertEqual(self.test.run(),
                              testcase_base.TestcaseBase.EX_RUN_ERROR)
 
     def test_run_apex(self):
-        ft_constants.SDN_CONTROLLER_IP = self._sdn_controller_ip
-        ft_constants.CI_INSTALLER_TYPE = "apex"
+        os.environ["SDN_CONTROLLER_IP"] = self._sdn_controller_ip
+        os.environ["INSTALLER_TYPE"] = "apex"
         self._test_run(testcase_base.TestcaseBase.EX_OK,
                        odlip=self._sdn_controller_ip, odlwebport='8181')
 
     def test_run_joid_missing_sdn_controller(self):
-        with mock.patch('functest.utils.openstack_utils.get_keystone_client',
-                        return_value=self._get_fake_keystone_client()):
-            ft_constants.CI_INSTALLER_TYPE = "joid"
-            ft_constants.SDN_CONTROLLER = None
+        with mock.patch('functest.utils.openstack_utils.get_endpoint',
+                        side_effect=self._fake_url_for):
+            os.environ["INSTALLER_TYPE"] = "joid"
             self.assertEqual(self.test.run(),
                              testcase_base.TestcaseBase.EX_RUN_ERROR)
 
     def test_run_joid(self):
-        ft_constants.SDN_CONTROLLER = self._sdn_controller_ip
-        ft_constants.CI_INSTALLER_TYPE = "joid"
+        os.environ["SDN_CONTROLLER"] = self._sdn_controller_ip
+        os.environ["INSTALLER_TYPE"] = "joid"
         self._test_run(testcase_base.TestcaseBase.EX_OK,
-                       odlip=self._sdn_controller_ip,
-                       odlwebport=self._odl_webport)
+                       odlip=self._sdn_controller_ip, odlwebport='8080')
 
     def test_run_compass(self, *args):
-        ft_constants.CI_INSTALLER_TYPE = "compass"
+        os.environ["INSTALLER_TYPE"] = "compass"
         self._test_run(testcase_base.TestcaseBase.EX_OK,
                        odlip=self._neutron_ip, odlwebport='8181')
 
+    def test_argparser_default(self):
+        parser = odl.ODLParser()
+        self.assertEqual(parser.parse_args(), self.defaultargs)
+
+    def test_argparser_basic(self):
+        self.defaultargs['neutronip'] = self._neutron_ip
+        self.defaultargs['odlip'] = self._sdn_controller_ip
+        parser = odl.ODLParser()
+        self.assertEqual(parser.parse_args(
+            ["--neutronip={}".format(self._neutron_ip),
+             "--odlip={}".format(self._sdn_controller_ip)
+             ]), self.defaultargs)
+
+    @mock.patch('sys.stderr', new_callable=StringIO.StringIO)
+    def test_argparser_fail(self, *args):
+        self.defaultargs['foo'] = 'bar'
+        parser = odl.ODLParser()
+        with self.assertRaises(SystemExit):
+            parser.parse_args(["--foo=bar"])
+
+    def _test_argparser(self, arg, value):
+        self.defaultargs[arg] = value
+        parser = odl.ODLParser()
+        self.assertEqual(parser.parse_args(["--{}={}".format(arg, value)]),
+                         self.defaultargs)
+
+    def test_argparser_odlusername(self):
+        self._test_argparser('odlusername', 'foo')
+
+    def test_argparser_odlpassword(self):
+        self._test_argparser('odlpassword', 'foo')
+
+    def test_argparser_keystoneip(self):
+        self._test_argparser('keystoneip', '127.0.0.4')
+
+    def test_argparser_neutronip(self):
+        self._test_argparser('neutronip', '127.0.0.4')
+
+    def test_argparser_osusername(self):
+        self._test_argparser('osusername', 'foo')
+
+    def test_argparser_ostenantname(self):
+        self._test_argparser('ostenantname', 'foo')
+
+    def test_argparser_ospassword(self):
+        self._test_argparser('ospassword', 'foo')
+
+    def test_argparser_odlip(self):
+        self._test_argparser('odlip', '127.0.0.4')
+
+    def test_argparser_odlwebport(self):
+        self._test_argparser('odlwebport', '80')
+
+    def test_argparser_odlrestconfport(self):
+        self._test_argparser('odlrestconfport', '80')
+
+    def test_argparser_pushtodb(self):
+        self.defaultargs['pushtodb'] = True
+        parser = odl.ODLParser()
+        self.assertEqual(parser.parse_args(["--{}".format('pushtodb')]),
+                         self.defaultargs)
+
+    def test_argparser_multiple_args(self):
+        self.defaultargs['neutronip'] = self._neutron_ip
+        self.defaultargs['odlip'] = self._sdn_controller_ip
+        parser = odl.ODLParser()
+        self.assertEqual(parser.parse_args(
+            ["--neutronip={}".format(self._neutron_ip),
+             "--odlip={}".format(self._sdn_controller_ip)
+             ]), self.defaultargs)
+
 
 if __name__ == "__main__":
     unittest.main(verbosity=2)
diff --git a/functest/tests/unit/test_utils.py b/functest/tests/unit/test_utils.py
new file mode 100644 (file)
index 0000000..e171db0
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import re
+
+
+class RegexMatch(str):
+    def __eq__(self, other):
+        match = re.search(self, other)
+        if match:
+            return True
+        return False
+
+
+class SubstrMatch(str):
+    def __eq__(self, other):
+        if self in other:
+            return True
+        return False
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
new file mode 100644 (file)
index 0000000..c4b5666
--- /dev/null
@@ -0,0 +1,600 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import logging
+import os
+import time
+import unittest
+import urllib2
+
+from git.exc import NoSuchPathError
+import mock
+import requests
+
+from functest.tests.unit import test_utils
+mock.patch('logging.FileHandler').start()  # noqa
+from functest.utils import functest_utils
+
+
+class FunctestUtilsTesting(unittest.TestCase):
+
+    logging.disable(logging.CRITICAL)
+
+    def setUp(self):
+        self.url = 'http://www.opnfv.org/'
+        self.timeout = 5
+        self.dest_path = 'test_path'
+        self.repo_path = 'test_repo_path'
+        self.installer = 'test_installer'
+        self.scenario = 'test_scenario'
+        self.build_tag = 'jenkins-functest-fuel-opnfv-jump-2-daily-master-190'
+        self.version = 'master'
+        self.node_name = 'test_node_name'
+        self.project = 'test_project'
+        self.case_name = 'test_case_name'
+        self.status = 'test_status'
+        self.details = 'test_details'
+        self.db_url = 'test_db_url'
+        self.success_rate = 2.0
+        self.criteria = 'test_criteria==2.0'
+        self.start_date = 1482624000
+        self.stop_date = 1482624000
+        self.start_time = time.time()
+        self.stop_time = time.time()
+        self.readline = -1
+        self.test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
+        self.test_file = 'test_file'
+        self.error_msg = 'test_error_msg'
+        self.cmd = 'test_cmd'
+        self.output_file = 'test_output_file'
+        self.testname = 'testname'
+        self.testcase_dict = {'name': 'testname', 'criteria': self.criteria}
+        self.parameter = 'general.openstack.image_name'
+        self.config_yaml = 'test_config_yaml-'
+        self.file_yaml = {'general': {'openstack': {'image_name':
+                                                    'test_image_name'}}}
+
+    @mock.patch('urllib2.urlopen',
+                side_effect=urllib2.URLError('no host given'))
+    def test_check_internet_connectivity_failed(self, mock_method):
+        self.assertFalse(functest_utils.check_internet_connectivity())
+        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
+
+    @mock.patch('urllib2.urlopen')
+    def test_check_internet_connectivity_default(self, mock_method):
+        self.assertTrue(functest_utils.check_internet_connectivity())
+        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
+
+    @mock.patch('urllib2.urlopen')
+    def test_check_internet_connectivity_debian(self, mock_method):
+        self.url = "https://www.debian.org/"
+        self.assertTrue(functest_utils.check_internet_connectivity(self.url))
+        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
+
+    @mock.patch('urllib2.urlopen',
+                side_effect=urllib2.URLError('no host given'))
+    def test_download_url_failed(self, mock_url):
+        self.assertFalse(functest_utils.download_url(self.url, self.dest_path))
+
+    @mock.patch('urllib2.urlopen')
+    def test_download_url_default(self, mock_url):
+        with mock.patch("__builtin__.open", mock.mock_open()) as m, \
+                mock.patch('functest.utils.functest_utils.shutil.copyfileobj')\
+                as mock_sh:
+            name = self.url.rsplit('/')[-1]
+            dest = self.dest_path + "/" + name
+            self.assertTrue(functest_utils.download_url(self.url,
+                                                        self.dest_path))
+            m.assert_called_once_with(dest, 'wb')
+            self.assertTrue(mock_sh.called)
+
+    def test_get_git_branch(self):
+        with mock.patch('functest.utils.functest_utils.Repo') as mock_repo:
+            mock_obj2 = mock.Mock()
+            attrs = {'name': 'test_branch'}
+            mock_obj2.configure_mock(**attrs)
+
+            mock_obj = mock.Mock()
+            attrs = {'active_branch': mock_obj2}
+            mock_obj.configure_mock(**attrs)
+
+            mock_repo.return_value = mock_obj
+            self.assertEqual(functest_utils.get_git_branch(self.repo_path),
+                             'test_branch')
+
+    @mock.patch('functest.utils.functest_utils.Repo',
+                side_effect=NoSuchPathError)
+    def test_get_git_branch_failed(self, mock_repo):
+        self.assertRaises(NoSuchPathError,
+                          lambda: functest_utils.get_git_branch(self.repo_path
+                                                                ))
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_get_installer_type_failed(self, mock_logger_error):
+        with mock.patch.dict(os.environ,
+                             {},
+                             clear=True):
+            self.assertEqual(functest_utils.get_installer_type(),
+                             "Unknown_installer")
+            mock_logger_error.assert_called_once_with("Impossible to retrieve"
+                                                      " the installer type")
+
+    def test_get_installer_type_default(self):
+        with mock.patch.dict(os.environ,
+                             {'INSTALLER_TYPE': 'test_installer'},
+                             clear=True):
+            self.assertEqual(functest_utils.get_installer_type(),
+                             self.installer)
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_get_scenario_failed(self, mock_logger_error):
+        with mock.patch.dict(os.environ,
+                             {},
+                             clear=True):
+            self.assertEqual(functest_utils.get_scenario(),
+                             "Unknown_scenario")
+            mock_logger_error.assert_called_once_with("Impossible to retrieve"
+                                                      " the scenario")
+
+    def test_get_scenario_default(self):
+        with mock.patch.dict(os.environ,
+                             {'DEPLOY_SCENARIO': 'test_scenario'},
+                             clear=True):
+            self.assertEqual(functest_utils.get_scenario(),
+                             self.scenario)
+
+    @mock.patch('functest.utils.functest_utils.get_build_tag')
+    def test_get_version_default(self, mock_get_build_tag):
+        mock_get_build_tag.return_value = self.build_tag
+        self.assertEqual(functest_utils.get_version(), self.version)
+
+    @mock.patch('functest.utils.functest_utils.get_build_tag')
+    def test_get_version_unknown(self, mock_get_build_tag):
+        mock_get_build_tag.return_value = "unknown_build_tag"
+        self.assertEqual(functest_utils.get_version(), "unknown")
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_get_pod_name_failed(self, mock_logger_error):
+        with mock.patch.dict(os.environ,
+                             {},
+                             clear=True):
+            self.assertEqual(functest_utils.get_pod_name(),
+                             "unknown-pod")
+            mock_logger_error.assert_called_once_with("Unable to retrieve "
+                                                      "the POD name from "
+                                                      "environment. Using "
+                                                      "pod name 'unknown-pod'")
+
+    def test_get_pod_name_default(self):
+        with mock.patch.dict(os.environ,
+                             {'NODE_NAME': 'test_node_name'},
+                             clear=True):
+            self.assertEqual(functest_utils.get_pod_name(),
+                             self.node_name)
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_get_build_tag_failed(self, mock_logger_error):
+        with mock.patch.dict(os.environ,
+                             {},
+                             clear=True):
+            self.assertEqual(functest_utils.get_build_tag(),
+                             "unknown_build_tag")
+            mock_logger_error.assert_called_once_with("Impossible to retrieve"
+                                                      " the build tag")
+
+    def test_get_build_tag_default(self):
+        with mock.patch.dict(os.environ,
+                             {'BUILD_TAG': self.build_tag},
+                             clear=True):
+            self.assertEqual(functest_utils.get_build_tag(),
+                             self.build_tag)
+
+    @mock.patch('functest.utils.functest_utils.get_functest_config')
+    def test_get_db_url(self, mock_get_functest_config):
+        mock_get_functest_config.return_value = self.db_url
+        self.assertEqual(functest_utils.get_db_url(), self.db_url)
+        mock_get_functest_config.assert_called_once_with('results.test_db_url')
+
+    @mock.patch('functest.utils.functest_utils.logger.info')
+    def test_logger_test_results(self, mock_logger_info):
+        with mock.patch('functest.utils.functest_utils.get_pod_name',
+                        return_value=self.node_name), \
+                mock.patch('functest.utils.functest_utils.get_scenario',
+                           return_value=self.scenario), \
+                mock.patch('functest.utils.functest_utils.get_version',
+                           return_value=self.version), \
+                mock.patch('functest.utils.functest_utils.get_build_tag',
+                           return_value=self.build_tag), \
+                mock.patch('functest.utils.functest_utils.get_db_url',
+                           return_value=self.db_url):
+            functest_utils.logger_test_results(self.project, self.case_name,
+                                               self.status, self.details)
+            mock_logger_info.assert_called_once_with(
+                "\n"
+                "****************************************\n"
+                "\t %(p)s/%(n)s results \n\n"
+                "****************************************\n"
+                "DB:\t%(db)s\n"
+                "pod:\t%(pod)s\n"
+                "version:\t%(v)s\n"
+                "scenario:\t%(s)s\n"
+                "status:\t%(c)s\n"
+                "build tag:\t%(b)s\n"
+                "details:\t%(d)s\n"
+                % {'p': self.project,
+                    'n': self.case_name,
+                    'db': self.db_url,
+                    'pod': self.node_name,
+                    'v': self.version,
+                    's': self.scenario,
+                    'c': self.status,
+                    'b': self.build_tag,
+                    'd': self.details})
+
+    def _get_env_dict(self, var):
+        dic = {'INSTALLER_TYPE': self.installer,
+               'DEPLOY_SCENARIO': self.scenario,
+               'NODE_NAME': self.node_name,
+               'BUILD_TAG': self.build_tag}
+        dic.pop(var, None)
+        return dic
+
+    def _test_push_results_to_db_missing_env(self, env_var):
+        dic = self._get_env_dict(env_var)
+        with mock.patch('functest.utils.functest_utils.get_db_url',
+                        return_value=self.db_url), \
+                mock.patch.dict(os.environ,
+                                dic,
+                                clear=True), \
+                mock.patch('functest.utils.functest_utils.logger.error') \
+                as mock_logger_error:
+            functest_utils.push_results_to_db(self.project, self.case_name,
+                                              self.start_date, self.stop_date,
+                                              self.criteria, self.details)
+            mock_logger_error.assert_called_once_with("Please set env var: " +
+                                                      str("\'" + env_var +
+                                                          "\'"))
+
+    def test_push_results_to_db_missing_installer(self):
+        self._test_push_results_to_db_missing_env('INSTALLER_TYPE')
+
+    def test_push_results_to_db_missing_scenario(self):
+        self._test_push_results_to_db_missing_env('DEPLOY_SCENARIO')
+
+    def test_push_results_to_db_missing_nodename(self):
+        self._test_push_results_to_db_missing_env('NODE_NAME')
+
+    def test_push_results_to_db_missing_buildtag(self):
+        self._test_push_results_to_db_missing_env('BUILD_TAG')
+
+    def test_push_results_to_db_incorrect_buildtag(self):
+        dic = self._get_env_dict(None)
+        dic['BUILD_TAG'] = 'incorrect_build_tag'
+        with mock.patch('functest.utils.functest_utils.get_db_url',
+                        return_value=self.db_url), \
+                mock.patch.dict(os.environ,
+                                dic,
+                                clear=True), \
+                mock.patch('functest.utils.functest_utils.logger.error') \
+                as mock_logger_error:
+            self.assertFalse(functest_utils.
+                             push_results_to_db(self.project, self.case_name,
+                                                self.start_date,
+                                                self.stop_date,
+                                                self.criteria, self.details))
+            mock_logger_error.assert_called_once_with("Please fix BUILD_TAG"
+                                                      " env var: incorrect_"
+                                                      "build_tag")
+
+    def test_push_results_to_db_request_post_failed(self):
+        dic = self._get_env_dict(None)
+        with mock.patch('functest.utils.functest_utils.get_db_url',
+                        return_value=self.db_url), \
+                mock.patch.dict(os.environ,
+                                dic,
+                                clear=True), \
+                mock.patch('functest.utils.functest_utils.logger.error') \
+                as mock_logger_error, \
+                mock.patch('functest.utils.functest_utils.requests.post',
+                           side_effect=requests.RequestException):
+            self.assertFalse(functest_utils.
+                             push_results_to_db(self.project, self.case_name,
+                                                self.start_date,
+                                                self.stop_date,
+                                                self.criteria, self.details))
+            mock_logger_error.assert_called_once_with(test_utils.
+                                                      RegexMatch("Pushing "
+                                                                 "Result to"
+                                                                 " DB"
+                                                                 "(\S+\s*) "
+                                                                 "failed:"))
+
+    def test_push_results_to_db_request_post_exception(self):
+        dic = self._get_env_dict(None)
+        with mock.patch('functest.utils.functest_utils.get_db_url',
+                        return_value=self.db_url), \
+                mock.patch.dict(os.environ,
+                                dic,
+                                clear=True), \
+                mock.patch('functest.utils.functest_utils.logger.error') \
+                as mock_logger_error, \
+                mock.patch('functest.utils.functest_utils.requests.post',
+                           side_effect=Exception):
+            self.assertFalse(functest_utils.
+                             push_results_to_db(self.project, self.case_name,
+                                                self.start_date,
+                                                self.stop_date,
+                                                self.criteria, self.details))
+            self.assertTrue(mock_logger_error.called)
+
+    def test_push_results_to_db_default(self):
+        dic = self._get_env_dict(None)
+        with mock.patch('functest.utils.functest_utils.get_db_url',
+                        return_value=self.db_url), \
+                mock.patch.dict(os.environ,
+                                dic,
+                                clear=True), \
+                mock.patch('functest.utils.functest_utils.requests.post'):
+            self.assertTrue(functest_utils.
+                            push_results_to_db(self.project, self.case_name,
+                                               self.start_date,
+                                               self.stop_date,
+                                               self.criteria, self.details))
+    readline = 0
+    test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
+
+    @staticmethod
+    def readline_side():
+        if FunctestUtilsTesting.readline == \
+                len(FunctestUtilsTesting.test_ip) - 1:
+            return False
+        FunctestUtilsTesting.readline += 1
+        return FunctestUtilsTesting.test_ip[FunctestUtilsTesting.readline]
+
+    # TODO: get_resolvconf_ns
+    @mock.patch('functest.utils.functest_utils.dns.resolver.Resolver')
+    def test_get_resolvconf_ns_default(self, mock_dns_resolve):
+        attrs = {'query.return_value': ["test"]}
+        mock_dns_resolve.configure_mock(**attrs)
+
+        m = mock.Mock()
+        attrs = {'readline.side_effect': self.readline_side}
+        m.configure_mock(**attrs)
+
+        with mock.patch("__builtin__.open") as mo:
+            mo.return_value = m
+            self.assertEqual(functest_utils.get_resolvconf_ns(),
+                             self.test_ip[1:])
+
+    def _get_environ(self, var):
+        if var == 'INSTALLER_TYPE':
+            return self.installer
+        elif var == 'DEPLOY_SCENARIO':
+            return self.scenario
+        return var
+
+    def test_get_ci_envvars_default(self):
+        with mock.patch('os.environ.get',
+                        side_effect=self._get_environ):
+            dic = {"installer": self.installer,
+                   "scenario": self.scenario}
+            self.assertDictEqual(functest_utils.get_ci_envvars(), dic)
+
+    def cmd_readline(self):
+        return 'test_value\n'
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    @mock.patch('functest.utils.functest_utils.logger.info')
+    def test_execute_command_args_present_with_error(self, mock_logger_info,
+                                                     mock_logger_error):
+        with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
+                as mock_subproc_open, \
+                mock.patch('__builtin__.open', mock.mock_open()) as mopen:
+
+            FunctestUtilsTesting.readline = 0
+
+            mock_obj = mock.Mock()
+            attrs = {'readline.side_effect': self.cmd_readline()}
+            mock_obj.configure_mock(**attrs)
+
+            mock_obj2 = mock.Mock()
+            attrs = {'stdout': mock_obj, 'wait.return_value': 1}
+            mock_obj2.configure_mock(**attrs)
+
+            mock_subproc_open.return_value = mock_obj2
+
+            resp = functest_utils.execute_command(self.cmd, info=True,
+                                                  error_msg=self.error_msg,
+                                                  verbose=True,
+                                                  output_file=self.output_file)
+            self.assertEqual(resp, 1)
+            msg_exec = ("Executing command: '%s'" % self.cmd)
+            mock_logger_info.assert_called_once_with(msg_exec)
+            mopen.assert_called_once_with(self.output_file, "w")
+            mock_logger_error.assert_called_once_with(self.error_msg)
+
+    @mock.patch('functest.utils.functest_utils.logger.info')
+    def test_execute_command_args_present_with_success(self, mock_logger_info,
+                                                       ):
+        with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
+                as mock_subproc_open, \
+                mock.patch('__builtin__.open', mock.mock_open()) as mopen:
+
+            FunctestUtilsTesting.readline = 0
+
+            mock_obj = mock.Mock()
+            attrs = {'readline.side_effect': self.cmd_readline()}
+            mock_obj.configure_mock(**attrs)
+
+            mock_obj2 = mock.Mock()
+            attrs = {'stdout': mock_obj, 'wait.return_value': 0}
+            mock_obj2.configure_mock(**attrs)
+
+            mock_subproc_open.return_value = mock_obj2
+
+            resp = functest_utils.execute_command(self.cmd, info=True,
+                                                  error_msg=self.error_msg,
+                                                  verbose=True,
+                                                  output_file=self.output_file)
+            self.assertEqual(resp, 0)
+            msg_exec = ("Executing command: '%s'" % self.cmd)
+            mock_logger_info.assert_called_once_with(msg_exec)
+            mopen.assert_called_once_with(self.output_file, "w")
+
+    @mock.patch('functest.utils.functest_utils.logger.info')
+    def test_execute_command_args_missing_with_success(self, mock_logger_info,
+                                                       ):
+        with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
+                as mock_subproc_open:
+
+            FunctestUtilsTesting.readline = 2
+
+            mock_obj = mock.Mock()
+            attrs = {'readline.side_effect': self.cmd_readline()}
+            mock_obj.configure_mock(**attrs)
+
+            mock_obj2 = mock.Mock()
+            attrs = {'stdout': mock_obj, 'wait.return_value': 0}
+            mock_obj2.configure_mock(**attrs)
+
+            mock_subproc_open.return_value = mock_obj2
+
+            resp = functest_utils.execute_command(self.cmd, info=False,
+                                                  error_msg="",
+                                                  verbose=False,
+                                                  output_file=None)
+            self.assertEqual(resp, 0)
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_execute_command_args_missing_with_error(self, mock_logger_error,
+                                                     ):
+        with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
+                as mock_subproc_open:
+
+            FunctestUtilsTesting.readline = 2
+            mock_obj = mock.Mock()
+            attrs = {'readline.side_effect': self.cmd_readline()}
+            mock_obj.configure_mock(**attrs)
+
+            mock_obj2 = mock.Mock()
+            attrs = {'stdout': mock_obj, 'wait.return_value': 1}
+            mock_obj2.configure_mock(**attrs)
+
+            mock_subproc_open.return_value = mock_obj2
+
+            resp = functest_utils.execute_command(self.cmd, info=False,
+                                                  error_msg="",
+                                                  verbose=False,
+                                                  output_file=None)
+            self.assertEqual(resp, 1)
+
+    def _get_functest_config(self, var):
+        return var
+
+    @mock.patch('functest.utils.functest_utils.logger.error')
+    def test_get_dict_by_test(self, mock_logger_error):
+        with mock.patch('__builtin__.open', mock.mock_open()), \
+                mock.patch('functest.utils.functest_utils.yaml.safe_load') \
+                as mock_yaml, \
+                mock.patch('functest.utils.functest_utils.get_testcases_'
+                           'file_dir'):
+            mock_obj = mock.Mock()
+            attrs = {'get.return_value': [{'testcases': [self.testcase_dict]}]}
+            mock_obj.configure_mock(**attrs)
+
+            mock_yaml.return_value = mock_obj
+
+            self.assertDictEqual(functest_utils.
+                                 get_dict_by_test(self.testname),
+                                 self.testcase_dict)
+
+    @mock.patch('functest.utils.functest_utils.get_dict_by_test')
+    def test_get_criteria_by_test_default(self, mock_get_dict_by_test):
+        mock_get_dict_by_test.return_value = self.testcase_dict
+        self.assertEqual(functest_utils.get_criteria_by_test(self.testname),
+                         self.criteria)
+
+    @mock.patch('functest.utils.functest_utils.get_dict_by_test')
+    def test_get_criteria_by_test_failed(self, mock_get_dict_by_test):
+        mock_get_dict_by_test.return_value = None
+        self.assertIsNone(functest_utils.get_criteria_by_test(self.testname))
+
+    def test_get_parameter_from_yaml_failed(self):
+        self.file_yaml['general'] = None
+        with mock.patch('__builtin__.open', mock.mock_open()), \
+                mock.patch('functest.utils.functest_utils.yaml.safe_load') \
+                as mock_yaml, \
+                self.assertRaises(ValueError) as excep:
+            mock_yaml.return_value = self.file_yaml
+            functest_utils.get_parameter_from_yaml(self.parameter,
+                                                   self.test_file)
+            self.assertTrue(("The parameter %s is not"
+                             " defined in config_functest.yaml" %
+                             self.parameter) in excep.exception)
+
+    def test_get_parameter_from_yaml_default(self):
+        with mock.patch('__builtin__.open', mock.mock_open()), \
+                mock.patch('functest.utils.functest_utils.yaml.safe_load') \
+                as mock_yaml:
+            mock_yaml.return_value = self.file_yaml
+            self.assertEqual(functest_utils.
+                             get_parameter_from_yaml(self.parameter,
+                                                     self.test_file),
+                             'test_image_name')
+
+    @mock.patch('functest.utils.functest_utils.get_parameter_from_yaml')
+    def test_get_functest_config_default(self, mock_get_parameter_from_yaml):
+        with mock.patch.dict(os.environ,
+                             {'CONFIG_FUNCTEST_YAML': self.config_yaml}):
+            functest_utils.get_functest_config(self.parameter)
+            mock_get_parameter_from_yaml. \
+                assert_called_once_with(self.parameter,
+                                        self.config_yaml)
+
+    def test_check_success_rate_default(self):
+        with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \
+                as mock_criteria:
+            mock_criteria.return_value = self.criteria
+            resp = functest_utils.check_success_rate(self.case_name,
+                                                     self.success_rate)
+            self.assertEqual(resp, 'PASS')
+
+    def test_check_success_rate_failed(self):
+        with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \
+                as mock_criteria:
+            mock_criteria.return_value = self.criteria
+            resp = functest_utils.check_success_rate(self.case_name,
+                                                     3.0)
+            self.assertEqual(resp, 'FAIL')
+
+    # TODO: merge_dicts
+
+    def test_get_testcases_file_dir(self):
+        resp = functest_utils.get_testcases_file_dir()
+        self.assertEqual(resp,
+                         "/home/opnfv/repos/functest/"
+                         "functest/ci/testcases.yaml")
+
+    def test_get_functest_yaml(self):
+        with mock.patch('__builtin__.open', mock.mock_open()), \
+                mock.patch('functest.utils.functest_utils.yaml.safe_load') \
+                as mock_yaml:
+            mock_yaml.return_value = self.file_yaml
+            resp = functest_utils.get_functest_yaml()
+            self.assertEqual(resp, self.file_yaml)
+
+    @mock.patch('functest.utils.functest_utils.logger.info')
+    def test_print_separator(self, mock_logger_info):
+        functest_utils.print_separator()
+        mock_logger_info.assert_called_once_with("======================="
+                                                 "=======================")
+
+
+if __name__ == "__main__":
+    unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_utils.py b/functest/tests/unit/utils/test_utils.py
deleted file mode 100644 (file)
index 8b6c5e1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2016 Orange and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-import logging
-import mock
-import unittest
-import urllib2
-
-from functest.utils import functest_utils
-
-
-class FunctestUtilsTesting(unittest.TestCase):
-
-    logging.disable(logging.CRITICAL)
-
-    def setUp(self):
-        self.url = 'http://www.opnfv.org/'
-        self.timeout = 5
-
-    @mock.patch('urllib2.urlopen',
-                side_effect=urllib2.URLError('no host given'))
-    def test_check_internet_connectivity_failed(self, mock_method):
-        self.assertFalse(functest_utils.check_internet_connectivity())
-        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
-
-    @mock.patch('urllib2.urlopen')
-    def test_check_internet_connectivity_default(self, mock_method):
-        self.assertTrue(functest_utils.check_internet_connectivity())
-        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
-
-    @mock.patch('urllib2.urlopen')
-    def test_check_internet_connectivity_debian(self, mock_method):
-        self.url = "https://www.debian.org/"
-        self.assertTrue(functest_utils.check_internet_connectivity(self.url))
-        mock_method.assert_called_once_with(self.url, timeout=self.timeout)
-
-
-if __name__ == "__main__":
-    unittest.main(verbosity=2)
diff --git a/functest/utils/config.py b/functest/utils/config.py
new file mode 100644 (file)
index 0000000..84166c1
--- /dev/null
@@ -0,0 +1,35 @@
+import os
+
+import yaml
+
+
+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:
+                self.functest_yaml = yaml.safe_load(f)
+                self._parse(None, self.functest_yaml)
+        except:
+            raise Exception('Parse {} failed'.format(self.config_functest))
+        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):
+                self.__setattr__(attr_further, param_v)
+            else:
+                self._parse(attr_further, param_v)
+
+    def _get_attr_further(self, attr_now, next):
+        return attr_now if next == 'general' else (
+            '{}_{}'.format(attr_now, next) if attr_now else next)
+
+    def _set_others(self):
+        self.env_active = os.path.join(self.dir_functest_conf, "env_active")
+
+
+CONF = Config()
diff --git a/functest/utils/constants.py b/functest/utils/constants.py
new file mode 100644 (file)
index 0000000..2e8eb3f
--- /dev/null
@@ -0,0 +1,20 @@
+import config
+import env
+
+
+class Constants(object):
+    def __init__(self):
+        for attr_n, attr_v in config.CONF.__dict__.iteritems():
+            self.__setattr__(attr_n, attr_v)
+        for env_n, env_v in env.ENV.__dict__.iteritems():
+            self.__setattr__(env_n, env_v)
+
+
+CONST = Constants()
+
+if __name__ == '__main__':
+    print CONST.__dict__
+    print CONST.NODE_NAME
+    print CONST.vIMS_clearwater_blueprint_url
+    print CONST.vIMS_clearwater_blueprint_file_name
+    print CONST.vIMS_clearwater_blueprint_name
diff --git a/functest/utils/env.py b/functest/utils/env.py
new file mode 100644 (file)
index 0000000..fa5245f
--- /dev/null
@@ -0,0 +1,41 @@
+import os
+import re
+
+default_envs = {
+    'NODE_NAME': 'unknown_pod',
+    'CI_DEBUG': 'true',
+    'DEPLOY_SCENARIO': 'os-nosdn-nofeature-noha',
+    'DEPLOY_TYPE': 'virt',
+    'INSTALLER_TYPE': None,
+    'INSTALLER_IP': None,
+    'BUILD_TAG': None,
+    'OS_ENDPOINT_TYPE': None,
+    'OS_AUTH_URL': None
+}
+
+
+class Environment(object):
+
+    def __init__(self):
+        for k, v in os.environ.iteritems():
+            self.__setattr__(k, v)
+        for k, v in default_envs.iteritems():
+            if k not in os.environ:
+                self.__setattr__(k, v)
+        self._set_ci_run()
+        self._set_ci_loop()
+
+    def _set_ci_run(self):
+        if self.BUILD_TAG:
+            self.IS_CI_RUN = True
+        else:
+            self.IS_CI_RUN = False
+
+    def _set_ci_loop(self):
+        if self.BUILD_TAG and re.search("daily", self.BUILD_TAG):
+            self.CI_LOOP = "daily"
+        else:
+            self.CI_LOOP = "weekly"
+
+
+ENV = Environment()
index 2664ace..ac9d77c 100644 (file)
@@ -7,8 +7,9 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 import os
-import functest.utils.functest_utils as ft_utils
+
 import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
 
 logger = ft_logger.Logger("functest_constants").getLogger()
 
@@ -60,25 +61,25 @@ def get_value(functest_config_key, env_variable):
             return constant
 
 
-HOME = get_value('general.directories.dir_home', 'HOME')
-REPOS_DIR = get_value('general.directories.dir_repos', 'REPOS_DIR')
-FUNCTEST_BASE_DIR = get_value('general.directories.dir_functest',
+HOME = get_value('general.dir.home', 'HOME')
+REPOS_DIR = get_value('general.dir.repos', 'REPOS_DIR')
+FUNCTEST_BASE_DIR = get_value('general.dir.functest',
                               'FUNCTEST_BASE_DIR')
-FUNCTEST_REPO_DIR = get_value('general.directories.dir_repo_functest',
+FUNCTEST_REPO_DIR = get_value('general.dir.repo_functest',
                               'FUNCTEST_REPO_DIR')
-FUNCTEST_TEST_DIR = get_value('general.directories.dir_functest_test',
+FUNCTEST_TEST_DIR = get_value('general.dir.functest_test',
                               'FUNCTEST_TEST_DIR')
-FUNCTEST_CONF_DIR = get_value('general.directories.dir_functest_conf',
+FUNCTEST_CONF_DIR = get_value('general.dir.functest_conf',
                               'FUNCTEST_CONF_DIR')
-FUNCTEST_DATA_DIR = get_value('general.directories.dir_functest_data',
+FUNCTEST_DATA_DIR = get_value('general.dir.functest_data',
                               'FUNCTEST_DATA_DIR')
-FUNCTEST_RESULTS_DIR = get_value('general.directories.dir_results',
+FUNCTEST_RESULTS_DIR = get_value('general.dir.results',
                                  'FUNCTEST_RESULTS_DIR')
 FUNCTEST_TESTCASES_YAML = get_value('general.functest.testcases_yaml',
                                     'FUNCTEST_TESTCASES_YAML')
 RALLY_DEPLOYMENT_NAME = get_value('rally.deployment_name',
                                   'RALLY_DEPLOYMENT_NAME')
-TEMPEST_REPO_DIR = get_value('general.directories.dir_repo_tempest',
+TEMPEST_REPO_DIR = get_value('general.dir.repo_tempest',
                              'TEMPEST_REPO_DIR')
 
 ENV_FILE = os.path.join(FUNCTEST_CONF_DIR, "env_active")
@@ -87,22 +88,22 @@ OPENSTACK_CREDS = get_value('general.openstack.creds', 'creds')
 OPENSTACK_SNAPSHOT_FILE = get_value('general.openstack.snapshot_file',
                                     'OPENSTACK_SNAPSHOT_FILE')
 
-DOMINO_REPO_DIR = get_value('general.directories.dir_repo_domino',
+DOMINO_REPO_DIR = get_value('general.dir.repo_domino',
                             'DOMINO_REPO_DIR')
-SDNVPN_REPO_DIR = get_value('general.directories.dir_repo_sdnvpn',
+SDNVPN_REPO_DIR = get_value('general.dir.repo_sdnvpn',
                             'SDNVPN_REPO_DIR')
-SFC_REPO_DIR = get_value('general.directories.dir_repo_sfc',
+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.directories.dir_onos_sfc',
+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.directories.dir_rally',
+RALLY_RELATIVE_PATH = get_value('general.dir.rally',
                                 'RALLY_RELATIVE_PATH')
 RALLY_PRIVATE_NET_NAME = get_value('rally.network_name',
                                    'RALLY_PRIVATE_NET_NAME')
@@ -111,7 +112,7 @@ RALLY_PRIVATE_SUBNET_NAME = get_value('rally.subnet_name',
 RALLY_PRIVATE_SUBNET_CIDR = get_value('rally.subnet_cidr',
                                       'RALLY_PRIVATE_SUBNET_CIDR')
 RALLY_ROUTER_NAME = get_value('rally.router_name', 'RALLY_ROUTER_NAME')
-RALLY_INSTALLATION_DIR = get_value('general.directories.dir_rally_inst',
+RALLY_INSTALLATION_DIR = get_value('general.dir.rally_inst',
                                    'RALLY_INSTALLATION_DIR')
 GLANCE_IMAGE_NAME = get_value('general.openstack.image_name',
                               'GLANCE_IMAGE_NAME')
@@ -149,24 +150,24 @@ TEMPEST_USE_CUSTOM_IMAGES = get_value('tempest.use_custom_images',
                                       'TEMPEST_USE_CUSTOM_IMAGES')
 TEMPEST_USE_CUSTOM_FLAVORS = get_value('tempest.use_custom_flavors',
                                        'TEMPEST_USE_CUSTOM_FLAVORS')
-TEMPEST_TEST_LIST_DIR = get_value('general.directories.dir_tempest_cases',
+TEMPEST_TEST_LIST_DIR = get_value('general.dir.tempest_cases',
                                   'TEMPEST_TEST_LIST_DIR')
 NAME_VM_1 = get_value('vping.vm_name_1', 'NAME_VM_1')
 NAME_VM_2 = get_value('vping.vm_name_2', 'NAME_VM_2')
 PING_TIMEOUT = get_value('vping.ping_timeout', 'PING_TIMEOUT')
 VPING__IMAGE_NAME = get_value('vping.image_name', 'VPING__IMAGE_NAME')
 VPING_VM_FLAVOR = get_value('vping.vm_flavor', 'VPING_VM_FLAVOR')
-VPING_PRIVATE_NET_NAME = get_value('vping.vping_private_net_name',
+VPING_PRIVATE_NET_NAME = get_value('vping.private_net_name',
                                    'VPING_PRIVATE_NET_NAME')
-VPING_PRIVATE_SUBNET_NAME = get_value('vping.vping_private_subnet_name',
+VPING_PRIVATE_SUBNET_NAME = get_value('vping.private_subnet_name',
                                       'VPING_PRIVATE_SUBNET_NAME')
-VPING_PRIVATE_SUBNET_CIDR = get_value('vping.vping_private_subnet_cidr',
+VPING_PRIVATE_SUBNET_CIDR = get_value('vping.private_subnet_cidr',
                                       'VPING_PRIVATE_SUBNET_CIDR')
-VPING_ROUTER_NAME = get_value('vping.vping_router_name',
+VPING_ROUTER_NAME = get_value('vping.router_name',
                               'VPING_ROUTER_NAME')
-VPING_SECGROUP_NAME = get_value('vping.vping_sg_name',
+VPING_SECGROUP_NAME = get_value('vping.sg_name',
                                 'VPING_SECGROUP_NAME')
-VPING_SECGROUP_DESCR = get_value('vping.vping_sg_descr',
+VPING_SECGROUP_DESCR = get_value('vping.sg_desc',
                                  'VPING_SECGROUP_DESCR')
 ONOSBENCH_USERNAME = get_value('ONOS.general.onosbench_username',
                                'ONOSBENCH_USERNAME')
@@ -192,7 +193,7 @@ ONOS_INSTALLER_MASTER_USERNAME = get_value(
 ONOS_INSTALLER_MASTER_PASSWORD = get_value(
     'ONOS.environment.installer_master_password',
     'ONOS_INSTALLER_MASTER_PASSWORD')
-PROMISE_REPO_DIR = get_value('general.directories.dir_repo_promise',
+PROMISE_REPO_DIR = get_value('general.dir.dir_repo_promise',
                              'PROMISE_REPO_DIR')
 PROMISE_TENANT_NAME = get_value('promise.tenant_name',
                                 'PROMISE_TENANT_NAME')
@@ -217,32 +218,32 @@ PROMISE_SUBNET_CIDR = get_value('promise.subnet_cidr',
                                 'PROMISE_SUBNET_CIDR')
 PROMISE_ROUTER_NAME = get_value('promise.router_name',
                                 'PROMISE_ROUTER_NAME')
-DOCTOR_REPO_DIR = get_value('general.directories.dir_repo_doctor',
+DOCTOR_REPO_DIR = get_value('general.dir.dir_repo_doctor',
                             'DOCTOR_REPO_DIR')
-COPPER_REPO_DIR = get_value('general.directories.dir_repo_copper',
+COPPER_REPO_DIR = get_value('general.dir.repo_copper',
                             'COPPER_REPO_DIR')
-EXAMPLE_INSTANCE_NAME = get_value('example.example_vm_name',
+EXAMPLE_INSTANCE_NAME = get_value('example.vm_name',
                                   'EXAMPLE_INSTANCE_NAME')
-EXAMPLE_FLAVOR = get_value('example.example_flavor', 'EXAMPLE_FLAVOR')
-EXAMPLE_IMAGE_NAME = get_value('example.example_image_name',
+EXAMPLE_FLAVOR = get_value('example.flavor', 'EXAMPLE_FLAVOR')
+EXAMPLE_IMAGE_NAME = get_value('example.image_name',
                                'EXAMPLE_IMAGE_NAME')
-EXAMPLE_PRIVATE_NET_NAME = get_value('example.example_private_net_name',
+EXAMPLE_PRIVATE_NET_NAME = get_value('example.private_net_name',
                                      'EXAMPLE_PRIVATE_NET_NAME')
 EXAMPLE_PRIVATE_SUBNET_NAME = get_value(
-    'example.example_private_subnet_name',
+    'example.private_subnet_name',
     'EXAMPLE_PRIVATE_SUBNET_NAME')
 EXAMPLE_PRIVATE_SUBNET_CIDR = get_value(
-    'example.example_private_subnet_cidr',
+    'example.private_subnet_cidr',
     'EXAMPLE_PRIVATE_SUBNET_CIDR')
-EXAMPLE_ROUTER_NAME = get_value('example.example_router_name',
+EXAMPLE_ROUTER_NAME = get_value('example.router_name',
                                 'EXAMPLE_ROUTER_NAME')
-EXAMPLE_SECGROUP_NAME = get_value('example.example_sg_name',
+EXAMPLE_SECGROUP_NAME = get_value('example.sg_name',
                                   'EXAMPLE_SECGROUP_NAME')
-EXAMPLE_SECGROUP_DESCR = get_value('example.example_sg_descr',
+EXAMPLE_SECGROUP_DESCR = get_value('example.sg_desc',
                                    'EXAMPLE_SECGROUP_DESCR')
-VIMS_DATA_DIR = get_value('general.directories.dir_vIMS_data',
+VIMS_DATA_DIR = get_value('general.dir.dir_vIMS_data',
                           'VIMS_DATA_DIR')
-VIMS_TEST_DIR = get_value('general.directories.dir_repo_vims_test',
+VIMS_TEST_DIR = get_value('general.dir.dir_repo_vims_test',
                           'VIMS_TEST_DIR')
 VIMS_TENANT_NAME = get_value('vIMS.general.tenant_name',
                              'VIMS_TENANT_NAME')
@@ -260,5 +261,5 @@ CW_DEPLOYMENT_NAME = get_value('vIMS.clearwater.deployment-name',
 CW_INPUTS = get_value('vIMS.clearwater.inputs', 'CW_INPUTS')
 CW_REQUIERMENTS = get_value('vIMS.clearwater.requierments',
                             'CW_REQUIERMENTS')
-PARSER_REPO_DIR = get_value('general.directories.dir_repo_parser',
+PARSER_REPO_DIR = get_value('general.dir.repo_parser',
                             'PARSER_REPO_DIR')
index b1e4d3c..1879e69 100644 (file)
@@ -7,12 +7,14 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 #
+import functools
 import json
 import os
 import re
 import shutil
 import subprocess
 import sys
+import time
 import urllib2
 from datetime import datetime as dt
 
@@ -21,9 +23,6 @@ import requests
 import yaml
 from git import Repo
 
-import time
-import functools
-
 import functest.utils.functest_logger as ft_logger
 
 logger = ft_logger.Logger("functest_utils").getLogger()
@@ -321,26 +320,6 @@ def execute_command(cmd, info=False, error_msg="",
     return returncode
 
 
-def get_deployment_dir():
-    """
-    Returns current Rally deployment directory
-    """
-    deployment_name = get_functest_config('rally.deployment_name')
-    rally_dir = get_functest_config('general.directories.dir_rally_inst')
-    cmd = ("rally deployment list | awk '/" + deployment_name +
-           "/ {print $2}'")
-    p = subprocess.Popen(cmd, shell=True,
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.STDOUT)
-    deployment_uuid = p.stdout.readline().rstrip()
-    if deployment_uuid == "":
-        logger.error("Rally deployment not found.")
-        exit(-1)
-    deployment_dir = (rally_dir + "/tempest/for-deployment-" +
-                      deployment_uuid)
-    return deployment_dir
-
-
 def get_dict_by_test(testname):
     with open(get_testcases_file_dir()) as f:
         testcases_yaml = yaml.safe_load(f)
index 949eee9..15a8f33 100755 (executable)
@@ -9,6 +9,8 @@
 #       - Neutron networks, subnets and ports
 #       - Routers
 #       - Users and tenants
+#       - Tacker VNFDs and VNFs
+#       - Tacker SFCs and SFC classifiers
 #
 # Author:
 #    jose.lausuch@ericsson.com
 #
 
 import time
+
+import yaml
+
 import functest.utils.functest_logger as ft_logger
 import functest.utils.openstack_utils as os_utils
-import yaml
-import functest.utils.functest_constants as ft_constants
+from functest.utils.constants import CONST
 
 logger = ft_logger.Logger("openstack_clean").getLogger()
 
-OS_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE
+OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file
 
 
 def separator():
@@ -105,7 +109,7 @@ def remove_volumes(cinder_client, default_volumes):
 
     for volume in volumes:
         volume_id = getattr(volume, 'id')
-        volume_name = getattr(volume, 'display_name')
+        volume_name = getattr(volume, 'name')
         logger.debug("'%s', ID=%s " % (volume_name, volume_id))
         if (volume_id not in default_volumes and
                 volume_name not in default_volumes.values()):
index 4be1af4..e64030f 100755 (executable)
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 
+import yaml
+
 import functest.utils.functest_logger as ft_logger
 import functest.utils.openstack_utils as os_utils
-import yaml
-import functest.utils.functest_constants as ft_constants
+from functest.utils.constants import CONST
 
 logger = ft_logger.Logger("openstack_snapshot").getLogger()
 
 
-OS_SNAPSHOT_FILE = ft_constants.OPENSTACK_SNAPSHOT_FILE
+OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file
 
 
 def separator():
@@ -62,7 +63,7 @@ def get_volumes(cinder_client):
     volumes = os_utils.get_volumes(cinder_client)
     if volumes is not None:
         for volume in volumes:
-            dic_volumes.update({volume.id: volume.display_name})
+            dic_volumes.update({volume.id: volume.name})
     return {'volumes': dic_volumes}
 
 
old mode 100644 (file)
new mode 100755 (executable)
index 6ab0566..f17b421
@@ -21,7 +21,7 @@ logger = ft_logger.Logger("tacker_utils").getLogger()
 
 
 def get_tacker_client():
-    creds_tacker = os_utils.get_credentials('tacker')
+    creds_tacker = os_utils.get_credentials()
     return tackerclient.Client(**creds_tacker)
 
 
index 15dc87c..64f1850 100755 (executable)
@@ -14,16 +14,21 @@ import subprocess
 import sys
 import time
 
+from keystoneauth1 import loading
+from keystoneauth1 import session
 from cinderclient import client as cinderclient
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
 from glanceclient import client as glanceclient
-from keystoneclient.v2_0 import client as keystoneclient
-from neutronclient.v2_0 import client as neutronclient
 from novaclient import client as novaclient
+from keystoneclient import client as keystoneclient
+from neutronclient.neutron import client as neutronclient
+
+import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
 
 logger = ft_logger.Logger("openstack_utils").getLogger()
 
+DEFAULT_API_VERSION = '2'
+
 
 # *********************************************
 #   CREDENTIALS
@@ -37,88 +42,72 @@ class MissingEnvVar(Exception):
         return str.format("Please set the mandatory env var: {}", self.var)
 
 
+def is_keystone_v3():
+    keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
+    if (keystone_api_version is None or
+            keystone_api_version == '2'):
+        return False
+    else:
+        return True
+
+
+def get_rc_env_vars():
+    env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD']
+    if is_keystone_v3():
+        env_vars.extend(['OS_PROJECT_NAME',
+                         'OS_USER_DOMAIN_NAME',
+                         'OS_PROJECT_DOMAIN_NAME'])
+    else:
+        env_vars.extend(['OS_TENANT_NAME'])
+    return env_vars
+
+
 def check_credentials():
     """
     Check if the OpenStack credentials (openrc) are sourced
     """
-    env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME']
+    env_vars = get_rc_env_vars()
     return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
 
 
-def get_credentials(service):
-    """Returns a creds dictionary filled with the following keys:
-    * username
-    * password/api_key (depending on the service)
-    * tenant_name/project_id (depending on the service)
-    * auth_url
-    :param service: a string indicating the name of the service
-                    requesting the credentials.
+def get_env_cred_dict():
+    env_cred_dict = {
+        'OS_USERNAME': 'username',
+        'OS_PASSWORD': 'password',
+        'OS_AUTH_URL': 'auth_url',
+        'OS_TENANT_NAME': 'tenant_name',
+        'OS_USER_DOMAIN_NAME': 'user_domain_name',
+        'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
+        'OS_PROJECT_NAME': 'project_name',
+        'OS_ENDPOINT_TYPE': 'endpoint_type',
+        'OS_REGION_NAME': 'region_name'
+    }
+    return env_cred_dict
+
+
+def get_credentials(other_creds={}):
+    """Returns a creds dictionary filled with parsed from env
     """
     creds = {}
+    env_vars = get_rc_env_vars()
+    env_cred_dict = get_env_cred_dict()
 
-    keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
-    if (keystone_api_version is None or
-            keystone_api_version == '2'):
-        keystone_v3 = False
-        tenant_env = 'OS_TENANT_NAME'
-        tenant = 'tenant_name'
-    else:
-        keystone_v3 = True
-        tenant_env = 'OS_PROJECT_NAME'
-        tenant = 'project_name'
-
-    # Check that the env vars exists:
-    envvars = ('OS_USERNAME', 'OS_PASSWORD', 'OS_AUTH_URL', tenant_env)
-    for envvar in envvars:
+    for envvar in env_vars:
         if os.getenv(envvar) is None:
             raise MissingEnvVar(envvar)
+        else:
+            creds_key = env_cred_dict.get(envvar)
+            creds.update({creds_key: os.getenv(envvar)})
+
+    if 'tenant' in other_creds.keys():
+        if is_keystone_v3():
+            tenant = 'project_name'
+        else:
+            tenant = 'tenant_name'
+        other_creds[tenant] = other_creds.pop('tenant')
+
+    creds.update(other_creds)
 
-    # Unfortunately, each of the OpenStack client will request slightly
-    # different entries in their credentials dict.
-    if service.lower() in ("nova", "cinder"):
-        password = "api_key"
-        tenant = "project_id"
-    else:
-        password = "password"
-
-    # The most common way to pass these info to the script is to do it through
-    # environment variables.
-    creds.update({
-        "username": os.environ.get("OS_USERNAME"),
-        password: os.environ.get("OS_PASSWORD"),
-        "auth_url": os.environ.get("OS_AUTH_URL"),
-        tenant: os.environ.get(tenant_env)
-    })
-    if keystone_v3:
-        if os.getenv('OS_USER_DOMAIN_NAME') is not None:
-            creds.update({
-                "user_domain_name": os.getenv('OS_USER_DOMAIN_NAME')
-            })
-        if os.getenv('OS_PROJECT_DOMAIN_NAME') is not None:
-            creds.update({
-                "project_domain_name": os.getenv('OS_PROJECT_DOMAIN_NAME')
-            })
-
-    if os.getenv('OS_ENDPOINT_TYPE') is not None:
-        creds.update({
-            "endpoint_type": os.environ.get("OS_ENDPOINT_TYPE")
-        })
-    if os.getenv('OS_REGION_NAME') is not None:
-        creds.update({
-            "region_name": os.environ.get("OS_REGION_NAME")
-        })
-    cacert = os.environ.get("OS_CACERT")
-    if cacert is not None:
-        # each openstack client uses differnt kwargs for this
-        creds.update({"cacert": cacert,
-                      "ca_cert": cacert,
-                      "https_ca_cert": cacert,
-                      "https_cacert": cacert,
-                      "ca_file": cacert})
-        creds.update({"insecure": "True", "https_insecure": "True"})
-        if not os.path.isfile(cacert):
-            logger.info("WARNING: The 'OS_CACERT' environment variable is "
-                        "set to %s but the file does not exist." % cacert)
     return creds
 
 
@@ -132,66 +121,121 @@ def source_credentials(rc_file):
 
 
 def get_credentials_for_rally():
-    creds = get_credentials("keystone")
-    keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
-    if (keystone_api_version is None or
-            keystone_api_version == '2'):
-        admin_keys = ['username', 'tenant_name', 'password']
-    else:
-        admin_keys = ['username', 'password', 'user_domain_name',
-                      'project_name', 'project_domain_name']
+    creds = get_credentials()
+    env_cred_dict = get_env_cred_dict()
+    rally_conf = {"type": "ExistingCloud", "admin": {}}
+    for key in creds:
+        if key == 'auth_url':
+            rally_conf[key] = creds[key]
+        else:
+            rally_conf['admin'][key] = creds[key]
 
     endpoint_types = [('internalURL', 'internal'),
                       ('publicURL', 'public'), ('adminURL', 'admin')]
-    if 'endpoint_type' in creds.keys():
+
+    endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
+    if endpoint_type is not None:
+        cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
         for k, v in endpoint_types:
-            if creds['endpoint_type'] == k:
-                creds['endpoint_type'] = v
-    rally_conf = {"type": "ExistingCloud", "admin": {}}
-    for key in creds:
-        if key in admin_keys:
-            rally_conf['admin'][key] = creds[key]
-        else:
-            rally_conf[key] = creds[key]
+            if endpoint_type == k:
+                rally_conf[cred_key] = v
+
+    region_name = os.getenv('OS_REGION_NAME')
+    if region_name is not None:
+        cred_key = env_cred_dict.get('OS_REGION_NAME')
+        rally_conf[cred_key] = region_name
     return rally_conf
 
 
+def get_session_auth(other_creds={}):
+    loader = loading.get_plugin_loader('password')
+    creds = get_credentials(other_creds)
+    auth = loader.load_from_options(**creds)
+    return auth
+
+
+def get_endpoint(service_type, endpoint_type='publicURL'):
+    auth = get_session_auth()
+    return get_session().get_endpoint(auth=auth,
+                                      service_type=service_type,
+                                      endpoint_type=endpoint_type)
+
+
+def get_session(other_creds={}):
+    auth = get_session_auth(other_creds)
+    return session.Session(auth=auth)
+
+
 # *********************************************
 #   CLIENTS
 # *********************************************
-def get_keystone_client():
-    creds_keystone = get_credentials("keystone")
-    return keystoneclient.Client(**creds_keystone)
+def get_keystone_client_version():
+    api_version = os.getenv('OS_IDENTITY_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'",
+                    api_version)
+        return api_version
+    return DEFAULT_API_VERSION
+
+
+def get_keystone_client(other_creds={}):
+    sess = get_session(other_creds)
+    return keystoneclient.Client(get_keystone_client_version(), session=sess)
+
 
+def get_nova_client_version():
+    api_version = os.getenv('OS_COMPUTE_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'",
+                    api_version)
+        return api_version
+    return DEFAULT_API_VERSION
 
-def get_nova_client():
-    creds_nova = get_credentials("nova")
-    return novaclient.Client('2', **creds_nova)
 
+def get_nova_client(other_creds={}):
+    sess = get_session(other_creds)
+    return novaclient.Client(get_nova_client_version(), session=sess)
 
-def get_cinder_client():
-    creds_cinder = get_credentials("cinder")
-    creds_cinder.update({
-        "service_type": "volume"
-    })
-    return cinderclient.Client('2', **creds_cinder)
 
+def get_cinder_client_version():
+    api_version = os.getenv('OS_VOLUME_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_VOLUME_API_VERSION is set in env as '%s'",
+                    api_version)
+        return api_version
+    return DEFAULT_API_VERSION
 
-def get_neutron_client():
-    creds_neutron = get_credentials("neutron")
-    return neutronclient.Client(**creds_neutron)
 
+def get_cinder_client(other_creds={}):
+    sess = get_session(other_creds)
+    return cinderclient.Client(get_cinder_client_version(), session=sess)
 
-def get_glance_client():
-    keystone_client = get_keystone_client()
-    glance_endpoint_type = 'publicURL'
-    os_endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
-    if os_endpoint_type is not None:
-        glance_endpoint_type = os_endpoint_type
-    glance_endpoint = keystone_client.service_catalog.url_for(
-        service_type='image', endpoint_type=glance_endpoint_type)
-    return glanceclient.Client(1, glance_endpoint,
-                               token=keystone_client.auth_token)
+
+def get_neutron_client_version():
+    api_version = os.getenv('OS_NETWORK_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_NETWORK_API_VERSION is set in env as '%s'",
+                    api_version)
+        return api_version
+    return DEFAULT_API_VERSION
+
+
+def get_neutron_client(other_creds={}):
+    sess = get_session(other_creds)
+    return neutronclient.Client(get_neutron_client_version(), session=sess)
+
+
+def get_glance_client_version():
+    api_version = os.getenv('OS_IMAGE_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
+        return api_version
+    return DEFAULT_API_VERSION
+
+
+def get_glance_client(other_creds={}):
+    sess = get_session(other_creds)
+    return glanceclient.Client(get_glance_client_version(), session=sess)
 
 
 # *********************************************
@@ -473,13 +517,13 @@ def create_floating_ip(neutron_client):
     return {'fip_addr': fip_addr, 'fip_id': fip_id}
 
 
-def add_floating_ip(nova_client, server_id, floatingip_id):
+def add_floating_ip(nova_client, server_id, floatingip_addr):
     try:
-        nova_client.servers.add_floating_ip(server_id, floatingip_id)
+        nova_client.servers.add_floating_ip(server_id, floatingip_addr)
         return True
     except Exception, e:
         logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
-                     % (server_id, floatingip_id, e))
+                     % (server_id, floatingip_addr, e))
         return False
 
 
@@ -1070,38 +1114,29 @@ def get_image_id(glance_client, image_name):
 
 
 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
-                        container="bare", public=True):
+                        container="bare", public="public"):
     if not os.path.isfile(file_path):
         logger.error("Error: file %s does not exist." % file_path)
         return None
     try:
         image_id = get_image_id(glance_client, image_name)
         if image_id != '':
-            if logger:
-                logger.info("Image %s already exists." % image_name)
+            logger.info("Image %s already exists." % image_name)
         else:
-            if logger:
-                logger.info("Creating image '%s' from '%s'..." % (image_name,
-                                                                  file_path))
-            try:
-                properties = ft_utils.get_functest_config(
-                    'general.image_properties')
-            except ValueError:
-                # image properties are not configured
-                # therefore don't add any properties
-                properties = {}
-            with open(file_path) as fimage:
-                image = glance_client.images.create(name=image_name,
-                                                    is_public=public,
-                                                    disk_format=disk,
-                                                    container_format=container,
-                                                    properties=properties,
-                                                    data=fimage)
+            logger.info("Creating image '%s' from '%s'..." % (image_name,
+                                                              file_path))
+
+            image = glance_client.images.create(name=image_name,
+                                                visibility=public,
+                                                disk_format=disk,
+                                                container_format=container)
             image_id = image.id
+            with open(file_path) as image_data:
+                glance_client.images.upload(image_id, image_data)
         return image_id
     except Exception, e:
         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
-                     "'%s')]: %s" % (image_name, file_path, str(public), e))
+                     "'%s')]: %s" % (image_name, file_path, public, e))
         return None
 
 
@@ -1218,7 +1253,10 @@ def delete_volume_type(cinder_client, volume_type):
 # *********************************************
 def get_tenants(keystone_client):
     try:
-        tenants = keystone_client.tenants.list()
+        if is_keystone_v3():
+            tenants = keystone_client.projects.list()
+        else:
+            tenants = keystone_client.tenants.list()
         return tenants
     except Exception, e:
         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
@@ -1235,7 +1273,7 @@ def get_users(keystone_client):
 
 
 def get_tenant_id(keystone_client, tenant_name):
-    tenants = keystone_client.tenants.list()
+    tenants = get_tenants(keystone_client)
     id = ''
     for t in tenants:
         if t.name == tenant_name:
@@ -1245,7 +1283,7 @@ def get_tenant_id(keystone_client, tenant_name):
 
 
 def get_user_id(keystone_client, user_name):
-    users = keystone_client.users.list()
+    users = get_users(keystone_client)
     id = ''
     for u in users:
         if u.name == user_name:
@@ -1266,9 +1304,16 @@ def get_role_id(keystone_client, role_name):
 
 def create_tenant(keystone_client, tenant_name, tenant_description):
     try:
-        tenant = keystone_client.tenants.create(tenant_name,
-                                                tenant_description,
-                                                enabled=True)
+        if is_keystone_v3():
+            tenant = keystone_client.projects.create(
+                name=tenant_name,
+                description=tenant_description,
+                domain="default",
+                enabled=True)
+        else:
+            tenant = keystone_client.tenants.create(tenant_name,
+                                                    tenant_description,
+                                                    enabled=True)
         return tenant.id
     except Exception, e:
         logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
@@ -1279,9 +1324,18 @@ def create_tenant(keystone_client, tenant_name, tenant_description):
 def create_user(keystone_client, user_name, user_password,
                 user_email, tenant_id):
     try:
-        user = keystone_client.users.create(user_name, user_password,
-                                            user_email, tenant_id,
-                                            enabled=True)
+        if is_keystone_v3():
+            user = keystone_client.users.create(name=user_name,
+                                                password=user_password,
+                                                email=user_email,
+                                                project_id=tenant_id,
+                                                enabled=True)
+        else:
+            user = keystone_client.users.create(user_name,
+                                                user_password,
+                                                user_email,
+                                                tenant_id,
+                                                enabled=True)
         return user.id
     except Exception, e:
         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
@@ -1292,7 +1346,12 @@ def create_user(keystone_client, user_name, user_password,
 
 def add_role_user(keystone_client, user_id, role_id, tenant_id):
     try:
-        keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
+        if is_keystone_v3():
+            keystone_client.roles.grant(role=role_id,
+                                        user=user_id,
+                                        project=tenant_id)
+        else:
+            keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
         return True
     except Exception, e:
         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
@@ -1302,7 +1361,10 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id):
 
 def delete_tenant(keystone_client, tenant_id):
     try:
-        keystone_client.tenants.delete(tenant_id)
+        if is_keystone_v3():
+            keystone_client.projects.delete(tenant_id)
+        else:
+            keystone_client.tenants.delete(tenant_id)
         return True
     except Exception, e:
         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
index ecd57d8..79d05d3 100755 (executable)
@@ -2,28 +2,6 @@
 set -o errexit
 set -o pipefail
 
-# ******************************
-# prepare the env for the tests
-# ******************************
-# clean useless results dir
-# should be done at the end
-# but in case of crash during unit test
-# clean it anyway
-if [ -d "/home/opnfv/functest/results" ]
-then
-    sudo rm -rf /home/opnfv/functest
-fi
-
-# TODO clean that...
-# Create log dir if needed
-# log shall be disabled during unit tests
-# fix to be done in Logger
-echo "Create dummy log file...."
-sudo mkdir -p /home/opnfv/functest/results/odl
-sudo touch /home/opnfv/functest/results/functest.log
-sudo touch /home/opnfv/functest/results/odl/stdout.txt
-sudo chmod -Rf a+rw /home/opnfv
-
 # Either Workspace is set (CI)
 if [ -z $WORKSPACE ]
 then
@@ -53,8 +31,11 @@ export CONFIG_FUNCTEST_YAML=$(pwd)/functest/ci/config_functest.yaml
 nosetests --with-xunit \
          --with-coverage \
          --cover-erase \
+         --cover-tests \
+         --cover-package=functest.cli \
          --cover-package=functest.core.testcase_base \
          --cover-package=functest.opnfv_tests.sdn.odl.odl \
+         --cover-package=functest.utils \
          --cover-xml \
          --cover-html \
          functest/tests/unit
@@ -62,13 +43,4 @@ rc=$?
 
 deactivate
 
-# *******
-# clean
-# *******
-# Clean useless logs
-if [ -d "/home/opnfv/functest/results" ]
-then
-    sudo rm -rf /home/opnfv/functest/results
-fi
-
 exit $rc
index 58a9a48..0c53ffb 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -1,25 +1,25 @@
-##############################################################################\r
-# All rights reserved. This program and the accompanying materials\r
-# are made available under the terms of the Apache License, Version 2.0\r
-# which accompanies this distribution, and is available at\r
-# http://www.apache.org/licenses/LICENSE-2.0\r
-##############################################################################\r
-\r
-from setuptools import setup, find_packages\r
-\r
-\r
-setup(\r
-    name="functest",\r
-    version="master",\r
-    py_modules=['cli_base'],\r
-    packages=find_packages(),\r
-    include_package_data=True,\r
-    package_data={\r
-    },\r
-    url="https://www.opnfv.org",\r
-    entry_points={\r
-        'console_scripts': [\r
-            'functest=functest.cli.cli_base:cli'\r
-        ],\r
-    },\r
-)\r
+##############################################################################
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+from setuptools import setup, find_packages
+
+
+setup(
+    name="functest",
+    version="master",
+    py_modules=['cli_base'],
+    packages=find_packages(),
+    include_package_data=True,
+    package_data={
+    },
+    url="https://www.opnfv.org",
+    entry_points={
+        'console_scripts': [
+            'functest=functest.cli.cli_base:cli'
+        ],
+    },
+)
index 8be8e20..2bf297b 100755 (executable)
@@ -5,6 +5,7 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 #
+click==6.6
 coverage==4.1
 dnspython==1.15.0
 gitpython==1.0.1
@@ -15,9 +16,10 @@ python-congressclient==1.5.0
 python-keystoneclient==3.5.0
 python-neutronclient==6.0.0
 python-openstackclient==2.3.0
+python-tackerclient==0.7.0
 pyyaml==3.10
 requests==2.8.0
 robotframework==2.9.1
 robotframework-requests==0.3.8
 robotframework-sshlibrary==2.1.1
-virtualenv==15.1.0
\ No newline at end of file
+virtualenv==15.1.0