aboutsummaryrefslogtreecommitdiffstats
path: root/functest
diff options
context:
space:
mode:
Diffstat (limited to 'functest')
-rw-r--r--functest/api/base.py5
-rw-r--r--functest/api/resources/v1/envs.py41
-rw-r--r--functest/api/resources/v1/tasks.py43
-rw-r--r--functest/api/resources/v1/testcases.py19
-rw-r--r--functest/api/urls.py11
-rw-r--r--functest/ci/config_aarch64_patch.yaml8
-rw-r--r--functest/ci/config_functest.yaml56
-rw-r--r--functest/ci/download_images.sh78
-rw-r--r--functest/ci/prepare_env.py2
-rw-r--r--functest/ci/run_tests.py10
-rw-r--r--functest/ci/testcases.yaml63
-rw-r--r--functest/energy/energy.py3
-rw-r--r--functest/opnfv_tests/mano/orchestra.py27
-rw-r--r--functest/opnfv_tests/openstack/rally/blacklist.txt43
-rw-r--r--functest/opnfv_tests/openstack/rally/rally.py4
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/full/opnfv-ceilometer.yaml458
-rw-r--r--functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-ceilometer.yaml247
-rw-r--r--functest/opnfv_tests/openstack/rally/task.yaml4
-rw-r--r--functest/opnfv_tests/openstack/refstack_client/refstack_client.py70
-rw-r--r--functest/opnfv_tests/openstack/refstack_client/tempest_conf.py20
-rw-r--r--functest/opnfv_tests/openstack/snaps/snaps_test_runner.py10
-rw-r--r--functest/opnfv_tests/openstack/tempest/conf_utils.py135
-rw-r--r--functest/opnfv_tests/openstack/tempest/tempest.py237
-rw-r--r--functest/opnfv_tests/openstack/vping/vping_base.py38
-rw-r--r--functest/opnfv_tests/sdn/onos/onos.py232
-rw-r--r--functest/opnfv_tests/sdn/onos/sfc/README.md21
-rw-r--r--functest/opnfv_tests/sdn/onos/sfc/sfc.py174
-rw-r--r--functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py887
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/Readme.txt5
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/client.py92
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/connection.py200
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/environment.py286
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py95
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/dependencies/onos29
-rw-r--r--functest/opnfv_tests/sdn/onos/teston/log/gitignore0
-rw-r--r--functest/opnfv_tests/vnf/ims/clearwater_ims_base.py21
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.py35
-rw-r--r--functest/opnfv_tests/vnf/ims/cloudify_ims.yaml4
-rw-r--r--functest/opnfv_tests/vnf/ims/orchestra.yaml8
-rw-r--r--functest/opnfv_tests/vnf/ims/orchestra_clearwaterims.py18
-rw-r--r--functest/opnfv_tests/vnf/ims/orchestra_openims.py17
-rw-r--r--functest/opnfv_tests/vnf/router/cloudify_vrouter.py542
-rw-r--r--functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml31
-rw-r--r--functest/opnfv_tests/vnf/router/test_controller/__init__.py (renamed from functest/opnfv_tests/sdn/onos/__init__.py)0
-rw-r--r--functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py137
-rw-r--r--functest/opnfv_tests/vnf/router/test_scenario.yaml27
-rw-r--r--functest/opnfv_tests/vnf/router/utilvnf.py345
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/__init__.py (renamed from functest/opnfv_tests/sdn/onos/teston/__init__.py)0
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/checker.py59
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py32
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py131
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py148
-rw-r--r--functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py136
-rw-r--r--functest/opnfv_tests/vnf/router/vrouter_base.py119
-rw-r--r--functest/opnfv_tests/vnf/router/vyos_vrouter.py34
-rw-r--r--functest/tests/unit/energy/test_functest_energy.py36
-rw-r--r--functest/tests/unit/openstack/refstack_client/test_refstack_client.py56
-rw-r--r--functest/tests/unit/openstack/tempest/test_conf_utils.py170
-rw-r--r--functest/tests/unit/openstack/tempest/test_tempest.py18
-rw-r--r--functest/tests/unit/openstack/vping/test_vping.py6
-rw-r--r--functest/tests/unit/utils/test_functest_utils.py65
-rw-r--r--functest/tests/unit/utils/test_openstack_tacker.py524
-rw-r--r--functest/tests/unit/vnf/router/__init__.py (renamed from functest/opnfv_tests/sdn/onos/teston/adapters/__init__.py)0
-rw-r--r--functest/tests/unit/vnf/router/test_cloudify_vrouter.py140
-rw-r--r--functest/tests/unit/vnf/router/test_vrouter_base.py28
-rw-r--r--functest/utils/functest_utils.py52
-rw-r--r--functest/utils/openstack_tacker.py317
-rw-r--r--functest/utils/openstack_utils.py59
68 files changed, 3490 insertions, 3478 deletions
diff --git a/functest/api/base.py b/functest/api/base.py
index ffc56786..75f059b7 100644
--- a/functest/api/base.py
+++ b/functest/api/base.py
@@ -45,6 +45,11 @@ class ApiResource(Resource):
return action, args
+ def _get_args(self): # pylint: disable=no-self-use
+ """ Convert the unicode to string for request.args """
+ args = api_utils.change_to_str_in_dict(request.args)
+ return args
+
def _dispatch_post(self):
""" Dispatch request """
action, args = self._post_args()
diff --git a/functest/api/resources/v1/envs.py b/functest/api/resources/v1/envs.py
index 9c455198..fb76fa63 100644
--- a/functest/api/resources/v1/envs.py
+++ b/functest/api/resources/v1/envs.py
@@ -10,11 +10,12 @@
Resources to handle environment related requests
"""
+import IPy
from flask import jsonify
from functest.api.base import ApiResource
-from functest.cli.commands.cli_env import Env
from functest.api.common import api_utils
+from functest.cli.commands.cli_env import Env
import functest.utils.functest_utils as ft_utils
@@ -38,3 +39,41 @@ class V1Envs(ApiResource):
return api_utils.result_handler(status=1, data=str(err))
return api_utils.result_handler(
status=0, data="Prepare env successfully")
+
+ def update_hosts(self, hosts_info): # pylint: disable=no-self-use
+ """ Update hosts info """
+
+ if not isinstance(hosts_info, dict):
+ return api_utils.result_handler(
+ status=1, data='Error, args should be a dict')
+
+ for key, value in hosts_info.items():
+ if key:
+ try:
+ IPy.IP(value)
+ except Exception: # pylint: disable=broad-except
+ return api_utils.result_handler(
+ status=1, data='The IP %s is invalid' % value)
+ else:
+ return api_utils.result_handler(
+ status=1, data='Domain name is absent')
+
+ try:
+ functest_flag = "# SUT hosts info for Functest"
+ hosts_list = ('\n{} {} {}'.format(ip, host_name, functest_flag)
+ for host_name, ip in hosts_info.items())
+
+ with open("/etc/hosts", 'r') as file_hosts:
+ origin_lines = [line for line in file_hosts
+ if functest_flag not in line]
+
+ with open("/etc/hosts", 'w') as file_hosts:
+ file_hosts.writelines(origin_lines)
+ file_hosts.write(functest_flag)
+ file_hosts.writelines(hosts_list)
+ except Exception: # pylint: disable=broad-except
+ return api_utils.result_handler(
+ status=1, data='Error when updating hosts info')
+ else:
+ return api_utils.result_handler(
+ status=0, data='Update hosts info successfully')
diff --git a/functest/api/resources/v1/tasks.py b/functest/api/resources/v1/tasks.py
index 7086e707..e05db51b 100644
--- a/functest/api/resources/v1/tasks.py
+++ b/functest/api/resources/v1/tasks.py
@@ -11,9 +11,10 @@
Resources to retrieve the task results
"""
-
+import errno
import json
import logging
+import os
import uuid
from flask import jsonify
@@ -21,13 +22,14 @@ from flask import jsonify
from functest.api.base import ApiResource
from functest.api.common import api_utils
from functest.api.database.v1.handlers import TasksHandler
+from functest.utils.constants import CONST
LOGGER = logging.getLogger(__name__)
-class V1Tasks(ApiResource):
- """ V1Tasks Resource class"""
+class V1Task(ApiResource):
+ """ V1Task Resource class"""
def get(self, task_id): # pylint: disable=no-self-use
""" GET the result of the task id """
@@ -56,3 +58,38 @@ class V1Tasks(ApiResource):
result = {'status': status, 'result': json.loads(task.result)}
return jsonify(result)
+
+
+class V1TaskLog(ApiResource):
+ """ V1TaskLog Resource class"""
+
+ def get(self, task_id): # pylint: disable=no-self-use
+ """ GET the log of the task id """
+ try:
+ uuid.UUID(task_id)
+ except ValueError:
+ return api_utils.result_handler(status=1, data='Invalid task id')
+
+ task_handler = TasksHandler()
+ try:
+ task = task_handler.get_task_by_taskid(task_id)
+ except ValueError:
+ return api_utils.result_handler(status=1, data='No such task id')
+
+ task_log_dir = CONST.__getattribute__('dir_results')
+
+ try:
+ with open(os.path.join(task_log_dir,
+ '{}.log'.format(task_id)), 'r') as log_file:
+ data = log_file.readlines()
+ except OSError as err:
+ if err.errno == errno.ENOENT:
+ return api_utils.result_handler(
+ status=1, data='Log file does not exist')
+
+ return api_utils.result_handler(
+ status=1, data='Error with log file')
+
+ return_data = {'data': data}
+
+ return api_utils.result_handler(status=task.status, data=return_data)
diff --git a/functest/api/resources/v1/testcases.py b/functest/api/resources/v1/testcases.py
index f146c24c..d708cf37 100644
--- a/functest/api/resources/v1/testcases.py
+++ b/functest/api/resources/v1/testcases.py
@@ -11,10 +11,12 @@
Resources to handle testcase related requests
"""
-import os
import logging
+import os
+import pkg_resources
import uuid
+import ConfigParser
from flask import abort, jsonify
from functest.api.base import ApiResource
@@ -84,6 +86,7 @@ class V1Testcase(ApiResource):
""" The built_in function to run a test case """
case_name = args.get('testcase')
+ self._update_logging_ini(args.get('task_id'))
if not os.path.isfile(CONST.__getattribute__('env_active')):
raise Exception("Functest environment is not ready.")
@@ -113,3 +116,17 @@ class V1Testcase(ApiResource):
}
return {'result': result}
+
+ def _update_logging_ini(self, task_id): # pylint: disable=no-self-use
+ """ Update the log file for each task"""
+ config = ConfigParser.RawConfigParser()
+ config.read(
+ pkg_resources.resource_filename('functest', 'ci/logging.ini'))
+ log_path = os.path.join(CONST.__getattribute__('dir_results'),
+ '{}.log'.format(task_id))
+ config.set('handler_file', 'args', '("{}",)'.format(log_path))
+
+ with open(
+ pkg_resources.resource_filename(
+ 'functest', 'ci/logging.ini'), 'wb') as configfile:
+ config.write(configfile)
diff --git a/functest/api/urls.py b/functest/api/urls.py
index f7bcae38..0cc22f80 100644
--- a/functest/api/urls.py
+++ b/functest/api/urls.py
@@ -25,8 +25,9 @@ URLPATTERNS = [
# GET /api/v1/functest/envs => GET environment
Url('/api/v1/functest/envs', 'v1_envs'),
- # POST /api/v1/functest/envs/action , {"action":"prepare"}
- # => Prepare environment
+ # POST /api/v1/functest/envs/action
+ # {"action":"prepare"} => Prepare environment
+ # {"action":"update_hosts", "args": {}} => Update hosts info
Url('/api/v1/functest/envs/action', 'v1_envs'),
# GET /api/v1/functest/openstack/credentials => GET credentials
@@ -62,5 +63,9 @@ URLPATTERNS = [
# GET /api/v1/functest/tasks/<task_id>
# => GET the result of the task id
- Url('/api/v1/functest/tasks/<task_id>', 'v1_tasks')
+ Url('/api/v1/functest/tasks/<task_id>', 'v1_task'),
+
+ # GET /api/v1/functest/tasks/<task_id>/log
+ # => GET the log of the task
+ Url('/api/v1/functest/tasks/<task_id>/log', 'v1_task_log')
]
diff --git a/functest/ci/config_aarch64_patch.yaml b/functest/ci/config_aarch64_patch.yaml
index de82dbc7..6b3699b4 100644
--- a/functest/ci/config_aarch64_patch.yaml
+++ b/functest/ci/config_aarch64_patch.yaml
@@ -18,6 +18,14 @@ os:
hw_firmware_type: 'uefi'
short_id: 'ubuntu16.04'
hw_video_model: 'vga'
+ ubuntu:
+ disk_file: /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-arm64-uefi1.img
+ extra_properties:
+ hw_firmware_type: 'uefi'
+ hw_video_model: 'vga'
+ centos:
+ disk_file: /home/opnfv/functest/images/CentOS-7-aarch64-GenericCloud.qcow2
+
vping:
image_name: TestVM
diff --git a/functest/ci/config_functest.yaml b/functest/ci/config_functest.yaml
index b3fc397f..5ff5c824 100644
--- a/functest/ci/config_functest.yaml
+++ b/functest/ci/config_functest.yaml
@@ -6,18 +6,17 @@ general:
repo_tempest: /src/tempest
dir_repo_releng: /home/opnfv/repos/releng
repo_vims_test: /src/vims-test
- repo_onos: /home/opnfv/repos/onos
repo_barometer: /home/opnfv/repos/barometer
repo_doctor: /home/opnfv/repos/doctor
repo_odl_test: /src/odl_test
repo_fds: /src/fds
repo_securityscan: /home/opnfv/repos/securityscanning
- repo_vrouter: /home/opnfv/repos/vnfs/vrouter
functest: /home/opnfv/functest
results: /home/opnfv/functest/results
functest_conf: /home/opnfv/functest/conf
functest_data: /home/opnfv/functest/data
ims_data: /home/opnfv/functest/data/ims/
+ router_data: /home/opnfv/functest/data/router/
functest_images: /home/opnfv/functest/images
rally_inst: /root/.rally
@@ -61,6 +60,25 @@ snaps:
disk_file: /home/opnfv/functest/images/ubuntu-14.04-server-cloudimg-amd64-disk1.img
centos:
disk_file: /home/opnfv/functest/images/CentOS-7-x86_64-GenericCloud.qcow2
+ # All of these values are optional and will override the values retrieved
+ # by the RC file
+# os_creds_override:
+# username: {user}
+# password: {password}
+# auth_url: {auth_url}
+# project_name: {project_name}
+# identity_api_version: {2|3}
+# network_api_version: {2}
+# compute_api_version: {2}
+# image_api_version: {1|2}
+# user_domain_id: {user_domain_id}
+# project_domain_id: {projects_domain_id}
+# interface: {interface}
+# cacert: {True|False}
+# proxy_settings:
+# host: {proxy_host}
+# port: {proxy_port}
+# ssh_proxy_cmd: {OpenSSH -o ProxyCommand value}
vping:
ping_timeout: 200
@@ -69,6 +87,9 @@ vping:
vm_name_2: opnfv-vping-2
image_name: functest-vping
private_net_name: vping-net
+ # network_type: vlan
+ # physical_network: physnet2
+ # segmentation_id: 2366
private_subnet_name: vping-subnet
private_subnet_cidr: 192.168.130.0/24
router_name: vping-router
@@ -83,11 +104,6 @@ vping:
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
@@ -96,6 +112,11 @@ odl_sfc:
tempest:
deployment_name: opnfv-tempest
+ identity:
+ tenant_name: tempest
+ tenant_description: Tenant for Tempest test suite
+ user_name: tempest
+ user_password: Tempest123!
validation:
ssh_timeout: 130
object_storage:
@@ -132,24 +153,11 @@ vnf:
tenant_name: orchestra_clearwaterims
tenant_description: Clearwater IMS deployed with Open Baton
config: orchestra.yaml
+ vyos_vrouter:
+ tenant_name: vrouter
+ tenant_description: vRouter
+ config: cloudify_vrouter.yaml
-ONOS:
- general:
- onosbench_username: 'root'
- onosbench_password: 'root'
- onoscli_username: 'root'
- onoscli_password: 'root'
- runtimeout: 300
- environment:
- OCT: '10.20.0.1'
- OC1: '10.20.0.7'
- OC2: '10.20.0.7'
- OC3: '10.20.0.7'
- OCN: '10.20.0.4'
- OCN2: '10.20.0.5'
- installer_master: '10.20.0.2'
- installer_master_username: 'root'
- installer_master_password: 'r00tme'
promise:
tenant_name: promise
tenant_description: promise Functionality Testing
diff --git a/functest/ci/download_images.sh b/functest/ci/download_images.sh
index dd3e3789..367ad8d9 100644
--- a/functest/ci/download_images.sh
+++ b/functest/ci/download_images.sh
@@ -1,62 +1,24 @@
#!/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> <scenario_name> [arch]${NC}"
- exit 0
-}
-
-script=`basename "$0"`
-IMAGES_FOLDER_DIR=$1
-SCENARIO=$2
-ARCH=$3
-
-if [[ -z $IMAGES_FOLDER_DIR ]]; then usage; fi;
-
set -ex
-mkdir -p ${IMAGES_FOLDER_DIR}
-
-
-####################
-# MANDATORY IMAGES #
-####################
-# These images should be present in Functest for the tests to work
-
-# Functest:
-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}
-
-# SNAPS:
-wget -nc http://uec-images.ubuntu.com/releases/trusty/14.04/ubuntu-14.04-server-cloudimg-amd64-disk1.img -P ${IMAGES_FOLDER_DIR}
-wget -nc http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2 -P ${IMAGES_FOLDER_DIR}
-
-
-###################
-# OPTIONAL IMAGES #
-###################
-# Optional images can be commented if they are not going to be used by the tests
-
-# SDNVPN (odl-bgpvpn scenarios):
-if [[ ${SCENARIO} == *"bgpvpn"* ]]; then
- wget -nc http://artifacts.opnfv.org/sdnvpn/ubuntu-16.04-server-cloudimg-amd64-disk1.img -P ${IMAGES_FOLDER_DIR}
-fi
-
-# ONOS (onos-sfc scenarios):
-if [[ ${SCENARIO} == *"onos-sfc"* ]]; then
- wget -nc http://artifacts.opnfv.org/onosfw/images/firewall_block_image.img -P ${IMAGES_FOLDER_DIR}
-fi
-
-if [[ ${ARCH} == "arm" ]] || [[ ${ARCH} == "aarch64" ]]; then
- # ARM (aarch64 cirros images):
- 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}
-fi
-set +ex \ No newline at end of file
+wget_opts="-N --tries=1 --connect-timeout=30"
+
+cat << EOF | wget ${wget_opts} -i - -P ${1:-/home/opnfv/functest/images}
+http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img
+https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-amd64-disk1.img
+https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2
+https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-disk1.img
+http://repository.cloudifysource.org/cloudify/4.0.1/sp-release/cloudify-manager-premium-4.0.1.qcow2
+http://marketplace.openbaton.org:8082/api/v1/images/52e2ccc0-1dce-4663-894d-28aab49323aa/img
+http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
+http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-lxc.tar.gz
+http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-disk.img
+http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-initramfs
+http://download.cirros-cloud.net/daily/20161201/cirros-d161201-aarch64-kernel
+https://cloud-images.ubuntu.com/releases/14.04/release/ubuntu-14.04-server-cloudimg-arm64-uefi1.img
+http://cloud.centos.org/altarch/7/images/aarch64/CentOS-7-aarch64-GenericCloud.qcow2.xz
+https://sourceforge.net/projects/ool-opnfv/files/vyos-1.1.7.img
+EOF
+
+xz --decompress --force --keep ${1:-/home/opnfv/functest/images}/CentOS-7-aarch64-GenericCloud.qcow2.xz
diff --git a/functest/ci/prepare_env.py b/functest/ci/prepare_env.py
index c40e3266..a354dbe8 100644
--- a/functest/ci/prepare_env.py
+++ b/functest/ci/prepare_env.py
@@ -33,7 +33,7 @@ actions = ['start', 'check']
logger = logging.getLogger('functest.ci.prepare_env')
handler = None
# set the architecture to default
-pod_arch = None
+pod_arch = os.getenv("POD_ARCH", None)
arch_filter = ['aarch64']
CONFIG_FUNCTEST_PATH = pkg_resources.resource_filename(
diff --git a/functest/ci/run_tests.py b/functest/ci/run_tests.py
index 63a50dea..feafa89e 100644
--- a/functest/ci/run_tests.py
+++ b/functest/ci/run_tests.py
@@ -188,12 +188,12 @@ class Runner(object):
self.run_tier(tier)
def main(self, **kwargs):
- if kwargs['noclean']:
- self.clean_flag = False
- if kwargs['report']:
- self.report_flag = True
+ if 'noclean' in kwargs:
+ self.clean_flag = not kwargs['noclean']
+ if 'report' in kwargs:
+ self.report_flag = kwargs['report']
try:
- if kwargs['test']:
+ if 'test' in kwargs:
self.source_rc_file()
logger.debug("Test args: %s", kwargs['test'])
if self._tiers.get_tier(kwargs['test']):
diff --git a/functest/ci/testcases.yaml b/functest/ci/testcases.yaml
index b0472b27..5364035f 100644
--- a/functest/ci/testcases.yaml
+++ b/functest/ci/testcases.yaml
@@ -207,22 +207,6 @@ tiers:
- /src/fds/testing/robot
-
- case_name: onos
- project_name: functest
- criteria: 100
- blocking: true
- description: >-
- Test Suite for the ONOS SDN Controller. It integrates
- some test suites from upstream using TestON as the test
- framework.
- dependencies:
- installer: ''
- scenario: 'onos'
- run:
- module: 'functest.opnfv_tests.sdn.onos.onos'
- class: 'Onos'
-
- -
case_name: snaps_smoke
project_name: functest
criteria: 100
@@ -319,15 +303,15 @@ tiers:
-
case_name: functest-odl-sfc
- enabled: false
+ enabled: true
project_name: sfc
criteria: 100
blocking: false
description: >-
- Test suite for odl-sfc to test two chains and two SFs
+ Test suite for odl-sfc to test two chains with one SF and one chain with two SFs
dependencies:
- installer: '(apex)|(fuel)'
- scenario: 'odl_l2-sfc'
+ installer: ''
+ scenario: 'odl.*sfc'
run:
module: 'functest.core.feature'
class: 'BashFeature'
@@ -335,21 +319,6 @@ tiers:
cmd: 'run_sfc_tests.py'
-
- case_name: onos_sfc
- enabled: false
- project_name: functest
- criteria: 100
- blocking: true
- description: >-
- Test Suite for onos-sfc to test sfc function.
- dependencies:
- installer: ''
- scenario: 'onos-sfc'
- run:
- module: 'functest.opnfv_tests.sdn.onos.onos'
- class: 'OnosSfc'
-
- -
case_name: parser-basics
enabled: false
project_name: parser
@@ -385,18 +354,17 @@ tiers:
-
case_name: barometercollectd
- enabled: false
+ enabled: true
project_name: barometer
criteria: 100
blocking: false
description: >-
- Test suite for the Barometer project. Separate tests verify the
- proper configuration and functionality of the following
- collectd plugins Ceilometer, Hugepages, Memory RAS (mcelog),
- and OVS Events
+ Test suite for the Barometer project. Separate tests verify
+ the proper configuration and basic functionality of all the
+ collectd plugins as described in the Project Release Plan
dependencies:
- installer: 'fuel'
- scenario: 'kvm_ovs_dpdk_bar'
+ installer: 'apex'
+ scenario: 'bar'
run:
module: 'baro_tests.barometer'
class: 'BarometerCollectd'
@@ -467,7 +435,7 @@ tiers:
-
case_name: cloudify_ims
project_name: functest
- criteria: 100
+ criteria: 80
blocking: false
description: >-
This test case deploys an OpenSource vIMS solution from Clearwater
@@ -508,15 +476,14 @@ tiers:
-
case_name: vyos_vrouter
- enabled: false
project_name: functest
criteria: 100
blocking: false
description: >-
This test case is vRouter testing.
dependencies:
- installer: 'fuel'
- scenario: 'nosdn-nofeature'
+ installer: ''
+ scenario: 'os-nosdn-nofeature-ha'
run:
- module: 'functest.opnfv_tests.vnf.router.vyos_vrouter'
- class: 'VrouterVnf'
+ module: 'functest.opnfv_tests.vnf.router.cloudify_vrouter'
+ class: 'CloudifyVrouter'
diff --git a/functest/energy/energy.py b/functest/energy/energy.py
index c410e84f..508f18e7 100644
--- a/functest/energy/energy.py
+++ b/functest/energy/energy.py
@@ -18,6 +18,7 @@ from functools import wraps
import requests
import urllib3
+from functest.utils.constants import CONST
import functest.utils.functest_utils as ft_utils
@@ -91,7 +92,7 @@ class EnergyRecorder(object):
# 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()
+ environment = CONST.__getattribute__('NODE_NAME')
# API URL
energy_recorder_uri = ft_utils.get_functest_config(
diff --git a/functest/opnfv_tests/mano/orchestra.py b/functest/opnfv_tests/mano/orchestra.py
deleted file mode 100644
index 955f82ce..00000000
--- a/functest/opnfv_tests/mano/orchestra.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env 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 Orchestra(base.Feature):
- 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/rally/blacklist.txt b/functest/opnfv_tests/openstack/rally/blacklist.txt
index 95bea2b7..cdb5be66 100644
--- a/functest/opnfv_tests/openstack/rally/blacklist.txt
+++ b/functest/opnfv_tests/openstack/rally/blacklist.txt
@@ -6,6 +6,49 @@ scenario:
- joid
tests:
- NovaServers.boot_server_from_volume_and_delete
+ -
+ scenarios:
+ - '^os-' # all scenarios
+ installers:
+ - '.+' # all installers
+ tests:
+ # Following tests currently fail due to required Gnocchi API:
+ # HTTP 410: "This telemetry installation is configured to use
+ # Gnocchi. Please use the Gnocchi API available on the
+ # metric endpoint to retrieve data."
+ # Issue: https://bugs.launchpad.net/rally/+bug/1704322
+ - CeilometerMeters.list_matched_meters
+ - CeilometerMeters.list_meters
+ - CeilometerQueries.create_and_query_samples
+ - CeilometerResource.get_tenant_resources
+ - CeilometerResource.list_matched_resources
+ - CeilometerResource.list_resources
+ - CeilometerSamples.list_matched_samples
+ - CeilometerSamples.list_samples
+ - CeilometerStats.create_meter_and_get_stats
+ - CeilometerStats.get_stats
+ -
+ scenarios:
+ - '^os-' # all scenarios
+ installers:
+ - '.+' # all installers
+ tests:
+ # Following test currently fails due to but in
+ # python-ceilometerclient during fetching of event_types
+ # Bug: https://bugs.launchpad.net/ubuntu/+bug/1704138
+ # Fix: https://review.openstack.org/#/c/483402/
+ - CeilometerEvents.create_user_and_list_event_types
+ -
+ scenarios:
+ - '^os-' # all scenarios
+ installers:
+ - '.+' # all installers
+ tests:
+ # Starting from ocata, following tests require the presence of
+ # panko in the deployment. This is not currently fulfilled
+ # Ref: https://docs.openstack.org/releasenotes/ceilometer/ocata.html
+ - 'CeilometerEvents..*'
+ - 'CeilometerTraits..*'
functionality:
-
diff --git a/functest/opnfv_tests/openstack/rally/rally.py b/functest/opnfv_tests/openstack/rally/rally.py
index 6b7c49ca..fdef8bed 100644
--- a/functest/opnfv_tests/openstack/rally/rally.py
+++ b/functest/opnfv_tests/openstack/rally/rally.py
@@ -34,8 +34,8 @@ LOGGER = logging.getLogger(__name__)
class RallyBase(testcase.OSGCTestCase):
"""Base class form Rally testcases implementation."""
- TESTS = ['authenticate', 'glance', 'cinder', 'heat', 'keystone',
- 'neutron', 'nova', 'quotas', 'vm', 'all']
+ TESTS = ['authenticate', 'glance', 'ceilometer', 'cinder', 'heat',
+ 'keystone', 'neutron', 'nova', 'quotas', 'vm', 'all']
GLANCE_IMAGE_NAME = CONST.__getattribute__('openstack_image_name')
GLANCE_IMAGE_FILENAME = CONST.__getattribute__('openstack_image_file_name')
GLANCE_IMAGE_PATH = os.path.join(
diff --git a/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-ceilometer.yaml b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-ceilometer.yaml
new file mode 100644
index 00000000..7efb5a83
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/scenario/full/opnfv-ceilometer.yaml
@@ -0,0 +1,458 @@
+ CeilometerMeters.list_meters:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ limit: 50
+ metadata_query:
+ status: "terminated"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerResource.list_resources:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ limit: 50
+ metadata_query:
+ status: "terminated"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_alarm_and_get_history:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ state: "ok"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_delete_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_get_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_list_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_alarm_history:
+ -
+ args:
+ orderby: !!null
+ limit: !!null
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_alarms:
+ -
+ args:
+ filter: {"and": [{"!=": {"state": "dummy_state"}},{"=": {"type": "threshold"}}]}
+ orderby: !!null
+ limit: 10
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_samples:
+ -
+ args:
+ filter: {"=": {"counter_unit": "instance"}}
+ orderby: !!null
+ limit: 10
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_unit: "instance"
+ counter_volume: 1.0
+ resource_id: "resource_id"
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_update_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerStats.create_meter_and_get_stats:
+ -
+ args:
+ user_id: "user-id"
+ resource_id: "resource-id"
+ counter_volume: 1.0
+ counter_unit: ""
+ counter_type: "cumulative"
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_get_event:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_list_events:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_list_event_types:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerTraits.create_user_and_list_trait_descriptions:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerTraits.create_user_and_list_traits:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerStats.get_stats:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ meter_name: "benchmark_meter"
+ filter_by_user_id: true
+ filter_by_project_id: true
+ filter_by_resource_id: true
+ metadata_query:
+ status: "terminated"
+ period: 300
+ groupby: "resource_id"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerResource.get_tenant_resources:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_volume: 1.0
+ counter_unit: "instance"
+ {% endcall %}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.list_alarms:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerSamples.list_matched_samples:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_unit: "instance"
+ counter_volume: 1.0
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 60
+ metadata_list:
+ - status: "active"
+ name: "fake_resource"
+ deleted: "False"
+ created_at: "2015-09-04T12:34:19.000000"
+ - status: "not_active"
+ name: "fake_resource_1"
+ deleted: "False"
+ created_at: "2015-09-10T06:55:12.000000"
+ {% endcall %}
+ args:
+ limit: 50
+ filter_by_user_id: true
+ filter_by_project_id: true
+ filter_by_resource_id: true
+ metadata_query:
+ status: "not_active"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerMeters.list_matched_meters:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ limit: 50
+ filter_by_user_id: true
+ filter_by_project_id: true
+ filter_by_resource_id: true
+ metadata_query:
+ status: "terminated"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerResource.list_matched_resources:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ limit: 50
+ filter_by_user_id: true
+ filter_by_project_id: true
+ metadata_query:
+ status: "terminated"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerSamples.list_samples:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_unit: "instance"
+ counter_volume: 1.0
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 60
+ metadata_list:
+ - status: "active"
+ name: "fake_resource"
+ deleted: "False"
+ created_at: "2015-09-04T12:34:19.000000"
+ - status: "not_active"
+ name: "fake_resource_1"
+ deleted: "False"
+ created_at: "2015-09-10T06:55:12.000000"
+ batch_size: 5
+ {% endcall %}
+ args:
+ limit: 50
+ metadata_query:
+ status: "not_active"
+ sla:
+ {{ no_failures_sla() }}
+
diff --git a/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-ceilometer.yaml b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-ceilometer.yaml
new file mode 100644
index 00000000..bb070cd3
--- /dev/null
+++ b/functest/opnfv_tests/openstack/rally/scenario/sanity/opnfv-ceilometer.yaml
@@ -0,0 +1,247 @@
+ CeilometerAlarms.create_alarm_and_get_history:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ state: "ok"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_delete_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_get_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_list_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_alarm_history:
+ -
+ args:
+ orderby: !!null
+ limit: !!null
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_alarms:
+ -
+ args:
+ filter: {"and": [{"!=": {"state": "dummy_state"}},{"=": {"type": "threshold"}}]}
+ orderby: !!null
+ limit: 10
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerQueries.create_and_query_samples:
+ -
+ args:
+ filter: {"=": {"counter_unit": "instance"}}
+ orderby: !!null
+ limit: 10
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_unit: "instance"
+ counter_volume: 1.0
+ resource_id: "resource_id"
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.create_and_update_alarm:
+ -
+ args:
+ meter_name: "ram_util"
+ threshold: 10.0
+ type: "threshold"
+ statistic: "avg"
+ alarm_actions: ["http://localhost:8776/alarm"]
+ ok_actions: ["http://localhost:8776/ok"]
+ insufficient_data_actions: ["http://localhost:8776/notok"]
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_get_event:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_list_events:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerEvents.create_user_and_list_event_types:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerTraits.create_user_and_list_trait_descriptions:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerTraits.create_user_and_list_traits:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerStats.get_stats:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "benchmark_meter"
+ counter_type: "gauge"
+ counter_unit: "%"
+ counter_volume: 100
+ resources_per_tenant: 100
+ samples_per_resource: 100
+ timestamp_interval: 10
+ metadata_list:
+ -
+ status: "active"
+ name: "rally benchmark on"
+ deleted: "false"
+ -
+ status: "terminated"
+ name: "rally benchmark off"
+ deleted: "true"
+ {% endcall %}
+ args:
+ meter_name: "benchmark_meter"
+ filter_by_user_id: true
+ filter_by_project_id: true
+ filter_by_resource_id: true
+ metadata_query:
+ status: "terminated"
+ period: 300
+ groupby: "resource_id"
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerResource.get_tenant_resources:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {% call user_context(tenants_amount, users_amount, use_existing_users) %}
+ ceilometer:
+ counter_name: "cpu_util"
+ counter_type: "gauge"
+ counter_volume: 1.0
+ counter_unit: "instance"
+ {% endcall %}
+ sla:
+ {{ no_failures_sla() }}
+
+ CeilometerAlarms.list_alarms:
+ -
+ runner:
+ {{ constant_runner(concurrency=concurrency, times=iterations, is_smoke=smoke) }}
+ context:
+ {{ user_context(tenants_amount, users_amount, use_existing_users) }}
+ sla:
+ {{ no_failures_sla() }}
diff --git a/functest/opnfv_tests/openstack/rally/task.yaml b/functest/opnfv_tests/openstack/rally/task.yaml
index 033edb83..65f101fb 100644
--- a/functest/opnfv_tests/openstack/rally/task.yaml
+++ b/functest/opnfv_tests/openstack/rally/task.yaml
@@ -31,6 +31,10 @@
{%- include "var/opnfv-neutron.yaml"-%}
{% endif %}
+{% if "ceilometer" in service_list %}
+{%- include "var/opnfv-ceilometer.yaml"-%}
+{% endif %}
+
{% if "quotas" in service_list %}
{%- include "var/opnfv-quotas.yaml"-%}
{% endif %}
diff --git a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
index 86053ccf..17e02466 100644
--- a/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
+++ b/functest/opnfv_tests/openstack/refstack_client/refstack_client.py
@@ -28,12 +28,13 @@ from functest.opnfv_tests.openstack.refstack_client.tempest_conf \
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
import functest.utils.functest_utils as ft_utils
+import functest.utils.openstack_utils as os_utils
# logging configuration """
LOGGER = logging.getLogger(__name__)
-class RefstackClient(testcase.OSGCTestCase):
+class RefstackClient(testcase.TestCase):
"""RefstackClient testcase implementation class."""
def __init__(self, **kwargs):
@@ -41,6 +42,7 @@ class RefstackClient(testcase.OSGCTestCase):
if "case_name" not in kwargs:
kwargs["case_name"] = "refstack_defcore"
super(RefstackClient, self).__init__(**kwargs)
+ self.tempestconf = None
self.conf_path = pkg_resources.resource_filename(
'functest',
'opnfv_tests/openstack/refstack_client/refstack_tempest.conf')
@@ -57,6 +59,13 @@ class RefstackClient(testcase.OSGCTestCase):
CONST.__getattribute__('OS_INSECURE').lower() == 'true'):
self.insecure = '-k'
+ def generate_conf(self):
+ if not os.path.exists(conf_utils.REFSTACK_RESULTS_DIR):
+ os.makedirs(conf_utils.REFSTACK_RESULTS_DIR)
+
+ self.tempestconf = TempestConf()
+ self.tempestconf.generate_tempestconf()
+
def run_defcore(self, conf, testlist):
"""Run defcore sys command."""
cmd = ("refstack-client test {0} -c {1} -v --test-list {2}"
@@ -87,10 +96,18 @@ class RefstackClient(testcase.OSGCTestCase):
stderr=subprocess.STDOUT)
def parse_refstack_result(self):
- """Parse Refstact results."""
+ """Parse Refstack results."""
try:
with open(os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
"refstack.log"), 'r') as logfile:
+ for line in logfile.readlines():
+ if 'Tests' in line:
+ break
+ if re.search(r"\} tempest\.", line):
+ LOGGER.info(line.replace('\n', ''))
+
+ with open(os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
+ "refstack.log"), 'r') as logfile:
output = logfile.read()
for match in re.findall(r"Ran: (\d+) tests in (\d+\.\d{4}) sec.",
@@ -144,18 +161,18 @@ class RefstackClient(testcase.OSGCTestCase):
"""
self.start_time = time.time()
- if not os.path.exists(conf_utils.REFSTACK_RESULTS_DIR):
- os.makedirs(conf_utils.REFSTACK_RESULTS_DIR)
-
try:
- tempestconf = TempestConf()
- tempestconf.generate_tempestconf()
+ # Make sure that Tempest is configured
+ if not self.tempestconf:
+ self.generate_conf()
self.run_defcore_default()
self.parse_refstack_result()
res = testcase.TestCase.EX_OK
except Exception:
LOGGER.exception("Error with run")
res = testcase.TestCase.EX_RUN_ERROR
+ finally:
+ self.tempestconf.clean()
self.stop_time = time.time()
return res
@@ -194,6 +211,45 @@ class RefstackClient(testcase.OSGCTestCase):
return res
+ def create_snapshot(self):
+ """
+ Run the Tempest cleanup utility to initialize OS state.
+ For details, see https://docs.openstack.org/tempest/latest/cleanup.html
+
+ :return: TestCase.EX_OK
+ """
+ LOGGER.info("Initializing the saved state of the OpenStack deployment")
+
+ # Make sure that Tempest is configured
+ if not self.tempestconf:
+ self.generate_conf()
+
+ try:
+ os_utils.init_tempest_cleanup(
+ self.tempestconf.DEPLOYMENT_DIR, 'tempest.conf',
+ os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
+ "tempest-cleanup-init.log"))
+ except Exception as err:
+ LOGGER.error(str(err))
+ return testcase.TestCase.EX_RUN_ERROR
+
+ return super(RefstackClient, self).create_snapshot()
+
+ def clean(self):
+ """
+ Run the Tempest cleanup utility to delete and destroy OS resources.
+ For details, see https://docs.openstack.org/tempest/latest/cleanup.html
+ """
+ LOGGER.info("Destroying the resources created for tempest")
+
+ os_utils.perform_tempest_cleanup(
+ self.tempestconf.DEPLOYMENT_DIR, 'tempest.conf',
+ os.path.join(conf_utils.REFSTACK_RESULTS_DIR,
+ "tempest-cleanup.log")
+ )
+
+ return super(RefstackClient, self).clean()
+
class RefstackClientParser(object): # pylint: disable=too-few-public-methods
"""Command line argument parser helper."""
diff --git a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
index 30590b9e..db745227 100644
--- a/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
+++ b/functest/opnfv_tests/openstack/refstack_client/tempest_conf.py
@@ -11,13 +11,15 @@ import pkg_resources
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils import openstack_utils
from functest.utils.constants import CONST
+from functest.opnfv_tests.openstack.tempest.tempest \
+ import TempestResourcesManager
""" logging configuration """
logger = logging.getLogger(__name__)
class TempestConf(object):
- def __init__(self):
+ def __init__(self, **kwargs):
self.VERIFIER_ID = conf_utils.get_verifier_id()
self.VERIFIER_REPO_DIR = conf_utils.get_verifier_repo_dir(
self.VERIFIER_ID)
@@ -27,15 +29,22 @@ class TempestConf(object):
self.confpath = pkg_resources.resource_filename(
'functest',
'opnfv_tests/openstack/refstack_client/refstack_tempest.conf')
+ self.resources = TempestResourcesManager(**kwargs)
def generate_tempestconf(self):
try:
openstack_utils.source_credentials(
CONST.__getattribute__('openstack_creds'))
- img_flavor_dict = conf_utils.create_tempest_resources(
- use_custom_images=True, use_custom_flavors=True)
+ resources = self.resources.create(create_project=True,
+ use_custom_images=True,
+ use_custom_flavors=True)
conf_utils.configure_tempest_defcore(
- self.DEPLOYMENT_DIR, img_flavor_dict)
+ self.DEPLOYMENT_DIR,
+ image_id=resources.get("image_id"),
+ flavor_id=resources.get("flavor_id"),
+ image_id_alt=resources.get("image_id_alt"),
+ flavor_id_alt=resources.get("flavor_id_alt"),
+ tenant_id=resources.get("project_id"))
except Exception as e:
logger.error("error with generating refstack client "
"reference tempest conf file: %s", e)
@@ -48,6 +57,9 @@ class TempestConf(object):
except Exception as e:
logger.error('Error with run: %s', e)
+ def clean(self):
+ self.resources.cleanup()
+
def main():
logging.basicConfig()
diff --git a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
index 0b87440b..bfdcd862 100644
--- a/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
+++ b/functest/opnfv_tests/openstack/snaps/snaps_test_runner.py
@@ -10,7 +10,6 @@ import logging
from functest.core import unit
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
@@ -28,9 +27,14 @@ class SnapsTestRunner(unit.Suite):
if 'os_creds' in kwargs:
self.os_creds = kwargs['os_creds']
else:
+ creds_override = None
+ if hasattr(CONST, 'snaps_os_creds_override'):
+ creds_override = CONST.__getattribute__(
+ 'snaps_os_creds_override')
self.os_creds = openstack_tests.get_credentials(
os_env_file=CONST.__getattribute__('openstack_creds'),
- proxy_settings_str=None, ssh_proxy_cmd=None)
+ proxy_settings_str=None, ssh_proxy_cmd=None,
+ overrides=creds_override)
if 'ext_net_name' in kwargs:
self.ext_net_name = kwargs['ext_net_name']
@@ -39,7 +43,7 @@ class SnapsTestRunner(unit.Suite):
self.use_fip = CONST.__getattribute__('snaps_use_floating_ips')
self.use_keystone = CONST.__getattribute__('snaps_use_keystone')
- scenario = functest_utils.get_scenario()
+ scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
self.flavor_metadata = None
if 'ovs' in scenario or 'fdio' in scenario:
diff --git a/functest/opnfv_tests/openstack/tempest/conf_utils.py b/functest/opnfv_tests/openstack/tempest/conf_utils.py
index fd3785b9..52fa6003 100644
--- a/functest/opnfv_tests/openstack/tempest/conf_utils.py
+++ b/functest/opnfv_tests/openstack/tempest/conf_utils.py
@@ -41,6 +41,9 @@ REFSTACK_RESULTS_DIR = os.path.join(CONST.__getattribute__('dir_results'),
'refstack')
TEMPEST_CONF_YAML = pkg_resources.resource_filename(
'functest', 'opnfv_tests/openstack/tempest/custom_tests/tempest_conf.yaml')
+TEST_ACCOUNTS_FILE = pkg_resources.resource_filename(
+ 'functest',
+ 'opnfv_tests/openstack/tempest/custom_tests/test_accounts.yaml')
CI_INSTALLER_TYPE = CONST.__getattribute__('INSTALLER_TYPE')
CI_INSTALLER_IP = CONST.__getattribute__('INSTALLER_IP')
@@ -49,77 +52,9 @@ CI_INSTALLER_IP = CONST.__getattribute__('INSTALLER_IP')
logger = logging.getLogger(__name__)
-def create_tempest_resources(use_custom_images=False,
- use_custom_flavors=False):
-
- logger.debug("Creating private network for Tempest suite")
- network_dic = os_utils.create_shared_network_full(
- CONST.__getattribute__('tempest_private_net_name'),
- CONST.__getattribute__('tempest_private_subnet_name'),
- CONST.__getattribute__('tempest_router_name'),
- CONST.__getattribute__('tempest_private_subnet_cidr'))
- if network_dic is None:
- raise Exception('Failed to create private network')
-
- image_id = ""
- image_id_alt = ""
- flavor_id = ""
- flavor_id_alt = ""
-
- if (CONST.__getattribute__('tempest_use_custom_images') or
- use_custom_images):
- # adding alternative image should be trivial should we need it
- logger.debug("Creating image for Tempest suite")
- _, image_id = os_utils.get_or_create_image(
- CONST.__getattribute__('openstack_image_name'),
- GLANCE_IMAGE_PATH,
- CONST.__getattribute__('openstack_image_disk_format'))
- if image_id is None:
- raise Exception('Failed to create image')
-
- if use_custom_images:
- logger.debug("Creating 2nd image for Tempest suite")
- _, image_id_alt = os_utils.get_or_create_image(
- CONST.__getattribute__('openstack_image_name_alt'),
- GLANCE_IMAGE_PATH,
- CONST.__getattribute__('openstack_image_disk_format'))
- if image_id_alt is None:
- raise Exception('Failed to create image')
-
- if (CONST.__getattribute__('tempest_use_custom_flavors') or
- use_custom_flavors):
- # adding alternative flavor should be trivial should we need it
- logger.debug("Creating flavor for Tempest suite")
- _, flavor_id = os_utils.get_or_create_flavor(
- CONST.__getattribute__('openstack_flavor_name'),
- CONST.__getattribute__('openstack_flavor_ram'),
- CONST.__getattribute__('openstack_flavor_disk'),
- CONST.__getattribute__('openstack_flavor_vcpus'))
- if flavor_id is None:
- raise Exception('Failed to create flavor')
-
- if use_custom_flavors:
- logger.debug("Creating 2nd flavor for tempest_defcore")
- _, flavor_id_alt = os_utils.get_or_create_flavor(
- CONST.__getattribute__('openstack_flavor_name_alt'),
- CONST.__getattribute__('openstack_flavor_ram'),
- CONST.__getattribute__('openstack_flavor_disk'),
- CONST.__getattribute__('openstack_flavor_vcpus'))
- if flavor_id_alt is None:
- raise Exception('Failed to create flavor')
-
- img_flavor_dict = {}
- img_flavor_dict['image_id'] = image_id
- img_flavor_dict['image_id_alt'] = image_id_alt
- img_flavor_dict['flavor_id'] = flavor_id
- img_flavor_dict['flavor_id_alt'] = flavor_id_alt
-
- return img_flavor_dict
-
-
def get_verifier_id():
"""
- Returns verifer id for current Tempest
+ Returns verifier id for current Tempest
"""
cmd = ("rally verify list-verifiers | awk '/" +
CONST.__getattribute__('tempest_deployment_name') +
@@ -153,7 +88,7 @@ def get_verifier_deployment_id():
def get_verifier_repo_dir(verifier_id):
"""
- Returns installed verfier repo directory for Tempest
+ Returns installed verifier repo directory for Tempest
"""
if not verifier_id:
verifier_id = get_verifier_id()
@@ -195,32 +130,27 @@ def backup_tempest_config(conf_file):
"""
Copy config file to tempest results directory
"""
- if not os.path.exists(TEMPEST_RESULTS_DIR):
- os.makedirs(TEMPEST_RESULTS_DIR)
-
shutil.copyfile(conf_file,
os.path.join(TEMPEST_RESULTS_DIR, 'tempest.conf'))
-def configure_tempest(deployment_dir, IMAGE_ID=None, FLAVOR_ID=None,
- MODE=None):
+def configure_tempest(deployment_dir, image_id=None, flavor_id=None,
+ mode=None):
"""
Calls rally verify and updates the generated tempest.conf with
given parameters
"""
conf_file = configure_verifier(deployment_dir)
- configure_tempest_update_params(conf_file,
- IMAGE_ID, FLAVOR_ID)
+ configure_tempest_update_params(conf_file, image_id, flavor_id)
-def configure_tempest_defcore(deployment_dir, img_flavor_dict):
+def configure_tempest_defcore(deployment_dir, image_id, flavor_id,
+ image_id_alt, flavor_id_alt, tenant_id):
"""
Add/update needed parameters into tempest.conf file
"""
conf_file = configure_verifier(deployment_dir)
- configure_tempest_update_params(conf_file,
- img_flavor_dict.get("image_id"),
- img_flavor_dict.get("flavor_id"))
+ configure_tempest_update_params(conf_file, image_id, flavor_id)
logger.debug("Updating selected tempest.conf parameters for defcore...")
config = ConfigParser.RawConfigParser()
@@ -228,14 +158,14 @@ def configure_tempest_defcore(deployment_dir, img_flavor_dict):
config.set('DEFAULT', 'log_file', '{}/tempest.log'.format(deployment_dir))
config.set('oslo_concurrency', 'lock_path',
'{}/lock_files'.format(deployment_dir))
+ generate_test_accounts_file(tenant_id=tenant_id)
+ config.set('auth', 'test_accounts_file', TEST_ACCOUNTS_FILE)
config.set('scenario', 'img_dir', '{}'.format(deployment_dir))
config.set('scenario', 'img_file', 'tempest-image')
- config.set('compute', 'image_ref', img_flavor_dict.get("image_id"))
- config.set('compute', 'image_ref_alt',
- img_flavor_dict['image_id_alt'])
- config.set('compute', 'flavor_ref', img_flavor_dict.get("flavor_id"))
- config.set('compute', 'flavor_ref_alt',
- img_flavor_dict['flavor_id_alt'])
+ config.set('compute', 'image_ref', image_id)
+ config.set('compute', 'image_ref_alt', image_id_alt)
+ config.set('compute', 'flavor_ref', flavor_id)
+ config.set('compute', 'flavor_ref_alt', flavor_id_alt)
with open(conf_file, 'wb') as config_file:
config.write(config_file)
@@ -246,8 +176,29 @@ def configure_tempest_defcore(deployment_dir, img_flavor_dict):
shutil.copyfile(conf_file, confpath)
+def generate_test_accounts_file(tenant_id):
+ """
+ Add needed tenant and user params into test_accounts.yaml
+ """
+
+ logger.debug("Add needed params into test_accounts.yaml...")
+ accounts_list = [
+ {
+ 'tenant_name':
+ CONST.__getattribute__('tempest_identity_tenant_name'),
+ 'tenant_id': str(tenant_id),
+ 'username': CONST.__getattribute__('tempest_identity_user_name'),
+ 'password':
+ CONST.__getattribute__('tempest_identity_user_password')
+ }
+ ]
+
+ with open(TEST_ACCOUNTS_FILE, "w") as f:
+ yaml.dump(accounts_list, f, default_flow_style=False)
+
+
def configure_tempest_update_params(tempest_conf_file,
- IMAGE_ID=None, FLAVOR_ID=None):
+ image_id=None, flavor_id=None):
"""
Add/update needed parameters into tempest.conf file
"""
@@ -261,13 +212,13 @@ def configure_tempest_update_params(tempest_conf_file,
config.set('compute', 'volume_device_name',
CONST.__getattribute__('tempest_volume_device_name'))
if CONST.__getattribute__('tempest_use_custom_images'):
- if IMAGE_ID is not None:
- config.set('compute', 'image_ref', IMAGE_ID)
+ if image_id is not None:
+ config.set('compute', 'image_ref', image_id)
if IMAGE_ID_ALT is not None:
config.set('compute', 'image_ref_alt', IMAGE_ID_ALT)
if CONST.__getattribute__('tempest_use_custom_flavors'):
- if FLAVOR_ID is not None:
- config.set('compute', 'flavor_ref', FLAVOR_ID)
+ if flavor_id is not None:
+ config.set('compute', 'flavor_ref', flavor_id)
if FLAVOR_ID_ALT is not None:
config.set('compute', 'flavor_ref_alt', FLAVOR_ID_ALT)
config.set('identity', 'region', 'RegionOne')
diff --git a/functest/opnfv_tests/openstack/tempest/tempest.py b/functest/opnfv_tests/openstack/tempest/tempest.py
index 003d4ea4..b8a4e9ad 100644
--- a/functest/opnfv_tests/openstack/tempest/tempest.py
+++ b/functest/opnfv_tests/openstack/tempest/tempest.py
@@ -23,15 +23,26 @@ from functest.core import testcase
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
import functest.utils.functest_utils as ft_utils
+import functest.utils.openstack_utils as os_utils
+
+from snaps.openstack import create_flavor
+from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
+from snaps.openstack.create_project import ProjectSettings
+from snaps.openstack.create_network import NetworkSettings, SubnetSettings
+from snaps.openstack.create_user import UserSettings
+from snaps.openstack.tests import openstack_tests
+from snaps.openstack.utils import deploy_utils
+
""" logging configuration """
logger = logging.getLogger(__name__)
-class TempestCommon(testcase.OSGCTestCase):
+class TempestCommon(testcase.TestCase):
def __init__(self, **kwargs):
super(TempestCommon, self).__init__(**kwargs)
+ self.resources = TempestResourcesManager(**kwargs)
self.MODE = ""
self.OPTION = ""
self.VERIFIER_ID = conf_utils.get_verifier_id()
@@ -184,9 +195,12 @@ class TempestCommon(testcase.OSGCTestCase):
try:
self.result = 100 * int(num_success) / int(num_executed)
except ZeroDivisionError:
- logger.error("No test has been executed")
self.result = 0
- return
+ if int(num_tests) > 0:
+ logger.info("All tests have been skipped")
+ else:
+ logger.error("No test has been executed")
+ return
with open(os.path.join(conf_utils.TEMPEST_RESULTS_DIR,
"tempest.log"), 'r') as logfile:
@@ -219,12 +233,12 @@ class TempestCommon(testcase.OSGCTestCase):
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()
+ resources = self.resources.create()
conf_utils.configure_tempest(
self.DEPLOYMENT_DIR,
- IMAGE_ID=image_and_flavor.get("image_id"),
- FLAVOR_ID=image_and_flavor.get("flavor_id"),
- MODE=self.MODE)
+ image_id=resources.get("image_id"),
+ flavor_id=resources.get("flavor_id"),
+ mode=self.MODE)
self.generate_test_list(self.VERIFIER_REPO_DIR)
self.apply_tempest_blacklist()
self.run_verifier_tests()
@@ -233,10 +247,52 @@ class TempestCommon(testcase.OSGCTestCase):
except Exception as e:
logger.error('Error with run: %s' % e)
res = testcase.TestCase.EX_RUN_ERROR
+ finally:
+ self.resources.cleanup()
self.stop_time = time.time()
return res
+ def create_snapshot(self):
+ """
+ Run the Tempest cleanup utility to initialize OS state.
+
+ :return: TestCase.EX_OK
+ """
+ logger.info("Initializing the saved state of the OpenStack deployment")
+
+ if not os.path.exists(conf_utils.TEMPEST_RESULTS_DIR):
+ os.makedirs(conf_utils.TEMPEST_RESULTS_DIR)
+
+ # Make sure that the verifier is configured
+ conf_utils.configure_verifier(self.DEPLOYMENT_DIR)
+
+ try:
+ os_utils.init_tempest_cleanup(
+ self.DEPLOYMENT_DIR, 'tempest.conf',
+ os.path.join(conf_utils.TEMPEST_RESULTS_DIR,
+ "tempest-cleanup-init.log"))
+ except Exception as err:
+ logger.error(str(err))
+ return testcase.TestCase.EX_RUN_ERROR
+
+ return super(TempestCommon, self).create_snapshot()
+
+ def clean(self):
+ """
+ Run the Tempest cleanup utility to delete and destroy OS resources
+ created by Tempest.
+ """
+ logger.info("Destroying the resources created for refstack")
+
+ os_utils.perform_tempest_cleanup(
+ self.DEPLOYMENT_DIR, 'tempest.conf',
+ os.path.join(conf_utils.TEMPEST_RESULTS_DIR,
+ "tempest-cleanup.log")
+ )
+
+ return super(TempestCommon, self).clean()
+
class TempestSmokeSerial(TempestCommon):
@@ -285,3 +341,170 @@ class TempestDefcore(TempestCommon):
TempestCommon.__init__(self, **kwargs)
self.MODE = "defcore"
self.OPTION = "--concurrency 1"
+
+
+class TempestResourcesManager(object):
+
+ def __init__(self, **kwargs):
+ self.os_creds = None
+ if 'os_creds' in kwargs:
+ self.os_creds = kwargs['os_creds']
+ else:
+ self.os_creds = openstack_tests.get_credentials(
+ os_env_file=CONST.__getattribute__('openstack_creds'))
+
+ self.creators = list()
+
+ if hasattr(CONST, 'snaps_images_cirros'):
+ self.cirros_image_config = CONST.__getattribute__(
+ 'snaps_images_cirros')
+ else:
+ self.cirros_image_config = None
+
+ def create(self, use_custom_images=False, use_custom_flavors=False,
+ create_project=False):
+ if create_project:
+ logger.debug("Creating project (tenant) for Tempest suite")
+ project_name = CONST.__getattribute__(
+ 'tempest_identity_tenant_name')
+ project_creator = deploy_utils.create_project(
+ self.os_creds, ProjectSettings(
+ name=project_name,
+ description=CONST.__getattribute__(
+ 'tempest_identity_tenant_description')))
+ if (project_creator is None or
+ project_creator.get_project() is None):
+ raise Exception("Failed to create tenant")
+ project_id = project_creator.get_project().id
+ self.creators.append(project_creator)
+
+ logger.debug("Creating user for Tempest suite")
+ user_creator = deploy_utils.create_user(
+ self.os_creds, UserSettings(
+ name=CONST.__getattribute__('tempest_identity_user_name'),
+ password=CONST.__getattribute__(
+ 'tempest_identity_user_password'),
+ project_name=project_name))
+ if user_creator is None or user_creator.get_user() is None:
+ raise Exception("Failed to create user")
+ user_id = user_creator.get_user().id
+ self.creators.append(user_creator)
+ else:
+ project_name = None
+ project_id = None
+ user_id = None
+
+ logger.debug("Creating private network for Tempest suite")
+ network_creator = deploy_utils.create_network(
+ self.os_creds, NetworkSettings(
+ name=CONST.__getattribute__('tempest_private_net_name'),
+ project_name=project_name,
+ subnet_settings=[SubnetSettings(
+ name=CONST.__getattribute__('tempest_private_subnet_name'),
+ cidr=CONST.__getattribute__('tempest_private_subnet_cidr'))
+ ]))
+ if network_creator is None or network_creator.get_network() is None:
+ raise Exception("Failed to create private network")
+ self.creators.append(network_creator)
+
+ image_id = None
+ image_id_alt = None
+ flavor_id = None
+ flavor_id_alt = None
+
+ if (CONST.__getattribute__('tempest_use_custom_images') or
+ use_custom_images):
+ logger.debug("Creating image for Tempest suite")
+ image_base_name = CONST.__getattribute__('openstack_image_name')
+ os_image_settings = openstack_tests.cirros_image_settings(
+ image_base_name, public=True,
+ image_metadata=self.cirros_image_config)
+ logger.debug("Creating image for Tempest suite")
+ image_creator = deploy_utils.create_image(
+ self.os_creds, os_image_settings)
+ if image_creator is None:
+ raise Exception('Failed to create image')
+ self.creators.append(image_creator)
+ image_id = image_creator.get_image().id
+
+ if use_custom_images:
+ logger.debug("Creating 2nd image for Tempest suite")
+ image_base_name_alt = CONST.__getattribute__(
+ 'openstack_image_name_alt')
+ os_image_settings_alt = openstack_tests.cirros_image_settings(
+ image_base_name_alt, public=True,
+ image_metadata=self.cirros_image_config)
+ logger.debug("Creating 2nd image for Tempest suite")
+ image_creator_alt = deploy_utils.create_image(
+ self.os_creds, os_image_settings_alt)
+ if image_creator_alt is None:
+ raise Exception('Failed to create image')
+ self.creators.append(image_creator_alt)
+ image_id_alt = image_creator_alt.get_image().id
+
+ if (CONST.__getattribute__('tempest_use_custom_flavors') or
+ use_custom_flavors):
+ logger.info("Creating flavor for Tempest suite")
+ scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+ flavor_metadata = None
+ if 'ovs' in scenario or 'fdio' in scenario:
+ flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
+ flavor_creator = OpenStackFlavor(
+ self.os_creds, FlavorSettings(
+ name=CONST.__getattribute__('openstack_flavor_name'),
+ ram=CONST.__getattribute__('openstack_flavor_ram'),
+ disk=CONST.__getattribute__('openstack_flavor_disk'),
+ vcpus=CONST.__getattribute__('openstack_flavor_vcpus'),
+ metadata=flavor_metadata))
+ flavor = flavor_creator.create()
+ if flavor is None:
+ raise Exception('Failed to create flavor')
+ self.creators.append(flavor_creator)
+ flavor_id = flavor.id
+
+ if use_custom_flavors:
+ logger.info("Creating 2nd flavor for Tempest suite")
+ scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
+ flavor_metadata_alt = None
+ if 'ovs' in scenario or 'fdio' in scenario:
+ flavor_metadata_alt = create_flavor.MEM_PAGE_SIZE_LARGE
+ flavor_creator_alt = OpenStackFlavor(
+ self.os_creds, FlavorSettings(
+ name=CONST.__getattribute__('openstack_flavor_name_alt'),
+ ram=CONST.__getattribute__('openstack_flavor_ram'),
+ disk=CONST.__getattribute__('openstack_flavor_disk'),
+ vcpus=CONST.__getattribute__('openstack_flavor_vcpus'),
+ metadata=flavor_metadata_alt))
+ flavor_alt = flavor_creator_alt.create()
+ if flavor_alt is None:
+ raise Exception('Failed to create flavor')
+ self.creators.append(flavor_creator_alt)
+ flavor_id_alt = flavor_alt.id
+
+ print("RESOURCES CREATE: image_id: %s, image_id_alt: %s, "
+ "flavor_id: %s, flavor_id_alt: %s" % (
+ image_id, image_id_alt, flavor_id, flavor_id_alt,))
+
+ result = {
+ 'image_id': image_id,
+ 'image_id_alt': image_id_alt,
+ 'flavor_id': flavor_id,
+ 'flavor_id_alt': flavor_id_alt
+ }
+
+ if create_project:
+ result['project_id'] = project_id
+ result['tenant_id'] = project_id # for compatibility
+ result['user_id'] = user_id
+
+ return result
+
+ def cleanup(self):
+ """
+ Cleanup all OpenStack objects. Should be called on completion.
+ """
+ for creator in reversed(self.creators):
+ try:
+ creator.clean()
+ except Exception as e:
+ logger.error('Unexpected error cleaning - %s', e)
diff --git a/functest/opnfv_tests/openstack/vping/vping_base.py b/functest/opnfv_tests/openstack/vping/vping_base.py
index 74fbce1b..c93d2f26 100644
--- a/functest/opnfv_tests/openstack/vping/vping_base.py
+++ b/functest/opnfv_tests/openstack/vping/vping_base.py
@@ -13,7 +13,6 @@ import time
import uuid
from functest.core import testcase
-from functest.utils import functest_utils
from functest.utils.constants import CONST
from snaps.openstack import create_flavor
@@ -43,8 +42,14 @@ class VPingBase(testcase.TestCase):
if 'os_creds' in kwargs:
self.os_creds = kwargs['os_creds']
else:
+ creds_override = None
+ if hasattr(CONST, 'snaps_os_creds_override'):
+ creds_override = CONST.__getattribute__(
+ 'snaps_os_creds_override')
+
self.os_creds = openstack_tests.get_credentials(
- os_env_file=CONST.__getattribute__('openstack_creds'))
+ os_env_file=CONST.__getattribute__('openstack_creds'),
+ overrides=creds_override)
self.creators = list()
self.image_creator = None
@@ -102,19 +107,38 @@ class VPingBase(testcase.TestCase):
'vping_private_subnet_name') + self.guid
private_subnet_cidr = CONST.__getattribute__(
'vping_private_subnet_cidr')
+
+ vping_network_type = None
+ vping_physical_network = None
+ vping_segmentation_id = None
+
+ if (hasattr(CONST, 'vping_network_type')):
+ vping_network_type = CONST.__getattribute__(
+ 'vping_network_type')
+ if (hasattr(CONST, 'vping_physical_network')):
+ vping_physical_network = CONST.__getattribute__(
+ 'vping_physical_network')
+ if (hasattr(CONST, 'vping_segmentation_id')):
+ vping_segmentation_id = CONST.__getattribute__(
+ 'vping_segmentation_id')
+
self.logger.info(
"Creating network with name: '%s'" % private_net_name)
self.network_creator = deploy_utils.create_network(
self.os_creds,
- NetworkSettings(name=private_net_name,
- subnet_settings=[SubnetSettings(
- name=private_subnet_name,
- cidr=private_subnet_cidr)]))
+ NetworkSettings(
+ name=private_net_name,
+ network_type=vping_network_type,
+ physical_network=vping_physical_network,
+ segmentation_id=vping_segmentation_id,
+ subnet_settings=[SubnetSettings(
+ name=private_subnet_name,
+ cidr=private_subnet_cidr)]))
self.creators.append(self.network_creator)
self.logger.info(
"Creating flavor with name: '%s'" % self.flavor_name)
- scenario = functest_utils.get_scenario()
+ scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
flavor_metadata = None
if 'ovs' in scenario or 'fdio' in scenario:
flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
diff --git a/functest/opnfv_tests/sdn/onos/onos.py b/functest/opnfv_tests/sdn/onos/onos.py
deleted file mode 100644
index 08ba4da3..00000000
--- a/functest/opnfv_tests/sdn/onos/onos.py
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2017 HUAWEI TECHNOLOGIES CO.,LTD and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-
-import logging
-import os
-import pkg_resources
-import re
-import subprocess
-import shutil
-import time
-import urlparse
-
-from functest.core import testcase
-from functest.utils.constants import CONST
-import functest.utils.functest_utils as ft_utils
-import functest.utils.openstack_utils as openstack_utils
-
-
-class OnosBase(testcase.TestCase):
- 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 = pkg_resources.resource_filename(
- 'functest', 'opnfv_tests/sdn/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()
- try:
- self._run()
- res = testcase.TestCase.EX_OK
- except Exception as e:
- self.logger.error('Error with run: %s', e)
- res = testcase.TestCase.EX_RUN_ERROR
-
- self.stop_time = time.time()
- return res
-
- def _run(self):
- raise NotImplementedError('_run is not implemented')
-
-
-class Onos(OnosBase):
- def __init__(self, **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 (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
- 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)
- self.logger.debug("Run script: %s", testname)
- ft_utils.execute_command_raise(
- cmd,
- error_msg=('Error when running ONOS script: %s'
- % (testname)))
-
- def clean_existing_logs(self):
- log_dir = [f for f in os.listdir(self.log_path)]
- for log in log_dir:
- try:
- if os.path.isdir(log):
- shutil.rmtree(log)
- elif os.path.isfile(log):
- os.remove(log)
- except OSError as e:
- 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)
- p = subprocess.Popen(cmd,
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
-
- for line in p.stdout:
- self.logger.debug(line)
- if re.search("\s+[1-9]+\s+", line):
- self.logger.debug("Testcase Fails\n" + line)
-
- cmd = "grep -rnh 'Execution Time' {0}".format(self.log_path)
- result_buffer = os.popen(cmd).read()
- time1 = result_buffer[114:128]
- time2 = result_buffer[28:42]
- cmd = "grep -rnh 'Success Percentage' {0}".format(
- os.path.join(self.log_path, "FUNCvirNetNB_*"))
- result_buffer = os.popen(cmd).read()
- if result_buffer.find('100%') >= 0:
- result1 = 'Success'
- else:
- result1 = 'Failed'
- cmd = "grep -rnh 'Success Percentage' {0}".format(
- os.path.join(self.log_path, "FUNCvirNetNBL3*"))
- result_buffer = os.popen(cmd).read()
- if result_buffer.find('100%') >= 0:
- result2 = 'Success'
- else:
- result2 = 'Failed'
- status1 = []
- status2 = []
- cmd = "grep -rnh 'h3' {0}".format(
- os.path.join(self.log_path, "FUNCvirNetNB_*"))
- result_buffer = os.popen(cmd).read()
- pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>")
- # res = pattern.search(result_buffer).groups()
- res = pattern.findall(result_buffer)
- i = 0
- for index in range(len(res)):
- status1.append({'Case name:': res[i][0] + res[i][1],
- 'Case result': res[i][2]})
- i = i + 1
- cmd = "grep -rnh 'h3' {0}".format(
- os.path.join(self.log_path, "FUNCvirNetNBL3*"))
- result_buffer = os.popen(cmd).read()
- pattern = re.compile("<h3>([^-]+) - ([^-]+) - (\S*)</h3>")
- res = pattern.findall(result_buffer)
- i = 0
- for index in range(len(res)):
- status2.append({'Case name:': res[i][0] + res[i][1],
- 'Case result': res[i][2]})
- i = i + 1
- payload = {'FUNCvirNet': {'duration': time1,
- 'result': result1,
- 'status': status1},
- 'FUNCvirNetL3': {'duration': time2,
- 'result': result2,
- 'status': status2}}
- return payload
-
- def parse_result(self):
- result = self.get_result()
- status = "FAIL"
- try:
- if (result['FUNCvirNet']['result'] == "Success" and
- result['FUNCvirNetL3']['result'] == "Success"):
- status = "PASS"
- except Exception:
- self.logger.error("Unable to set ONOS result")
-
- self.result = status
- self.details = result
-
- def _run(self):
- self.clean_existing_logs()
- self.set_onos_ip()
- self.run_onos_script('FUNCvirNetNB')
- self.run_onos_script('FUNCvirNetNBL3')
- self.parse_result()
-
-
-class OnosSfc(OnosBase):
- def __init__(self, **kwargs):
- if "case_name" not in kwargs:
- kwargs["case_name"] = "onos_sfc"
- super(OnosSfc, self).__init__(**kwargs)
-
- def get_ip(self, type):
- url = openstack_utils.get_endpoint(service_type=type)
- self.logger.debug('get_ip for %s: %s', type, url)
- return urlparse.urlparse(url).hostname
-
- def update_sfc_onos_file(self, before, after):
- file_dir = os.path.join(self.onos_sfc_path, "sfc_onos.py")
- cmd = "sed -i 's/{0}/{1}/g' {2}".format(before,
- after,
- file_dir)
- ft_utils.execute_command_raise(
- cmd,
- error_msg=('Error with replacing %s with %s'
- % (before, after)))
-
- def create_image(self):
- self.logger.warn('inside create_image')
- glance_client = openstack_utils.get_glance_client()
- image_id = openstack_utils.create_glance_image(
- glance_client,
- self.onos_sfc_image_name,
- self.onos_sfc_image_path)
- if image_id is None:
- raise Exception('Failed to create image')
-
- 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("identity"))
- self.update_sfc_onos_file("neutron_ip", self.get_ip("network"))
- self.update_sfc_onos_file("nova_ip", self.get_ip("compute"))
- self.update_sfc_onos_file("glance_ip", self.get_ip("image"))
- 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)
- self.logger.debug("SFC configuration is modified")
-
- def sfc_test(self):
- cmd = 'python {0}'.format(os.path.join(self.onos_sfc_path, 'sfc.py'))
- ft_utils.execute_command_raise(cmd,
- error_msg='Error with testing SFC')
-
- def _run(self):
- self.create_image()
- self.set_sfc_conf()
- self.sfc_test()
diff --git a/functest/opnfv_tests/sdn/onos/sfc/README.md b/functest/opnfv_tests/sdn/onos/sfc/README.md
deleted file mode 100644
index ae63ee21..00000000
--- a/functest/opnfv_tests/sdn/onos/sfc/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-SFC Script ReadMe File
-**********************
-
-Topology
----------
-
-Validated with the Fuel Enviroment.
-
-
-Things to Remember :
---------------------
-
-1] This Script basically Tests the SFC functionality with ONOS controller.
-2] Ip address of Openstack and ONOS are got dynamically.
-3] Initally this sfc script can be used for ONOS and on Request , if need will modify for other controllers.
-
-
-Contact Details :
------------------
-
-email-id : antonysilvester@gmail.com
diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc.py b/functest/opnfv_tests/sdn/onos/sfc/sfc.py
deleted file mode 100644
index 2bb9082c..00000000
--- a/functest/opnfv_tests/sdn/onos/sfc/sfc.py
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) CREATED5 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
-#
-# ###########################################################################
-# OPNFV SFC Script
-# **** Scripted by Antony Silvester - antony.silvester@huawei.com ******
-# ###########################################################################
-
-# Testcase 1 : Prerequisites configuration for SFC
-# Testcase 2 : Creation of 3 VNF Nodes and Attaching Ports
-# Testcase 3 : Configure SFC [Port pair,Port Group ,Flow classifer
-# Testcase 4 : Configure Port Chain and verify the flows are added.
-# Testcase 5 : Verify traffic with VNF node.
-# Testcase 6 : Remove the Port Chain and Verify the traffic.
-# Testcase 7 : Cleanup
-# ###########################################################################
-#
-"""Script to Test the SFC scenarios in ONOS."""
-
-import logging
-import time
-import functest.utils.functest_utils as ft_utils
-from sfc_onos import SfcOnos
-
-logger = logging.getLogger(__name__)
-Sfc_obj = SfcOnos()
-
-OK = 200
-CREATED = 201
-ACCEPTED = 202
-NO_CONTENT = 204
-
-start_time = time.time()
-
-
-def PreConfig():
- logger.info("Testcase 1 : Prerequisites configuration for SFC")
- logger.info("1.1 Creation of Auth-Token")
- check(Sfc_obj.getToken, OK, "Creation of Token")
- logger.info("1.2 Creation of Network")
- check(Sfc_obj.createNetworks, CREATED, "Creation of network")
- logger.info("1.3 Creation of Subnetwork")
- check(Sfc_obj.createSubnets, CREATED, "Creation of Subnetwork")
-
-
-def CreateNodes():
- logger.info("Testcase 2 : Creation of 3 VNF Nodes and Attaching Ports")
- logger.info("2.1 Creation of Ports")
- check(Sfc_obj.createPorts, CREATED, "Creation of Port")
- logger.info("2.2 Creation of VM-Compute-Node")
- check(Sfc_obj.createVm, ACCEPTED, "Creation of VM")
- logger.info("2.3 Check VM Status")
- check(Sfc_obj.checkVmState, OK, "Vm statue check")
- logger.info("2.4 Router Creation")
- check(Sfc_obj.createRouter, CREATED, "Creation of Router")
- logger.info("2.5 Attachement of Interface to VM")
- check(Sfc_obj.attachInterface, OK, "Interface attached to VM")
- logger.info("2.6 Attachement of FLoating Ip to VM")
- check(Sfc_obj.addFloatingIp, ACCEPTED, "Floating Ip attached to VM")
-
-
-def ConfigSfc():
- logger.info(
- "Testcase 3 : Configure SFC [Portair,PortGroup,Flow classifer]")
- logger.info("3.1 Creation of Port Pair")
- check(Sfc_obj.createPortPair, CREATED, "Creation of Port Pair")
- logger.info("3.2 Getting the Port Pair ID")
- check(Sfc_obj.getPortPair, OK, "Getting Port Pair ID")
- logger.info("3.3 Creation of Port Pair Group")
- check(Sfc_obj.createPortGroup, CREATED, "Creation of Port Pair Group")
- logger.info("3.4 Getting Port Pair Group ID ")
- check(Sfc_obj.getPortGroup, OK, "Getting Port Pair Group ID")
- logger.info("3.5 Creation of Flow Classifier")
- check(Sfc_obj.createFlowClassifier, CREATED, "Creation of Flow Classifier")
- logger.info(
- "Testcase 4 : Configure Port Chain and verify flows are added")
- logger.info("4.1 Creation of Port Chain")
- check(Sfc_obj.createPortChain, CREATED, "Creation of Port Chain")
-
-
-def VerifySfcTraffic():
- status = "PASS"
- logger.info("Testcase 5 : Verify traffic with VNF node.")
- if (Sfc_obj.loginToVM() == "1"):
- logger.info("SFC function Working")
- else:
- logger.error("SFC function not working")
- status = "FAIL"
-
- logger.info("Testcase 6 : Remove the Port Chain and Verify the traffic")
- if (Sfc_obj.deletePortChain() == NO_CONTENT):
- if (Sfc_obj.loginToVM() == "0"):
- logger.info("SFC function is removed Successfully")
- else:
- logger.error("SFC function not Removed. Have some problem")
- status = "FAIL"
- if (Sfc_obj.deleteFlowClassifier() == NO_CONTENT):
- if (Sfc_obj.deletePortGroup() == NO_CONTENT):
- if (Sfc_obj.deletePortPair() == NO_CONTENT):
- logger.info(
- "SFC configuration is deleted successfully")
- else:
- logger.error("Port pair is deleted successfully")
- status = "FAIL"
- else:
- logger.error("Port Group is NOT deleted successfully")
- status = "FAIL"
- else:
- logger.error("Flow classifier is NOT deleted successfully")
- status = "FAIL"
- else:
- logger.error("PortChain configuration is NOT deleted successfully")
- status = "FAIL"
- if (status == "FAIL"):
- fail("Traffic for SFC is NOT verified successfully")
-
-
-def CleanUp():
- logger.info("Testcase 7 : Cleanup")
- if (Sfc_obj.cleanup() == NO_CONTENT):
- logger.info("CleanUp is successfull")
- else:
- logger.error("CleanUp is NOT successfull")
-
-
-def check(method, criteria, msg):
- if (method() == criteria):
- logger.info(msg + 'is Successful')
- else:
- fail(msg + 'is not successful')
-
-
-def fail(fail_info):
- logger.error(fail_info)
- CleanUp()
- PushDB("FAIL", fail_info)
- exit(-1)
-
-
-def PushDB(status, info):
- logger.info("Summary :")
- try:
- logger.debug("Push ONOS SFC results into DB")
- stop_time = time.time()
-
- # ONOS SFC success criteria = all tests OK
- duration = round(stop_time - start_time, 1)
- logger.info("Result is " + status)
- ft_utils.push_results_to_db("functest",
- "onos_sfc",
- start_time,
- stop_time,
- status,
- details={'duration': duration,
- 'error': info})
- except:
- logger.error("Error pushing results into Database")
-
-
-def main():
- """Script to Test the SFC scenarios in ONOS."""
- logging.basicConfig()
- PreConfig()
- CreateNodes()
- ConfigSfc()
- VerifySfcTraffic()
- CleanUp()
- PushDB("PASS", "")
diff --git a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py b/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
deleted file mode 100644
index 4e93c133..00000000
--- a/functest/opnfv_tests/sdn/onos/sfc/sfc_onos.py
+++ /dev/null
@@ -1,887 +0,0 @@
-import logging
-import os
-import re
-import time
-import json
-import requests
-
-from multiprocessing import Process
-from multiprocessing import Queue
-from pexpect import pxssh
-
-from functest.utils.constants import CONST
-
-OK = 200
-CREATED = 201
-ACCEPTED = 202
-NO_CONTENT = 204
-
-
-class SfcOnos(object):
- """Defines all the def function of SFC."""
-
- def __init__(self):
- """Initialization of variables."""
- self.logger = logging.getLogger(__name__)
- self.osver = "v2.0"
- self.token_id = 0
- self.net_id = 0
- self.image_id = 0
- self.keystone_hostname = 'keystone_ip'
- self.neutron_hostname = 'neutron_ip'
- self.nova_hostname = 'nova_ip'
- self.glance_hostname = 'glance_ip'
- self.onos_hostname = 'onos_ip'
- # Network variables #######
- self.netname = "test_nw"
- self.admin_state_up = True
- self.tenant_id = 0
- self.subnetId = 0
- # #########################
- # SubNet variables#########
- self.ip_version = 4
- self.cidr = "20.20.20.0/24"
- self.subnetname = "test_nw_subnets"
- # ###############################
- # Port variable
- self.port = "port"
- self.port_num = []
- self.vm_id = 0
- self.port_ip = []
- self.count = 0
- self.i = 0
- self.numTerms = 3
- self.security_groups = []
- self.port_security_enabled = False
- # ###############################
- # VM creation variable
- self.container_format = "bare"
- self.disk_format = "qcow2"
- self.imagename = "TestSfcVm"
- self.createImage = ("/home/root1/devstack/files/images/"
- "firewall_block_image.img")
-
- self.vm_name = "vm"
- self.imageRef = "test"
- self.flavorRef = "1"
- self.max_count = "1"
- self.min_count = "1"
- self.org_nw_port = []
- self.image_id = 0
- self.routername = "router1"
- self.router_id = 0
- # #####################################
- # Port pair
- self.port_pair_ingress = 0
- self.port_pair_egress = 0
- self.port_pair_name = "PP"
- self.port_pair_id = []
- # ####################################
- # Port Group
- self.port_group_name = "PG"
- self.port_grp_id = []
- # ####################################
- # FlowClassifier
- self.source_ip_prefix = "20.20.20.0/24"
- self.destination_ip_prefix = "20.20.20.0/24"
- self.logical_source_port = 0
- self.fcname = "FC"
- self.ethertype = "IPv4"
- # #####################################
- self.flow_class_if = 0
- # #####################################
- # Port Chain variables
- self.pcname = 'PC'
- self.PC_id = 0
- # #####################################
- # Port Chain variables
- self.flowadd = ''
- # #####################################
- self.ip_pool = 0
- self.vm_public_ip = []
- self.vm_public_id = []
- self.cirros_username = CONST.__getattribute__(
- 'openstack_image_username')
- self.cirros_password = CONST.__getattribute__(
- 'openstack_image_password')
- self.net_id1 = 0
- self.vm = []
- self.address = 0
- self.value = 0
- self.pub_net_id = 0
-
- def getToken(self):
- """Get the keystone token value from Openstack ."""
- url = 'http://%s:5000/%s/tokens' % (self.keystone_hostname,
- self.osver)
- data = ('{"auth": {"tenantName": "admin", "passwordCredentials":'
- '{ "username": "admin", "password": "console"}}}')
- headers = {"Accept": "application/json"}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == OK):
- json1_data = json.loads(response.content)
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.debug(json1_data)
- self.token_id = json1_data['access']['token']['id']
- self.tenant_id = json1_data['access']['token']['tenant']['id']
- return(response.status_code)
- else:
- return(response.status_code)
-
- def createNetworks(self):
- """Creation of networks."""
- Dicdata = {}
- if self.netname != '':
- Dicdata['name'] = self.netname
- if self.admin_state_up != '':
- Dicdata['admin_state_up'] = self.admin_state_up
- Dicdata = {'network': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/networks' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
-
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.net_id = json1_data['network']['id']
- return(response.status_code)
- else:
- return(response.status_code)
-
- def createSubnets(self):
- """Creation of SubNets."""
- Dicdata = {}
- if self.net_id != 0:
- Dicdata['network_id'] = self.net_id
- if self.ip_version != '':
- Dicdata['ip_version'] = self.ip_version
- if self.cidr != '':
- Dicdata['cidr'] = self.cidr
- if self.subnetname != '':
- Dicdata['name'] = self.subnetname
-
- Dicdata = {'subnet': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/subnets' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
-
- if (response.status_code == CREATED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.subnetId = json1_data['subnet']['id']
- return(response.status_code)
- else:
- return(response.status_code)
-
- def createPorts(self):
- """Creation of Ports."""
- for x in range(self.i, self.numTerms):
- Dicdata = {}
- if self.net_id != '':
- Dicdata['network_id'] = self.net_id
- if self.port != '':
- Dicdata['name'] = "port" + str(x)
- if self.admin_state_up != '':
- Dicdata['admin_state_up'] = self.admin_state_up
- if self.security_groups != '':
- Dicdata['security_groups'] = self.security_groups
- # if self.port_security_enabled != '':
- # Dicdata['port_security_enabled'] = self.port_security_enabled
-
- Dicdata = {'port': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/ports' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
-
- if (response.status_code == CREATED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
-
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.port_num.append(json1_data['port']['id'])
- self.port_ip.append(json1_data['port']['fixed_ips'][0]
- ['ip_address'])
- else:
- return(response.status_code)
- return(response.status_code)
-
- def createVm(self):
- """Creation of Instance, using firewall image."""
- url = ("http://%s:9292/v2/images?"
- "name=TestSfcVm" % (self.glance_hostname))
- headers = {"Accept": "application/json",
- "Content-Type": "application/octet-stream",
- "X-Auth-Token": self.token_id}
- response = requests.get(url, headers=headers)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("FireWall Image is available")
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.image_id = json1_data['images'][0]['id']
- else:
- return(response.status_code)
-
- url = ("http://%s:8774/v2.1/%s/flavors?"
- "name=m1.tiny" % (self.nova_hostname, self.tenant_id))
- headers = {"Accept": "application/json", "Content-Type":
- "application/json", "X-Auth-Token": self.token_id}
- response = requests.get(url, headers=headers)
-
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("Flavor is available")
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.flavorRef = json1_data['flavors'][0]['id']
- else:
- return(response.status_code)
-
- for y in range(0, 3):
- Dicdata = {}
- org_nw_port = []
- org_nw_port.append({'port': self.port_num[y]})
- if self.vm_name != '':
- Dicdata['name'] = "vm" + str(y)
- if self.imageRef != '':
- Dicdata['imageRef'] = self.image_id
- if self.flavorRef != '':
- Dicdata['flavorRef'] = self.flavorRef
- if self.max_count != '':
- Dicdata['max_count'] = self.max_count
- if self.min_count != '':
- Dicdata['min_count'] = self.min_count
- if self.org_nw_port != '':
- Dicdata['networks'] = org_nw_port
- Dicdata = {'server': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:8774/v2.1/%s/servers' % (self.nova_hostname,
- self.tenant_id)
- headers = {"Accept": "application/json", "Content-Type":
- "application/json", "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == ACCEPTED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- info = "Creation of VM" + str(y) + " is successfull"
- self.logger.debug(info)
-
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.vm_id = json1_data['server']['id']
- self.vm.append(json1_data['server']['id'])
- else:
- return(response.status_code)
-
- return(response.status_code)
-
- def checkVmState(self):
- """Checking the Status of the Instance."""
- time.sleep(10)
- for y in range(0, 3):
- url = ("http://%s:8774/v2.1/servers/"
- "detail?name=vm" + str(y)) % (self.neutron_hostname)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.get(url, headers=headers)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.vm_active = json1_data['servers'][0]['status']
- if (self.vm_active == "ACTIVE"):
- info = "VM" + str(y) + " is Active : " + self.vm_active
- else:
- info = "VM" + str(y) + " is NOT Active : " + self.vm_active
- self.logger.debug(info)
- else:
- return(response.status_code)
- return(response.status_code)
- time.sleep(10)
-
- def createPortPair(self):
- """Creation of Port Pair."""
- for p in range(1, 2):
- Dicdata = {}
- if self.port_pair_ingress != '':
- Dicdata['ingress'] = self.port_num[p]
- if self.port_pair_egress != '':
- egress = p
- Dicdata['egress'] = self.port_num[egress]
- if self.port_pair_name != '':
- Dicdata['name'] = "PP" + str(p)
-
- Dicdata = {'port_pair': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/sfc/port_pairs' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- info = ("Creation of Port Pair PP" + str(p) +
- " is successful")
- self.logger.debug(info)
- else:
- return(response.status_code)
-
- return(response.status_code)
-
- def getPortPair(self):
- """Query the Portpair id value."""
- for p in range(0, 1):
- url = ("http://%s:9696/%s/"
- "sfc/port_pairs?name=PP1" % (self.neutron_hostname,
- self.osver))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.get(url, headers=headers)
-
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.port_pair_id.append(json1_data['port_pairs'][0]['id'])
- else:
- return(response.status_code)
- return(response.status_code)
-
- def createPortGroup(self):
- """Creation of PortGroup."""
- for p in range(0, 1):
- Dicdata = {}
- port_pair_list = []
- port_pair_list.append(self.port_pair_id[p])
- if self.port_group_name != '':
- Dicdata['name'] = "PG" + str(p)
- if self.port_pair_id != '':
- Dicdata['port_pairs'] = port_pair_list
-
- Dicdata = {'port_pair_group': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = ("http://%s:9696/%s/"
- "sfc/port_pair_groups" % (self.neutron_hostname,
- self.osver))
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- info = ("Creation of Port Group PG" + str(p) +
- "is successful")
- self.logger.debug(info)
- else:
- return(response.status_code)
-
- return(response.status_code)
-
- def getPortGroup(self):
- """Query the PortGroup id."""
- for p in range(0, 1):
- url = ("http://%s:9696/%s/sfc/port_pair_groups"
- "?name=PG" + str(p)) % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.get(url, headers=headers)
-
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- json1_data = json.loads(response.content)
- self.port_grp_id.append(json1_data['port_pair_groups']
- [0]['id'])
- else:
- return(response.status_code)
- return(response.status_code)
-
- def createFlowClassifier(self):
- """Creation of Flow Classifier."""
- Dicdata = {}
- if self.source_ip_prefix != '':
- Dicdata['source_ip_prefix'] = self.source_ip_prefix
- if self.destination_ip_prefix != '':
- Dicdata['destination_ip_prefix'] = self.destination_ip_prefix
- if self.logical_source_port != '':
- Dicdata['logical_source_port'] = self.port_num[0]
- if self.fcname != '':
- Dicdata['name'] = "FC1"
- if self.ethertype != '':
- Dicdata['ethertype'] = self.ethertype
-
- Dicdata = {'flow_classifier': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = ("http://%s:9696/%s/"
- "sfc/flow_classifiers" % (self.neutron_hostname,
- self.osver))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- json1_data = json.loads(response.content)
- self.flow_class_if = json1_data['flow_classifier']['id']
- self.logger.debug("Creation of Flow Classifier is successful")
- return(response.status_code)
- else:
- return(response.status_code)
-
- def createPortChain(self):
- """Creation of PortChain."""
- Dicdata = {}
- flow_class_list = []
- flow_class_list.append(self.flow_class_if)
- port_pair_groups_list = []
- port_pair_groups_list.append(self.port_grp_id[0])
-
- if flow_class_list != '':
- Dicdata['flow_classifiers'] = flow_class_list
- if self.pcname != '':
- Dicdata['name'] = "PC1"
- if port_pair_groups_list != '':
- Dicdata['port_pair_groups'] = port_pair_groups_list
-
- Dicdata = {'port_chain': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/sfc/port_chains' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json",
- "Content-Type": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- self.logger.debug("Creation of PORT CHAIN is successful")
- json1_data = json.loads(response.content)
- self.PC_id = json1_data['port_chain']['id']
- return(response.status_code)
- else:
- return(response.status_code)
-
- def checkFlowAdded(self):
- """Check whether the Flows are downloaded successfully."""
- time.sleep(5)
- response = requests.get('http://' + self.onos_hostname +
- ':8181/onos/v1/flows',
- auth=("karaf", "karaf"))
- if (response.status_code == OK):
- self.logger.debug("Flow is successfully Queries")
- json1_data = json.loads(response.content)
- self.flowadd = json1_data['flows'][0]['state']
-
- if (self.flowadd == "ADDED"):
- self.logger.info("Flow is successfully added to OVS")
- return(response.status_code)
- else:
- return(404)
- else:
- return(response.status_code)
-####################################################################
-
- def createRouter(self):
- """Creation of Router."""
- Dicdata = {}
- if self.routername != '':
- Dicdata['name'] = "router1"
- if self.admin_state_up != '':
- Dicdata['admin_state_up'] = self.admin_state_up
-
- Dicdata = {'router': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = 'http://%s:9696/%s/routers.json' % (self.neutron_hostname,
- self.osver)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == CREATED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.debug("Creation of Router is successfull")
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.router_id = json1_data['router']['id']
- return(response.status_code)
- else:
- return(response.status_code)
-
- def attachInterface(self):
- """Attachment of instance ports to the Router."""
- url = ("http://%s:9696/%s/networks"
- "?name=admin_floating_net" % (self.neutron_hostname,
- self.osver))
- headers = {"Accept": "application/json", "X-Auth-Token": self.token_id}
- response = requests.get(url, headers=headers)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.net_name = json1_data['networks'][0]['name']
- if (self.net_name == "admin_floating_net"):
- self.pub_net_id = json1_data['networks'][0]['id']
- else:
- return(response.status_code)
- ############################################################
-
- self.logger.info("Attachment of Instance interface to Router")
- Dicdata = {}
- if self.subnetId != '':
- Dicdata['subnet_id'] = self.subnetId
-
- data = json.dumps(Dicdata, indent=4)
- url = ("http://%s:9696/%s/routers"
- "/%s/add_router_interface" % (self.neutron_hostname,
- self.osver,
- self.router_id))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("Interface attached successfull")
- else:
- return(response.status_code)
- ############################################################
- self.logger.info("Attachment of Gateway to Router")
-
- Dicdata1 = {}
- if self.pub_net_id != 0:
- Dicdata1['network_id'] = self.pub_net_id
-
- Dicdata1 = {'external_gateway_info': Dicdata1}
- Dicdata1 = {'router': Dicdata1}
- data = json.dumps(Dicdata1, indent=4)
- url = 'http://%s:9696/%s/routers/%s' % (self.neutron_hostname,
- self.osver,
- self.router_id)
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("Gateway Interface attached successfull")
- return(response.status_code)
- else:
- return(response.status_code)
-
- def addFloatingIp(self):
- """Attachment of Floating Ip to the Router."""
- for ip_num in range(0, 2):
- Dicdata = {}
- Dicdata['pool'] = "admin_floating_net"
-
- data = json.dumps(Dicdata, indent=4)
- url = ("http://%s:8774/v2.1/"
- "os-floating-ips" % (self.nova_hostname))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("Floating ip created successfully")
- json1_data = json.loads(response.content)
- self.logger.debug(json1_data)
- self.vm_public_ip.append(json1_data['floating_ip']['ip'])
- self.vm_public_id.append(json1_data['floating_ip']['id'])
- else:
- self.logger.error("Floating ip NOT created successfully")
-
- Dicdata1 = {}
- if self.address != '':
- Dicdata1['address'] = self.vm_public_ip[ip_num]
-
- Dicdata1 = {'addFloatingIp': Dicdata1}
- data = json.dumps(Dicdata1, indent=4)
- url = ("http://%s:8774/v2.1/"
- "servers/%s/action" % (self.nova_hostname,
- self.vm[ip_num]))
-
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.post(url, headers=headers, data=data)
- if(response.status_code == ACCEPTED):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.info("Public Ip successfully added to VM")
- else:
- return(response.status_code)
- return(response.status_code)
-
- def loginToVM(self):
- """Login to the VM to check NSH packets are received."""
- queue1 = "0"
-
- def vm0():
-
- s = pxssh.pxssh()
- hostname = self.vm_public_ip[0]
- s.login(hostname, self.cirros_username, self.cirros_password)
- s.sendline("ping -c 5 " + str(self.port_ip[2]))
- s.prompt() # match the prompt
-
- ping_re = re.search("transmitted.*received", s.before).group()
- x = re.split('\s+', ping_re)
- if (x[1] >= "1"):
- self.logger.info("Ping is Successfull")
- else:
- self.logger.info("Ping is NOT Successfull")
-
- def vm1(queue1):
- s = pxssh.pxssh()
- hostname = self.vm_public_ip[1]
- s.login(hostname, self.cirros_username, self.cirros_password)
- s.sendline('sudo ./firewall')
- s.prompt()
- output_pack = s.before
-
- if(output_pack.find("nshc") != -1):
- self.logger.info("The packet has reached VM2 Instance")
- queue1.put("1")
- else:
- self.logger.info("Packet not received in Instance")
- queue1.put("0")
-
- def ping(ip, timeout=300):
- while True:
- time.sleep(1)
- self.logger.debug("Pinging %s. Waiting for response..." % ip)
- response = os.system("ping -c 1 " + ip + " >/dev/null 2>&1")
- if response == 0:
- self.logger.info("Ping " + ip + " detected!")
- return 0
-
- elif timeout == 0:
- self.logger.info("Ping " + ip + " timeout reached.")
- return 1
- timeout -= 1
-
- result0 = ping(self.vm_public_ip[0])
- result1 = ping(self.vm_public_ip[1])
- if result0 == 0 and result1 == 0:
- time.sleep(300)
- queue1 = Queue()
- p1 = Process(target=vm1, args=(queue1, ))
- p1.start()
- p2 = Process(target=vm0)
- p2.start()
- p1.join(10)
- return (queue1.get())
- else:
- self.logger.error("Thread didnt run")
-
- """##################################################################"""
- """ ######################## Stats Functions ################# #####"""
-
- def portChainDeviceMap(self):
- """Check the PC Device Stats in the ONOS."""
- response = requests.get('http://' + self.onos_hostname +
- ':8181/onos/vtn/portChainDeviceMap/' +
- self.PC_id, auth=("karaf", "karaf"))
- if (response.status_code == OK):
- self.logger.info("PortChainDeviceMap is successfully Queries")
- return(response.status_code)
- else:
- return(response.status_code)
-
- def portChainSfMap(self):
- """Check the PC SF Map Stats in the ONOS."""
- response = requests.get('http://' + self.onos_hostname +
- ':8181/onos/vtn/portChainSfMap/' +
- self.PC_id, auth=("karaf", "karaf"))
- if (response.status_code == OK):
- self.logger.info("portChainSfMap is successfully Queries")
- return(response.status_code)
- else:
- return(response.status_code)
-
- """###################################################################"""
-
- def deletePortChain(self):
- """Deletion of PortChain."""
- url = ('http://' + self.neutron_hostname + ':9696/' +
- self.osver + '/sfc/port_chains/' + self.PC_id)
- headers = {"Accept": "application/json", "Content-Type":
- "application/json", "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- return(response.status_code)
- else:
- return(response.status_code)
-
- def deleteFlowClassifier(self):
- """Deletion of Flow Classifier."""
- url = ("http://%s:9696/%s/sfc/"
- "flow_classifiers/%s" % (self.neutron_hostname,
- self.osver,
- self.flow_class_if))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- return(response.status_code)
- else:
- return(response.status_code)
-
- def deletePortGroup(self):
- """Deletion of PortGroup."""
- for p in range(0, 1):
- url = ("http://%s:9696/%s/sfc/"
- "port_pair_groups/%s" % (self.neutron_hostname,
- self.osver,
- self.port_grp_id[p]))
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- else:
- return(response.status_code)
- return(response.status_code)
-
- def deletePortPair(self):
- """Deletion of Portpair."""
- for p in range(1, 2):
- url = ("http://%s:9696/%s/sfc/"
- "port_pairs/%s" % (self.neutron_hostname,
- self.osver,
- self.port_pair_id[0]))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- else:
- return(response.status_code)
- return(response.status_code)
-
- def cleanup(self):
- """Cleanup."""
- self.logger.info("Deleting VMs")
- for y in range(0, 3):
- url = ("http://%s:8774/v2.1/"
- "/servers/%s" % (self.nova_hostname,
- self.vm[y]))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.debug("VM" + str(y) + " is Deleted : ")
- time.sleep(10)
- else:
- return(response.status_code)
- self.logger.info("Deleting Ports")
- for x in range(self.i, self.numTerms):
- url = ('http://' + self.neutron_hostname + ':9696/' +
- self.osver + '/ports/' + self.port_num[x])
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.delete(url, headers=headers)
-
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- self.logger.debug("Port" + str(x) + " Deleted")
- else:
- return(response.status_code)
- self.logger.info("Deleting Router")
-
- Dicdata = {}
- Dicdata['external_gateway_info'] = {}
- Dicdata = {'router': Dicdata}
- data = json.dumps(Dicdata, indent=4)
- url = ("http://%s:9696/%s/"
- "/routers/%s" % (self.neutron_hostname,
- self.osver,
- self.router_id))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
- if (response.status_code == OK):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- Dicdata1 = {}
- if self.subnetId != '':
- Dicdata1['subnet_id'] = self.subnetId
- data = json.dumps(Dicdata1, indent=4)
- url = ("http://%s:9696/%s/routers/%s"
- "/remove_router_interface.json" % (self.neutron_hostname,
- self.osver,
- self.router_id))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.put(url, headers=headers, data=data)
- if (response.status_code == OK):
- url = ("http://%s:9696/%s/"
- "routers/%s" % (self.neutron_hostname,
- self.osver,
- self.router_id))
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- else:
- return(response.status_code)
- else:
- return(response.status_code)
- else:
- return(response.status_code)
-
- self.logger.info("Deleting Network")
- url = "http://%s:9696/%s/networks/%s" % (self.neutron_hostname,
- self.osver,
- self.net_id)
-
- headers = {"Accept": "application/json",
- "X-Auth-Token": self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- else:
- return(response.status_code)
-
- self.logger.info("Deleting Floating ip")
- for ip_num in range(0, 2):
- url = ("http://%s:9696/%s/floatingips"
- "/%s" % (self.neutron_hostname,
- self.osver,
- self.vm_public_id[ip_num]))
-
- headers = {"Accept": "application/json", "X-Auth-Token":
- self.token_id}
- response = requests.delete(url, headers=headers)
- if (response.status_code == NO_CONTENT):
- self.logger.debug(response.status_code)
- self.logger.debug(response.content)
- else:
- return(response.status_code)
- return(response.status_code)
diff --git a/functest/opnfv_tests/sdn/onos/teston/Readme.txt b/functest/opnfv_tests/sdn/onos/teston/Readme.txt
deleted file mode 100644
index 7393f59a..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/Readme.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-1.This is a basic test run about onos,we will make them better and better
-2.This test include two suites:
-(1)Test northbound(network/subnet/ports create/update/delete)
-(2)Ovsdb test,default configuration,openflow connection,vm go onlines.
-3.Later we will make a framework to do this test \ No newline at end of file
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py b/functest/opnfv_tests/sdn/onos/teston/adapters/client.py
deleted file mode 100644
index a88d2f06..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/client.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-Description:
- This file is used to run testcase
- lanqinglong@huawei.com
-
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-"""
-import json
-import logging
-import pexpect
-import requests
-import time
-
-from environment import Environment
-
-
-class Client(Environment):
-
- logger = logging.getLogger(__name__)
-
- def __init__(self):
- Environment.__init__(self)
- self.loginfo = Environment()
- self.testcase = ''
-
- def RunScript(self, handle, testname, timeout=300):
- """
- Run ONOS Test Script
- Parameters:
- testname: ONOS Testcase Name
- masterusername: The server username of running ONOS
- masterpassword: The server password of running ONOS
- """
- self.testcase = testname
- self.ChangeTestCasePara(testname, self.masterusername,
- self.masterpassword)
- runhandle = handle
- runtest = (self.home + "/OnosSystemTest/TestON/bin/cli.py run " +
- testname)
- runhandle.sendline(runtest)
- circletime = 0
- lastshowscreeninfo = ''
- while True:
- Result = runhandle.expect(["PEXPECT]#", pexpect.EOF,
- pexpect.TIMEOUT])
- curshowscreeninfo = runhandle.before
- if(len(lastshowscreeninfo) != len(curshowscreeninfo)):
- self.loginfo.log(str(curshowscreeninfo)
- [len(lastshowscreeninfo)::])
- lastshowscreeninfo = curshowscreeninfo
- if Result == 0:
- self.logger.info("Done!")
- return
- time.sleep(1)
- circletime += 1
- if circletime > timeout:
- break
- self.loginfo.log("Timeout when running the test, please check!")
-
- def onosstart(self):
- # This is the compass run machine user&pass,you need to modify
-
- self.logger.info("Test Begin.....")
- self.OnosConnectionSet()
- masterhandle = self.SSHlogin(self.localhost, self.masterusername,
- self.masterpassword)
- self.OnosEnvSetup(masterhandle)
- return masterhandle
-
- def onosclean(self, handle):
- self.SSHRelease(handle)
- self.loginfo.log('Release onos handle Successful')
-
- def push_results_to_db(self, payload, pushornot=1):
- if pushornot != 1:
- return 1
- url = self.Result_DB + "/results"
- params = {"project_name": "functest", "case_name": "ONOS-" +
- self.testcase, "pod_name": 'huawei-build-2',
- "details": payload}
-
- headers = {'Content-Type': 'application/json'}
- try:
- r = requests.post(url, data=json.dumps(params), headers=headers)
- self.loginfo.log(r)
- except:
- self.loginfo.log('Error pushing results into Database')
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py b/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
deleted file mode 100644
index a6d192ee..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/connection.py
+++ /dev/null
@@ -1,200 +0,0 @@
-"""
-Description:
- This file is used to make connections
- Include ssh & exchange public-key to each other so that
- it can run without password
-
- lanqinglong@huawei.com
-
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-"""
-import logging
-import os
-import pexpect
-import re
-
-from foundation import Foundation
-
-
-class Connection(Foundation):
-
- logger = logging.getLogger(__name__)
-
- def __init__(self):
- Foundation.__init__(self)
- self.loginfo = Foundation()
-
- def AddKnownHost(self, handle, ipaddr, username, password):
- """
- Add an user to known host,so that onos can login in with onos $ipaddr.
- parameters:
- ipaddr: ip address
- username: login user name
- password: login password
- """
- self.logger.info("Now Adding an user to known hosts " + ipaddr)
- login = handle
- login.sendline("ssh -l %s -p 8101 %s" % (username, ipaddr))
- index = 0
- while index != 2:
- index = login.expect(['assword:', 'yes/no', pexpect.EOF,
- pexpect.TIMEOUT])
- if index == 0:
- login.sendline(password)
- login.sendline("logout")
- index = login.expect(["closed", pexpect.EOF])
- if index == 0:
- self.loginfo.log("Add SSH Known Host Success!")
- break
- else:
- self.loginfo.log("Add SSH Known Host Failed! "
- "Please Check!")
- break
- login.prompt()
-
- if index == 1:
- login.sendline('yes')
-
- def GetEnvValue(self, handle, envname):
- """
- os.getenv only returns current user value
- GetEnvValue returns a environment value of
- current handle
- eg: GetEnvValue(handle,'HOME')
- """
- envhandle = handle
- envhandle.sendline('echo $' + envname)
- envhandle.prompt()
- reg = envname + '\r\n(.*)\r'
- envaluereg = re.compile(reg)
- envalue = envaluereg.search(envhandle.before)
- if envalue:
- return envalue.groups()[0]
- else:
- return None
-
- def Gensshkey(self, handle):
- """
- Generate ssh keys, used for some server have no sshkey.
- """
- self.logger.info("Now Generating SSH keys...")
- # Here file name may be id_rsa or id_ecdsa or others
- # So here will have a judgement
- keysub = handle
- filepath = self.GetEnvValue(keysub, 'HOME') + '/.ssh'
- filelist = os.listdir(filepath)
- for item in filelist:
- if 'id' in item:
- self.loginfo.log("SSH keys are exsit in ssh directory.")
- return True
- keysub.sendline("ssh-keygen -t rsa")
- Result = 0
- while Result != 2:
- Result = keysub.expect(["Overwrite", "Enter", pexpect.EOF,
- 'PEXPECT]#', pexpect.TIMEOUT])
- if Result == 0:
- keysub.sendline("y")
- if Result == 1 or Result == 2:
- keysub.sendline("\n")
- if Result == 3:
- self.loginfo.log("Generate SSH key success.")
- keysub.prompt()
- break
- if Result == 4:
- self.loginfo.log("Generate SSH key failed.")
- keysub.prompt()
- break
-
- def GetRootAuth(self, password):
- """
- Get root user
- parameters:
- password: root login password
- """
- self.logger.info("Now changing to user root")
- login = pexpect.spawn("su - root")
- index = 0
- while index != 2:
- index = login.expect(['assword:', "failure",
- pexpect.EOF, pexpect.TIMEOUT])
- if index == 0:
- login.sendline(password)
- if index == 1:
- self.loginfo.log("Change user to root failed.")
-
- login.interact()
-
- def ReleaseRootAuth(self):
- """
- Exit root user.
- """
- self.logger.info("Now Release user root")
- login = pexpect.spawn("exit")
- index = login.expect(['logout', pexpect.EOF, pexpect.TIMEOUT])
- if index == 0:
- self.loginfo.log("Release root user success.")
- if index == 1:
- self.loginfo.log("Release root user failed.")
-
- login.interact()
-
- def AddEnvIntoBashrc(self, envalue):
- """
- Add Env var into /etc/profile.
- parameters:
- envalue: environment value to add
- """
- self.logger.info("Now Adding bash environment")
- fileopen = open("/etc/profile", 'r')
- findContext = 1
- while findContext:
- findContext = fileopen.readline()
- result = findContext.find(envalue)
- if result != -1:
- break
- fileopen.close
- if result == -1:
- envAdd = open("/etc/profile", 'a+')
- envAdd.writelines("\n" + envalue)
- envAdd.close()
- self.loginfo.log("Add env to bashrc success!")
-
- def OnosRootPathChange(self, onospath):
- """
- Change ONOS root path in file:bash_profile
- onospath: path of onos root
- """
- self.logger.info("Now Changing ONOS Root Path")
- filepath = onospath + 'onos/tools/dev/bash_profile'
- line = open(filepath, 'r').readlines()
- lenall = len(line) - 1
- for i in range(lenall):
- if "export ONOS_ROOT" in line[i]:
- line[i] = 'export ONOS_ROOT=' + onospath + 'onos\n'
- NewFile = open(filepath, 'w')
- NewFile.writelines(line)
- NewFile.close
- self.logger.info("Done!")
-
- def OnosConnectionSet(self):
- """
- Intergrate for ONOS connection setup
- """
- if self.masterusername == 'root':
- filepath = '/root/'
- else:
- filepath = '/home/' + self.masterusername + '/'
- filepath = os.path.join(filepath, "onos/tools/dev/bash_profile")
- self.AddEnvIntoBashrc("source " + filepath + "\n")
- self.AddEnvIntoBashrc("export OCT=" + self.OCT)
- self.AddEnvIntoBashrc("export OC1=" + self.OC1)
- self.AddEnvIntoBashrc("export OC2=" + self.OC2)
- self.AddEnvIntoBashrc("export OC3=" + self.OC3)
- self.AddEnvIntoBashrc("export OCN=" + self.OCN)
- self.AddEnvIntoBashrc("export OCN2=" + self.OCN2)
- self.AddEnvIntoBashrc("export localhost=" + self.localhost)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py b/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
deleted file mode 100644
index 875a2dc9..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/environment.py
+++ /dev/null
@@ -1,286 +0,0 @@
-"""
-Description:
-This file is used to setup the running environment
-Include Download code,setup environment variable
-Set onos running config
-Set user name/password
-Onos-push-keys and so on
-lanqinglong@huawei.com
-
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-"""
-
-import logging
-import pexpect
-from pexpect import pxssh
-import re
-import os
-import sys
-import time
-
-from connection import Connection
-
-
-class Environment(Connection):
-
- logger = logging.getLogger(__name__)
-
- def __init__(self):
- Connection.__init__(self)
- self.loginfo = Connection()
- self.masterhandle = ''
- self.home = ''
-
- def DownLoadCode(self, handle, codeurl):
- """
- Download Code use 'git clone'
- parameters:
- handle: current working handle
- codeurl: clone code url
- """
- self.logger.info("Now loading test codes! Please wait in patient...")
- originalfolder = sys.path[0]
- self.logger.info(originalfolder)
- gitclone = handle
- gitclone.sendline("git clone " + codeurl)
- index = 0
- # increment = 0
- while index != 1 or index != 4:
- index = gitclone.expect(['already exists',
- 'esolving deltas: 100%',
- 'eceiving objects',
- 'Already up-to-date',
- 'npacking objects: 100%', pexpect.EOF])
-
- filefolder = self.home + '/' + codeurl.split('/')[-1].split('.')[0]
- if index == 0:
- os.chdir(filefolder)
- os.system('git pull')
- os.chdir(originalfolder)
- self.loginfo.log('Download code success!')
- break
- elif index == 1 or index == 4:
- self.loginfo.log('Download code success!')
- gitclone.sendline("mkdir onos")
- gitclone.prompt()
- gitclone.sendline("cp -rf " + filefolder + "/tools onos/")
- gitclone.prompt()
- break
- elif index == 2:
- os.write(1, gitclone.before)
- sys.stdout.flush()
- else:
- self.loginfo.log('Download code failed!')
- self.loginfo.log('Information before' + gitclone.before)
- break
- gitclone.prompt()
-
- def InstallDefaultSoftware(self, handle):
- """
- Install default software
- parameters:
- handle(input): current working handle
- """
- self.logger.info("Now Cleaning test environment")
- handle.sendline("sudo apt-get install -y mininet")
- handle.prompt()
- handle.sendline("sudo pip install configobj")
- handle.prompt()
- handle.sendline("sudo apt-get install -y sshpass")
- handle.prompt()
- handle.sendline("OnosSystemTest/TestON/bin/cleanup.sh")
- handle.prompt()
- time.sleep(5)
- self.loginfo.log('Clean environment success!')
-
- def OnosPushKeys(self, handle, cmd, password):
- """
- Using onos-push-keys to make ssh device without password
- parameters:
- handle(input): working handle
- cmd(input): onos-push-keys xxx(xxx is device)
- password(input): login in password
- """
- self.logger.info("Now Pushing Onos Keys:" + cmd)
- Pushkeys = handle
- Pushkeys.sendline(cmd)
- Result = 0
- while Result != 2:
- Result = Pushkeys.expect(["(yes/no)", "assword:", "PEXPECT]#",
- pexpect.EOF, pexpect.TIMEOUT])
- if(Result == 0):
- Pushkeys.sendline("yes")
- if(Result == 1):
- Pushkeys.sendline(password)
- if(Result == 2):
- self.loginfo.log("ONOS Push keys Success!")
- break
- if(Result == 3):
- self.loginfo.log("ONOS Push keys Error!")
- break
- time.sleep(2)
- Pushkeys.prompt()
- self.logger.info("Done!")
-
- def SetOnosEnvVar(self, handle, masterpass, agentpass):
- """
- Setup onos pushkeys to all devices(3+2)
- parameters:
- handle(input): current working handle
- masterpass: scripts running server's password
- agentpass: onos cluster&compute node password
- """
- self.logger.info("Now Setting test environment")
- for host in self.hosts:
- self.logger.info("try to connect " + str(host))
- result = self.CheckSshNoPasswd(host)
- if not result:
- self.logger.info(
- "ssh login failed,try to copy master publickey" +
- "to agent " + str(host))
- self.CopyPublicKey(host)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OCT, masterpass)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OC1, agentpass)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OC2, agentpass)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OC3, agentpass)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OCN, agentpass)
- self.OnosPushKeys(handle, "onos-push-keys " + self.OCN2, agentpass)
-
- def CheckSshNoPasswd(self, host):
- """
- Check master can connect agent with no password
- """
- login = pexpect.spawn("ssh " + str(host))
- index = 4
- while index == 4:
- index = login.expect(['(yes/no)', '>|#|\$',
- pexpect.EOF, pexpect.TIMEOUT])
- if index == 0:
- login.sendline("yes")
- index = 4
- if index == 1:
- self.loginfo.log("ssh connect to " + str(host) +
- " success,no need to copy ssh public key")
- return True
- login.interact()
- return False
-
- def ChangeOnosName(self, user, password):
- """
- Change onos name in envDefault file
- Because some command depend on this
- parameters:
- user: onos&compute node user
- password: onos&compute node password
- """
- self.logger.info("Now Changing ONOS name&password")
- filepath = self.home + '/onos/tools/build/envDefaults'
- line = open(filepath, 'r').readlines()
- lenall = len(line) - 1
- for i in range(lenall):
- if "ONOS_USER=" in line[i]:
- line[i] = line[i].replace("sdn", user)
- if "ONOS_GROUP" in line[i]:
- line[i] = line[i].replace("sdn", user)
- if "ONOS_PWD" in line[i]:
- line[i] = line[i].replace("rocks", password)
- NewFile = open(filepath, 'w')
- NewFile.writelines(line)
- NewFile.close
- self.logger.info("Done!")
-
- def ChangeTestCasePara(self, testcase, user, password):
- """
- When running test script, there\'s something need
- to change in every test folder\'s \*.param & \*.topo files
- user: onos\&compute node user
- password: onos\&compute node password
- """
- self.logger.info("Now Changing " + testcase + " name&password")
- if self.masterusername == 'root':
- filepath = '/root/'
- else:
- filepath = '/home/' + self.masterusername + '/'
- filepath = (filepath + "OnosSystemTest/TestON/tests/" +
- testcase + "/" + testcase + ".topo")
- line = open(filepath, 'r').readlines()
- lenall = len(line) - 1
- for i in range(lenall - 2):
- if("localhost" in line[i]) or ("OCT" in line[i]):
- line[i + 1] = re.sub(">\w+", ">" + user, line[i + 1])
- line[i + 2] = re.sub(">\w+", ">" + password, line[i + 2])
- if ("OC1" in line[i] or "OC2" in line[i] or "OC3" in line[i] or
- "OCN" in line[i] or "OCN2" in line[i]):
- line[i + 1] = re.sub(">\w+", ">root", line[i + 1])
- line[i + 2] = re.sub(">\w+", ">root", line[i + 2])
- NewFile = open(filepath, 'w')
- NewFile.writelines(line)
- NewFile.close
-
- def SSHlogin(self, ipaddr, username, password):
- """
- SSH login provide a connection to destination.
- parameters:
- ipaddr: ip address
- username: login user name
- password: login password
- return: handle
- """
- login = pxssh.pxssh()
- login.login(ipaddr, username, password, original_prompt='[$#>]')
- # send command ls -l
- login.sendline('ls -l')
- # match prompt
- login.prompt()
- self.logger.info("SSH login " + ipaddr + " success!")
- return login
-
- def SSHRelease(self, handle):
- # Release ssh
- handle.logout()
-
- def CopyOnostoTestbin(self):
- sourcefile = self.cipath + '/dependencies/onos'
- destifile = self.home + '/onos/tools/test/bin/'
- os.system('pwd')
- runcommand = 'cp ' + sourcefile + ' ' + destifile
- os.system(runcommand)
-
- def CopyPublicKey(self, host):
- output = os.popen('cat /root/.ssh/id_rsa.pub')
- publickey = output.read().strip('\n')
- tmphandle = self.SSHlogin(self.installer_master,
- self.installer_master_username,
- self.installer_master_password)
- tmphandle.sendline("ssh " + host + " -T \'echo " +
- str(publickey) + ">>/root/.ssh/authorized_keys\'")
- tmphandle.prompt()
- self.SSHRelease(tmphandle)
- self.logger.info("Add OCT PublicKey to " + host + " success")
-
- def OnosEnvSetup(self, handle):
- """
- Onos Environment Setup function
- """
- self.Gensshkey(handle)
- self.home = self.GetEnvValue(handle, 'HOME')
- self.AddKnownHost(handle, self.OC1, "karaf", "karaf")
- self.AddKnownHost(handle, self.OC2, "karaf", "karaf")
- self.AddKnownHost(handle, self.OC3, "karaf", "karaf")
- self.DownLoadCode(handle,
- 'https://github.com/wuwenbin2/OnosSystemTest.git')
- # self.DownLoadCode(handle, 'https://gerrit.onosproject.org/onos')
- if self.masterusername == 'root':
- filepath = '/root/'
- else:
- filepath = '/home/' + self.masterusername + '/'
- self.OnosRootPathChange(filepath)
- self.CopyOnostoTestbin()
- self.ChangeOnosName(self.agentusername, self.agentpassword)
- self.InstallDefaultSoftware(handle)
- self.SetOnosEnvVar(handle, self.masterpassword, self.agentpassword)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py b/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py
deleted file mode 100644
index aed98ee4..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/foundation.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-Description:
- This file include basis functions
- lanqinglong@huawei.com
-
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-"""
-
-import datetime
-import logging
-import os
-import re
-import time
-
-from functest.utils.constants import CONST
-
-
-class Foundation(object):
-
- def __init__(self):
-
- # currentpath = os.getcwd()
- currentpath = ('{0}/sdn/onos/teston/ci'
- .format(CONST.__getattribute__('dir_functest_data')))
- self.cipath = currentpath
- self.logdir = os.path.join(currentpath, 'log')
- self.workhome = currentpath[0: currentpath.rfind('opnfv_tests') - 1]
- self.Result_DB = ''
- filename = time.strftime('%Y-%m-%d-%H-%M-%S') + '.log'
- self.logfilepath = os.path.join(self.logdir, filename)
- self.starttime = datetime.datetime.now()
-
- def log(self, loginfo):
- """
- Record log in log directory for deploying test environment
- parameters:
- loginfo(input): record info
- """
- logging.basicConfig(level=logging.INFO,
- format='%(asctime)s %(filename)s:%(message)s',
- datefmt='%d %b %Y %H:%M:%S',
- filename=self.logfilepath,
- filemode='w')
- filelog = logging.FileHandler(self.logfilepath)
- logging.getLogger('Functest').addHandler(filelog)
- logging.info(loginfo)
-
- def getdefaultpara(self):
- """
- Get Default Parameters value
- """
- self.Result_DB = CONST.__getattribute__("results_test_db_url")
- self.masterusername = CONST.__getattribute__('ONOS_onosbench_username')
- self.masterpassword = CONST.__getattribute__('ONOS_onosbench_password')
- self.agentusername = CONST.__getattribute__('ONOS_onoscli_username')
- self.agentpassword = CONST.__getattribute__('ONOS_onoscli_password')
- self.runtimeout = CONST.__getattribute__('ONOS_runtimeout')
- self.OCT = CONST.__getattribute__('ONOS_environment_OCT')
- self.OC1 = CONST.__getattribute__('ONOS_environment_OC1')
- self.OC2 = CONST.__getattribute__('ONOS_environment_OC2')
- self.OC3 = CONST.__getattribute__('ONOS_environment_OC3')
- self.OCN = CONST.__getattribute__('ONOS_environment_OCN')
- self.OCN2 = CONST.__getattribute__('ONOS_environment_OCN2')
- self.installer_master = CONST.__getattribute__(
- 'ONOS_environment_installer_master')
- self.installer_master_username = (
- CONST.__getattribute__(
- 'ONOS_environment_installer_master_username'))
- self.installer_master_password = (
- CONST.__getattribute__(
- 'ONOS_environment_installer_master_password'))
- self.hosts = [self.OC1, self.OCN, self.OCN2]
- self.localhost = self.OCT
-
- def GetResult(self):
- cmd = "cat " + self.logfilepath + " | grep Fail"
- Resultbuffer = os.popen(cmd).read()
- duration = datetime.datetime.now() - self.starttime
- time.sleep(2)
-
- if re.search("[1-9]+", Resultbuffer):
- self.log("Testcase Fails\n" + Resultbuffer)
- Result = "POK"
- else:
- self.log("Testcases Pass")
- Result = "OK"
- payload = {'timestart': str(self.starttime),
- 'duration': str(duration), 'status': Result}
-
- return payload
diff --git a/functest/opnfv_tests/sdn/onos/teston/dependencies/onos b/functest/opnfv_tests/sdn/onos/teston/dependencies/onos
deleted file mode 100644
index bb02fa89..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/dependencies/onos
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# -----------------------------------------------------------------------------
-# ONOS remote command-line client.
-# -----------------------------------------------------------------------------
-#
-# 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
-#
-
-[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
-. /root/.bashrc
-. $ONOS_ROOT/tools/build/envDefaults
-. $ONOS_ROOT/tools/test/bin/find-node.sh
-
-[ "$1" = "-w" ] && shift && onos-wait-for-start $1
-
-[ -n "$1" ] && OCI=$(find_node $1) && shift
-
-if which client 1>/dev/null 2>&1 && [ -z "$ONOS_USE_SSH" ]; then
- # Use Karaf client only if we can and are allowed to
- unset KARAF_HOME
- client -h $OCI -u karaf "$@" 2>/dev/null
-else
- # Otherwise use raw ssh; strict checking is off for dev environments only
- #ssh -p 8101 -o StrictHostKeyChecking=no $OCI "$@"
- sshpass -p karaf ssh -l karaf -p 8101 $OCI "$@"
-fi
diff --git a/functest/opnfv_tests/sdn/onos/teston/log/gitignore b/functest/opnfv_tests/sdn/onos/teston/log/gitignore
deleted file mode 100644
index e69de29b..00000000
--- a/functest/opnfv_tests/sdn/onos/teston/log/gitignore
+++ /dev/null
diff --git a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
index 1c3f69c6..8851f7a4 100644
--- a/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
+++ b/functest/opnfv_tests/vnf/ims/clearwater_ims_base.py
@@ -10,7 +10,9 @@ import json
import logging
import os
import pkg_resources
+import shlex
import shutil
+import subprocess
import time
import requests
@@ -109,18 +111,17 @@ class ClearwaterOnBoardingBase(vnf.VnfOnBoarding):
bono_ip=None, ellis_ip=None,
signup_code='secret'):
self.logger.info('Run Clearwater live test')
- nameservers = ft_utils.get_resolvconf_ns()
- resolvconf = ['{0}{1}{2}'.format(os.linesep, 'nameserver ', ns)
- for ns in nameservers]
- self.logger.debug('resolvconf: %s', resolvconf)
dns_file = '/etc/resolv.conf'
dns_file_bak = '/etc/resolv.conf.bak'
+ self.logger.debug('Backup %s -> %s', dns_file, dns_file_bak)
shutil.copy(dns_file, dns_file_bak)
- script = ('echo -e "nameserver {0}{1}" > {2};'
- 'cd {3};'
- 'rake test[{4}] SIGNUP_CODE={5}'
- .format(dns_ip,
- ''.join(resolvconf),
+ cmd = ("dnsmasq -d -u root --server=/clearwater.opnfv/{0} "
+ "-r /etc/resolv.conf.bak".format(dns_ip))
+ dnsmasq_process = subprocess.Popen(shlex.split(cmd))
+ script = ('echo -e "nameserver {0}" > {1};'
+ 'cd {2};'
+ 'rake test[{3}] SIGNUP_CODE={4}'
+ .format('127.0.0.1',
dns_file,
self.test_dir,
public_domain,
@@ -135,7 +136,7 @@ class ClearwaterOnBoardingBase(vnf.VnfOnBoarding):
ft_utils.execute_command(cmd,
error_msg='Clearwater live test failed',
output_file=output_file)
-
+ dnsmasq_process.kill()
with open(dns_file_bak, 'r') as bak_file:
result = bak_file.read()
with open(dns_file, 'w') as f:
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.py b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
index 2733bc3a..b98cbe9a 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.py
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.py
@@ -115,15 +115,15 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
# needs some images
self.__logger.info("Upload some OS images if it doesn't exist")
- for image_name, image_url in self.images.iteritems():
- self.__logger.info("image: %s, url: %s", image_name, image_url)
- if image_url and image_name:
+ for image_name, image_file in self.images.iteritems():
+ self.__logger.info("image: %s, file: %s", image_name, image_file)
+ if image_file and image_name:
image_creator = OpenStackImage(
self.snaps_creds,
ImageSettings(name=image_name,
image_user='cloud',
img_format='qcow2',
- url=image_url))
+ image_file=image_file))
image_creator.create()
# self.created_object.append(image_creator)
@@ -286,6 +286,7 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
external_network_name=ext_net_name,
network_name=network_settings.name
))
+ self.result = 1/3 * 100
return True
def deploy_vnf(self):
@@ -335,6 +336,7 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
self.__logger.info(execution)
if execution.status == 'terminated':
self.details['vnf'].update(status='PASS', duration=duration)
+ self.result += 1/3 * 100
result = True
else:
self.details['vnf'].update(status='FAIL', duration=duration)
@@ -360,12 +362,20 @@ class CloudifyIms(clearwater_ims_base.ClearwaterOnBoardingBase):
dns_ip=dns_ip,
public_domain=self.vnf['inputs']["public_domain"])
duration = time.time() - start_time
- short_result = sig_test_format(vims_test_result)
+ short_result, nb_test = sig_test_format(vims_test_result)
self.__logger.info(short_result)
- self.details['test_vnf'].update(status='PASS',
- result=short_result,
+ self.details['test_vnf'].update(result=short_result,
full_result=vims_test_result,
duration=duration)
+ try:
+ vnf_test_rate = short_result['passed'] / nb_test
+ # orchestrator + vnf + test_vnf
+ self.result += vnf_test_rate / 3 * 100
+ except ZeroDivisionError:
+ self.__logger.error("No test has been executed")
+ self.details['test_vnf'].update(status='FAIL')
+ return False
+
return True
def clean(self):
@@ -506,11 +516,12 @@ def sig_test_format(sig_test):
nb_failures += 1
elif data_test['result'] == "Skipped":
nb_skipped += 1
- total_sig_test_result = {}
- total_sig_test_result['passed'] = nb_passed
- total_sig_test_result['failures'] = nb_failures
- total_sig_test_result['skipped'] = nb_skipped
- return total_sig_test_result
+ short_sig_test_result = {}
+ short_sig_test_result['passed'] = nb_passed
+ short_sig_test_result['failures'] = nb_failures
+ short_sig_test_result['skipped'] = nb_skipped
+ nb_test = nb_passed + nb_skipped
+ return (short_sig_test_result, nb_test)
def run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"):
diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
index 1b239468..ad7fa70a 100644
--- a/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
+++ b/functest/opnfv_tests/vnf/ims/cloudify_ims.yaml
@@ -1,6 +1,6 @@
tenant_images:
- ubuntu_14.04: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
- cloudify_manager_4.0: http://repository.cloudifysource.org/cloudify/4.0.1/sp-release/cloudify-manager-premium-4.0.1.qcow2
+ ubuntu_14.04: /home/opnfv/functest/images/trusty-server-cloudimg-amd64-disk1.img
+ cloudify_manager_4.0: /home/opnfv/functest/images/cloudify-manager-premium-4.0.1.qcow2
orchestrator:
name: cloudify
version: '4.0'
diff --git a/functest/opnfv_tests/vnf/ims/orchestra.yaml b/functest/opnfv_tests/vnf/ims/orchestra.yaml
index 7b43c001..4cd18e72 100644
--- a/functest/opnfv_tests/vnf/ims/orchestra.yaml
+++ b/functest/opnfv_tests/vnf/ims/orchestra.yaml
@@ -1,10 +1,10 @@
tenant_images:
orchestrator:
- ubuntu-14.04-server-cloudimg-amd64-disk1: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
+ ubuntu-14.04-server-cloudimg-amd64-disk1: /home/opnfv/functest/images/trusty-server-cloudimg-amd64-disk1.img
orchestra_openims:
- openims: http://marketplace.openbaton.org:8082/api/v1/images/52e2ccc0-1dce-4663-894d-28aab49323aa/img
+ openims: /home/opnfv/functest/images/img
orchestra_clearwaterims:
- ubuntu-14.04-server-cloudimg-amd64-disk1: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img
+ ubuntu-14.04-server-cloudimg-amd64-disk1: /home/opnfv/functest/images/trusty-server-cloudimg-amd64-disk1.img
mano:
name: OpenBaton
version: '3.2.0'
@@ -58,4 +58,4 @@ orchestra_clearwaterims:
ram_min: 2048
disk: 5
vcpus: 2
- test: \ No newline at end of file
+ test:
diff --git a/functest/opnfv_tests/vnf/ims/orchestra_clearwaterims.py b/functest/opnfv_tests/vnf/ims/orchestra_clearwaterims.py
index c1b88c66..c924a347 100644
--- a/functest/opnfv_tests/vnf/ims/orchestra_clearwaterims.py
+++ b/functest/opnfv_tests/vnf/ims/orchestra_clearwaterims.py
@@ -194,9 +194,7 @@ class ClearwaterImsVnf(vnf.VnfOnBoarding):
if not os.path.exists(self.data_dir):
os.makedirs(self.data_dir)
- self.images = get_config(
- "tenant_images.%s" %
- self.case_name, config_file)
+ self.images = get_config("tenant_images.orchestrator", config_file)
self.images.update(
get_config(
"tenant_images.%s" %
@@ -225,15 +223,16 @@ class ClearwaterImsVnf(vnf.VnfOnBoarding):
def prepare_images(self):
"""Upload images if they doen't exist yet"""
self.logger.info("Upload images if they doen't exist yet")
- for image_name, image_url in self.images.iteritems():
- self.logger.info("image: %s, url: %s", image_name, image_url)
- if image_url and image_name:
+ for image_name, image_file in self.images.iteritems():
+ self.logger.info("image: %s, file: %s", image_name, image_file)
+ if image_file and image_name:
image = OpenStackImage(
self.snaps_creds,
ImageSettings(name=image_name,
image_user='cloud',
img_format='qcow2',
- url=image_url))
+ image_file=image_file,
+ public=True))
image.create()
# self.created_resources.append(image);
@@ -659,8 +658,9 @@ class ClearwaterImsVnf(vnf.VnfOnBoarding):
try:
neutron_client = os_utils.get_neutron_client(self.creds)
self.logger.info("Deleting Open Baton Port...")
- port = snaps_utils.neutron_utils.get_port_by_name(
- neutron_client, '%s_port' % self.case_name)
+ port = snaps_utils.neutron_utils.get_port(
+ neutron_client,
+ port_name='%s_port' % self.case_name)
snaps_utils.neutron_utils.delete_port(neutron_client, port)
time.sleep(10)
except Exception as exc:
diff --git a/functest/opnfv_tests/vnf/ims/orchestra_openims.py b/functest/opnfv_tests/vnf/ims/orchestra_openims.py
index d9d4d8a1..aae35146 100644
--- a/functest/opnfv_tests/vnf/ims/orchestra_openims.py
+++ b/functest/opnfv_tests/vnf/ims/orchestra_openims.py
@@ -194,8 +194,7 @@ class OpenImsVnf(vnf.VnfOnBoarding):
if not os.path.exists(self.data_dir):
os.makedirs(self.data_dir)
- self.images = get_config("tenant_images.%s" %
- self.case_name, config_file)
+ self.images = get_config("tenant_images.orchestrator", config_file)
self.images.update(get_config("tenant_images.%s" %
self.case_name, config_file))
@@ -219,15 +218,16 @@ class OpenImsVnf(vnf.VnfOnBoarding):
def prepare_images(self):
"""Upload images if they doen't exist yet"""
self.logger.info("Upload images if they doen't exist yet")
- for image_name, image_url in self.images.iteritems():
- self.logger.info("image: %s, url: %s", image_name, image_url)
- if image_url and image_name:
+ for image_name, image_file in self.images.iteritems():
+ self.logger.info("image: %s, file: %s", image_name, image_file)
+ if image_file and image_name:
image = OpenStackImage(
self.snaps_creds,
ImageSettings(name=image_name,
image_user='cloud',
img_format='qcow2',
- url=image_url))
+ image_file=image_file,
+ public=True))
image.create()
# self.created_resources.append(image);
@@ -692,8 +692,9 @@ class OpenImsVnf(vnf.VnfOnBoarding):
try:
neutron_client = os_utils.get_neutron_client(self.creds)
self.logger.info("Deleting Open Baton Port...")
- port = snaps_utils.neutron_utils.get_port_by_name(
- neutron_client, '%s_port' % self.case_name)
+ port = snaps_utils.neutron_utils.get_port(
+ neutron_client,
+ port_name='%s_port' % self.case_name)
snaps_utils.neutron_utils.delete_port(neutron_client, port)
time.sleep(10)
except Exception as exc:
diff --git a/functest/opnfv_tests/vnf/router/cloudify_vrouter.py b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py
new file mode 100644
index 00000000..c3cccb98
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/cloudify_vrouter.py
@@ -0,0 +1,542 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vrouter testcase implementation."""
+
+import logging
+import os
+import time
+
+from cloudify_rest_client import CloudifyClient
+from cloudify_rest_client.executions import Execution
+from scp import SCPClient
+import yaml
+
+from functest.opnfv_tests.openstack.snaps import snaps_utils
+import functest.opnfv_tests.vnf.router.vrouter_base as vrouter_base
+from functest.utils.constants import CONST
+import functest.utils.openstack_utils as os_utils
+
+from git import Repo
+
+from snaps.openstack.os_credentials import OSCreds
+from snaps.openstack.create_network import (NetworkSettings, SubnetSettings,
+ OpenStackNetwork)
+from snaps.openstack.create_security_group import (SecurityGroupSettings,
+ SecurityGroupRuleSettings,
+ Direction, Protocol,
+ OpenStackSecurityGroup)
+from snaps.openstack.create_router import RouterSettings, OpenStackRouter
+from snaps.openstack.create_instance import (VmInstanceSettings,
+ FloatingIpSettings,
+ OpenStackVmInstance)
+from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
+from snaps.openstack.create_image import ImageSettings, OpenStackImage
+from snaps.openstack.create_keypairs import KeypairSettings, OpenStackKeypair
+from snaps.openstack.create_network import PortSettings
+import snaps.openstack.utils.glance_utils as glance_utils
+
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+
+__author__ = "Shuya Nakama <shuya.nakama@okinawaopenlabs.org>"
+
+
+class CloudifyVrouter(vrouter_base.VrouterOnBoardingBase):
+ """vrouter testcase deployed with Cloudify Orchestrator."""
+
+ __logger = logging.getLogger(__name__)
+ name = __name__
+
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "vyos_vrouter"
+ super(CloudifyVrouter, self).__init__(**kwargs)
+
+ # Retrieve the configuration
+ try:
+ self.config = CONST.__getattribute__(
+ 'vnf_{}_config'.format(self.case_name))
+ except Exception:
+ raise Exception("VNF config file not found")
+
+ self.snaps_creds = ''
+ self.created_object = []
+
+ self.cfy_manager_ip = ''
+ self.util_info = {}
+ self.deployment_name = ''
+
+ config_file = os.path.join(self.case_dir, self.config)
+ self.orchestrator = dict(
+ requirements=get_config("orchestrator.requirements", config_file),
+ )
+ self.details['orchestrator'] = dict(
+ name=get_config("orchestrator.name", config_file),
+ version=get_config("orchestrator.version", config_file),
+ status='ERROR',
+ result=''
+ )
+ self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
+ self.__logger.debug("name = %s", self.name)
+ self.vnf = dict(
+ descriptor=get_config("vnf.descriptor", config_file),
+ inputs=get_config("vnf.inputs", config_file),
+ requirements=get_config("vnf.requirements", config_file)
+ )
+ self.details['vnf'] = dict(
+ descriptor_version=self.vnf['descriptor']['version'],
+ name=get_config("vnf.name", config_file),
+ version=get_config("vnf.version", config_file),
+ )
+ self.__logger.debug("VNF configuration: %s", self.vnf)
+
+ self.util = Utilvnf()
+
+ self.details['test_vnf'] = dict(
+ name=get_config("vnf_test_suite.name", config_file),
+ version=get_config("vnf_test_suite.version", config_file)
+ )
+ self.images = get_config("tenant_images", config_file)
+ self.__logger.info("Images needed for vrouter: %s", self.images)
+
+ def prepare(self):
+ super(CloudifyVrouter, self).prepare()
+
+ self.__logger.info("Additional pre-configuration steps")
+
+ self.snaps_creds = OSCreds(
+ username=self.creds['username'],
+ password=self.creds['password'],
+ auth_url=self.creds['auth_url'],
+ project_name=self.creds['tenant'],
+ identity_api_version=int(os_utils.get_keystone_client_version()))
+
+ self.util.set_credentials(self.creds["username"],
+ self.creds["password"],
+ self.creds["auth_url"],
+ self.creds["tenant"])
+
+ # needs some images
+ self.__logger.info("Upload some OS images if it doesn't exist")
+ for image_name, image_file in self.images.iteritems():
+ self.__logger.info("image: %s, file: %s", image_name, image_file)
+ if image_file and image_name:
+ image_creator = OpenStackImage(
+ self.snaps_creds,
+ ImageSettings(name=image_name,
+ image_user='cloud',
+ img_format='qcow2',
+ image_file=image_file))
+ image_creator.create()
+ self.created_object.append(image_creator)
+
+ def deploy_orchestrator(self):
+ """
+ Deploy Cloudify Manager.
+ network, security group, fip, VM creation
+ """
+ # network creation
+
+ start_time = time.time()
+ self.__logger.info("Creating keypair ...")
+ kp_file = os.path.join(self.data_dir, "cloudify_vrouter.pem")
+ keypair_settings = KeypairSettings(name='cloudify_vrouter_kp',
+ private_filepath=kp_file)
+ keypair_creator = OpenStackKeypair(self.snaps_creds, keypair_settings)
+ keypair_creator.create()
+ self.created_object.append(keypair_creator)
+
+ self.__logger.info("Creating full network ...")
+ subnet_settings = SubnetSettings(name='cloudify_vrouter_subnet',
+ cidr='10.67.79.0/24')
+ network_settings = NetworkSettings(name='cloudify_vrouter_network',
+ subnet_settings=[subnet_settings])
+ network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
+ network_creator.create()
+ self.created_object.append(network_creator)
+ ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
+ router_creator = OpenStackRouter(
+ self.snaps_creds,
+ RouterSettings(
+ name='cloudify_vrouter_router',
+ external_gateway=ext_net_name,
+ internal_subnets=[subnet_settings.name]))
+ router_creator.create()
+ self.created_object.append(router_creator)
+
+ # security group creation
+ self.__logger.info("Creating security group for cloudify manager vm")
+ sg_rules = list()
+ sg_rules.append(
+ SecurityGroupRuleSettings(sec_grp_name="sg-cloudify-manager",
+ direction=Direction.ingress,
+ protocol=Protocol.tcp, port_range_min=1,
+ port_range_max=65535))
+ sg_rules.append(
+ SecurityGroupRuleSettings(sec_grp_name="sg-cloudify-manager",
+ direction=Direction.ingress,
+ protocol=Protocol.udp, port_range_min=1,
+ port_range_max=65535))
+
+ security_group_creator = OpenStackSecurityGroup(
+ self.snaps_creds,
+ SecurityGroupSettings(
+ name="sg-cloudify-manager",
+ rule_settings=sg_rules))
+
+ security_group_creator.create()
+ self.created_object.append(security_group_creator)
+
+ # orchestrator VM flavor
+ self.__logger.info("Get or create flavor for cloudify manager vm ...")
+
+ flavor_settings = FlavorSettings(
+ name=self.orchestrator['requirements']['flavor']['name'],
+ ram=self.orchestrator['requirements']['flavor']['ram_min'],
+ disk=50,
+ vcpus=2)
+ flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
+ flavor_creator.create()
+ self.created_object.append(flavor_creator)
+ image_settings = ImageSettings(
+ name=self.orchestrator['requirements']['os_image'],
+ image_user='centos',
+ exists=True)
+
+ port_settings = PortSettings(name='cloudify_manager_port',
+ network_name=network_settings.name)
+
+ manager_settings = VmInstanceSettings(
+ name='cloudify_manager',
+ flavor=flavor_settings.name,
+ port_settings=[port_settings],
+ security_group_names=[
+ security_group_creator.sec_grp_settings.name],
+ floating_ip_settings=[FloatingIpSettings(
+ name='cloudify_manager_fip',
+ port_name=port_settings.name,
+ router_name=router_creator.router_settings.name)])
+
+ manager_creator = OpenStackVmInstance(self.snaps_creds,
+ manager_settings,
+ image_settings,
+ keypair_settings)
+
+ self.__logger.info("Creating cloudify manager VM")
+ manager_creator.create()
+ self.created_object.append(manager_creator)
+
+ public_auth_url = os_utils.get_endpoint('identity')
+
+ self.__logger.info("Set creds for cloudify manager")
+ cfy_creds = dict(keystone_username=self.tenant_name,
+ keystone_password=self.tenant_name,
+ keystone_tenant_name=self.tenant_name,
+ keystone_url=public_auth_url)
+
+ cfy_client = CloudifyClient(host=manager_creator.get_floating_ip().ip,
+ username='admin',
+ password='admin',
+ tenant='default_tenant')
+
+ self.orchestrator['object'] = cfy_client
+
+ self.cfy_manager_ip = manager_creator.get_floating_ip().ip
+
+ self.__logger.info("Attemps running status of the Manager")
+ cfy_status = None
+ retry = 10
+ while str(cfy_status) != 'running' and retry:
+ try:
+ cfy_status = cfy_client.manager.get_status()['status']
+ self.__logger.debug("The current manager status is %s",
+ cfy_status)
+ except Exception: # pylint: disable=broad-except
+ self.__logger.warning("Cloudify Manager isn't " +
+ "up and running. Retrying ...")
+ retry = retry - 1
+ time.sleep(30)
+
+ if str(cfy_status) == 'running':
+ self.__logger.info("Cloudify Manager is up and running")
+ else:
+ raise Exception("Cloudify Manager isn't up and running")
+
+ self.__logger.info("Put OpenStack creds in manager")
+ secrets_list = cfy_client.secrets.list()
+ for k, val in cfy_creds.iteritems():
+ if not any(d.get('key', None) == k for d in secrets_list):
+ cfy_client.secrets.create(k, val)
+ else:
+ cfy_client.secrets.update(k, val)
+
+ duration = time.time() - start_time
+
+ self.__logger.info("Put private keypair in manager")
+ if manager_creator.vm_ssh_active(block=True):
+ ssh = manager_creator.ssh_client()
+ scp = SCPClient(ssh.get_transport(), socket_timeout=15.0)
+ scp.put(kp_file, '~/')
+ cmd = "sudo cp ~/cloudify_vrouter.pem /etc/cloudify/"
+ run_blocking_ssh_command(ssh, cmd)
+ cmd = "sudo chmod 444 /etc/cloudify/cloudify_vrouter.pem"
+ run_blocking_ssh_command(ssh, cmd)
+ cmd = "sudo yum install -y gcc python-devel"
+ run_blocking_ssh_command(
+ ssh, cmd, "Unable to install packages on manager")
+
+ self.details['orchestrator'].update(status='PASS', duration=duration)
+
+ self.vnf['inputs'].update(dict(external_network_name=ext_net_name))
+
+ return True
+
+ def deploy_vnf(self):
+ start_time = time.time()
+
+ self.__logger.info("Upload VNFD")
+ cfy_client = self.orchestrator['object']
+ descriptor = self.vnf['descriptor']
+ self.deployment_name = descriptor.get('name')
+
+ vrouter_blueprint_dir = os.path.join(self.data_dir,
+ self.util.blueprint_dir)
+ if not os.path.exists(vrouter_blueprint_dir):
+ Repo.clone_from(descriptor.get('url'),
+ vrouter_blueprint_dir,
+ branch=descriptor.get('version'))
+
+ cfy_client.blueprints.upload(vrouter_blueprint_dir +
+ self.util.blueprint_file_name,
+ descriptor.get('name'))
+
+ self.__logger.info("Get or create flavor for vrouter")
+ flavor_settings = FlavorSettings(
+ name=self.vnf['requirements']['flavor']['name'],
+ ram=self.vnf['requirements']['flavor']['ram_min'],
+ disk=25,
+ vcpus=1)
+ flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
+ flavor = flavor_creator.create()
+ self.created_object.append(flavor_creator)
+
+ # set image name
+ glance = glance_utils.glance_client(self.snaps_creds)
+ image = glance_utils.get_image(glance,
+ "vyos1.1.7")
+ self.vnf['inputs'].update(dict(target_vnf_image_id=image.id))
+ self.vnf['inputs'].update(dict(reference_vnf_image_id=image.id))
+
+ # set flavor id
+ self.vnf['inputs'].update(dict(target_vnf_flavor_id=flavor.id))
+ self.vnf['inputs'].update(dict(reference_vnf_flavor_id=flavor.id))
+
+ self.vnf['inputs'].update(dict(keystone_username=self.tenant_name))
+ self.vnf['inputs'].update(dict(keystone_password=self.tenant_name))
+ self.vnf['inputs'].update(dict(keystone_tenant_name=self.tenant_name))
+ self.vnf['inputs'].update(
+ dict(keystone_url=os_utils.get_endpoint('identity')))
+
+ self.__logger.info("Create VNF Instance")
+ cfy_client.deployments.create(descriptor.get('name'),
+ descriptor.get('name'),
+ self.vnf.get('inputs'))
+
+ wait_for_execution(cfy_client,
+ get_execution_id(
+ cfy_client, descriptor.get('name')),
+ self.__logger,
+ timeout=7200)
+
+ self.__logger.info("Start the VNF Instance deployment")
+ execution = cfy_client.executions.start(descriptor.get('name'),
+ 'install')
+ # Show execution log
+ execution = wait_for_execution(cfy_client, execution, self.__logger)
+
+ duration = time.time() - start_time
+
+ self.__logger.info(execution)
+ if execution.status == 'terminated':
+ self.details['vnf'].update(status='PASS', duration=duration)
+ result = True
+ else:
+ self.details['vnf'].update(status='FAIL', duration=duration)
+ result = False
+ return result
+
+ def test_vnf(self):
+ cfy_client = self.orchestrator['object']
+ credentials = {"username": self.creds["username"],
+ "password": self.creds["password"],
+ "auth_url": self.creds["auth_url"],
+ "tenant_name": self.creds["tenant"],
+ "region_name": os.environ['OS_REGION_NAME']}
+
+ self.util_info = {"credentials": credentials,
+ "cfy": cfy_client,
+ "vnf_data_dir": self.util.vnf_data_dir}
+
+ start_time = time.time()
+
+ result, test_result_data = super(CloudifyVrouter, self).test_vnf()
+
+ duration = time.time() - start_time
+
+ if result:
+ self.details['test_vnf'].update(status='PASS',
+ result='OK',
+ full_result=test_result_data,
+ duration=duration)
+ else:
+ self.details['test_vnf'].update(status='FAIL',
+ result='NG',
+ full_result=test_result_data,
+ duration=duration)
+
+ return True
+
+ def clean(self):
+ try:
+ cfy_client = self.orchestrator['object']
+ dep_name = self.vnf['descriptor'].get('name')
+ # kill existing execution
+ self.__logger.info('Deleting the current deployment')
+ exec_list = cfy_client.executions.list(dep_name)
+ for execution in exec_list:
+ if execution['status'] == "started":
+ try:
+ cfy_client.executions.cancel(execution['id'],
+ force=True)
+ except: # pylint: disable=broad-except
+ self.__logger.warn("Can't cancel the current exec")
+
+ execution = cfy_client.executions.start(
+ dep_name,
+ 'uninstall',
+ parameters=dict(ignore_failure=True))
+
+ wait_for_execution(cfy_client, execution, self.__logger)
+ cfy_client.deployments.delete(self.vnf['descriptor'].get('name'))
+ cfy_client.blueprints.delete(self.vnf['descriptor'].get('name'))
+ except: # pylint: disable=broad-except
+ self.__logger.warn("Some issue during the undeployment ..")
+ self.__logger.warn("Tenant clean continue ..")
+
+ self.__logger.info('Remove the cloudify manager OS object ..')
+ for creator in reversed(self.created_object):
+ try:
+ creator.clean()
+ except Exception as exc:
+ self.logger.error('Unexpected error cleaning - %s', exc)
+
+ super(CloudifyVrouter, self).clean()
+
+ def run(self, **kwargs):
+ """Execute CloudifyVrouter test case."""
+ return super(CloudifyVrouter, self).run(**kwargs)
+
+ def get_vnf_info_list(self, target_vnf_name):
+ return self.util.get_vnf_info_list(self.cfy_manager_ip,
+ self.deployment_name,
+ target_vnf_name)
+
+
+# ----------------------------------------------------------
+#
+# YAML UTILS
+#
+# -----------------------------------------------------------
+def get_config(parameter, file_path):
+ """
+ Get config parameter.
+ Returns the value of a given parameter in file.yaml
+ parameter must be given in string format with dots
+ Example: general.openstack.image_name
+ """
+ with open(file_path) as config_file:
+ file_yaml = yaml.safe_load(config_file)
+ config_file.close()
+ value = file_yaml
+ for element in parameter.split("."):
+ value = value.get(element)
+ if value is None:
+ raise ValueError("The parameter %s is not defined in"
+ " reporting.yaml" % parameter)
+ return value
+
+
+def wait_for_execution(client, execution, logger, timeout=7200, ):
+ """Wait for a workflow execution on Cloudify Manager."""
+ # if execution already ended - return without waiting
+ if execution.status in Execution.END_STATES:
+ return execution
+
+ if timeout is not None:
+ deadline = time.time() + timeout
+
+ # Poll for execution status and execution logs, until execution ends
+ # and we receive an event of type in WORKFLOW_END_TYPES
+ offset = 0
+ batch_size = 50
+ event_list = []
+ execution_ended = False
+ while True:
+ event_list = client.events.list(
+ execution_id=execution.id,
+ _offset=offset,
+ _size=batch_size,
+ include_logs=False,
+ sort='@timestamp').items
+
+ offset = offset + len(event_list)
+ for event in event_list:
+ logger.debug(event.get('message'))
+
+ if timeout is not None:
+ if time.time() > deadline:
+ raise RuntimeError(
+ 'execution of operation {0} for deployment {1} '
+ 'timed out'.format(execution.workflow_id,
+ execution.deployment_id))
+ else:
+ # update the remaining timeout
+ timeout = deadline - time.time()
+
+ if not execution_ended:
+ execution = client.executions.get(execution.id)
+ execution_ended = execution.status in Execution.END_STATES
+
+ if execution_ended:
+ break
+
+ time.sleep(5)
+
+ return execution
+
+
+def get_execution_id(client, deployment_id):
+ """
+ Get the execution id of a env preparation.
+ network, security group, fip, VM creation
+ """
+ executions = client.executions.list(deployment_id=deployment_id)
+ for execution in executions:
+ if execution.workflow_id == 'create_deployment_environment':
+ return execution
+ raise RuntimeError('Failed to get create_deployment_environment '
+ 'workflow execution.'
+ 'Available executions: {0}'.format(executions))
+
+
+def run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"):
+ """Command to run ssh command with the exit status."""
+ (_, stdout, _) = ssh.exec_command(cmd)
+ if stdout.channel.recv_exit_status() != 0:
+ raise Exception(error_msg)
diff --git a/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml b/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml
new file mode 100644
index 00000000..c09477ab
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/cloudify_vrouter.yaml
@@ -0,0 +1,31 @@
+tenant_images:
+ cloudify_manager_4.0: /home/opnfv/functest/images/cloudify-manager-premium-4.0.1.qcow2
+ vyos1.1.7: /home/opnfv/functest/images/vyos-1.1.7.img
+test_data:
+ url: 'https://github.com/oolorg/opnfv-vnf-data.git'
+ branch: 'master'
+orchestrator:
+ name: cloudify
+ version: '4.0'
+ requirements:
+ flavor:
+ name: m1.medium
+ ram_min: 4096
+ os_image: 'cloudify_manager_4.0'
+vnf:
+ name: vyos1.1.7
+ version: '1.1.7'
+ descriptor:
+ url: https://github.com/oolorg/opnfv-vnf-vyos-blueprint/
+ name: vrouter-opnfv
+ version: 'master'
+ requirements:
+ flavor:
+ name: m1.medium
+ ram_min: 2048
+ inputs:
+ external_network_name: admin_floating_net
+ region: RegionOne
+vnf_test_suite:
+ name: vyos-vrouter-test
+ version: "1.0"
diff --git a/functest/opnfv_tests/sdn/onos/__init__.py b/functest/opnfv_tests/vnf/router/test_controller/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/opnfv_tests/sdn/onos/__init__.py
+++ b/functest/opnfv_tests/vnf/router/test_controller/__init__.py
diff --git a/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py
new file mode 100644
index 00000000..236447e0
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/test_controller/function_test_exec.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vrouter function test execution module"""
+
+import logging
+import time
+import yaml
+
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+from functest.opnfv_tests.vnf.router.vnf_controller.vnf_controller import (
+ VnfController)
+
+
+class FunctionTestExec(object):
+ """vrouter function test execution class"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, util_info):
+ self.logger.debug("init test exec")
+ self.util = Utilvnf()
+ credentials = util_info["credentials"]
+ self.vnf_ctrl = VnfController(util_info)
+
+ test_cmd_map_file = open(self.util.vnf_data_dir +
+ self.util.opnfv_vnf_data_dir +
+ self.util.command_template_dir +
+ self.util.test_cmd_map_yaml_file,
+ 'r')
+ self.test_cmd_map_yaml = yaml.safe_load(test_cmd_map_file)
+ test_cmd_map_file.close()
+
+ self.util.set_credentials(credentials["username"],
+ credentials["password"],
+ credentials["auth_url"],
+ credentials["tenant_name"],
+ credentials["region_name"])
+
+ with open(self.util.test_env_config_yaml) as file_fd:
+ test_env_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ self.protocol_stable_wait = test_env_config_yaml.get("general").get(
+ "protocol_stable_wait")
+
+ def config_target_vnf(self, target_vnf, reference_vnf, test_kind):
+ self.logger.debug("Configuration to target vnf")
+ test_info = self.test_cmd_map_yaml[target_vnf["os_type"]]
+ test_cmd_file_path = test_info[test_kind]["pre_command_target"]
+ target_parameter_file_path = test_info[test_kind]["parameter_target"]
+ prompt_file_path = test_info["prompt"]
+
+ return self.vnf_ctrl.config_vnf(target_vnf,
+ reference_vnf,
+ test_cmd_file_path,
+ target_parameter_file_path,
+ prompt_file_path)
+
+ def config_reference_vnf(self, target_vnf, reference_vnf, test_kind):
+ self.logger.debug("Configuration to reference vnf")
+ test_info = self.test_cmd_map_yaml[reference_vnf["os_type"]]
+ test_cmd_file_path = test_info[test_kind]["pre_command_reference"]
+ reference_parameter_file_path = test_info[test_kind][
+ "parameter_reference"]
+ prompt_file_path = test_info["prompt"]
+
+ return self.vnf_ctrl.config_vnf(reference_vnf,
+ target_vnf,
+ test_cmd_file_path,
+ reference_parameter_file_path,
+ prompt_file_path)
+
+ def result_check(self, target_vnf, reference_vnf, test_kind, test_list):
+ test_info = self.test_cmd_map_yaml[target_vnf["os_type"]]
+ target_parameter_file_path = test_info[test_kind]["parameter_target"]
+ prompt_file_path = test_info["prompt"]
+ check_rule_file_path_list = []
+
+ for test in test_list:
+ check_rule_file_path_list.append(test_info[test_kind][test])
+
+ return self.vnf_ctrl.result_check(target_vnf,
+ reference_vnf,
+ check_rule_file_path_list,
+ target_parameter_file_path,
+ prompt_file_path)
+
+ def run(self, target_vnf, reference_vnf_list, test_info, test_list):
+ test_result_data = {}
+ test_kind = test_info["protocol"]
+ for reference_vnf in reference_vnf_list:
+ self.logger.debug("Start config command " +
+ target_vnf["vnf_name"] + " and " +
+ reference_vnf["vnf_name"])
+
+ result = self.config_target_vnf(target_vnf,
+ reference_vnf,
+ test_kind)
+ if not result:
+ return False, test_result_data
+
+ result = self.config_reference_vnf(target_vnf,
+ reference_vnf,
+ test_kind)
+ if not result:
+ return False, test_result_data
+
+ self.logger.debug("Finish config command.")
+
+ self.logger.debug("Waiting for protocol stable.")
+ time.sleep(self.protocol_stable_wait)
+
+ self.logger.debug("Start check method")
+
+ (result, res_dict_data_list) = self.result_check(target_vnf,
+ reference_vnf,
+ test_kind,
+ test_list)
+
+ test_result_data = {"test_kind": test_info["test_kind"],
+ "protocol": test_info["protocol"],
+ "result": res_dict_data_list}
+
+ if not result:
+ self.logger.debug("Error check method.")
+ return False, test_result_data
+
+ self.logger.debug("Finish check method.")
+
+ return True, test_result_data
diff --git a/functest/opnfv_tests/vnf/router/test_scenario.yaml b/functest/opnfv_tests/vnf/router/test_scenario.yaml
new file mode 100644
index 00000000..03185592
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/test_scenario.yaml
@@ -0,0 +1,27 @@
+test_scenario_list:
+ -
+ test_type: 'function_test'
+ vnf_list:
+ -
+ vnf_name: 'target_vnf'
+ os_type: 'vyos'
+ image_name: 'vyos1.1.7'
+ flavor_name: 'm1.medium'
+ -
+ vnf_name: 'reference_vnf'
+ os_type: 'vyos'
+ image_name: 'vyos1.1.7'
+ flavor_name: 'm1.medium'
+ function_test_list:
+ -
+ target_vnf_name: 'target_vnf'
+ test_list:
+ -
+ test_kind: 'Interoperability'
+ protocol: 'BGP'
+ BGP:
+ - 'Checking_the_peer_of_BGP'
+ - 'Checking_the_status_of_BGP'
+ - 'Checking_the_advertised_routes'
+ - 'Checking_the_received_routes'
+ - 'Checking_the_routing_table'
diff --git a/functest/opnfv_tests/vnf/router/utilvnf.py b/functest/opnfv_tests/vnf/router/utilvnf.py
new file mode 100644
index 00000000..084af331
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/utilvnf.py
@@ -0,0 +1,345 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+""" Utility module of vrouter testcase """
+
+import json
+import logging
+import os
+import pkg_resources
+import requests
+import yaml
+
+from functest.utils.constants import CONST
+from git import Repo
+from novaclient import client as novaclient
+from keystoneauth1 import session
+from keystoneauth1 import loading
+from requests.auth import HTTPBasicAuth
+
+RESULT_SPRIT_INDEX = {
+ "transfer": 8,
+ "bandwidth": 6,
+ "jitter": 4,
+ "los_total": 2,
+ "pkt_loss": 1
+}
+
+BIT_PER_BYTE = 8
+
+NOVA_CLIENT_API_VERSION = '2'
+NOVA_CILENT_NETWORK_INFO_INDEX = 0
+CFY_INFO_OUTPUT_FILE = "output.txt"
+
+CIDR_NETWORK_SEGMENT_INFO_INDEX = 0
+PACKET_LOST_INFO_INDEX = 0
+PACKET_TOTAL_INFO_INDEX = 1
+
+NUMBER_OF_DIGITS_FOR_AVG_TRANSFER = 0
+NUMBER_OF_DIGITS_FOR_AVG_BANDWIDTH = 0
+NUMBER_OF_DIGITS_FOR_AVG_JITTER = 3
+NUMBER_OF_DIGITS_FOR_AVG_PKT_LOSS = 1
+
+
+class Utilvnf(object):
+ """ Utility class of vrouter testcase """
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self):
+ self.username = ""
+ self.password = ""
+ self.auth_url = ""
+ self.tenant_name = ""
+ self.region_name = ""
+
+ data_dir = data_dir = CONST.__getattribute__('dir_router_data')
+
+ self.vnf_data_dir = data_dir
+ self.opnfv_vnf_data_dir = "opnfv-vnf-data/"
+ self.command_template_dir = "command_template/"
+ self.test_scenario_yaml = "test_scenario.yaml"
+ test_env_config_yaml_file = "test_env_config.yaml"
+ self.test_cmd_map_yaml_file = "test_cmd_map.yaml"
+ self.test_env_config_yaml = os.path.join(
+ self.vnf_data_dir,
+ self.opnfv_vnf_data_dir,
+ test_env_config_yaml_file)
+
+ self.blueprint_dir = "opnfv-vnf-vyos-blueprint/"
+ self.blueprint_file_name = "function-test-openstack-blueprint.yaml"
+
+ if not os.path.exists(self.vnf_data_dir):
+ os.makedirs(self.vnf_data_dir)
+
+ case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/router')
+
+ config_file_name = CONST.__getattribute__(
+ 'vnf_{}_config'.format("vyos_vrouter"))
+
+ config_file = os.path.join(case_dir, config_file_name)
+
+ with open(config_file) as file_fd:
+ vrouter_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ test_data = vrouter_config_yaml.get("test_data")
+
+ self.logger.debug("Downloading the test data.")
+ vrouter_data_path = self.vnf_data_dir + self.opnfv_vnf_data_dir
+
+ if not os.path.exists(vrouter_data_path):
+ Repo.clone_from(test_data['url'],
+ vrouter_data_path,
+ branch=test_data['branch'])
+
+ with open(self.test_env_config_yaml) as file_fd:
+ test_env_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ self.image = test_env_config_yaml.get(
+ "general").get("images").get("vyos")
+ self.tester_image = test_env_config_yaml.get(
+ "general").get("images").get("tester_vm_os")
+
+ self.test_result_json_file = "test_result.json"
+ if os.path.isfile(self.test_result_json_file):
+ os.remove(self.test_result_json_file)
+ self.logger.debug("removed %s" % self.test_result_json_file)
+
+ def get_nova_client(self):
+ creds = self.get_nova_credentials()
+ loader = loading.get_plugin_loader('password')
+ auth = loader.load_from_options(**creds)
+ sess = session.Session(auth=auth)
+ nova_client = novaclient.Client(NOVA_CLIENT_API_VERSION, session=sess)
+
+ return nova_client
+
+ def set_credentials(self, username, password, auth_url,
+ tenant_name, region_name="RegionOne"):
+ self.username = username
+ self.password = password
+ self.auth_url = auth_url
+ self.tenant_name = tenant_name
+ self.region_name = region_name
+
+ def get_nova_credentials(self):
+ creds = {}
+ creds['username'] = self.username
+ creds['password'] = self.password
+ creds['auth_url'] = self.auth_url
+ creds['tenant_name'] = self.tenant_name
+ return creds
+
+ def get_address(self, server_name, network_name):
+ nova_client = self.get_nova_client()
+ servers_list = nova_client.servers.list()
+ server = None
+
+ for server in servers_list:
+ if server.name == server_name:
+ break
+
+ address = server.addresses[
+ network_name][NOVA_CILENT_NETWORK_INFO_INDEX]["addr"]
+
+ return address
+
+ def get_mac_address(self, server_name, network_name):
+ nova_client = self.get_nova_client()
+ servers_list = nova_client.servers.list()
+ server = None
+
+ for server in servers_list:
+ if server.name == server_name:
+ break
+
+ mac_address = server.addresses[network_name][
+ NOVA_CILENT_NETWORK_INFO_INDEX][
+ "OS-EXT-IPS-MAC:mac_addr"]
+
+ return mac_address
+
+ def reboot_vm(self, server_name):
+ nova_client = self.get_nova_client()
+ servers_list = nova_client.servers.list()
+ server = None
+
+ for server in servers_list:
+ if server.name == server_name:
+ break
+
+ server.reboot()
+
+ return
+
+ def delete_vm(self, server_name):
+ nova_client = self.get_nova_client()
+ servers_list = nova_client.servers.list()
+ server = None
+
+ for server in servers_list:
+ if server.name == server_name:
+ nova_client.servers.delete(server)
+ break
+
+ return
+
+ def get_blueprint_outputs(self, cfy_manager_ip, deployment_name):
+ url = "http://%s/deployments/%s/outputs" % (
+ cfy_manager_ip, deployment_name)
+
+ response = requests.get(
+ url,
+ auth=HTTPBasicAuth('admin', 'admin'),
+ headers={'Tenant': 'default_tenant'})
+
+ resp_data = response.json()
+ self.logger.debug(resp_data)
+ data = resp_data["outputs"]
+ return data
+
+ def get_blueprint_outputs_vnfs(self, cfy_manager_ip, deployment_name):
+ outputs = self.get_blueprint_outputs(cfy_manager_ip,
+ deployment_name)
+ vnfs = outputs["vnfs"]
+ vnf_list = []
+ for vnf_name in vnfs:
+ vnf_list.append(vnfs[vnf_name])
+ return vnf_list
+
+ def get_blueprint_outputs_networks(self, cfy_manager_ip, deployment_name):
+ outputs = self.get_blueprint_outputs(cfy_manager_ip,
+ deployment_name)
+ networks = outputs["networks"]
+ network_list = []
+ for network_name in networks:
+ network_list.append(networks[network_name])
+ return network_list
+
+ def request_vnf_reboot(self, vnf_info_list):
+ for vnf in vnf_info_list:
+ self.logger.debug("reboot the " + vnf["vnf_name"])
+ self.reboot_vm(vnf["vnf_name"])
+
+ def request_vm_delete(self, vnf_info_list):
+ for vnf in vnf_info_list:
+ self.logger.debug("delete the " + vnf["vnf_name"])
+ self.delete_vm(vnf["vnf_name"])
+
+ def get_vnf_info_list(self, cfy_manager_ip, topology_deploy_name,
+ target_vnf_name):
+ network_list = self.get_blueprint_outputs_networks(
+ cfy_manager_ip,
+ topology_deploy_name)
+ vnf_info_list = self.get_blueprint_outputs_vnfs(cfy_manager_ip,
+ topology_deploy_name)
+ for vnf in vnf_info_list:
+ vnf_name = vnf["vnf_name"]
+ vnf["os_type"] = self.image["os_type"]
+ vnf["user"] = self.image["user"]
+ vnf["pass"] = self.image["pass"]
+
+ if vnf_name == target_vnf_name:
+ vnf["target_vnf_flag"] = True
+ else:
+ vnf["target_vnf_flag"] = False
+
+ self.logger.debug("vnf name : " + vnf_name)
+ self.logger.debug(vnf_name + " floating ip address : " +
+ vnf["floating_ip"])
+
+ for network in network_list:
+ network_name = network["network_name"]
+ ip_address = self.get_address(vnf["vnf_name"],
+ network["network_name"])
+ vnf[network_name + "_ip"] = ip_address
+ mac = self.get_mac_address(vnf["vnf_name"],
+ network["network_name"])
+ vnf[network_name + "_mac"] = mac
+
+ self.logger.debug(network_name + "_ip of " + vnf["vnf_name"] +
+ " : " + vnf[network_name + "_ip"])
+ self.logger.debug(network_name + "_mac of " + vnf["vnf_name"] +
+ " : " + vnf[network_name + "_mac"])
+
+ return vnf_info_list
+
+ def get_target_vnf(self, vnf_info_list):
+ for vnf in vnf_info_list:
+ if vnf["target_vnf_flag"]:
+ return vnf
+
+ return None
+
+ def get_reference_vnf_list(self, vnf_info_list):
+ reference_vnf_list = []
+ for vnf in vnf_info_list:
+ if not vnf["target_vnf_flag"]:
+ reference_vnf_list.append(vnf)
+
+ return reference_vnf_list
+
+ def get_vnf_info(self, vnf_info_list, vnf_name):
+ for vnf in vnf_info_list:
+ if vnf["vnf_name"] == vnf_name:
+ return vnf
+
+ return None
+
+ def convert_functional_test_result(self, result_data_list):
+ result = {}
+ for result_data in result_data_list:
+ test_kind = result_data["test_kind"]
+ protocol = result_data["protocol"]
+ test_result_data = result_data["result"]
+
+ if test_kind not in result:
+ result[test_kind] = []
+
+ result[test_kind].append({protocol: test_result_data})
+
+ return {"Functional_test": result}
+
+ def write_result_data(self, result_data):
+ test_result = []
+ if not os.path.isfile(self.test_result_json_file):
+ file_fd = open(self.test_result_json_file, "w")
+ file_fd.close()
+ else:
+ file_fd = open(self.test_result_json_file, "r")
+ test_result = json.load(file_fd)
+ file_fd.close()
+
+ test_result.append(result_data)
+
+ file_fd = open(self.test_result_json_file, "w")
+ json.dump(test_result, file_fd)
+ file_fd.close()
+
+ def output_test_result_json(self):
+ if os.path.isfile(self.test_result_json_file):
+ file_fd = open(self.test_result_json_file, "r")
+ test_result = json.load(file_fd)
+ file_fd.close()
+ output_json_data = json.dumps(test_result,
+ sort_keys=True,
+ indent=4)
+ self.logger.debug("test_result %s" % output_json_data)
+ else:
+ self.logger.debug("Not found %s" % self.test_result_json_file)
+
+ def get_test_scenario(self, file_path):
+ test_scenario_file = open(file_path,
+ 'r')
+ test_scenario_yaml = yaml.safe_load(test_scenario_file)
+ test_scenario_file.close()
+ return test_scenario_yaml["test_scenario_list"]
diff --git a/functest/opnfv_tests/sdn/onos/teston/__init__.py b/functest/opnfv_tests/vnf/router/vnf_controller/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/opnfv_tests/sdn/onos/teston/__init__.py
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/__init__.py
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/checker.py b/functest/opnfv_tests/vnf/router/vnf_controller/checker.py
new file mode 100644
index 00000000..198a5ffc
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/checker.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vrouter test result check module"""
+
+import json
+import logging
+import re
+
+from jinja2 import Environment, FileSystemLoader
+
+
+class Checker(object):
+ """vrouter test result check class"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self):
+ self.logger.debug("init checker")
+
+ def load_check_rule(self, rule_file_dir, rule_file_name, parameter):
+ loader = FileSystemLoader(rule_file_dir,
+ encoding='utf8')
+ env = Environment(loader=loader)
+ check_rule_template = env.get_template(rule_file_name)
+ check_rule = check_rule_template.render(parameter)
+ check_rule_data = json.loads(check_rule)
+ return check_rule_data
+
+ def regexp_information(self, response, rules):
+ status = False
+ result_data = {}
+
+ for rule in rules["rules"]:
+ result_data = {
+ "test_name": rule["description"],
+ "result": "NG"
+ }
+
+ match = re.search(rule["regexp"],
+ response)
+ rule["response"] = response
+ if match is None:
+ status = False
+ break
+
+ if not match.group(1) == rule["result"]:
+ status = False
+ else:
+ result_data["result"] = "OK"
+ status = True
+
+ return status, result_data
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py b/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py
new file mode 100644
index 00000000..98cb14cc
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/command_generator.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""command generator module for vrouter testing"""
+
+import logging
+from jinja2 import Environment, FileSystemLoader
+
+
+class CommandGenerator(object):
+ """command generator class for vrouter testing"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self):
+ self.logger.debug("init command generator")
+
+ def load_template(self, template_dir, template):
+ loader = FileSystemLoader(template_dir,
+ encoding='utf8')
+ env = Environment(loader=loader)
+ return env.get_template(template)
+
+ def command_create(self, template, parameter):
+ commands = template.render(parameter)
+ return commands.split('\n')
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py
new file mode 100644
index 00000000..c85a5735
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/ssh_client.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""ssh client module for vrouter testing"""
+
+import logging
+import paramiko
+import time
+import yaml
+
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+
+RECEIVE_ROOP_WAIT = 1
+
+DEFAULT_CONNECT_TIMEOUT = 10
+DEFAULT_CONNECT_RETRY_COUNT = 10
+DEFAULT_SEND_TIMEOUT = 10
+
+
+class SshClient(object):
+ """ssh client class for vrouter testing"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, ip_address, user, password=None, key_filename=None):
+ self.ip_address = ip_address
+ self.user = user
+ self.password = password
+ self.key_filename = key_filename
+ self.connected = False
+ self.shell = None
+
+ self.logger.setLevel(logging.INFO)
+
+ self.ssh = paramiko.SSHClient()
+ self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+ self.util = Utilvnf()
+ with open(self.util.test_env_config_yaml) as file_fd:
+ test_env_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ self.ssh_revieve_buff = test_env_config_yaml.get("general").get(
+ "ssh_receive_buffer")
+
+ def connect(self, time_out=DEFAULT_CONNECT_TIMEOUT,
+ retrycount=DEFAULT_CONNECT_RETRY_COUNT):
+ while retrycount > 0:
+ try:
+ self.logger.info("SSH connect to %s.", self.ip_address)
+ self.ssh.connect(self.ip_address,
+ username=self.user,
+ password=self.password,
+ key_filename=self.key_filename,
+ timeout=time_out,
+ look_for_keys=False,
+ allow_agent=False)
+
+ self.logger.info("SSH connection established to %s.",
+ self.ip_address)
+
+ self.shell = self.ssh.invoke_shell()
+
+ while not self.shell.recv_ready():
+ time.sleep(RECEIVE_ROOP_WAIT)
+
+ self.shell.recv(self.ssh_revieve_buff)
+ break
+ except: # pylint: disable=broad-except
+ self.logger.info("SSH timeout for %s...", self.ip_address)
+ time.sleep(time_out)
+ retrycount -= 1
+
+ if retrycount == 0:
+ self.logger.error("Cannot establish connection to IP '%s'. " +
+ "Aborting",
+ self.ip_address)
+ self.connected = False
+ return self.connected
+
+ self.connected = True
+ return self.connected
+
+ def send(self, cmd, prompt, timeout=DEFAULT_SEND_TIMEOUT):
+ if self.connected is True:
+ self.shell.settimeout(timeout)
+ self.logger.debug("Commandset : '%s'", cmd)
+
+ try:
+ self.shell.send(cmd + '\n')
+ except: # pylint: disable=broad-except
+ self.logger.error("ssh send timeout : Command : '%s'", cmd)
+ return None
+
+ res_buff = ''
+ while not res_buff.endswith(prompt):
+ time.sleep(RECEIVE_ROOP_WAIT)
+ try:
+ res = self.shell.recv(self.ssh_revieve_buff)
+ except: # pylint: disable=broad-except
+ self.logger.error("ssh receive timeout : Command : '%s'",
+ cmd)
+ break
+
+ res_buff += res
+
+ self.logger.debug("Response : '%s'", res_buff)
+ return res_buff
+ else:
+ self.logger.error("Cannot connected to IP '%s'.", self.ip_address)
+ return None
+
+ def close(self):
+ if self.connected is True:
+ self.ssh.close()
+
+ def error_check(response, err_strs=["error",
+ "warn",
+ "unknown command",
+ "already exist"]):
+ for err in err_strs:
+ if err in response:
+ return False
+
+ return True
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py
new file mode 100644
index 00000000..cd228fe2
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/vm_controller.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vm controll module"""
+
+import logging
+import os
+import time
+import yaml
+
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+from functest.opnfv_tests.vnf.router.vnf_controller.command_generator import (
+ CommandGenerator)
+from functest.opnfv_tests.vnf.router.vnf_controller.ssh_client import (
+ SshClient)
+
+
+class VmController(object):
+ """vm controll class"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, util_info):
+ self.logger.debug("initialize vm controller")
+ self.command_gen = CommandGenerator()
+ credentials = util_info["credentials"]
+
+ self.util = Utilvnf()
+ self.util.set_credentials(credentials["username"],
+ credentials["password"],
+ credentials["auth_url"],
+ credentials["tenant_name"],
+ credentials["region_name"])
+
+ with open(self.util.test_env_config_yaml) as file_fd:
+ test_env_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ self.reboot_wait = test_env_config_yaml.get("general").get(
+ "reboot_wait")
+ self.command_wait = test_env_config_yaml.get("general").get(
+ "command_wait")
+ self.ssh_connect_timeout = test_env_config_yaml.get("general").get(
+ "ssh_connect_timeout")
+ self.ssh_connect_retry_count = test_env_config_yaml.get("general").get(
+ "ssh_connect_retry_count")
+
+ def command_gen_from_template(self, command_file_path, cmd_input_param):
+ (command_file_dir, command_file_name) = os.path.split(
+ command_file_path)
+ template = self.command_gen.load_template(command_file_dir,
+ command_file_name)
+ return self.command_gen.command_create(template,
+ cmd_input_param)
+
+ def config_vm(self, vm_info, test_cmd_file_path,
+ cmd_input_param, prompt_file_path):
+ ssh = self.connect_ssh_and_config_vm(vm_info,
+ test_cmd_file_path,
+ cmd_input_param,
+ prompt_file_path)
+ if ssh is None:
+ return False
+
+ ssh.close()
+
+ return True
+
+ def connect_ssh_and_config_vm(self, vm_info, test_cmd_file_path,
+ cmd_input_param, prompt_file_path):
+
+ key_filename = None
+ if "key_path" in vm_info:
+ key_filename = vm_info["key_path"]
+
+ ssh = SshClient(ip_address=vm_info["floating_ip"],
+ user=vm_info["user"],
+ password=vm_info["pass"],
+ key_filename=key_filename)
+
+ result = ssh.connect(self.ssh_connect_timeout,
+ self.ssh_connect_retry_count)
+ if not result:
+ self.logger.debug("try to vm reboot.")
+ self.util.reboot_vm(vm_info["vnf_name"])
+ time.sleep(self.reboot_wait)
+ result = ssh.connect(self.ssh_connect_timeout,
+ self.ssh_connect_retry_count)
+ if not result:
+ return None
+
+ (result, _) = self.command_create_and_execute(
+ ssh,
+ test_cmd_file_path,
+ cmd_input_param,
+ prompt_file_path)
+ if not result:
+ ssh.close()
+ return None
+
+ return ssh
+
+ def command_create_and_execute(self, ssh, test_cmd_file_path,
+ cmd_input_param, prompt_file_path):
+ prompt_file = open(prompt_file_path,
+ 'r')
+ prompt = yaml.safe_load(prompt_file)
+ prompt_file.close()
+ config_mode_prompt = prompt["config_mode"]
+
+ commands = self.command_gen_from_template(test_cmd_file_path,
+ cmd_input_param)
+ return self.command_list_execute(ssh,
+ commands,
+ config_mode_prompt)
+
+ def command_list_execute(self, ssh, command_list, prompt):
+ res_data_list = []
+ for command in command_list:
+ self.logger.debug("Command : " + command)
+ (res, res_data) = self.command_execute(ssh,
+ command,
+ prompt)
+ self.logger.debug("Response : " + res_data)
+ res_data_list.append(res_data)
+ if not res:
+ return res, res_data_list
+
+ time.sleep(self.command_wait)
+
+ return True, res_data_list
+
+ def command_execute(self, ssh, command, prompt):
+ res_data = ssh.send(command, prompt)
+ if res_data is None:
+ self.logger.info("retry send command : " + command)
+ res_data = ssh.send(command,
+ prompt)
+ if not ssh.error_check(res_data):
+ return False, res_data
+
+ return True, res_data
diff --git a/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py
new file mode 100644
index 00000000..814e9e33
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vnf_controller/vnf_controller.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vrouter controll module"""
+
+import logging
+import os
+import prettytable
+import time
+import yaml
+
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+from functest.opnfv_tests.vnf.router.vnf_controller.checker import Checker
+from functest.opnfv_tests.vnf.router.vnf_controller.ssh_client import (
+ SshClient)
+from functest.opnfv_tests.vnf.router.vnf_controller.vm_controller import (
+ VmController)
+
+
+class VnfController(object):
+ """vrouter controll class"""
+
+ logger = logging.getLogger(__name__)
+
+ def __init__(self, util_info):
+ self.logger.debug("init vnf controller")
+ self.util = Utilvnf()
+ self.vm_controller = VmController(util_info)
+
+ with open(self.util.test_env_config_yaml) as file_fd:
+ test_env_config_yaml = yaml.safe_load(file_fd)
+ file_fd.close()
+
+ self.cmd_wait = test_env_config_yaml.get("general").get("command_wait")
+ self.ssh_connect_timeout = test_env_config_yaml.get("general").get(
+ "ssh_connect_timeout")
+ self.ssh_connect_retry_count = test_env_config_yaml.get("general").get(
+ "ssh_connect_retry_count")
+
+ def config_vnf(self, source_vnf, destination_vnf, test_cmd_file_path,
+ parameter_file_path, prompt_file_path):
+ parameter_file = open(parameter_file_path,
+ 'r')
+ cmd_input_param = yaml.safe_load(parameter_file)
+ parameter_file.close()
+
+ cmd_input_param["macaddress"] = source_vnf["data_plane_network_mac"]
+ cmd_input_param["source_ip"] = source_vnf["data_plane_network_ip"]
+ cmd_input_param["destination_ip"] = destination_vnf[
+ "data_plane_network_ip"]
+
+ return self.vm_controller.config_vm(source_vnf,
+ test_cmd_file_path,
+ cmd_input_param,
+ prompt_file_path)
+
+ def result_check(self, target_vnf, reference_vnf,
+ check_rule_file_path_list, parameter_file_path,
+ prompt_file_path):
+
+ res_dict_data_list = []
+
+ parameter_file = open(parameter_file_path,
+ 'r')
+ cmd_input_param = yaml.safe_load(parameter_file)
+ parameter_file.close()
+
+ cmd_input_param["source_ip"] = target_vnf["data_plane_network_ip"]
+ cmd_input_param["destination_ip"] = reference_vnf[
+ "data_plane_network_ip"]
+
+ prompt_file = open(prompt_file_path,
+ 'r')
+ prompt = yaml.safe_load(prompt_file)
+ prompt_file.close()
+ terminal_mode_prompt = prompt["terminal_mode"]
+
+ ssh = SshClient(target_vnf["floating_ip"],
+ target_vnf["user"],
+ target_vnf["pass"])
+
+ result = ssh.connect(self.ssh_connect_timeout,
+ self.ssh_connect_retry_count)
+ if not result:
+ return False, res_dict_data_list
+
+ checker = Checker()
+
+ res_table = prettytable.PrettyTable(
+ header_style='upper', padding_width=5,
+ field_names=['test item', 'result'])
+
+ status = True
+ res_data_list = []
+ for check_rule_file_path in check_rule_file_path_list:
+ (check_rule_dir, check_rule_file) = os.path.split(
+ check_rule_file_path)
+ check_rules = checker.load_check_rule(check_rule_dir,
+ check_rule_file,
+ cmd_input_param)
+ (res, res_data) = self.vm_controller.command_execute(
+ ssh,
+ check_rules["command"],
+ terminal_mode_prompt)
+ res_data_list.append(res_data)
+ if not res:
+ status = False
+ break
+
+ (res, res_dict_data) = checker.regexp_information(res_data,
+ check_rules)
+ res_dict_data_list.append(res_dict_data)
+ res_table.add_row([res_dict_data["test_name"],
+ res_dict_data["result"]])
+ if not res:
+ status = False
+
+ time.sleep(self.cmd_wait)
+
+ ssh.close()
+
+ self.logger.info("Test result:\n\n%s\n", res_table.get_string())
+
+ self.output_check_result_detail_data(res_data_list)
+
+ return status, res_dict_data_list
+
+ def output_check_result_detail_data(self, res_data_list):
+ for res_data in res_data_list:
+ self.logger.debug(res_data)
diff --git a/functest/opnfv_tests/vnf/router/vrouter_base.py b/functest/opnfv_tests/vnf/router/vrouter_base.py
new file mode 100644
index 00000000..a534f1f2
--- /dev/null
+++ b/functest/opnfv_tests/vnf/router/vrouter_base.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory 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
+
+"""vrouter testing base class module"""
+
+import datetime
+import json
+import logging
+import os
+import pkg_resources
+import time
+
+import functest.core.vnf as vnf
+from functest.utils.constants import CONST
+from functest.opnfv_tests.vnf.router.test_controller import function_test_exec
+from functest.opnfv_tests.vnf.router.utilvnf import Utilvnf
+
+__author__ = "Shuya Nakama <shuya.nakama@okinawaopenlabs.org>"
+
+REBOOT_WAIT = 30
+
+
+class VrouterOnBoardingBase(vnf.VnfOnBoarding):
+ """vrouter testing base class"""
+
+ def __init__(self, **kwargs):
+ self.logger = logging.getLogger(__name__)
+ super(VrouterOnBoardingBase, self).__init__(**kwargs)
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/router')
+ self.data_dir = CONST.__getattribute__('dir_router_data')
+ self.result_dir = os.path.join(CONST.__getattribute__('dir_results'),
+ self.case_name)
+ self.util = Utilvnf()
+ self.util_info = {}
+
+ self.vnf_list = []
+
+ if not os.path.exists(self.data_dir):
+ os.makedirs(self.data_dir)
+ if not os.path.exists(self.result_dir):
+ os.makedirs(self.result_dir)
+
+ def test_vnf(self):
+ """vrouter test execution"""
+ result = False
+ test_result_data_list = []
+ test_scenario_file_path = os.path.join(self.case_dir,
+ self.util.test_scenario_yaml)
+ test_scenario_list = self.util.get_test_scenario(
+ test_scenario_file_path)
+ for test_scenario in test_scenario_list:
+ if test_scenario["test_type"] == "function_test":
+ function_test_list = test_scenario["function_test_list"]
+ for function_test in function_test_list:
+ test_list = function_test["test_list"]
+ target_vnf_name = function_test["target_vnf_name"]
+ for test_info in test_list:
+ self.logger.info(test_info["protocol"] + " " +
+ test_info["test_kind"] +
+ " test.")
+ (result, result_data) = self.function_test_vrouter(
+ target_vnf_name,
+ test_info)
+ test_result_data_list.append(result_data)
+ if not result:
+ break
+
+ self.util.request_vm_delete(self.vnf_list)
+
+ test_result_data = json.dumps(test_result_data_list, indent=4)
+
+ return result, test_result_data
+
+ def function_test_vrouter(self, target_vnf_name, test_info):
+ """function test execution"""
+
+ test_protocol = test_info["protocol"]
+ test_list = test_info[test_protocol]
+
+ vnf_info_list = self.get_vnf_info_list(target_vnf_name)
+ self.vnf_list = vnf_info_list
+
+ self.logger.debug("request vnf's reboot.")
+ self.util.request_vnf_reboot(vnf_info_list)
+ time.sleep(REBOOT_WAIT)
+
+ target_vnf = self.util.get_target_vnf(vnf_info_list)
+
+ reference_vnf_list = self.util.get_reference_vnf_list(vnf_info_list)
+
+ test_exec = function_test_exec.FunctionTestExec(self.util_info)
+
+ # start test
+ start_time_ts = time.time()
+ self.logger.info("vRouter test Start Time:'%s'", (
+ datetime.datetime.fromtimestamp(start_time_ts).strftime(
+ '%Y-%m-%d %H:%M:%S')))
+
+ (result, test_result_data) = test_exec.run(target_vnf,
+ reference_vnf_list,
+ test_info,
+ test_list)
+
+ end_time_ts = time.time()
+ duration = round(end_time_ts - start_time_ts, 1)
+ self.logger.info("vRouter test duration :'%s'", duration)
+
+ return result, test_result_data
+
+ def get_vnf_info_list(self, target_vnf_name):
+ vnf_info_list = []
+ return vnf_info_list
diff --git a/functest/opnfv_tests/vnf/router/vyos_vrouter.py b/functest/opnfv_tests/vnf/router/vyos_vrouter.py
deleted file mode 100644
index 5654278d..00000000
--- a/functest/opnfv_tests/vnf/router/vyos_vrouter.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2017 Okinawa Open Laboratory
-#
-# 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
-import json
-import os
-
-RESULT_DETAILS_FILE = "test_result.json"
-
-
-class VrouterVnf(base.Feature):
- 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):
- filepath = os.path.join(self.repo, RESULT_DETAILS_FILE)
- if os.path.exists(filepath):
- f = open(filepath, 'r')
- self.details = json.load(f)
- f.close()
-
- def log_results(self):
- if self.result == 'PASS':
- self.set_result_details()
- super(VrouterVnf, self).log_results()
diff --git a/functest/tests/unit/energy/test_functest_energy.py b/functest/tests/unit/energy/test_functest_energy.py
index a576e2c3..5e2254ad 100644
--- a/functest/tests/unit/energy/test_functest_energy.py
+++ b/functest/tests/unit/energy/test_functest_energy.py
@@ -17,7 +17,7 @@ import mock
from functest.energy.energy import EnergyRecorder
import functest.energy.energy as energy
-
+from functest.utils.constants import CONST
CASE_NAME = "UNIT_TEST_CASE"
STEP_NAME = "UNIT_TEST_STEP"
@@ -237,16 +237,14 @@ class EnergyRecorderTest(unittest.TestCase):
return_value={"scenario": PREVIOUS_SCENARIO,
"step": PREVIOUS_STEP})
@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_with_previous(self,
loader_mock=None,
- pod_mock=None,
recorder_mock=None,
cur_scenario_mock=None):
"""Test energy module decorators."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
self.__decorated_method()
calls = [mock.call.start(self.case_name),
mock.call.submit_scenario(PREVIOUS_SCENARIO,
@@ -274,13 +272,11 @@ class EnergyRecorderTest(unittest.TestCase):
@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")
@mock.patch("functest.energy.energy.requests.get",
return_value=API_OK)
- def test_load_config(self, loader_mock=None, pod_mock=None,
- get_mock=None):
+ def test_load_config(self, loader_mock=None, get_mock=None):
"""Test load config."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
EnergyRecorder.energy_recorder_api = None
EnergyRecorder.load_config()
@@ -295,13 +291,11 @@ class EnergyRecorderTest(unittest.TestCase):
@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")
@mock.patch("functest.energy.energy.requests.get",
return_value=API_OK)
- def test_load_config_no_creds(self, loader_mock=None, pod_mock=None,
- get_mock=None):
+ def test_load_config_no_creds(self, loader_mock=None, get_mock=None):
"""Test load config without creds."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
EnergyRecorder.energy_recorder_api = None
EnergyRecorder.load_config()
self.assertEquals(EnergyRecorder.energy_recorder_api["auth"], None)
@@ -312,13 +306,11 @@ class EnergyRecorderTest(unittest.TestCase):
@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")
@mock.patch("functest.energy.energy.requests.get",
return_value=API_OK)
- def test_load_config_ex(self, loader_mock=None, pod_mock=None,
- get_mock=None):
+ def test_load_config_ex(self, loader_mock=None, get_mock=None):
"""Test load config with exception."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
with self.assertRaises(AssertionError):
EnergyRecorder.energy_recorder_api = None
EnergyRecorder.load_config()
@@ -326,13 +318,11 @@ class EnergyRecorderTest(unittest.TestCase):
@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")
@mock.patch("functest.energy.energy.requests.get",
return_value=API_KO)
- def test_load_config_api_ko(self, loader_mock=None, pod_mock=None,
- get_mock=None):
+ def test_load_config_api_ko(self, loader_mock=None, get_mock=None):
"""Test load config with API unavailable."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
EnergyRecorder.energy_recorder_api = None
EnergyRecorder.load_config()
self.assertEquals(EnergyRecorder.energy_recorder_api["available"],
@@ -340,13 +330,11 @@ class EnergyRecorderTest(unittest.TestCase):
@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")
@mock.patch('functest.energy.energy.requests.get',
return_value=RECORDER_OK)
- def test_get_current_scenario(self, loader_mock=None,
- pod_mock=None, get_mock=None):
+ def test_get_current_scenario(self, loader_mock=None, get_mock=None):
"""Test get_current_scenario."""
+ CONST.__setattr__('NODE_NAME', 'MOCK_POD')
self.test_load_config()
scenario = EnergyRecorder.get_current_scenario()
self.assertTrue(scenario is not None)
diff --git a/functest/tests/unit/openstack/refstack_client/test_refstack_client.py b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
index c5601075..ca097483 100644
--- a/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
+++ b/functest/tests/unit/openstack/refstack_client/test_refstack_client.py
@@ -12,9 +12,12 @@ import pkg_resources
import unittest
from functest.core import testcase
-from functest.opnfv_tests.openstack.refstack_client import refstack_client
+from functest.opnfv_tests.openstack.refstack_client.refstack_client import \
+ RefstackClient, RefstackClientParser
from functest.utils.constants import CONST
+from snaps.openstack.os_credentials import OSCreds
+
class OSRefstackClientTesting(unittest.TestCase):
@@ -25,34 +28,44 @@ class OSRefstackClientTesting(unittest.TestCase):
'functest', 'opnfv_tests/openstack/refstack_client/defcore.txt')
def setUp(self):
- self.defaultargs = {'config': self._config,
- 'testlist': self._testlist}
+ self.default_args = {'config': self._config,
+ 'testlist': self._testlist}
CONST.__setattr__('OS_AUTH_URL', 'https://ip:5000/v3')
CONST.__setattr__('OS_INSECURE', 'true')
- self.refstackclient = refstack_client.RefstackClient()
+ self.os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
+ @mock.patch('functest.opnfv_tests.openstack.refstack_client.tempest_conf.'
+ 'TempestConf', return_value=mock.Mock())
+ def _create_client(self, mock_conf):
+ with mock.patch('snaps.openstack.tests.openstack_tests.'
+ 'get_credentials', return_value=self.os_creds):
+ return RefstackClient()
def test_run_defcore_insecure(self):
insecure = '-k'
config = 'tempest.conf'
testlist = 'testlist'
+ client = self._create_client()
with mock.patch('functest.opnfv_tests.openstack.refstack_client.'
'refstack_client.ft_utils.execute_command') as m:
cmd = ("refstack-client test {0} -c {1} -v --test-list {2}"
.format(insecure, config, testlist))
- self.refstackclient.run_defcore(config, testlist)
+ client.run_defcore(config, testlist)
m.assert_any_call(cmd)
def test_run_defcore(self):
CONST.__setattr__('OS_AUTH_URL', 'http://ip:5000/v3')
- refstackclient = refstack_client.RefstackClient()
insecure = ''
config = 'tempest.conf'
testlist = 'testlist'
+ client = self._create_client()
with mock.patch('functest.opnfv_tests.openstack.refstack_client.'
'refstack_client.ft_utils.execute_command') as m:
cmd = ("refstack-client test {0} -c {1} -v --test-list {2}"
.format(insecure, config, testlist))
- refstackclient.run_defcore(config, testlist)
+ client.run_defcore(config, testlist)
m.assert_any_call(cmd)
@mock.patch('functest.opnfv_tests.openstack.refstack_client.'
@@ -62,7 +75,7 @@ class OSRefstackClientTesting(unittest.TestCase):
mock_logger_info):
self.case_name = 'refstack_defcore'
self.result = 0
- self.refstackclient.parse_refstack_result()
+ self._create_client().parse_refstack_result()
mock_logger_info.assert_called_once_with(
"Testcase %s success_rate is %s%%",
self.case_name, self.result)
@@ -82,10 +95,11 @@ class OSRefstackClientTesting(unittest.TestCase):
"success": ['tempest.api.compute [18.464988s]'],
"errors": ['tempest.api.volume [0.230334s]'],
"skipped": ['tempest.api.network [1.265828s]']}
+ client = self._create_client()
with mock.patch('__builtin__.open',
mock.mock_open(read_data=log_file)):
- self.refstackclient.parse_refstack_result()
- self.assertEqual(self.refstackclient.details, self.details)
+ client.parse_refstack_result()
+ self.assertEqual(client.details, self.details)
def _get_main_kwargs(self, key=None):
kwargs = {'config': self._config,
@@ -96,16 +110,18 @@ class OSRefstackClientTesting(unittest.TestCase):
def _test_main(self, status, *args):
kwargs = self._get_main_kwargs()
- self.assertEqual(self.refstackclient.main(**kwargs), status)
+ client = self._create_client()
+ self.assertEqual(client.main(**kwargs), status)
if len(args) > 0:
args[0].assert_called_once_with(
- refstack_client.RefstackClient.result_dir)
+ RefstackClient.result_dir)
if len(args) > 1:
args
def _test_main_missing_keyword(self, key):
kwargs = self._get_main_kwargs(key)
- self.assertEqual(self.refstackclient.main(**kwargs),
+ client = self._create_client()
+ self.assertEqual(client.main(**kwargs),
testcase.TestCase.EX_RUN_ERROR)
def test_main_missing_conf(self):
@@ -115,10 +131,10 @@ class OSRefstackClientTesting(unittest.TestCase):
self._test_main_missing_keyword('testlist')
def _test_argparser(self, arg, value):
- self.defaultargs[arg] = value
- parser = refstack_client.RefstackClientParser()
+ self.default_args[arg] = value
+ parser = RefstackClientParser()
self.assertEqual(parser.parse_args(["--{}={}".format(arg, value)]),
- self.defaultargs)
+ self.default_args)
def test_argparser_conf(self):
self._test_argparser('config', self._config)
@@ -127,13 +143,13 @@ class OSRefstackClientTesting(unittest.TestCase):
self._test_argparser('testlist', self._testlist)
def test_argparser_multiple_args(self):
- self.defaultargs['config'] = self._config
- self.defaultargs['testlist'] = self._testlist
- parser = refstack_client.RefstackClientParser()
+ self.default_args['config'] = self._config
+ self.default_args['testlist'] = self._testlist
+ parser = RefstackClientParser()
self.assertEqual(parser.parse_args(
["--config={}".format(self._config),
"--testlist={}".format(self._testlist)
- ]), self.defaultargs)
+ ]), self.default_args)
if __name__ == "__main__":
diff --git a/functest/tests/unit/openstack/tempest/test_conf_utils.py b/functest/tests/unit/openstack/tempest/test_conf_utils.py
index bbfcc57d..77558086 100644
--- a/functest/tests/unit/openstack/tempest/test_conf_utils.py
+++ b/functest/tests/unit/openstack/tempest/test_conf_utils.py
@@ -10,71 +10,83 @@ import unittest
import mock
-from functest.opnfv_tests.openstack.tempest import conf_utils
+from functest.opnfv_tests.openstack.tempest import tempest, conf_utils
from functest.utils.constants import CONST
+from snaps.openstack.os_credentials import OSCreds
class OSTempestConfUtilsTesting(unittest.TestCase):
- def test_create_tempest_resources_missing_network_dic(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_keystone_client',
- return_value=mock.Mock()), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.create_shared_network_full',
- return_value=None), \
- self.assertRaises(Exception) as context:
- conf_utils.create_tempest_resources()
- msg = 'Failed to create private network'
- self.assertTrue(msg in context)
-
- def test_create_tempest_resources_missing_image(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_keystone_client',
- return_value=mock.Mock()), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.create_shared_network_full',
- return_value=mock.Mock()), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_or_create_image',
- return_value=(mock.Mock(), None)), \
- self.assertRaises(Exception) as context:
-
- CONST.__setattr__('tempest_use_custom_images', True)
- conf_utils.create_tempest_resources()
- msg = 'Failed to create image'
- self.assertTrue(msg in context)
-
- CONST.__setattr__('tempest_use_custom_images', False)
- conf_utils.create_tempest_resources(use_custom_images=True)
- msg = 'Failed to create image'
- self.assertTrue(msg in context)
-
- def test_create_tempest_resources_missing_flavor(self):
- with mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_keystone_client',
- return_value=mock.Mock()), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.create_shared_network_full',
- return_value=mock.Mock()), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_or_create_image',
- return_value=(mock.Mock(), 'image_id')), \
- mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
- 'os_utils.get_or_create_flavor',
- return_value=(mock.Mock(), None)), \
- self.assertRaises(Exception) as context:
- CONST.__setattr__('tempest_use_custom_images', True)
- CONST.__setattr__('tempest_use_custom_flavors', True)
- conf_utils.create_tempest_resources()
- msg = 'Failed to create flavor'
- self.assertTrue(msg in context)
-
- CONST.__setattr__('tempest_use_custom_images', True)
- CONST.__setattr__('tempest_use_custom_flavors', False)
- conf_utils.create_tempest_resources(use_custom_flavors=False)
- msg = 'Failed to create flavor'
- self.assertTrue(msg in context)
+ def setUp(self):
+ self.os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_project',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_user',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_network',
+ return_value=None)
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_image',
+ return_value=mock.Mock())
+ def test_create_tempest_resources_missing_network_dic(self, *mock_args):
+ tempest_resources = tempest.TempestResourcesManager(os_creds={})
+ with self.assertRaises(Exception) as context:
+ tempest_resources.create()
+ msg = 'Failed to create private network'
+ self.assertTrue(msg in context.exception)
+
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_project',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_user',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_network',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_image',
+ return_value=None)
+ def test_create_tempest_resources_missing_image(self, *mock_args):
+ tempest_resources = tempest.TempestResourcesManager(os_creds={})
+
+ CONST.__setattr__('tempest_use_custom_imagess', True)
+ with self.assertRaises(Exception) as context:
+ tempest_resources.create()
+ msg = 'Failed to create image'
+ self.assertTrue(msg in context.exception, msg=str(context.exception))
+
+ CONST.__setattr__('tempest_use_custom_imagess', False)
+ with self.assertRaises(Exception) as context:
+ tempest_resources.create(use_custom_images=True)
+ msg = 'Failed to create image'
+ self.assertTrue(msg in context.exception, msg=str(context.exception))
+
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_project',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_user',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_network',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.utils.deploy_utils.create_image',
+ return_value=mock.Mock())
+ @mock.patch('snaps.openstack.create_flavor.OpenStackFlavor.create',
+ return_value=None)
+ def test_create_tempest_resources_missing_flavor(self, *mock_args):
+ tempest_resources = tempest.TempestResourcesManager(
+ os_creds=self.os_creds)
+
+ CONST.__setattr__('tempest_use_custom_images', True)
+ CONST.__setattr__('tempest_use_custom_flavors', True)
+ with self.assertRaises(Exception) as context:
+ tempest_resources.create()
+ msg = 'Failed to create flavor'
+ self.assertTrue(msg in context.exception, msg=str(context.exception))
+
+ CONST.__setattr__('tempest_use_custom_images', True)
+ CONST.__setattr__('tempest_use_custom_flavors', False)
+ with self.assertRaises(Exception) as context:
+ tempest_resources.create(use_custom_flavors=True)
+ msg = 'Failed to create flavor'
+ self.assertTrue(msg in context.exception, msg=str(context.exception))
def test_get_verifier_id_missing_verifier(self):
CONST.__setattr__('tempest_deployment_name', 'test_deploy_name')
@@ -158,23 +170,9 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
def test_backup_tempest_config_default(self):
with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.exists',
- return_value=False), \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.makedirs') as m1, \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.shutil.copyfile') as m2:
+ 'conf_utils.shutil.copyfile') as m1:
conf_utils.backup_tempest_config('test_conf_file')
self.assertTrue(m1.called)
- self.assertTrue(m2.called)
-
- with mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.os.path.exists',
- return_value=True), \
- mock.patch('functest.opnfv_tests.openstack.tempest.'
- 'conf_utils.shutil.copyfile') as m2:
- conf_utils.backup_tempest_config('test_conf_file')
- self.assertTrue(m2.called)
def test_configure_tempest_default(self):
with mock.patch('functest.opnfv_tests.openstack.tempest.'
@@ -186,10 +184,6 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
self.assertTrue(m1.called)
def test_configure_tempest_defcore_default(self):
- img_flavor_dict = {'image_id': 'test_image_id',
- 'flavor_id': 'test_flavor_id',
- 'image_id_alt': 'test_image_alt_id',
- 'flavor_id_alt': 'test_flavor_alt_id'}
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.configure_verifier',
return_value='test_conf_file'), \
@@ -206,9 +200,12 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
'write') as mwrite, \
mock.patch('__builtin__.open', mock.mock_open()), \
mock.patch('functest.opnfv_tests.openstack.tempest.'
+ 'conf_utils.generate_test_accounts_file'), \
+ mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.shutil.copyfile'):
- conf_utils.configure_tempest_defcore('test_dep_dir',
- img_flavor_dict)
+ conf_utils.configure_tempest_defcore(
+ 'test_dep_dir', 'test_image_id', 'test_flavor_id',
+ 'test_image_alt_id', 'test_flavor_alt_id', 'test_tenant_id')
mset.assert_any_call('compute', 'image_ref', 'test_image_id')
mset.assert_any_call('compute', 'image_ref_alt',
'test_image_alt_id')
@@ -218,6 +215,13 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
self.assertTrue(mread.called)
self.assertTrue(mwrite.called)
+ def test_generate_test_accounts_file_default(self):
+ with mock.patch("__builtin__.open", mock.mock_open()), \
+ mock.patch('functest.opnfv_tests.openstack.tempest.conf_utils.'
+ 'yaml.dump') as mock_dump:
+ conf_utils.generate_test_accounts_file('test_tenant_id')
+ self.assertTrue(mock_dump.called)
+
def _test_missing_param(self, params, image_id, flavor_id):
with mock.patch('functest.opnfv_tests.openstack.tempest.'
'conf_utils.ConfigParser.RawConfigParser.'
@@ -236,8 +240,8 @@ class OSTempestConfUtilsTesting(unittest.TestCase):
CONST.__setattr__('OS_ENDPOINT_TYPE', None)
conf_utils.\
configure_tempest_update_params('test_conf_file',
- IMAGE_ID=image_id,
- FLAVOR_ID=flavor_id)
+ image_id=image_id,
+ flavor_id=flavor_id)
mset.assert_any_call(params[0], params[1], params[2])
self.assertTrue(mread.called)
self.assertTrue(mwrite.called)
diff --git a/functest/tests/unit/openstack/tempest/test_tempest.py b/functest/tests/unit/openstack/tempest/test_tempest.py
index d5016f71..54d7d49b 100644
--- a/functest/tests/unit/openstack/tempest/test_tempest.py
+++ b/functest/tests/unit/openstack/tempest/test_tempest.py
@@ -15,10 +15,16 @@ from functest.opnfv_tests.openstack.tempest import tempest
from functest.opnfv_tests.openstack.tempest import conf_utils
from functest.utils.constants import CONST
+from snaps.openstack.os_credentials import OSCreds
+
class OSTempestTesting(unittest.TestCase):
def setUp(self):
+ os_creds = OSCreds(
+ username='user', password='pass',
+ auth_url='http://foo.com:5000/v3', project_name='bar')
+
with mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'conf_utils.get_verifier_id',
return_value='test_deploy_id'), \
@@ -30,7 +36,9 @@ class OSTempestTesting(unittest.TestCase):
return_value='test_verifier_repo_dir'), \
mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'conf_utils.get_verifier_deployment_dir',
- return_value='test_verifier_deploy_dir'):
+ return_value='test_verifier_deploy_dir'), \
+ mock.patch('snaps.openstack.tests.openstack_tests.get_credentials',
+ return_value=os_creds):
self.tempestcommon = tempest.TempestCommon()
self.tempestsmoke_serial = tempest.TempestSmokeSerial()
self.tempestsmoke_parallel = tempest.TempestSmokeParallel()
@@ -153,8 +161,8 @@ class OSTempestTesting(unittest.TestCase):
'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):
+ 'TempestResourcesManager.create', side_effect=Exception)
+ def test_run_tempest_create_resources_ko(self, *args):
self.assertEqual(self.tempestcommon.run(),
testcase.TestCase.EX_RUN_ERROR)
@@ -162,7 +170,7 @@ class OSTempestTesting(unittest.TestCase):
'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={})
+ 'TempestResourcesManager.create', 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):
@@ -173,7 +181,7 @@ class OSTempestTesting(unittest.TestCase):
'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={})
+ 'TempestResourcesManager.create', return_value={})
@mock.patch('functest.opnfv_tests.openstack.tempest.tempest.'
'conf_utils.configure_tempest')
def _test_run(self, status, *args):
diff --git a/functest/tests/unit/openstack/vping/test_vping.py b/functest/tests/unit/openstack/vping/test_vping.py
index b229c351..a28c61ae 100644
--- a/functest/tests/unit/openstack/vping/test_vping.py
+++ b/functest/tests/unit/openstack/vping/test_vping.py
@@ -50,8 +50,6 @@ class VPingUserdataTesting(unittest.TestCase):
'vm_active', return_value=True)
def test_vping_userdata(self, deploy_vm, path_exists, create_flavor,
get_port_ip, vm_active):
- os_vm_inst = mock.MagicMock(name='get_console_output')
- os_vm_inst.get_console_output.return_value = 'vPing OK'
with mock.patch('snaps.openstack.utils.deploy_utils.create_image',
return_value=OpenStackImage(self.os_creds, None)), \
mock.patch('snaps.openstack.utils.deploy_utils.create_network',
@@ -67,8 +65,8 @@ class VPingUserdataTesting(unittest.TestCase):
name='foo', network_name='bar')]),
None)), \
mock.patch('snaps.openstack.create_instance.'
- 'OpenStackVmInstance.get_os_vm_server_obj',
- return_value=os_vm_inst):
+ 'OpenStackVmInstance.get_console_output',
+ return_value='vPing OK'):
self.assertEquals(TestCase.EX_OK, self.vping_userdata.run())
diff --git a/functest/tests/unit/utils/test_functest_utils.py b/functest/tests/unit/utils/test_functest_utils.py
index b4cc5b73..17fb4c1f 100644
--- a/functest/tests/unit/utils/test_functest_utils.py
+++ b/functest/tests/unit/utils/test_functest_utils.py
@@ -97,42 +97,6 @@ class FunctestUtilsTesting(unittest.TestCase):
m.assert_called_once_with(dest, 'wb')
self.assertTrue(mock_sh.called)
- @mock.patch('functest.utils.functest_utils.logger.error')
- def test_get_installer_type_failed(self, mock_logger_error):
- with mock.patch.dict(os.environ,
- {},
- clear=True):
- self.assertEqual(functest_utils.get_installer_type(),
- "Unknown_installer")
- mock_logger_error.assert_called_once_with("Impossible to retrieve"
- " the installer type")
-
- def test_get_installer_type_default(self):
- with mock.patch.dict(os.environ,
- {'INSTALLER_TYPE': 'test_installer'},
- clear=True):
- self.assertEqual(functest_utils.get_installer_type(),
- self.installer)
-
- @mock.patch('functest.utils.functest_utils.logger.info')
- def test_get_scenario_failed(self, mock_logger_info):
- with mock.patch.dict(os.environ,
- {},
- clear=True):
- self.assertEqual(functest_utils.get_scenario(),
- "os-nosdn-nofeature-noha")
- mock_logger_info.assert_called_once_with("Impossible to retrieve "
- "the scenario.Use "
- "default "
- "os-nosdn-nofeature-noha")
-
- def test_get_scenario_default(self):
- with mock.patch.dict(os.environ,
- {'DEPLOY_SCENARIO': 'test_scenario'},
- clear=True):
- self.assertEqual(functest_utils.get_scenario(),
- self.scenario)
-
def test_get_version_daily_job(self):
CONST.__setattr__('BUILD_TAG', self.build_tag)
self.assertEqual(functest_utils.get_version(), self.version)
@@ -150,34 +114,13 @@ class FunctestUtilsTesting(unittest.TestCase):
self.assertEqual(functest_utils.get_version(), "unknown")
@mock.patch('functest.utils.functest_utils.logger.info')
- def test_get_pod_name_failed(self, mock_logger_info):
- with mock.patch.dict(os.environ,
- {},
- clear=True):
- self.assertEqual(functest_utils.get_pod_name(),
- "unknown-pod")
- mock_logger_info.assert_called_once_with("Unable to retrieve "
- "the POD name from "
- "environment. Using "
- "pod name 'unknown-pod'")
-
- def test_get_pod_name_default(self):
- with mock.patch.dict(os.environ,
- {'NODE_NAME': 'test_node_name'},
- clear=True):
- self.assertEqual(functest_utils.get_pod_name(),
- self.node_name)
-
- @mock.patch('functest.utils.functest_utils.logger.info')
def test_logger_test_results(self, mock_logger_info):
CONST.__setattr__('results_test_db_url', self.db_url)
CONST.__setattr__('BUILD_TAG', self.build_tag)
- with mock.patch('functest.utils.functest_utils.get_pod_name',
- return_value=self.node_name), \
- mock.patch('functest.utils.functest_utils.get_scenario',
- return_value=self.scenario), \
- mock.patch('functest.utils.functest_utils.get_version',
- return_value=self.version):
+ CONST.__setattr__('NODE_NAME', self.node_name)
+ CONST.__setattr__('DEPLOY_SCENARIO', self.scenario)
+ with mock.patch('functest.utils.functest_utils.get_version',
+ return_value=self.version):
functest_utils.logger_test_results(self.project, self.case_name,
self.status, self.details)
mock_logger_info.assert_called_once_with(
diff --git a/functest/tests/unit/utils/test_openstack_tacker.py b/functest/tests/unit/utils/test_openstack_tacker.py
deleted file mode 100644
index 3c0fc3d0..00000000
--- a/functest/tests/unit/utils/test_openstack_tacker.py
+++ /dev/null
@@ -1,524 +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 tackerclient.v1_0 import client as tackerclient
-
-from functest.utils import openstack_tacker
-from functest.tests.unit import test_utils
-
-
-class OSTackerTesting(unittest.TestCase):
-
- def setUp(self):
- self.tacker_client = mock.Mock()
- self.getresponse = {'vnfds': [{'id': 'test_id'}],
- 'vnfs': [{'id': 'test_id'}],
- 'sfcs': [{'id': 'test_id'}]}
- self.vnfdlist = {'vnfds': [{'id': 'test_vnfd1'}, {'id': 'test_vnfd2'}]}
- self.vnflist = {'vnfs': [{'id': 'test_vnf1'}, {'id': 'test_vnf2'}]}
- self.sfclist = {'sfcs': [{'id': 'test_sfc1'}, {'id': 'test_sfc2'}]}
- self.sfc_classifierlist = {'sfc_classifiers': [{'id': 'test_sfc_cl1'},
- {'id': 'test_sfc_cl2'}]}
-
- self.createvnfd = {"vnfd": {"attributes": {"vnfd": 'vnfd_body'}}}
- self.createvnf = {"vnf": {"attributes": {"vnf": 'vnf_body'}}}
- self.createsfc = {"sfc": {"attributes": {"sfc": 'sfc_body'}}}
- self.createsfc_clf = {"sfc_classifier": {"attributes":
- {"sfc_clf": 'sfc_clf_body'}}}
-
- self.resource_type = 'vnfd'
- self.resource_name = 'resource_name'
- self.tosca_file = 'test_tosca_file'
- self.vnfd = 'test_vnfd'
- self.vnf = 'test_vnf'
- self.sfc = 'test_sfc'
- self.sfc_clf = 'test_sfc_clf'
-
- def _get_creds(self):
- cred_dict = {
- 'OS_USERNAME': 'username',
- 'OS_PASSWORD': 'password',
- 'OS_AUTH_URL': 'auth_url',
- 'OS_TENANT_NAME': 'tenant_name',
- 'OS_USER_DOMAIN_NAME': 'user_domain_name',
- 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
- 'OS_PROJECT_NAME': 'project_name',
- 'OS_ENDPOINT_TYPE': 'endpoint_type',
- 'OS_REGION_NAME': 'region_name'
- }
- return cred_dict
-
- def test_get_tacker_client(self):
- with mock.patch('functest.utils.openstack_tacker.'
- 'os_utils.get_session'):
- tackerclient.Client = mock.Mock
- ret = openstack_tacker.get_tacker_client()
- self.assertTrue(isinstance(ret, mock.Mock))
-
- def test_get_id_from_name(self):
- with mock.patch.object(self.tacker_client, 'get',
- return_value=self.getresponse):
- resp = openstack_tacker.get_id_from_name(self.tacker_client,
- self.resource_type,
- self.resource_name)
- self.assertEqual(resp, 'test_id')
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_get_id_from_name_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'get',
- side_effect=Exception):
- resp = openstack_tacker.get_id_from_name(self.tacker_client,
- self.resource_type,
- self.resource_name)
- self.assertIsNone(resp)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error [get"
- "_id_from_"
- "name(tacker"
- "_client"
- ", resource_"
- "type, "
- "resource_"
- "name)]:"))
-
- @mock.patch('functest.utils.openstack_tacker.get_id_from_name')
- def test_get_vnfd_id(self, mock_get_id_from_name):
- openstack_tacker.get_vnfd_id(self.tacker_client, self.resource_name)
- mock_get_id_from_name.assert_called_once_with(self.tacker_client,
- 'vnfd',
- self.resource_name)
-
- @mock.patch('functest.utils.openstack_tacker.get_id_from_name')
- def test_get_vnf_id(self, mock_get_id_from_name):
- openstack_tacker.get_vnf_id(self.tacker_client, self.resource_name)
- mock_get_id_from_name.assert_called_once_with(self.tacker_client,
- 'vnf',
- self.resource_name)
-
- @mock.patch('functest.utils.openstack_tacker.get_id_from_name')
- def test_get_sfc_id(self, mock_get_id_from_name):
- openstack_tacker.get_sfc_id(self.tacker_client, self.resource_name)
- mock_get_id_from_name.assert_called_once_with(self.tacker_client,
- 'sfc',
- self.resource_name)
-
- @mock.patch('functest.utils.openstack_tacker.get_id_from_name')
- def test_get_sfc_classifier_id(self, mock_get_id_from_name):
- openstack_tacker.get_sfc_classifier_id(self.tacker_client,
- self.resource_name)
- mock_get_id_from_name.assert_called_once_with(self.tacker_client,
- 'sfc-classifier',
- self.resource_name)
-
- def test_list_vnfds(self):
- with mock.patch.object(self.tacker_client, 'list_vnfds',
- return_value=self.vnfdlist):
- resp = openstack_tacker.list_vnfds(self.tacker_client,
- verbose=False)
- self.assertEqual(resp, ['test_vnfd1', 'test_vnfd2'])
-
- def test_list_vnfds_verbose(self):
- with mock.patch.object(self.tacker_client, 'list_vnfds',
- return_value=self.vnfdlist):
- resp = openstack_tacker.list_vnfds(self.tacker_client,
- verbose=True)
- self.assertEqual(resp, self.vnfdlist)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_list_vnfds_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'list_vnfds',
- side_effect=Exception):
- resp = openstack_tacker.list_vnfds(self.tacker_client,
- verbose=False)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error"
- " [list"
- "_vnfds("
- "tacker_"
- "client)]:"))
- self.assertIsNone(resp)
-
- def test_create_vnfd_missing_file(self):
- with mock.patch.object(self.tacker_client, 'create_vnfd',
- return_value=self.createvnfd):
- resp = openstack_tacker.create_vnfd(self.tacker_client,
- tosca_file=None)
- self.assertEqual(resp, self.createvnfd)
-
- def test_create_vnfd_default(self):
- with mock.patch.object(self.tacker_client, 'create_vnfd',
- return_value=self.createvnfd), \
- mock.patch('__builtin__.open', mock.mock_open(read_data='1')) \
- as m:
- resp = openstack_tacker.create_vnfd(self.tacker_client,
- tosca_file=self.tosca_file)
- m.assert_called_once_with(self.tosca_file)
- self.assertEqual(resp, self.createvnfd)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_create_vnfd_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'create_vnfd',
- side_effect=Exception):
- resp = openstack_tacker.create_vnfd(self.tacker_client,
- tosca_file=self.tosca_file)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error"
- " [create"
- "_vnfd("
- "tacker_"
- "client, "
- "'%s')]"
- % self.
- tosca_file))
- self.assertIsNone(resp)
-
- def test_delete_vnfd(self):
- with mock.patch('functest.utils.openstack_tacker.get_vnfd_id',
- return_value=self.vnfd), \
- mock.patch.object(self.tacker_client, 'delete_vnfd',
- return_value=self.vnfd):
- resp = openstack_tacker.delete_vnfd(self.tacker_client,
- vnfd_id='vnfd_id',
- vnfd_name=self.vnfd)
- self.assertEqual(resp, self.vnfd)
-
- def test_delete_vnfd_missing_vnfd_name(self):
- with mock.patch('functest.utils.openstack_tacker.get_vnfd_id',
- return_value=self.vnfd), \
- self.assertRaises(Exception) as context:
- resp = openstack_tacker.delete_vnfd(self.tacker_client,
- vnfd_id=None,
- vnfd_name=None)
- self.assertIsNone(resp)
- msg = 'You need to provide VNFD id or VNFD name'
- self.assertTrue(msg in context)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_delete_vnfd_exception(self, mock_logger_error):
- with mock.patch('functest.utils.openstack_tacker.get_vnfd_id',
- return_value=self.vnfd), \
- mock.patch.object(self.tacker_client, 'delete_vnfd',
- side_effect=Exception):
- resp = openstack_tacker.delete_vnfd(self.tacker_client,
- vnfd_id=None,
- vnfd_name=None)
- self.assertIsNone(resp)
- self.assertTrue(mock_logger_error.called)
-
- def test_list_vnfs(self):
- with mock.patch.object(self.tacker_client, 'list_vnfs',
- return_value=self.vnflist):
- resp = openstack_tacker.list_vnfs(self.tacker_client,
- verbose=False)
- self.assertEqual(resp, ['test_vnf1', 'test_vnf2'])
-
- def test_list_vnfs_verbose(self):
- with mock.patch.object(self.tacker_client, 'list_vnfs',
- return_value=self.vnflist):
- resp = openstack_tacker.list_vnfs(self.tacker_client,
- verbose=True)
- self.assertEqual(resp, self.vnflist)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_list_vnfs_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'list_vnfs',
- side_effect=Exception):
- resp = openstack_tacker.list_vnfs(self.tacker_client,
- verbose=False)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error"
- " [list"
- "_vnfs("
- "tacker_"
- "client)]:"))
- self.assertIsNone(resp)
-
- def test_create_vnf_default(self):
- with mock.patch.object(self.tacker_client, 'create_vnf',
- return_value=self.createvnf), \
- mock.patch('functest.utils.openstack_tacker.get_vnfd_id',
- return_value=self.vnf):
- resp = openstack_tacker.create_vnf(self.tacker_client,
- vnf_name=self.vnf,
- vnfd_id='vnfd_id',
- vnfd_name=self.vnfd)
- self.assertEqual(resp, self.createvnf)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_create_vnf_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'create_vnf',
- side_effect=Exception):
- resp = openstack_tacker.create_vnf(self.tacker_client,
- vnf_name=self.vnf,
- vnfd_id='vnfd_id',
- vnfd_name=self.vnfd)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("error"
- " [create"
- "_vnf("
- "tacker_"
- "client"))
- self.assertIsNone(resp)
-
- def test_wait_for_vnf_vnf_retrieval_failed(self):
- with mock.patch('functest.utils.openstack_tacker.get_vnf',
- return_value=None), \
- self.assertRaises(Exception) as context:
- openstack_tacker.wait_for_vnf(self.tacker_client,
- vnf_id='vnf_id',
- vnf_name='vnf_name')
- msg = ("Could not retrieve VNF - id='vnf_id', "
- "name='vnf_name'")
- self.assertTrue(msg in context)
- with mock.patch('functest.utils.openstack_tacker.get_vnf',
- side_effect=Exception):
- ret = openstack_tacker.wait_for_vnf(self.tacker_client,
- vnf_id='vnf_id',
- vnf_name='vnf_name')
- self.assertEqual(ret, None)
-
- def test_wait_for_vnf_vnf_status_error(self):
- vnf = {'id': 'vnf_id',
- 'status': 'ERROR'}
- with mock.patch('functest.utils.openstack_tacker.get_vnf',
- return_value=vnf), \
- self.assertRaises(Exception) as context:
- openstack_tacker.wait_for_vnf(self.tacker_client,
- vnf_id='vnf_id',
- vnf_name='vnf_name')
- msg = ('Error when booting vnf vnf_id')
- self.assertTrue(msg in context)
-
- def test_wait_for_vnf_vnf_timeout(self):
- vnf = {'id': 'vnf_id',
- 'status': 'PENDING_CREATE'}
- with mock.patch('functest.utils.openstack_tacker.get_vnf',
- return_value=vnf), \
- self.assertRaises(Exception) as context:
- openstack_tacker.wait_for_vnf(self.tacker_client,
- vnf_id='vnf_id',
- vnf_name='vnf_name',
- timeout=2)
- msg = ('Timeout when booting vnf vnf_id')
- self.assertTrue(msg in context)
-
- def test_delete_vnf(self):
- with mock.patch('functest.utils.openstack_tacker.get_vnf_id',
- return_value=self.vnf), \
- mock.patch.object(self.tacker_client, 'delete_vnf',
- return_value=self.vnf):
- resp = openstack_tacker.delete_vnf(self.tacker_client,
- vnf_id='vnf_id',
- vnf_name=self.vnf)
- self.assertEqual(resp, self.vnf)
-
- def test_delete_vnf_missing_vnf_name(self):
- with self.assertRaises(Exception) as context:
- openstack_tacker.delete_vnf(self.tacker_client,
- vnf_id=None,
- vnf_name=None)
- msg = 'You need to provide a VNF id or name'
- self.assertTrue(msg in context)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_delete_vnf_exception(self, mock_logger_error):
- with mock.patch('functest.utils.openstack_tacker.get_vnf_id',
- return_value=self.vnf), \
- mock.patch.object(self.tacker_client, 'delete_vnf',
- side_effect=Exception):
- resp = openstack_tacker.delete_vnf(self.tacker_client,
- vnf_id=None,
- vnf_name=None)
- self.assertIsNone(resp)
- self.assertTrue(mock_logger_error.called)
-
- def test_list_sfcs(self):
- with mock.patch.object(self.tacker_client, 'list_sfcs',
- return_value=self.sfclist):
- resp = openstack_tacker.list_sfcs(self.tacker_client,
- verbose=False)
- self.assertEqual(resp, ['test_sfc1', 'test_sfc2'])
-
- def test_list_sfcs_verbose(self):
- with mock.patch.object(self.tacker_client, 'list_sfcs',
- return_value=self.sfclist):
- resp = openstack_tacker.list_sfcs(self.tacker_client,
- verbose=True)
- self.assertEqual(resp, self.sfclist)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_list_sfcs_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'list_sfcs',
- side_effect=Exception):
- resp = openstack_tacker.list_sfcs(self.tacker_client,
- verbose=False)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error"
- " [list"
- "_sfcs("
- "tacker_"
- "client)]:"))
- self.assertIsNone(resp)
-
- def test_create_sfc_default(self):
- with mock.patch.object(self.tacker_client, 'create_sfc',
- return_value=self.createsfc), \
- mock.patch('functest.utils.openstack_tacker.get_vnf_id',
- return_value=self.vnf):
- resp = openstack_tacker.create_sfc(self.tacker_client,
- sfc_name=self.sfc,
- chain_vnf_ids=['chain_vnf_id'],
- chain_vnf_names=[self.vnf])
- self.assertEqual(resp, self.createsfc)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_create_sfc_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'create_sfc',
- side_effect=Exception):
- resp = openstack_tacker.create_sfc(self.tacker_client,
- sfc_name=self.sfc,
- chain_vnf_ids=['chain_vnf_id'],
- chain_vnf_names=[self.vnf])
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("error"
- " [create"
- "_sfc("
- "tacker_"
- "client"))
- self.assertIsNone(resp)
-
- def test_delete_sfc(self):
- with mock.patch('functest.utils.openstack_tacker.get_sfc_id',
- return_value=self.sfc), \
- mock.patch.object(self.tacker_client, 'delete_sfc',
- return_value=self.sfc):
- resp = openstack_tacker.delete_sfc(self.tacker_client,
- sfc_id='sfc_id',
- sfc_name=self.sfc)
- self.assertEqual(resp, self.sfc)
-
- def test_delete_sfc_missing_sfc_name(self):
- with self.assertRaises(Exception) as context:
- openstack_tacker.delete_sfc(self.tacker_client,
- sfc_id=None,
- sfc_name=None)
- msg = 'You need to provide an SFC id or name'
- self.assertTrue(msg in context)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_delete_sfc_exception(self, mock_logger_error):
- with mock.patch('functest.utils.openstack_tacker.get_sfc_id',
- return_value=self.sfc), \
- mock.patch.object(self.tacker_client, 'delete_sfc',
- side_effect=Exception):
- resp = openstack_tacker.delete_sfc(self.tacker_client,
- sfc_id=None,
- sfc_name=None)
- self.assertIsNone(resp)
- self.assertTrue(mock_logger_error.called)
-
- def test_list_sfc_classifiers(self):
- with mock.patch.object(self.tacker_client, 'list_sfc_classifiers',
- return_value=self.sfc_classifierlist):
- resp = openstack_tacker.list_sfc_classifiers(self.tacker_client,
- verbose=False)
- self.assertEqual(resp, ['test_sfc_cl1', 'test_sfc_cl2'])
-
- def test_list_sfc_classifiers_verbose(self):
- with mock.patch.object(self.tacker_client, 'list_sfc_classifiers',
- return_value=self.sfc_classifierlist):
- resp = openstack_tacker.list_sfc_classifiers(self.tacker_client,
- verbose=True)
- self.assertEqual(resp, self.sfc_classifierlist)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_list_sfc_classifiers_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'list_sfc_classifiers',
- side_effect=Exception):
- resp = openstack_tacker.list_sfc_classifiers(self.tacker_client,
- verbose=False)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("Error"
- " [list"
- "_sfc_cl"
- "assifiers("
- "tacker_"
- "client)]:"))
- self.assertIsNone(resp)
-
- def test_create_sfc_classifier_default(self):
- with mock.patch.object(self.tacker_client, 'create_sfc_classifier',
- return_value=self.createsfc_clf), \
- mock.patch('functest.utils.openstack_tacker.get_sfc_id',
- return_value=self.sfc):
- cl = self.sfc_clf
- resp = openstack_tacker.create_sfc_classifier(self.tacker_client,
- sfc_clf_name=cl,
- sfc_id='sfc_id',
- sfc_name=self.sfc)
- self.assertEqual(resp, self.createsfc_clf)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_sfc_classifier_exception(self, mock_logger_error):
- with mock.patch.object(self.tacker_client, 'create_sfc_classifier',
- side_effect=Exception):
- cl = self.sfc_clf
- resp = openstack_tacker.create_sfc_classifier(self.tacker_client,
- sfc_clf_name=cl,
- sfc_id='sfc_id',
- sfc_name=self.sfc)
- mock_logger_error.assert_called_once_with(test_utils.
- SubstrMatch("error"
- " [create"
- "_sfc_cl"
- "assifier("
- "tacker_"
- "client"))
- self.assertIsNone(resp)
-
- def test_delete_sfc_classifier(self):
- with mock.patch('functest.utils.openstack_tacker.get_sfc_'
- 'classifier_id',
- return_value=self.sfc_clf), \
- mock.patch.object(self.tacker_client, 'delete_sfc_classifier',
- return_value=self.sfc_clf):
- cl = self.sfc_clf
- resp = openstack_tacker.delete_sfc_classifier(self.tacker_client,
- sfc_clf_id='sfc_id',
- sfc_clf_name=cl)
- self.assertEqual(resp, cl)
-
- def test_delete_sfc_classifier_missing_sfc_name(self):
- with self.assertRaises(Exception) as context:
- openstack_tacker.delete_vnf(self.tacker_client,
- sfc_clf_id=None,
- sfc_clf_name=None)
- msg = 'You need to provide an SFCclassifier id or name'
- self.assertTrue(msg in context)
-
- @mock.patch('functest.utils.openstack_tacker.logger.error')
- def test_delete_sfc_classifier_exception(self, mock_logger_error):
- with mock.patch('functest.utils.openstack_tacker.get_sfc_'
- 'classifier_id',
- return_value=self.sfc_clf), \
- mock.patch.object(self.tacker_client, 'delete_sfc_classifier',
- side_effect=Exception):
- cl = self.sfc_clf
- resp = openstack_tacker.delete_sfc_classifier(self.tacker_client,
- sfc_clf_id='sfc_id',
- sfc_clf_name=cl)
- self.assertIsNone(resp)
- self.assertTrue(mock_logger_error.called)
-
-
-if __name__ == "__main__":
- logging.disable(logging.CRITICAL)
- unittest.main(verbosity=2)
diff --git a/functest/opnfv_tests/sdn/onos/teston/adapters/__init__.py b/functest/tests/unit/vnf/router/__init__.py
index e69de29b..e69de29b 100644
--- a/functest/opnfv_tests/sdn/onos/teston/adapters/__init__.py
+++ b/functest/tests/unit/vnf/router/__init__.py
diff --git a/functest/tests/unit/vnf/router/test_cloudify_vrouter.py b/functest/tests/unit/vnf/router/test_cloudify_vrouter.py
new file mode 100644
index 00000000..7f2091be
--- /dev/null
+++ b/functest/tests/unit/vnf/router/test_cloudify_vrouter.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import logging
+import unittest
+
+import mock
+
+from functest.core import vnf
+from functest.opnfv_tests.vnf.router import cloudify_vrouter
+
+from snaps.openstack.os_credentials import OSCreds
+
+
+class CloudifyVrouterTesting(unittest.TestCase):
+
+ def setUp(self):
+
+ self.tenant = 'cloudify_vrouter'
+ self.creds = {'username': 'user',
+ 'password': 'pwd'}
+ self.orchestrator = {'name': 'cloudify',
+ 'version': '4.0',
+ 'object': 'foo',
+ 'requirements': {'flavor': {'name': 'm1.medium',
+ 'ram_min': 4096},
+ 'os_image': 'manager_4.0'}}
+
+ self.vnf = {'name': 'vrouter',
+ 'descriptor': {'version': '100',
+ 'file_name': 'function-test-' +
+ 'openstack-blueprint.yaml',
+ 'name': 'vrouter-opnfv',
+ 'url': 'https://foo',
+ 'requirements': {'flavor':
+ {'name': 'm1.medium',
+ 'ram_min': 2048}}}}
+
+ with mock.patch('functest.opnfv_tests.vnf.router.cloudify_vrouter.'
+ 'os.makedirs'), \
+ mock.patch('functest.opnfv_tests.vnf.router.cloudify_vrouter.'
+ 'get_config', return_value={
+ 'tenant_images': 'foo',
+ 'orchestrator': self.orchestrator,
+ 'vnf': self.vnf,
+ 'vnf_test_suite': '',
+ 'version': 'whatever'}):
+
+ self.router_vnf = cloudify_vrouter.CloudifyVrouter()
+
+ self.images = {'image1': 'url1',
+ 'image2': 'url2'}
+ self.details = {'orchestrator': {'status': 'PASS', 'duration': 120},
+ 'vnf': {},
+ 'test_vnf': {}}
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ return_value='test')
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_tenant_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_user_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_credentials',
+ return_value={'auth_url': 'test/v1'})
+ @mock.patch('snaps.openstack.create_image.OpenStackImage.create')
+ def test_prepare_default(self, *args):
+ self.assertIsNone(self.router_vnf.prepare())
+ args[4].assert_called_once_with()
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ return_value='test')
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_tenant_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_user_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_credentials',
+ return_value={'auth_url': 'test/no_v'})
+ @mock.patch('snaps.openstack.create_image.OpenStackImage.create')
+ def test_prepare_bad_auth_url(self, *args):
+ with self.assertRaises(Exception):
+ self.router_vnf.image_creator(
+ OSCreds(username='user', password='pass', auth_url='url',
+ project_name='project', identity_api_version=3),
+ mock.Mock())
+ args[0].assert_not_called()
+
+ def test_prepare_missing_param(self):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.router_vnf.prepare()
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ side_effect=Exception)
+ def test_prepare_keystone_exception(self, *args):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.router_vnf.prepare()
+ args[0].assert_called_once_with()
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ return_value='test')
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_tenant_for_vnf',
+ side_effect=Exception)
+ def test_prepare_tenant_exception(self, *args):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.router_vnf.prepare()
+ args[1].assert_called_once_with()
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ return_value='test')
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_tenant_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_user_for_vnf',
+ side_effect=Exception)
+ def test_prepare_user_exception(self, *args):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.router_vnf.prepare()
+ args[2].assert_called_once_with()
+
+ @mock.patch('functest.core.vnf.os_utils.get_keystone_client',
+ return_value='test')
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_tenant_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_or_create_user_for_vnf',
+ return_value=True)
+ @mock.patch('functest.core.vnf.os_utils.get_credentials',
+ side_effect=Exception)
+ def test_prepare_credentials_exception(self, *args):
+ with self.assertRaises(vnf.VnfPreparationException):
+ self.router_vnf.prepare()
+ args[0].assert_called_once_with()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/functest/tests/unit/vnf/router/test_vrouter_base.py b/functest/tests/unit/vnf/router/test_vrouter_base.py
new file mode 100644
index 00000000..def201d1
--- /dev/null
+++ b/functest/tests/unit/vnf/router/test_vrouter_base.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2017 Okinawa Open Laboratory and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+
+import logging
+import unittest
+
+import mock
+
+from functest.opnfv_tests.vnf.router import vrouter_base
+
+
+class VrouterOnBoardingBaseTesting(unittest.TestCase):
+
+ def setUp(self):
+ with mock.patch('functest.opnfv_tests.vnf.router.cloudify_vrouter.'
+ 'os.makedirs'):
+ self.vrouter_vnf = vrouter_base.VrouterOnBoardingBase()
+
+
+if __name__ == "__main__":
+ logging.disable(logging.CRITICAL)
+ unittest.main(verbosity=2)
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py
index bf68e43a..e4062373 100644
--- a/functest/utils/functest_utils.py
+++ b/functest/utils/functest_utils.py
@@ -68,33 +68,6 @@ def download_url(url, dest_path):
# CI UTILS
#
# -----------------------------------------------------------
-def get_installer_type():
- """
- Get installer type (fuel, apex, joid, compass)
- """
- try:
- installer = os.environ['INSTALLER_TYPE']
- except KeyError:
- logger.error("Impossible to retrieve the installer type")
- installer = "Unknown_installer"
-
- return installer
-
-
-def get_scenario():
- """
- Get scenario
- """
- try:
- scenario = os.environ['DEPLOY_SCENARIO']
- except KeyError:
- logger.info("Impossible to retrieve the scenario."
- "Use default os-nosdn-nofeature-noha")
- scenario = "os-nosdn-nofeature-noha"
-
- return scenario
-
-
def get_version():
"""
Get version
@@ -117,25 +90,12 @@ def get_version():
return "unknown"
-def get_pod_name():
- """
- Get PoD Name from env variable NODE_NAME
- """
- try:
- return os.environ['NODE_NAME']
- except KeyError:
- logger.info(
- "Unable to retrieve the POD name from environment. " +
- "Using pod name 'unknown-pod'")
- return "unknown-pod"
-
-
def logger_test_results(project, case_name, status, details):
"""
Format test case results for the logger
"""
- pod_name = get_pod_name()
- scenario = get_scenario()
+ pod_name = CONST.__getattribute__('NODE_NAME')
+ scenario = CONST.__getattribute__('DEPLOY_SCENARIO')
version = get_version()
build_tag = CONST.__getattribute__('BUILD_TAG')
db_url = CONST.__getattribute__("results_test_db_url")
@@ -267,14 +227,14 @@ def get_ci_envvars():
def execute_command_raise(cmd, info=False, error_msg="",
- verbose=True, output_file=None):
- ret = execute_command(cmd, info, error_msg, verbose, output_file)
+ verbose=True, output_file=None, env=None):
+ ret = execute_command(cmd, info, error_msg, verbose, output_file, env)
if ret != 0:
raise Exception(error_msg)
def execute_command(cmd, info=False, error_msg="",
- verbose=True, output_file=None):
+ verbose=True, output_file=None, env=None):
if not error_msg:
error_msg = ("The command '%s' failed." % cmd)
msg_exec = ("Executing command: '%s'" % cmd)
@@ -283,7 +243,7 @@ def execute_command(cmd, info=False, error_msg="",
logger.info(msg_exec)
else:
logger.debug(msg_exec)
- p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
+ p = subprocess.Popen(cmd, env=env, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
if output_file:
f = open(output_file, "w")
diff --git a/functest/utils/openstack_tacker.py b/functest/utils/openstack_tacker.py
deleted file mode 100644
index 9fd9d5c4..00000000
--- a/functest/utils/openstack_tacker.py
+++ /dev/null
@@ -1,317 +0,0 @@
-###########################################################################
-# Copyright (c) 2016 Ericsson AB and others.
-# Author: George Paraskevopoulos <geopar@intracom-telecom.com>
-#
-# Wrappers for trozet's python-tackerclient v1.0
-# (https://github.com/trozet/python-tackerclient)
-#
-# 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
-
-from tackerclient.v1_0 import client as tackerclient
-import functest.utils.openstack_utils as os_utils
-import time
-
-logger = logging.getLogger(__name__)
-
-
-def get_tacker_client(other_creds={}):
- sess = os_utils.get_session(other_creds)
- return tackerclient.Client(session=sess)
-
-
-# *********************************************
-# TACKER
-# *********************************************
-def get_id_from_name(tacker_client, resource_type, resource_name):
- try:
- req_params = {'fields': 'id', 'name': resource_name}
- endpoint = '/{0}s'.format(resource_type)
- resp = tacker_client.get(endpoint, params=req_params)
- endpoint = endpoint.replace('-', '_')
- return resp[endpoint[1:]][0]['id']
- except Exception, e:
- logger.error("Error [get_id_from_name(tacker_client, "
- "resource_type, resource_name)]: %s" % e)
- return None
-
-
-def get_vnfd_id(tacker_client, vnfd_name):
- return get_id_from_name(tacker_client, 'vnfd', vnfd_name)
-
-
-def get_vnf_id(tacker_client, vnf_name, timeout=5):
- vnf_id = None
- while vnf_id is None and timeout >= 0:
- vnf_id = get_id_from_name(tacker_client, 'vnf', vnf_name)
- if vnf_id is None:
- logger.info("Could not retrieve ID for vnf with name [%s]."
- " Retrying." % vnf_name)
- time.sleep(1)
- timeout -= 1
- return vnf_id
-
-
-def get_sfc_id(tacker_client, sfc_name):
- return get_id_from_name(tacker_client, 'sfc', sfc_name)
-
-
-def get_sfc_classifier_id(tacker_client, sfc_clf_name):
- return get_id_from_name(tacker_client, 'sfc-classifier', sfc_clf_name)
-
-
-def list_vnfds(tacker_client, verbose=False):
- try:
- vnfds = tacker_client.list_vnfds(retrieve_all=True)
- if not verbose:
- vnfds = [vnfd['id'] for vnfd in vnfds['vnfds']]
- return vnfds
- except Exception, e:
- logger.error("Error [list_vnfds(tacker_client)]: %s" % e)
- return None
-
-
-def create_vnfd(tacker_client, tosca_file=None):
- try:
- vnfd_body = {}
- if tosca_file is not None:
- with open(tosca_file) as tosca_fd:
- vnfd_body = tosca_fd.read()
- logger.info('VNFD template:\n{0}'.format(vnfd_body))
- return tacker_client.create_vnfd(
- body={"vnfd": {"attributes": {"vnfd": vnfd_body}}})
- except Exception, e:
- logger.error("Error [create_vnfd(tacker_client, '%s')]: %s"
- % (tosca_file, e))
- return None
-
-
-def delete_vnfd(tacker_client, vnfd_id=None, vnfd_name=None):
- try:
- vnfd = vnfd_id
- if vnfd is None:
- if vnfd_name is None:
- raise Exception('You need to provide VNFD id or VNFD name')
- vnfd = get_vnfd_id(tacker_client, vnfd_name)
- return tacker_client.delete_vnfd(vnfd)
- except Exception, e:
- logger.error("Error [delete_vnfd(tacker_client, '%s', '%s')]: %s"
- % (vnfd_id, vnfd_name, e))
- return None
-
-
-def list_vnfs(tacker_client, verbose=False):
- try:
- vnfs = tacker_client.list_vnfs(retrieve_all=True)
- if not verbose:
- vnfs = [vnf['id'] for vnf in vnfs['vnfs']]
- return vnfs
- except Exception, e:
- logger.error("Error [list_vnfs(tacker_client)]: %s" % e)
- return None
-
-
-def create_vnf(tacker_client, vnf_name, vnfd_id=None,
- vnfd_name=None, param_file=None):
- try:
- vnf_body = {
- 'vnf': {
- 'attributes': {},
- 'name': vnf_name
- }
- }
- if param_file is not None:
- params = None
- with open(param_file) as f:
- params = f.read()
- vnf_body['vnf']['attributes']['param_values'] = params
- if vnfd_id is not None:
- vnf_body['vnf']['vnfd_id'] = vnfd_id
- else:
- if vnfd_name is None:
- raise Exception('vnfd id or vnfd name is required')
- vnf_body['vnf']['vnfd_id'] = get_vnfd_id(tacker_client, vnfd_name)
- return tacker_client.create_vnf(body=vnf_body)
- except Exception, e:
- logger.error("error [create_vnf(tacker_client,"
- " '%s', '%s', '%s')]: %s"
- % (vnf_name, vnfd_id, vnfd_name, e))
- return None
-
-
-def get_vnf(tacker_client, vnf_id=None, vnf_name=None):
- try:
- if vnf_id is None and vnf_name is None:
- raise Exception('You must specify vnf_id or vnf_name')
-
- _id = get_vnf_id(tacker_client, vnf_name) if vnf_id is None else vnf_id
-
- if _id is not None:
- all_vnfs = list_vnfs(tacker_client, verbose=True)['vnfs']
- return next((vnf for vnf in all_vnfs if vnf['id'] == _id), None)
- else:
- raise Exception('Could not retrieve ID from name [%s]' % vnf_name)
-
- except Exception, e:
- logger.error("Could not retrieve VNF [vnf_id=%s, vnf_name=%s] - %s"
- % (vnf_id, vnf_name, e))
- return None
-
-
-def wait_for_vnf(tacker_client, vnf_id=None, vnf_name=None, timeout=60):
- try:
- vnf = get_vnf(tacker_client, vnf_id, vnf_name)
- if vnf is None:
- raise Exception("Could not retrieve VNF - id='%s', name='%s'"
- % vnf_id, vnf_name)
- logger.info('Waiting for vnf {0}'.format(str(vnf)))
- while vnf['status'] != 'ACTIVE' and timeout >= 0:
- if vnf['status'] == 'ERROR':
- raise Exception('Error when booting vnf %s' % vnf['id'])
- elif vnf['status'] == 'PENDING_CREATE':
- time.sleep(3)
- timeout -= 3
- vnf = get_vnf(tacker_client, vnf_id, vnf_name)
-
- if (timeout < 0):
- raise Exception('Timeout when booting vnf %s' % vnf['id'])
-
- return vnf['id']
- except Exception, e:
- logger.error("error [wait_for_vnf(tacker_client, '%s', '%s')]: %s"
- % (vnf_id, vnf_name, e))
- return None
-
-
-def delete_vnf(tacker_client, vnf_id=None, vnf_name=None):
- try:
- vnf = vnf_id
- if vnf is None:
- if vnf_name is None:
- raise Exception('You need to provide a VNF id or name')
- vnf = get_vnf_id(tacker_client, vnf_name)
- return tacker_client.delete_vnf(vnf)
- except Exception, e:
- logger.error("Error [delete_vnf(tacker_client, '%s', '%s')]: %s"
- % (vnf_id, vnf_name, e))
- return None
-
-
-def list_sfcs(tacker_client, verbose=False):
- try:
- sfcs = tacker_client.list_sfcs(retrieve_all=True)
- if not verbose:
- sfcs = [sfc['id'] for sfc in sfcs['sfcs']]
- return sfcs
- except Exception, e:
- logger.error("Error [list_sfcs(tacker_client)]: %s" % e)
- return None
-
-
-def create_sfc(tacker_client, sfc_name,
- chain_vnf_ids=None,
- chain_vnf_names=None,
- symmetrical=False):
- try:
- sfc_body = {
- 'sfc': {
- 'attributes': {},
- 'name': sfc_name,
- 'chain': []
- }
- }
- if symmetrical:
- sfc_body['sfc']['symmetrical'] = True
- if chain_vnf_ids is not None:
- sfc_body['sfc']['chain'] = chain_vnf_ids
- else:
- if chain_vnf_names is None:
- raise Exception('You need to provide a chain of VNFs')
- sfc_body['sfc']['chain'] = [get_vnf_id(tacker_client, name)
- for name in chain_vnf_names]
- return tacker_client.create_sfc(body=sfc_body)
- except Exception, e:
- logger.error("error [create_sfc(tacker_client,"
- " '%s', '%s', '%s')]: %s"
- % (sfc_name, chain_vnf_ids, chain_vnf_names, e))
- return None
-
-
-def delete_sfc(tacker_client, sfc_id=None, sfc_name=None):
- try:
- sfc = sfc_id
- if sfc is None:
- if sfc_name is None:
- raise Exception('You need to provide an SFC id or name')
- sfc = get_sfc_id(tacker_client, sfc_name)
- return tacker_client.delete_sfc(sfc)
- except Exception, e:
- logger.error("Error [delete_sfc(tacker_client, '%s', '%s')]: %s"
- % (sfc_id, sfc_name, e))
- return None
-
-
-def list_sfc_classifiers(tacker_client, verbose=False):
- try:
- sfc_clfs = tacker_client.list_sfc_classifiers(retrieve_all=True)
- if not verbose:
- sfc_clfs = [sfc_clf['id']
- for sfc_clf in sfc_clfs['sfc_classifiers']]
- return sfc_clfs
- except Exception, e:
- logger.error("Error [list_sfc_classifiers(tacker_client)]: %s" % e)
- return None
-
-
-def create_sfc_classifier(tacker_client, sfc_clf_name, sfc_id=None,
- sfc_name=None, match={}):
- # Example match:
- # match: {
- # "source_port": "0",
- # "protocol": "6",
- # "dest_port": "80"
- # }
- try:
- sfc_clf_body = {
- 'sfc_classifier': {
- 'attributes': {},
- 'name': sfc_clf_name,
- 'match': match,
- 'chain': ''
- }
- }
- if sfc_id is not None:
- sfc_clf_body['sfc_classifier']['chain'] = sfc_id
- else:
- if sfc_name is None:
- raise Exception('You need to provide an SFC id or name')
- sfc_clf_body['sfc_classifier']['chain'] = get_sfc_id(
- tacker_client, sfc_name)
- return tacker_client.create_sfc_classifier(body=sfc_clf_body)
- except Exception, e:
- logger.error("error [create_sfc_classifier(tacker_client,"
- " '%s', '%s','%s', '%s')]: '%s'"
- % (sfc_clf_name, sfc_id, sfc_name, str(match), e))
- return None
-
-
-def delete_sfc_classifier(tacker_client,
- sfc_clf_id=None,
- sfc_clf_name=None):
- try:
- sfc_clf = sfc_clf_id
- if sfc_clf is None:
- if sfc_clf_name is None:
- raise Exception('You need to provide an SFC'
- 'classifier id or name')
- sfc_clf = get_sfc_classifier_id(tacker_client, sfc_clf_name)
- return tacker_client.delete_sfc_classifier(sfc_clf)
- except Exception, e:
- logger.error("Error [delete_sfc_classifier(tacker_client, '%s', "
- "'%s')]: %s" % (sfc_clf_id, sfc_clf_name, e))
- return None
diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py
index 8b59c954..73d1cde4 100644
--- a/functest/utils/openstack_utils.py
+++ b/functest/utils/openstack_utils.py
@@ -1561,3 +1561,62 @@ def get_resource(heat_client, stack_id, resource):
except Exception as e:
logger.error("Error [get_resource]: %s" % e)
return None
+
+
+# *********************************************
+# TEMPEST
+# *********************************************
+def init_tempest_cleanup(tempest_config_dir=None,
+ tempest_config_filename='tempest.conf',
+ output_file=None):
+ """
+ Initialize the Tempest Cleanup utility.
+ See https://docs.openstack.org/tempest/latest/cleanup.html for docs.
+
+ :param tempest_config_dir: The directory where the Tempest config file is
+ located. If not specified, we let Tempest pick both the directory
+ and the filename (i.e. second parameter is ignored)
+ :param tempest_config_filename: The filename of the Tempest config file
+ :param output_file: Optional file where to save output
+ """
+ # The Tempest cleanup utility currently offers no cmd argument to specify
+ # the config file, therefore it has to be configured with env variables
+ env = None
+ if tempest_config_dir:
+ env = os.environ.copy()
+ env['TEMPEST_CONFIG_DIR'] = tempest_config_dir
+ env['TEMPEST_CONFIG'] = tempest_config_filename
+
+ # If this command fails, an exception must be raised to stop the script
+ # otherwise the later cleanup would destroy also other resources
+ cmd_line = "tempest cleanup --init-saved-state"
+ ft_utils.execute_command_raise(cmd_line, env=env, output_file=output_file,
+ error_msg="Tempest cleanup init failed")
+
+
+def perform_tempest_cleanup(tempest_config_dir=None,
+ tempest_config_filename='tempest.conf',
+ output_file=None):
+ """
+ Perform cleanup using the Tempest Cleanup utility.
+ See https://docs.openstack.org/tempest/latest/cleanup.html for docs.
+
+ :param tempest_config_dir: The directory where the Tempest config file is
+ located. If not specified, we let Tempest pick both the directory
+ and the filename (i.e. second parameter is ignored)
+ :param tempest_config_filename: The filename of the Tempest config file
+ :param output_file: Optional file where to save output
+ """
+ # The Tempest cleanup utility currently offers no cmd argument to specify
+ # the config file, therefore it has to be configured with env variables
+ env = None
+ if tempest_config_dir:
+ env = os.environ.copy()
+ env['TEMPEST_CONFIG_DIR'] = tempest_config_dir
+ env['TEMPEST_CONFIG'] = tempest_config_filename
+
+ # If this command fails, an exception must be raised to stop the script
+ # otherwise the later cleanup would destroy also other resources
+ cmd_line = "tempest cleanup"
+ ft_utils.execute_command(cmd_line, env=env, output_file=output_file,
+ error_msg="Tempest cleanup failed")