aboutsummaryrefslogtreecommitdiffstats
path: root/functest
diff options
context:
space:
mode:
Diffstat (limited to 'functest')
-rwxr-xr-xfunctest/ci/check_os.sh26
-rw-r--r--functest/ci/config_aarch64_patch.yaml8
-rw-r--r--[-rwxr-xr-x]functest/ci/config_functest.yaml53
-rw-r--r--[-rwxr-xr-x]functest/ci/config_patch.yaml4
-rw-r--r--functest/ci/download_images.sh31
-rwxr-xr-xfunctest/ci/generate_report.py153
-rw-r--r--functest/ci/installer_params.yaml8
-rw-r--r--functest/ci/logging.ini75
-rw-r--r--functest/ci/logging.json29
-rwxr-xr-xfunctest/ci/prepare_env.py162
-rw-r--r--functest/ci/rally_aarch64_patch.conf4
-rwxr-xr-xfunctest/ci/run_tests.py104
-rw-r--r--[-rwxr-xr-x]functest/ci/testcases.yaml284
-rw-r--r--functest/ci/tier_builder.py13
-rw-r--r--functest/ci/tier_handler.py7
-rw-r--r--functest/cli/cli_base.py6
-rw-r--r--functest/cli/commands/cli_env.py20
-rw-r--r--functest/cli/commands/cli_os.py15
-rw-r--r--functest/cli/commands/cli_testcase.py13
-rw-r--r--functest/cli/commands/cli_tier.py13
-rw-r--r--functest/core/feature.py149
-rw-r--r--functest/core/pytest_suite_runner.py46
-rw-r--r--functest/core/testcase.py127
-rw-r--r--functest/core/vnf.py (renamed from functest/core/vnf_base.py)170
-rw-r--r--functest/energy/__init__.py (renamed from functest/opnfv_tests/vnf/rnc/__init__.py)0
-rw-r--r--functest/energy/energy.py203
-rw-r--r--functest/opnfv_tests/features/barometer.py9
-rw-r--r--functest/opnfv_tests/features/copper.py25
-rw-r--r--functest/opnfv_tests/features/doctor.py24
-rw-r--r--functest/opnfv_tests/features/domino.py25
-rw-r--r--functest/opnfv_tests/features/netready.py22
-rw-r--r--functest/opnfv_tests/features/odl_sfc.py20
-rw-r--r--functest/opnfv_tests/features/promise.py24
-rw-r--r--functest/opnfv_tests/features/sdnvpn.py20
-rw-r--r--functest/opnfv_tests/features/security_scan.py24
-rw-r--r--functest/opnfv_tests/mano/orchestra.py11
-rwxr-xr-xfunctest/opnfv_tests/openstack/examples/create_instance_and_ip.py128
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py44
-rw-r--r--functest/opnfv_tests/openstack/refstack_client/defcore.txt9
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/refstack_client.py37
-rwxr-xr-xfunctest/opnfv_tests/openstack/refstack_client/tempest_conf.py24
-rw-r--r--functest/opnfv_tests/openstack/snaps/api_check.py16
-rw-r--r--functest/opnfv_tests/openstack/snaps/connection_check.py16
-rw-r--r--functest/opnfv_tests/openstack/snaps/health_check.py16
-rw-r--r--functest/opnfv_tests/openstack/snaps/smoke.py33
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_test_runner.py25
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_utils.py8
-rw-r--r--functest/opnfv_tests/openstack/tempest/conf_utils.py15
-rw-r--r--functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt3
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py74
-rw-r--r--functest/opnfv_tests/openstack/vping/vping_base.py415
-rwxr-xr-xfunctest/opnfv_tests/openstack/vping/vping_ssh.py286
-rwxr-xr-xfunctest/opnfv_tests/openstack/vping/vping_userdata.py140
-rwxr-xr-xfunctest/opnfv_tests/sdn/odl/odl.py75
-rw-r--r--functest/opnfv_tests/sdn/onos/onos.py80
-rwxr-xr-xfunctest/opnfv_tests/sdn/onos/sfc/sfc.py7
-rw-r--r--functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py5
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/client.py4
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/connection.py4
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/environment.py4
-rwxr-xr-xfunctest/opnfv_tests/vnf/aaa/aaa.py18
-rw-r--r--functest/opnfv_tests/vnf/ims/clearwater_ims_base.py18
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.py13
-rw-r--r--functest/opnfv_tests/vnf/ims/opera_ims.py26
-rwxr-xr-xfunctest/opnfv_tests/vnf/ims/orchestra_ims.py79
-rw-r--r--functest/opnfv_tests/vnf/ims/orchestra_ims.yaml2
-rw-r--r--functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py5
-rw-r--r--functest/opnfv_tests/vnf/rnc/parser.py26
-rw-r--r--functest/opnfv_tests/vnf/router/vyos_vrouter.py11
-rw-r--r--functest/tests/unit/ci/test_generate_report.py129
-rw-r--r--functest/tests/unit/ci/test_prepare_env.py87
-rw-r--r--functest/tests/unit/ci/test_run_tests.py42
-rw-r--r--functest/tests/unit/ci/test_tier_builder.py10
-rw-r--r--functest/tests/unit/ci/test_tier_handler.py5
-rw-r--r--functest/tests/unit/cli/commands/test_cli_env.py21
-rw-r--r--functest/tests/unit/cli/commands/test_cli_os.py33
-rw-r--r--functest/tests/unit/cli/commands/test_cli_testcase.py16
-rw-r--r--functest/tests/unit/cli/commands/test_cli_tier.py20
-rw-r--r--functest/tests/unit/core/test_feature.py98
-rw-r--r--functest/tests/unit/core/test_pytest_suite_runner.py51
-rw-r--r--functest/tests/unit/core/test_testcase.py166
-rw-r--r--functest/tests/unit/core/test_vnf.py168
-rw-r--r--functest/tests/unit/core/test_vnf_base.py53
-rw-r--r--functest/tests/unit/energy/__init__.py (renamed from functest/tests/unit/opnfv_tests/__init__.py)0
-rw-r--r--functest/tests/unit/energy/test_functest_energy.py277
-rw-r--r--functest/tests/unit/features/__init__.py (renamed from functest/tests/unit/opnfv_tests/openstack/__init__.py)0
-rw-r--r--functest/tests/unit/features/test_barometer.py50
-rw-r--r--functest/tests/unit/odl/test_odl.py127
-rw-r--r--functest/tests/unit/openstack/__init__.py (renamed from functest/tests/unit/opnfv_tests/openstack/rally/__init__.py)0
-rw-r--r--functest/tests/unit/openstack/rally/__init__.py (renamed from functest/tests/unit/opnfv_tests/openstack/refstack_client/__init__.py)0
-rw-r--r--functest/tests/unit/openstack/rally/test_rally.py (renamed from functest/tests/unit/opnfv_tests/openstack/rally/test_rally.py)13
-rw-r--r--functest/tests/unit/openstack/refstack_client/__init__.py (renamed from functest/tests/unit/opnfv_tests/openstack/tempest/__init__.py)0
-rw-r--r--functest/tests/unit/openstack/refstack_client/test_refstack_client.py (renamed from functest/tests/unit/opnfv_tests/openstack/refstack_client/test_refstack_client.py)0
-rw-r--r--functest/tests/unit/openstack/tempest/__init__.py (renamed from functest/tests/unit/opnfv_tests/vnf/__init__.py)0
-rw-r--r--functest/tests/unit/openstack/tempest/test_conf_utils.py (renamed from functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py)0
-rw-r--r--functest/tests/unit/openstack/tempest/test_tempest.py (renamed from functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py)186
-rw-r--r--functest/tests/unit/utils/test_decorators.py135
-rw-r--r--functest/tests/unit/utils/test_functest_logger.py48
-rw-r--r--functest/tests/unit/utils/test_functest_utils.py65
-rw-r--r--functest/tests/unit/utils/test_openstack_utils.py50
-rw-r--r--functest/tests/unit/vnf/__init__.py (renamed from functest/tests/unit/opnfv_tests/vnf/ims/__init__.py)0
-rw-r--r--functest/tests/unit/vnf/ims/__init__.py0
-rw-r--r--functest/tests/unit/vnf/ims/test_clearwater.py (renamed from functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py)0
-rw-r--r--functest/tests/unit/vnf/ims/test_cloudify_ims.py (renamed from functest/tests/unit/opnfv_tests/vnf/ims/test_cloudify_ims.py)0
-rw-r--r--functest/tests/unit/vnf/ims/test_ims_base.py (renamed from functest/tests/unit/opnfv_tests/vnf/ims/test_ims_base.by)6
-rw-r--r--functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py (renamed from functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py)0
-rw-r--r--functest/tests/unit/vnf/rnc/__init__.py0
-rw-r--r--[-rwxr-xr-x]functest/utils/config.py14
-rw-r--r--[-rwxr-xr-x]functest/utils/constants.py19
-rw-r--r--functest/utils/decorators.py29
-rw-r--r--functest/utils/env.py9
-rw-r--r--functest/utils/functest_logger.py76
-rw-r--r--functest/utils/functest_utils.py45
-rw-r--r--functest/utils/openstack/cinder.py7
-rw-r--r--functest/utils/openstack/glance.py7
-rw-r--r--functest/utils/openstack/keystone.py7
-rw-r--r--functest/utils/openstack/neutron.py7
-rw-r--r--functest/utils/openstack/nova.py7
-rwxr-xr-xfunctest/utils/openstack_clean.py5
-rwxr-xr-xfunctest/utils/openstack_snapshot.py5
-rw-r--r--functest/utils/openstack_tacker.py4
-rw-r--r--functest/utils/openstack_utils.py153
122 files changed, 3295 insertions, 2548 deletions
diff --git a/functest/ci/check_os.sh b/functest/ci/check_os.sh
index 3920b7ac..ce0bc20c 100755
--- a/functest/ci/check_os.sh
+++ b/functest/ci/check_os.sh
@@ -69,7 +69,7 @@ fi
echo "Checking OpenStack endpoints:"
publicURL=$(openstack catalog show identity |awk '/public/ {print $4}')
publicIP=$(echo $publicURL|sed 's/^.*http.*\:\/\///'|sed 's/.[^:]*$//')
-publicPort=$(echo $publicURL|sed 's/^.*://'|sed 's/\/.*$//')
+publicPort=$(echo $publicURL|grep -Po '(?<=:)\d+')
https_enabled=$(echo $publicURL | grep 'https')
if [[ -n $https_enabled ]]; then
echo ">>Verifying SSL connectivity to the public endpoint $publicIP:$publicPort..."
@@ -86,30 +86,6 @@ if [ $RETVAL -ne 0 ]; then
fi
echo " ...OK"
-adminURL=$(openstack catalog show identity |awk '/admin/ {print $4}')
-if [ -z ${adminURL} ]; then
- echo "ERROR: Cannot determine the admin URL."
- openstack catalog show identity
- exit 1
-fi
-adminIP=$(echo $adminURL|sed 's/^.*http.*\:\/\///'|sed 's/.[^:]*$//')
-adminPort=$(echo $adminURL|sed 's/^.*://'|sed 's/.[^\/]*$//')
-https_enabled=$(echo $adminURL | grep 'https')
-if [[ -n $https_enabled ]]; then
- echo ">>Verifying SSL connectivity to the admin endpoint $adminIP:$adminPort..."
- verify_SSL_connectivity $adminIP $adminPort
-else
- echo ">>Verifying connectivity to the admin endpoint $adminIP:$adminPort..."
- verify_connectivity $adminIP $adminPort
-fi
-RETVAL=$?
-if [ $RETVAL -ne 0 ]; then
- echo "ERROR: Cannot talk to the admin endpoint $adminIP:$adminPort ."
- echo "$adminURL"
- exit 1
-fi
-echo " ...OK"
-
echo "Checking Required OpenStack services:"
for service in $MANDATORY_SERVICES; do
diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml
index b43b5a76..cd395ab8 100644
--- a/functest/ci/config_aarch64_patch.yaml
+++ b/functest/ci/config_aarch64_patch.yaml
@@ -16,5 +16,13 @@ os:
vping:
image_name: TestVM
+ odl_sfc:
+ image_base_url: "http://artifacts.opnfv.org/sfc/demo"
+ image_name: sfc_nsh_danube
+ image_file_name: sf_nsh_danube_arm64.img
+ image_initrd: sf_nsh_danube_arm64-initrd
+ image_kernel: sf_nsh_danube_arm64-kernel
+ image_format: ami
+ os_cmd_line: 'root=LABEL=cloudimg-rootfs ro'
doctor:
image_name: TestVM
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index 95a4408a..9b796071 100755..100644
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -34,10 +34,11 @@ general:
functest: /home/opnfv/functest
functest_test: /home/opnfv/repos/functest/functest/opnfv_tests
results: /home/opnfv/functest/results
- functest_logging_cfg: /home/opnfv/repos/functest/functest/ci/logging.json
+ functest_logging_cfg: /home/opnfv/repos/functest/functest/ci/logging.ini
functest_conf: /home/opnfv/functest/conf
functest_data: /home/opnfv/functest/data
ims_data: /home/opnfv/functest/data/ims/
+ functest_images: /home/opnfv/functest/images
rally_inst: /home/opnfv/.rally
repo_kingbird: /home/opnfv/repos/kingbird
refstack_client: /home/opnfv/repos/refstack-client
@@ -49,6 +50,8 @@ general:
image_name: Cirros-0.3.5
image_name_alt: Cirros-0.3.5-1
image_file_name: cirros-0.3.5-x86_64-disk.img
+ image_url: http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
+ image_user: cirros
image_disk_format: qcow2
image_username: cirros
image_password: cubswin:)
@@ -71,14 +74,23 @@ general:
functest:
testcases_yaml: /home/opnfv/repos/functest/functest/ci/testcases.yaml
-healthcheck:
- disk_image: /home/opnfv/functest/data/cirros-0.3.5-x86_64-disk.img
- disk_format: qcow2
- wait_time: 60
-
snaps:
use_keystone: True
- use_floating_ips: False
+ use_floating_ips: True
+# images:
+# cirros:
+# disk_url: http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
+ # ARM
+# disk_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img
+# kernel_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-kernel
+# ramdisk_url: http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-initramfs
+# extra_properties:
+# os_command_line: root=/dev/vdb1 rw rootwait console=tty0 console=ttyS0 console=ttyAMA0
+# hw_video_model: vga
+# ubuntu:
+# disk_url: http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img
+# centos:
+# disk_url: http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2
vping:
ping_timeout: 200
@@ -92,12 +104,26 @@ vping:
router_name: vping-router
sg_name: vPing-sg
sg_desc: Security group for vPing test case
+ keypair_name: vPing-keypair
+ keypair_priv_file: /tmp/vPing-keypair
+ keypair_pub_file: /tmp/vPing-keypair.pub
+ vm_boot_timeout: 180
+ vm_delete_timeout: 100
+ vm_ssh_connect_timeout: 60
+ cleanup_objects: True
+ unique_names: True
onos_sfc:
image_base_url: http://artifacts.opnfv.org/sfc/demo
image_name: TestSfcVm
image_file_name: firewall_block_image.img
+odl_sfc:
+ image_base_url: "http://artifacts.opnfv.org/sfc/images"
+ image_name: sfc_nsh_danube
+ image_file_name: sfc_nsh_danube.qcow2
+ image_format: qcow2
+
tempest:
deployment_name: opnfv-tempest
identity:
@@ -125,7 +151,7 @@ rally:
router_name: rally-router
refstack:
- tempest_conf_path: openstack/refstack_client/tempest.conf
+ tempest_conf_path: openstack/refstack_client/refstack_tempest.conf
defcore_list: openstack/refstack_client/defcore.txt
vnf:
@@ -201,6 +227,11 @@ example:
sg_desc: Example Security group
results:
- # you can also set a dir (e.g. /home/opnfv/db) to dump results
- # test_db_url: file:///home/opnfv/db
- test_db_url: http://testresults.opnfv.org/test/api/v1
+ # you can also set a file (e.g. /home/opnfv/functest/results/dump.txt) to dump results
+ # test_db_url: file:///home/opnfv/functest/results/dump.txt
+ test_db_url: http://testresults.opnfv.org/test/api/v1/results
+
+energy_recorder:
+ api_url: http://161.105.253.100:8888/resources
+ api_user: ""
+ api_password: ""
diff --git a/functest/ci/config_patch.yaml b/functest/ci/config_patch.yaml
index d984a3f4..d47766b6 100755..100644
--- a/functest/ci/config_patch.yaml
+++ b/functest/ci/config_patch.yaml
@@ -22,3 +22,7 @@ ovs:
tempest:
use_custom_images: True
use_custom_flavors: True
+multisite:
+ tempest:
+ use_custom_images: True
+ use_custom_flavors: True
diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh
new file mode 100644
index 00000000..f3fdef2e
--- /dev/null
+++ b/functest/ci/download_images.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+CIRROS_REPO_URL=http://download.cirros-cloud.net
+CIRROS_AARCH64_TAG=161201
+CIRROS_X86_64_TAG=0.3.5
+
+RED='\033[1;31m'
+NC='\033[0m' # No Color
+
+function usage(){
+ echo -e "${RED}USAGE: $script <destination_folder>${NC}"
+ exit 0
+}
+
+script=`basename "$0"`
+IMAGES_FOLDER_DIR=$1
+
+if [[ -z $IMAGES_FOLDER_DIR ]]; then usage; fi;
+
+set -ex
+mkdir -p ${IMAGES_FOLDER_DIR}
+
+wget -nc ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-disk.img -P ${IMAGES_FOLDER_DIR}
+wget -nc ${CIRROS_REPO_URL}/${CIRROS_X86_64_TAG}/cirros-${CIRROS_X86_64_TAG}-x86_64-lxc.tar.gz -P ${IMAGES_FOLDER_DIR}
+wget -nc http://artifacts.opnfv.org/sdnvpn/ubuntu-16.04-server-cloudimg-amd64-disk1.img -P ${IMAGES_FOLDER_DIR}
+
+# Add 3rd-party images for aarch64, since Functest can be run on an x86 machine to test an aarch64 POD
+wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-disk.img -P ${IMAGES_FOLDER_DIR}
+wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-initramfs -P ${IMAGES_FOLDER_DIR}
+wget -nc ${CIRROS_REPO_URL}/daily/20${CIRROS_AARCH64_TAG}/cirros-d${CIRROS_AARCH64_TAG}-aarch64-kernel -P ${IMAGES_FOLDER_DIR}
+set +ex \ No newline at end of file
diff --git a/functest/ci/generate_report.py b/functest/ci/generate_report.py
deleted file mode 100755
index 3872a07e..00000000
--- a/functest/ci/generate_report.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-import json
-import re
-import urllib2
-
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
-from functest.utils.constants import CONST
-
-COL_1_LEN = 25
-COL_2_LEN = 15
-COL_3_LEN = 12
-COL_4_LEN = 15
-COL_5_LEN = 75
-
-# If we run from CI (Jenkins) we will push the results to the DB
-# and then we can print the url to the specific test result
-
-
-logger = ft_logger.Logger("generate_report").getLogger()
-
-
-def init(tiers_to_run=[]):
- test_cases_arr = []
- for tier in tiers_to_run:
- for test in tier.get_tests():
- test_cases_arr.append({'test_name': test.get_name(),
- 'tier_name': tier.get_name(),
- 'result': 'Not executed',
- 'duration': '0',
- 'url': ''})
- return test_cases_arr
-
-
-def get_results_from_db():
- url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(),
- CONST.BUILD_TAG)
- logger.debug("Query to rest api: %s" % url)
- try:
- data = json.load(urllib2.urlopen(url))
- return data['results']
- except:
- logger.error("Cannot read content from the url: %s" % url)
- return None
-
-
-def get_data(test, results):
- test_result = test['result']
- url = ''
- for test_db in results:
- if test['test_name'] in test_db['case_name']:
- id = test_db['_id']
- url = ft_utils.get_db_url() + '/results/' + id
- test_result = test_db['criteria']
-
- return {"url": url, "result": test_result}
-
-
-def print_line(w1, w2='', w3='', w4='', w5=''):
- str = ('| ' + w1.ljust(COL_1_LEN - 1) +
- '| ' + w2.ljust(COL_2_LEN - 1) +
- '| ' + w3.ljust(COL_3_LEN - 1) +
- '| ' + w4.ljust(COL_4_LEN - 1))
- if CONST.IS_CI_RUN:
- str += ('| ' + w5.ljust(COL_5_LEN - 1))
- str += '|\n'
- return str
-
-
-def print_line_no_columns(str):
- TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN + 2
- if CONST.IS_CI_RUN:
- TOTAL_LEN += COL_5_LEN + 1
- return ('| ' + str.ljust(TOTAL_LEN) + "|\n")
-
-
-def print_separator(char="=", delimiter="+"):
- str = ("+" + char * COL_1_LEN +
- delimiter + char * COL_2_LEN +
- delimiter + char * COL_3_LEN +
- delimiter + char * COL_4_LEN)
- if CONST.IS_CI_RUN:
- str += (delimiter + char * COL_5_LEN)
- str += '+\n'
- return str
-
-
-def main(args=[]):
- executed_test_cases = args
-
- if CONST.IS_CI_RUN:
- results = get_results_from_db()
- if results is not None:
- for test in executed_test_cases:
- data = get_data(test, results)
- test.update({"url": data['url'],
- "result": data['result']})
-
- TOTAL_LEN = COL_1_LEN + COL_2_LEN + COL_3_LEN + COL_4_LEN
- if CONST.IS_CI_RUN:
- TOTAL_LEN += COL_5_LEN
- MID = TOTAL_LEN / 2
-
- if CONST.BUILD_TAG is not None:
- if re.search("daily", CONST.BUILD_TAG) is not None:
- CONST.CI_LOOP = "daily"
- else:
- CONST.CI_LOOP = "weekly"
-
- str = ''
- str += print_separator('=', delimiter="=")
- str += print_line_no_columns(' ' * (MID - 8) + 'FUNCTEST REPORT')
- str += print_separator('=', delimiter="=")
- str += print_line_no_columns(' ')
- str += print_line_no_columns(" Deployment description:")
- str += print_line_no_columns(" INSTALLER: %s"
- % CONST.INSTALLER_TYPE)
- if CONST.DEPLOY_SCENARIO is not None:
- str += print_line_no_columns(" SCENARIO: %s"
- % CONST.DEPLOY_SCENARIO)
- if CONST.BUILD_TAG is not None:
- str += print_line_no_columns(" BUILD TAG: %s"
- % CONST.BUILD_TAG)
- if CONST.CI_LOOP is not None:
- str += print_line_no_columns(" CI LOOP: %s"
- % CONST.CI_LOOP)
- str += print_line_no_columns(' ')
- str += print_separator('=')
- if CONST.IS_CI_RUN:
- str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT', 'URL')
- else:
- str += print_line('TEST CASE', 'TIER', 'DURATION', 'RESULT')
- str += print_separator('=')
- for test in executed_test_cases:
- str += print_line(test['test_name'],
- test['tier_name'],
- test['duration'],
- test['result'],
- test['url'])
- str += print_separator('-')
-
- logger.info("\n\n\n%s" % str)
-
-
-if __name__ == '__main__':
- import sys
- main(sys.argv[1:])
diff --git a/functest/ci/installer_params.yaml b/functest/ci/installer_params.yaml
index 26aff9bb..77e9355f 100644
--- a/functest/ci/installer_params.yaml
+++ b/functest/ci/installer_params.yaml
@@ -2,10 +2,10 @@ apex:
ip: ''
user: 'stack'
pkey: '/root/.ssh/id_rsa'
-# compass:
-# ip: '192.168.200.2'
-# user: 'root'
-# password: 'root'
+compass:
+ ip: '192.168.200.2'
+ user: 'root'
+ password: 'root'
fuel:
ip: '10.20.0.2'
user: 'root'
diff --git a/functest/ci/logging.ini b/functest/ci/logging.ini
new file mode 100644
index 00000000..210c8f5f
--- /dev/null
+++ b/functest/ci/logging.ini
@@ -0,0 +1,75 @@
+[loggers]
+keys=root,functest,ci,cli,core,energy,opnfv_tests,utils
+
+[handlers]
+keys=console,wconsole,file,null
+
+[formatters]
+keys=standard
+
+[logger_root]
+level=NOTSET
+handlers=null
+
+[logger_functest]
+level=NOTSET
+handlers=file
+qualname=functest
+
+[logger_ci]
+level=NOTSET
+handlers=console
+qualname=functest.ci
+
+[logger_cli]
+level=NOTSET
+handlers=wconsole
+qualname=functest.cli
+
+[logger_core]
+level=NOTSET
+handlers=console
+qualname=functest.core
+
+[logger_energy]
+level=NOTSET
+handlers=wconsole
+qualname=functest.energy
+
+[logger_opnfv_tests]
+level=NOTSET
+handlers=wconsole
+qualname=functest.opnfv_tests
+
+[logger_utils]
+level=NOTSET
+handlers=wconsole
+qualname=functest.utils
+
+[handler_null]
+class=NullHandler
+level=NOTSET
+formatter=standard
+args=()
+
+[handler_console]
+class=StreamHandler
+level=INFO
+formatter=standard
+args=(sys.stdout,)
+
+[handler_wconsole]
+class=StreamHandler
+level=WARN
+formatter=standard
+args=(sys.stdout,)
+
+[handler_file]
+class=FileHandler
+level=DEBUG
+formatter=standard
+args=("/home/opnfv/functest/results/functest.log",)
+
+[formatter_standard]
+format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
+datefmt=
diff --git a/functest/ci/logging.json b/functest/ci/logging.json
deleted file mode 100644
index 2a2399d3..00000000
--- a/functest/ci/logging.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "version": 1,
- "disable_existing_loggers": false,
- "formatters": {
- "standard": {
- "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
- }
- },
- "handlers": {
- "console": {
- "level": "INFO",
- "class": "logging.StreamHandler",
- "formatter": "standard"
- },
- "file": {
- "level": "DEBUG",
- "class": "logging.FileHandler",
- "formatter": "standard",
- "filename": "/home/opnfv/functest/results/functest.log"
- }
- },
- "loggers": {
- "": {
- "handlers": ["console", "file"],
- "level": "DEBUG",
- "propagate": "yes"
- }
- }
-}
diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py
index e9a470f9..8e17a4fc 100755
--- a/functest/ci/prepare_env.py
+++ b/functest/ci/prepare_env.py
@@ -8,6 +8,8 @@
import argparse
import json
+import logging
+import logging.config
import os
import re
import subprocess
@@ -16,7 +18,6 @@ import fileinput
import yaml
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST
@@ -27,13 +28,13 @@ from opnfv.deployment import factory
actions = ['start', 'check']
""" logging configuration """
-logger = ft_logger.Logger("prepare_env").getLogger()
+logger = logging.getLogger('functest.ci.prepare_env')
handler = None
# set the architecture to default
pod_arch = None
arch_filter = ['aarch64']
-CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML
+CONFIG_FUNCTEST_PATH = CONST.__getattribute__('CONFIG_FUNCTEST_YAML')
CONFIG_PATCH_PATH = os.path.join(os.path.dirname(
CONFIG_FUNCTEST_PATH), "config_patch.yaml")
CONFIG_AARCH64_PATCH_PATH = os.path.join(os.path.dirname(
@@ -65,63 +66,70 @@ def check_env_variables():
print_separator()
logger.info("Checking environment variables...")
- if CONST.INSTALLER_TYPE is None:
+ if CONST.__getattribute__('INSTALLER_TYPE') is None:
logger.warning("The env variable 'INSTALLER_TYPE' is not defined.")
- CONST.INSTALLER_TYPE = "undefined"
+ CONST.__setattr__('INSTALLER_TYPE', 'undefined')
else:
- if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
+ if (CONST.__getattribute__('INSTALLER_TYPE') not in
+ opnfv_constants.INSTALLERS):
logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. "
"Available OPNFV Installers are : %s. "
"Setting INSTALLER_TYPE=undefined."
- % (CONST.INSTALLER_TYPE,
+ % (CONST.__getattribute__('INSTALLER_TYPE'),
opnfv_constants.INSTALLERS))
- CONST.INSTALLER_TYPE = "undefined"
+ CONST.__setattr__('INSTALLER_TYPE', 'undefined')
else:
logger.info(" INSTALLER_TYPE=%s"
- % CONST.INSTALLER_TYPE)
+ % CONST.__getattribute__('INSTALLER_TYPE'))
- if CONST.INSTALLER_IP is None:
+ if CONST.__getattribute__('INSTALLER_IP') is None:
logger.warning("The env variable 'INSTALLER_IP' is not defined. "
"It is needed to fetch the OpenStack credentials. "
"If the credentials are not provided to the "
"container as a volume, please add this env variable "
"to the 'docker run' command.")
else:
- logger.info(" INSTALLER_IP=%s" % CONST.INSTALLER_IP)
+ logger.info(" INSTALLER_IP=%s" %
+ CONST.__getattribute__('INSTALLER_IP'))
- if CONST.DEPLOY_SCENARIO is None:
+ if CONST.__getattribute__('DEPLOY_SCENARIO') is None:
logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. "
"Setting CI_SCENARIO=undefined.")
- CONST.DEPLOY_SCENARIO = "undefined"
+ CONST.__setattr__('DEPLOY_SCENARIO', 'undefined')
else:
- logger.info(" DEPLOY_SCENARIO=%s" % CONST.DEPLOY_SCENARIO)
- if CONST.CI_DEBUG:
- logger.info(" CI_DEBUG=%s" % CONST.CI_DEBUG)
+ logger.info(" DEPLOY_SCENARIO=%s"
+ % CONST.__getattribute__('DEPLOY_SCENARIO'))
+ if CONST.__getattribute__('CI_DEBUG'):
+ logger.info(" CI_DEBUG=%s" % CONST.__getattribute__('CI_DEBUG'))
- if CONST.NODE_NAME:
- logger.info(" NODE_NAME=%s" % CONST.NODE_NAME)
+ if CONST.__getattribute__('NODE_NAME'):
+ logger.info(" NODE_NAME=%s" % CONST.__getattribute__('NODE_NAME'))
- if CONST.BUILD_TAG:
- logger.info(" BUILD_TAG=%s" % CONST.BUILD_TAG)
+ if CONST.__getattribute__('BUILD_TAG'):
+ logger.info(" BUILD_TAG=%s" % CONST.__getattribute__('BUILD_TAG'))
- if CONST.IS_CI_RUN:
- logger.info(" IS_CI_RUN=%s" % CONST.IS_CI_RUN)
+ if CONST.__getattribute__('IS_CI_RUN'):
+ logger.info(" IS_CI_RUN=%s" % CONST.__getattribute__('IS_CI_RUN'))
def get_deployment_handler():
global handler
global pod_arch
- installer_params_yaml = os.path.join(CONST.dir_repo_functest,
- 'functest/ci/installer_params.yaml')
- if (CONST.INSTALLER_IP and CONST.INSTALLER_TYPE and
- CONST.INSTALLER_TYPE in opnfv_constants.INSTALLERS):
+ installer_params_yaml = os.path.join(
+ CONST.__getattribute__('dir_repo_functest'),
+ 'functest/ci/installer_params.yaml')
+ if (CONST.__getattribute__('INSTALLER_IP') and
+ CONST.__getattribute__('INSTALLER_TYPE') and
+ CONST.__getattribute__('INSTALLER_TYPE') in
+ opnfv_constants.INSTALLERS):
try:
installer_params = ft_utils.get_parameter_from_yaml(
- CONST.INSTALLER_TYPE, installer_params_yaml)
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ installer_params_yaml)
except ValueError as e:
logger.debug('Printing deployment info is not supported for %s' %
- CONST.INSTALLER_TYPE)
+ CONST.__getattribute__('INSTALLER_TYPE'))
logger.debug(e)
else:
user = installer_params.get('user', None)
@@ -129,8 +137,8 @@ def get_deployment_handler():
pkey = installer_params.get('pkey', None)
try:
handler = factory.Factory.get_handler(
- installer=CONST.INSTALLER_TYPE,
- installer_ip=CONST.INSTALLER_IP,
+ installer=CONST.__getattribute__('INSTALLER_TYPE'),
+ installer_ip=CONST.__getattribute__('INSTALLER_IP'),
installer_user=user,
installer_pwd=password,
pkey_file=pkey)
@@ -143,51 +151,62 @@ def get_deployment_handler():
def create_directories():
print_separator()
logger.info("Creating needed directories...")
- if not os.path.exists(CONST.dir_functest_conf):
- os.makedirs(CONST.dir_functest_conf)
- logger.info(" %s created." % CONST.dir_functest_conf)
+ if not os.path.exists(CONST.__getattribute__('dir_functest_conf')):
+ os.makedirs(CONST.__getattribute__('dir_functest_conf'))
+ logger.info(" %s created." %
+ CONST.__getattribute__('dir_functest_conf'))
else:
- logger.debug(" %s already exists."
- % CONST.dir_functest_conf)
+ logger.debug(" %s already exists." %
+ CONST.__getattribute__('dir_functest_conf'))
- if not os.path.exists(CONST.dir_functest_data):
- os.makedirs(CONST.dir_functest_data)
- logger.info(" %s created." % CONST.dir_functest_data)
+ if not os.path.exists(CONST.__getattribute__('dir_functest_data')):
+ os.makedirs(CONST.__getattribute__('dir_functest_data'))
+ logger.info(" %s created." %
+ CONST.__getattribute__('dir_functest_data'))
else:
- logger.debug(" %s already exists."
- % CONST.dir_functest_data)
+ logger.debug(" %s already exists." %
+ CONST.__getattribute__('dir_functest_data'))
+ if not os.path.exists(CONST.__getattribute__('dir_functest_images')):
+ os.makedirs(CONST.__getattribute__('dir_functest_images'))
+ logger.info(" %s created." %
+ CONST.__getattribute__('dir_functest_images'))
+ else:
+ logger.debug(" %s already exists." %
+ CONST.__getattribute__('dir_functest_images'))
def source_rc_file():
print_separator()
logger.info("Fetching RC file...")
- if CONST.openstack_creds is None:
+ if CONST.__getattribute__('openstack_creds') is None:
logger.warning("The environment variable 'creds' must be set and"
"pointing to the local RC file. Using default: "
"/home/opnfv/functest/conf/openstack.creds ...")
- os.path.join(CONST.dir_functest_conf, 'openstack.creds')
+ os.path.join(
+ CONST.__getattribute__('dir_functest_conf'), 'openstack.creds')
- if not os.path.isfile(CONST.openstack_creds):
+ if not os.path.isfile(CONST.__getattribute__('openstack_creds')):
logger.info("RC file not provided. "
"Fetching it from the installer...")
- if CONST.INSTALLER_IP is None:
- logger.error("The env variable CI_INSTALLER_IP must be provided in"
+ if CONST.__getattribute__('INSTALLER_IP')is None:
+ logger.error("The env variable 'INSTALLER_IP' must be provided in"
" order to fetch the credentials from the installer.")
raise Exception("Missing CI_INSTALLER_IP.")
- if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
+ if (CONST.__getattribute__('INSTALLER_TYPE') not in
+ opnfv_constants.INSTALLERS):
logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is "
"not a valid OPNFV installer. Available "
"installers are : %s." %
- (CONST.INSTALLER_TYPE,
+ (CONST.__getattribute__('INSTALLER_TYPE'),
opnfv_constants.INSTALLERS))
raise Exception("Wrong INSTALLER_TYPE.")
cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh "
"-d %s -i %s -a %s"
- % (CONST.openstack_creds,
- CONST.INSTALLER_TYPE,
- CONST.INSTALLER_IP))
+ % (CONST.__getattribute__('openstack_creds'),
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('INSTALLER_IP')))
logger.debug("Executing command: %s" % cmd)
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
output = p.communicate()[0]
@@ -196,22 +215,23 @@ def source_rc_file():
raise Exception("Failed to fetch credentials from installer.")
else:
logger.info("RC file provided in %s."
- % CONST.openstack_creds)
- if os.path.getsize(CONST.openstack_creds) == 0:
- raise Exception("The file %s is empty." % CONST.openstack_creds)
+ % CONST.__getattribute__('openstack_creds'))
+ if os.path.getsize(CONST.__getattribute__('openstack_creds')) == 0:
+ raise Exception("The file %s is empty." %
+ CONST.__getattribute__('openstack_creds'))
logger.info("Sourcing the OpenStack RC file...")
- os_utils.source_credentials(CONST.openstack_creds)
+ os_utils.source_credentials(CONST.__getattribute__('openstack_creds'))
for key, value in os.environ.iteritems():
if re.search("OS_", key):
if key == 'OS_AUTH_URL':
- CONST.OS_AUTH_URL = value
+ CONST.__setattr__('OS_AUTH_URL', value)
elif key == 'OS_USERNAME':
- CONST.OS_USERNAME = value
+ CONST.__setattr__('OS_USERNAME', value)
elif key == 'OS_TENANT_NAME':
- CONST.OS_TENANT_NAME = value
+ CONST.__setattr__('OS_TENANT_NAME', value)
elif key == 'OS_PASSWORD':
- CONST.OS_PASSWORD = value
+ CONST.__setattr__('OS_PASSWORD', value)
def patch_config_file():
@@ -228,7 +248,7 @@ def patch_file(patch_file_path):
updated = False
for key in patch_file:
- if key in CONST.DEPLOY_SCENARIO:
+ if key in CONST.__getattribute__('DEPLOY_SCENARIO'):
new_functest_yaml = dict(ft_utils.merge_dicts(
ft_utils.get_functest_yaml(), patch_file[key]))
updated = True
@@ -243,7 +263,8 @@ def patch_file(patch_file_path):
def verify_deployment():
print_separator()
logger.info("Verifying OpenStack services...")
- cmd = ("%s/functest/ci/check_os.sh" % CONST.dir_repo_functest)
+ cmd = ("%s/functest/ci/check_os.sh" %
+ CONST.__getattribute__('dir_repo_functest'))
logger.debug("Executing command: %s" % cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
@@ -274,7 +295,7 @@ def install_rally():
cmd = "rally deployment destroy opnfv-rally"
ft_utils.execute_command(cmd, error_msg=(
"Deployment %s does not exist."
- % CONST.rally_deployment_name),
+ % CONST.__getattribute__('rally_deployment_name')),
verbose=False)
rally_conf = os_utils.get_credentials_for_rally()
@@ -282,7 +303,7 @@ def install_rally():
json.dump(rally_conf, fp)
cmd = ("rally deployment create "
"--file=rally_conf.json --name={0}"
- .format(CONST.rally_deployment_name))
+ .format(CONST.__getattribute__('rally_deployment_name')))
error_msg = "Problem while creating Rally deployment"
ft_utils.execute_command_raise(cmd, error_msg=error_msg)
@@ -304,17 +325,18 @@ def install_rally():
def install_tempest():
logger.info("Installing tempest from existing repo...")
cmd = ("rally verify list-verifiers | "
- "grep '{0}' | wc -l".format(CONST.tempest_deployment_name))
+ "grep '{0}' | wc -l".format(
+ CONST.__getattribute__('tempest_deployment_name')))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
while p.poll() is None:
line = p.stdout.readline().rstrip()
if str(line) == '0':
logger.debug("Tempest %s does not exist" %
- CONST.tempest_deployment_name)
+ CONST.__getattribute__('tempest_deployment_name'))
cmd = ("rally verify create-verifier --source {0} "
"--name {1} --type tempest --system-wide"
- .format(CONST.dir_repo_tempest,
- CONST.tempest_deployment_name))
+ .format(CONST.__getattribute__('dir_repo_tempest'),
+ CONST.__getattribute__('tempest_deployment_name')))
error_msg = "Problem while installing Tempest."
ft_utils.execute_command_raise(cmd, error_msg=error_msg)
@@ -331,10 +353,10 @@ def create_flavor():
def check_environment():
msg_not_active = "The Functest environment is not installed."
- if not os.path.isfile(CONST.env_active):
+ if not os.path.isfile(CONST.__getattribute__('env_active')):
raise Exception(msg_not_active)
- with open(CONST.env_active, "r") as env_file:
+ with open(CONST.__getattribute__('env_active'), "r") as env_file:
s = env_file.read()
if not re.search("1", s):
raise Exception(msg_not_active)
@@ -364,7 +386,7 @@ def main(**kwargs):
install_rally()
install_tempest()
create_flavor()
- with open(CONST.env_active, "w") as env_file:
+ with open(CONST.__getattribute__('env_active'), "w") as env_file:
env_file.write("1")
check_environment()
print_deployment_info()
@@ -377,6 +399,8 @@ def main(**kwargs):
if __name__ == '__main__':
+ logging.config.fileConfig(
+ CONST.__getattribute__('dir_functest_logging_cfg'))
parser = PrepareEnvParser()
args = parser.parse_args(sys.argv[1:])
sys.exit(main(**args))
diff --git a/functest/ci/rally_aarch64_patch.conf b/functest/ci/rally_aarch64_patch.conf
index a49588bf..e5cae813 100644
--- a/functest/ci/rally_aarch64_patch.conf
+++ b/functest/ci/rally_aarch64_patch.conf
@@ -1,5 +1,5 @@
img_name_regex = ^TestVM$
img_url = http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img
-flavor_ref_ram = 128
+flavor_ref_ram = 256
flavor_ref_alt_ram = 256
-heat_instance_type_ram = 128
+heat_instance_type_ram = 256
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index 37b90f92..76760096 100755
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -9,26 +9,26 @@
#
import argparse
-import datetime
import enum
import importlib
+import logging
+import logging.config
import os
import re
import sys
-import functest.ci.generate_report as generate_report
+import prettytable
+
import functest.ci.tier_builder as tb
import functest.core.testcase as testcase
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_clean as os_clean
import functest.utils.openstack_snapshot as os_snapshot
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST
-
-""" logging configuration """
-logger = ft_logger.Logger("run_tests").getLogger()
+# __name__ cannot be used here
+logger = logging.getLogger('functest.ci.run_tests')
class Result(enum.Enum):
@@ -40,6 +40,10 @@ class BlockingTestFailed(Exception):
pass
+class TestNotEnabled(Exception):
+ pass
+
+
class RunTestsParser(object):
def __init__(self):
@@ -75,7 +79,7 @@ def print_separator(str, count=45):
def source_rc_file():
- rc_file = CONST.openstack_creds
+ rc_file = CONST.__getattribute__('openstack_creds')
if not os.path.isfile(rc_file):
raise Exception("RC file %s does not exist..." % rc_file)
logger.debug("Sourcing the OpenStack RC file...")
@@ -83,13 +87,13 @@ def source_rc_file():
for key, value in os.environ.iteritems():
if re.search("OS_", key):
if key == 'OS_AUTH_URL':
- CONST.OS_AUTH_URL = value
+ CONST.__setattr__('OS_AUTH_URL', value)
elif key == 'OS_USERNAME':
- CONST.OS_USERNAME = value
+ CONST.__setattr__('OS_USERNAME', value)
elif key == 'OS_TENANT_NAME':
- CONST.OS_TENANT_NAME = value
+ CONST.__setattr__('OS_TENANT_NAME', value)
elif key == 'OS_PASSWORD':
- CONST.OS_PASSWORD = value
+ CONST.__setattr__('OS_PASSWORD', value)
def generate_os_snapshot():
@@ -100,13 +104,6 @@ def cleanup():
os_clean.main()
-def update_test_info(test_name, result, duration):
- for test in GlobalVariables.EXECUTED_TEST_CASES:
- if test['test_name'] == test_name:
- test.update({"result": result,
- "duration": duration})
-
-
def get_run_dict(testname):
try:
dict = ft_utils.get_dict_by_test(testname)
@@ -121,8 +118,9 @@ def get_run_dict(testname):
def run_test(test, tier_name, testcases=None):
- result_str = "PASS"
- start = datetime.datetime.now()
+ if not test.is_enabled():
+ raise TestNotEnabled("The test case {} is not enabled"
+ .format(test.get_name()))
test_name = test.get_name()
logger.info("\n") # blank line
print_separator("=")
@@ -144,8 +142,9 @@ def run_test(test, tier_name, testcases=None):
try:
module = importlib.import_module(run_dict['module'])
cls = getattr(module, run_dict['class'])
- test_case = cls()
-
+ test_dict = ft_utils.get_dict_by_test(test_name)
+ test_case = cls(**test_dict)
+ GlobalVariables.EXECUTED_TEST_CASES.append(test_case)
try:
kwargs = run_dict['args']
result = test_case.run(**kwargs)
@@ -154,7 +153,8 @@ def run_test(test, tier_name, testcases=None):
if result == testcase.TestCase.EX_OK:
if GlobalVariables.REPORT_FLAG:
test_case.push_to_db()
- result = test_case.check_criteria()
+ result = test_case.is_successful()
+ logger.info("Test result:\n\n%s\n", test_case)
except ImportError:
logger.exception("Cannot import module {}".format(
run_dict['module']))
@@ -166,27 +166,13 @@ def run_test(test, tier_name, testcases=None):
if test.needs_clean() and GlobalVariables.CLEAN_FLAG:
cleanup()
-
- end = datetime.datetime.now()
- duration = (end - start).seconds
- duration_str = ("%02d:%02d" % divmod(duration, 60))
- logger.info("Test execution time: %s" % duration_str)
-
- if result != 0:
+ if result != testcase.TestCase.EX_OK:
logger.error("The test case '%s' failed. " % test_name)
GlobalVariables.OVERALL_RESULT = Result.EX_ERROR
- result_str = "FAIL"
-
if test.is_blocking():
- if not testcases or testcases == "all":
- # if it is a single test we don't print the whole results table
- update_test_info(test_name, result_str, duration_str)
- generate_report.main(GlobalVariables.EXECUTED_TEST_CASES)
raise BlockingTestFailed("The test case {} failed and is blocking"
.format(test.get_name()))
- update_test_info(test_name, result_str, duration_str)
-
def run_tier(tier):
tier_name = tier.get_name()
@@ -210,27 +196,24 @@ def run_all(tiers):
for tier in tiers.get_tiers():
if (len(tier.get_tests()) != 0 and
- re.search(CONST.CI_LOOP, tier.get_ci_loop()) is not None):
+ re.search(CONST.__getattribute__('CI_LOOP'),
+ tier.get_ci_loop()) is not None):
tiers_to_run.append(tier)
summary += ("\n - %s:\n\t %s"
% (tier.get_name(),
tier.get_test_names()))
logger.info("Tests to be executed:%s" % summary)
- GlobalVariables.EXECUTED_TEST_CASES = generate_report.init(tiers_to_run)
for tier in tiers_to_run:
run_tier(tier)
- generate_report.main(GlobalVariables.EXECUTED_TEST_CASES)
-
def main(**kwargs):
- CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE
- CI_SCENARIO = CONST.DEPLOY_SCENARIO
-
file = CONST.functest_testcases_yaml
- _tiers = tb.TierBuilder(CI_INSTALLER_TYPE, CI_SCENARIO, file)
+ _tiers = tb.TierBuilder(CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ file)
if kwargs['noclean']:
GlobalVariables.CLEAN_FLAG = False
@@ -242,12 +225,10 @@ def main(**kwargs):
if kwargs['test']:
source_rc_file()
if _tiers.get_tier(kwargs['test']):
- GlobalVariables.EXECUTED_TEST_CASES = generate_report.init(
- [_tiers.get_tier(kwargs['test'])])
run_tier(_tiers.get_tier(kwargs['test']))
elif _tiers.get_test(kwargs['test']):
run_test(_tiers.get_test(kwargs['test']),
- _tiers.get_tier(kwargs['test']),
+ _tiers.get_tier_name(kwargs['test']),
kwargs['test'])
elif kwargs['test'] == "all":
run_all(_tiers)
@@ -255,7 +236,8 @@ def main(**kwargs):
logger.error("Unknown test case or tier '%s', "
"or not supported by "
"the given scenario '%s'."
- % (kwargs['test'], CI_SCENARIO))
+ % (kwargs['test'],
+ CONST.__getattribute__('DEPLOY_SCENARIO')))
logger.debug("Available tiers are:\n\n%s"
% _tiers)
return Result.EX_ERROR
@@ -264,11 +246,33 @@ def main(**kwargs):
except Exception as e:
logger.error(e)
GlobalVariables.OVERALL_RESULT = Result.EX_ERROR
+
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['env var', 'value'])
+ for env_var in ['INSTALLER_TYPE', 'DEPLOY_SCENARIO', 'BUILD_TAG',
+ 'CI_LOOP']:
+ msg.add_row([env_var, CONST.__getattribute__(env_var)])
+ logger.info("Deployment description: \n\n%s\n", msg)
+
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['test case', 'project', 'tier', 'duration', 'result'])
+ for test_case in GlobalVariables.EXECUTED_TEST_CASES:
+ result = 'PASS' if(test_case.is_successful(
+ ) == test_case.EX_OK) else 'FAIL'
+ msg.add_row([test_case.case_name, test_case.project_name,
+ _tiers.get_tier_name(test_case.case_name),
+ test_case.get_duration(), result])
+ logger.info("FUNCTEST REPORT: \n\n%s\n", msg)
+
logger.info("Execution exit value: %s" % GlobalVariables.OVERALL_RESULT)
return GlobalVariables.OVERALL_RESULT
if __name__ == '__main__':
+ logging.config.fileConfig(
+ CONST.__getattribute__('dir_functest_logging_cfg'))
parser = RunTestsParser()
args = parser.parse_args(sys.argv[1:])
sys.exit(main(**args).value)
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index 23b214bb..d98a2de2 100755..100644
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -8,8 +8,9 @@ tiers:
operations in the VIM.
testcases:
-
- name: connection_check
- criteria: 'status == "PASS"'
+ case_name: connection_check
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: false
description: >-
@@ -18,7 +19,6 @@ tiers:
simple queries. When the config value of
snaps.use_keystone is True, functest must have access to
the cloud's private network.
-
dependencies:
installer: '^((?!netvirt).)*$'
scenario: ''
@@ -27,8 +27,9 @@ tiers:
class: 'ConnectionCheck'
-
- name: api_check
- criteria: 'status == "PASS"'
+ case_name: api_check
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: false
description: >-
@@ -37,16 +38,17 @@ tiers:
simple queries. When the config value of
snaps.use_keystone is True, functest must have access to
the cloud's private network.
-
dependencies:
installer: '^((?!netvirt).)*$'
scenario: ''
run:
module: 'functest.opnfv_tests.openstack.snaps.api_check'
class: 'ApiCheck'
+
-
- name: snaps_health_check
- criteria: 'status == "PASS"'
+ case_name: snaps_health_check
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: false
description: >-
@@ -60,6 +62,7 @@ tiers:
run:
module: 'functest.opnfv_tests.openstack.snaps.health_check'
class: 'HealthCheck'
+
-
name: smoke
order: 1
@@ -68,8 +71,9 @@ tiers:
Set of basic Functional tests to validate the OPNFV scenarios.
testcases:
-
- name: vping_ssh
- criteria: 'status == "PASS"'
+ case_name: vping_ssh
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: true
description: >-
@@ -84,8 +88,9 @@ tiers:
class: 'VPingSSH'
-
- name: vping_userdata
- criteria: 'status == "PASS"'
+ case_name: vping_userdata
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: true
description: >-
@@ -99,8 +104,9 @@ tiers:
class: 'VPingUserdata'
-
- name: tempest_smoke_serial
- criteria: 'success_rate == 100%'
+ case_name: tempest_smoke_serial
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -116,8 +122,9 @@ tiers:
class: 'TempestSmokeSerial'
-
- name: rally_sanity
- criteria: 'success_rate == 100%'
+ case_name: rally_sanity
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: false
description: >-
@@ -131,8 +138,9 @@ tiers:
class: 'RallySanity'
-
- name: refstack_defcore
- criteria: 'success_rate == 100%'
+ case_name: refstack_defcore
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -146,8 +154,9 @@ tiers:
class: 'RefstackClient'
-
- name: odl
- criteria: 'success_rate == 100%'
+ case_name: odl
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: false
description: >-
@@ -166,8 +175,9 @@ tiers:
- /home/opnfv/repos/odl_test/csit/suites/openstack/neutron
-
- name: odl_netvirt
- criteria: 'success_rate == 100%'
+ case_name: odl_netvirt
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: false
description: >-
@@ -188,8 +198,9 @@ tiers:
- /home/opnfv/repos/odl_test/csit/suites/openstack/connectivity
-
- name: fds
- criteria: 'success_rate == 100%'
+ case_name: fds
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: false
description: >-
@@ -207,8 +218,9 @@ tiers:
- /home/opnfv/repos/fds/testing/robot
-
- name: onos
- criteria: 'status == "PASS"'
+ case_name: onos
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: true
description: >-
@@ -223,8 +235,9 @@ tiers:
class: 'Onos'
-
- name: snaps_smoke
- criteria: 'status == "PASS"'
+ case_name: snaps_smoke
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: false
description: >-
@@ -252,8 +265,10 @@ tiers:
integrated in functest
testcases:
-
- name: promise
- criteria: 'success_rate == 100%'
+ case_name: promise
+ enabled: false
+ project_name: promise
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -262,12 +277,16 @@ tiers:
installer: '(fuel)|(joid)'
scenario: ''
run:
- module: 'functest.opnfv_tests.features.promise'
- class: 'Promise'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/promise/promise/test/functest && python ./run_tests.py'
-
- name: doctor
- criteria: 'status == "PASS"'
+ case_name: doctor-notification
+ enabled: false
+ project_name: doctor
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -276,12 +295,16 @@ tiers:
installer: '(apex)|(fuel)'
scenario: '^((?!fdio).)*$'
run:
- module: 'functest.opnfv_tests.features.doctor'
- class: 'Doctor'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/doctor/tests && ./run.sh'
-
- name: bgpvpn
- criteria: 'status == "PASS"'
+ case_name: bgpvpn
+ enabled: false
+ project_name: sdnvpn
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -290,12 +313,16 @@ tiers:
installer: '(fuel)|(apex)|(netvirt)'
scenario: 'bgpvpn'
run:
- module: 'functest.opnfv_tests.features.sdnvpn'
- class: 'SdnVpnTests'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/sdnvpn/sdnvpn/test/functest && python ./run_tests.py'
-
- name: security_scan
- criteria: 'status == "PASS"'
+ case_name: security_scan
+ enabled: false
+ project_name: securityscanning
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -304,12 +331,34 @@ tiers:
installer: 'apex'
scenario: '^((?!fdio).)*$'
run:
- module: 'functest.opnfv_tests.features.security_scan'
- class: 'SecurityScan'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: '. /home/opnfv/functest/conf/stackrc && cd /home/opnfv/repos/securityscanning && python security_scan.py --config config.ini && cd -'
+
+ -
+ case_name: copper
+ enabled: false
+ project_name: copper
+ criteria: 100
+ blocking: false
+ clean_flag: true
+ description: >-
+ Test suite for policy management based on OpenStack Congress
+ dependencies:
+ installer: 'apex'
+ scenario: '^((?!fdio).)*$'
+ run:
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/copper/tests && bash run.sh && cd -'
-
- name: multisite
- criteria: 'success_rate == 100%'
+ case_name: multisite
+ enabled: false
+ project_name: multisite
+ criteria: 100
blocking: false
clean_flag: false
description: >-
@@ -320,9 +369,12 @@ tiers:
run:
module: 'functest.opnfv_tests.openstack.tempest.tempest'
class: 'TempestMultisite'
+
-
- name: odl-sfc
- criteria: 'status == "PASS"'
+ case_name: functest-odl-sfc
+ enabled: false
+ project_name: sfc
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -331,11 +383,16 @@ tiers:
installer: '(apex)|(fuel)'
scenario: 'odl_l2-sfc'
run:
- module: 'functest.opnfv_tests.features.odl_sfc'
- class: 'OpenDaylightSFC'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/sfc/sfc/tests/functest && python ./run_tests.py'
+
-
- name: onos_sfc
- criteria: 'status == "PASS"'
+ case_name: onos_sfc
+ enabled: false
+ project_name: functest
+ criteria: 100
blocking: true
clean_flag: true
description: >-
@@ -346,9 +403,12 @@ tiers:
run:
module: 'functest.opnfv_tests.sdn.onos.onos'
class: 'OnosSfc'
+
-
- name: parser
- criteria: 'ret == 0'
+ case_name: parser-basics
+ enabled: false
+ project_name: parser
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -357,11 +417,16 @@ tiers:
installer: 'fuel'
scenario: '^((?!bgpvpn|noha).)*$'
run:
- module: 'functest.opnfv_tests.vnf.rnc.parser'
- class: 'Parser'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/parser/tests && ./functest_run.sh'
+
-
- name: domino
- criteria: 'status == "PASS"'
+ case_name: domino-multinode
+ enabled: false
+ project_name: domino
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -370,11 +435,16 @@ tiers:
installer: ''
scenario: ''
run:
- module: 'functest.opnfv_tests.features.domino'
- class: 'Domino'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/domino && ./tests/run_multinode.sh'
+
-
- name: netready
- criteria: 'status == "PASS"'
+ case_name: gluon_vping
+ enabled: false
+ project_name: netready
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -383,11 +453,16 @@ tiers:
installer: 'apex'
scenario: 'gluon'
run:
- module: 'functest.opnfv_tests.features.netready'
- class: 'GluonVping'
+ module: 'functest.core.feature'
+ class: 'BashFeature'
+ args:
+ cmd: 'cd /home/opnfv/repos/netready/test/functest && python ./gluon-test-suite.py'
+
-
- name: barometer
- criteria: 'status == "PASS"'
+ case_name: barometercollectd
+ enabled: false
+ project_name: barometer
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -401,6 +476,7 @@ tiers:
run:
module: 'functest.opnfv_tests.features.barometer'
class: 'BarometerCollectd'
+
-
name: components
order: 3
@@ -409,8 +485,9 @@ tiers:
Extensive testing of OpenStack API.
testcases:
-
- name: tempest_full_parallel
- criteria: 'success_rate >= 80%'
+ case_name: tempest_full_parallel
+ project_name: functest
+ criteria: 80
blocking: false
clean_flag: true
description: >-
@@ -423,9 +500,11 @@ tiers:
run:
module: 'functest.opnfv_tests.openstack.tempest.tempest'
class: 'TempestFullParallel'
+
-
- name: tempest_custom
- criteria: 'success_rate == 100%'
+ case_name: tempest_custom
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -440,9 +519,11 @@ tiers:
run:
module: 'functest.opnfv_tests.openstack.tempest.tempest'
class: 'TempestCustom'
+
-
- name: rally_full
- criteria: 'success_rate >= 90%'
+ case_name: rally_full
+ project_name: functest
+ criteria: 90
blocking: false
clean_flag: false
description: >-
@@ -463,8 +544,9 @@ tiers:
Collection of VNF test cases.
testcases:
-
- name: cloudify_ims
- criteria: 'status == "PASS"'
+ case_name: cloudify_ims
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -476,22 +558,28 @@ tiers:
run:
module: 'functest.opnfv_tests.vnf.ims.cloudify_ims'
class: 'CloudifyIms'
-# -
-# name: aaa
-# criteria: 'ret == 0'
-# blocking: false
-# clean_flag: true
-# description: >-
-# Test suite from Parser project.
-# dependencies:
-# installer: ''
-# scenario: ''
-# run:
-# module: 'functest.opnfv_tests.vnf.aaa.aaa'
-# class: 'AaaVnf'
- -
- name: orchestra_ims
- criteria: 'ret == 0'
+
+ -
+ case_name: aaa
+ enabled: false
+ project_name: functest
+ criteria: 100
+ blocking: false
+ clean_flag: true
+ description: >-
+ Test suite from Parser project.
+ dependencies:
+ installer: ''
+ scenario: ''
+ run:
+ module: 'functest.opnfv_tests.vnf.aaa.aaa'
+ class: 'AaaVnf'
+
+ -
+ case_name: orchestra_ims
+ enabled: false
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
@@ -504,22 +592,26 @@ tiers:
class: 'ImsVnf'
-
- name: opera_ims
- criteria: 'status == "PASS"'
+ case_name: opera_vims
+ enabled: false
+ project_name: opera
+ criteria: 100
blocking: false
clean_flag: true
description: >-
VNF deployment with OPEN-O
dependencies:
- installer: 'unknown'
- scenario: 'unknown'
+ installer: 'compass'
+ scenario: 'os-nosdn-openo-ha'
run:
module: 'functest.opnfv_tests.vnf.ims.opera_ims'
class: 'OperaIms'
-
- name: vyos_vrouter
- criteria: 'status == "PASS"'
+ case_name: vyos_vrouter
+ enabled: false
+ project_name: functest
+ criteria: 100
blocking: false
clean_flag: true
description: >-
diff --git a/functest/ci/tier_builder.py b/functest/ci/tier_builder.py
index f4c6f70f..12562f09 100644
--- a/functest/ci/tier_builder.py
+++ b/functest/ci/tier_builder.py
@@ -46,13 +46,16 @@ class TierBuilder(object):
scenario = dic_testcase['dependencies']['scenario']
dep = th.Dependency(installer, scenario)
- testcase = th.TestCase(name=dic_testcase['name'],
+ testcase = th.TestCase(name=dic_testcase['case_name'],
+ enabled=dic_testcase.get(
+ 'enabled', True),
dependency=dep,
criteria=dic_testcase['criteria'],
blocking=dic_testcase['blocking'],
clean_flag=dic_testcase['clean_flag'],
description=dic_testcase['description'])
- if testcase.is_compatible(self.ci_installer, self.ci_scenario):
+ if (testcase.is_compatible(self.ci_installer, self.ci_scenario)
+ and testcase.is_enabled()):
tier.add_test(testcase)
self.tier_objects.append(tier)
@@ -72,6 +75,12 @@ class TierBuilder(object):
return self.tier_objects[i]
return None
+ def get_tier_name(self, test_name):
+ for i in range(0, len(self.tier_objects)):
+ if self.tier_objects[i].is_test(test_name):
+ return self.tier_objects[i].name
+ return None
+
def get_test(self, test_name):
for i in range(0, len(self.tier_objects)):
if self.tier_objects[i].is_test(test_name):
diff --git a/functest/ci/tier_handler.py b/functest/ci/tier_handler.py
index 6b4864b5..36ce245e 100644
--- a/functest/ci/tier_handler.py
+++ b/functest/ci/tier_handler.py
@@ -105,12 +105,14 @@ class Tier(object):
class TestCase(object):
def __init__(self, name,
+ enabled,
dependency,
criteria,
blocking,
clean_flag,
description=""):
self.name = name
+ self.enabled = enabled
self.dependency = dependency
self.criteria = criteria
self.blocking = blocking
@@ -138,6 +140,9 @@ class TestCase(object):
def get_name(self):
return self.name
+ def is_enabled(self):
+ return self.enabled
+
def get_criteria(self):
return self.criteria
@@ -158,7 +163,7 @@ class TestCase(object):
for line in lines:
out += ("| " + line.ljust(LINE_LENGTH - 7) + " |\n")
out += ("| Criteria: " +
- self.criteria.ljust(LINE_LENGTH - 14) + "|\n")
+ str(self.criteria).ljust(LINE_LENGTH - 14) + "|\n")
out += ("| Dependencies:".ljust(LINE_LENGTH - 1) + "|\n")
installer = self.dependency.get_installer()
scenario = self.dependency.get_scenario()
diff --git a/functest/cli/cli_base.py b/functest/cli/cli_base.py
index cc697ed7..2104e125 100644
--- a/functest/cli/cli_base.py
+++ b/functest/cli/cli_base.py
@@ -8,11 +8,14 @@
#
import click
+import logging.config
from functest.cli.commands.cli_env import CliEnv
from functest.cli.commands.cli_os import CliOpenStack
from functest.cli.commands.cli_testcase import CliTestcase
from functest.cli.commands.cli_tier import CliTier
+from functest.utils.constants import CONST
+
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@@ -20,7 +23,8 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
@click.group(context_settings=CONTEXT_SETTINGS)
@click.version_option(version='opnfv colorado.0.1 ')
def cli():
- pass
+ logging.config.fileConfig(
+ CONST.__getattribute__('dir_functest_logging_cfg'))
_env = CliEnv()
diff --git a/functest/cli/commands/cli_env.py b/functest/cli/commands/cli_env.py
index 14ad01bf..f5ba4b34 100644
--- a/functest/cli/commands/cli_env.py
+++ b/functest/cli/commands/cli_env.py
@@ -28,7 +28,7 @@ class CliEnv(object):
"it again? [y|n]\n")
while True:
if answer.lower() in ["y", "yes"]:
- os.remove(CONST.env_active)
+ os.remove(CONST.__getattribute__('env_active'))
break
elif answer.lower() in ["n", "no"]:
return
@@ -36,19 +36,19 @@ class CliEnv(object):
answer = raw_input("Invalid answer. Please type [y|n]\n")
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
ft_utils.execute_command(cmd)
def show(self):
def _get_value(attr, default='Unknown'):
return attr if attr else default
- install_type = _get_value(CONST.INSTALLER_TYPE)
- installer_ip = _get_value(CONST.INSTALLER_IP)
+ install_type = _get_value(CONST.__getattribute__('INSTALLER_TYPE'))
+ installer_ip = _get_value(CONST.__getattribute__('INSTALLER_IP'))
installer_info = ("%s, %s" % (install_type, installer_ip))
- scenario = _get_value(CONST.DEPLOY_SCENARIO)
- node = _get_value(CONST.NODE_NAME)
- repo_h = git.Repo(CONST.dir_repo_functest).head
+ scenario = _get_value(CONST.__getattribute__('DEPLOY_SCENARIO'))
+ node = _get_value(CONST.__getattribute__('NODE_NAME'))
+ repo_h = git.Repo(CONST.__getattribute__('dir_repo_functest')).head
if repo_h.is_detached:
git_branch = 'detached from FETCH_HEAD'
git_hash = repo_h.commit.hexsha
@@ -56,8 +56,8 @@ class CliEnv(object):
branch = repo_h.reference
git_branch = branch.name
git_hash = branch.commit.hexsha
- is_debug = _get_value(CONST.CI_DEBUG, 'false')
- build_tag = CONST.BUILD_TAG
+ is_debug = _get_value(CONST.__getattribute__('CI_DEBUG'), 'false')
+ build_tag = CONST.__getattribute__('BUILD_TAG')
if build_tag is not None:
build_tag = build_tag.lstrip(
"jenkins-").lstrip("functest").lstrip("-")
@@ -84,7 +84,7 @@ class CliEnv(object):
def status(self, verbose=True):
ret_val = 0
- if not os.path.isfile(CONST.env_active):
+ if not os.path.isfile(CONST.__getattribute__('env_active')):
if verbose:
click.echo("Functest environment is not installed.\n")
ret_val = 1
diff --git a/functest/cli/commands/cli_os.py b/functest/cli/commands/cli_os.py
index f85f4041..e54eb423 100644
--- a/functest/cli/commands/cli_os.py
+++ b/functest/cli/commands/cli_os.py
@@ -21,11 +21,11 @@ import functest.utils.openstack_snapshot as os_snapshot
class CliOpenStack(object):
def __init__(self):
- self.os_auth_url = CONST.OS_AUTH_URL
+ self.os_auth_url = CONST.__getattribute__('OS_AUTH_URL')
self.endpoint_ip = None
self.endpoint_port = None
- self.openstack_creds = CONST.openstack_creds
- self.snapshot_file = CONST.openstack_snapshot_file
+ self.openstack_creds = CONST.__getattribute__('openstack_creds')
+ self.snapshot_file = CONST.__getattribute__('openstack_snapshot_file')
if self.os_auth_url:
self.endpoint_ip = self.os_auth_url.rsplit("/")[2].rsplit(":")[0]
self.endpoint_port = self.os_auth_url.rsplit("/")[2].rsplit(":")[1]
@@ -59,16 +59,16 @@ class CliOpenStack(object):
else:
answer = raw_input("Invalid answer. Please type [y|n]\n")
- installer_type = CONST.INSTALLER_TYPE
+ installer_type = CONST.__getattribute__('INSTALLER_TYPE')
if installer_type is None:
click.echo("The environment variable 'INSTALLER_TYPE' is not"
"defined. Please export it")
- installer_ip = CONST.INSTALLER_IP
+ installer_ip = CONST.__getattribute__('INSTALLER_IP')
if installer_ip is None:
click.echo("The environment variable 'INSTALLER_IP' is not"
"defined. Please export it")
cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
+ % (CONST.__getattribute__('dir_repos'),
self.openstack_creds,
installer_type,
installer_ip))
@@ -78,7 +78,8 @@ class CliOpenStack(object):
def check(self):
self.ping_endpoint()
- cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
+ cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'),
+ "functest/ci/check_os.sh")
ft_utils.execute_command(cmd, verbose=False)
def snapshot_create(self):
diff --git a/functest/cli/commands/cli_testcase.py b/functest/cli/commands/cli_testcase.py
index 6644a0c2..3d3f1cb3 100644
--- a/functest/cli/commands/cli_testcase.py
+++ b/functest/cli/commands/cli_testcase.py
@@ -22,9 +22,10 @@ import functest.utils.functest_vacation as vacation
class CliTestcase(object):
def __init__(self):
- self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.functest_testcases_yaml)
+ self.tiers = tb.TierBuilder(
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('functest_testcases_yaml'))
def list(self):
summary = ""
@@ -52,12 +53,14 @@ class CliTestcase(object):
if testname == 'vacation':
vacation.main()
- elif not os.path.isfile(CONST.env_active):
+ elif not os.path.isfile(CONST.__getattribute__('env_active')):
click.echo("Functest environment is not ready. "
"Run first 'functest env prepare'")
else:
tests = testname.split(",")
for test in tests:
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, flags, test))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ flags, test))
ft_utils.execute_command(cmd)
diff --git a/functest/cli/commands/cli_tier.py b/functest/cli/commands/cli_tier.py
index 012b11d0..531f0ff9 100644
--- a/functest/cli/commands/cli_tier.py
+++ b/functest/cli/commands/cli_tier.py
@@ -21,9 +21,10 @@ import functest.utils.functest_utils as ft_utils
class CliTier(object):
def __init__(self):
- self.tiers = tb.TierBuilder(CONST.INSTALLER_TYPE,
- CONST.DEPLOY_SCENARIO,
- CONST.functest_testcases_yaml)
+ self.tiers = tb.TierBuilder(
+ CONST.__getattribute__('INSTALLER_TYPE'),
+ CONST.__getattribute__('DEPLOY_SCENARIO'),
+ CONST.__getattribute__('functest_testcases_yaml'))
def list(self):
summary = ""
@@ -62,10 +63,12 @@ class CliTier(object):
if report:
flags += "-r "
- if not os.path.isfile(CONST.env_active):
+ if not os.path.isfile(CONST.__getattribute__('env_active')):
click.echo("Functest environment is not ready. "
"Run first 'functest env prepare'")
else:
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, flags, tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ flags, tiername))
ft_utils.execute_command(cmd)
diff --git a/functest/core/feature.py b/functest/core/feature.py
index 325c10d4..140c9bb2 100644
--- a/functest/core/feature.py
+++ b/functest/core/feature.py
@@ -1,63 +1,116 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 ZTE Corp and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the parent class of all Functest Features.
+
+Feature is considered as TestCase offered by Third-party. It offers
+helpers to run any python method or any bash command.
+"""
+
+import logging
import time
-import testcase as base
+import functest.core.testcase as base
import functest.utils.functest_utils as ft_utils
-import functest.utils.functest_logger as ft_logger
from functest.utils.constants import CONST
+__author__ = ("Serena Feng <feng.xiaowei@zte.com.cn>, "
+ "Cedric Ollivier <cedric.ollivier@orange.com>")
+
class Feature(base.TestCase):
+ """Base model for single feature."""
+
+ __logger = logging.getLogger(__name__)
+
+ def __init__(self, **kwargs):
+ super(Feature, self).__init__(**kwargs)
+ self.result_file = "{}/{}.log".format(
+ CONST.__getattribute__('dir_results'), self.case_name)
+
+ def execute(self, **kwargs):
+ """Execute the Python method.
+
+ The subclasses must override the default implementation which
+ is false on purpose.
+
+ The new implementation must return 0 if success or anything
+ else if failure.
+
+ Args:
+ kwargs: Arbitrary keyword arguments.
- def __init__(self, project='functest', case='', repo='', cmd=''):
- super(Feature, self).__init__()
- self.project_name = project
- self.case_name = case
- self.cmd = cmd
- self.repo = CONST.__getattribute__(repo)
- self.result_file = self.get_result_file()
- self.logger = ft_logger.Logger(project).getLogger()
+ Returns:
+ -1.
+ """
+ # pylint: disable=unused-argument,no-self-use
+ return -1
def run(self, **kwargs):
- self.prepare()
+ """Run the feature.
+
+ It allows executing any Python method by calling execute().
+
+ It sets the following attributes required to push the results
+ to DB:
+
+ * result,
+ * start_time,
+ * stop_time.
+
+ It doesn't fulfill details when pushing the results to the DB.
+
+ Args:
+ kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ TestCase.EX_OK if execute() returns 0,
+ TestCase.EX_RUN_ERROR otherwise.
+ """
self.start_time = time.time()
- ret = self.execute()
+ exit_code = base.TestCase.EX_RUN_ERROR
+ self.result = 0
+ try:
+ if self.execute(**kwargs) == 0:
+ exit_code = base.TestCase.EX_OK
+ self.result = 100
+ ft_utils.logger_test_results(
+ self.project_name, self.case_name,
+ self.result, self.details)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception("%s FAILED", self.project_name)
+ self.__logger.info("Test result is stored in '%s'", self.result_file)
self.stop_time = time.time()
- self.post()
- self.parse_results(ret)
- self.log_results()
- self.logger.info("Test result is stored in '%s'" % self.result_file)
- return base.TestCase.EX_OK
-
- def execute(self):
- '''
- Executer method that can be overwritten
- By default it executes a shell command.
- '''
- return ft_utils.execute_command(self.cmd, output_file=self.result_file)
-
- def prepare(self, **kwargs):
- pass
-
- def post(self, **kwargs):
- pass
-
- def parse_results(self, ret):
- exit_code = base.TestCase.EX_OK
- if ret == 0:
- self.logger.info("{} OK".format(self.project_name))
- self.criteria = 'PASS'
- else:
- self.logger.info("{} FAILED".format(self.project_name))
- exit_code = base.TestCase.EX_RUN_ERROR
- self.criteria = "FAIL"
-
return exit_code
- def get_result_file(self):
- return "{}/{}.log".format(CONST.dir_results, self.project_name)
- def log_results(self):
- ft_utils.logger_test_results(self.project_name,
- self.case_name,
- self.criteria,
- self.details)
+class BashFeature(Feature):
+ """Class designed to run any bash command."""
+
+ __logger = logging.getLogger(__name__)
+
+ def execute(self, **kwargs):
+ """Execute the cmd passed as arg
+
+ Args:
+ kwargs: Arbitrary keyword arguments.
+
+ Returns:
+ 0 if cmd returns 0,
+ -1 otherwise.
+ """
+ ret = -1
+ try:
+ cmd = kwargs["cmd"]
+ ret = ft_utils.execute_command(cmd, output_file=self.result_file)
+ except KeyError:
+ self.__logger.error("Please give cmd as arg. kwargs: %s", kwargs)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.exception("Execute cmd: %s failed", cmd)
+ return ret
diff --git a/functest/core/pytest_suite_runner.py b/functest/core/pytest_suite_runner.py
index 4f777628..a6e47660 100644
--- a/functest/core/pytest_suite_runner.py
+++ b/functest/core/pytest_suite_runner.py
@@ -5,26 +5,46 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
-import testcase as base
-import unittest
+# pylint: disable=missing-docstring
+
+import logging
import time
+import unittest
+import six
-class PyTestSuiteRunner(base.TestCase):
+from functest.core import testcase
+
+
+class PyTestSuiteRunner(testcase.TestCase):
"""
This superclass is designed to execute pre-configured unittest.TestSuite()
objects
"""
- def __init__(self):
- super(PyTestSuiteRunner, self).__init__()
+
+ def __init__(self, **kwargs):
+ super(PyTestSuiteRunner, self).__init__(**kwargs)
self.suite = None
+ self.logger = logging.getLogger(__name__)
def run(self, **kwargs):
"""
Starts test execution from the functest framework
"""
+ try:
+ name = kwargs["name"]
+ try:
+ self.suite = unittest.TestLoader().loadTestsFromName(name)
+ except ImportError:
+ self.logger.error("Can not import %s", name)
+ return testcase.TestCase.EX_RUN_ERROR
+ except KeyError:
+ pass
self.start_time = time.time()
- result = unittest.TextTestRunner(verbosity=2).run(self.suite)
+ stream = six.StringIO()
+ result = unittest.TextTestRunner(
+ stream=stream, verbosity=2).run(self.suite)
+ self.logger.debug("\n\n%s", stream.getvalue())
self.stop_time = time.time()
if result.errors:
@@ -44,14 +64,14 @@ class PyTestSuiteRunner(base.TestCase):
# we shall distinguish Execution Error from FAIL results
# TestCase.EX_RUN_ERROR means that the test case was not run
# not that it was run but the result was FAIL
- exit_code = base.TestCase.EX_OK
- if ((result.errors and len(result.errors) > 0)
- or (result.failures and len(result.failures) > 0)):
- self.logger.info("%s FAILED" % self.case_name)
- self.criteria = 'FAIL'
+ exit_code = testcase.TestCase.EX_OK
+ if ((result.errors and len(result.errors) > 0) or
+ (result.failures and len(result.failures) > 0)):
+ self.logger.info("%s FAILED", self.case_name)
+ self.result = 0
else:
- self.logger.info("%s OK" % self.case_name)
- self.criteria = 'PASS'
+ self.logger.info("%s OK", self.case_name)
+ self.result = 100
self.details = {}
return exit_code
diff --git a/functest/core/testcase.py b/functest/core/testcase.py
index b540cfb5..43161525 100644
--- a/functest/core/testcase.py
+++ b/functest/core/testcase.py
@@ -7,88 +7,149 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-"""Define the parent class of Functest TestCase."""
+"""Define the parent class of all Functest TestCases."""
+import logging
import os
-import functest.utils.functest_logger as ft_logger
+import prettytable
+
import functest.utils.functest_utils as ft_utils
__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
class TestCase(object):
- """Parent class of Functest TestCase."""
+ """Base model for single test case."""
EX_OK = os.EX_OK
+ """everything is OK"""
+
EX_RUN_ERROR = os.EX_SOFTWARE
+ """run() failed"""
+
EX_PUSH_TO_DB_ERROR = os.EX_SOFTWARE - 1
+ """push_to_db() failed"""
+
EX_TESTCASE_FAILED = os.EX_SOFTWARE - 2
+ """results are false"""
- logger = ft_logger.Logger(__name__).getLogger()
+ __logger = logging.getLogger(__name__)
- def __init__(self):
+ def __init__(self, **kwargs):
self.details = {}
- self.project_name = "functest"
- self.case_name = ""
- self.criteria = ""
- self.start_time = ""
- self.stop_time = ""
+ self.project_name = kwargs.get('project_name', 'functest')
+ self.case_name = kwargs.get('case_name', '')
+ self.criteria = kwargs.get('criteria', 100)
+ self.result = 0
+ self.start_time = 0
+ self.stop_time = 0
+
+ def __str__(self):
+ try:
+ assert self.project_name
+ assert self.case_name
+ result = 'PASS' if(self.is_successful(
+ ) == TestCase.EX_OK) else 'FAIL'
+ msg = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['test case', 'project', 'duration',
+ 'result'])
+ msg.add_row([self.case_name, self.project_name,
+ self.get_duration(), result])
+ return msg.get_string()
+ except AssertionError:
+ self.__logger.error("We cannot print invalid objects")
+ return super(TestCase, self).__str__()
- def check_criteria(self):
- """Interpret the results of TestCase.
+ def get_duration(self):
+ """Return the duration of the test case.
- It allows getting the results of TestCase. It completes run()
+ Returns:
+ duration if start_time and stop_time are set
+ "XX:XX" otherwise.
+ """
+ try:
+ assert self.start_time
+ assert self.stop_time
+ if self.stop_time < self.start_time:
+ return "XX:XX"
+ return "{0[0]:02.0f}:{0[1]:02.0f}".format(divmod(
+ self.stop_time - self.start_time, 60))
+ except Exception: # pylint: disable=broad-except
+ self.__logger.error("Please run test before getting the duration")
+ return "XX:XX"
+
+ def is_successful(self):
+ """Interpret the result of the test case.
+
+ It allows getting the result of TestCase. It completes run()
which only returns the execution status.
- It can be overriden if checking criteria is not suitable.
+ It can be overriden if checking result is not suitable.
Returns:
- TestCase.EX_OK if criteria is 'PASS'.
+ TestCase.EX_OK if result is 'PASS'.
TestCase.EX_TESTCASE_FAILED otherwise.
"""
try:
assert self.criteria
- if self.criteria == 'PASS':
- return TestCase.EX_OK
+ assert self.result is not None
+ if (not isinstance(self.result, str) and
+ not isinstance(self.criteria, str)):
+ if self.result >= self.criteria:
+ return TestCase.EX_OK
+ else:
+ # Backward compatibility
+ # It must be removed as soon as TestCase subclasses
+ # stop setting result = 'PASS' or 'FAIL'.
+ # In this case criteria is unread.
+ self.__logger.warning(
+ "Please update result which must be an int!")
+ if self.result == 'PASS':
+ return TestCase.EX_OK
except AssertionError:
- self.logger.error("Please run test before checking the results")
+ self.__logger.error("Please run test before checking the results")
return TestCase.EX_TESTCASE_FAILED
def run(self, **kwargs):
- """Run TestCase.
+ """Run the test case.
It allows running TestCase and getting its execution
status.
The subclasses must override the default implementation which
- is false on purpose. The only prerequisite is to set the
- following attributes to push the results to DB:
- * case_name,
- * criteria,
+ is false on purpose.
+
+ The new implementation must set the following attributes to
+ push the results to DB:
+
+ * result,
* start_time,
* stop_time.
Args:
- **kwargs: Arbitrary keyword arguments.
+ kwargs: Arbitrary keyword arguments.
Returns:
TestCase.EX_RUN_ERROR.
"""
# pylint: disable=unused-argument
- self.logger.error("Run must be implemented")
+ self.__logger.error("Run must be implemented")
return TestCase.EX_RUN_ERROR
def push_to_db(self):
- """Push the results of TestCase to the DB.
+ """Push the results of the test case to the DB.
It allows publishing the results and to check the status.
It could be overriden if the common implementation is not
suitable. The following attributes must be set before pushing
the results to DB:
+
+ * project_name,
* case_name,
- * criteria,
+ * result,
* start_time,
* stop_time.
@@ -99,17 +160,19 @@ class TestCase(object):
try:
assert self.project_name
assert self.case_name
- assert self.criteria
assert self.start_time
assert self.stop_time
+ pub_result = 'PASS' if self.is_successful(
+ ) == TestCase.EX_OK else 'FAIL'
if ft_utils.push_results_to_db(
self.project_name, self.case_name, self.start_time,
- self.stop_time, self.criteria, self.details):
- self.logger.info("The results were successfully pushed to DB")
+ self.stop_time, pub_result, self.details):
+ self.__logger.info(
+ "The results were successfully pushed to DB")
return TestCase.EX_OK
else:
- self.logger.error("The results cannot be pushed to DB")
+ self.__logger.error("The results cannot be pushed to DB")
return TestCase.EX_PUSH_TO_DB_ERROR
except Exception: # pylint: disable=broad-except
- self.logger.exception("The results cannot be pushed to DB")
+ self.__logger.exception("The results cannot be pushed to DB")
return TestCase.EX_PUSH_TO_DB_ERROR
diff --git a/functest/core/vnf_base.py b/functest/core/vnf.py
index 3f0adcc6..5667b299 100644
--- a/functest/core/vnf_base.py
+++ b/functest/core/vnf.py
@@ -8,27 +8,31 @@
# http://www.apache.org/licenses/LICENSE-2.0
import inspect
+import logging
import time
import functest.core.testcase as base
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
-class VnfOnBoardingBase(base.TestCase):
+class VnfOnBoarding(base.TestCase):
- logger = ft_logger.Logger(__name__).getLogger()
+ __logger = logging.getLogger(__name__)
- def __init__(self, project='functest', case='', repo='', cmd=''):
- super(VnfOnBoardingBase, self).__init__()
- self.repo = repo
- self.project_name = project
- self.case_name = case
- self.cmd = cmd
+ def __init__(self, **kwargs):
+ super(VnfOnBoarding, self).__init__(**kwargs)
+ self.repo = kwargs.get('repo', '')
+ self.cmd = kwargs.get('cmd', '')
self.details = {}
- self.result_dir = CONST.dir_results
+ self.result_dir = CONST.__getattribute__('dir_results')
+ self.details_step_mapping = dict(
+ deploy_orchestrator='orchestrator',
+ deploy_vnf='vnf',
+ test_vnf='test_vnf',
+ prepare='prepare_env')
+ self.details['prepare_env'] = {}
self.details['orchestrator'] = {}
self.details['vnf'] = {}
self.details['test_vnf'] = {}
@@ -40,28 +44,28 @@ class VnfOnBoardingBase(base.TestCase):
'vnf_{}_tenant_description'.format(self.case_name))
except Exception:
# raise Exception("Unknown VNF case=" + self.case_name)
- self.logger.error("Unknown VNF case={}".format(self.case_name))
+ self.__logger.error("Unknown VNF case={}".format(self.case_name))
try:
self.images = CONST.__getattribute__(
'vnf_{}_tenant_images'.format(self.case_name))
except Exception:
- self.logger.warn("No tenant image defined for this VNF")
+ self.__logger.warn("No tenant image defined for this VNF")
def execute(self):
self.start_time = time.time()
# Prepare the test (Create Tenant, User, ...)
try:
- self.logger.info("Create VNF Onboarding environment")
+ self.__logger.info("Create VNF Onboarding environment")
self.prepare()
except Exception:
- self.logger.error("Error during VNF Onboarding environment" +
- "creation", exc_info=True)
+ self.__logger.error("Error during VNF Onboarding environment"
+ "creation", exc_info=True)
return base.TestCase.EX_TESTCASE_FAILED
# Deploy orchestrator
try:
- self.logger.info("Deploy orchestrator (if necessary)")
+ self.__logger.info("Deploy orchestrator (if necessary)")
orchestrator_ready_time = time.time()
res_orchestrator = self.deploy_orchestrator()
# orchestrator is not mandatory
@@ -73,11 +77,11 @@ class VnfOnBoardingBase(base.TestCase):
self.details['orchestrator']['duration'] = round(
orchestrator_ready_time - self.start_time, 1)
except Exception:
- self.logger.warn("Problem with the Orchestrator", exc_info=True)
+ self.__logger.warn("Problem with the Orchestrator", exc_info=True)
# Deploy VNF
try:
- self.logger.info("Deploy VNF " + self.case_name)
+ self.__logger.info("Deploy VNF " + self.case_name)
res_deploy_vnf = self.deploy_vnf()
vnf_ready_time = time.time()
self.details['vnf']['status'] = res_deploy_vnf['status']
@@ -85,12 +89,12 @@ class VnfOnBoardingBase(base.TestCase):
self.details['vnf']['duration'] = round(
vnf_ready_time - orchestrator_ready_time, 1)
except Exception:
- self.logger.error("Error during VNF deployment", exc_info=True)
+ self.__logger.error("Error during VNF deployment", exc_info=True)
return base.TestCase.EX_TESTCASE_FAILED
# Test VNF
try:
- self.logger.info("Test VNF")
+ self.__logger.info("Test VNF")
res_test_vnf = self.test_vnf()
test_vnf_done_time = time.time()
self.details['test_vnf']['status'] = res_test_vnf['status']
@@ -98,7 +102,7 @@ class VnfOnBoardingBase(base.TestCase):
self.details['test_vnf']['duration'] = round(
test_vnf_done_time - vnf_ready_time, 1)
except Exception:
- self.logger.error("Error when running VNF tests", exc_info=True)
+ self.__logger.error("Error when running VNF tests", exc_info=True)
return base.TestCase.EX_TESTCASE_FAILED
# Clean the system
@@ -111,59 +115,57 @@ class VnfOnBoardingBase(base.TestCase):
# prepare state could consist in the creation of the resources
# a dedicated user
- # a dedictaed tenant
+ # a dedicated tenant
# dedicated images
def prepare(self):
self.creds = os_utils.get_credentials()
self.keystone_client = os_utils.get_keystone_client()
- self.logger.info("Prepare OpenStack plateform(create tenant and user)")
+ self.__logger.info(
+ "Prepare OpenStack plateform(create tenant and user)")
admin_user_id = os_utils.get_user_id(self.keystone_client,
self.creds['username'])
- if admin_user_id == '':
- self.step_failure("Failed to get id of " +
- self.creds['username'])
+ if not admin_user_id:
+ self.step_failure("Failed to get id of {0}".format(
+ self.creds['username']))
- tenant_id = os_utils.create_tenant(
- self.keystone_client, self.tenant_name, self.tenant_description)
+ tenant_id = os_utils.get_tenant_id(self.keystone_client,
+ self.tenant_name)
if not tenant_id:
- self.step_failure("Failed to create " +
- self.tenant_name + " tenant")
-
- roles_name = ["admin", "Admin"]
- role_id = ''
- for role_name in roles_name:
- if role_id == '':
- role_id = os_utils.get_role_id(self.keystone_client, role_name)
-
- if role_id == '':
- self.logger.error("Failed to get id for %s role" % role_name)
- self.step_failure("Failed to get role id of " + role_name)
-
- if not os_utils.add_role_user(self.keystone_client, admin_user_id,
- role_id, tenant_id):
- self.logger.error("Failed to add %s on tenant" %
- self.creds['username'])
- self.step_failure("Failed to add %s on tenant" %
- self.creds['username'])
-
- user_id = os_utils.create_user(self.keystone_client,
- self.tenant_name,
- self.tenant_name,
- None,
- tenant_id)
+ tenant_id = os_utils.create_tenant(self.keystone_client,
+ self.tenant_name,
+ self.tenant_description)
+ if not tenant_id:
+ self.step_failure("Failed to get or create {0} tenant".format(
+ self.tenant_name))
+ roles_name = ["admin", "Admin"]
+ role_id = ''
+ for role_name in roles_name:
+ if not role_id:
+ role_id = os_utils.get_role_id(self.keystone_client,
+ role_name)
+
+ if not role_id:
+ self.step_failure("Failed to get id for {0} role".format(
+ role_name))
+
+ if not os_utils.add_role_user(self.keystone_client, admin_user_id,
+ role_id, tenant_id):
+ self.step_failure("Failed to add {0} on tenant".format(
+ self.creds['username']))
+
+ user_id = os_utils.get_or_create_user(self.keystone_client,
+ self.tenant_name,
+ self.tenant_name,
+ tenant_id)
if not user_id:
- self.logger.error("Failed to create %s user" % self.tenant_name)
- self.step_failure("Failed to create user ")
+ self.step_failure("Failed to get or create {0} user".format(
+ self.tenant_name))
- if not os_utils.add_role_user(self.keystone_client, user_id,
- role_id, tenant_id):
- self.logger.error("Failed to add %s on tenant" %
- self.tenant_name)
- self.step_failure("Failed to add %s on tenant" %
- self.tenant_name)
+ os_utils.add_role_user(self.keystone_client, user_id,
+ role_id, tenant_id)
- self.logger.info("Update OpenStack creds informations")
+ self.__logger.info("Update OpenStack creds informations")
self.admin_creds = self.creds.copy()
self.admin_creds.update({
"tenant": self.tenant_name
@@ -176,66 +178,46 @@ class VnfOnBoardingBase(base.TestCase):
"password": self.tenant_name,
})
- # orchestrator is not mandatory to dpeloy and test VNF
+ # orchestrator is not mandatory to deploy and test VNF
def deploy_orchestrator(self, **kwargs):
pass
# TODO see how to use built-in exception from releng module
def deploy_vnf(self):
- self.logger.error("VNF must be deployed")
+ self.__logger.error("VNF must be deployed")
raise Exception("VNF not deployed")
def test_vnf(self):
- self.logger.error("VNF must be tested")
+ self.__logger.error("VNF must be tested")
raise Exception("VNF not tested")
+ # clean before openstack clean run
def clean(self):
- self.logger.info("test cleaning")
-
- self.logger.info("Removing %s tenant .." % self.tenant_name)
- tenant_id = os_utils.get_tenant_id(self.keystone_client,
- self.tenant_name)
- if tenant_id == '':
- self.logger.error("Error : Failed to get id of %s tenant" %
- self.tenant_name)
- else:
- if not os_utils.delete_tenant(self.keystone_client, tenant_id):
- self.logger.error("Error : Failed to remove %s tenant" %
- self.tenant_name)
-
- self.logger.info("Removing %s user .." % self.tenant_name)
- user_id = os_utils.get_user_id(
- self.keystone_client, self.tenant_name)
- if user_id == '':
- self.logger.error("Error : Failed to get id of %s user" %
- self.tenant_name)
- else:
- if not os_utils.delete_user(self.keystone_client, user_id):
- self.logger.error("Error : Failed to remove %s user" %
- self.tenant_name)
+ self.__logger.info("test cleaning")
def parse_results(self):
exit_code = self.EX_OK
- self.criteria = "PASS"
- self.logger.info(self.details)
+ self.result = "PASS"
+ self.__logger.info(self.details)
# The 2 VNF steps must be OK to get a PASS result
if (self.details['vnf']['status'] is not "PASS" or
self.details['test_vnf']['status'] is not "PASS"):
exit_code = self.EX_RUN_ERROR
- self.criteria = "FAIL"
+ self.result = "FAIL"
return exit_code
def log_results(self):
ft_utils.logger_test_results(self.project_name,
self.case_name,
- self.criteria,
+ self.result,
self.details)
def step_failure(self, error_msg):
part = inspect.stack()[1][3]
- self.logger.error("Step '%s' failed: %s", part, error_msg)
+ self.__logger.error("Step {0} failed: {1}".format(part, error_msg))
try:
- part_info = self.details[part]
+ step_name = self.details_step_mapping[part]
+ part_info = self.details[step_name]
except KeyError:
self.details[part] = {}
part_info = self.details[part]
diff --git a/functest/opnfv_tests/vnf/rnc/__init__.py b/functest/energy/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/opnfv_tests/vnf/rnc/__init__.py
+++ b/functest/energy/__init__.py
diff --git a/functest/energy/energy.py b/functest/energy/energy.py
new file mode 100644
index 00000000..a20c7992
--- /dev/null
+++ b/functest/energy/energy.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""This module manages calls to Energy recording API."""
+
+import json
+import logging
+import urllib
+import requests
+
+import functest.utils.functest_utils as ft_utils
+
+
+def enable_recording(method):
+ """
+ Decorator to record energy during "method" exection.
+
+ param method: Method to suround with start and stop
+ :type method: function
+
+ .. note:: "method" should belong to a class having a "case_name"
+ attribute
+ """
+ def wrapper(*args):
+ """Wrapper for decorator to handle method arguments."""
+ EnergyRecorder.start(args[0].case_name)
+ return_value = method(*args)
+ EnergyRecorder.stop()
+ return return_value
+ return wrapper
+
+
+# Class to manage energy recording sessions
+class EnergyRecorder(object):
+ """Manage Energy recording session."""
+
+ logger = logging.getLogger(__name__)
+ # Energy recording API connectivity settings
+ # see load_config method
+ energy_recorder_api = None
+
+ # Default initial step
+ INITIAL_STEP = "starting"
+
+ @staticmethod
+ def load_config():
+ """
+ Load connectivity settings from yaml.
+
+ Load connectivity settings to Energy recording API
+ Use functest global config yaml file
+ (see functest_utils.get_functest_config)
+ """
+ # Singleton pattern for energy_recorder_api static member
+ # Load only if not previouly done
+ if EnergyRecorder.energy_recorder_api is None:
+ environment = ft_utils.get_pod_name()
+
+ # API URL
+ energy_recorder_uri = ft_utils.get_functest_config(
+ "energy_recorder.api_url")
+ assert energy_recorder_uri
+ assert environment
+
+ energy_recorder_uri += "/recorders/environment/"
+ energy_recorder_uri += urllib.quote_plus(environment)
+ EnergyRecorder.logger.debug(
+ "API recorder at: " + energy_recorder_uri)
+
+ # Creds
+ user = ft_utils.get_functest_config(
+ "energy_recorder.api_user")
+ password = ft_utils.get_functest_config(
+ "energy_recorder.api_password")
+
+ if user != "" and password != "":
+ energy_recorder_api_auth = (user, password)
+ else:
+ energy_recorder_api_auth = None
+
+ # Final config
+ EnergyRecorder.energy_recorder_api = {
+ "uri": energy_recorder_uri,
+ "auth": energy_recorder_api_auth
+ }
+
+ @staticmethod
+ def start(scenario):
+ """
+ Start a recording session for scenario.
+
+ param scenario: Starting scenario
+ :type scenario: string
+ """
+ return_status = True
+ try:
+ EnergyRecorder.logger.debug("Starting recording")
+ # Ensure that connectyvity settings are loaded
+ EnergyRecorder.load_config()
+
+ # Create API payload
+ payload = {
+ "step": EnergyRecorder.INITIAL_STEP,
+ "scenario": scenario
+ }
+ # Call API to start energy recording
+ response = requests.post(
+ EnergyRecorder.energy_recorder_api["uri"],
+ data=json.dumps(payload),
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers={
+ 'content-type': 'application/json'
+ }
+ )
+ if response.status_code != 200:
+ log_msg = "Error while starting energy recording session\n{}"
+ log_msg = log_msg.format(response.text)
+ EnergyRecorder.logger.info(log_msg)
+ return_status = False
+
+ except Exception: # pylint: disable=broad-except
+ # Default exception handler to ensure that method
+ # is safe for caller
+ EnergyRecorder.logger.exception(
+ "Error while starting energy recorder API"
+ )
+ return_status = False
+ return return_status
+
+ @staticmethod
+ def stop():
+ """Stop current recording session."""
+ EnergyRecorder.logger.debug("Stopping recording")
+ return_status = True
+ try:
+ # Ensure that connectyvity settings are loaded
+ EnergyRecorder.load_config()
+
+ # Call API to stop energy recording
+ response = requests.delete(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers={
+ 'content-type': 'application/json'
+ }
+ )
+ if response.status_code != 200:
+ log_msg = "Error while stating energy recording session\n{}"
+ log_msg = log_msg.format(response.text)
+ EnergyRecorder.logger.error(log_msg)
+ return_status = False
+ except Exception: # pylint: disable=broad-except
+ # Default exception handler to ensure that method
+ # is safe for caller
+ EnergyRecorder.logger.exception(
+ "Error while stoping energy recorder API"
+ )
+ return_status = False
+ return return_status
+
+ @staticmethod
+ def set_step(step):
+ """Notify energy recording service of current step of the testcase."""
+ EnergyRecorder.logger.debug("Setting step")
+ return_status = True
+ try:
+ # Ensure that connectyvity settings are loaded
+ EnergyRecorder.load_config()
+
+ # Create API payload
+ payload = {
+ "step": step,
+ }
+
+ # Call API to define step
+ response = requests.post(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ data=json.dumps(payload),
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers={
+ 'content-type': 'application/json'
+ }
+ )
+ if response.status_code != 200:
+ log_msg = "Error while setting current step of testcase\n{}"
+ log_msg = log_msg.format(response.text)
+ EnergyRecorder.logger.error(log_msg)
+ return_status = False
+ except Exception: # pylint: disable=broad-except
+ # Default exception handler to ensure that method
+ # is safe for caller
+ EnergyRecorder.logger.exception(
+ "Error while setting step on energy recorder API"
+ )
+ return_status = False
+ return return_status
diff --git a/functest/opnfv_tests/features/barometer.py b/functest/opnfv_tests/features/barometer.py
index 6011340f..cbfe7d9a 100644
--- a/functest/opnfv_tests/features/barometer.py
+++ b/functest/opnfv_tests/features/barometer.py
@@ -6,6 +6,8 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
+import logging
+
from baro_tests import collectd
import functest.core.feature as base
@@ -16,10 +18,7 @@ class BarometerCollectd(base.Feature):
Class for executing barometercollectd testcase.
'''
- def __init__(self):
- super(BarometerCollectd, self).__init__(project='barometer',
- case='barometercollectd',
- repo='dir_repo_barometer')
+ __logger = logging.getLogger(__name__)
def execute(self):
- return collectd.main(self.logger)
+ return collectd.main(self.__logger)
diff --git a/functest/opnfv_tests/features/copper.py b/functest/opnfv_tests/features/copper.py
deleted file mode 100644
index 689341ea..00000000
--- a/functest/opnfv_tests/features/copper.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 AT&T Intellectual Property, Inc
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import functest.core.feature as base
-
-
-class Copper(base.Feature):
- def __init__(self):
- super(Copper, self).__init__(project='copper',
- case='copper-notification',
- repo='dir_repo_copper')
- self.cmd = 'cd %s/tests && bash run.sh && cd -' % self.repo
diff --git a/functest/opnfv_tests/features/doctor.py b/functest/opnfv_tests/features/doctor.py
deleted file mode 100644
index d32bbfc9..00000000
--- a/functest/opnfv_tests/features/doctor.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2017 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# 0.1: This script boots the VM1 and allocates IP address from Nova
-# Later, the VM2 boots then execute cloud-init to ping VM1.
-# After successful ping, both the VMs are deleted.
-# 0.2: measure test duration and publish results under json format
-#
-#
-import functest.core.feature as base
-
-
-class Doctor(base.Feature):
- def __init__(self):
- super(Doctor, self).__init__(project='doctor',
- case='doctor-notification',
- repo='dir_repo_doctor')
- self.cmd = 'cd %s/tests && ./run.sh' % self.repo
diff --git a/functest/opnfv_tests/features/domino.py b/functest/opnfv_tests/features/domino.py
deleted file mode 100644
index e34429bc..00000000
--- a/functest/opnfv_tests/features/domino.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# 0.1: This script boots the VM1 and allocates IP address from Nova
-# Later, the VM2 boots then execute cloud-init to ping VM1.
-# After successful ping, both the VMs are deleted.
-# 0.2: measure test duration and publish results under json format
-# 0.3: add report flag to push results when needed
-# 0.4: refactoring to match Test abstraction class
-
-import functest.core.feature as base
-
-
-class Domino(base.Feature):
- def __init__(self):
- super(Domino, self).__init__(project='domino',
- case='domino-multinode',
- repo='dir_repo_domino')
- self.cmd = 'cd %s && ./tests/run_multinode.sh' % self.repo
diff --git a/functest/opnfv_tests/features/netready.py b/functest/opnfv_tests/features/netready.py
deleted file mode 100644
index 88f377c2..00000000
--- a/functest/opnfv_tests/features/netready.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-
-#
-import functest.core.feature as base
-
-
-class GluonVping(base.Feature):
-
- def __init__(self):
- super(GluonVping, self).__init__(project='netready',
- case='gluon_vping',
- repo='dir_repo_netready')
- dir_netready_functest = '{}/test/functest'.format(self.repo)
- self.cmd = ('cd %s && python ./gluon-test-suite.py' %
- dir_netready_functest)
diff --git a/functest/opnfv_tests/features/odl_sfc.py b/functest/opnfv_tests/features/odl_sfc.py
deleted file mode 100644
index fff7f2b0..00000000
--- a/functest/opnfv_tests/features/odl_sfc.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-import functest.core.feature as base
-
-
-class OpenDaylightSFC(base.Feature):
-
- def __init__(self):
- super(OpenDaylightSFC, self).__init__(project='sfc',
- case='functest-odl-sfc',
- repo='dir_repo_sfc')
- dir_sfc_functest = '{}/sfc/tests/functest'.format(self.repo)
- self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
diff --git a/functest/opnfv_tests/features/promise.py b/functest/opnfv_tests/features/promise.py
deleted file mode 100644
index a7f4e628..00000000
--- a/functest/opnfv_tests/features/promise.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-import functest.core.feature as base
-
-
-class Promise(base.Feature):
- def __init__(self):
- super(Promise, self).__init__(project='promise',
- case='promise',
- repo='dir_repo_promise')
- dir_promise_functest = '{}/promise/test/functest'.format(self.repo)
- self.cmd = 'cd %s && python ./run_tests.py' % dir_promise_functest
diff --git a/functest/opnfv_tests/features/sdnvpn.py b/functest/opnfv_tests/features/sdnvpn.py
deleted file mode 100644
index 10e3146c..00000000
--- a/functest/opnfv_tests/features/sdnvpn.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2016 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-import functest.core.feature as base
-
-
-class SdnVpnTests(base.Feature):
-
- def __init__(self):
- super(SdnVpnTests, self).__init__(project='sdnvpn',
- case='bgpvpn',
- repo='dir_repo_sdnvpn')
- dir_sfc_functest = '{}/sdnvpn/test/functest'.format(self.repo)
- self.cmd = 'cd %s && python ./run_tests.py' % dir_sfc_functest
diff --git a/functest/opnfv_tests/features/security_scan.py b/functest/opnfv_tests/features/security_scan.py
deleted file mode 100644
index 2374b39f..00000000
--- a/functest/opnfv_tests/features/security_scan.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-
-import functest.core.feature as base
-from functest.utils.constants import CONST
-
-
-class SecurityScan(base.Feature):
- def __init__(self):
- super(SecurityScan, self).__init__(project='securityscanning',
- case='security_scan',
- repo='dir_repo_securityscan')
- self.cmd = ('. {0}/stackrc && '
- 'cd {1} && '
- 'python security_scan.py --config config.ini && '
- 'cd -'.format(CONST.dir_functest_conf,
- self.repo))
diff --git a/functest/opnfv_tests/mano/orchestra.py b/functest/opnfv_tests/mano/orchestra.py
index a9cf0ae6..dea26efc 100644
--- a/functest/opnfv_tests/mano/orchestra.py
+++ b/functest/opnfv_tests/mano/orchestra.py
@@ -16,9 +16,12 @@ import functest.core.feature as base
class Orchestra(base.Feature):
- def __init__(self):
- super(Orchestra, self).__init__(project='orchestra',
- case='orchestra',
- repo='dir_repo_orchestra')
+ def __init__(self, **kwargs):
+ if "project_name" not in kwargs:
+ kwargs["project_name"] = "orchestra"
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "orchestra"
+ kwargs['repo'] = 'dir_repo_orchestra'
+ super(Orchestra, self).__init__(**kwargs)
# TODO
# self.cmd = "%s/tests/run.sh %s/tests" % (self.repo, self.repo)
diff --git a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py b/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py
deleted file mode 100755
index b4400864..00000000
--- a/functest/opnfv_tests/openstack/examples/create_instance_and_ip.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (c) 2015 All rights reserved
-# This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# This script boots an instance and assigns a floating ip
-#
-
-import argparse
-import os
-import sys
-
-from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
-import functest.utils.openstack_utils as os_utils
-
-parser = argparse.ArgumentParser()
-
-parser.add_argument("-r", "--report",
- help="Create json result file",
- action="store_true")
-
-args = parser.parse_args()
-
-""" logging configuration """
-logger = ft_logger.Logger("create_instance_and_ip").getLogger()
-
-HOME = CONST.dir_home + "/"
-
-VM_BOOT_TIMEOUT = 180
-
-EXAMPLE_INSTANCE_NAME = CONST.example_vm_name
-EXAMPLE_FLAVOR = CONST.example_flavor
-EXAMPLE_IMAGE_NAME = CONST.example_image_name
-IMAGE_FILENAME = CONST.openstack_image_file_name
-IMAGE_FORMAT = CONST.openstack_image_disk_format
-IMAGE_PATH = os.path.join(CONST.dir_functest_data, IMAGE_FILENAME)
-
-# NEUTRON Private Network parameters
-
-EXAMPLE_PRIVATE_NET_NAME = CONST.example_private_net_name
-EXAMPLE_PRIVATE_SUBNET_NAME = CONST.example_private_subnet_name
-EXAMPLE_PRIVATE_SUBNET_CIDR = CONST.example_private_subnet_cidr
-EXAMPLE_ROUTER_NAME = CONST.example_router_name
-
-EXAMPLE_SECGROUP_NAME = CONST.example_sg_name
-EXAMPLE_SECGROUP_DESCR = CONST.example_sg_desc
-
-
-def main():
-
- nova_client = os_utils.get_nova_client()
- neutron_client = os_utils.get_neutron_client()
- glance_client = os_utils.get_glance_client()
-
- image_id = os_utils.create_glance_image(glance_client,
- EXAMPLE_IMAGE_NAME,
- IMAGE_PATH,
- disk=IMAGE_FORMAT,
- container="bare",
- public=True)
-
- network_dic = os_utils.create_network_full(
- neutron_client,
- EXAMPLE_PRIVATE_NET_NAME,
- EXAMPLE_PRIVATE_SUBNET_NAME,
- EXAMPLE_ROUTER_NAME,
- EXAMPLE_PRIVATE_SUBNET_CIDR)
- if not network_dic:
- logger.error(
- "There has been a problem when creating the neutron network")
- sys.exit(-1)
-
- network_id = network_dic["net_id"]
-
- sg_id = os_utils.create_security_group_full(neutron_client,
- EXAMPLE_SECGROUP_NAME,
- EXAMPLE_SECGROUP_DESCR)
-
- # boot INTANCE
- logger.info("Creating instance '%s'..." % EXAMPLE_INSTANCE_NAME)
- logger.debug(
- "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
- "network=%s \n"
- % (EXAMPLE_INSTANCE_NAME, EXAMPLE_FLAVOR, image_id, network_id))
- instance = os_utils.create_instance_and_wait_for_active(
- EXAMPLE_FLAVOR,
- image_id,
- network_id,
- EXAMPLE_INSTANCE_NAME)
-
- if instance is None:
- logger.error("Error while booting instance.")
- sys.exit(-1)
- # Retrieve IP of INSTANCE
- instance_ip = instance.networks.get(EXAMPLE_PRIVATE_NET_NAME)[0]
- logger.debug("Instance '%s' got private ip '%s'." %
- (EXAMPLE_INSTANCE_NAME, instance_ip))
-
- logger.info("Adding '%s' to security group '%s'..."
- % (EXAMPLE_INSTANCE_NAME, EXAMPLE_SECGROUP_NAME))
- os_utils.add_secgroup_to_instance(nova_client, instance.id, sg_id)
-
- logger.info("Creating floating IP for VM '%s'..." % EXAMPLE_INSTANCE_NAME)
- floatip_dic = os_utils.create_floating_ip(neutron_client)
- floatip = floatip_dic['fip_addr']
- # floatip_id = floatip_dic['fip_id']
-
- if floatip is None:
- logger.error("Cannot create floating IP.")
- sys.exit(-1)
- logger.info("Floating IP created: '%s'" % floatip)
-
- logger.info("Associating floating ip: '%s' to VM '%s' "
- % (floatip, EXAMPLE_INSTANCE_NAME))
- if not os_utils.add_floating_ip(nova_client, instance.id, floatip):
- logger.error("Cannot associate floating IP to VM.")
- sys.exit(-1)
-
- sys.exit(0)
-
-
-if __name__ == '__main__':
- main()
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 8c6abc15..40f8386c 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -8,7 +8,10 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
+from __future__ import division
+
import json
+import logging
import os
import re
import subprocess
@@ -19,11 +22,9 @@ import yaml
from functest.core import testcase
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
-import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
-logger = ft_logger.Logger('Rally').getLogger()
+logger = logging.getLogger(__name__)
class RallyBase(testcase.TestCase):
@@ -31,7 +32,7 @@ class RallyBase(testcase.TestCase):
'neutron', 'nova', 'quotas', 'requests', 'vm', 'all']
GLANCE_IMAGE_NAME = CONST.openstack_image_name
GLANCE_IMAGE_FILENAME = CONST.openstack_image_file_name
- GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data,
+ GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images,
GLANCE_IMAGE_FILENAME)
GLANCE_IMAGE_FORMAT = CONST.openstack_image_disk_format
FLAVOR_NAME = "m1.tiny"
@@ -56,8 +57,8 @@ class RallyBase(testcase.TestCase):
RALLY_PRIVATE_SUBNET_CIDR = CONST.rally_subnet_cidr
RALLY_ROUTER_NAME = CONST.rally_router_name
- def __init__(self):
- super(RallyBase, self).__init__()
+ def __init__(self, **kwargs):
+ super(RallyBase, self).__init__(**kwargs)
self.mode = ''
self.summary = []
self.scenario_dir = ''
@@ -480,11 +481,12 @@ class RallyBase(testcase.TestCase):
total_duration_str2 = "{0:<10}".format(total_duration_str)
total_nb_tests_str = "{0:<13}".format(total_nb_tests)
- if len(self.summary):
- success_rate = total_success / len(self.summary)
- else:
- success_rate = 100
- success_rate = "{:0.2f}".format(success_rate)
+ try:
+ self.result = total_success / len(self.summary)
+ except ZeroDivisionError:
+ self.result = 100
+
+ success_rate = "{:0.2f}".format(self.result)
success_rate_str = "{0:<10}".format(str(success_rate) + '%')
report += ("+===================+============"
"+===============+===========+")
@@ -500,12 +502,10 @@ class RallyBase(testcase.TestCase):
'nb tests': total_nb_tests,
'nb success': success_rate}})
- self.criteria = ft_utils.check_success_rate(
- self.case_name, success_rate)
self.details = payload
- logger.info("Rally '%s' success_rate is %s%%, is marked as %s"
- % (self.case_name, success_rate, self.criteria))
+ logger.info("Rally '%s' success_rate is %s%%"
+ % (self.case_name, success_rate))
def _clean_up(self):
if self.volume_type:
@@ -536,9 +536,10 @@ class RallyBase(testcase.TestCase):
class RallySanity(RallyBase):
- def __init__(self):
- super(RallySanity, self).__init__()
- self.case_name = 'rally_sanity'
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "rally_sanity"
+ super(RallySanity, self).__init__(**kwargs)
self.mode = 'sanity'
self.test_name = 'all'
self.smoke = True
@@ -546,9 +547,10 @@ class RallySanity(RallyBase):
class RallyFull(RallyBase):
- def __init__(self):
- super(RallyFull, self).__init__()
- self.case_name = 'rally_full'
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "rally_full"
+ super(RallyFull, self).__init__(**kwargs)
self.mode = 'full'
self.test_name = 'all'
self.smoke = False
diff --git a/functest/opnfv_tests/openstack/refstack_client/defcore.txt b/functest/opnfv_tests/openstack/refstack_client/defcore.txt
index be8fd899..0a1787ef 100644
--- a/functest/opnfv_tests/openstack/refstack_client/defcore.txt
+++ b/functest/opnfv_tests/openstack/refstack_client/defcore.txt
@@ -1,4 +1,11 @@
-# Set of DefCore tempest test cases not flagged and required. It only contains OpenStack core (no object storage)
+# Set of DefCore tempest test cases not flagged and required.
+# According to https://github.com/openstack/interop/blob/master/2016.08/procedure.rst,
+# some tests are still flagged due to outstanding bugs in the Tempest library,
+# particularly tests that require SSH. Refstack developers
+# are working on correcting these bugs upstream. Please note that although some tests
+# are flagged because of bugs, there is still an expectation that the capabilities
+# covered by the tests are available.
+# It only contains Openstack core compute (no object storage)
# The approved guidelines (2016.08) are valid for Kilo, Liberty, Mitaka and Newton releases of OpenStack
# The list can be generated using the Rest API from RefStack project:
# https://refstack.openstack.org/api/v1/guidelines/2016.08/tests?target=compute&type=required&alias=true&flag=false
diff --git a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
index 37aa9e39..2a2718dd 100755
--- a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
+++ b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
@@ -5,7 +5,12 @@
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
+
+from __future__ import division
+
+
import argparse
+import logging
import os
import re
import sys
@@ -15,19 +20,19 @@ import time
from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
from tempest_conf import TempestConf
""" logging configuration """
-logger = ft_logger.Logger("refstack_defcore").getLogger()
+logger = logging.getLogger(__name__)
class RefstackClient(testcase.TestCase):
- def __init__(self):
- super(RefstackClient, self).__init__()
- self.case_name = "refstack_defcore"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "refstack_defcore"
+ super(RefstackClient, self).__init__(**kwargs)
self.FUNCTEST_TEST = CONST.dir_functest_test
self.CONF_PATH = CONST.refstack_tempest_conf_path
self.DEFCORE_LIST = CONST.refstack_defcore_list
@@ -122,7 +127,11 @@ class RefstackClient(testcase.TestCase):
skipped_testcases += match + ", "
num_executed = int(num_tests) - int(num_skipped)
- success_rate = 100 * int(num_success) / int(num_executed)
+
+ try:
+ self.result = 100 * int(num_success) / int(num_executed)
+ except ZeroDivisionError:
+ logger.error("No test has been executed")
self.details = {"tests": int(num_tests),
"failures": int(num_failures),
@@ -130,12 +139,10 @@ class RefstackClient(testcase.TestCase):
"errors": failed_testcases,
"skipped": skipped_testcases}
except Exception:
- success_rate = 0
+ self.result = 0
- self.criteria = ft_utils.check_success_rate(
- self.case_name, success_rate)
- logger.info("Testcase %s success_rate is %s%%, is marked as %s"
- % (self.case_name, success_rate, self.criteria))
+ logger.info("Testcase %s success_rate is %s%%"
+ % (self.case_name, self.result))
def run(self):
'''used for functest command line,
@@ -170,7 +177,7 @@ class RefstackClient(testcase.TestCase):
'''used for manually running,
python refstack_client.py -c <tempest_conf_path>
--testlist <testlist_path>
- can generate a reference tempest.conf by
+ can generate a reference refstack_tempest.conf by
python tempest_conf.py
'''
try:
@@ -192,10 +199,9 @@ class RefstackClient(testcase.TestCase):
return res
-class RefstackClientParser(testcase.TestCase):
+class RefstackClientParser(object):
def __init__(self):
- super(RefstackClientParser, self).__init__()
self.FUNCTEST_TEST = CONST.dir_functest_test
self.CONF_PATH = CONST.refstack_tempest_conf_path
self.DEFCORE_LIST = CONST.refstack_defcore_list
@@ -206,7 +212,7 @@ class RefstackClientParser(testcase.TestCase):
self.parser = argparse.ArgumentParser()
self.parser.add_argument(
'-c', '--config',
- help='the file path of tempest.conf',
+ help='the file path of refstack_tempest.conf',
default=self.confpath)
self.parser.add_argument(
'-t', '--testlist',
@@ -220,6 +226,7 @@ class RefstackClientParser(testcase.TestCase):
if __name__ == '__main__':
+ logging.basicConfig()
refstackclient = RefstackClient()
parser = RefstackClientParser()
args = parser.parse_args(sys.argv[1:])
diff --git a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
index 5624ed79..5c04253c 100755
--- a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
+++ b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
@@ -5,16 +5,15 @@
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-import sys
+import logging
+import os
-from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils import openstack_utils
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
""" logging configuration """
-logger = ft_logger.Logger("refstack_defcore").getLogger()
+logger = logging.getLogger(__name__)
class TempestConf(object):
@@ -25,6 +24,8 @@ class TempestConf(object):
self.DEPLOYMENT_ID = conf_utils.get_verifier_deployment_id()
self.DEPLOYMENT_DIR = conf_utils.get_verifier_deployment_dir(
self.VERIFIER_ID, self.DEPLOYMENT_ID)
+ self.confpath = os.path.join(CONST.dir_functest_test,
+ CONST.refstack_tempest_conf_path)
def generate_tempestconf(self):
try:
@@ -33,21 +34,20 @@ class TempestConf(object):
use_custom_images=True, use_custom_flavors=True)
conf_utils.configure_tempest_defcore(
self.DEPLOYMENT_DIR, img_flavor_dict)
- except KeyError as e:
- logger.error("defcore prepare env error with: %s", e)
+ except Exception as e:
+ logger.error("error with generating refstack client "
+ "reference tempest conf file: %s", e)
def main(self):
try:
self.generate_tempestconf()
- res = testcase.TestCase.EX_OK
+ logger.info("a reference tempest conf file generated "
+ "at %s", self.confpath)
except Exception as e:
logger.error('Error with run: %s', e)
- res = testcase.TestCase.EX_RUN_ERROR
- return res
if __name__ == '__main__':
+ logging.basicConfig()
tempestconf = TempestConf()
- result = tempestconf.main()
- if result != testcase.TestCase.EX_OK:
- sys.exit(result)
+ tempestconf.main()
diff --git a/functest/opnfv_tests/openstack/snaps/api_check.py b/functest/opnfv_tests/openstack/snaps/api_check.py
index ad77d9be..50f67094 100644
--- a/functest/opnfv_tests/openstack/snaps/api_check.py
+++ b/functest/opnfv_tests/openstack/snaps/api_check.py
@@ -11,7 +11,6 @@ from snaps import test_suite_builder
from functest.opnfv_tests.openstack.snaps.snaps_test_runner import \
SnapsTestRunner
-from functest.utils.constants import CONST
class ApiCheck(SnapsTestRunner):
@@ -20,14 +19,15 @@ class ApiCheck(SnapsTestRunner):
that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
and Nova
"""
- def __init__(self):
- super(ApiCheck, self).__init__()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "api_check"
+ super(ApiCheck, self).__init__(**kwargs)
self.suite = unittest.TestSuite()
- self.case_name = "api_check"
test_suite_builder.add_openstack_api_tests(
- self.suite,
- CONST.openstack_creds,
- self.ext_net_name,
- use_keystone=CONST.snaps_use_keystone)
+ suite=self.suite,
+ os_creds=self.os_creds,
+ ext_net_name=self.ext_net_name,
+ use_keystone=self.use_keystone)
diff --git a/functest/opnfv_tests/openstack/snaps/connection_check.py b/functest/opnfv_tests/openstack/snaps/connection_check.py
index 0637bcfb..f2753aea 100644
--- a/functest/opnfv_tests/openstack/snaps/connection_check.py
+++ b/functest/opnfv_tests/openstack/snaps/connection_check.py
@@ -11,7 +11,6 @@ from snaps import test_suite_builder
from functest.opnfv_tests.openstack.snaps.snaps_test_runner import \
SnapsTestRunner
-from functest.utils.constants import CONST
class ConnectionCheck(SnapsTestRunner):
@@ -20,14 +19,15 @@ class ConnectionCheck(SnapsTestRunner):
that simply obtain the different OpenStack clients and may perform
simple queries
"""
- def __init__(self):
- super(ConnectionCheck, self).__init__()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "connection_check"
+ super(ConnectionCheck, self).__init__(**kwargs)
self.suite = unittest.TestSuite()
- self.case_name = "connection_check"
test_suite_builder.add_openstack_client_tests(
- self.suite,
- CONST.openstack_creds,
- self.ext_net_name,
- use_keystone=CONST.snaps_use_keystone)
+ suite=self.suite,
+ os_creds=self.os_creds,
+ ext_net_name=self.ext_net_name,
+ use_keystone=self.use_keystone)
diff --git a/functest/opnfv_tests/openstack/snaps/health_check.py b/functest/opnfv_tests/openstack/snaps/health_check.py
index 8fece746..0daddcdd 100644
--- a/functest/opnfv_tests/openstack/snaps/health_check.py
+++ b/functest/opnfv_tests/openstack/snaps/health_check.py
@@ -21,19 +21,21 @@ class HealthCheck(SnapsTestRunner):
creates a VM with a single port with an IPv4 address that is assigned by
DHCP. This test then validates the expected IP with the actual
"""
- def __init__(self):
- super(HealthCheck, self).__init__()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "snaps_images_cirros"
+ super(HealthCheck, self).__init__(**kwargs)
self.suite = unittest.TestSuite()
- self.case_name = "snaps_health_check"
image_custom_config = None
- if hasattr(CONST, 'snaps_health_check'):
- image_custom_config = CONST.snaps_health_check
+ if hasattr(CONST, 'snaps_images_cirros'):
+ image_custom_config = CONST.__getattribute__('snaps_images_cirros')
self.suite.addTest(
OSIntegrationTestCase.parameterize(
- SimpleHealthCheck, CONST.openstack_creds, self.ext_net_name,
- use_keystone=CONST.snaps_use_keystone,
+ SimpleHealthCheck, os_creds=self.os_creds,
+ ext_net_name=self.ext_net_name,
+ use_keystone=self.use_keystone,
flavor_metadata=self.flavor_metadata,
image_metadata=image_custom_config))
diff --git a/functest/opnfv_tests/openstack/snaps/smoke.py b/functest/opnfv_tests/openstack/snaps/smoke.py
index 45fa6de8..d9f95e90 100644
--- a/functest/opnfv_tests/openstack/snaps/smoke.py
+++ b/functest/opnfv_tests/openstack/snaps/smoke.py
@@ -21,30 +21,29 @@ class SnapsSmoke(SnapsTestRunner):
that exercise many of the OpenStack APIs within Keystone, Glance, Neutron,
and Nova
"""
- def __init__(self):
- super(SnapsSmoke, self).__init__()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "snaps_smoke"
+ super(SnapsSmoke, self).__init__(**kwargs)
self.suite = unittest.TestSuite()
- self.case_name = "snaps_smoke"
- use_fip = CONST.snaps_use_floating_ips
- # The snaps smoke test uses the same config as the
- # snaps_health_check suite, so reuse it here
- image_custom_config = None
- if hasattr(CONST, 'snaps_health_check'):
- image_custom_config = CONST.snaps_health_check
+ image_config = None
+ if hasattr(CONST, 'snaps_images_cirros'):
+ image_config = CONST.__getattribute__('snaps_images_cirros')
# Tests requiring floating IPs leverage files contained within the
# SNAPS repository and are found relative to that path
- if use_fip:
- snaps_dir = CONST.dir_repo_snaps + '/snaps'
+ if self.use_fip:
+ snaps_dir = os.path.join(CONST.__getattribute__('dir_repo_snaps'),
+ 'snaps')
os.chdir(snaps_dir)
test_suite_builder.add_openstack_integration_tests(
- self.suite,
- CONST.openstack_creds,
- self.ext_net_name,
- use_keystone=CONST.snaps_use_keystone,
+ suite=self.suite,
+ os_creds=self.os_creds,
+ ext_net_name=self.ext_net_name,
+ use_keystone=self.use_keystone,
flavor_metadata=self.flavor_metadata,
- image_metadata=image_custom_config,
- use_floating_ips=use_fip)
+ image_metadata=image_config,
+ use_floating_ips=self.use_fip)
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
index 9d723905..94b97551 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
@@ -5,29 +5,36 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
-from functest.utils import functest_logger as ft_logger
+import logging
+
from functest.core.pytest_suite_runner import PyTestSuiteRunner
from functest.opnfv_tests.openstack.snaps import snaps_utils
from functest.utils import functest_utils
+from functest.utils.constants import CONST
from snaps.openstack import create_flavor
+from snaps.openstack.tests import openstack_tests
class SnapsTestRunner(PyTestSuiteRunner):
"""
- This test executes the SNAPS Python Test case SimpleHealthCheck which
- creates a VM with a single port with an IPv4 address that is assigned by
- DHCP. This test then validates the expected IP with the actual
+ This test executes the SNAPS Python Tests
"""
- def __init__(self):
- super(SnapsTestRunner, self).__init__()
+ def __init__(self, **kwargs):
+ super(SnapsTestRunner, self).__init__(**kwargs)
+ self.logger = logging.getLogger(__name__)
+
+ self.os_creds = openstack_tests.get_credentials(
+ os_env_file=CONST.__getattribute__('openstack_creds'),
+ proxy_settings_str=None, ssh_proxy_cmd=None)
- self.ext_net_name = snaps_utils.get_ext_net_name()
- self.logger = ft_logger.Logger(self.project_name).getLogger()
+ self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds)
+ self.use_fip = CONST.__getattribute__('snaps_use_floating_ips')
+ self.use_keystone = CONST.__getattribute__('snaps_use_keystone')
scenario = functest_utils.get_scenario()
self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_ANY
if 'ovs' in scenario or 'fdio' in scenario:
self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
- self.logger.info("Using flavor metatdata '%s'" % self.flavor_metadata)
+ self.logger.info("Using flavor metadata '%s'", self.flavor_metadata)
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_utils.py b/functest/opnfv_tests/openstack/snaps/snaps_utils.py
index 4ea1a04a..327ba073 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_utils.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_utils.py
@@ -5,19 +5,15 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
-from snaps.openstack.tests import openstack_tests
from snaps.openstack.utils import neutron_utils
-from functest.utils.constants import CONST
-
-def get_ext_net_name():
+def get_ext_net_name(os_creds):
"""
Returns the first external network name
+ :param: os_creds: an instance of snaps OSCreds object
:return:
"""
- os_env_file = CONST.openstack_creds
- os_creds = openstack_tests.get_credentials(os_env_file=os_env_file)
neutron = neutron_utils.neutron_client(os_creds)
ext_nets = neutron_utils.get_external_networks(neutron)
return ext_nets[0]['network']['name']
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
index f4a94f65..cd6a2a8c 100644
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py
@@ -8,13 +8,13 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
import ConfigParser
+import logging
import os
import re
import shutil
import subprocess
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
@@ -22,7 +22,7 @@ import functest.utils.openstack_utils as os_utils
IMAGE_ID_ALT = None
FLAVOR_ID_ALT = None
REPO_PATH = CONST.dir_repo_functest
-GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_data,
+GLANCE_IMAGE_PATH = os.path.join(CONST.dir_functest_images,
CONST.openstack_image_file_name)
TEMPEST_TEST_LIST_DIR = CONST.dir_tempest_cases
TEMPEST_RESULTS_DIR = os.path.join(CONST.dir_results,
@@ -42,7 +42,7 @@ CI_INSTALLER_TYPE = CONST.INSTALLER_TYPE
CI_INSTALLER_IP = CONST.INSTALLER_IP
""" logging configuration """
-logger = ft_logger.Logger("Tempest").getLogger()
+logger = logging.getLogger(__name__)
def create_tempest_resources(use_custom_images=False,
@@ -279,12 +279,20 @@ def configure_tempest_update_params(tempest_conf_file,
config.set('identity', 'tenant_name', CONST.tempest_identity_tenant_name)
config.set('identity', 'username', CONST.tempest_identity_user_name)
config.set('identity', 'password', CONST.tempest_identity_user_password)
+ config.set('identity', 'region', 'RegionOne')
config.set(
'validation', 'ssh_timeout', CONST.tempest_validation_ssh_timeout)
config.set('object-storage', 'operator_role',
CONST.tempest_object_storage_operator_role)
if CONST.OS_ENDPOINT_TYPE is not None:
+ sections = config.sections()
+ if os_utils.is_keystone_v3():
+ config.set('identity', 'v3_endpoint_type', CONST.OS_ENDPOINT_TYPE)
+ if 'identity-feature-enabled' not in sections:
+ config.add_section('identity-feature-enabled')
+ config.set('identity-feature-enabled', 'api_v2', False)
+ config.set('identity-feature-enabled', 'api_v2_admin', False)
services_list = ['compute',
'volume',
'image',
@@ -292,7 +300,6 @@ def configure_tempest_update_params(tempest_conf_file,
'data-processing',
'object-storage',
'orchestration']
- sections = config.sections()
for service in services_list:
if service not in sections:
config.add_section(service)
diff --git a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
index 0da92cd8..026b24f4 100644
--- a/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
+++ b/functest/opnfv_tests/openstack/tempest/custom_tests/blacklist.txt
@@ -52,7 +52,7 @@
tests:
- tempest.scenario.test_server_basic_ops.TestServerBasicOps.test_server_basic_ops
-
+-
# https://bugs.opendaylight.org/show_bug.cgi?id=5586
scenarios:
- os-odl-bgpvpn-ha
@@ -60,6 +60,5 @@
- os-odl_l2-bgpvpn-ha
installers:
- apex
- - fuel
tests:
- tempest.api.compute.servers.test_server_actions.ServerActionsTestJSON.test_reboot_server_hard
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index 0addbd17..a41d07c7 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -8,6 +8,9 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
+from __future__ import division
+
+import logging
import os
import re
import shutil
@@ -19,17 +22,16 @@ import yaml
from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
""" logging configuration """
-logger = ft_logger.Logger("Tempest").getLogger()
+logger = logging.getLogger(__name__)
class TempestCommon(testcase.TestCase):
- def __init__(self):
- super(TempestCommon, self).__init__()
+ def __init__(self, **kwargs):
+ super(TempestCommon, self).__init__(**kwargs)
self.MODE = ""
self.OPTION = ""
self.VERIFIER_ID = conf_utils.get_verifier_id()
@@ -181,7 +183,13 @@ class TempestCommon(testcase.TestCase):
try:
num_executed = int(num_tests) - int(num_skipped)
- success_rate = 100 * int(num_success) / int(num_executed)
+ try:
+ self.result = 100 * int(num_success) / int(num_executed)
+ except ZeroDivisionError:
+ logger.error("No test has been executed")
+ self.result = 0
+ return
+
with open(os.path.join(conf_utils.TEMPEST_RESULTS_DIR,
"tempest.log"), 'r') as logfile:
output = logfile.read()
@@ -198,21 +206,17 @@ class TempestCommon(testcase.TestCase):
"errors": error_logs,
"skipped": skipped_testcase}
except Exception:
- success_rate = 0
+ self.result = 0
- self.criteria = ft_utils.check_success_rate(
- self.case_name, success_rate)
- logger.info("Tempest %s success_rate is %s%%, is marked as %s"
- % (self.case_name, success_rate, self.criteria))
+ logger.info("Tempest %s success_rate is %s%%"
+ % (self.case_name, self.result))
def run(self):
self.start_time = time.time()
-
- if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
- os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
-
try:
+ if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
+ os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
image_and_flavor = conf_utils.create_tempest_resources()
conf_utils.configure_tempest(
self.DEPLOYMENT_DIR,
@@ -234,35 +238,39 @@ class TempestCommon(testcase.TestCase):
class TempestSmokeSerial(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "tempest_smoke_serial"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'tempest_smoke_serial'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "smoke"
self.OPTION = "--concurrency 1"
class TempestSmokeParallel(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "tempest_smoke_parallel"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'tempest_smoke_parallel'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "smoke"
self.OPTION = ""
class TempestFullParallel(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "tempest_full_parallel"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'tempest_full_parallel'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "full"
class TempestMultisite(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "multisite"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'multisite'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "feature_multisite"
self.OPTION = "--concurrency 1"
conf_utils.install_verifier_ext(CONST.dir_repo_kingbird)
@@ -270,17 +278,19 @@ class TempestMultisite(TempestCommon):
class TempestCustom(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "tempest_custom"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'tempest_custom'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "custom"
self.OPTION = "--concurrency 1"
class TempestDefcore(TempestCommon):
- def __init__(self):
- TempestCommon.__init__(self)
- self.case_name = "tempest_defcore"
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = 'tempest_defcore'
+ TempestCommon.__init__(self, **kwargs)
self.MODE = "defcore"
self.OPTION = "--concurrency 1"
diff --git a/functest/opnfv_tests/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py
index 584ded38..8e71bf82 100644
--- a/functest/opnfv_tests/openstack/vping/vping_base.py
+++ b/functest/opnfv_tests/openstack/vping/vping_base.py
@@ -7,281 +7,194 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
+from datetime import datetime
+import logging
import os
-import pprint
import time
-from datetime import datetime
+import uuid
-import functest.core.testcase as testcase
-import functest.utils.openstack_utils as os_utils
+from functest.core.testcase import TestCase
+from functest.utils import functest_utils
from functest.utils.constants import CONST
+from snaps.openstack import create_flavor
+from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
+from snaps.openstack.create_network import NetworkSettings, SubnetSettings
+from snaps.openstack.tests import openstack_tests
+from snaps.openstack.utils import deploy_utils, nova_utils
+
+
+class VPingBase(TestCase):
+
+ """
+ Base class for vPing tests that check connectivity between two VMs shared
+ internal network.
+ This class is responsible for creating the image, internal network.
+ """
+
+ def __init__(self, **kwargs):
+ super(VPingBase, self).__init__(**kwargs)
+
+ self.logger = logging.getLogger(self.__class__.__name__)
+
+ self.functest_repo = CONST.__getattribute__('dir_repo_functest')
+ self.guid = ''
+ if CONST.__getattribute__('vping_unique_names'):
+ self.guid = '-' + str(uuid.uuid4())
+
+ self.os_creds = openstack_tests.get_credentials(
+ os_env_file=CONST.__getattribute__('openstack_creds'))
+
+ self.repo = CONST.__getattribute__('dir_vping')
-class VPingBase(testcase.TestCase):
- def __init__(self):
- super(VPingBase, self).__init__()
- self.logger = None
- self.functest_repo = CONST.dir_repo_functest
- self.repo = CONST.dir_vping
- self.vm1_name = CONST.vping_vm_name_1
- self.vm2_name = CONST.vping_vm_name_2
- self.vm_boot_timeout = 180
- self.vm_delete_timeout = 100
- self.ping_timeout = CONST.vping_ping_timeout
-
- self.image_name = CONST.vping_image_name
- self.image_filename = CONST.openstack_image_file_name
- self.image_format = CONST.openstack_image_disk_format
- self.image_username = CONST.openstack_image_username
- self.image_password = CONST.openstack_image_password
- self.image_path = os.path.join(CONST.dir_functest_data,
- self.image_filename)
-
- self.flavor_name = CONST.vping_vm_flavor
+ self.creators = list()
+ self.image_creator = None
+ self.network_creator = None
+ self.vm1_creator = None
+ self.vm2_creator = None
+
+ self.self_cleanup = CONST.__getattribute__('vping_cleanup_objects')
+
+ # Image constants
+ self.image_name =\
+ CONST.__getattribute__('vping_image_name') + self.guid
+
+ # VM constants
+ self.vm1_name = CONST.__getattribute__('vping_vm_name_1') + self.guid
+ self.vm2_name = CONST.__getattribute__('vping_vm_name_2') + self.guid
+ self.vm_boot_timeout = CONST.__getattribute__('vping_vm_boot_timeout')
+ self.vm_delete_timeout =\
+ CONST.__getattribute__('vping_vm_delete_timeout')
+ self.vm_ssh_connect_timeout = CONST.vping_vm_ssh_connect_timeout
+ self.ping_timeout = CONST.__getattribute__('vping_ping_timeout')
+ self.flavor_name = 'vping-flavor' + self.guid
# NEUTRON Private Network parameters
- self.private_net_name = CONST.vping_private_net_name
- self.private_subnet_name = CONST.vping_private_subnet_name
- self.private_subnet_cidr = CONST.vping_private_subnet_cidr
- self.router_name = CONST.vping_router_name
- self.sg_name = CONST.vping_sg_name
- self.sg_desc = CONST.vping_sg_desc
- self.neutron_client = os_utils.get_neutron_client()
- self.glance_client = os_utils.get_glance_client()
- self.nova_client = os_utils.get_nova_client()
-
- def run(self, **kwargs):
- if not self.check_repo_exist():
- return testcase.TestCase.EX_RUN_ERROR
-
- image_id = self.create_image()
- if not image_id:
- return testcase.TestCase.EX_RUN_ERROR
-
- flavor = self.get_flavor()
- if not flavor:
- return testcase.TestCase.EX_RUN_ERROR
-
- network_id = self.create_network_full()
- if not network_id:
- return testcase.TestCase.EX_RUN_ERROR
-
- sg_id = self.create_security_group()
- if not sg_id:
- return testcase.TestCase.EX_RUN_ERROR
-
- self.delete_exist_vms()
+ self.private_net_name =\
+ CONST.__getattribute__('vping_private_net_name') + self.guid
+ self.private_subnet_name =\
+ CONST.__getattribute__('vping_private_subnet_name') + self.guid
+ self.private_subnet_cidr =\
+ CONST.__getattribute__('vping_private_subnet_cidr')
- self.start_time = time.time()
- self.logger.info("vPing Start Time:'%s'" % (
- datetime.fromtimestamp(self.start_time).strftime(
- '%Y-%m-%d %H:%M:%S')))
+ scenario = functest_utils.get_scenario()
- vm1 = self.boot_vm(self.vm1_name,
- image_id,
- flavor,
- network_id,
- None,
- sg_id)
- if not vm1:
- return testcase.TestCase.EX_RUN_ERROR
-
- test_ip = self.get_test_ip(vm1)
- vm2 = self.boot_vm(self.vm2_name,
- image_id,
- flavor,
- network_id,
- test_ip,
- sg_id)
- if not vm2:
- return testcase.TestCase.EX_RUN_ERROR
-
- EXIT_CODE = self.do_vping(vm2, test_ip)
- if EXIT_CODE == testcase.TestCase.EX_RUN_ERROR:
- return EXIT_CODE
+ self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_ANY
+ if 'ovs' in scenario or 'fdio' in scenario:
+ self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
- self.stop_time = time.time()
- self.parse_result(EXIT_CODE,
- self.start_time,
- self.stop_time)
- return testcase.TestCase.EX_OK
+ self.cirros_image_config = None
- def boot_vm_preparation(self, config, vmname, test_ip):
- pass
+ # Move this configuration option up for all tests to leverage
+ if hasattr(CONST, 'snaps_images_cirros'):
+ self.cirros_image_config = CONST.__getattribute__(
+ 'snaps_images_cirros')
- def do_vping(self, vm, test_ip):
- raise NotImplementedError('vping execution is not implemented')
+ def run(self):
+ """
+ Begins the test execution which should originate from the subclass
+ """
- def check_repo_exist(self):
if not os.path.exists(self.functest_repo):
- self.logger.error("Functest repository not found '%s'"
- % self.functest_repo)
- return False
- return True
+ raise Exception(
+ "Functest repository not found '%s'" % self.functest_repo)
- def create_image(self):
- _, image_id = os_utils.get_or_create_image(self.image_name,
- self.image_path,
- self.image_format)
- if not image_id:
- return None
+ self.logger.info('Begin virtual environment setup')
- return image_id
+ self.start_time = time.time()
+ self.logger.info("vPing Start Time:'%s'" % (
+ datetime.fromtimestamp(self.start_time).strftime(
+ '%Y-%m-%d %H:%M:%S')))
- def get_flavor(self):
- try:
- flavor = self.nova_client.flavors.find(name=self.flavor_name)
- self.logger.info("Using existing Flavor '%s'..."
- % self.flavor_name)
- return flavor
- except:
- self.logger.error("Flavor '%s' not found." % self.flavor_name)
- self.logger.info("Available flavors are: ")
- self.pMsg(self.nova_client.flavor.list())
- return None
-
- def create_network_full(self):
- network_dic = os_utils.create_network_full(self.neutron_client,
- self.private_net_name,
- self.private_subnet_name,
- self.router_name,
- self.private_subnet_cidr)
-
- if not network_dic:
- self.logger.error(
- "There has been a problem when creating the neutron network")
- return None
- network_id = network_dic["net_id"]
- return network_id
-
- def create_security_group(self):
- sg_id = os_utils.get_security_group_id(self.neutron_client,
- self.sg_name)
- if sg_id != '':
- self.logger.info("Using existing security group '%s'..."
- % self.sg_name)
+ self.__delete_exist_vms()
+
+ image_base_name = self.image_name + '-' + str(self.guid)
+ os_image_settings = openstack_tests.cirros_image_settings(
+ image_base_name, image_metadata=self.cirros_image_config)
+ self.logger.info("Creating image with name: '%s'" % self.image_name)
+
+ self.image_creator = deploy_utils.create_image(
+ self.os_creds, os_image_settings)
+ self.creators.append(self.image_creator)
+
+ self.logger.info(
+ "Creating network with name: '%s'" % self.private_net_name)
+ self.network_creator = deploy_utils.create_network(
+ self.os_creds,
+ NetworkSettings(name=self.private_net_name,
+ subnet_settings=[SubnetSettings(
+ name=self.private_subnet_name,
+ cidr=self.private_subnet_cidr)]))
+ self.creators.append(self.network_creator)
+
+ self.logger.info(
+ "Creating flavor with name: '%s'" % self.flavor_name)
+ flavor_creator = OpenStackFlavor(
+ self.os_creds,
+ FlavorSettings(name=self.flavor_name, ram=512, disk=1, vcpus=1,
+ metadata=self.flavor_metadata))
+ flavor_creator.create()
+ self.creators.append(flavor_creator)
+
+ def _execute(self):
+ """
+ Method called by subclasses after environment has been setup
+ :return: the exit code
+ """
+ self.logger.info('Begin test execution')
+
+ test_ip = self.vm1_creator.get_port_ip(
+ self.vm1_creator.instance_settings.port_settings[0].name)
+
+ if self.vm1_creator.vm_active(
+ block=True) and self.vm2_creator.vm_active(block=True):
+ result = self._do_vping(self.vm2_creator, test_ip)
else:
- self.logger.info("Creating security group '%s'..."
- % self.sg_name)
- SECGROUP = os_utils.create_security_group(self.neutron_client,
- self.sg_name,
- self.sg_desc)
- if not SECGROUP:
- self.logger.error("Failed to create the security group...")
- return None
-
- sg_id = SECGROUP['id']
-
- self.logger.debug("Security group '%s' with ID=%s created "
- "successfully." % (SECGROUP['name'], sg_id))
-
- self.logger.debug("Adding ICMP rules in security group '%s'..."
- % self.sg_name)
- if not os_utils.create_secgroup_rule(self.neutron_client, sg_id,
- 'ingress', 'icmp'):
- self.logger.error("Failed to create security group rule...")
- return None
-
- self.logger.debug("Adding SSH rules in security group '%s'..."
- % self.sg_name)
- if not os_utils.create_secgroup_rule(self.neutron_client, sg_id,
- 'ingress', 'tcp',
- '22', '22'):
- self.logger.error("Failed to create security group rule...")
- return None
-
- if not os_utils.create_secgroup_rule(
- self.neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
- self.logger.error("Failed to create security group rule...")
- return None
- return sg_id
-
- def delete_exist_vms(self):
- servers = self.nova_client.servers.list()
+ raise Exception('VMs never became active')
+
+ if result == TestCase.EX_RUN_ERROR:
+ return TestCase.EX_RUN_ERROR
+
+ self.stop_time = time.time()
+ self.result = 100
+ return TestCase.EX_OK
+
+ def _cleanup(self):
+ """
+ Cleanup all OpenStack objects. Should be called on completion
+ :return:
+ """
+ if self.self_cleanup:
+ for creator in reversed(self.creators):
+ try:
+ creator.clean()
+ except Exception as e:
+ self.logger.error('Unexpected error cleaning - %s', e)
+
+ def _do_vping(self, vm_creator, test_ip):
+ """
+ Method to be implemented by subclasses
+ Begins the real test after the OpenStack environment has been setup
+ :param vm_creator: the SNAPS VM instance creator object
+ :param test_ip: the IP to which the VM needs to issue the ping
+ :return: T/F
+ """
+ raise NotImplementedError('vping execution is not implemented')
+
+ def __delete_exist_vms(self):
+ """
+ Cleans any existing VMs using the same name.
+ """
+ nova_client = nova_utils.nova_client(self.os_creds)
+ servers = nova_client.servers.list()
for server in servers:
if server.name == self.vm1_name or server.name == self.vm2_name:
self.logger.info("Deleting instance %s..." % server.name)
server.delete()
- def boot_vm(self, vmname, image_id, flavor, network_id, test_ip, sg_id):
- config = dict()
- config['name'] = vmname
- config['flavor'] = flavor
- config['image'] = image_id
- config['nics'] = [{"net-id": network_id}]
- self.boot_vm_preparation(config, vmname, test_ip)
- self.logger.info("Creating instance '%s'..." % vmname)
- self.logger.debug("Configuration: %s" % config)
- vm = self.nova_client.servers.create(**config)
-
- # wait until VM status is active
- if not self.waitVmActive(self.nova_client, vm):
- vm_status = os_utils.get_instance_status(self.nova_client, vm)
- self.logger.error("Instance '%s' cannot be booted. Status is '%s'"
- % (vmname, vm_status))
- return None
- else:
- self.logger.info("Instance '%s' is ACTIVE." % vmname)
-
- self.add_secgroup(vmname, vm.id, sg_id)
-
- return vm
-
- def waitVmActive(self, nova, vm):
- # sleep and wait for VM status change
- sleep_time = 3
- count = self.vm_boot_timeout / sleep_time
- while True:
- status = os_utils.get_instance_status(nova, vm)
- self.logger.debug("Status: %s" % status)
- if status == "ACTIVE":
- return True
- if status == "ERROR" or status == "error":
- return False
- if count == 0:
- self.logger.debug("Booting a VM timed out...")
- return False
- count -= 1
- time.sleep(sleep_time)
- return False
-
- def add_secgroup(self, vmname, vm_id, sg_id):
- self.logger.info("Adding '%s' to security group '%s'..." %
- (vmname, self.sg_name))
- os_utils.add_secgroup_to_instance(self.nova_client, vm_id, sg_id)
-
- def get_test_ip(self, vm):
- test_ip = vm.networks.get(self.private_net_name)[0]
- self.logger.debug("Instance '%s' got %s" % (vm.name, test_ip))
- return test_ip
-
- def parse_result(self, code, start_time, stop_time):
- test_status = "FAIL"
- if code == 0:
- self.logger.info("vPing OK")
- duration = round(stop_time - start_time, 1)
- self.logger.info("vPing duration:'%s'" % duration)
- test_status = "PASS"
- elif code == -2:
- duration = 0
- self.logger.info("Userdata is not supported in nova boot. "
- "Aborting test...")
- else:
- duration = 0
- self.logger.error("vPing FAILED")
-
- self.details = {'timestart': start_time,
- 'duration': duration,
- 'status': test_status}
- self.criteria = test_status
-
- @staticmethod
- def pMsg(msg):
- """pretty printing"""
- pprint.PrettyPrinter(indent=4).pprint(msg)
-
class VPingMain(object):
+
def __init__(self, vping_cls):
self.vping = vping_cls()
@@ -291,6 +204,6 @@ class VPingMain(object):
if result != VPingBase.EX_OK:
return result
if kwargs['report']:
- return self.vping.push_to_db()
- except Exception:
+ return self.vping.publish_report()
+ except:
return VPingBase.EX_RUN_ERROR
diff --git a/functest/opnfv_tests/openstack/vping/vping_ssh.py b/functest/opnfv_tests/openstack/vping/vping_ssh.py
index fc2f01c6..0ad77402 100755
--- a/functest/opnfv_tests/openstack/vping/vping_ssh.py
+++ b/functest/opnfv_tests/openstack/vping/vping_ssh.py
@@ -7,123 +7,161 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
+import argparse
import os
-import re
+from scp import SCPClient
import sys
import time
-import argparse
-import paramiko
-from scp import SCPClient
-
-import functest.utils.functest_logger as ft_logger
-import functest.utils.openstack_utils as os_utils
+from snaps.openstack.create_instance import FloatingIpSettings, \
+ VmInstanceSettings
+from snaps.openstack.create_keypairs import KeypairSettings
+from snaps.openstack.create_network import PortSettings
+from snaps.openstack.create_router import RouterSettings
+from snaps.openstack.create_security_group import Direction, Protocol, \
+ SecurityGroupSettings, SecurityGroupRuleSettings
+from snaps.openstack.utils import deploy_utils
+
+from functest.core.testcase import TestCase
+from functest.opnfv_tests.openstack.snaps import snaps_utils
+from functest.utils.constants import CONST
import vping_base
-import functest.core.testcase as testcase
class VPingSSH(vping_base.VPingBase):
-
- def __init__(self):
- super(VPingSSH, self).__init__()
- self.case_name = 'vping_ssh'
- self.logger = ft_logger.Logger(self.case_name).getLogger()
-
- def do_vping(self, vm, test_ip):
- floatip = self.add_float_ip(vm)
- if not floatip:
- return testcase.TestCase.EX_RUN_ERROR
- ssh = self.establish_ssh(vm, floatip)
- if not ssh:
- return testcase.TestCase.EX_RUN_ERROR
- if not self.transfer_ping_script(ssh, floatip):
- return testcase.TestCase.EX_RUN_ERROR
- return self.do_vping_ssh(ssh, test_ip)
-
- def add_float_ip(self, vm):
- self.logger.info("Creating floating IP for VM '%s'..." % self.vm2_name)
- floatip_dic = os_utils.create_floating_ip(self.neutron_client)
- floatip = floatip_dic['fip_addr']
-
- if floatip is None:
- self.logger.error("Cannot create floating IP.")
- return None
- self.logger.info("Floating IP created: '%s'" % floatip)
-
- self.logger.info("Associating floating ip: '%s' to VM '%s' "
- % (floatip, self.vm2_name))
- if not os_utils.add_floating_ip(self.nova_client, vm.id, floatip):
- self.logger.error("Cannot associate floating IP to VM.")
- return None
-
- return floatip
-
- def establish_ssh(self, vm, floatip):
- self.logger.info("Trying to establish SSH connection to %s..."
- % floatip)
- ssh = paramiko.SSHClient()
- ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-
- timeout = 50
- nolease = False
- got_ip = False
- discover_count = 0
- cidr_first_octet = self.private_subnet_cidr.split('.')[0]
- while timeout > 0:
- try:
- ssh.connect(floatip, username=self.image_username,
- password=self.image_password, timeout=2)
- self.logger.debug("SSH connection established to %s."
- % floatip)
- break
- except:
- self.logger.debug("Waiting for %s..." % floatip)
- time.sleep(6)
- timeout -= 1
-
- console_log = vm.get_console_output()
-
- # print each "Sending discover" captured on the console log
- if (len(re.findall("Sending discover", console_log)) >
- discover_count and not got_ip):
- discover_count += 1
- self.logger.debug("Console-log '%s': Sending discover..."
- % self.vm2_name)
-
- # check if eth0 got an ip,the line looks like this:
- # "inet addr:192.168."....
- # if the dhcp agent fails to assing ip, this line will not appear
- if "inet addr:" + cidr_first_octet in console_log and not got_ip:
- got_ip = True
- self.logger.debug("The instance '%s' succeeded to get the IP "
- "from the dhcp agent." % self.vm2_name)
-
- # if dhcp not work,it shows "No lease, failing".The test will fail
- if ("No lease, failing" in console_log and
- not nolease and
- not got_ip):
- nolease = True
- self.logger.debug("Console-log '%s': No lease, failing..."
- % self.vm2_name)
- self.logger.info("The instance failed to get an IP from DHCP "
- "agent. The test will probably timeout...")
-
- if timeout == 0: # 300 sec timeout (5 min)
- self.logger.error("Cannot establish connection to IP '%s'. "
- "Aborting" % floatip)
- return None
- return ssh
-
- def transfer_ping_script(self, ssh, floatip):
- self.logger.info("Trying to transfer ping.sh to %s..." % floatip)
+ """
+ Class to execute the vPing test using a Floating IP to connect to one VM
+ to issue the ping command to the second
+ """
+
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "vping_ssh"
+ super(VPingSSH, self).__init__(**kwargs)
+
+ self.kp_name = CONST.__getattribute__('vping_keypair_name') + self.guid
+ self.kp_priv_file = CONST.__getattribute__('vping_keypair_priv_file')
+ self.kp_pub_file = CONST.__getattribute__('vping_keypair_pub_file')
+ self.router_name =\
+ CONST.__getattribute__('vping_router_name') + self.guid
+ self.sg_name = CONST.__getattribute__('vping_sg_name') + self.guid
+ self.sg_desc = CONST.__getattribute__('vping_sg_desc')
+
+ self.ext_net_name = snaps_utils.get_ext_net_name(self.os_creds)
+
+ def run(self):
+ """
+ Sets up the OpenStack keypair, router, security group, and VM instance
+ objects then validates the ping.
+ :return: the exit code from the super.execute() method
+ """
+ try:
+ super(VPingSSH, self).run()
+
+ self.logger.info("Creating keypair with name: '%s'" % self.kp_name)
+ kp_creator = deploy_utils.create_keypair(
+ self.os_creds,
+ KeypairSettings(name=self.kp_name,
+ private_filepath=self.kp_priv_file,
+ public_filepath=self.kp_pub_file))
+ self.creators.append(kp_creator)
+
+ # Creating router to external network
+ self.logger.info("Creating router with name: '%s'"
+ % self.router_name)
+ net_set = self.network_creator.network_settings
+ sub_set = [net_set.subnet_settings[0].name]
+ router_creator = deploy_utils.create_router(
+ self.os_creds,
+ RouterSettings(
+ name=self.router_name,
+ external_gateway=self.ext_net_name,
+ internal_subnets=sub_set))
+ self.creators.append(router_creator)
+
+ # Creating Instance 1
+ port1_settings = PortSettings(
+ name=self.vm1_name + '-vPingPort',
+ network_name=self.network_creator.network_settings.name)
+ instance1_settings = VmInstanceSettings(
+ name=self.vm1_name, flavor=self.flavor_name,
+ vm_boot_timeout=self.vm_boot_timeout,
+ vm_delete_timeout=self.vm_delete_timeout,
+ ssh_connect_timeout=self.vm_ssh_connect_timeout,
+ port_settings=[port1_settings])
+
+ self.logger.info(
+ "Creating VM 1 instance with name: '%s'"
+ % instance1_settings.name)
+ self.vm1_creator = deploy_utils.create_vm_instance(
+ self.os_creds,
+ instance1_settings,
+ self.image_creator.image_settings,
+ keypair_creator=kp_creator)
+ self.creators.append(self.vm1_creator)
+
+ # Creating Instance 2
+ sg_creator = self.__create_security_group()
+ self.creators.append(sg_creator)
+
+ port2_settings = PortSettings(
+ name=self.vm2_name + '-vPingPort',
+ network_name=self.network_creator.network_settings.name)
+ instance2_settings = VmInstanceSettings(
+ name=self.vm2_name, flavor=self.flavor_name,
+ vm_boot_timeout=self.vm_boot_timeout,
+ vm_delete_timeout=self.vm_delete_timeout,
+ ssh_connect_timeout=self.vm_ssh_connect_timeout,
+ port_settings=[port2_settings],
+ security_group_names=[sg_creator.sec_grp_settings.name],
+ floating_ip_settings=[FloatingIpSettings(
+ name=self.vm2_name + '-FIPName',
+ port_name=port2_settings.name,
+ router_name=router_creator.router_settings.name)])
+
+ self.logger.info(
+ "Creating VM 2 instance with name: '%s'"
+ % instance2_settings.name)
+ self.vm2_creator = deploy_utils.create_vm_instance(
+ self.os_creds,
+ instance2_settings,
+ self.image_creator.image_settings,
+ keypair_creator=kp_creator)
+ self.creators.append(self.vm2_creator)
+
+ return self._execute()
+ except Exception as e:
+ self.logger.error('Unexpected error running test - ' + e.message)
+ return TestCase.EX_RUN_ERROR
+ finally:
+ self._cleanup()
+
+ def _do_vping(self, vm_creator, test_ip):
+ """
+ Override from super
+ """
+ if vm_creator.vm_ssh_active(block=True):
+ ssh = vm_creator.ssh_client()
+ if not self.__transfer_ping_script(ssh):
+ return TestCase.EX_RUN_ERROR
+ return self.__do_vping_ssh(ssh, test_ip)
+ else:
+ return -1
+
+ def __transfer_ping_script(self, ssh):
+ """
+ Uses SCP to copy the ping script via the SSH client
+ :param ssh: the SSH client
+ :return:
+ """
+ self.logger.info("Trying to transfer ping.sh")
scp = SCPClient(ssh.get_transport())
local_path = self.functest_repo + "/" + self.repo
ping_script = os.path.join(local_path, "ping.sh")
try:
scp.put(ping_script, "~/")
except:
- self.logger.error("Cannot SCP the file '%s' to VM '%s'"
- % (ping_script, floatip))
+ self.logger.error("Cannot SCP the file '%s'" % ping_script)
return False
cmd = 'chmod 755 ~/ping.sh'
@@ -133,8 +171,14 @@ class VPingSSH(vping_base.VPingBase):
return True
- def do_vping_ssh(self, ssh, test_ip):
- EXIT_CODE = -1
+ def __do_vping_ssh(self, ssh, test_ip):
+ """
+ Pings the test_ip via the SSH client
+ :param ssh: the SSH client used to issue the ping command
+ :param test_ip: the IP for the ping command to use
+ :return: exit_code (int)
+ """
+ exit_code = TestCase.EX_TESTCASE_FAILED
self.logger.info("Waiting for ping...")
sec = 0
@@ -149,7 +193,7 @@ class VPingSSH(vping_base.VPingBase):
for line in output:
if "vPing OK" in line:
self.logger.info("vPing detected!")
- EXIT_CODE = 0
+ exit_code = TestCase.EX_OK
flag = True
break
@@ -161,7 +205,35 @@ class VPingSSH(vping_base.VPingBase):
break
self.logger.debug("Pinging %s. Waiting for response..." % test_ip)
sec += 1
- return EXIT_CODE
+ return exit_code
+
+ def __create_security_group(self):
+ """
+ Configures and deploys an OpenStack security group object
+ :return: the creator object
+ """
+ sg_rules = list()
+ sg_rules.append(
+ SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
+ direction=Direction.ingress,
+ protocol=Protocol.icmp))
+ sg_rules.append(
+ SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
+ direction=Direction.ingress,
+ protocol=Protocol.tcp, port_range_min=22,
+ port_range_max=22))
+ sg_rules.append(
+ SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
+ direction=Direction.egress,
+ protocol=Protocol.tcp, port_range_min=22,
+ port_range_max=22))
+
+ self.logger.info("Security group with name: '%s'" % self.sg_name)
+ return deploy_utils.create_security_group(self.os_creds,
+ SecurityGroupSettings(
+ name=self.sg_name,
+ description=self.sg_desc,
+ rule_settings=sg_rules))
if __name__ == '__main__':
diff --git a/functest/opnfv_tests/openstack/vping/vping_userdata.py b/functest/opnfv_tests/openstack/vping/vping_userdata.py
index fa91c12a..8ea9be84 100755
--- a/functest/opnfv_tests/openstack/vping/vping_userdata.py
+++ b/functest/opnfv_tests/openstack/vping/vping_userdata.py
@@ -7,69 +7,141 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
+import argparse
import sys
import time
-import argparse
+from functest.core.testcase import TestCase
+
+from snaps.openstack.utils import deploy_utils
+from snaps.openstack.create_instance import VmInstanceSettings
+from snaps.openstack.create_network import PortSettings
-import functest.utils.functest_logger as ft_logger
import vping_base
class VPingUserdata(vping_base.VPingBase):
+ """
+ Class to execute the vPing test using userdata and the VM's console
+ """
+
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "vping_userdata"
+ super(VPingUserdata, self).__init__(**kwargs)
+
+ def run(self):
+ """
+ Sets up the OpenStack VM instance objects then executes the ping and
+ validates.
+ :return: the exit code from the super.execute() method
+ """
+ try:
+ super(VPingUserdata, self).run()
+
+ # Creating Instance 1
+ port1_settings = PortSettings(
+ name=self.vm1_name + '-vPingPort',
+ network_name=self.network_creator.network_settings.name)
+ instance1_settings = VmInstanceSettings(
+ name=self.vm1_name,
+ flavor=self.flavor_name,
+ vm_boot_timeout=self.vm_boot_timeout,
+ port_settings=[port1_settings])
+
+ self.logger.info(
+ "Creating VM 1 instance with name: '%s'"
+ % instance1_settings.name)
+ self.vm1_creator = deploy_utils.create_vm_instance(
+ self.os_creds, instance1_settings,
+ self.image_creator.image_settings)
+ self.creators.append(self.vm1_creator)
- def __init__(self):
- super(VPingUserdata, self).__init__()
- self.case_name = 'vping_userdata'
- self.logger = ft_logger.Logger(self.case_name).getLogger()
-
- def boot_vm_preparation(self, config, vmname, test_ip):
- config['config_drive'] = True
- if vmname == self.vm2_name:
- u = ("#!/bin/sh\n\n"
- "while true; do\n"
- " ping -c 1 %s 2>&1 >/dev/null\n"
- " RES=$?\n"
- " if [ \"Z$RES\" = \"Z0\" ] ; then\n"
- " echo 'vPing OK'\n"
- " break\n"
- " else\n"
- " echo 'vPing KO'\n"
- " fi\n"
- " sleep 1\n"
- "done\n" % test_ip)
- config['userdata'] = u
-
- def do_vping(self, vm, test_ip):
+ userdata = _get_userdata(
+ self.vm1_creator.get_port_ip(port1_settings.name))
+ if userdata:
+ # Creating Instance 2
+ port2_settings = PortSettings(
+ name=self.vm2_name + '-vPingPort',
+ network_name=self.network_creator.network_settings.name)
+ instance2_settings = VmInstanceSettings(
+ name=self.vm2_name,
+ flavor=self.flavor_name,
+ vm_boot_timeout=self.vm_boot_timeout,
+ port_settings=[port2_settings],
+ userdata=userdata)
+
+ self.logger.info(
+ "Creating VM 2 instance with name: '%s'"
+ % instance2_settings.name)
+ self.vm2_creator = deploy_utils.create_vm_instance(
+ self.os_creds, instance2_settings,
+ self.image_creator.image_settings)
+ self.creators.append(self.vm2_creator)
+ else:
+ raise Exception('Userdata is None')
+
+ return self._execute()
+
+ finally:
+ self._cleanup()
+
+ def _do_vping(self, vm_creator, test_ip):
+ """
+ Override from super
+ """
self.logger.info("Waiting for ping...")
- EXIT_CODE = -1
+ exit_code = -1
sec = 0
tries = 0
while True:
time.sleep(1)
- p_console = vm.get_console_output()
+ p_console = vm_creator.get_vm_inst().get_console_output()
if "vPing OK" in p_console:
self.logger.info("vPing detected!")
- EXIT_CODE = 0
+ exit_code = TestCase.EX_OK
break
elif "failed to read iid from metadata" in p_console or tries > 5:
- EXIT_CODE = -2
+ exit_code = TestCase.EX_TESTCASE_FAILED
break
elif sec == self.ping_timeout:
self.logger.info("Timeout reached.")
break
elif sec % 10 == 0:
if "request failed" in p_console:
- self.logger.debug("It seems userdata is not supported "
- "in nova boot. Waiting a bit...")
+ self.logger.debug(
+ "It seems userdata is not supported in nova boot. " +
+ "Waiting a bit...")
tries += 1
else:
- self.logger.debug("Pinging %s. Waiting for response..."
- % test_ip)
+ self.logger.debug(
+ "Pinging %s. Waiting for response..." % test_ip)
sec += 1
- return EXIT_CODE
+ return exit_code
+
+
+def _get_userdata(test_ip):
+ """
+ Returns the post VM creation script to be added into the VM's userdata
+ :param test_ip: the IP value to substitute into the script
+ :return: the bash script contents
+ """
+ if test_ip:
+ return ("#!/bin/sh\n\n"
+ "while true; do\n"
+ " ping -c 1 %s 2>&1 >/dev/null\n"
+ " RES=$?\n"
+ " if [ \"Z$RES\" = \"Z0\" ] ; then\n"
+ " echo 'vPing OK'\n"
+ " break\n"
+ " else\n"
+ " echo 'vPing KO'\n"
+ " fi\n"
+ " sleep 1\n"
+ "done\n" % test_ip)
+ return None
if __name__ == '__main__':
diff --git a/functest/opnfv_tests/sdn/odl/odl.py b/functest/opnfv_tests/sdn/odl/odl.py
index ccc1101a..2f3dd74b 100755
--- a/functest/opnfv_tests/sdn/odl/odl.py
+++ b/functest/opnfv_tests/sdn/odl/odl.py
@@ -16,21 +16,24 @@ Example:
$ python odl.py
"""
+from __future__ import division
+
import argparse
import errno
import fileinput
+import logging
import os
import re
import sys
-import urlparse
import robot.api
from robot.errors import RobotError
import robot.run
from robot.utils.robottime import timestamp_to_secs
+from six import StringIO
+from six.moves import urllib
from functest.core import testcase
-import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as op_utils
__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
@@ -70,11 +73,7 @@ class ODLTests(testcase.TestCase):
"csit/suites/integration/basic")
default_suites = [basic_suite_dir, neutron_suite_dir]
res_dir = '/home/opnfv/functest/results/odl/'
- logger = ft_logger.Logger("opendaylight").getLogger()
-
- def __init__(self):
- testcase.TestCase.__init__(self)
- self.case_name = "odl"
+ __logger = logging.getLogger(__name__)
@classmethod
def set_robotframework_vars(cls, odlusername="admin", odlpassword="admin"):
@@ -89,13 +88,13 @@ class ODLTests(testcase.TestCase):
try:
for line in fileinput.input(odl_variables_files,
inplace=True):
- print re.sub("AUTH = .*",
+ print(re.sub("AUTH = .*",
("AUTH = [u'" + odlusername + "', u'" +
odlpassword + "']"),
- line.rstrip())
+ line.rstrip()))
return True
except Exception as ex: # pylint: disable=broad-except
- cls.logger.error("Cannot set ODL creds: %s", str(ex))
+ cls.__logger.error("Cannot set ODL creds: %s", str(ex))
return False
def parse_results(self):
@@ -104,7 +103,12 @@ class ODLTests(testcase.TestCase):
result = robot.api.ExecutionResult(xml_file)
visitor = ODLResultVisitor()
result.visit(visitor)
- self.criteria = result.suite.status
+ try:
+ self.result = 100 * (
+ result.suite.statistics.critical.passed /
+ result.suite.statistics.critical.total)
+ except ZeroDivisionError:
+ self.__logger.error("No test has been ran")
self.start_time = timestamp_to_secs(result.suite.starttime)
self.stop_time = timestamp_to_secs(result.suite.endtime)
self.details = {}
@@ -116,6 +120,7 @@ class ODLTests(testcase.TestCase):
It has been designed to be called in any context.
It requires the following keyword arguments:
+
* odlusername,
* odlpassword,
* osauthurl,
@@ -134,7 +139,7 @@ class ODLTests(testcase.TestCase):
* delete temporary files.
Args:
- **kwargs: Arbitrary keyword arguments.
+ kwargs: Arbitrary keyword arguments.
Returns:
EX_OK if all suites ran well.
@@ -146,7 +151,7 @@ class ODLTests(testcase.TestCase):
odlusername = kwargs['odlusername']
odlpassword = kwargs['odlpassword']
osauthurl = kwargs['osauthurl']
- keystoneip = urlparse.urlparse(osauthurl).hostname
+ keystoneip = urllib.parse.urlparse(osauthurl).hostname
variables = ['KEYSTONE:' + keystoneip,
'NEUTRON:' + kwargs['neutronip'],
'OS_AUTH_URL:"' + osauthurl + '"',
@@ -157,39 +162,30 @@ class ODLTests(testcase.TestCase):
'PORT:' + kwargs['odlwebport'],
'RESTCONFPORT:' + kwargs['odlrestconfport']]
except KeyError as ex:
- self.logger.error("Cannot run ODL testcases. Please check "
- "%s", str(ex))
+ self.__logger.error("Cannot run ODL testcases. Please check "
+ "%s", str(ex))
return self.EX_RUN_ERROR
if self.set_robotframework_vars(odlusername, odlpassword):
try:
os.makedirs(self.res_dir)
except OSError as ex:
if ex.errno != errno.EEXIST:
- self.logger.exception(
+ self.__logger.exception(
"Cannot create %s", self.res_dir)
return self.EX_RUN_ERROR
- stdout_file = os.path.join(self.res_dir, 'stdout.txt')
output_dir = os.path.join(self.res_dir, 'output.xml')
- with open(stdout_file, 'w+') as stdout:
- robot.run(*suites, variable=variables,
- output=output_dir,
- log='NONE',
- report='NONE',
- stdout=stdout)
- stdout.seek(0, 0)
- self.logger.info("\n" + stdout.read())
- self.logger.info("ODL results were successfully generated")
+ stream = StringIO()
+ robot.run(*suites, variable=variables, output=output_dir,
+ log='NONE', report='NONE', stdout=stream)
+ self.__logger.info("\n" + stream.getvalue())
+ self.__logger.info("ODL results were successfully generated")
try:
self.parse_results()
- self.logger.info("ODL results were successfully parsed")
+ self.__logger.info("ODL results were successfully parsed")
except RobotError as ex:
- self.logger.error("Run tests before publishing: %s",
- ex.message)
+ self.__logger.error("Run tests before publishing: %s",
+ ex.message)
return self.EX_RUN_ERROR
- try:
- os.remove(stdout_file)
- except OSError:
- self.logger.warning("Cannot remove %s", stdout_file)
return self.EX_OK
else:
return self.EX_RUN_ERROR
@@ -201,7 +197,7 @@ class ODLTests(testcase.TestCase):
required.
Args:
- **kwargs: Arbitrary keyword arguments.
+ kwargs: Arbitrary keyword arguments.
Returns:
EX_OK if all suites ran well.
@@ -214,7 +210,7 @@ class ODLTests(testcase.TestCase):
except KeyError:
pass
neutron_url = op_utils.get_endpoint(service_type='network')
- kwargs = {'neutronip': urlparse.urlparse(neutron_url).hostname}
+ kwargs = {'neutronip': urllib.parse.urlparse(neutron_url).hostname}
kwargs['odlip'] = kwargs['neutronip']
kwargs['odlwebport'] = '8080'
kwargs['odlrestconfport'] = '8181'
@@ -240,12 +236,12 @@ class ODLTests(testcase.TestCase):
else:
kwargs['odlip'] = os.environ['SDN_CONTROLLER_IP']
except KeyError as ex:
- self.logger.error("Cannot run ODL testcases. "
- "Please check env var: "
- "%s", str(ex))
+ self.__logger.error("Cannot run ODL testcases. "
+ "Please check env var: "
+ "%s", str(ex))
return self.EX_RUN_ERROR
except Exception: # pylint: disable=broad-except
- self.logger.exception("Cannot run ODL testcases.")
+ self.__logger.exception("Cannot run ODL testcases.")
return self.EX_RUN_ERROR
return self.main(suites, **kwargs)
@@ -304,6 +300,7 @@ class ODLParser(object): # pylint: disable=too-few-public-methods
if __name__ == '__main__':
+ logging.basicConfig()
ODL = ODLTests()
PARSER = ODLParser()
ARGS = PARSER.parse_args(sys.argv[1:])
diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py
index d482ae32..5dfff036 100644
--- a/functest/opnfv_tests/sdn/onos/onos.py
+++ b/functest/opnfv_tests/sdn/onos/onos.py
@@ -7,6 +7,7 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
+import logging
import os
import re
import subprocess
@@ -16,24 +17,25 @@ import urlparse
from functest.core import testcase
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as openstack_utils
-logger = ft_logger.Logger(__name__).getLogger()
-
-
class OnosBase(testcase.TestCase):
- onos_repo_path = CONST.dir_repo_onos
- onos_sfc_image_name = CONST.onos_sfc_image_name
- onos_sfc_image_path = os.path.join(CONST.dir_functest_data,
- CONST.onos_sfc_image_file_name)
- onos_sfc_path = os.path.join(CONST.dir_repo_functest,
- CONST.dir_onos_sfc)
-
- def __init__(self):
- super(OnosBase, self).__init__()
+ onos_repo_path = CONST.__getattribute__('dir_repo_onos')
+ onos_sfc_image_name = CONST.__getattribute__('onos_sfc_image_name')
+ onos_sfc_image_path = os.path.join(
+ CONST.__getattribute__('dir_functest_images'),
+ CONST.__getattribute__('onos_sfc_image_file_name'))
+ onos_sfc_path = os.path.join(CONST.__getattribute__('dir_repo_functest'),
+ CONST.__getattribute__('dir_onos_sfc'))
+ installer_type = CONST.__getattribute__('INSTALLER_TYPE')
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "onos_base"
+ super(OnosBase, self).__init__(**kwargs)
def run(self):
self.start_time = time.time()
@@ -41,7 +43,7 @@ class OnosBase(testcase.TestCase):
self._run()
res = testcase.TestCase.EX_OK
except Exception as e:
- logger.error('Error with run: %s', e)
+ self.logger.error('Error with run: %s', e)
res = testcase.TestCase.EX_RUN_ERROR
self.stop_time = time.time()
@@ -52,26 +54,27 @@ class OnosBase(testcase.TestCase):
class Onos(OnosBase):
- def __init__(self):
- super(Onos, self).__init__()
- self.case_name = 'onos'
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "onos"
+ super(Onos, self).__init__(**kwargs)
self.log_path = os.path.join(self.onos_repo_path, 'TestON/logs')
def set_onos_ip(self):
- if (CONST.INSTALLER_TYPE and
- CONST.INSTALLER_TYPE.lower() == 'joid'):
+ if (self.installer_type and
+ self.installer_type.lower() == 'joid'):
sdn_controller_env = os.getenv('SDN_CONTROLLER')
OC1 = re.search(r"\d+\.\d+\.\d+\.\d+", sdn_controller_env).group()
else:
neutron_url = openstack_utils.get_endpoint(service_type='network')
OC1 = urlparse.urlparse(neutron_url).hostname
os.environ['OC1'] = OC1
- logger.debug("ONOS IP is %s" % OC1)
+ self.logger.debug("ONOS IP is %s", OC1)
def run_onos_script(self, testname):
cli_dir = os.path.join(self.onos_repo_path, 'TestON/bin/cli.py')
cmd = '{0} run {1}'.format(cli_dir, testname)
- logger.debug("Run script: %s" % testname)
+ self.logger.debug("Run script: %s", testname)
ft_utils.execute_command_raise(
cmd,
error_msg=('Error when running ONOS script: %s'
@@ -86,8 +89,8 @@ class Onos(OnosBase):
elif os.path.isfile(log):
os.remove(log)
except OSError as e:
- logger.error('Error with deleting file %s: %s',
- log, e.strerror)
+ self.logger.error('Error with deleting file %s: %s',
+ log, e.strerror)
def get_result(self):
cmd = 'grep -rnh Fail {0}'.format(self.log_path)
@@ -97,9 +100,9 @@ class Onos(OnosBase):
stderr=subprocess.STDOUT)
for line in p.stdout:
- logger.debug(line)
+ self.logger.debug(line)
if re.search("\s+[1-9]+\s+", line):
- logger.debug("Testcase Fails\n" + line)
+ self.logger.debug("Testcase Fails\n" + line)
cmd = "grep -rnh 'Execution Time' {0}".format(self.log_path)
result_buffer = os.popen(cmd).read()
@@ -157,10 +160,10 @@ class Onos(OnosBase):
if (result['FUNCvirNet']['result'] == "Success" and
result['FUNCvirNetL3']['result'] == "Success"):
status = "PASS"
- except:
- logger.error("Unable to set ONOS criteria")
+ except Exception:
+ self.logger.error("Unable to set ONOS result")
- self.criteria = status
+ self.result = status
self.details = result
def _run(self):
@@ -172,13 +175,14 @@ class Onos(OnosBase):
class OnosSfc(OnosBase):
- def __init__(self):
- super(OnosSfc, self).__init__()
- self.case_name = 'onos_sfc'
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "onos_sfc"
+ super(OnosSfc, self).__init__(**kwargs)
- def get_ip(type):
+ def get_ip(self, type):
url = openstack_utils.get_endpoint(service_type=type)
- logger.debug('get_ip for %s: %s' % (type, url))
+ self.logger.debug('get_ip for %s: %s', type, url)
return urlparse.urlparse(url).hostname
def update_sfc_onos_file(self, before, after):
@@ -192,6 +196,7 @@ class OnosSfc(OnosBase):
% (before, after)))
def create_image(self):
+ self.logger.warn('inside create_image')
glance_client = openstack_utils.get_glance_client()
image_id = openstack_utils.create_glance_image(
glance_client,
@@ -200,19 +205,20 @@ class OnosSfc(OnosBase):
if image_id is None:
raise Exception('Failed to create image')
- logger.debug("Image '%s' with ID=%s is created successfully."
- % (self.onos_sfc_image_name, image_id))
+ self.logger.debug("Image '%s' with ID=%s is created successfully.",
+ self.onos_sfc_image_name, image_id)
def set_sfc_conf(self):
self.update_sfc_onos_file("keystone_ip", self.get_ip("keystone"))
self.update_sfc_onos_file("neutron_ip", self.get_ip("neutron"))
self.update_sfc_onos_file("nova_ip", self.get_ip("nova"))
self.update_sfc_onos_file("glance_ip", self.get_ip("glance"))
- self.update_sfc_onos_file("console", CONST.OS_PASSWORD)
+ self.update_sfc_onos_file("console",
+ CONST.__getattribute__('OS_PASSWORD'))
neutron_client = openstack_utils.get_neutron_client()
ext_net = openstack_utils.get_external_net(neutron_client)
self.update_sfc_onos_file("admin_floating_net", ext_net)
- logger.debug("SFC configuration is modified")
+ self.logger.debug("SFC configuration is modified")
def sfc_test(self):
cmd = 'python {0}'.format(os.path.join(self.onos_sfc_path, 'sfc.py'))
diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc.py b/functest/opnfv_tests/sdn/onos/sfc/sfc.py
index 22412270..0155d24d 100755
--- a/functest/opnfv_tests/sdn/onos/sfc/sfc.py
+++ b/functest/opnfv_tests/sdn/onos/sfc/sfc.py
@@ -1,4 +1,3 @@
-"""Script to Test the SFC scenarios in ONOS."""
# !/usr/bin/python
#
# Copyright (c) CREATED5 All rights reserved
@@ -22,13 +21,14 @@
# Testcase 7 : Cleanup
# ###########################################################################
#
+"""Script to Test the SFC scenarios in ONOS."""
+import logging
import time
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
from sfc_onos import SfcOnos
-logger = ft_logger.Logger("sfc").getLogger()
+logger = logging.getLogger(__name__)
Sfc_obj = SfcOnos()
OK = 200
@@ -174,4 +174,5 @@ def main():
if __name__ == '__main__':
+ logging.basicConfig()
main()
diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
index c2198690..1101f239 100644
--- a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
+++ b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
@@ -1,3 +1,4 @@
+import logging
import os
import re
import time
@@ -8,8 +9,6 @@ from multiprocessing import Process
from multiprocessing import Queue
from pexpect import pxssh
-import functest.utils.functest_logger as ft_logger
-
from functest.utils.constants import CONST
OK = 200
@@ -23,7 +22,7 @@ class SfcOnos(object):
def __init__(self):
"""Initialization of variables."""
- self.logger = ft_logger.Logger("sfc_fun").getLogger()
+ self.logger = logging.getLogger(__name__)
self.osver = "v2.0"
self.token_id = 0
self.net_id = 0
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py b/functest/opnfv_tests/sdn/onos/teston/adapters/client.py
index 81d5f7d7..a88d2f06 100644
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py
+++ b/functest/opnfv_tests/sdn/onos/teston/adapters/client.py
@@ -11,17 +11,17 @@ Description:
#
"""
import json
+import logging
import pexpect
import requests
import time
from environment import Environment
-import functest.utils.functest_logger as ft_logger
class Client(Environment):
- logger = ft_logger.Logger("client").getLogger()
+ logger = logging.getLogger(__name__)
def __init__(self):
Environment.__init__(self)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py b/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
index 3786945d..dfaa5cc1 100644
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
+++ b/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
@@ -13,17 +13,17 @@ Description:
# http://www.apache.org/licenses/LICENSE-2.0
#
"""
+import logging
import os
import pexpect
import re
from foundation import Foundation
-import functest.utils.functest_logger as ft_logger
class Connection(Foundation):
- logger = ft_logger.Logger("connection").getLogger()
+ logger = logging.getLogger(__name__)
def __init__(self):
Foundation.__init__(self)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py b/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
index 046a821d..cb75b5c3 100644
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
+++ b/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
@@ -15,6 +15,7 @@ Description:
#
"""
+import logging
import pexpect
import pxssh
import re
@@ -23,12 +24,11 @@ import sys
import time
from connection import Connection
-import functest.utils.functest_logger as ft_logger
class Environment(Connection):
- logger = ft_logger.Logger("environment").getLogger()
+ logger = logging.getLogger(__name__)
def __init__(self):
Connection.__init__(self)
diff --git a/functest/opnfv_tests/vnf/aaa/aaa.py b/functest/opnfv_tests/vnf/aaa/aaa.py
index bdedcf7c..0030256c 100755
--- a/functest/opnfv_tests/vnf/aaa/aaa.py
+++ b/functest/opnfv_tests/vnf/aaa/aaa.py
@@ -7,21 +7,23 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
+import logging
import sys
import argparse
import functest.core.testcase as testcase
-import functest.core.vnf_base as vnf_base
-import functest.utils.functest_logger as ft_logger
+import functest.core.vnf as vnf
-class AaaVnf(vnf_base.VnfOnBoardingBase):
+class AaaVnf(vnf.VnfOnBoarding):
- logger = ft_logger.Logger("VNF AAA").getLogger()
+ logger = logging.getLogger(__name__)
- def __init__(self):
- super(AaaVnf, self).__init__(case="aaa")
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "aaa"
+ super(AaaVnf, self).__init__(**kwargs)
def deploy_orchestrator(self):
self.logger.info("No VNFM needed to deploy a free radius here")
@@ -47,7 +49,7 @@ class AaaVnf(vnf_base.VnfOnBoardingBase):
def main(self, **kwargs):
self.logger.info("AAA VNF onboarding")
self.execute()
- if self.criteria is "PASS":
+ if self.result is "PASS":
return self.EX_OK
else:
return self.EX_RUN_ERROR
@@ -56,7 +58,9 @@ class AaaVnf(vnf_base.VnfOnBoardingBase):
kwargs = {}
return self.main(**kwargs)
+
if __name__ == '__main__':
+ logging.basicConfig()
parser = argparse.ArgumentParser()
args = vars(parser.parse_args())
aaa_vnf = AaaVnf()
diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
index f21ce3f9..42d31e3b 100644
--- a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
+++ b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
@@ -7,26 +7,25 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
import json
+import logging
import os
import shutil
import requests
-import functest.core.vnf_base as vnf_base
+import functest.core.vnf as vnf
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
-class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase):
+class ClearwaterOnBoardingBase(vnf.VnfOnBoarding):
- def __init__(self, project='functest', case='', repo='', cmd=''):
- self.logger = ft_logger.Logger(__name__).getLogger()
- super(ClearwaterOnBoardingBase, self).__init__(
- project, case, repo, cmd)
+ def __init__(self, **kwargs):
+ self.logger = logging.getLogger(__name__)
+ super(ClearwaterOnBoardingBase, self).__init__(**kwargs)
self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf', 'ims')
self.data_dir = CONST.dir_ims_data
- self.result_dir = os.path.join(CONST.dir_results, case)
+ self.result_dir = os.path.join(CONST.dir_results, self.case_name)
self.test_dir = CONST.dir_repo_vims_test
if not os.path.exists(self.data_dir):
@@ -46,8 +45,7 @@ class ClearwaterOnBoardingBase(vnf_base.VnfOnBoardingBase):
rq = requests.post(account_url, data=params)
output_dict['login'] = params
if rq.status_code != 201 and rq.status_code != 409:
- raise Exception("Unable to create an account for number"
- " provision: %s" % rq.json()['reason'])
+ raise Exception("Unable to create an account for number provision")
self.logger.info('Account is created on Ellis: %s', params)
session_url = 'http://{0}/session'.format(ellis_ip)
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
index 404f208e..ba4c5790 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
@@ -7,6 +7,7 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
+import logging
import os
import sys
import time
@@ -18,17 +19,17 @@ from functest.opnfv_tests.vnf.ims.clearwater import Clearwater
import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base
from functest.opnfv_tests.vnf.ims.orchestrator_cloudify import Orchestrator
from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
- def __init__(self, project='functest', case='cloudify_ims',
- repo='', cmd=''):
- super(CloudifyIms, self).__init__(project, case, repo, cmd)
- self.logger = ft_logger.Logger(__name__).getLogger()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "cloudify_ims"
+ super(CloudifyIms, self).__init__(**kwargs)
+ self.logger = logging.getLogger(__name__)
# Retrieve the configuration
try:
@@ -276,7 +277,7 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
self.logger.info("Cloudify IMS VNF onboarding test starting")
self.execute()
self.logger.info("Cloudify IMS VNF onboarding test executed")
- if self.criteria is "PASS":
+ if self.result is "PASS":
return self.EX_OK
else:
return self.EX_RUN_ERROR
diff --git a/functest/opnfv_tests/vnf/ims/opera_ims.py b/functest/opnfv_tests/vnf/ims/opera_ims.py
index d022b3c7..8c33d16e 100644
--- a/functest/opnfv_tests/vnf/ims/opera_ims.py
+++ b/functest/opnfv_tests/vnf/ims/opera_ims.py
@@ -8,6 +8,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
import json
+import logging
import os
import time
@@ -15,16 +16,15 @@ from opera import openo_connect
import requests
import functest.opnfv_tests.vnf.ims.clearwater_ims_base as clearwater_ims_base
-from functest.utils.constants import CONST
-import functest.utils.functest_logger as ft_logger
class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
- def __init__(self, project='functest', case='opera_ims',
- repo=CONST.dir_repo_opera, cmd=''):
- super(OperaIms, self).__init__(project, case, repo, cmd)
- self.logger = ft_logger.Logger(__name__).getLogger()
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "opera_ims"
+ super(OperaIms, self).__init__(**kwargs)
+ self.logger = logging.getLogger(__name__)
self.ellis_file = os.path.join(self.result_dir, 'ellis.info')
self.live_test_file = os.path.join(self.result_dir,
'live_test_report.json')
@@ -64,27 +64,27 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
self.logger.info('VNFM IP: %s', vnfm_ip)
vnf_status_url = 'http://{0}:5000/api/v1/model/status'.format(vnfm_ip)
vnf_alive = False
- retry = 15
+ retry = 40
self.logger.info('Check the VNF status')
while retry > 0:
- rq = requests.get(vnf_status_url)
+ rq = requests.get(vnf_status_url, timeout=90)
response = rq.json()
vnf_alive = response['vnf_alive']
msg = response['msg']
self.logger.info(msg)
if vnf_alive:
break
- self.logger.info('check again in one minute...')
+ self.logger.info('check again in one and half a minute...')
retry = retry - 1
- time.sleep(60)
+ time.sleep(90)
if not vnf_alive:
raise Exception('VNF failed to start: {0}'.format(msg))
ellis_config_url = ('http://{0}:5000/api/v1/model/ellis/configure'
.format(vnfm_ip))
- rq = requests.get(ellis_config_url, timeout=60)
+ rq = requests.get(ellis_config_url, timeout=90)
if rq.json() and not rq.json()['ellis_ok']:
self.logger.error(rq.json()['data'])
raise Exception('Failed to configure Ellis')
@@ -92,7 +92,7 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
self.logger.info('Get Clearwater deployment detail')
vnf_info_url = ('http://{0}:5000/api/v1/model/output'
.format(vnfm_ip))
- rq = requests.get(vnf_info_url, timeout=60)
+ rq = requests.get(vnf_info_url, timeout=90)
data = rq.json()['data']
self.logger.info(data)
bono_ip = data['bono_ip']
@@ -119,7 +119,7 @@ class OperaIms(clearwater_ims_base.ClearwaterOnBoardingBase):
self.logger.info("Start to run Opera vIMS VNF onboarding test")
self.execute()
self.logger.info("Opera vIMS VNF onboarding test finished")
- if self.criteria is "PASS":
+ if self.result is "PASS":
return self.EX_OK
else:
return self.EX_RUN_ERROR
diff --git a/functest/opnfv_tests/vnf/ims/orchestra_ims.py b/functest/opnfv_tests/vnf/ims/orchestra_ims.py
index 5c19be09..6f341970 100755
--- a/functest/opnfv_tests/vnf/ims/orchestra_ims.py
+++ b/functest/opnfv_tests/vnf/ims/orchestra_ims.py
@@ -8,16 +8,16 @@
# http://www.apache.org/licenses/LICENSE-2.0
import json
+import logging
+import os
import socket
import sys
import time
import yaml
-import functest.core.vnf_base as vnf_base
-import functest.utils.functest_logger as ft_logger
+import functest.core.vnf as vnf
import functest.utils.functest_utils as ft_utils
import functest.utils.openstack_utils as os_utils
-import os
from functest.utils.constants import CONST
from org.openbaton.cli.agents.agents import MainAgent
@@ -76,18 +76,18 @@ def servertest(host, port):
return True
-class ImsVnf(vnf_base.VnfOnBoardingBase):
+class ImsVnf(vnf.VnfOnBoarding):
- def __init__(self, project='functest', case='orchestra_ims',
+ def __init__(self, project='functest', case_name='orchestra_ims',
repo='', cmd=''):
- super(ImsVnf, self).__init__(project, case, repo, cmd)
+ super(ImsVnf, self).__init__(project, case_name, repo, cmd)
self.ob_password = "openbaton"
self.ob_username = "admin"
self.ob_https = False
self.ob_port = "8080"
self.ob_ip = "localhost"
self.ob_instance_id = ""
- self.logger = ft_logger.Logger("orchestra_ims").getLogger()
+ self.logger = logging.getLogger(__name__)
self.case_dir = os.path.join(CONST.dir_functest_test, 'vnf/ims/')
self.data_dir = CONST.dir_ims_data
self.test_dir = CONST.dir_repo_vims_test
@@ -103,7 +103,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
try:
self.config = CONST.__getattribute__(
'vnf_{}_config'.format(self.case_name))
- except:
+ except BaseException:
raise Exception("Orchestra VNF config file not found")
config_file = self.case_dir + self.config
self.imagename = get_config("openbaton.imagename", config_file)
@@ -115,6 +115,8 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
config_file)
self.images = get_config("tenant_images", config_file)
self.ims_conf = get_config("vIMS", config_file)
+ self.userdata_file = get_config("openbaton.userdata.file",
+ config_file)
def deploy_orchestrator(self, **kwargs):
self.logger.info("Additional pre-configuration steps")
@@ -132,7 +134,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
image_id = os_utils.get_image_id(glance_client,
image_name)
self.logger.info("image_id: %s" % image_id)
- except:
+ except BaseException:
self.logger.error("Unexpected error: %s" % sys.exc_info()[0])
if image_id == '':
@@ -153,7 +155,8 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
"192.168.100.0/24")
# orchestrator VM flavor
- self.logger.info("Check if Flavor is available, if not create one")
+ self.logger.info(
+ "Check if orchestra Flavor is available, if not create one")
flavor_exist, flavor_id = os_utils.get_or_create_flavor(
"orchestra",
"4096",
@@ -210,8 +213,13 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
bootstrap = "sh ./bootstrap release -configFile=./config_file"
userdata += bootstrap + "\n"
userdata += "echo \"Setting 'nfvo.plugin.timeout' to '300000'\"\n"
- userdata += ("echo \"nfvo.plugin.timeout=300000\" >> "
+ userdata += ("echo \"nfvo.plugin.timeout=600000\" >> "
"/etc/openbaton/openbaton-nfvo.properties\n")
+ userdata += (
+ "wget %s -O /etc/openbaton/openbaton-vnfm-generic-user-data.sh\n" %
+ self.userdata_file)
+ userdata += "sed -i '113i\ \ \ \ sleep 60' " \
+ "/etc/openbaton/openbaton-vnfm-generic-user-data.sh\n"
userdata += "echo \"Starting NFVO\"\n"
userdata += "service openbaton-nfvo restart\n"
userdata += "echo \"Starting Generic VNFM\"\n"
@@ -283,7 +291,10 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.ob_username = "admin"
self.ob_https = False
self.ob_port = "8080"
-
+ self.logger.info("Waiting for all components up and running...")
+ time.sleep(60)
+ self.details["orchestrator"] = {
+ 'status': "PASS", 'result': "Deploy Open Baton NFVO: OK"}
self.logger.info("Deploy Open Baton NFVO: OK")
def deploy_vnf(self):
@@ -296,6 +307,16 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
username=self.ob_username,
password=self.ob_password)
+ self.logger.info(
+ "Check if openims Flavor is available, if not create one")
+ flavor_exist, flavor_id = os_utils.get_or_create_flavor(
+ "m1.small",
+ "2048",
+ '20',
+ '1',
+ public=True)
+ self.logger.debug("Flavor id: %s" % flavor_id)
+
self.logger.info("Getting project 'default'...")
project_agent = self.main_agent.get_agent("project", self.ob_projectid)
for p in json.loads(project_agent.find()):
@@ -311,9 +332,16 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
creds = os_utils.get_credentials()
self.logger.info("PoP creds: %s" % creds)
- project_id = os_utils.get_tenant_id(
- os_utils.get_keystone_client(),
- creds.get("project_name"))
+ if os_utils.is_keystone_v3():
+ self.logger.info(
+ "Using v3 API of OpenStack... -> Using OS_PROJECT_ID")
+ project_id = os_utils.get_tenant_id(
+ os_utils.get_keystone_client(),
+ creds.get("project_name"))
+ else:
+ self.logger.info(
+ "Using v2 API of OpenStack... -> Using OS_TENANT_NAME")
+ project_id = creds.get("tenant_name")
self.logger.debug("project id: %s" % project_id)
@@ -381,16 +409,17 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.nsr = json.loads(nsr_agent.find(self.nsr.get('id')))
if self.nsr.get("status") == 'ACTIVE':
- deploy_vnf = {'status': "PASS", 'result': self.nsr}
+ self.details["vnf"] = {'status': "PASS", 'result': self.nsr}
self.logger.info("Deploy VNF: OK")
else:
- deploy_vnf = {'status': "FAIL", 'result': self.nsr}
+ self.details["vnf"] = {'status': "FAIL", 'result': self.nsr}
+ self.logger.error(self.nsr)
self.step_failure("Deploy VNF: ERROR")
self.ob_nsr_id = self.nsr.get("id")
self.logger.info(
"Sleep for 60s to ensure that all services are up and running...")
time.sleep(60)
- return deploy_vnf
+ return self.details.get("vnf")
def test_vnf(self):
# Adaptations probably needed
@@ -427,9 +456,18 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
"VNFC instance %s is not reachable "
"at %s:%s" % (vnfci.get('hostname'),
floatingIp.get('ip'), port))
+ self.details["test_vnf"] = {
+ 'status': "FAIL", 'result': (
+ "Port %s of server %s -> %s is "
+ "not reachable" %
+ (port, vnfci.get('hostname'),
+ floatingIp.get('ip')))}
self.step_failure("Test VNF: ERROR")
+ self.details["test_vnf"] = {
+ 'status': "PASS",
+ 'result': "All tests have been executed successfully"}
self.logger.info("Test VNF: OK")
- return
+ return self.details.get('test_vnf')
def clean(self):
self.main_agent.get_agent(
@@ -446,7 +484,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
self.logger.info("Orchestra IMS VNF onboarding test starting")
self.execute()
self.logger.info("Orchestra IMS VNF onboarding test executed")
- if self.criteria is "PASS":
+ if self.result is "PASS":
return self.EX_OK
else:
return self.EX_RUN_ERROR
@@ -457,6 +495,7 @@ class ImsVnf(vnf_base.VnfOnBoardingBase):
if __name__ == '__main__':
+ logging.basicConfig()
test = ImsVnf()
test.deploy_orchestrator()
test.deploy_vnf()
diff --git a/functest/opnfv_tests/vnf/ims/orchestra_ims.yaml b/functest/opnfv_tests/vnf/ims/orchestra_ims.yaml
index 5923a775..5b25d3c9 100644
--- a/functest/opnfv_tests/vnf/ims/orchestra_ims.yaml
+++ b/functest/opnfv_tests/vnf/ims/orchestra_ims.yaml
@@ -4,6 +4,8 @@ tenant_images:
openbaton:
bootstrap_link: http://get.openbaton.org/bootstraps/bootstrap_3.2.0_opnfv/bootstrap
bootstrap_config_link: http://get.openbaton.org/bootstraps/bootstrap_3.2.0_opnfv/bootstrap-config-file
+ userdata:
+ file: https://raw.githubusercontent.com/openbaton/generic-vnfm/3.2.0/src/main/resources/user-data.sh
marketplace_link: http://marketplace.openbaton.org:8082/api/v1/nsds/fokus/OpenImsCore/3.2.0/json
imagename: ubuntu_14.04
vIMS:
diff --git a/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py
index 82a9dca0..4ceeb25f 100644
--- a/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py
+++ b/functest/opnfv_tests/vnf/ims/orchestrator_cloudify.py
@@ -11,6 +11,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
########################################################################
+import logging
import os
import shutil
import subprocess32 as subprocess
@@ -18,8 +19,6 @@ import yaml
from git import Repo
-import functest.utils.functest_logger as ft_logger
-
class Orchestrator(object):
@@ -29,7 +28,7 @@ class Orchestrator(object):
self.input_file = 'inputs.yaml'
self.manager_blueprint = False
self.config = inputs
- self.logger = ft_logger.Logger("Orchestrator").getLogger()
+ self.logger = logging.getLogger(__name__)
self.manager_up = False
def set_credentials(self, username, password, tenant_name, auth_url):
diff --git a/functest/opnfv_tests/vnf/rnc/parser.py b/functest/opnfv_tests/vnf/rnc/parser.py
deleted file mode 100644
index 133145d7..00000000
--- a/functest/opnfv_tests/vnf/rnc/parser.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 ZTE Corporation
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-import functest.core.feature as base
-
-
-class Parser(base.Feature):
- def __init__(self):
- super(Parser, self).__init__(project='parser',
- case='parser-basics',
- repo='dir_repo_parser')
- self.cmd = 'cd %s/tests && ./functest_run.sh' % self.repo
diff --git a/functest/opnfv_tests/vnf/router/vyos_vrouter.py b/functest/opnfv_tests/vnf/router/vyos_vrouter.py
index e188c3fb..5654278d 100644
--- a/functest/opnfv_tests/vnf/router/vyos_vrouter.py
+++ b/functest/opnfv_tests/vnf/router/vyos_vrouter.py
@@ -14,10 +14,11 @@ RESULT_DETAILS_FILE = "test_result.json"
class VrouterVnf(base.Feature):
- def __init__(self):
- super(VrouterVnf, self).__init__(project='functest',
- case='vyos_vrouter',
- repo='dir_repo_vrouter')
+ def __init__(self, **kwargs):
+ kwargs["repo"] = 'dir_repo_vrouter'
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "vyos_vrouter"
+ super(VrouterVnf, self).__init__(**kwargs)
self.cmd = 'cd %s && ./run.sh' % self.repo
def set_result_details(self):
@@ -28,6 +29,6 @@ class VrouterVnf(base.Feature):
f.close()
def log_results(self):
- if self.criteria == 'PASS':
+ if self.result == 'PASS':
self.set_result_details()
super(VrouterVnf, self).log_results()
diff --git a/functest/tests/unit/ci/test_generate_report.py b/functest/tests/unit/ci/test_generate_report.py
deleted file mode 100644
index 2225586f..00000000
--- a/functest/tests/unit/ci/test_generate_report.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/env python
-
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-import logging
-import unittest
-import urllib2
-
-import mock
-
-from functest.ci import generate_report as gen_report
-from functest.tests.unit import test_utils
-from functest.utils import functest_utils as ft_utils
-from functest.utils.constants import CONST
-
-
-class GenerateReportTesting(unittest.TestCase):
-
- logging.disable(logging.CRITICAL)
-
- def test_init(self):
- test_array = gen_report.init()
- self.assertEqual(test_array, [])
-
- @mock.patch('functest.ci.generate_report.urllib2.urlopen',
- side_effect=urllib2.URLError('no host given'))
- def test_get_results_from_db_fail(self, mock_method):
- url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(),
- CONST.BUILD_TAG)
- self.assertIsNone(gen_report.get_results_from_db())
- mock_method.assert_called_once_with(url)
-
- @mock.patch('functest.ci.generate_report.urllib2.urlopen',
- return_value={'results': []})
- def test_get_results_from_db_success(self, mock_method):
- url = "%s/results?build_tag=%s" % (ft_utils.get_db_url(),
- CONST.BUILD_TAG)
- self.assertEqual(gen_report.get_results_from_db(), None)
- mock_method.assert_called_once_with(url)
-
- def test_get_data(self):
- self.assertIsInstance(gen_report.get_data({'result': ''}, ''), dict)
-
- def test_print_line_with_ci_run(self):
- CONST.IS_CI_RUN = True
- w1 = 'test_print_line'
- test_str = ("| %s| %s| %s| %s| %s|\n"
- % (w1.ljust(gen_report.COL_1_LEN - 1),
- ''.ljust(gen_report.COL_2_LEN - 1),
- ''.ljust(gen_report.COL_3_LEN - 1),
- ''.ljust(gen_report.COL_4_LEN - 1),
- ''.ljust(gen_report.COL_5_LEN - 1)))
- self.assertEqual(gen_report.print_line(w1), test_str)
-
- def test_print_line_without_ci_run(self):
- CONST.IS_CI_RUN = False
- w1 = 'test_print_line'
- test_str = ("| %s| %s| %s| %s|\n"
- % (w1.ljust(gen_report.COL_1_LEN - 1),
- ''.ljust(gen_report.COL_2_LEN - 1),
- ''.ljust(gen_report.COL_3_LEN - 1),
- ''.ljust(gen_report.COL_4_LEN - 1)))
- self.assertEqual(gen_report.print_line(w1), test_str)
-
- def test_print_line_no_column_with_ci_run(self):
- CONST.IS_CI_RUN = True
- TOTAL_LEN = gen_report.COL_1_LEN + gen_report.COL_2_LEN
- TOTAL_LEN += gen_report.COL_3_LEN + gen_report.COL_4_LEN + 2
- TOTAL_LEN += gen_report.COL_5_LEN + 1
- test_str = ("| %s|\n" % 'test'.ljust(TOTAL_LEN))
- self.assertEqual(gen_report.print_line_no_columns('test'), test_str)
-
- def test_print_line_no_column_without_ci_run(self):
- CONST.IS_CI_RUN = False
- TOTAL_LEN = gen_report.COL_1_LEN + gen_report.COL_2_LEN
- TOTAL_LEN += gen_report.COL_3_LEN + gen_report.COL_4_LEN + 2
- test_str = ("| %s|\n" % 'test'.ljust(TOTAL_LEN))
- self.assertEqual(gen_report.print_line_no_columns('test'), test_str)
-
- def test_print_separator_with_ci_run(self):
- CONST.IS_CI_RUN = True
- test_str = ("+" + "=" * gen_report.COL_1_LEN +
- "+" + "=" * gen_report.COL_2_LEN +
- "+" + "=" * gen_report.COL_3_LEN +
- "+" + "=" * gen_report.COL_4_LEN +
- "+" + "=" * gen_report.COL_5_LEN)
- test_str += '+\n'
- self.assertEqual(gen_report.print_separator(), test_str)
-
- def test_print_separator_without_ci_run(self):
- CONST.IS_CI_RUN = False
- test_str = ("+" + "=" * gen_report.COL_1_LEN +
- "+" + "=" * gen_report.COL_2_LEN +
- "+" + "=" * gen_report.COL_3_LEN +
- "+" + "=" * gen_report.COL_4_LEN)
- test_str += "+\n"
- self.assertEqual(gen_report.print_separator(), test_str)
-
- @mock.patch('functest.ci.generate_report.logger.info')
- def test_main_with_ci_run(self, mock_method):
- CONST.IS_CI_RUN = True
- gen_report.main()
- mock_method.assert_called_once_with(test_utils.SubstrMatch('URL'))
-
- @mock.patch('functest.ci.generate_report.logger.info')
- def test_main_with_ci_loop(self, mock_method):
- CONST.CI_LOOP = 'daily'
- gen_report.main()
- mock_method.assert_called_once_with(test_utils.SubstrMatch('CI LOOP'))
-
- @mock.patch('functest.ci.generate_report.logger.info')
- def test_main_with_scenario(self, mock_method):
- CONST.DEPLOY_SCENARIO = 'test_scenario'
- gen_report.main()
- mock_method.assert_called_once_with(test_utils.SubstrMatch('SCENARIO'))
-
- @mock.patch('functest.ci.generate_report.logger.info')
- def test_main_with_build_tag(self, mock_method):
- CONST.BUILD_TAG = 'test_build_tag'
- gen_report.main()
- mock_method.assert_called_once_with(test_utils.
- SubstrMatch('BUILD TAG'))
-
-
-if __name__ == "__main__":
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_prepare_env.py b/functest/tests/unit/ci/test_prepare_env.py
index 714dd13c..fbb59651 100644
--- a/functest/tests/unit/ci/test_prepare_env.py
+++ b/functest/tests/unit/ci/test_prepare_env.py
@@ -33,7 +33,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_missing_inst_type(self, mock_logger_warn,
mock_logger_info):
- CONST.INSTALLER_TYPE = None
+ CONST.__setattr__('INSTALLER_TYPE', None)
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -44,7 +44,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_missing_inst_ip(self, mock_logger_warn,
mock_logger_info):
- CONST.INSTALLER_IP = None
+ CONST.__setattr__('INSTALLER_IP', None)
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -61,7 +61,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_inst_ip(self, mock_logger_warn,
mock_logger_info):
- CONST.INSTALLER_IP = mock.Mock()
+ CONST.__setattr__('INSTALLER_IP', mock.Mock())
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -72,7 +72,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_missing_scenario(self, mock_logger_warn,
mock_logger_info):
- CONST.DEPLOY_SCENARIO = None
+ CONST.__setattr__('DEPLOY_SCENARIO', None)
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -84,7 +84,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_scenario(self, mock_logger_warn,
mock_logger_info):
- CONST.DEPLOY_SCENARIO = 'test_scenario'
+ CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -95,7 +95,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_ci_debug(self, mock_logger_warn,
mock_logger_info):
- CONST.CI_DEBUG = mock.Mock()
+ CONST.__setattr__('CI_DEBUG', mock.Mock())
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -106,7 +106,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_node(self, mock_logger_warn,
mock_logger_info):
- CONST.NODE_NAME = mock.Mock()
+ CONST.__setattr__('NODE_NAME', mock.Mock())
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -117,7 +117,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_build_tag(self, mock_logger_warn,
mock_logger_info):
- CONST.BUILD_TAG = mock.Mock()
+ CONST.__setattr__('BUILD_TAG', mock.Mock())
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -129,7 +129,7 @@ class PrepareEnvTesting(unittest.TestCase):
@mock.patch('functest.ci.prepare_env.logger.warning')
def test_check_env_variables_with_is_ci_run(self, mock_logger_warn,
mock_logger_info):
- CONST.IS_CI_RUN = mock.Mock()
+ CONST.__setattr__('IS_CI_RUN', mock.Mock())
prepare_env.check_env_variables()
mock_logger_info.assert_any_call("Checking environment variables"
"...")
@@ -140,11 +140,11 @@ class PrepareEnvTesting(unittest.TestCase):
def test_get_deployment_handler_missing_const_vars(self):
with mock.patch('functest.ci.prepare_env.'
'factory.Factory.get_handler') as m:
- CONST.INSTALLER_IP = None
+ CONST.__setattr__('INSTALLER_IP', None)
prepare_env.get_deployment_handler()
self.assertFalse(m.called)
- CONST.INSTALLER_TYPE = None
+ CONST.__setattr__('INSTALLER_TYPE', None)
prepare_env.get_deployment_handler()
self.assertFalse(m.called)
@@ -156,8 +156,8 @@ class PrepareEnvTesting(unittest.TestCase):
mock.patch('functest.ci.prepare_env.'
'ft_utils.get_parameter_from_yaml',
side_effect=ValueError):
- CONST.INSTALLER_IP = 'test_ip'
- CONST.INSTALLER_TYPE = 'test_inst_type'
+ CONST.__setattr__('INSTALLER_IP', 'test_ip')
+ CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
opnfv_constants.INSTALLERS = ['test_inst_type']
prepare_env.get_deployment_handler()
msg = ('Printing deployment info is not supported for '
@@ -172,8 +172,8 @@ class PrepareEnvTesting(unittest.TestCase):
side_effect=Exception), \
mock.patch('functest.ci.prepare_env.'
'ft_utils.get_parameter_from_yaml'):
- CONST.INSTALLER_IP = 'test_ip'
- CONST.INSTALLER_TYPE = 'test_inst_type'
+ CONST.__setattr__('INSTALLER_IP', 'test_ip')
+ CONST.__setattr__('INSTALLER_TYPE', 'test_inst_type')
opnfv_constants.INSTALLERS = ['test_inst_type']
prepare_env.get_deployment_handler()
self.assertTrue(mock_debug.called)
@@ -188,12 +188,21 @@ class PrepareEnvTesting(unittest.TestCase):
as mock_method:
prepare_env.create_directories()
mock_logger_info.assert_any_call("Creating needed directories...")
- mock_method.assert_any_call(CONST.dir_functest_conf)
- mock_method.assert_any_call(CONST.dir_functest_data)
+ mock_method.assert_any_call(
+ CONST.__getattribute__('dir_functest_conf'))
+ mock_method.assert_any_call(
+ CONST.__getattribute__('dir_functest_data'))
+ mock_method.assert_any_call(
+ CONST.__getattribute__('dir_functest_images'))
mock_logger_info.assert_any_call(" %s created." %
- CONST.dir_functest_conf)
+ CONST.__getattribute__(
+ 'dir_functest_conf'))
mock_logger_info.assert_any_call(" %s created." %
- CONST.dir_functest_data)
+ CONST.__getattribute__(
+ 'dir_functest_data'))
+ mock_logger_info.assert_any_call(" %s created." %
+ CONST.__getattribute__(
+ 'dir_functest_images'))
@mock.patch('functest.ci.prepare_env.logger.info')
@mock.patch('functest.ci.prepare_env.logger.debug')
@@ -204,9 +213,14 @@ class PrepareEnvTesting(unittest.TestCase):
prepare_env.create_directories()
mock_logger_info.assert_any_call("Creating needed directories...")
mock_logger_debug.assert_any_call(" %s already exists." %
- CONST.dir_functest_conf)
+ CONST.__getattribute__(
+ 'dir_functest_conf'))
+ mock_logger_debug.assert_any_call(" %s already exists." %
+ CONST.__getattribute__(
+ 'dir_functest_data'))
mock_logger_debug.assert_any_call(" %s already exists." %
- CONST.dir_functest_data)
+ CONST.__getattribute__(
+ 'dir_functest_images'))
def _get_env_cred_dict(self, os_prefix=''):
return {'OS_USERNAME': os_prefix + 'username',
@@ -230,24 +244,24 @@ class PrepareEnvTesting(unittest.TestCase):
mock.patch('functest.ci.prepare_env.os.path.getsize',
return_value=0), \
self.assertRaises(Exception):
- CONST.openstack_creds = 'test_creds'
+ CONST.__setattr__('openstack_creds', 'test_creds')
prepare_env.source_rc_file()
def test_source_rc_missing_installer_ip(self):
with mock.patch('functest.ci.prepare_env.os.path.isfile',
return_value=False), \
self.assertRaises(Exception):
- CONST.INSTALLER_IP = None
- CONST.openstack_creds = 'test_creds'
+ CONST.__setattr__('INSTALLER_IP', None)
+ CONST.__setattr__('openstack_creds', 'test_creds')
prepare_env.source_rc_file()
def test_source_rc_missing_installer_type(self):
with mock.patch('functest.ci.prepare_env.os.path.isfile',
return_value=False), \
self.assertRaises(Exception):
- CONST.INSTALLER_IP = 'test_ip'
- CONST.openstack_creds = 'test_creds'
- CONST.INSTALLER_TYPE = 'test_type'
+ CONST.__setattr__('INSTALLER_IP', 'test_ip')
+ CONST.__setattr__('openstack_creds', 'test_creds')
+ CONST.__setattr__('INSTALLER_TYPE', 'test_type')
opnfv_constants.INSTALLERS = []
prepare_env.source_rc_file()
@@ -259,9 +273,9 @@ class PrepareEnvTesting(unittest.TestCase):
mock.patch('functest.ci.prepare_env.subprocess.Popen') \
as mock_subproc_popen, \
self.assertRaises(Exception):
- CONST.openstack_creds = 'test_creds'
- CONST.INSTALLER_IP = None
- CONST.INSTALLER_TYPE = 'test_type'
+ CONST.__setattr__('openstack_creds', 'test_creds')
+ CONST.__setattr__('INSTALLER_IP', None)
+ CONST.__setattr__('INSTALLER_TYPE', 'test_type')
opnfv_constants.INSTALLERS = ['test_type']
process_mock = mock.Mock()
@@ -281,7 +295,7 @@ class PrepareEnvTesting(unittest.TestCase):
return_value={'tkey1': 'tvalue1'}), \
mock.patch('functest.ci.prepare_env.os.remove') as m, \
mock.patch('functest.ci.prepare_env.yaml.dump'):
- CONST.DEPLOY_SCENARIO = 'test_scenario'
+ CONST.__setattr__('DEPLOY_SCENARIO', 'test_scenario')
prepare_env.patch_file('test_file')
self.assertTrue(m.called)
@@ -321,12 +335,12 @@ class PrepareEnvTesting(unittest.TestCase):
cmd = "rally deployment destroy opnfv-rally"
error_msg = "Deployment %s does not exist." % \
- CONST.rally_deployment_name
+ CONST.__getattribute__('rally_deployment_name')
mock_logger_info.assert_any_call("Creating Rally environment...")
mock_exec.assert_any_call(cmd, error_msg=error_msg, verbose=False)
cmd = "rally deployment create --file=rally_conf.json --name="
- cmd += CONST.rally_deployment_name
+ cmd += CONST.__getattribute__('rally_deployment_name')
error_msg = "Problem while creating Rally deployment"
mock_exec_raise.assert_any_call(cmd, error_msg=error_msg)
@@ -352,7 +366,7 @@ class PrepareEnvTesting(unittest.TestCase):
'stdout.readline.return_value': '0'}
mock_popen.configure_mock(**attrs)
- CONST.tempest_deployment_name = 'test_dep_name'
+ CONST.__setattr__('tempest_deployment_name', 'test_dep_name')
with mock.patch('functest.ci.prepare_env.'
'ft_utils.execute_command_raise',
side_effect=Exception), \
@@ -379,7 +393,7 @@ class PrepareEnvTesting(unittest.TestCase):
with mock.patch('functest.ci.prepare_env.os.path.isfile',
return_value=False), \
self.assertRaises(Exception):
- prepare_env.check_environment()
+ prepare_env.check_environment()
@mock.patch('functest.ci.prepare_env.sys.exit')
@mock.patch('functest.ci.prepare_env.logger.error')
@@ -431,7 +445,8 @@ class PrepareEnvTesting(unittest.TestCase):
self.assertTrue(mock_install_rally.called)
self.assertTrue(mock_install_temp.called)
self.assertTrue(mock_create_flavor.called)
- m.assert_called_once_with(CONST.env_active, "w")
+ m.assert_called_once_with(
+ CONST.__getattribute__('env_active'), "w")
self.assertTrue(mock_check_env.called)
self.assertTrue(mock_print_info.called)
diff --git a/functest/tests/unit/ci/test_run_tests.py b/functest/tests/unit/ci/test_run_tests.py
index 7d02b1af..d0052392 100644
--- a/functest/tests/unit/ci/test_run_tests.py
+++ b/functest/tests/unit/ci/test_run_tests.py
@@ -62,24 +62,13 @@ class RunTestsTesting(unittest.TestCase):
@mock.patch('functest.ci.run_tests.os_snapshot.main')
def test_generate_os_snapshot(self, mock_os_snap):
- run_tests.generate_os_snapshot()
- self.assertTrue(mock_os_snap.called)
+ run_tests.generate_os_snapshot()
+ self.assertTrue(mock_os_snap.called)
@mock.patch('functest.ci.run_tests.os_clean.main')
def test_cleanup(self, mock_os_clean):
- run_tests.cleanup()
- self.assertTrue(mock_os_clean.called)
-
- def test_update_test_info(self):
- run_tests.GlobalVariables.EXECUTED_TEST_CASES = [self.test]
- run_tests.update_test_info('test_name',
- 'test_result',
- 'test_duration')
- exp = self.test
- exp.update({"result": 'test_result',
- "duration": 'test_duration'})
- self.assertEqual(run_tests.GlobalVariables.EXECUTED_TEST_CASES,
- [exp])
+ run_tests.cleanup()
+ self.assertTrue(mock_os_clean.called)
def test_get_run_dict_if_defined_default(self):
mock_obj = mock.Mock()
@@ -148,10 +137,8 @@ class RunTestsTesting(unittest.TestCase):
mock.patch('functest.ci.run_tests.source_rc_file'), \
mock.patch('functest.ci.run_tests.generate_os_snapshot'), \
mock.patch('functest.ci.run_tests.cleanup'), \
- mock.patch('functest.ci.run_tests.update_test_info'), \
mock.patch('functest.ci.run_tests.get_run_dict',
return_value=test_run_dict), \
- mock.patch('functest.ci.run_tests.generate_report.main'), \
self.assertRaises(run_tests.BlockingTestFailed) as context:
run_tests.GlobalVariables.CLEAN_FLAG = True
run_tests.run_test(mock_test, 'tier_name')
@@ -176,21 +163,17 @@ class RunTestsTesting(unittest.TestCase):
@mock.patch('functest.ci.run_tests.logger.info')
def test_run_all_default(self, mock_logger_info):
- with mock.patch('functest.ci.run_tests.run_tier') as mock_method, \
- mock.patch('functest.ci.run_tests.generate_report.init'), \
- mock.patch('functest.ci.run_tests.generate_report.main'):
- CONST.CI_LOOP = 'test_ci_loop'
+ with mock.patch('functest.ci.run_tests.run_tier') as mock_method:
+ CONST.__setattr__('CI_LOOP', 'test_ci_loop')
run_tests.run_all(self.tiers)
mock_method.assert_any_call(self.tier)
self.assertTrue(mock_logger_info.called)
@mock.patch('functest.ci.run_tests.logger.info')
- def test_run_all__missing_tier(self, mock_logger_info):
- with mock.patch('functest.ci.run_tests.generate_report.init'), \
- mock.patch('functest.ci.run_tests.generate_report.main'):
- CONST.CI_LOOP = 'loop_re_not_available'
- run_tests.run_all(self.tiers)
- self.assertTrue(mock_logger_info.called)
+ def test_run_all_missing_tier(self, mock_logger_info):
+ CONST.__setattr__('CI_LOOP', 'loop_re_not_available')
+ run_tests.run_all(self.tiers)
+ self.assertTrue(mock_logger_info.called)
def test_main_failed(self):
kwargs = {'test': 'test_name', 'noclean': True, 'report': True}
@@ -221,7 +204,6 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.generate_report.init'), \
mock.patch('functest.ci.run_tests.run_tier') as m:
self.assertEqual(run_tests.main(**kwargs),
run_tests.Result.EX_OK)
@@ -234,7 +216,6 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.generate_report.init'), \
mock.patch('functest.ci.run_tests.run_test') as m:
self.assertEqual(run_tests.main(**kwargs),
run_tests.Result.EX_OK)
@@ -248,7 +229,6 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.generate_report.init'), \
mock.patch('functest.ci.run_tests.run_all') as m:
self.assertEqual(run_tests.main(**kwargs),
run_tests.Result.EX_OK)
@@ -262,11 +242,11 @@ class RunTestsTesting(unittest.TestCase):
with mock.patch('functest.ci.run_tests.tb.TierBuilder',
return_value=mock_obj), \
mock.patch('functest.ci.run_tests.source_rc_file'), \
- mock.patch('functest.ci.run_tests.generate_report.init'), \
mock.patch('functest.ci.run_tests.logger.debug') as m:
self.assertEqual(run_tests.main(**kwargs),
run_tests.Result.EX_ERROR)
self.assertTrue(m.called)
+
if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_tier_builder.py b/functest/tests/unit/ci/test_tier_builder.py
index 48c94a57..feaf33a8 100644
--- a/functest/tests/unit/ci/test_tier_builder.py
+++ b/functest/tests/unit/ci/test_tier_builder.py
@@ -22,7 +22,8 @@ class TierBuilderTesting(unittest.TestCase):
'scenario': 'test_scenario'}
self.testcase = {'dependencies': self.dependency,
- 'name': 'test_name',
+ 'enabled': 'true',
+ 'case_name': 'test_name',
'criteria': 'test_criteria',
'blocking': 'test_blocking',
'clean_flag': 'test_clean_flag',
@@ -78,6 +79,13 @@ class TierBuilderTesting(unittest.TestCase):
self.assertEqual(self.tierbuilder.get_tests('test_tier2'),
None)
+ def test_get_tier_name_ok(self):
+ self.assertEqual(self.tierbuilder.get_tier_name('test_name'),
+ 'test_tier')
+
+ def test_get_tier_name_ko(self):
+ self.assertEqual(self.tierbuilder.get_tier_name('test_name2'), None)
+
if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/ci/test_tier_handler.py b/functest/tests/unit/ci/test_tier_handler.py
index 21df4098..28006274 100644
--- a/functest/tests/unit/ci/test_tier_handler.py
+++ b/functest/tests/unit/ci/test_tier_handler.py
@@ -32,6 +32,7 @@ class TierHandlerTesting(unittest.TestCase):
'test_ci_loop',
description='test_desc')
self.testcase = tier_handler.TestCase('test_name',
+ 'true',
self.mock_depend,
'test_criteria',
'test_blocking',
@@ -116,6 +117,10 @@ class TierHandlerTesting(unittest.TestCase):
self.assertEqual(self.tier.get_name(),
'test_tier')
+ def test_testcase_is_enabled(self):
+ self.assertEqual(self.testcase.is_enabled(),
+ 'true')
+
def test_testcase_get_criteria(self):
self.assertEqual(self.tier.get_order(),
'test_order')
diff --git a/functest/tests/unit/cli/commands/test_cli_env.py b/functest/tests/unit/cli/commands/test_cli_env.py
index 4b6ea57a..c3d89ea3 100644
--- a/functest/tests/unit/cli/commands/test_cli_env.py
+++ b/functest/tests/unit/cli/commands/test_cli_env.py
@@ -28,7 +28,7 @@ class CliEnvTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_prepare_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
self.cli_environ.prepare()
mock_ft_utils.assert_called_with(cmd)
@@ -40,29 +40,30 @@ class CliEnvTesting(unittest.TestCase):
mock.patch('functest.cli.commands.cli_testcase.os.remove') \
as mock_os_remove:
cmd = ("python %s/functest/ci/prepare_env.py start" %
- CONST.dir_repo_functest)
+ CONST.__getattribute__('dir_repo_functest'))
self.cli_environ.prepare()
- mock_os_remove.assert_called_once_with(CONST.env_active)
+ mock_os_remove.assert_called_once_with(
+ CONST.__getattribute__('env_active'))
mock_ft_utils.assert_called_with(cmd)
def _test_show_missing_env_var(self, var, *args):
if var == 'INSTALLER_TYPE':
- CONST.INSTALLER_TYPE = None
+ CONST.__setattr__('INSTALLER_TYPE', None)
reg_string = "| INSTALLER: Unknown, \S+\s*|"
elif var == 'INSTALLER_IP':
- CONST.INSTALLER_IP = None
+ CONST.__setattr__('INSTALLER_IP', None)
reg_string = "| INSTALLER: \S+, Unknown\s*|"
elif var == 'SCENARIO':
- CONST.DEPLOY_SCENARIO = None
+ CONST.__setattr__('DEPLOY_SCENARIO', None)
reg_string = "| SCENARIO: Unknown\s*|"
elif var == 'NODE':
- CONST.NODE_NAME = None
+ CONST.__setattr__('NODE_NAME', None)
reg_string = "| POD: Unknown\s*|"
elif var == 'BUILD_TAG':
- CONST.BUILD_TAG = None
+ CONST.__setattr__('BUILD_TAG', None)
reg_string = "| BUILD TAG: None|"
elif var == 'DEBUG':
- CONST.CI_DEBUG = None
+ CONST.__setattr__('CI_DEBUG', None)
reg_string = "| DEBUG FLAG: false\s*|"
elif var == 'STATUS':
reg_string = "| STATUS: not ready\s*|"
@@ -106,7 +107,7 @@ class CliEnvTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_env.os.path.exists',
return_value=False)
def test_show_missing_git_repo_dir(self, *args):
- CONST.dir_repo_functest = None
+ CONST.__setattr__('dir_repo_functest', None)
self.assertRaises(NoSuchPathError, lambda: self.cli_environ.show())
@mock.patch('functest.cli.commands.cli_env.click.echo')
diff --git a/functest/tests/unit/cli/commands/test_cli_os.py b/functest/tests/unit/cli/commands/test_cli_os.py
index f0e58c67..54042769 100644
--- a/functest/tests/unit/cli/commands/test_cli_os.py
+++ b/functest/tests/unit/cli/commands/test_cli_os.py
@@ -69,10 +69,10 @@ class CliOpenStackTesting(unittest.TestCase):
def test_fetch_credentials_default(self, mock_click_echo,
mock_os_path,
mock_ftutils_execute):
- CONST.INSTALLER_TYPE = self.installer_type
- CONST.INSTALLER_IP = self.installer_ip
+ CONST.__setattr__('INSTALLER_TYPE', self.installer_type)
+ CONST.__setattr__('INSTALLER_IP', self.installer_ip)
cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
+ % (CONST.__getattribute__('dir_repos'),
self.openstack_creds,
self.installer_type,
self.installer_ip))
@@ -92,15 +92,13 @@ class CliOpenStackTesting(unittest.TestCase):
def test_fetch_credentials_missing_installer_type(self, mock_click_echo,
mock_os_path,
mock_ftutils_execute):
- installer_type = None
- installer_ip = self.installer_ip
- CONST.INSTALLER_TYPE = installer_type
- CONST.INSTALLER_IP = installer_ip
+ CONST.__setattr__('INSTALLER_TYPE', None)
+ CONST.__setattr__('INSTALLER_IP', self.installer_ip)
cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
+ % (CONST.__getattribute__('dir_repos'),
self.openstack_creds,
- installer_type,
- installer_ip))
+ None,
+ self.installer_ip))
self.cli_os.openstack_creds = self.openstack_creds
self.cli_os.fetch_credentials()
mock_click_echo.assert_any_call("The environment variable "
@@ -109,8 +107,8 @@ class CliOpenStackTesting(unittest.TestCase):
mock_click_echo.assert_any_call("Fetching credentials from "
"installer node '%s' with "
"IP=%s.." %
- (installer_type,
- installer_ip))
+ (None,
+ self.installer_ip))
mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
@mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
@@ -122,10 +120,10 @@ class CliOpenStackTesting(unittest.TestCase):
mock_ftutils_execute):
installer_type = self.installer_type
installer_ip = None
- CONST.INSTALLER_TYPE = installer_type
- CONST.INSTALLER_IP = installer_ip
+ CONST.__setattr__('INSTALLER_TYPE', installer_type)
+ CONST.__setattr__('INSTALLER_IP', installer_ip)
cmd = ("%s/releng/utils/fetch_os_creds.sh -d %s -i %s -a %s"
- % (CONST.dir_repos,
+ % (CONST.__getattribute__('dir_repos'),
self.openstack_creds,
installer_type,
installer_ip))
@@ -144,8 +142,9 @@ class CliOpenStackTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_os.ft_utils.execute_command')
def test_check(self, mock_ftutils_execute):
with mock.patch.object(self.cli_os, 'ping_endpoint'):
- CONST.dir_repo_functest = self.dir_repo_functest
- cmd = CONST.dir_repo_functest + "/functest/ci/check_os.sh"
+ CONST.__setattr__('dir_repo_functest', self.dir_repo_functest)
+ cmd = os.path.join(CONST.__getattribute__('dir_repo_functest'),
+ "functest/ci/check_os.sh")
self.cli_os.check()
mock_ftutils_execute.assert_called_once_with(cmd, verbose=False)
diff --git a/functest/tests/unit/cli/commands/test_cli_testcase.py b/functest/tests/unit/cli/commands/test_cli_testcase.py
index 39c8139d..2d09514e 100644
--- a/functest/tests/unit/cli/commands/test_cli_testcase.py
+++ b/functest/tests/unit/cli/commands/test_cli_testcase.py
@@ -42,7 +42,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n -r ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n -r ", self.testname))
self.cli_tests.run(self.testname, noclean=True, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -51,7 +53,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n ", self.testname))
self.cli_tests.run(self.testname, noclean=True, report=False)
mock_ft_utils.assert_called_with(cmd)
@@ -60,7 +64,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-r ", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-r ", self.testname))
self.cli_tests.run(self.testname, noclean=False, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -69,7 +75,9 @@ class CliTestCasesTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_testcase.ft_utils.execute_command')
def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "", self.testname))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "", self.testname))
self.cli_tests.run(self.testname, noclean=False, report=False)
mock_ft_utils.assert_called_with(cmd)
diff --git a/functest/tests/unit/cli/commands/test_cli_tier.py b/functest/tests/unit/cli/commands/test_cli_tier.py
index 802359f1..fbc75253 100644
--- a/functest/tests/unit/cli/commands/test_cli_tier.py
+++ b/functest/tests/unit/cli/commands/test_cli_tier.py
@@ -90,8 +90,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_default(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n -r ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n -r ", self.tiername))
self.cli_tier.run(self.tiername, noclean=True, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -100,8 +101,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_report_missing_noclean(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-r ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-r ", self.tiername))
self.cli_tier.run(self.tiername, noclean=False, report=True)
mock_ft_utils.assert_called_with(cmd)
@@ -110,8 +112,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_noclean_missing_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "-n ",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "-n ", self.tiername))
self.cli_tier.run(self.tiername, noclean=True, report=False)
mock_ft_utils.assert_called_with(cmd)
@@ -120,8 +123,9 @@ class CliTierTesting(unittest.TestCase):
@mock.patch('functest.cli.commands.cli_tier.ft_utils.execute_command')
def test_run_missing_noclean_report(self, mock_ft_utils, mock_os):
cmd = ("python %s/functest/ci/run_tests.py "
- "%s -t %s" % (CONST.dir_repo_functest, "",
- self.tiername))
+ "%s -t %s" %
+ (CONST.__getattribute__('dir_repo_functest'),
+ "", self.tiername))
self.cli_tier.run(self.tiername, noclean=False, report=False)
mock_ft_utils.assert_called_with(cmd)
diff --git a/functest/tests/unit/core/test_feature.py b/functest/tests/unit/core/test_feature.py
new file mode 100644
index 00000000..8de42ec5
--- /dev/null
+++ b/functest/tests/unit/core/test_feature.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from functest.core import feature
+from functest.core import testcase
+
+# logging must be disabled else it calls time.time()
+# what will break these unit tests.
+logging.disable(logging.CRITICAL)
+
+
+class FeatureTestingBase(unittest.TestCase):
+
+ _case_name = "foo"
+ _project_name = "bar"
+ _repo = "dir_repo_copper"
+ _cmd = "cd /home/opnfv/repos/foo/tests && bash run.sh && cd -"
+ _output_file = '/home/opnfv/functest/results/foo.log'
+ feature = None
+
+ @mock.patch('time.time', side_effect=[1, 2])
+ def _test_run(self, status, mock_method=None):
+ self.assertEqual(self.feature.run(cmd=self._cmd), status)
+ if status == testcase.TestCase.EX_OK:
+ self.assertEqual(self.feature.result, 100)
+ else:
+ self.assertEqual(self.feature.result, 0)
+ mock_method.assert_has_calls([mock.call(), mock.call()])
+ self.assertEqual(self.feature.start_time, 1)
+ self.assertEqual(self.feature.stop_time, 2)
+
+
+class FeatureTesting(FeatureTestingBase):
+
+ def setUp(self):
+ self.feature = feature.Feature(
+ project_name=self._project_name, case_name=self._case_name)
+
+ def test_run_exc(self):
+ # pylint: disable=bad-continuation
+ with mock.patch.object(
+ self.feature, 'execute',
+ side_effect=Exception) as mock_method:
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+ mock_method.assert_called_once_with(cmd=self._cmd)
+
+ def test_run(self):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+
+class BashFeatureTesting(FeatureTestingBase):
+
+ def setUp(self):
+ self.feature = feature.BashFeature(
+ project_name=self._project_name, case_name=self._case_name)
+
+ @mock.patch("functest.utils.functest_utils.execute_command")
+ def test_run_no_cmd(self, mock_method=None):
+ self.assertEqual(self.feature.run(), testcase.TestCase.EX_RUN_ERROR)
+ mock_method.assert_not_called()
+
+ @mock.patch("functest.utils.functest_utils.execute_command",
+ return_value=1)
+ def test_run_ko(self, mock_method=None):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+ mock_method.assert_called_once_with(
+ self._cmd, output_file=self._output_file)
+
+ @mock.patch("functest.utils.functest_utils.execute_command",
+ side_effect=Exception)
+ def test_run_exc(self, mock_method=None):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+ mock_method.assert_called_once_with(
+ self._cmd, output_file=self._output_file)
+
+ @mock.patch("functest.utils.functest_utils.execute_command",
+ return_value=0)
+ def test_run(self, mock_method):
+ self._test_run(testcase.TestCase.EX_OK)
+ mock_method.assert_called_once_with(
+ self._cmd, output_file=self._output_file)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_pytest_suite_runner.py b/functest/tests/unit/core/test_pytest_suite_runner.py
new file mode 100644
index 00000000..15e5bd73
--- /dev/null
+++ b/functest/tests/unit/core/test_pytest_suite_runner.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import unittest
+
+import mock
+
+from functest.core import pytest_suite_runner
+from functest.core import testcase
+
+
+class PyTestSuiteRunnerTesting(unittest.TestCase):
+
+ logging.disable(logging.CRITICAL)
+
+ def setUp(self):
+ self.psrunner = pytest_suite_runner.PyTestSuiteRunner()
+ self.result = mock.Mock()
+ attrs = {'errors': [('test1', 'error_msg1')],
+ 'failures': [('test2', 'failure_msg1')]}
+ self.result.configure_mock(**attrs)
+
+ self.pass_results = mock.Mock()
+ attrs = {'errors': None,
+ 'failures': None}
+ self.pass_results.configure_mock(**attrs)
+
+ def test_run(self):
+ self.psrunner.case_name = 'test_case_name'
+ with mock.patch('functest.core.pytest_suite_runner.'
+ 'unittest.TextTestRunner.run',
+ return_value=self.result):
+ self.assertEqual(self.psrunner.run(),
+ testcase.TestCase.EX_OK)
+
+ with mock.patch('functest.core.pytest_suite_runner.'
+ 'unittest.TextTestRunner.run',
+ return_value=self.pass_results):
+ self.assertEqual(self.psrunner.run(),
+ testcase.TestCase.EX_OK)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_testcase.py b/functest/tests/unit/core/test_testcase.py
index 32104194..2adf4a6d 100644
--- a/functest/tests/unit/core/test_testcase.py
+++ b/functest/tests/unit/core/test_testcase.py
@@ -7,7 +7,7 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
-"""Define the classe required to fully cover testcase."""
+"""Define the class required to fully cover testcase."""
import logging
import unittest
@@ -20,19 +20,21 @@ __author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
class TestCaseTesting(unittest.TestCase):
-
"""The class testing TestCase."""
- # pylint: disable=missing-docstring
+ # pylint: disable=missing-docstring,too-many-public-methods
logging.disable(logging.CRITICAL)
+ _case_name = "base"
+ _project_name = "functest"
+ _published_result = "PASS"
+
def setUp(self):
- self.test = testcase.TestCase()
- self.test.project = "functest"
- self.test.case_name = "base"
+ self.test = testcase.TestCase(case_name=self._case_name,
+ project_name=self._project_name)
self.test.start_time = "1"
self.test.stop_time = "2"
- self.test.criteria = "PASS"
+ self.test.result = 100
self.test.details = {"Hello": "World"}
def test_run_unimplemented(self):
@@ -46,12 +48,12 @@ class TestCaseTesting(unittest.TestCase):
testcase.TestCase.EX_PUSH_TO_DB_ERROR)
mock_function.assert_not_called()
- def test_missing_case_name(self):
- self.test.case_name = None
+ def test_missing_project_name(self):
+ self.test.project_name = None
self._test_missing_attribute()
- def test_missing_criteria(self):
- self.test.criteria = None
+ def test_missing_case_name(self):
+ self.test.case_name = None
self._test_missing_attribute()
def test_missing_start_time(self):
@@ -69,8 +71,8 @@ class TestCaseTesting(unittest.TestCase):
self.assertEqual(self.test.push_to_db(),
testcase.TestCase.EX_OK)
mock_function.assert_called_once_with(
- self.test.project, self.test.case_name, self.test.start_time,
- self.test.stop_time, self.test.criteria, self.test.details)
+ self._project_name, self._case_name, self.test.start_time,
+ self.test.stop_time, self._published_result, self.test.details)
@mock.patch('functest.utils.functest_utils.push_results_to_db',
return_value=False)
@@ -78,8 +80,8 @@ class TestCaseTesting(unittest.TestCase):
self.assertEqual(self.test.push_to_db(),
testcase.TestCase.EX_PUSH_TO_DB_ERROR)
mock_function.assert_called_once_with(
- self.test.project, self.test.case_name, self.test.start_time,
- self.test.stop_time, self.test.criteria, self.test.details)
+ self._project_name, self._case_name, self.test.start_time,
+ self.test.stop_time, self._published_result, self.test.details)
@mock.patch('functest.utils.functest_utils.push_results_to_db',
return_value=True)
@@ -87,24 +89,140 @@ class TestCaseTesting(unittest.TestCase):
self.assertEqual(self.test.push_to_db(),
testcase.TestCase.EX_OK)
mock_function.assert_called_once_with(
- self.test.project, self.test.case_name, self.test.start_time,
- self.test.stop_time, self.test.criteria, self.test.details)
+ self._project_name, self._case_name, self.test.start_time,
+ self.test.stop_time, self._published_result, self.test.details)
+
+ @mock.patch('functest.utils.functest_utils.push_results_to_db',
+ return_value=True)
+ def test_push_to_db_res_ko(self, mock_function=None):
+ self.test.result = 0
+ self.assertEqual(self.test.push_to_db(),
+ testcase.TestCase.EX_OK)
+ mock_function.assert_called_once_with(
+ self._project_name, self._case_name, self.test.start_time,
+ self.test.stop_time, 'FAIL', self.test.details)
+
+ @mock.patch('functest.utils.functest_utils.push_results_to_db',
+ return_value=True)
+ def test_push_to_db_both_ko(self, mock_function=None):
+ self.test.result = 0
+ self.test.criteria = 0
+ self.assertEqual(self.test.push_to_db(),
+ testcase.TestCase.EX_OK)
+ mock_function.assert_called_once_with(
+ self._project_name, self._case_name, self.test.start_time,
+ self.test.stop_time, 'FAIL', self.test.details)
def test_check_criteria_missing(self):
self.test.criteria = None
- self.assertEqual(self.test.check_criteria(),
+ self.assertEqual(self.test.is_successful(),
testcase.TestCase.EX_TESTCASE_FAILED)
- def test_check_criteria_failed(self):
- self.test.criteria = 'FAILED'
- self.assertEqual(self.test.check_criteria(),
+ def test_check_result_missing(self):
+ self.test.result = None
+ self.assertEqual(self.test.is_successful(),
testcase.TestCase.EX_TESTCASE_FAILED)
- def test_check_criteria_pass(self):
- self.test.criteria = 'PASS'
- self.assertEqual(self.test.check_criteria(),
+ def test_check_result_failed(self):
+ # Backward compatibility
+ # It must be removed as soon as TestCase subclasses
+ # stop setting result = 'PASS' or 'FAIL'.
+ self.test.result = 'FAIL'
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_pass(self):
+ # Backward compatibility
+ # It must be removed as soon as TestCase subclasses
+ # stop setting result = 'PASS' or 'FAIL'.
+ self.test.result = 'PASS'
+ self.assertEqual(self.test.is_successful(),
testcase.TestCase.EX_OK)
+ def test_check_result_lt(self):
+ self.test.result = 50
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_check_result_eq(self):
+ self.test.result = 100
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ def test_check_result_gt(self):
+ self.test.criteria = 50
+ self.test.result = 100
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_OK)
+
+ def test_check_result_zero(self):
+ self.test.criteria = 0
+ self.test.result = 0
+ self.assertEqual(self.test.is_successful(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_get_duration_start_ko(self):
+ self.test.start_time = None
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+ self.test.start_time = 0
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_duration_end_ko(self):
+ self.test.stop_time = None
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+ self.test.stop_time = 0
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_invalid_duration(self):
+ self.test.start_time = 2
+ self.test.stop_time = 1
+ self.assertEqual(self.test.get_duration(), "XX:XX")
+
+ def test_get_zero_duration(self):
+ self.test.start_time = 2
+ self.test.stop_time = 2
+ self.assertEqual(self.test.get_duration(), "00:00")
+
+ def test_get_duration(self):
+ self.test.start_time = 1
+ self.test.stop_time = 180
+ self.assertEqual(self.test.get_duration(), "02:59")
+
+ def test_str_project_name_ko(self):
+ self.test.project_name = None
+ self.assertIn("<functest.core.testcase.TestCase object at",
+ str(self.test))
+
+ def test_str_case_name_ko(self):
+ self.test.case_name = None
+ self.assertIn("<functest.core.testcase.TestCase object at",
+ str(self.test))
+
+ def test_str_pass(self):
+ duration = '01:01'
+ with mock.patch.object(self.test, 'get_duration',
+ return_value=duration), \
+ mock.patch.object(self.test, 'is_successful',
+ return_value=testcase.TestCase.EX_OK):
+ message = str(self.test)
+ self.assertIn(self._project_name, message)
+ self.assertIn(self._case_name, message)
+ self.assertIn(duration, message)
+ self.assertIn('PASS', message)
+
+ def test_str_fail(self):
+ duration = '00:59'
+ with mock.patch.object(self.test, 'get_duration',
+ return_value=duration), \
+ mock.patch.object(
+ self.test, 'is_successful',
+ return_value=testcase.TestCase.EX_TESTCASE_FAILED):
+ message = str(self.test)
+ self.assertIn(self._project_name, message)
+ self.assertIn(self._case_name, message)
+ self.assertIn(duration, message)
+ self.assertIn('FAIL', message)
+
if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_vnf.py b/functest/tests/unit/core/test_vnf.py
new file mode 100644
index 00000000..793e9576
--- /dev/null
+++ b/functest/tests/unit/core/test_vnf.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import os
+import unittest
+
+import mock
+
+from functest.core import vnf
+from functest.core import testcase
+
+
+class VnfBaseTesting(unittest.TestCase):
+
+ logging.disable(logging.CRITICAL)
+
+ def setUp(self):
+ self.test = vnf.VnfOnBoarding(
+ project='functest', case_name='aaa')
+ self.test.project = "functest"
+ self.test.start_time = "1"
+ self.test.stop_time = "5"
+ self.test.result = ""
+ self.test.details = {
+ "orchestrator": {"status": "PASS", "result": "", "duration": 20},
+ "vnf": {"status": "PASS", "result": "", "duration": 15},
+ "test_vnf": {"status": "FAIL", "result": "", "duration": 5}}
+ self.test.keystone_client = 'test_client'
+ self.test.tenant_name = 'test_tenant_name'
+
+ def test_execute_deploy_vnf_fail(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=None), \
+ mock.patch.object(self.test, 'deploy_vnf',
+ side_effect=Exception):
+ self.assertEqual(self.test.execute(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ def test_execute_test_vnf_fail(self):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=None), \
+ mock.patch.object(self.test, 'deploy_vnf'), \
+ mock.patch.object(self.test, 'test_vnf',
+ side_effect=Exception):
+ self.assertEqual(self.test.execute(),
+ testcase.TestCase.EX_TESTCASE_FAILED)
+
+ @mock.patch('functest.core.vnf.os_utils.get_tenant_id',
+ return_value='test_tenant_id')
+ @mock.patch('functest.core.vnf.os_utils.delete_tenant',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_user_id',
+ return_value='test_user_id')
+ @mock.patch('functest.core.vnf.os_utils.delete_user',
+ return_value=True)
+ def test_execute_default(self, *args):
+ with mock.patch.object(self.test, 'prepare'),\
+ mock.patch.object(self.test, 'deploy_orchestrator',
+ return_value=None), \
+ mock.patch.object(self.test, 'deploy_vnf'), \
+ mock.patch.object(self.test, 'test_vnf'), \
+ mock.patch.object(self.test, 'parse_results',
+ return_value='ret_exit_code'), \
+ mock.patch.object(self.test, 'log_results'):
+ self.assertEqual(self.test.execute(),
+ 'ret_exit_code')
+
+ @mock.patch('functest.core.vnf.os_utils.get_credentials')
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client')
+ @mock.patch('functest.core.vnf.os_utils.get_user_id', return_value='')
+ def test_prepare_missing_userid(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+
+ @mock.patch('functest.core.vnf.os_utils.get_credentials')
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client')
+ @mock.patch('functest.core.vnf.os_utils.get_user_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.create_tenant',
+ return_value='')
+ def test_prepare_missing_tenantid(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+
+ @mock.patch('functest.core.vnf.os_utils.get_credentials')
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client')
+ @mock.patch('functest.core.vnf.os_utils.get_user_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.create_tenant',
+ return_value='test_tenantid')
+ @mock.patch('functest.core.vnf.os_utils.get_role_id',
+ return_value='')
+ def test_prepare_missing_roleid(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+
+ @mock.patch('functest.core.vnf.os_utils.get_credentials')
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client')
+ @mock.patch('functest.core.vnf.os_utils.get_user_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.create_tenant',
+ return_value='test_tenantid')
+ @mock.patch('functest.core.vnf.os_utils.get_role_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.add_role_user',
+ return_value='')
+ def test_prepare_role_add_failure(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+
+ @mock.patch('functest.core.vnf.os_utils.get_credentials')
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client')
+ @mock.patch('functest.core.vnf.os_utils.get_user_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.create_tenant',
+ return_value='test_tenantid')
+ @mock.patch('functest.core.vnf.os_utils.get_role_id',
+ return_value='test_roleid')
+ @mock.patch('functest.core.vnf.os_utils.add_role_user')
+ @mock.patch('functest.core.vnf.os_utils.create_user',
+ return_value='')
+ def test_create_user_failure(self, *args):
+ with self.assertRaises(Exception):
+ self.test.prepare()
+
+ def test_log_results_default(self):
+ with mock.patch('functest.core.vnf.'
+ 'ft_utils.logger_test_results') \
+ as mock_method:
+ self.test.log_results()
+ self.assertTrue(mock_method.called)
+
+ def test_step_failures_default(self):
+ with self.assertRaises(Exception):
+ self.test.step_failure("error_msg")
+
+ def test_deploy_vnf_unimplemented(self):
+ with self.assertRaises(Exception) as context:
+ self.test.deploy_vnf()
+ self.assertTrue('VNF not deployed' in context.exception)
+
+ def test_test_vnf_unimplemented(self):
+ with self.assertRaises(Exception) as context:
+ self.test.test_vnf()()
+ self.assertTrue('VNF not tested' in context.exception)
+
+ def test_parse_results_ex_ok(self):
+ self.test.details['test_vnf']['status'] = 'PASS'
+ self.assertEqual(self.test.parse_results(), os.EX_OK)
+
+ def test_parse_results_ex_run_error(self):
+ self.test.details['vnf']['status'] = 'FAIL'
+ self.assertEqual(self.test.parse_results(), os.EX_SOFTWARE)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/core/test_vnf_base.py b/functest/tests/unit/core/test_vnf_base.py
deleted file mode 100644
index 1680f03f..00000000
--- a/functest/tests/unit/core/test_vnf_base.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2016 Orange and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-import logging
-import unittest
-
-from functest.core import vnf_base
-
-
-class VnfBaseTesting(unittest.TestCase):
-
- logging.disable(logging.CRITICAL)
-
- def setUp(self):
- self.test = vnf_base.VnfOnBoardingBase(project='functest',
- case='aaa')
- self.test.project = "functest"
- self.test.case_name = "aaa"
- self.test.start_time = "1"
- self.test.stop_time = "5"
- self.test.criteria = ""
- self.test.details = {"orchestrator": {"status": "PASS",
- "result": "",
- "duration": 20},
- "vnf": {"status": "PASS",
- "result": "",
- "duration": 15},
- "test_vnf": {"status": "FAIL",
- "result": "",
- "duration": 5}}
-
- def test_deploy_vnf_unimplemented(self):
- with self.assertRaises(Exception) as context:
- self.test.deploy_vnf()
- self.assertTrue('VNF not deployed' in context.exception)
-
- def test_test_vnf_unimplemented(self):
- with self.assertRaises(Exception) as context:
- self.test.test_vnf()()
- self.assertTrue('VNF not tested' in context.exception)
-
- def test_parse_results(self):
- self.assertNotEqual(self.test.parse_results(), 0)
-
-
-if __name__ == "__main__":
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/opnfv_tests/__init__.py b/functest/tests/unit/energy/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/__init__.py
+++ b/functest/tests/unit/energy/__init__.py
diff --git a/functest/tests/unit/energy/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py
new file mode 100644
index 00000000..ffe044bc
--- /dev/null
+++ b/functest/tests/unit/energy/test_functest_energy.py
@@ -0,0 +1,277 @@
+#!/usr/bin/env python
+
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Unitary test for energy module."""
+# pylint: disable=unused-argument
+import logging
+import unittest
+
+import mock
+
+from functest.energy.energy import EnergyRecorder
+import functest.energy.energy as energy
+
+
+CASE_NAME = "UNIT_test_CASE"
+STEP_NAME = "UNIT_test_STEP"
+
+logging.disable(logging.CRITICAL)
+
+
+class MockHttpResponse(object): # pylint: disable=too-few-public-methods
+ """Mock response for Energy recorder API."""
+
+ def __init__(self, text, status_code):
+ """Create an instance of MockHttpResponse."""
+ self.text = text
+ self.status_code = status_code
+
+
+RECORDER_OK = MockHttpResponse(
+ '{"environment": "UNIT_TEST",'
+ ' "step": "string",'
+ ' "scenario": "' + CASE_NAME + '"}',
+ 200
+)
+RECORDER_KO = MockHttpResponse(
+ '{"message": "An unhandled API exception occurred (MOCK)"}',
+ 500
+)
+
+
+def config_loader_mock(config_key):
+ """Return mocked config values."""
+ if config_key == "energy_recorder.api_url":
+ return "http://pod-uri:8888"
+ elif config_key == "energy_recorder.api_user":
+ return "user"
+ elif config_key == "energy_recorder.api_password":
+ return "password"
+ else:
+ raise Exception("Config not mocked")
+
+
+def config_loader_mock_no_creds(config_key):
+ """Return mocked config values."""
+ if config_key == "energy_recorder.api_url":
+ return "http://pod-uri:8888"
+ elif config_key == "energy_recorder.api_user":
+ return ""
+ elif config_key == "energy_recorder.api_password":
+ return ""
+ else:
+ raise Exception("Config not mocked:" + config_key)
+
+
+class EnergyRecorderTest(unittest.TestCase):
+ """Energy module unitary test suite."""
+
+ case_name = CASE_NAME
+ request_headers = {'content-type': 'application/json'}
+ returned_value_to_preserve = "value"
+ exception_message_to_preserve = "exception_message"
+
+ @mock.patch('functest.energy.energy.requests.post',
+ return_value=RECORDER_OK)
+ def test_start(self, post_mock=None):
+ """EnergyRecorder.start method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.post',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_start_error(self, post_mock=None):
+ """EnergyRecorder.start method (error in method)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.post',
+ return_value=RECORDER_KO)
+ def test_start_api_error(self, post_mock=None):
+ """EnergyRecorder.start method (API error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.start(self.case_name))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.post',
+ return_value=RECORDER_OK)
+ def test_set_step(self, post_mock=None):
+ """EnergyRecorder.set_step method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.post',
+ return_value=RECORDER_KO)
+ def test_set_step_api_error(self, post_mock=None):
+ """EnergyRecorder.set_step method (API error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.post',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_set_step_error(self, post_mock=None):
+ """EnergyRecorder.set_step method (method error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.set_step(STEP_NAME))
+ post_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"] + "/step",
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ data=mock.ANY,
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.delete',
+ return_value=RECORDER_OK)
+ def test_stop(self, delete_mock=None):
+ """EnergyRecorder.stop method (regular case)."""
+ self.test_load_config()
+ self.assertTrue(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.delete',
+ return_value=RECORDER_KO)
+ def test_stop_api_error(self, delete_mock=None):
+ """EnergyRecorder.stop method (API Error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers
+ )
+
+ @mock.patch('functest.energy.energy.requests.delete',
+ side_effect=Exception("Internal execution error (MOCK)"))
+ def test_stop_error(self, delete_mock=None):
+ """EnergyRecorder.stop method (method error)."""
+ self.test_load_config()
+ self.assertFalse(EnergyRecorder.stop())
+ delete_mock.assert_called_once_with(
+ EnergyRecorder.energy_recorder_api["uri"],
+ auth=EnergyRecorder.energy_recorder_api["auth"],
+ headers=self.request_headers
+ )
+
+ @energy.enable_recording
+ def __decorated_method(self):
+ """Call with to energy recorder decorators."""
+ return self.returned_value_to_preserve
+
+ @energy.enable_recording
+ def __decorated_method_with_ex(self):
+ """Call with to energy recorder decorators."""
+ raise Exception(self.exception_message_to_preserve)
+
+ @mock.patch("functest.energy.energy.EnergyRecorder")
+ @mock.patch("functest.utils.functest_utils.get_pod_name",
+ return_value="MOCK_POD")
+ @mock.patch("functest.utils.functest_utils.get_functest_config",
+ side_effect=config_loader_mock)
+ def test_decorators(self,
+ loader_mock=None,
+ pod_mock=None,
+ recorder_mock=None):
+ """Test energy module decorators."""
+ self.__decorated_method()
+ calls = [mock.call.start(self.case_name),
+ mock.call.stop()]
+ recorder_mock.assert_has_calls(calls)
+
+ def test_decorator_preserve_return(self):
+ """Test that decorator preserve method returned value."""
+ self.test_load_config()
+ self.assertTrue(
+ self.__decorated_method() == self.returned_value_to_preserve
+ )
+
+ def test_decorator_preserve_ex(self):
+ """Test that decorator preserve method exceptions."""
+ self.test_load_config()
+ with self.assertRaises(Exception) as context:
+ self.__decorated_method_with_ex()
+ self.assertTrue(
+ self.exception_message_to_preserve in context.exception
+ )
+
+ @mock.patch("functest.utils.functest_utils.get_functest_config",
+ side_effect=config_loader_mock)
+ @mock.patch("functest.utils.functest_utils.get_pod_name",
+ return_value="MOCK_POD")
+ def test_load_config(self, loader_mock=None, pod_mock=None):
+ """Test load config."""
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["auth"],
+ ("user", "password")
+ )
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["uri"],
+ "http://pod-uri:8888/recorders/environment/MOCK_POD"
+ )
+
+ @mock.patch("functest.utils.functest_utils.get_functest_config",
+ side_effect=config_loader_mock_no_creds)
+ @mock.patch("functest.utils.functest_utils.get_pod_name",
+ return_value="MOCK_POD")
+ def test_load_config_no_creds(self, loader_mock=None, pod_mock=None):
+ """Test load config without creds."""
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(EnergyRecorder.energy_recorder_api["auth"], None)
+ self.assertEquals(
+ EnergyRecorder.energy_recorder_api["uri"],
+ "http://pod-uri:8888/recorders/environment/MOCK_POD"
+ )
+
+ @mock.patch("functest.utils.functest_utils.get_functest_config",
+ return_value=None)
+ @mock.patch("functest.utils.functest_utils.get_pod_name",
+ return_value="MOCK_POD")
+ def test_load_config_ex(self, loader_mock=None, pod_mock=None):
+ """Test load config with exception."""
+ with self.assertRaises(AssertionError):
+ EnergyRecorder.energy_recorder_api = None
+ EnergyRecorder.load_config()
+ self.assertEquals(EnergyRecorder.energy_recorder_api, None)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/opnfv_tests/openstack/__init__.py b/functest/tests/unit/features/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/openstack/__init__.py
+++ b/functest/tests/unit/features/__init__.py
diff --git a/functest/tests/unit/features/test_barometer.py b/functest/tests/unit/features/test_barometer.py
new file mode 100644
index 00000000..8ca463b2
--- /dev/null
+++ b/functest/tests/unit/features/test_barometer.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# pylint: disable=missing-docstring
+
+import logging
+import sys
+import unittest
+
+import mock
+
+from functest.core import testcase
+sys.modules['baro_tests'] = mock.Mock() # noqa
+# pylint: disable=wrong-import-position
+from functest.opnfv_tests.features import barometer
+
+
+class BarometerTesting(unittest.TestCase):
+
+ logging.disable(logging.CRITICAL)
+
+ _case_name = "barometercollectd"
+ _project_name = "barometer"
+
+ def setUp(self):
+ self.barometer = barometer.BarometerCollectd(
+ case_name=self._case_name, project_name=self._project_name)
+
+ def test_init(self):
+ self.assertEqual(self.barometer.project_name, self._project_name)
+ self.assertEqual(self.barometer.case_name, self._case_name)
+
+ def test_run_ko(self):
+ sys.modules['baro_tests'].collectd.main = mock.Mock(return_value=1)
+ self.assertEqual(self.barometer.run(),
+ testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run(self):
+ sys.modules['baro_tests'].collectd.main = mock.Mock(return_value=0)
+ self.assertEqual(self.barometer.run(), testcase.TestCase.EX_OK)
+
+
+if __name__ == "__main__":
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/odl/test_odl.py b/functest/tests/unit/odl/test_odl.py
index e08deb27..6e2e9b1d 100644
--- a/functest/tests/unit/odl/test_odl.py
+++ b/functest/tests/unit/odl/test_odl.py
@@ -12,14 +12,14 @@
import errno
import logging
import os
-import StringIO
import unittest
from keystoneauth1.exceptions import auth_plugins
import mock
from robot.errors import DataError, RobotError
-from robot.result import testcase as result_testcase
+from robot.result import model
from robot.utils.robottime import timestamp_to_secs
+import six
from functest.core import testcase
from functest.opnfv_tests.sdn.odl import odl
@@ -49,11 +49,9 @@ class ODLVisitorTesting(unittest.TestCase):
'elapsedtime': 1000,
'text': 'Hello, World!',
'critical': True}
- test = result_testcase.TestCase(name=data['name'],
- status=data['status'],
- message=data['text'],
- starttime=data['starttime'],
- endtime=data['endtime'])
+ test = model.TestCase(
+ name=data['name'], status=data['status'], message=data['text'],
+ starttime=data['starttime'], endtime=data['endtime'])
test.parent = mock.Mock()
config = {'name': data['parent'],
'criticality.test_is_critical.return_value': data[
@@ -90,7 +88,7 @@ class ODLTesting(unittest.TestCase):
os.environ["OS_USERNAME"] = self._os_username
os.environ["OS_PASSWORD"] = self._os_password
os.environ["OS_TENANT_NAME"] = self._os_tenantname
- self.test = odl.ODLTests()
+ self.test = odl.ODLTests(case_name='odl', project_name='functest')
self.defaultargs = {'odlusername': self._odl_username,
'odlpassword': self._odl_password,
'neutronip': self._keystone_ip,
@@ -109,21 +107,23 @@ class ODLParseResultTesting(ODLTesting):
"""The class testing ODLTests.parse_results()."""
# pylint: disable=missing-docstring
+ _config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000',
+ 'endtime': '20161216 16:00:01.000'}
+
@mock.patch('robot.api.ExecutionResult', side_effect=DataError)
def test_raises_exc(self, mock_method):
with self.assertRaises(DataError):
self.test.parse_results()
- mock_method.assert_called_once_with()
+ mock_method.assert_called_once_with(
+ os.path.join(odl.ODLTests.res_dir, 'output.xml'))
- def test_ok(self):
- config = {'name': 'dummy', 'starttime': '20161216 16:00:00.000',
- 'endtime': '20161216 16:00:01.000', 'status': 'PASS'}
+ def _test_result(self, config, result):
suite = mock.Mock()
suite.configure_mock(**config)
with mock.patch('robot.api.ExecutionResult',
return_value=mock.Mock(suite=suite)):
self.test.parse_results()
- self.assertEqual(self.test.criteria, config['status'])
+ self.assertEqual(self.test.result, result)
self.assertEqual(self.test.start_time,
timestamp_to_secs(config['starttime']))
self.assertEqual(self.test.stop_time,
@@ -131,6 +131,26 @@ class ODLParseResultTesting(ODLTesting):
self.assertEqual(self.test.details,
{'description': config['name'], 'tests': []})
+ def test_null_passed(self):
+ self._config.update({'statistics.critical.passed': 0,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 0)
+
+ def test_no_test(self):
+ self._config.update({'statistics.critical.passed': 20,
+ 'statistics.critical.total': 0})
+ self._test_result(self._config, 0)
+
+ def test_half_success(self):
+ self._config.update({'statistics.critical.passed': 10,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 50)
+
+ def test_success(self):
+ self._config.update({'statistics.critical.passed': 20,
+ 'statistics.critical.total': 20})
+ self._test_result(self._config, 100)
+
class ODLRobotTesting(ODLTesting):
@@ -151,7 +171,7 @@ class ODLRobotTesting(ODLTesting):
os.path.join(odl.ODLTests.odl_test_repo,
'csit/variables/Variables.py'), inplace=True)
- @mock.patch('sys.stdout', new_callable=StringIO.StringIO)
+ @mock.patch('sys.stdout', new_callable=six.StringIO)
def _test_set_vars(self, msg1, msg2, *args):
line = mock.MagicMock()
line.__iter__.return_value = [msg1]
@@ -169,7 +189,7 @@ class ODLRobotTesting(ODLTesting):
def test_set_vars_auth1(self):
self._test_set_vars("AUTH1 = []", "AUTH1 = []")
- @mock.patch('sys.stdout', new_callable=StringIO.StringIO)
+ @mock.patch('sys.stdout', new_callable=six.StringIO)
def test_set_vars_auth_foo(self, *args):
line = mock.MagicMock()
line.__iter__.return_value = ["AUTH = []"]
@@ -292,8 +312,6 @@ class ODLMainTesting(ODLTesting):
def test_run_ko(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
self.assertRaises(RobotError):
self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
@@ -302,63 +320,31 @@ class ODLMainTesting(ODLTesting):
def test_parse_results_ko(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results',
side_effect=RobotError):
self._test_main(testcase.TestCase.EX_RUN_ERROR, *args)
- @mock.patch('os.remove', side_effect=Exception)
- @mock.patch('robot.run')
- @mock.patch('os.makedirs')
- def test_remove_exc(self, *args):
- with mock.patch.object(self.test, 'set_robotframework_vars',
- return_value=True), \
- mock.patch.object(self.test, 'parse_results'), \
- self.assertRaises(Exception):
- self._test_main(testcase.TestCase.EX_OK, *args)
-
- @mock.patch('os.remove')
@mock.patch('robot.run')
@mock.patch('os.makedirs')
def test_ok(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
- @mock.patch('os.remove')
@mock.patch('robot.run')
@mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
def test_makedirs_oserror17(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
- @mock.patch('os.remove')
@mock.patch('robot.run', return_value=1)
@mock.patch('os.makedirs')
def test_testcases_in_failure(self, *args):
with mock.patch.object(self.test, 'set_robotframework_vars',
return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
- mock.patch.object(self.test, 'parse_results'):
- self._test_main(testcase.TestCase.EX_OK, *args)
-
- @mock.patch('os.remove', side_effect=OSError)
- @mock.patch('robot.run')
- @mock.patch('os.makedirs')
- def test_remove_oserror(self, *args):
- with mock.patch.object(self.test, 'set_robotframework_vars',
- return_value=True), \
- mock.patch.object(odl, 'open', mock.mock_open(),
- create=True), \
mock.patch.object(self.test, 'parse_results'):
self._test_main(testcase.TestCase.EX_OK, *args)
@@ -368,19 +354,10 @@ class ODLRunTesting(ODLTesting):
"""The class testing ODLTests.run()."""
# pylint: disable=missing-docstring
- @classmethod
- def _fake_url_for(cls, service_type='identity'):
- if service_type == 'identity':
- return "http://{}:5000/v2.0".format(
- ODLTesting._keystone_ip)
- elif service_type == 'network':
- return "http://{}:9696".format(ODLTesting._neutron_ip)
- else:
- return None
-
def _test_no_env_var(self, var):
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
del os.environ[var]
self.assertEqual(self.test.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -393,7 +370,8 @@ class ODLRunTesting(ODLTesting):
if 'odlrestconfport' in kwargs else '8181')
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
if exception:
self.test.main = mock.Mock(side_effect=exception)
else:
@@ -410,18 +388,15 @@ class ODLRunTesting(ODLTesting):
osusername=self._os_username)
def _test_multiple_suites(self, suites,
- status=testcase.TestCase.EX_OK,
- exception=None, **kwargs):
+ status=testcase.TestCase.EX_OK, **kwargs):
odlip = kwargs['odlip'] if 'odlip' in kwargs else '127.0.0.3'
odlwebport = kwargs['odlwebport'] if 'odlwebport' in kwargs else '8080'
odlrestconfport = (kwargs['odlrestconfport']
if 'odlrestconfport' in kwargs else '8181')
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
- if exception:
- self.test.main = mock.Mock(side_effect=exception)
- else:
- self.test.main = mock.Mock(return_value=status)
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
+ self.test.main = mock.Mock(return_value=status)
self.assertEqual(self.test.run(suites=suites), status)
self.test.main.assert_called_once_with(
suites,
@@ -467,7 +442,8 @@ class ODLRunTesting(ODLTesting):
def test_no_sdn_controller_ip(self):
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
self.assertEqual(self.test.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -492,7 +468,8 @@ class ODLRunTesting(ODLTesting):
def test_apex_no_controller_ip(self):
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
os.environ["INSTALLER_TYPE"] = "apex"
self.assertEqual(self.test.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -506,7 +483,8 @@ class ODLRunTesting(ODLTesting):
def test_netvirt_no_controller_ip(self):
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
os.environ["INSTALLER_TYPE"] = "netvirt"
self.assertEqual(self.test.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -520,7 +498,8 @@ class ODLRunTesting(ODLTesting):
def test_joid_no_controller_ip(self):
with mock.patch('functest.utils.openstack_utils.get_endpoint',
- side_effect=self._fake_url_for):
+ return_value="http://{}:9696".format(
+ ODLTesting._neutron_ip)):
os.environ["INSTALLER_TYPE"] = "joid"
self.assertEqual(self.test.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -558,12 +537,12 @@ class ODLArgParserTesting(ODLTesting):
"--odlip={}".format(self._sdn_controller_ip)]),
self.defaultargs)
- @mock.patch('sys.stderr', new_callable=StringIO.StringIO)
+ @mock.patch('sys.stderr', new_callable=six.StringIO)
def test_fail(self, mock_method):
self.defaultargs['foo'] = 'bar'
with self.assertRaises(SystemExit):
self.parser.parse_args(["--foo=bar"])
- mock_method.assert_called_once_with()
+ self.assertTrue(mock_method.getvalue().startswith("usage:"))
def _test_arg(self, arg, value):
self.defaultargs[arg] = value
diff --git a/functest/tests/unit/opnfv_tests/openstack/rally/__init__.py b/functest/tests/unit/openstack/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/openstack/rally/__init__.py
+++ b/functest/tests/unit/openstack/__init__.py
diff --git a/functest/tests/unit/opnfv_tests/openstack/refstack_client/__init__.py b/functest/tests/unit/openstack/rally/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/openstack/refstack_client/__init__.py
+++ b/functest/tests/unit/openstack/rally/__init__.py
diff --git a/functest/tests/unit/opnfv_tests/openstack/rally/test_rally.py b/functest/tests/unit/openstack/rally/test_rally.py
index fe25dfcf..c7828618 100644
--- a/functest/tests/unit/opnfv_tests/openstack/rally/test_rally.py
+++ b/functest/tests/unit/openstack/rally/test_rally.py
@@ -343,19 +343,6 @@ class OSRallyTesting(unittest.TestCase):
self.rally_base._run_tests()
self.rally_base._run_task.assert_any_call('test1')
- @mock.patch('functest.opnfv_tests.openstack.rally.rally.logger.info')
- def test_generate_report(self, mock_logger_info):
- summary = [{'test_name': 'test_name',
- 'overall_duration': 5,
- 'nb_tests': 3,
- 'success': 5}]
- self.rally_base.summary = summary
- with mock.patch('functest.opnfv_tests.openstack.rally.rally.'
- 'ft_utils.check_success_rate',
- return_value='criteria'):
- self.rally_base._generate_report()
- self.assertTrue(mock_logger_info.called)
-
def test_clean_up_default(self):
self.rally_base.volume_type = mock.Mock()
self.rally_base.cinder_client = mock.Mock()
diff --git a/functest/tests/unit/opnfv_tests/openstack/tempest/__init__.py b/functest/tests/unit/openstack/refstack_client/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/openstack/tempest/__init__.py
+++ b/functest/tests/unit/openstack/refstack_client/__init__.py
diff --git a/functest/tests/unit/opnfv_tests/openstack/refstack_client/test_refstack_client.py b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
index 60e180c9..60e180c9 100644
--- a/functest/tests/unit/opnfv_tests/openstack/refstack_client/test_refstack_client.py
+++ b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
diff --git a/functest/tests/unit/opnfv_tests/vnf/__init__.py b/functest/tests/unit/openstack/tempest/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/vnf/__init__.py
+++ b/functest/tests/unit/openstack/tempest/__init__.py
diff --git a/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py b/functest/tests/unit/openstack/tempest/test_conf_utils.py
index 8ca5cc5b..8ca5cc5b 100644
--- a/functest/tests/unit/opnfv_tests/openstack/tempest/test_conf_utils.py
+++ b/functest/tests/unit/openstack/tempest/test_conf_utils.py
diff --git a/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py
index 34031b40..bb75c9ed 100644
--- a/functest/tests/unit/opnfv_tests/openstack/tempest/test_tempest.py
+++ b/functest/tests/unit/openstack/tempest/test_tempest.py
@@ -105,7 +105,7 @@ class OSTempestTesting(unittest.TestCase):
self._test_generate_test_list_mode_default('full')
def test_parse_verifier_result_missing_verification_uuid(self):
- self.tempestcommon.VERIFICATION_ID = ''
+ self.tempestcommon.VERIFICATION_ID = None
with self.assertRaises(Exception):
self.tempestcommon.parse_verifier_result()
@@ -151,118 +151,82 @@ class OSTempestTesting(unittest.TestCase):
assert_any_call("Starting Tempest test suite: '%s'."
% cmd_line)
- @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.logger.info')
- def test_parse_verifier_result_default(self, mock_logger_info):
- self.tempestcommon.VERIFICATION_ID = 'test_uuid'
- self.tempestcommon.case_name = 'test_case_name'
- stdout = ['Testscount||2', 'Success||2', 'Skipped||0', 'Failures||0']
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'subprocess.Popen') as mock_popen, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'ft_utils.check_success_rate') as mock_method, \
- mock.patch('__builtin__.open', mock.mock_open()):
- mock_stdout = mock.Mock()
- attrs = {'stdout': stdout}
- mock_stdout.configure_mock(**attrs)
- mock_popen.return_value = mock_stdout
-
- self.tempestcommon.parse_verifier_result()
- mock_method.assert_any_call('test_case_name', 100)
-
- def test_run_missing_create_tempest_dir(self):
- ret = testcase.TestCase.EX_RUN_ERROR
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.path.exists', return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.makedirs') as mock_os_makedirs, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.create_tempest_resources',
- return_value="image_and_flavor"):
- self.assertEqual(self.tempestcommon.run(),
- ret)
- self.assertTrue(mock_os_makedirs.called)
-
- def test_run_missing_configure_tempest(self):
- ret = testcase.TestCase.EX_RUN_ERROR
- ret_ok = testcase.TestCase.EX_OK
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.path.exists', return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.makedirs') as mock_os_makedirs, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.create_tempest_resources',
- return_value=ret_ok), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.configure_tempest',
- return_value=ret):
- self.assertEqual(self.tempestcommon.run(),
- ret)
- self.assertTrue(mock_os_makedirs.called)
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'os.path.exists', return_value=False)
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs',
+ side_effect=Exception)
+ def test_run_makedirs_ko(self, *args):
+ self.assertEqual(self.tempestcommon.run(),
+ testcase.TestCase.EX_RUN_ERROR)
+
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'os.path.exists', return_value=False)
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'conf_utils.create_tempest_resources', side_effect=Exception)
+ def test_run_create_tempest_resources_ko(self, *args):
+ self.assertEqual(self.tempestcommon.run(),
+ testcase.TestCase.EX_RUN_ERROR)
+
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'os.path.exists', return_value=False)
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'conf_utils.create_tempest_resources', return_value={})
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'conf_utils.configure_tempest', side_effect=Exception)
+ def test_run_configure_tempest_ko(self, *args):
+ self.assertEqual(self.tempestcommon.run(),
+ testcase.TestCase.EX_RUN_ERROR)
+
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'os.path.exists', return_value=False)
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.os.makedirs')
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'conf_utils.create_tempest_resources', return_value={})
+ @mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
+ 'conf_utils.configure_tempest')
+ def _test_run(self, status, *args):
+ self.assertEqual(self.tempestcommon.run(), status)
def test_run_missing_generate_test_list(self):
- ret = testcase.TestCase.EX_RUN_ERROR
- ret_ok = testcase.TestCase.EX_OK
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.path.exists', return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.makedirs') as mock_os_makedirs, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.create_tempest_resources',
- return_value=ret_ok), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.configure_tempest',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'generate_test_list',
- return_value=ret):
- self.assertEqual(self.tempestcommon.run(),
- ret)
- self.assertTrue(mock_os_makedirs.called)
-
- def test_run_missing_apply_tempest_blacklist(self):
- ret = testcase.TestCase.EX_RUN_ERROR
- ret_ok = testcase.TestCase.EX_OK
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.path.exists', return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.makedirs') as mock_os_makedirs, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.create_tempest_resources',
- return_value=ret_ok), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.configure_tempest',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'generate_test_list',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'apply_tempest_blacklist',
- return_value=ret):
- self.assertEqual(self.tempestcommon.run(),
- ret)
- self.assertTrue(mock_os_makedirs.called)
-
- def test_run_missing_parse_verifier_result(self):
- ret = testcase.TestCase.EX_RUN_ERROR
- ret_ok = testcase.TestCase.EX_OK
- with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.path.exists', return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'os.makedirs') as mock_os_makedirs, \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.create_tempest_resources',
- return_value=ret_ok), \
- mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
- 'conf_utils.configure_tempest',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'generate_test_list',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'apply_tempest_blacklist',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'run_verifier_tests',
- return_value=ret_ok), \
- mock.patch.object(self.tempestcommon, 'parse_verifier_result',
- return_value=ret):
- self.assertEqual(self.tempestcommon.run(),
- ret)
- self.assertTrue(mock_os_makedirs.called)
+ with mock.patch.object(self.tempestcommon, 'generate_test_list',
+ side_effect=Exception):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run_apply_tempest_blacklist_ko(self):
+ with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+ mock.patch.object(self.tempestcommon,
+ 'apply_tempest_blacklist',
+ side_effect=Exception()):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run_verifier_tests_ko(self, *args):
+ with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+ mock.patch.object(self.tempestcommon,
+ 'apply_tempest_blacklist'), \
+ mock.patch.object(self.tempestcommon, 'run_verifier_tests',
+ side_effect=Exception()), \
+ mock.patch.object(self.tempestcommon, 'parse_verifier_result',
+ side_effect=Exception):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run_parse_verifier_result_ko(self, *args):
+ with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+ mock.patch.object(self.tempestcommon,
+ 'apply_tempest_blacklist'), \
+ mock.patch.object(self.tempestcommon, 'run_verifier_tests'), \
+ mock.patch.object(self.tempestcommon, 'parse_verifier_result',
+ side_effect=Exception):
+ self._test_run(testcase.TestCase.EX_RUN_ERROR)
+
+ def test_run(self, *args):
+ with mock.patch.object(self.tempestcommon, 'generate_test_list'), \
+ mock.patch.object(self.tempestcommon,
+ 'apply_tempest_blacklist'), \
+ mock.patch.object(self.tempestcommon, 'run_verifier_tests'), \
+ mock.patch.object(self.tempestcommon, 'parse_verifier_result'):
+ self._test_run(testcase.TestCase.EX_OK)
if __name__ == "__main__":
diff --git a/functest/tests/unit/utils/test_decorators.py b/functest/tests/unit/utils/test_decorators.py
new file mode 100644
index 00000000..f8bd9a54
--- /dev/null
+++ b/functest/tests/unit/utils/test_decorators.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Orange and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+"""Define the class required to fully cover decorators."""
+
+from datetime import datetime
+import errno
+import json
+import logging
+import os
+import unittest
+
+import mock
+
+from functest.utils import decorators
+from functest.utils import functest_utils
+
+__author__ = "Cedric Ollivier <cedric.ollivier@orange.com>"
+
+VERSION = 'master'
+DIR = '/dev'
+FILE = '{}/null'.format(DIR)
+URL = 'file://{}'.format(FILE)
+
+
+class DecoratorsTesting(unittest.TestCase):
+ # pylint: disable=missing-docstring
+
+ logging.disable(logging.CRITICAL)
+
+ _case_name = 'base'
+ _project_name = 'functest'
+ _start_time = 1.0
+ _stop_time = 2.0
+ _result = 'PASS'
+ _build_tag = VERSION
+ _node_name = 'bar'
+ _deploy_scenario = 'foo'
+ _installer_type = 'debian'
+
+ def setUp(self):
+ os.environ['INSTALLER_TYPE'] = self._installer_type
+ os.environ['DEPLOY_SCENARIO'] = self._deploy_scenario
+ os.environ['NODE_NAME'] = self._node_name
+ os.environ['BUILD_TAG'] = self._build_tag
+
+ def test_wraps(self):
+ self.assertEqual(functest_utils.push_results_to_db.__name__,
+ "push_results_to_db")
+
+ def _get_json(self):
+ stop_time = datetime.fromtimestamp(self._stop_time).strftime(
+ '%Y-%m-%d %H:%M:%S')
+ start_time = datetime.fromtimestamp(self._start_time).strftime(
+ '%Y-%m-%d %H:%M:%S')
+ data = {'project_name': self._project_name,
+ 'stop_date': stop_time, 'start_date': start_time,
+ 'case_name': self._case_name, 'build_tag': self._build_tag,
+ 'pod_name': self._node_name, 'installer': self._installer_type,
+ 'scenario': self._deploy_scenario, 'version': VERSION,
+ 'details': {}, 'criteria': self._result}
+ return json.dumps(data)
+
+ @mock.patch('{}.get_db_url'.format(functest_utils.__name__),
+ return_value='http://127.0.0.1')
+ @mock.patch('{}.get_version'.format(functest_utils.__name__),
+ return_value=VERSION)
+ @mock.patch('requests.post')
+ def test_http_shema(self, *args):
+ self.assertTrue(functest_utils.push_results_to_db(
+ self._project_name, self._case_name, self._start_time,
+ self._stop_time, self._result, {}))
+ args[1].assert_called_once_with()
+ args[2].assert_called_once_with()
+ args[0].assert_called_once_with(
+ 'http://127.0.0.1', data=self._get_json(),
+ headers={'Content-Type': 'application/json'})
+
+ @mock.patch('{}.get_db_url'.format(functest_utils.__name__),
+ return_value="/dev/null")
+ def test_wrong_shema(self, mock_method=None):
+ self.assertFalse(functest_utils.push_results_to_db(
+ self._project_name, self._case_name, self._start_time,
+ self._stop_time, self._result, {}))
+ mock_method.assert_called_once_with()
+
+ @mock.patch('{}.get_version'.format(functest_utils.__name__),
+ return_value=VERSION)
+ @mock.patch('{}.get_db_url'.format(functest_utils.__name__),
+ return_value=URL)
+ def _test_dump(self, *args):
+ with mock.patch.object(decorators, 'open', mock.mock_open(),
+ create=True) as mock_open:
+ self.assertTrue(functest_utils.push_results_to_db(
+ self._project_name, self._case_name, self._start_time,
+ self._stop_time, self._result, {}))
+ mock_open.assert_called_once_with(FILE, 'a')
+ handle = mock_open()
+ call_args, _ = handle.write.call_args
+ self.assertIn('POST', call_args[0])
+ self.assertIn(self._get_json(), call_args[0])
+ args[0].assert_called_once_with()
+ args[1].assert_called_once_with()
+
+ @mock.patch('os.makedirs')
+ def test_default_dump(self, mock_method=None):
+ self._test_dump()
+ mock_method.assert_called_once_with(DIR)
+
+ @mock.patch('os.makedirs', side_effect=OSError(errno.EEXIST, ''))
+ def test_makedirs_dir_exists(self, mock_method=None):
+ self._test_dump()
+ mock_method.assert_called_once_with(DIR)
+
+ @mock.patch('{}.get_db_url'.format(functest_utils.__name__),
+ return_value=URL)
+ @mock.patch('os.makedirs', side_effect=OSError)
+ def test_makedirs_exc(self, *args):
+ self.assertFalse(
+ functest_utils.push_results_to_db(
+ self._project_name, self._case_name, self._start_time,
+ self._stop_time, self._result, {}))
+ args[0].assert_called_once_with(DIR)
+ args[1].assert_called_once_with()
+
+
+if __name__ == "__main__":
+ logging.basicConfig()
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_functest_logger.py b/functest/tests/unit/utils/test_functest_logger.py
deleted file mode 100644
index 42e41a14..00000000
--- a/functest/tests/unit/utils/test_functest_logger.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-import logging
-import unittest
-
-import mock
-
-from functest.utils import functest_logger
-from functest.utils.constants import CONST
-
-
-class OSUtilsLogger(unittest.TestCase):
-
- logging.disable(logging.CRITICAL)
-
- def setUp(self):
- with mock.patch('__builtin__.open', mock.mock_open()):
- with mock.patch('functest.utils.functest_logger.os.path.exists',
- return_value=True), \
- mock.patch('functest.utils.functest_logger.'
- 'json.load'), \
- mock.patch('functest.utils.functest_logger.'
- 'logging.config.dictConfig') as m:
- self.logger = functest_logger.Logger('os_utils')
- self.assertTrue(m.called)
- with mock.patch('functest.utils.functest_logger.os.path.exists',
- return_value=False), \
- mock.patch('functest.utils.functest_logger.'
- 'logging.basicConfig') as m:
- self.logger = functest_logger.Logger('os_utils')
- self.assertTrue(m.called)
-
- def test_is_debug_false(self):
- CONST.CI_DEBUG = False
- self.assertFalse(self.logger.is_debug())
-
- def test_is_debug_true(self):
- CONST.CI_DEBUG = "True"
- self.assertTrue(self.logger.is_debug())
-
-
-if __name__ == "__main__":
- unittest.main(verbosity=2)
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
index eb241e5d..57e0c465 100644
--- a/functest/tests/unit/utils/test_functest_utils.py
+++ b/functest/tests/unit/utils/test_functest_utils.py
@@ -11,11 +11,11 @@ import logging
import os
import time
import unittest
-import urllib2
from git.exc import NoSuchPathError
import mock
import requests
+from six.moves import urllib
from functest.tests.unit import test_utils
from functest.utils import functest_utils
@@ -41,8 +41,8 @@ class FunctestUtilsTesting(unittest.TestCase):
self.status = 'test_status'
self.details = 'test_details'
self.db_url = 'test_db_url'
- self.success_rate = 2.0
- self.criteria = 'test_criteria==2.0'
+ self.criteria = 50
+ self.result = 75
self.start_date = 1482624000
self.stop_date = 1482624000
self.start_time = time.time()
@@ -54,38 +54,39 @@ class FunctestUtilsTesting(unittest.TestCase):
self.cmd = 'test_cmd'
self.output_file = 'test_output_file'
self.testname = 'testname'
- self.testcase_dict = {'name': 'testname', 'criteria': self.criteria}
+ self.testcase_dict = {'case_name': 'testname',
+ 'criteria': self.criteria}
self.parameter = 'general.openstack.image_name'
self.config_yaml = 'test_config_yaml-'
self.db_url_env = 'http://foo/testdb'
self.file_yaml = {'general': {'openstack': {'image_name':
'test_image_name'}}}
- @mock.patch('urllib2.urlopen',
- side_effect=urllib2.URLError('no host given'))
+ @mock.patch('six.moves.urllib.request.urlopen',
+ side_effect=urllib.error.URLError('no host given'))
def test_check_internet_connectivity_failed(self, mock_method):
self.assertFalse(functest_utils.check_internet_connectivity())
mock_method.assert_called_once_with(self.url, timeout=self.timeout)
- @mock.patch('urllib2.urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
def test_check_internet_connectivity_default(self, mock_method):
self.assertTrue(functest_utils.check_internet_connectivity())
mock_method.assert_called_once_with(self.url, timeout=self.timeout)
- @mock.patch('urllib2.urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
def test_check_internet_connectivity_debian(self, mock_method):
self.url = "https://www.debian.org/"
self.assertTrue(functest_utils.check_internet_connectivity(self.url))
mock_method.assert_called_once_with(self.url, timeout=self.timeout)
- @mock.patch('urllib2.urlopen',
- side_effect=urllib2.URLError('no host given'))
+ @mock.patch('six.moves.urllib.request.urlopen',
+ side_effect=urllib.error.URLError('no host given'))
def test_download_url_failed(self, mock_url):
self.assertFalse(functest_utils.download_url(self.url, self.dest_path))
- @mock.patch('urllib2.urlopen')
+ @mock.patch('six.moves.urllib.request.urlopen')
def test_download_url_default(self, mock_url):
- with mock.patch("__builtin__.open", mock.mock_open()) as m, \
+ with mock.patch("six.moves.builtins.open", mock.mock_open()) as m, \
mock.patch('functest.utils.functest_utils.shutil.copyfileobj')\
as mock_sh:
name = self.url.rsplit('/')[-1]
@@ -278,7 +279,7 @@ class FunctestUtilsTesting(unittest.TestCase):
as mock_logger_error:
functest_utils.push_results_to_db(self.project, self.case_name,
self.start_date, self.stop_date,
- self.criteria, self.details)
+ self.result, self.details)
mock_logger_error.assert_called_once_with("Please set env var: " +
str("\'" + env_var +
"\'"))
@@ -310,7 +311,7 @@ class FunctestUtilsTesting(unittest.TestCase):
push_results_to_db(self.project, self.case_name,
self.start_date,
self.stop_date,
- self.criteria, self.details))
+ self.result, self.details))
mock_logger_error.assert_called_once_with(test_utils.
RegexMatch("Pushing "
"Result to"
@@ -333,7 +334,7 @@ class FunctestUtilsTesting(unittest.TestCase):
push_results_to_db(self.project, self.case_name,
self.start_date,
self.stop_date,
- self.criteria, self.details))
+ self.result, self.details))
self.assertTrue(mock_logger_error.called)
def test_push_results_to_db_default(self):
@@ -348,7 +349,7 @@ class FunctestUtilsTesting(unittest.TestCase):
push_results_to_db(self.project, self.case_name,
self.start_date,
self.stop_date,
- self.criteria, self.details))
+ self.result, self.details))
readline = 0
test_ip = ['10.1.23.4', '10.1.14.15', '10.1.16.15']
@@ -370,7 +371,7 @@ class FunctestUtilsTesting(unittest.TestCase):
attrs = {'readline.side_effect': self.readline_side}
m.configure_mock(**attrs)
- with mock.patch("__builtin__.open") as mo:
+ with mock.patch("six.moves.builtins.open") as mo:
mo.return_value = m
self.assertEqual(functest_utils.get_resolvconf_ns(),
self.test_ip[1:])
@@ -398,7 +399,8 @@ class FunctestUtilsTesting(unittest.TestCase):
mock_logger_error):
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open, \
- mock.patch('__builtin__.open', mock.mock_open()) as mopen:
+ mock.patch('six.moves.builtins.open',
+ mock.mock_open()) as mopen:
FunctestUtilsTesting.readline = 0
@@ -427,7 +429,8 @@ class FunctestUtilsTesting(unittest.TestCase):
):
with mock.patch('functest.utils.functest_utils.subprocess.Popen') \
as mock_subproc_open, \
- mock.patch('__builtin__.open', mock.mock_open()) as mopen:
+ mock.patch('six.moves.builtins.open',
+ mock.mock_open()) as mopen:
FunctestUtilsTesting.readline = 0
@@ -502,7 +505,7 @@ class FunctestUtilsTesting(unittest.TestCase):
@mock.patch('functest.utils.functest_utils.logger.error')
def test_get_dict_by_test(self, mock_logger_error):
- with mock.patch('__builtin__.open', mock.mock_open()), \
+ with mock.patch('six.moves.builtins.open', mock.mock_open()), \
mock.patch('functest.utils.functest_utils.yaml.safe_load') \
as mock_yaml, \
mock.patch('functest.utils.functest_utils.get_testcases_'
@@ -530,7 +533,7 @@ class FunctestUtilsTesting(unittest.TestCase):
def test_get_parameter_from_yaml_failed(self):
self.file_yaml['general'] = None
- with mock.patch('__builtin__.open', mock.mock_open()), \
+ with mock.patch('six.moves.builtins.open', mock.mock_open()), \
mock.patch('functest.utils.functest_utils.yaml.safe_load') \
as mock_yaml, \
self.assertRaises(ValueError) as excep:
@@ -542,7 +545,7 @@ class FunctestUtilsTesting(unittest.TestCase):
self.parameter) in excep.exception)
def test_get_parameter_from_yaml_default(self):
- with mock.patch('__builtin__.open', mock.mock_open()), \
+ with mock.patch('six.moves.builtins.open', mock.mock_open()), \
mock.patch('functest.utils.functest_utils.yaml.safe_load') \
as mock_yaml:
mock_yaml.return_value = self.file_yaml
@@ -560,22 +563,6 @@ class FunctestUtilsTesting(unittest.TestCase):
assert_called_once_with(self.parameter,
self.config_yaml)
- def test_check_success_rate_default(self):
- with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \
- as mock_criteria:
- mock_criteria.return_value = self.criteria
- resp = functest_utils.check_success_rate(self.case_name,
- self.success_rate)
- self.assertEqual(resp, 'PASS')
-
- def test_check_success_rate_failed(self):
- with mock.patch('functest.utils.functest_utils.get_criteria_by_test') \
- as mock_criteria:
- mock_criteria.return_value = self.criteria
- resp = functest_utils.check_success_rate(self.case_name,
- 3.0)
- self.assertEqual(resp, 'FAIL')
-
# TODO: merge_dicts
def test_get_testcases_file_dir(self):
@@ -585,7 +572,7 @@ class FunctestUtilsTesting(unittest.TestCase):
"functest/ci/testcases.yaml")
def test_get_functest_yaml(self):
- with mock.patch('__builtin__.open', mock.mock_open()), \
+ with mock.patch('six.moves.builtins.open', mock.mock_open()), \
mock.patch('functest.utils.functest_utils.yaml.safe_load') \
as mock_yaml:
mock_yaml.return_value = self.file_yaml
diff --git a/functest/tests/unit/utils/test_openstack_utils.py b/functest/tests/unit/utils/test_openstack_utils.py
index 7f3995d0..a7df264c 100644
--- a/functest/tests/unit/utils/test_openstack_utils.py
+++ b/functest/tests/unit/utils/test_openstack_utils.py
@@ -418,21 +418,45 @@ class OSUtilsTesting(unittest.TestCase):
mock_logger_info.assert_called_once_with("OS_IDENTITY_API_VERSION is "
"set in env as '%s'", '3')
- def test_get_keystone_client(self):
+ @mock.patch('functest.utils.openstack_utils.get_session')
+ @mock.patch('functest.utils.openstack_utils.keystoneclient.Client')
+ @mock.patch('functest.utils.openstack_utils.get_keystone_client_version',
+ return_value='3')
+ @mock.patch('functest.utils.openstack_utils.os.getenv',
+ return_value='public')
+ def test_get_keystone_client_with_interface(self, mock_os_getenv,
+ mock_keystoneclient_version,
+ mock_key_client,
+ mock_get_session):
mock_keystone_obj = mock.Mock()
mock_session_obj = mock.Mock()
- with mock.patch('functest.utils.openstack_utils'
- '.get_keystone_client_version', return_value='3'), \
- mock.patch('functest.utils.openstack_utils'
- '.keystoneclient.Client',
- return_value=mock_keystone_obj) \
- as mock_key_client, \
- mock.patch('functest.utils.openstack_utils.get_session',
- return_value=mock_session_obj):
- self.assertEqual(openstack_utils.get_keystone_client(),
- mock_keystone_obj)
- mock_key_client.assert_called_once_with('3',
- session=mock_session_obj)
+ mock_key_client.return_value = mock_keystone_obj
+ mock_get_session.return_value = mock_session_obj
+ self.assertEqual(openstack_utils.get_keystone_client(),
+ mock_keystone_obj)
+ mock_key_client.assert_called_once_with('3',
+ session=mock_session_obj,
+ interface='public')
+
+ @mock.patch('functest.utils.openstack_utils.get_session')
+ @mock.patch('functest.utils.openstack_utils.keystoneclient.Client')
+ @mock.patch('functest.utils.openstack_utils.get_keystone_client_version',
+ return_value='3')
+ @mock.patch('functest.utils.openstack_utils.os.getenv',
+ return_value='admin')
+ def test_get_keystone_client_no_interface(self, mock_os_getenv,
+ mock_keystoneclient_version,
+ mock_key_client,
+ mock_get_session):
+ mock_keystone_obj = mock.Mock()
+ mock_session_obj = mock.Mock()
+ mock_key_client.return_value = mock_keystone_obj
+ mock_get_session.return_value = mock_session_obj
+ self.assertEqual(openstack_utils.get_keystone_client(),
+ mock_keystone_obj)
+ mock_key_client.assert_called_once_with('3',
+ session=mock_session_obj,
+ interface='admin')
@mock.patch('functest.utils.openstack_utils.os.getenv',
return_value=None)
diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/__init__.py b/functest/tests/unit/vnf/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/tests/unit/opnfv_tests/vnf/ims/__init__.py
+++ b/functest/tests/unit/vnf/__init__.py
diff --git a/functest/tests/unit/vnf/ims/__init__.py b/functest/tests/unit/vnf/ims/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/functest/tests/unit/vnf/ims/__init__.py
diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py b/functest/tests/unit/vnf/ims/test_clearwater.py
index 18bebfdf..18bebfdf 100644
--- a/functest/tests/unit/opnfv_tests/vnf/ims/test_clearwater.py
+++ b/functest/tests/unit/vnf/ims/test_clearwater.py
diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_cloudify_ims.py b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
index f47ea865..f47ea865 100644
--- a/functest/tests/unit/opnfv_tests/vnf/ims/test_cloudify_ims.py
+++ b/functest/tests/unit/vnf/ims/test_cloudify_ims.py
diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_ims_base.by b/functest/tests/unit/vnf/ims/test_ims_base.py
index 9440bcdf..e283199c 100644
--- a/functest/tests/unit/opnfv_tests/vnf/ims/test_ims_base.by
+++ b/functest/tests/unit/vnf/ims/test_ims_base.py
@@ -10,7 +10,7 @@ import unittest
import mock
-from functest.opnfv_tests.vnf.ims import ims_base
+from functest.opnfv_tests.vnf.ims import clearwater_ims_base as ims_base
class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
@@ -38,8 +38,8 @@ class ClearwaterOnBoardingBaseTesting(unittest.TestCase):
self.mock_post_200.configure_mock(**attrs)
def test_create_ellis_number_failure(self):
- with mock.patch('functest.opnfv_tests.vnf.ims.ims_base.'
- 'requests.post',
+ with mock.patch('functest.opnfv_tests.vnf.ims.'
+ 'clearwater_ims_base.requests.post',
return_value=self.mock_post_500), \
self.assertRaises(Exception) as context:
self.ims_vnf.create_ellis_number()
diff --git a/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py b/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py
index bf6d483f..bf6d483f 100644
--- a/functest/tests/unit/opnfv_tests/vnf/ims/test_orchestrator_cloudify.py
+++ b/functest/tests/unit/vnf/ims/test_orchestrator_cloudify.py
diff --git a/functest/tests/unit/vnf/rnc/__init__.py b/functest/tests/unit/vnf/rnc/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/functest/tests/unit/vnf/rnc/__init__.py
diff --git a/functest/utils/config.py b/functest/utils/config.py
index b5b84501..d91f63ac 100755..100644
--- a/functest/utils/config.py
+++ b/functest/utils/config.py
@@ -1,8 +1,11 @@
-import os
+#!/usr/bin/env python
+import os
import yaml
-import env
+import six
+
+from functest.utils import env
class Config(object):
@@ -16,7 +19,7 @@ class Config(object):
self._set_others()
def _parse(self, attr_now, left_parametes):
- for param_n, param_v in left_parametes.iteritems():
+ for param_n, param_v in six.iteritems(left_parametes):
attr_further = self._get_attr_further(attr_now, param_n)
if attr_further:
self.__setattr__(attr_further, param_v)
@@ -32,8 +35,3 @@ class Config(object):
CONF = Config()
-
-if __name__ == "__main__":
- print CONF.vnf_cloudify_ims
- print CONF.vnf_cloudify_ims_tenant_images
- print CONF.vnf_cloudify_ims_tenant_images_centos_7
diff --git a/functest/utils/constants.py b/functest/utils/constants.py
index 2e8eb3f4..75c97c76 100755..100644
--- a/functest/utils/constants.py
+++ b/functest/utils/constants.py
@@ -1,20 +1,17 @@
-import config
-import env
+#!/usr/bin/env python
+
+import six
+
+from functest.utils import config
+from functest.utils import env
class Constants(object):
def __init__(self):
- for attr_n, attr_v in config.CONF.__dict__.iteritems():
+ for attr_n, attr_v in six.iteritems(config.CONF.__dict__):
self.__setattr__(attr_n, attr_v)
- for env_n, env_v in env.ENV.__dict__.iteritems():
+ for env_n, env_v in six.iteritems(env.ENV.__dict__):
self.__setattr__(env_n, env_v)
CONST = Constants()
-
-if __name__ == '__main__':
- print CONST.__dict__
- print CONST.NODE_NAME
- print CONST.vIMS_clearwater_blueprint_url
- print CONST.vIMS_clearwater_blueprint_file_name
- print CONST.vIMS_clearwater_blueprint_name
diff --git a/functest/utils/decorators.py b/functest/utils/decorators.py
index 276235d9..73e0a352 100644
--- a/functest/utils/decorators.py
+++ b/functest/utils/decorators.py
@@ -1,41 +1,48 @@
#!/usr/bin/env python
+# pylint: disable=missing-docstring
+
import errno
-import mock
+import functools
import os
+
+import mock
import requests.sessions
-import urlparse
+from six.moves import urllib
def can_dump_request_to_file(method):
def dump_preparedrequest(request, **kwargs):
- parseresult = urlparse.urlparse(request.url)
+ # pylint: disable=unused-argument
+ parseresult = urllib.parse.urlparse(request.url)
if parseresult.scheme == "file":
try:
- os.makedirs(parseresult.path)
- except OSError as e:
- if e.errno != errno.EEXIST:
+ dirname = os.path.dirname(parseresult.path)
+ os.makedirs(dirname)
+ except OSError as ex:
+ if ex.errno != errno.EEXIST:
raise
- with open(os.path.join(parseresult.path, 'dump.txt'), 'a') as f:
+ with open(parseresult.path, 'a') as dumpfile:
headers = ""
for key in request.headers:
headers += key + " " + request.headers[key] + "\n"
message = "{} {}\n{}\n{}\n\n\n".format(
request.method, request.url, headers, request.body)
- f.write(message)
+ dumpfile.write(message)
return mock.Mock()
def patch_request(method, url, **kwargs):
with requests.sessions.Session() as session:
- parseresult = urlparse.urlparse(url)
+ parseresult = urllib.parse.urlparse(url)
if parseresult.scheme == "file":
- with mock.patch.object(
- session, 'send', side_effect=dump_preparedrequest):
+ with mock.patch.object(session, 'send',
+ side_effect=dump_preparedrequest):
return session.request(method=method, url=url, **kwargs)
else:
return session.request(method=method, url=url, **kwargs)
+ @functools.wraps(method)
def hook(*args, **kwargs):
with mock.patch('requests.api.request', side_effect=patch_request):
return method(*args, **kwargs)
diff --git a/functest/utils/env.py b/functest/utils/env.py
index 7e4df2ea..c9629e15 100644
--- a/functest/utils/env.py
+++ b/functest/utils/env.py
@@ -1,6 +1,11 @@
+#!/usr/bin/env python
+
import os
import re
+import six
+
+
default_envs = {
'NODE_NAME': 'unknown_pod',
'CI_DEBUG': 'false',
@@ -17,9 +22,9 @@ default_envs = {
class Environment(object):
def __init__(self):
- for k, v in os.environ.iteritems():
+ for k, v in six.iteritems(os.environ):
self.__setattr__(k, v)
- for k, v in default_envs.iteritems():
+ for k, v in six.iteritems(default_envs):
if k not in os.environ:
self.__setattr__(k, v)
self._set_ci_run()
diff --git a/functest/utils/functest_logger.py b/functest/utils/functest_logger.py
deleted file mode 100644
index 555e9c28..00000000
--- a/functest/utils/functest_logger.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-#
-# jose.lausuch@ericsson.com
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Logging levels:
-# Level Numeric value
-# CRITICAL 50
-# ERROR 40
-# WARNING 30
-# INFO 20
-# DEBUG 10
-# NOTSET 0
-#
-# Usage:
-# import functest_logger as fl
-# logger = fl.Logger("script_name").getLogger()
-# logger.info("message to be shown with - INFO - ")
-# logger.debug("message to be shown with - DEBUG -")
-import logging
-import logging.config
-import os
-
-import json
-
-from functest.utils.constants import CONST
-
-ignore = ["paramiko",
- "stevedore.extension",
- "keystoneauth.session",
- "keystoneauth.identity.v3.base",
- "novaclient.v2.client",
- "neutronclient.v2_0.client",
- "glanceclient.common.http",
- "cinderclient.v2.client",
- "cinderclient.client"]
-
-
-class Logger(object):
-
- def __init__(self, logger_name):
- self.setup_logging()
- self.logger = logging.getLogger(logger_name)
- for module_name in ignore:
- logging.getLogger(module_name).setLevel(logging.WARNING)
-
- def getLogger(self):
- return self.logger
-
- def is_debug(self):
- if CONST.CI_DEBUG and CONST.CI_DEBUG.lower() == "true":
- return True
- return False
-
- def setup_logging(self, default_path=CONST.dir_functest_logging_cfg,
- default_level=logging.INFO,
- env_key='LOG_CFG'):
- path = default_path
- value = os.getenv(env_key, None)
- if value:
- path = value
- if os.path.exists(path):
- with open(path, 'rt') as f:
- config = json.load(f)
- if (config['handlers'] and
- config['handlers']['console']):
- stream_level = logging.INFO
- if self.is_debug():
- stream_level = logging.DEBUG
- config['handlers']['console']['level'] = stream_level
- logging.config.dictConfig(config)
- else:
- logging.basicConfig(level=default_level)
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py
index 7cc5029d..bf30f56e 100644
--- a/functest/utils/functest_utils.py
+++ b/functest/utils/functest_utils.py
@@ -9,24 +9,24 @@
#
import functools
import json
+import logging
import os
import re
import shutil
import subprocess
import sys
import time
-import urllib2
from datetime import datetime as dt
import dns.resolver
import requests
+from six.moves import urllib
import yaml
from git import Repo
from functest.utils import decorators
-import functest.utils.functest_logger as ft_logger
-logger = ft_logger.Logger("functest_utils").getLogger()
+logger = logging.getLogger(__name__)
# ----------------------------------------------------------
@@ -39,9 +39,9 @@ def check_internet_connectivity(url='http://www.opnfv.org/'):
Check if there is access to the internet
"""
try:
- urllib2.urlopen(url, timeout=5)
+ urllib.request.urlopen(url, timeout=5)
return True
- except urllib2.URLError:
+ except urllib.error.URLError:
return False
@@ -52,8 +52,8 @@ def download_url(url, dest_path):
name = url.rsplit('/')[-1]
dest = dest_path + "/" + name
try:
- response = urllib2.urlopen(url)
- except (urllib2.HTTPError, urllib2.URLError):
+ response = urllib.request.urlopen(url)
+ except (urllib.error.HTTPError, urllib.error.URLError):
return False
with open(dest, 'wb') as f:
@@ -192,12 +192,12 @@ def logger_test_results(project, case_name, status, details):
@decorators.can_dump_request_to_file
def push_results_to_db(project, case_name,
- start_date, stop_date, criteria, details):
+ start_date, stop_date, result, details):
"""
POST results to the Result target DB
"""
# Retrieve params from CI and conf
- url = get_db_url() + "/results"
+ url = get_db_url()
try:
installer = os.environ['INSTALLER_TYPE']
@@ -213,7 +213,7 @@ def push_results_to_db(project, case_name,
params = {"project_name": project, "case_name": case_name,
"pod_name": pod_name, "installer": installer,
- "version": version, "scenario": scenario, "criteria": criteria,
+ "version": version, "scenario": scenario, "criteria": result,
"build_tag": build_tag, "start_date": test_start,
"stop_date": test_stop, "details": details}
@@ -248,7 +248,7 @@ def push_results_to_db(project, case_name,
'pod': pod_name,
'v': version,
's': scenario,
- 'c': criteria,
+ 'c': result,
't': build_tag,
'd': details,
'error': e
@@ -318,7 +318,7 @@ def execute_command(cmd, info=False, error_msg="",
f.write(line)
else:
line = line.replace('\n', '')
- print line
+ print(line)
sys.stdout.flush()
if output_file:
f.close()
@@ -337,7 +337,7 @@ def get_dict_by_test(testname):
for dic_tier in testcases_yaml.get("tiers"):
for dic_testcase in dic_tier['testcases']:
- if dic_testcase['name'] == testname:
+ if dic_testcase['case_name'] == testname:
return dic_testcase
logger.error('Project %s is not defined in testcases.yaml' % testname)
@@ -379,25 +379,6 @@ def get_functest_config(parameter):
return get_parameter_from_yaml(parameter, yaml_)
-def check_success_rate(case_name, success_rate):
- success_rate = float(success_rate)
- criteria = get_criteria_by_test(case_name)
-
- def get_criteria_value(op):
- return float(criteria.split(op)[1].rstrip('%'))
-
- status = 'FAIL'
- ops = ['==', '>=']
- for op in ops:
- if op in criteria:
- c_value = get_criteria_value(op)
- if eval("%s %s %s" % (success_rate, op, c_value)):
- status = 'PASS'
- break
-
- return status
-
-
def merge_dicts(dict1, dict2):
for k in set(dict1.keys()).union(dict2.keys()):
if k in dict1 and k in dict2:
diff --git a/functest/utils/openstack/cinder.py b/functest/utils/openstack/cinder.py
deleted file mode 100644
index f966468a..00000000
--- a/functest/utils/openstack/cinder.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
diff --git a/functest/utils/openstack/glance.py b/functest/utils/openstack/glance.py
deleted file mode 100644
index f966468a..00000000
--- a/functest/utils/openstack/glance.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
diff --git a/functest/utils/openstack/keystone.py b/functest/utils/openstack/keystone.py
deleted file mode 100644
index f966468a..00000000
--- a/functest/utils/openstack/keystone.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
diff --git a/functest/utils/openstack/neutron.py b/functest/utils/openstack/neutron.py
deleted file mode 100644
index f966468a..00000000
--- a/functest/utils/openstack/neutron.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
diff --git a/functest/utils/openstack/nova.py b/functest/utils/openstack/nova.py
deleted file mode 100644
index f966468a..00000000
--- a/functest/utils/openstack/nova.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
diff --git a/functest/utils/openstack_clean.py b/functest/utils/openstack_clean.py
index ce61fcac..29106d9e 100755
--- a/functest/utils/openstack_clean.py
+++ b/functest/utils/openstack_clean.py
@@ -24,13 +24,13 @@
import time
+import logging
import yaml
-import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST
-logger = ft_logger.Logger("openstack_clean").getLogger()
+logger = logging.getLogger(__name__)
OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file
@@ -428,4 +428,5 @@ def main():
if __name__ == '__main__':
+ logging.basicConfig()
main()
diff --git a/functest/utils/openstack_snapshot.py b/functest/utils/openstack_snapshot.py
index e64030f7..952fb7bb 100755
--- a/functest/utils/openstack_snapshot.py
+++ b/functest/utils/openstack_snapshot.py
@@ -20,13 +20,13 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
+import logging
import yaml
-import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST
-logger = ft_logger.Logger("openstack_snapshot").getLogger()
+logger = logging.getLogger(__name__)
OS_SNAPSHOT_FILE = CONST.openstack_snapshot_file
@@ -162,4 +162,5 @@ def main():
if __name__ == '__main__':
+ logging.basicConfig()
main()
diff --git a/functest/utils/openstack_tacker.py b/functest/utils/openstack_tacker.py
index 8327fdbe..9fd9d5c4 100644
--- a/functest/utils/openstack_tacker.py
+++ b/functest/utils/openstack_tacker.py
@@ -11,13 +11,13 @@
# http://www.apache.org/licenses/LICENSE-2.0
##########################################################################
+import logging
from tackerclient.v1_0 import client as tackerclient
-import functest.utils.functest_logger as ft_logger
import functest.utils.openstack_utils as os_utils
import time
-logger = ft_logger.Logger("tacker_utils").getLogger()
+logger = logging.getLogger(__name__)
def get_tacker_client(other_creds={}):
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index 4663f7ba..8bd95052 100644
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -8,7 +8,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
-import os
+import logging
import os.path
import re
import sys
@@ -23,10 +23,9 @@ from novaclient import client as novaclient
from keystoneclient import client as keystoneclient
from neutronclient.neutron import client as neutronclient
-import functest.utils.functest_logger as ft_logger
import functest.utils.functest_utils as ft_utils
-logger = ft_logger.Logger("openstack_utils").getLogger()
+logger = logging.getLogger(__name__)
DEFAULT_API_VERSION = '2'
DEFAULT_HEAT_API_VERSION = '1'
@@ -139,11 +138,11 @@ def get_credentials_for_rally():
endpoint_types = [('internalURL', 'internal'),
('publicURL', 'public'), ('adminURL', 'admin')]
- endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
+ endpoint_type = get_endpoint_type_from_env()
if endpoint_type is not None:
cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
for k, v in endpoint_types:
- if endpoint_type == k:
+ if endpoint_type == v:
rally_conf[cred_key] = v
region_name = os.getenv('OS_REGION_NAME')
@@ -158,6 +157,14 @@ def get_credentials_for_rally():
return rally_conf
+def get_endpoint_type_from_env():
+ endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
+ os.environ.get("OS_INTERFACE"))
+ if endpoint_type and "URL" in endpoint_type:
+ endpoint_type = endpoint_type.replace("URL", "")
+ return endpoint_type
+
+
def get_session_auth(other_creds={}):
loader = loading.get_plugin_loader('password')
creds = get_credentials(other_creds)
@@ -198,7 +205,9 @@ def get_keystone_client_version():
def get_keystone_client(other_creds={}):
sess = get_session(other_creds)
- return keystoneclient.Client(get_keystone_client_version(), session=sess)
+ return keystoneclient.Client(get_keystone_client_version(),
+ session=sess,
+ interface=os.getenv('OS_INTERFACE', 'admin'))
def get_nova_client_version():
@@ -277,7 +286,7 @@ def get_instances(nova_client):
try:
instances = nova_client.servers.list(search_opts={'all_tenants': 1})
return instances
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_instances(nova_client)]: %s" % e)
return None
@@ -286,7 +295,7 @@ def get_instance_status(nova_client, instance):
try:
instance = nova_client.servers.get(instance.id)
return instance.status
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_instance_status(nova_client)]: %s" % e)
return None
@@ -295,7 +304,7 @@ def get_instance_by_name(nova_client, instance_name):
try:
instance = nova_client.servers.find(name=instance_name)
return instance
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
% (instance_name, e))
return None
@@ -325,7 +334,7 @@ def get_aggregates(nova_client):
try:
aggregates = nova_client.aggregates.list()
return aggregates
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_aggregates(nova_client)]: %s" % e)
return None
@@ -335,7 +344,7 @@ def get_aggregate_id(nova_client, aggregate_name):
aggregates = get_aggregates(nova_client)
_id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
return _id
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_aggregate_id(nova_client, %s)]:"
" %s" % (aggregate_name, e))
return None
@@ -345,7 +354,7 @@ def get_availability_zones(nova_client):
try:
availability_zones = nova_client.availability_zones.list()
return availability_zones
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
return None
@@ -354,7 +363,7 @@ def get_availability_zone_names(nova_client):
try:
az_names = [az.zoneName for az in get_availability_zones(nova_client)]
return az_names
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_availability_zone_names(nova_client)]:"
" %s" % e)
return None
@@ -372,7 +381,7 @@ def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
# flavor extra specs are not configured, therefore skip the update
pass
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
"'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
return None
@@ -405,7 +414,7 @@ def get_floating_ips(nova_client):
try:
floating_ips = nova_client.floating_ips.list()
return floating_ips
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
return None
@@ -418,7 +427,7 @@ def get_hypervisors(nova_client):
if hypervisor.state == "up":
nodes.append(hypervisor.hypervisor_hostname)
return nodes
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
return None
@@ -427,7 +436,7 @@ def create_aggregate(nova_client, aggregate_name, av_zone):
try:
nova_client.aggregates.create(aggregate_name, av_zone)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
% (aggregate_name, av_zone, e))
return None
@@ -438,7 +447,7 @@ def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
aggregate_id = get_aggregate_id(nova_client, aggregate_name)
nova_client.aggregates.add_host(aggregate_id, compute_host)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
% (aggregate_name, compute_host, e))
return None
@@ -450,7 +459,7 @@ def create_aggregate_with_host(
create_aggregate(nova_client, aggregate_name, av_zone)
add_host_to_aggregate(nova_client, aggregate_name, compute_host)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_aggregate_with_host("
"nova_client, %s, %s, %s)]: %s"
% (aggregate_name, av_zone, compute_host, e))
@@ -543,7 +552,7 @@ def create_floating_ip(neutron_client):
ip_json = neutron_client.create_floatingip({'floatingip': props})
fip_addr = ip_json['floatingip']['floating_ip_address']
fip_id = ip_json['floatingip']['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
return None
return {'fip_addr': fip_addr, 'fip_id': fip_id}
@@ -553,7 +562,7 @@ def add_floating_ip(nova_client, server_id, floatingip_addr):
try:
nova_client.servers.add_floating_ip(server_id, floatingip_addr)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
% (server_id, floatingip_addr, e))
return False
@@ -563,7 +572,7 @@ def delete_instance(nova_client, instance_id):
try:
nova_client.servers.force_delete(instance_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_instance(nova_client, '%s')]: %s"
% (instance_id, e))
return False
@@ -573,7 +582,7 @@ def delete_floating_ip(nova_client, floatingip_id):
try:
nova_client.floating_ips.delete(floatingip_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
% (floatingip_id, e))
return False
@@ -584,7 +593,7 @@ def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
aggregate_id = get_aggregate_id(nova_client, aggregate_name)
nova_client.aggregates.remove_host(aggregate_id, compute_host)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
" %s" % (aggregate_name, compute_host, e))
return False
@@ -603,7 +612,7 @@ def delete_aggregate(nova_client, aggregate_name):
remove_hosts_from_aggregate(nova_client, aggregate_name)
nova_client.aggregates.delete(aggregate_name)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
% (aggregate_name, e))
return False
@@ -706,7 +715,7 @@ def create_neutron_net(neutron_client, name):
network = neutron_client.create_network(body=json_body)
network_dict = network['network']
return network_dict['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
% (name, e))
return None
@@ -718,7 +727,7 @@ def create_neutron_subnet(neutron_client, name, cidr, net_id):
try:
subnet = neutron_client.create_subnet(body=json_body)
return subnet['subnets'][0]['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
"'%s', '%s')]: %s" % (name, cidr, net_id, e))
return None
@@ -729,7 +738,7 @@ def create_neutron_router(neutron_client, name):
try:
router = neutron_client.create_router(json_body)
return router['router']['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
% (name, e))
return None
@@ -745,7 +754,7 @@ def create_neutron_port(neutron_client, name, network_id, ip):
try:
port = neutron_client.create_port(body=json_body)
return port['port']['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
"'%s')]: %s" % (name, network_id, ip, e))
return None
@@ -756,7 +765,7 @@ def update_neutron_net(neutron_client, network_id, shared=False):
try:
neutron_client.update_network(network_id, body=json_body)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
"%s" % (network_id, str(shared), e))
return False
@@ -770,7 +779,7 @@ def update_neutron_port(neutron_client, port_id, device_owner):
port = neutron_client.update_port(port=port_id,
body=json_body)
return port['port']['id']
- except Exception, e:
+ except Exception as e:
logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
" %s" % (port_id, device_owner, e))
return None
@@ -781,7 +790,7 @@ def add_interface_router(neutron_client, router_id, subnet_id):
try:
neutron_client.add_interface_router(router=router_id, body=json_body)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_interface_router(neutron_client, '%s', "
"'%s')]: %s" % (router_id, subnet_id, e))
return False
@@ -793,7 +802,7 @@ def add_gateway_router(neutron_client, router_id):
try:
neutron_client.add_gateway_router(router_id, router_dict)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
% (router_id, e))
return False
@@ -803,7 +812,7 @@ def delete_neutron_net(neutron_client, network_id):
try:
neutron_client.delete_network(network_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
% (network_id, e))
return False
@@ -813,7 +822,7 @@ def delete_neutron_subnet(neutron_client, subnet_id):
try:
neutron_client.delete_subnet(subnet_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
% (subnet_id, e))
return False
@@ -823,7 +832,7 @@ def delete_neutron_router(neutron_client, router_id):
try:
neutron_client.delete_router(router=router_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
% (router_id, e))
return False
@@ -833,7 +842,7 @@ def delete_neutron_port(neutron_client, port_id):
try:
neutron_client.delete_port(port_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
% (port_id, e))
return False
@@ -845,7 +854,7 @@ def remove_interface_router(neutron_client, router_id, subnet_id):
neutron_client.remove_interface_router(router=router_id,
body=json_body)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [remove_interface_router(neutron_client, '%s', "
"'%s')]: %s" % (router_id, subnet_id, e))
return False
@@ -855,7 +864,7 @@ def remove_gateway_router(neutron_client, router_id):
try:
neutron_client.remove_gateway_router(router_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
% (router_id, e))
return False
@@ -985,7 +994,7 @@ def get_security_groups(neutron_client):
security_groups = neutron_client.list_security_groups()[
'security_groups']
return security_groups
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
return None
@@ -1006,7 +1015,7 @@ def create_security_group(neutron_client, sg_name, sg_description):
try:
secgroup = neutron_client.create_security_group(json_body)
return secgroup['security_group']
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_security_group(neutron_client, '%s', "
"'%s')]: %s" % (sg_name, sg_description, e))
return None
@@ -1061,7 +1070,7 @@ def get_security_group_rules(neutron_client, sg_id):
security_rules = [rule for rule in security_rules
if rule["security_group_id"] == sg_id]
return security_rules
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
" %s" % e)
return None
@@ -1080,7 +1089,7 @@ def check_security_group_rules(neutron_client, sg_id, direction, protocol,
return True
else:
return False
- except Exception, e:
+ except Exception as e:
logger.error("Error [check_security_group_rules("
" neutron_client, sg_id, direction,"
" protocol, port_min=None, port_max=None)]: "
@@ -1132,7 +1141,7 @@ def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
try:
nova_client.servers.add_security_group(instance_id, secgroup_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
"'%s')]: %s" % (instance_id, secgroup_id, e))
return False
@@ -1148,7 +1157,7 @@ def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
neutron_client.update_quota(tenant_id=tenant_id,
body=json_body)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
"'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
return False
@@ -1158,7 +1167,7 @@ def delete_security_group(neutron_client, secgroup_id):
try:
neutron_client.delete_security_group(secgroup_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
% (secgroup_id, e))
return False
@@ -1171,7 +1180,7 @@ def get_images(nova_client):
try:
images = nova_client.images.list()
return images
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_images]: %s" % e)
return None
@@ -1207,7 +1216,7 @@ def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
with open(file_path) as image_data:
glance_client.images.upload(image_id, image_data)
return image_id
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
"'%s')]: %s" % (image_name, file_path, public, e))
return None
@@ -1237,7 +1246,7 @@ def delete_glance_image(nova_client, image_id):
try:
nova_client.images.delete(image_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
% (image_id, e))
return False
@@ -1250,7 +1259,7 @@ def get_volumes(cinder_client):
try:
volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
return volumes
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_volumes(cinder_client)]: %s" % e)
return None
@@ -1263,7 +1272,7 @@ def list_volume_types(cinder_client, public=True, private=True):
if not private:
volume_types = [vt for vt in volume_types if vt.is_public]
return volume_types
- except Exception, e:
+ except Exception as e:
logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
return None
@@ -1272,7 +1281,7 @@ def create_volume_type(cinder_client, name):
try:
volume_type = cinder_client.volume_types.create(name)
return volume_type
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
% (name, e))
return None
@@ -1287,7 +1296,7 @@ def update_cinder_quota(cinder_client, tenant_id, vols_quota,
try:
cinder_client.quotas.update(tenant_id, **quotas_values)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
"'%s' '%s')]: %s" % (tenant_id, vols_quota,
snapshots_quota, gigabytes_quota, e))
@@ -1305,7 +1314,7 @@ def delete_volume(cinder_client, volume_id, forced=False):
else:
cinder_client.volumes.delete(volume_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
% (volume_id, str(forced), e))
return False
@@ -1315,7 +1324,7 @@ def delete_volume_type(cinder_client, volume_type):
try:
cinder_client.volume_types.delete(volume_type)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
% (volume_type, e))
return False
@@ -1331,7 +1340,7 @@ def get_tenants(keystone_client):
else:
tenants = keystone_client.tenants.list()
return tenants
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_tenants(keystone_client)]: %s" % e)
return None
@@ -1340,7 +1349,7 @@ def get_users(keystone_client):
try:
users = keystone_client.users.list()
return users
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_users(keystone_client)]: %s" % e)
return None
@@ -1388,12 +1397,21 @@ def create_tenant(keystone_client, tenant_name, tenant_description):
tenant_description,
enabled=True)
return tenant.id
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
% (tenant_name, tenant_description, e))
return None
+def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
+ tenant_id = get_tenant_id(keystone_client, tenant_name)
+ if not tenant_id:
+ tenant_id = create_tenant(keystone_client, tenant_name,
+ tenant_description)
+
+ return tenant_id
+
+
def create_user(keystone_client, user_name, user_password,
user_email, tenant_id):
try:
@@ -1410,13 +1428,22 @@ def create_user(keystone_client, user_name, user_password,
tenant_id,
enabled=True)
return user.id
- except Exception, e:
+ except Exception as e:
logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
"'%s')]: %s" % (user_name, user_password,
user_email, tenant_id, e))
return None
+def get_or_create_user(keystone_client, user_name, user_password,
+ tenant_id, user_email=None):
+ user_id = get_user_id(keystone_client, user_name)
+ if not user_id:
+ user_id = create_user(keystone_client, user_name, user_password,
+ user_email, tenant_id)
+ return user_id
+
+
def add_role_user(keystone_client, user_id, role_id, tenant_id):
try:
if is_keystone_v3():
@@ -1426,7 +1453,7 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id):
else:
keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
"'%s')]: %s " % (user_id, role_id, tenant_id, e))
return False
@@ -1439,7 +1466,7 @@ def delete_tenant(keystone_client, tenant_id):
else:
keystone_client.tenants.delete(tenant_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
% (tenant_id, e))
return False
@@ -1449,7 +1476,7 @@ def delete_user(keystone_client, user_id):
try:
keystone_client.users.delete(user_id)
return True
- except Exception, e:
+ except Exception as e:
logger.error("Error [delete_user(keystone_client, '%s')]: %s"
% (user_id, e))
return False
@@ -1462,6 +1489,6 @@ def get_resource(heat_client, stack_id, resource):
try:
resources = heat_client.resources.get(stack_id, resource)
return resources
- except Exception, e:
+ except Exception as e:
logger.error("Error [get_resource]: %s" % e)
return None