diff options
Diffstat (limited to 'sfc/tests')
25 files changed, 1314 insertions, 1518 deletions
diff --git a/sfc/tests/NAME_tests.py b/sfc/tests/NAME_tests.py deleted file mode 100644 index e95004bc..00000000 --- a/sfc/tests/NAME_tests.py +++ /dev/null @@ -1,11 +0,0 @@ - -def setup(): - print "SETUP!" - - -def teardown(): - print "TEAR DOWN!" - - -def test_basic(): - print "I RAN!" diff --git a/sfc/tests/functest/README.tests b/sfc/tests/functest/README.tests index d4e3df3e..f39d8888 100644 --- a/sfc/tests/functest/README.tests +++ b/sfc/tests/functest/README.tests @@ -34,15 +34,36 @@ will be running a firewall that blocks the traffic in a specific port (e.g. 33333). A symmetric service chain routing the traffic throught this SF will be created as well. -1st check: The client is able to reach the server using a source port different -from the one that the firewall blocks (e.g 22222), and the response gets back -to the client. +1st check: The client is able to reach the server and the response gets back +to the client. Here the firewall is running without blocking any port. -2nd check: The client is able to reach the server using the source port that -the firewall blocks, but responses back from the server are blocked, as the -symmetric service chain makes them go through the firewall that blocks on the -destination port initially used as source port by the client (e.g. 33333). +2nd check: The client is not able to reach the server as the firewall +is configured to block traffic on port 80, and the request from the client +is blocked, as the symmetric service chain makes them go through the firewall. -If the client is able to receive the response, it would be a symptom of the +If the client is able to reach the server, it would be a symptom of the +symmetric chain not working, as traffic would be flowing from client to server +directly without traversing the SF. + +3rd check: The client is able to reach the server, as the firewall +is configured to block traffic on port 22222, and the response from the server +is blocked. + +If the server is able to reach the client, it would be a symptom of the symmetric chain not working, as traffic would be flowing from server to client directly without traversing the SF. + +4th check: The client is able to reach the server and the response gets back +to the client. Like in 1st check to verify test ends with same config +as at the beginning. + + +## TEST DELETION - sfc_chain_deletion ## + +One client and one server are created using nova. Then a SF is created using tacker. +A service chain which routes the traffic through this SF will be created as well. +After that the chain is deleted and re-created. + +vxlan_tool is started in the SF and HTTP traffic is sent from the client to the server. +If it works, the vxlan_tool is modified to block HTTP traffic. +It is tried again and it should fail because packets are dropped.
\ No newline at end of file diff --git a/sfc/tests/functest/config-pike.yaml b/sfc/tests/functest/config-pike.yaml deleted file mode 100644 index eff95c08..00000000 --- a/sfc/tests/functest/config-pike.yaml +++ /dev/null @@ -1,84 +0,0 @@ ---- -defaults: - # odl-sfc uses custom flavors as per below params - flavor: custom - ram_size_in_mb: 500 - disk_size_in_gb: 1 - vcpu_count: 1 - image_name: sfc_nsh_fraser - installer: - fuel: - user: root - password: r00tme - cluster: 1 # Change this to the id of the desired fuel env (1, 2, 3...) - apex: - user: stack - pkey_file: "/root/.ssh/id_rsa" - osa: - user: root - pkey_file: "/root/.ssh/id_rsa" - compass: - user: root - pkey_file: "/root/.ssh/id_rsa" - image_format: qcow2 - image_url: "http://artifacts.opnfv.org/sfc/images/sfc_nsh_fraser.qcow2" - vnfd-dir: "vnfd-templates" - vnfd-default-params-file: "test-vnfd-default-params.yaml" - - -testcases: - sfc_one_chain_two_service_functions: - enabled: true - order: 0 - description: "ODL-SFC Testing SFs when they are located on the same chain" - net_name: example-net - subnet_name: example-subnet - router_name: example-router - subnet_cidr: "11.0.0.0/24" - secgroup_name: "example-sg" - secgroup_descr: "Example Security group" - test_vnfd_red: "test-one-chain-vnfd1.yaml" - test_vnfd_blue: "test-one-chain-vnfd2.yaml" - test_vnffgd_red: "test-one-chain-vnffgd-pike.yaml" - - sfc_two_chains_SSH_and_HTTP: - enabled: false - order: 1 - description: "ODL-SFC tests with two chains and one SF per chain" - net_name: example-net - subnet_name: example-subnet - router_name: example-router - subnet_cidr: "11.0.0.0/24" - secgroup_name: "example-sg" - secgroup_descr: "Example Security group" - test_vnfd_red: "test-two-chains-vnfd1.yaml" - test_vnfd_blue: "test-two-chains-vnfd2.yaml" - test_vnffgd_red: "test-two-chains-vnffgd1-pike.yaml" - test_vnffgd_blue: "test-two-chains-vnffgd2-pike.yaml" - - sfc_symmetric_chain: - enabled: false - order: 2 - description: "Verify the behavior of a symmetric service chain" - net_name: example-net - subnet_name: example-subnet - router_name: example-router - subnet_cidr: "11.0.0.0/24" - secgroup_name: "example-sg" - secgroup_descr: "Example Security group" - test_vnfd: "test-symmetric-vnfd.yaml" - test_vnffgd: "test-symmetric-vnffgd.yaml" - source_port: 22222 - - sfc_chain_deletion: - enabled: false - order: 3 - description: "Verify if chains work correctly after deleting one" - net_name: example-net - subnet_name: example-subnet - router_name: example-router - subnet_cidr: "11.0.0.0/24" - secgroup_name: "example-sg" - secgroup_descr: "Example Security group" - test_vnfd_red: "test-one-chain-vnfd1.yaml" - test_vnffgd_red: "test-deletion-vnffgd-pike.yaml" diff --git a/sfc/tests/functest/config.yaml b/sfc/tests/functest/config.yaml index cad3cf72..021b4c39 100644 --- a/sfc/tests/functest/config.yaml +++ b/sfc/tests/functest/config.yaml @@ -25,9 +25,18 @@ defaults: vnfd-dir: "vnfd-templates" vnfd-default-params-file: "test-vnfd-default-params.yaml" + # mano_component can be [tacker, no-mano]. When no-mano, + # then networking-sfc is used + mano_component: "no-mano" + + # [OPTIONAL] Only when deploying VNFs without the default image (vxlan_tool) + # vnf_image_name: xxx + # vnf_image_format: yyy + # vnf_image_url: zzz testcases: sfc_one_chain_two_service_functions: + class_name: "SfcOneChainTwoServiceTC" enabled: true order: 0 description: "ODL-SFC Testing SFs when they are located on the same chain" @@ -37,12 +46,21 @@ testcases: subnet_cidr: "11.0.0.0/24" secgroup_name: "example-sg" secgroup_descr: "Example Security group" + vnf_names: + - 'testVNF1' + - 'testVNF2' + supported_installers: + - 'fuel' + - 'apex' + - 'osa' + - 'compass' test_vnfd_red: "test-one-chain-vnfd1.yaml" test_vnfd_blue: "test-one-chain-vnfd2.yaml" test_vnffgd_red: "test-one-chain-vnffgd.yaml" sfc_two_chains_SSH_and_HTTP: - enabled: false + class_name: "SfcTwoChainsSSHandHTTP" + enabled: true order: 1 description: "ODL-SFC tests with two chains and one SF per chain" net_name: example-net @@ -51,13 +69,22 @@ testcases: subnet_cidr: "11.0.0.0/24" secgroup_name: "example-sg" secgroup_descr: "Example Security group" + vnf_names: + - 'testVNF1' + - 'testVNF2' + supported_installers: + - 'fuel' + - 'apex' + - 'osa' + - 'compass' test_vnfd_red: "test-two-chains-vnfd1.yaml" test_vnfd_blue: "test-two-chains-vnfd2.yaml" test_vnffgd_red: "test-two-chains-vnffgd1.yaml" test_vnffgd_blue: "test-two-chains-vnffgd2.yaml" sfc_symmetric_chain: - enabled: false + class_name: "SfcSymmetricChain" + enabled: true order: 2 description: "Verify the behavior of a symmetric service chain" net_name: example-net @@ -66,12 +93,20 @@ testcases: subnet_cidr: "11.0.0.0/24" secgroup_name: "example-sg" secgroup_descr: "Example Security group" + vnf_names: + - 'testVNF1' + supported_installers: + - 'fuel' + - 'apex' + - 'osa' + - 'compass' test_vnfd: "test-symmetric-vnfd.yaml" test_vnffgd: "test-symmetric-vnffgd.yaml" source_port: 22222 sfc_chain_deletion: - enabled: false + class_name: "SfcChainDeletion" + enabled: true order: 3 description: "Verify if chains work correctly after deleting one" net_name: example-net @@ -80,5 +115,12 @@ testcases: subnet_cidr: "11.0.0.0/24" secgroup_name: "example-sg" secgroup_descr: "Example Security group" + vnf_names: + - 'testVNF1' + supported_installers: + - 'fuel' + - 'apex' + - 'osa' + - 'compass' test_vnfd_red: "test-one-chain-vnfd1.yaml" test_vnffgd_red: "test-deletion-vnffgd.yaml" diff --git a/sfc/tests/functest/pod.yaml.sample b/sfc/tests/functest/pod.yaml.sample new file mode 100644 index 00000000..aa5fddad --- /dev/null +++ b/sfc/tests/functest/pod.yaml.sample @@ -0,0 +1,58 @@ +# Sample config file about the POD information is located under the dovetail project. +# https://github.com/opnfv/dovetail/blob/master/etc/userconfig/pod.yaml.sample +# On the top of the above template the node0 could be used, defining the role Host. +# After that the proper number of controller nodes should be defined and +# at the end the respective compute nodes. + +nodes: +- + # This can not be changed and must be node0. + name: node0 + + # This must be Host. + role: Host + + # This is the instance IP of a node which has installed. + ip: xx.xx.xx.xx + + # User name of the user of this node. This user **must** have sudo privileges. + user: root + + # keyfile of the user. + key_filename: /root/.ssh/id_rsa + +- + # This can not be changed and must be node1. + name: node1 + + # This must be controller. + role: Controller + + # This is the instance IP of a controller node + ip: xx.xx.xx.xx + + # User name of the user of this node. This user **must** have sudo privileges. + user: root + + # keyfile of the user. + key_filename: /root/.ssh/id_rsa + +- + # This can not be changed and must be node1. + name: node2 + + # This must be compute. + role: Compute + + # This is the instance IP of a compute node + ip: xx.xx.xx.xx + + # User name of the user of this node. This user **must** have sudo privileges. + user: root + + # keyfile of the user. + key_filename: /root/.ssh/id_rsa + + # Private ssh key for accessing the controller nodes. If there is not + # a keyfile for that use, the password of the user could be used instead. + # password: root
\ No newline at end of file diff --git a/sfc/tests/functest/run_sfc_tests.py b/sfc/tests/functest/run_sfc_tests.py index 64c5b385..7f0eaa8a 100644 --- a/sfc/tests/functest/run_sfc_tests.py +++ b/sfc/tests/functest/run_sfc_tests.py @@ -11,18 +11,17 @@ import importlib import os import time -import yaml +import logging import sys +import yaml -from xtesting.core import testcase +from collections import OrderedDict from opnfv.utils import ovs_logger as ovs_log from opnfv.deployment.factory import Factory as DeploymentFactory from sfc.lib import cleanup as sfc_cleanup from sfc.lib import config as sfc_config from sfc.lib import odl_utils as odl_utils - -from collections import OrderedDict -import logging +from xtesting.core import testcase logger = logging.getLogger(__name__) COMMON_CONFIG = sfc_config.CommonConfig() @@ -30,6 +29,13 @@ COMMON_CONFIG = sfc_config.CommonConfig() class SfcFunctest(testcase.TestCase): + def __init__(self, **kwargs): + super(SfcFunctest, self).__init__(**kwargs) + + self.cleanup_flag = True + if '--nocleanup' in sys.argv: + self.cleanup_flag = False + def __fetch_tackerc_file(self, controller_node): rc_file = os.path.join(COMMON_CONFIG.sfc_test_dir, 'tackerc') if not os.path.exists(rc_file): @@ -98,35 +104,49 @@ class SfcFunctest(testcase.TestCase): time.sleep(10) def __disable_heat_resource_finder_cache(self, nodes, installer_type): - controllers = [node for node in nodes if node.is_controller()] + + if COMMON_CONFIG.installer_type != 'configByUser': + controllers = [node for node in nodes if node.is_controller()] + else: + controllers = [] + for n in COMMON_CONFIG.nodes_pod: + if n['role'] == 'Controller': + controllers.append(n) + logger.info("CONTROLLER : %s", controllers) if installer_type == 'apex': self.__disable_heat_resource_finder_cache_apex(controllers) elif installer_type == "fuel": self.__disable_heat_resource_finder_cache_fuel(controllers) - elif installer_type == "osa" or "compass": + elif installer_type == "osa" or "compass" or "configByUser": pass else: raise Exception('Unsupported installer') def run(self): - deploymentHandler = DeploymentFactory.get_handler( - COMMON_CONFIG.installer_type, - COMMON_CONFIG.installer_ip, - COMMON_CONFIG.installer_user, - COMMON_CONFIG.installer_password, - COMMON_CONFIG.installer_key_file) - cluster = COMMON_CONFIG.installer_cluster - nodes = (deploymentHandler.get_nodes({'cluster': cluster}) - if cluster is not None - else deploymentHandler.get_nodes()) - - self.__disable_heat_resource_finder_cache(nodes, - COMMON_CONFIG.installer_type) + if COMMON_CONFIG.installer_type != 'configByUser': + deploymentHandler = DeploymentFactory.get_handler( + COMMON_CONFIG.installer_type, + COMMON_CONFIG.installer_ip, + COMMON_CONFIG.installer_user, + COMMON_CONFIG.installer_password, + COMMON_CONFIG.installer_key_file) + + nodes = (deploymentHandler.get_nodes({'cluster': cluster}) + if cluster is not None + else deploymentHandler.get_nodes()) + self.__disable_heat_resource_finder_cache(nodes, + COMMON_CONFIG. + installer_type) + odl_ip, odl_port = odl_utils.get_odl_ip_port(nodes) - odl_ip, odl_port = odl_utils.get_odl_ip_port(nodes) + else: + nodes = COMMON_CONFIG.nodes_pod + self.__disable_heat_resource_finder_cache(nodes, "configByUser") + odl_ip, odl_port = odl_utils. \ + get_odl_ip_port_no_installer(COMMON_CONFIG.nodes_pod) ovs_logger = ovs_log.OVSLogger( os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), @@ -149,16 +169,33 @@ class SfcFunctest(testcase.TestCase): (test_name, test_descr)) logger.info(title) logger.info("%s\n" % ("=" * len(title))) - t = importlib.import_module( + module = importlib.import_module( "sfc.tests.functest.{0}".format(test_name), package=None) + + testcase_config = sfc_config.TestcaseConfig(test_name) + supported_installers = test_cfg['supported_installers'] + vnf_names = test_cfg['vnf_names'] + + tc_class = getattr(module, test_cfg['class_name']) + tc_instance = tc_class(testcase_config, supported_installers, + vnf_names) + cleanup_run_flag = False start_time = time.time() try: - result, creators = t.main() + result, creators = tc_instance.run() except Exception as e: logger.error("Exception when executing: %s" % test_name) logger.error(e) result = {'status': 'FAILED'} + creators = tc_instance.get_creators() + if self.cleanup_flag is True: + sfc_cleanup.cleanup(testcase_config, + creators, + COMMON_CONFIG.mano_component, + odl_ip=odl_ip, + odl_port=odl_port) + cleanup_run_flag = True end_time = time.time() duration = end_time - start_time logger.info("Results of test case '%s - %s':\n%s\n" % @@ -176,7 +213,13 @@ class SfcFunctest(testcase.TestCase): dic = {"duration": duration, "status": status} self.details.update({test_name: dic}) - sfc_cleanup.cleanup(creators, odl_ip=odl_ip, odl_port=odl_port) + + if cleanup_run_flag is not True and self.cleanup_flag is True: + sfc_cleanup.cleanup(testcase_config, + creators, + COMMON_CONFIG.mano_component, + odl_ip=odl_ip, + odl_port=odl_port) self.stop_time = time.time() diff --git a/sfc/tests/functest/setup_scripts/__init__.py b/sfc/tests/functest/setup_scripts/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/sfc/tests/functest/setup_scripts/__init__.py +++ /dev/null diff --git a/sfc/tests/functest/setup_scripts/compute_presetup_CI.bash b/sfc/tests/functest/setup_scripts/compute_presetup_CI.bash deleted file mode 100644 index 36148aa1..00000000 --- a/sfc/tests/functest/setup_scripts/compute_presetup_CI.bash +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -# This script must be use with vxlan-gpe + nsh. Once we have eth + nsh support -# in ODL, we will not need it anymore - -set -e -ssh_options='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' -BASEDIR=`dirname $0` -INSTALLER_IP=${INSTALLER_IP:-10.20.0.2} - -pushd $BASEDIR -#ip=`sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'fuel node'|grep compute|\ -#awk '{print $10}' | head -1` - -ip=$1 -echo $ip -#sshpass -p r00tme scp $ssh_options correct_classifier.bash ${INSTALLER_IP}:/root -#sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'scp correct_classifier.bash '"$ip"':/root' - -sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'ssh root@'"$ip"' ifconfig br-int up' -output=$(sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'ssh root@'"$ip"' ip route | \ -cut -d" " -f1 | grep 11.0.0.0' ; exit 0) - -if [ -z "$output" ]; then -sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'ssh root@'"$ip"' ip route add 11.0.0.0/24 \ -dev br-int' -fi diff --git a/sfc/tests/functest/setup_scripts/delete.sh b/sfc/tests/functest/setup_scripts/delete.sh deleted file mode 100644 index 3333c52b..00000000 --- a/sfc/tests/functest/setup_scripts/delete.sh +++ /dev/null @@ -1,8 +0,0 @@ -# Remember to source the env variables $creds before -FILE=$(readlink -f $0) -FILE_PATH=$(dirname $FILE) -cd $FILE_PATH -python ../../../lib/cleanup.py $1 $2 -openstack server delete client -openstack server delete server -for line in $(openstack floating ip list);do openstack floating ip delete $line;done diff --git a/sfc/tests/functest/setup_scripts/delete_symmetric.sh b/sfc/tests/functest/setup_scripts/delete_symmetric.sh deleted file mode 100644 index b0aa4d81..00000000 --- a/sfc/tests/functest/setup_scripts/delete_symmetric.sh +++ /dev/null @@ -1,9 +0,0 @@ -# Remember to source the env variables $creds before -tacker sfc-classifier-delete red_http -tacker sfc-classifier-delete red_http_reverse -tacker sfc-delete red -tacker vnf-delete testVNF1 -tacker vnfd-delete test-vnfd1 -nova delete client -nova delete server -for line in $(neutron floatingip-list | cut -d" " -f2);do neutron floatingip-delete $line;done diff --git a/sfc/tests/functest/setup_scripts/prepare_odl_sfc.py b/sfc/tests/functest/setup_scripts/prepare_odl_sfc.py deleted file mode 100644 index 1ddf36a6..00000000 --- a/sfc/tests/functest/setup_scripts/prepare_odl_sfc.py +++ /dev/null @@ -1,92 +0,0 @@ -# -# Author: George Paraskevopoulos (geopar@intracom-telecom.com) -# Manuel Buil (manuel.buil@ericsson.com) -# Prepares the controller and the compute nodes for the odl-sfc testcase -# -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -# - -import os -import paramiko -import subprocess -import sys - -import functest.utils.functest_logger as ft_logger - - -logger = ft_logger.Logger(__name__).getLogger() - -SFC_REPO_DIR = "/home/opnfv/repos/sfc" - -try: - INSTALLER_IP = os.environ['INSTALLER_IP'] -except: - logger.debug("INSTALLER_IP does not exist. We create 10.20.0.2") - INSTALLER_IP = "10.20.0.2" - -os.environ['ODL_SFC_LOG'] = "/home/opnfv/functest/results/sfc.log" -os.environ['ODL_SFC_DIR'] = os.path.join(SFC_REPO_DIR, - "sfc/tests/functest") -SETUP_SCRIPTS_DIR = os.path.join(os.environ['ODL_SFC_DIR'], 'setup_scripts') - -command = SETUP_SCRIPTS_DIR + ("/server_presetup_CI.bash | " - "tee -a ${ODL_SFC_LOG} 1>/dev/null 2>&1") - -output = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) - -# This code is for debugging purposes -# for line in iter(output.stdout.readline, ''): -# i = line.rstrip() -# print(i) - -# Make sure the process is finished before checking the returncode -if not output.poll(): - output.wait() - -# Get return value -if output.returncode: - print("The presetup of the server did not work") - sys.exit(output.returncode) - -logger.info("The presetup of the server worked ") - -ssh_options = "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" -ssh = paramiko.SSHClient() -ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - -try: - ssh.connect(INSTALLER_IP, username="root", - password="r00tme", timeout=2) - command = "fuel node | grep compute | awk '{print $10}'" - logger.info("Executing ssh to collect the compute IPs") - (stdin, stdout, stderr) = ssh.exec_command(command) -except: - logger.debug("Something went wrong in the ssh to collect the computes IP") - -output = stdout.readlines() -for ip in output: - command = SETUP_SCRIPTS_DIR + ("/compute_presetup_CI.bash " + ip.rstrip() + - "| tee -a ${ODL_SFC_LOG} 1>/dev/null 2>&1") - - output = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) - -# This code is for debugging purposes -# for line in iter(output.stdout.readline, ''): -# print(line) -# sys.stdout.flush() - - output.stdout.close() - - if not (output.poll()): - output.wait() - - # Get return value - if output.returncode: - print("The compute config did not work on compute %s" % ip) - sys.exit(output.returncode) - -sys.exit(0) diff --git a/sfc/tests/functest/setup_scripts/server_presetup_CI.bash b/sfc/tests/functest/setup_scripts/server_presetup_CI.bash deleted file mode 100644 index 240353f5..00000000 --- a/sfc/tests/functest/setup_scripts/server_presetup_CI.bash +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -e -ssh_options='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' -BASEDIR=`dirname $0` -INSTALLER_IP=${INSTALLER_IP:-10.20.0.2} - -pushd $BASEDIR -ip=$(sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'fuel node'|grep controller|awk '{print $10}' | head -1) -echo $ip - -sshpass -p r00tme scp $ssh_options delete.sh ${INSTALLER_IP}:/root -sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'scp '"$ip"':/root/tackerc .' -sshpass -p r00tme scp $ssh_options ${INSTALLER_IP}:/root/tackerc $BASEDIR diff --git a/sfc/tests/functest/sfc_chain_deletion.py b/sfc/tests/functest/sfc_chain_deletion.py index 9fde460f..5f73d0c7 100644 --- a/sfc/tests/functest/sfc_chain_deletion.py +++ b/sfc/tests/functest/sfc_chain_deletion.py @@ -8,261 +8,113 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -import os -import sys import threading import logging +import urllib3 -import sfc.lib.openstack_utils as os_sfc_utils import sfc.lib.odl_utils as odl_utils -import opnfv.utils.ovs_logger as ovs_log - import sfc.lib.config as sfc_config import sfc.lib.test_utils as test_utils -from sfc.lib.results import Results -from opnfv.deployment.factory import Factory as DeploymentFactory -import sfc.lib.topology_shuffler as topo_shuffler - +from sfc.tests.functest import sfc_parent_function logger = logging.getLogger(__name__) -CLIENT = "client" -SERVER = "server" -COMMON_CONFIG = sfc_config.CommonConfig() -TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_chain_deletion') - - -def main(): - deploymentHandler = DeploymentFactory.get_handler( - COMMON_CONFIG.installer_type, - COMMON_CONFIG.installer_ip, - COMMON_CONFIG.installer_user, - COMMON_CONFIG.installer_password, - COMMON_CONFIG.installer_key_file) - - installer_type = os.environ.get("INSTALLER_TYPE") - - supported_installers = ['fuel', 'apex', 'osa', 'compass'] - - if installer_type not in supported_installers: - logger.error( - '\033[91mYour installer is not supported yet\033[0m') - sys.exit(1) - - installer_ip = os.environ.get("INSTALLER_IP") - if not installer_ip: - logger.error( - '\033[91minstaller ip is not set\033[0m') - logger.error( - '\033[91mexport INSTALLER_IP=<ip>\033[0m') - sys.exit(1) - cluster = COMMON_CONFIG.installer_cluster - openstack_nodes = (deploymentHandler.get_nodes({'cluster': cluster}) - if cluster is not None - else deploymentHandler.get_nodes()) +class SfcChainDeletion(sfc_parent_function.SfcCommonTestCase): + """We create one client and one server using nova. + Then, a SF is created using tacker. + A service chain routing the traffic + throught this SF will be created as well. + After that the chain is deleted and re-created. + Finally, the vxlan tool is used in order to check a single + HTTP traffic scenario. + """ + def run(self): - controller_nodes = [node for node in openstack_nodes - if node.is_controller()] - compute_nodes = [node for node in openstack_nodes - if node.is_compute()] + logger.info("The test scenario %s is starting", __name__) + self.register_vnf_template(self.testcase_config.test_vnfd_red, + 'test-vnfd1') + self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim') - odl_ip, odl_port = odl_utils.get_odl_ip_port(openstack_nodes) + self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red', + 'red_http', port=80, protocol='tcp', symmetric=False) - for compute in compute_nodes: - logger.info("This is a compute: %s" % compute.ip) + t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.odl_ip, self.odl_port, + self.client_instance.hypervisor_hostname, + [self.neutron_port],)) + try: + t1.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) - results = Results(COMMON_CONFIG.line_length) - results.add_to_summary(0, "=") - results.add_to_summary(2, "STATUS", "SUBTEST") - results.add_to_summary(0, "=") + logger.info("Assigning floating IPs to instances") - openstack_sfc = os_sfc_utils.OpenStackSFC() - - custom_flv = openstack_sfc.create_flavor( - COMMON_CONFIG.flavor, - COMMON_CONFIG.ram_size_in_mb, - COMMON_CONFIG.disk_size_in_gb, - COMMON_CONFIG.vcpu_count) - if not custom_flv: - logger.error("Failed to create custom flavor") - sys.exit(1) - - tacker_client = os_sfc_utils.get_tacker_client() - - controller_clients = test_utils.get_ssh_clients(controller_nodes) - compute_clients = test_utils.get_ssh_clients(compute_nodes) - - ovs_logger = ovs_log.OVSLogger( - os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), - COMMON_CONFIG.functest_results_dir) - - image_creator = openstack_sfc.register_glance_image( - COMMON_CONFIG.image_name, - COMMON_CONFIG.image_url, - COMMON_CONFIG.image_format, - 'public') - - network, router = openstack_sfc.create_network_infrastructure( - TESTCASE_CONFIG.net_name, - TESTCASE_CONFIG.subnet_name, - TESTCASE_CONFIG.subnet_cidr, - TESTCASE_CONFIG.router_name) - - sg = openstack_sfc.create_security_group(TESTCASE_CONFIG.secgroup_name) - - vnf_names = ['testVNF1', 'testVNF2'] + self.assign_floating_ip_client_server() + self.assign_floating_ip_sfs() - topo_seed = topo_shuffler.get_seed() # change to None for nova av zone - testTopology = topo_shuffler.topology(vnf_names, openstack_sfc, - seed=topo_seed) + self.check_floating_ips() - logger.info('This test is run with the topology {0}' - .format(testTopology['id'])) - logger.info('Topology description: {0}' - .format(testTopology['description'])) + self.start_services_in_vm() + logger.info("Wait for ODL to update the classification rules in OVS") + t1.join() - client_instance, client_creator = openstack_sfc.create_instance( - CLIENT, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['client']) + self.remove_vnffg('red_http', 'red') + self.check_deletion() - server_instance, server_creator = openstack_sfc.create_instance( - SERVER, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['server']) + self.create_vnffg(self.testcase_config.test_vnffgd_red, 'blue', + 'blue_http', port=80, protocol='tcp', + symmetric=False) - server_ip = server_instance.ports[0].ips[0]['ip_address'] + t2 = threading.Thread(target=odl_utils.wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.odl_ip, self.odl_port, + self.client_instance.hypervisor_hostname, + [self.neutron_port],)) + try: + t2.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) - os_sfc_utils.register_vim(tacker_client, vim_file=COMMON_CONFIG.vim_file) + logger.info("Starting SSH firewall on %s" % self.fips_sfs[0]) + test_utils.start_vxlan_tool(self.fips_sfs[0]) - tosca_red = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd_red) - os_sfc_utils.create_vnfd(tacker_client, - tosca_file=tosca_red, - vnfd_name='test-vnfd1') + logger.info("Wait for ODL to update the classification rules in OVS") + t2.join() - default_param_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - COMMON_CONFIG.vnfd_default_params_file) + logger.info("Test HTTP") + results = self.present_results_allowed_http() - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, vnf_names[0], 'test-vnfd1', 'test-vim', - default_param_file, testTopology[vnf_names[0]]) + self.vxlan_blocking_start(self.fips_sfs[0], "80") - vnf1_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnf_names[0]) - if vnf1_id is None: - logger.error('ERROR while booting vnfs') - sys.exit(1) + logger.info("Test HTTP again") + results = self.present_results_http() - neutron_port = openstack_sfc.get_client_port(client_instance, - client_creator) - odl_utils.create_chain(tacker_client, default_param_file, neutron_port, - COMMON_CONFIG, TESTCASE_CONFIG) + if __name__ == '__main__': + return results.compile_summary(), self.creators - # Start measuring the time it takes to implement the classification rules - t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, - args=(ovs_logger, compute_nodes, odl_ip, - odl_port, openstack_sfc.get_compute_client(), - [neutron_port],)) + if __name__ == 'sfc.tests.functest.sfc_chain_deletion': + return results.compile_summary(), self.creators - try: - t1.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) + def get_creators(self): + """Return the creators info, specially in case the info is not + returned due to an exception. - logger.info("Assigning floating IPs to instances") - client_floating_ip = openstack_sfc.assign_floating_ip(router, - client_instance, - client_creator) - server_floating_ip = openstack_sfc.assign_floating_ip(router, - server_instance, - server_creator) - fips_sfs = openstack_sfc.assign_floating_ip_vnfs(router) - sf1_floating_ip = fips_sfs[0] + :return: creators + """ + return self.creators - fips = [client_floating_ip, server_floating_ip, sf1_floating_ip] - for ip in fips: - logger.info("Checking connectivity towards floating IP [%s]" % ip) - if not test_utils.ping(ip, retries=50, retry_timeout=3): - logger.error("Cannot ping floating IP [%s]" % ip) - os_sfc_utils.get_tacker_items() - odl_utils.get_odl_items(odl_ip, odl_port) - sys.exit(1) - logger.info("Successful ping to floating IP [%s]" % ip) - - if not test_utils.check_ssh([sf1_floating_ip]): - logger.error("Cannot establish SSH connection to the SFs") - sys.exit(1) - - logger.info("Starting HTTP server on %s" % server_floating_ip) - if not test_utils.start_http_server(server_floating_ip): - logger.error('\033[91mFailed to start HTTP server on %s\033[0m' - % server_floating_ip) - sys.exit(1) - - logger.info("Wait for ODL to update the classification rules in OVS") - t1.join() - - os_sfc_utils.delete_vnffg(tacker_client, vnffg_name='red_http') - - os_sfc_utils.delete_vnffgd(tacker_client, vnffgd_name='red') - - if not odl_utils.check_vnffg_deletion(odl_ip, odl_port, ovs_logger, - [neutron_port], - openstack_sfc.get_compute_client(), - compute_nodes): - logger.debug("The chains were not correctly removed") - raise Exception("Chains not correctly removed, test failed") - - odl_utils.create_chain(tacker_client, default_param_file, neutron_port, - COMMON_CONFIG, TESTCASE_CONFIG) - - # Start measuring the time it takes to implement the classification rules - t2 = threading.Thread(target=odl_utils.wait_for_classification_rules, - args=(ovs_logger, compute_nodes, odl_ip, - odl_port, openstack_sfc.get_compute_client(), - [neutron_port],)) - try: - t2.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) - - logger.info("Starting SSH firewall on %s" % sf1_floating_ip) - test_utils.start_vxlan_tool(sf1_floating_ip) - - logger.info("Wait for ODL to update the classification rules in OVS") - t2.join() - - logger.info("Test HTTP") - if not test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP works") - else: - error = ('\033[91mTEST 1 [FAILED] ==> HTTP BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP Blocked") - - logger.info("Stopping HTTP firewall on %s" % sf1_floating_ip) - test_utils.stop_vxlan_tool(sf1_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf1_floating_ip) - test_utils.start_vxlan_tool(sf1_floating_ip, block="80") - - logger.info("Test HTTP again") - if test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP Blocked") - else: - error = ('\033[91mTEST 2 [FAILED] ==> HTTP works\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP works") +if __name__ == '__main__': - return results.compile_summary(), openstack_sfc.creators + # Disable InsecureRequestWarning errors when executing the SFC tests in XCI + urllib3.disable_warnings() + TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_chain_deletion') + supported_installers = ['fuel', 'apex', 'osa', 'compass'] + vnf_names = ['testVNF1', 'testVNF2'] -if __name__ == '__main__': - logging.config.fileConfig(COMMON_CONFIG.functest_logging_api) - main() + test_run = SfcChainDeletion(TESTCASE_CONFIG, supported_installers, + vnf_names) + test_run.run() diff --git a/sfc/tests/functest/sfc_one_chain_two_service_functions.py b/sfc/tests/functest/sfc_one_chain_two_service_functions.py index 07f7814c..38fa3fef 100644 --- a/sfc/tests/functest/sfc_one_chain_two_service_functions.py +++ b/sfc/tests/functest/sfc_one_chain_two_service_functions.py @@ -7,280 +7,97 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # -import os -import sys import threading import logging +import urllib3 -import sfc.lib.openstack_utils as os_sfc_utils import sfc.lib.odl_utils as odl_utils -import opnfv.utils.ovs_logger as ovs_log - import sfc.lib.config as sfc_config -import sfc.lib.test_utils as test_utils -from sfc.lib.results import Results -from opnfv.deployment.factory import Factory as DeploymentFactory -import sfc.lib.topology_shuffler as topo_shuffler +from sfc.tests.functest import sfc_parent_function """ logging configuration """ logger = logging.getLogger(__name__) -CLIENT = "client" -SERVER = "server" -COMMON_CONFIG = sfc_config.CommonConfig() -TESTCASE_CONFIG = sfc_config.TestcaseConfig( - 'sfc_one_chain_two_service' - '_functions') +class SfcOneChainTwoServiceTC(sfc_parent_function.SfcCommonTestCase): + """We create one client and one server using nova. + Then, 2 SFs are created using tacker. + A chain is created where both SFs are included. + The vxlan tool is used on both SFs. The purpose is to + check different HTTP traffic combinations. + """ + def run(self): -def main(): - deploymentHandler = DeploymentFactory.get_handler( - COMMON_CONFIG.installer_type, - COMMON_CONFIG.installer_ip, - COMMON_CONFIG.installer_user, - COMMON_CONFIG.installer_password, - COMMON_CONFIG.installer_key_file) + logger.info("The test scenario %s is starting", __name__) - installer_type = os.environ.get("INSTALLER_TYPE") + self.register_vnf_template(self.testcase_config.test_vnfd_red, + 'test-vnfd1') + self.register_vnf_template(self.testcase_config.test_vnfd_blue, + 'test-vnfd2') - supported_installers = ['fuel', 'apex', 'osa', 'compass'] + self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim') + self.create_vnf(self.vnfs[1], 'test-vnfd2', 'test-vim') - if installer_type not in supported_installers: - logger.error( - '\033[91mYour installer is not supported yet\033[0m') - sys.exit(1) + self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red', + 'red_http', port=80, protocol='tcp', symmetric=False) + # Start measuring the time it takes to implement the + # classification rules + t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.odl_ip, self.odl_port, + self.client_instance.hypervisor_hostname, + [self.neutron_port],)) + try: + t1.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) - installer_ip = os.environ.get("INSTALLER_IP") - if not installer_ip: - logger.error( - '\033[91minstaller ip is not set\033[0m') - logger.error( - '\033[91mexport INSTALLER_IP=<ip>\033[0m') - sys.exit(1) + self.assign_floating_ip_client_server() - cluster = COMMON_CONFIG.installer_cluster + self.assign_floating_ip_sfs() - openstack_nodes = (deploymentHandler.get_nodes({'cluster': cluster}) - if cluster is not None - else deploymentHandler.get_nodes()) + self.check_floating_ips() + self.start_services_in_vm() - controller_nodes = [node for node in openstack_nodes - if node.is_controller()] - compute_nodes = [node for node in openstack_nodes - if node.is_compute()] + t1.join() - odl_ip, odl_port = odl_utils.get_odl_ip_port(openstack_nodes) + logger.info("Allowed HTTP scenario") + results = self.present_results_allowed_http() - for compute in compute_nodes: - logger.info("This is a compute: %s" % compute.ip) + self.vxlan_blocking_start(self.fips_sfs[0], "80") + results = self.present_results_http() - results = Results(COMMON_CONFIG.line_length) - results.add_to_summary(0, "=") - results.add_to_summary(2, "STATUS", "SUBTEST") - results.add_to_summary(0, "=") + self.vxlan_blocking_start(self.fips_sfs[1], "80") + self.vxlan_blocking_stop(self.fips_sfs[0]) - openstack_sfc = os_sfc_utils.OpenStackSFC() + results = self.present_results_http() - custom_flv = openstack_sfc.create_flavor( - COMMON_CONFIG.flavor, - COMMON_CONFIG.ram_size_in_mb, - COMMON_CONFIG.disk_size_in_gb, - COMMON_CONFIG.vcpu_count) - if not custom_flv: - logger.error("Failed to create custom flavor") - sys.exit(1) + if __name__ == '__main__': + return results.compile_summary(), self.creators - tacker_client = os_sfc_utils.get_tacker_client() + if __name__ == \ + 'sfc.tests.functest.sfc_one_chain_two_service_functions': + return results.compile_summary(), self.creators - controller_clients = test_utils.get_ssh_clients(controller_nodes) - compute_clients = test_utils.get_ssh_clients(compute_nodes) + def get_creators(self): + """Return the creators info, specially in case the info is not + returned due to an exception. - ovs_logger = ovs_log.OVSLogger( - os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), - COMMON_CONFIG.functest_results_dir) + :return: creators + """ + return self.creators - image_creator = openstack_sfc.register_glance_image( - COMMON_CONFIG.image_name, - COMMON_CONFIG.image_url, - COMMON_CONFIG.image_format, - 'public') - network, router = openstack_sfc.create_network_infrastructure( - TESTCASE_CONFIG.net_name, - TESTCASE_CONFIG.subnet_name, - TESTCASE_CONFIG.subnet_cidr, - TESTCASE_CONFIG.router_name) +if __name__ == '__main__': - sg = openstack_sfc.create_security_group(TESTCASE_CONFIG.secgroup_name) + # Disable InsecureRequestWarning errors when executing the SFC tests in XCI + urllib3.disable_warnings() + TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_one_chain_two_service' + '_functions') + supported_installers = ['fuel', 'apex', 'osa', 'compass'] vnfs = ['testVNF1', 'testVNF2'] - topo_seed = topo_shuffler.get_seed() - testTopology = topo_shuffler.topology(vnfs, openstack_sfc, seed=topo_seed) - - logger.info('This test is run with the topology {0}' - .format(testTopology['id'])) - logger.info('Topology description: {0}' - .format(testTopology['description'])) - - client_instance, client_creator = openstack_sfc.create_instance( - CLIENT, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['client']) - - server_instance, server_creator = openstack_sfc.create_instance( - SERVER, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['server']) - - server_ip = server_instance.ports[0].ips[0]['ip_address'] - logger.info("Server instance received private ip [{}]".format(server_ip)) - - os_sfc_utils.register_vim(tacker_client, vim_file=COMMON_CONFIG.vim_file) - - tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd_red) - - os_sfc_utils.create_vnfd( - tacker_client, - tosca_file=tosca_file, vnfd_name='test-vnfd1') - - tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd_blue) - os_sfc_utils.create_vnfd( - tacker_client, - tosca_file=tosca_file, vnfd_name='test-vnfd2') - - default_param_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - COMMON_CONFIG.vnfd_default_params_file) - - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, vnfs[0], 'test-vnfd1', 'test-vim', - default_param_file, testTopology[vnfs[0]]) - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, vnfs[1], 'test-vnfd2', 'test-vim', - default_param_file, testTopology[vnfs[1]]) - - vnf1_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnfs[0]) - vnf2_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnfs[1]) - if vnf1_id is None or vnf2_id is None: - logger.error('ERROR while booting vnfs') - sys.exit(1) - - tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnffgd_dir, - TESTCASE_CONFIG.test_vnffgd_red) - - os_sfc_utils.create_vnffgd(tacker_client, - tosca_file=tosca_file, - vnffgd_name='red') - - neutron_port = openstack_sfc.get_client_port(client_instance, - client_creator) - os_sfc_utils.create_vnffg_with_param_file(tacker_client, 'red', - 'red_http', - default_param_file, - neutron_port.id) - - # Start measuring the time it takes to implement the classification rules - t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, - args=(ovs_logger, compute_nodes, odl_ip, - odl_port, openstack_sfc.get_compute_client(), - [neutron_port],)) - try: - t1.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) - - logger.info("Assigning floating IPs to instances") - client_floating_ip = openstack_sfc.assign_floating_ip(router, - client_instance, - client_creator) - server_floating_ip = openstack_sfc.assign_floating_ip(router, - server_instance, - server_creator) - fips_sfs = openstack_sfc.assign_floating_ip_vnfs(router) - sf1_floating_ip = fips_sfs[0] - sf2_floating_ip = fips_sfs[1] - - fips = [client_floating_ip, server_floating_ip, sf1_floating_ip, - sf2_floating_ip] - - for ip in fips: - logger.info("Checking connectivity towards floating IP [%s]" % ip) - if not test_utils.ping(ip, retries=50, retry_timeout=3): - logger.error("Cannot ping floating IP [%s]" % ip) - os_sfc_utils.get_tacker_items() - odl_utils.get_odl_items(odl_ip, odl_port) - sys.exit(1) - logger.info("Successful ping to floating IP [%s]" % ip) - - if not test_utils.check_ssh([sf1_floating_ip, sf2_floating_ip]): - logger.error("Cannot establish SSH connection to the SFs") - sys.exit(1) - - logger.info("Starting HTTP server on %s" % server_floating_ip) - if not test_utils.start_http_server(server_floating_ip): - logger.error( - 'Failed to start HTTP server on %s' % server_floating_ip) - sys.exit(1) - - for sf_floating_ip in (sf1_floating_ip, sf2_floating_ip): - logger.info("Starting vxlan_tool on %s" % sf_floating_ip) - test_utils.start_vxlan_tool(sf_floating_ip) - - logger.info("Wait for ODL to update the classification rules in OVS") - t1.join() - - logger.info("Test HTTP") - if not test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP works") - else: - error = ('\033[91mTEST 1 [FAILED] ==> HTTP BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP blocked") - - logger.info("Changing the vxlan_tool to block HTTP traffic") - - # Make SF1 block http traffic - test_utils.stop_vxlan_tool(sf1_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf1_floating_ip) - test_utils.start_vxlan_tool(sf1_floating_ip, block="80") - - logger.info("Test HTTP again blocking SF1") - if test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP Blocked") - else: - error = ('\033[91mTEST 2 [FAILED] ==> HTTP WORKS\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP not blocked") - - # Make SF2 block http traffic - test_utils.stop_vxlan_tool(sf2_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf2_floating_ip) - test_utils.start_vxlan_tool(sf2_floating_ip, block="80") - logger.info("Stopping HTTP firewall on %s" % sf1_floating_ip) - test_utils.stop_vxlan_tool(sf1_floating_ip) - - logger.info("Test HTTP again blocking SF2") - if test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP Blocked") - else: - error = ('\033[91mTEST 3 [FAILED] ==> HTTP WORKS\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP not blocked") - - return results.compile_summary(), openstack_sfc.creators - - -if __name__ == '__main__': - logging.config.fileConfig(COMMON_CONFIG.functest_logging_api) - main() + test_run = SfcOneChainTwoServiceTC(TESTCASE_CONFIG, supported_installers, + vnfs) + test_run.run() diff --git a/sfc/tests/functest/sfc_parent_function.py b/sfc/tests/functest/sfc_parent_function.py new file mode 100644 index 00000000..410c0e71 --- /dev/null +++ b/sfc/tests/functest/sfc_parent_function.py @@ -0,0 +1,768 @@ +import logging +import os +import urllib3 + +import sfc.lib.test_utils as test_utils +import sfc.lib.openstack_utils as os_sfc_utils +import sfc.lib.topology_shuffler as topo_shuffler + +from opnfv.utils import ovs_logger as ovs_log +from opnfv.deployment.factory import Factory as DeploymentFactory +from sfc.lib import config as sfc_config +from sfc.lib import odl_utils as odl_utils +from sfc.lib.results import Results + +# Disable InsecureRequestWarning errors when executing the SFC tests in XCI +urllib3.disable_warnings() + +logger = logging.getLogger(__name__) +CLIENT = "client" +SERVER = "server" +openstack_sfc = os_sfc_utils.OpenStackSFC() +COMMON_CONFIG = sfc_config.CommonConfig() +results = Results(COMMON_CONFIG.line_length) + + +class SfcCommonTestCase(object): + + def __init__(self, testcase_config, supported_installers, vnfs): + + self.compute_nodes = None + self.controller_clients = None + self.compute_clients = None + self.tacker_client = None + self.ovs_logger = None + self.network = None + self.router = None + self.sg = None + self.image_creator = None + self.vnf_image_creator = None + self.creators = None + self.odl_ip = None + self.odl_port = None + self.default_param_file = None + self.topo_seed = None + self.test_topology = None + self.server_instance = None + self.server_creator = None + self.client_instance = None + self.client_creator = None + self.vnf_id = None + self.client_floating_ip = None + self.server_floating_ip = None + self.fips_sfs = [] + self.vnf_objects = dict() + self.testcase_config = testcase_config + self.vnfs = vnfs + self.port_server = None + self.server_ip = None + self.port_client = None + + self.prepare_env(testcase_config, supported_installers, vnfs) + + def prepare_env(self, testcase_config, supported_installers, vnfs): + """Prepare the testcase environment and the components + that the test scenario is going to use later on. + + :param testcase_config: the input test config file + :param supported_installers: the supported installers for this tc + :param vnfs: the names of vnfs + :return: Environment preparation + """ + + if COMMON_CONFIG.installer_type != 'configByUser': + deployment_handler = DeploymentFactory.get_handler( + COMMON_CONFIG.installer_type, + COMMON_CONFIG.installer_ip, + COMMON_CONFIG.installer_user, + COMMON_CONFIG.installer_password, + COMMON_CONFIG.installer_key_file) + + installer_type = os.environ.get("INSTALLER_TYPE") + installer_ip = os.environ.get("INSTALLER_IP") + cluster = COMMON_CONFIG.installer_cluster + openstack_nodes = (deployment_handler. + get_nodes({'cluster': cluster}) + if cluster is not None + else deployment_handler.get_nodes()) + + self.compute_nodes = [node for node in openstack_nodes + if node.is_compute()] + + for compute in self.compute_nodes: + logger.info("This is a compute: %s" % compute.ip) + + controller_nodes = [node for node in openstack_nodes + if node.is_controller()] + self.controller_clients = test_utils. \ + get_ssh_clients(controller_nodes) + self.compute_clients = test_utils. \ + get_ssh_clients(self.compute_nodes) + + self.odl_ip, self.odl_port = odl_utils. \ + get_odl_ip_port(openstack_nodes) + + else: + installer_type = 'configByUser' + installer_ip = COMMON_CONFIG.installer_ip + openstack_nodes = COMMON_CONFIG.nodes_pod + self.compute_nodes = [node for node in + COMMON_CONFIG.nodes_pod + if node['role'] == 'Compute'] + + for compute in self.compute_nodes: + logger.info("This is a compute: %s" % compute['ip']) + + controller_nodes = [node for node in openstack_nodes + if node['role'] == 'Controller'] + + self.odl_ip, self.odl_port = odl_utils. \ + get_odl_ip_port_no_installer(openstack_nodes) + + if installer_type not in supported_installers: + if installer_type != 'configByUser': + raise Exception( + '\033[91mYour installer is not supported yet\033[0m') + + if not installer_ip: + logger.error( + '\033[91minstaller ip is not set\033[0m') + raise Exception( + '\033[91mexport INSTALLER_IP=<ip>\033[0m') + + results.add_to_summary(0, "=") + results.add_to_summary(2, "STATUS", "SUBTEST") + results.add_to_summary(0, "=") + + custom_flv = openstack_sfc.create_flavor( + COMMON_CONFIG.flavor, + COMMON_CONFIG.ram_size_in_mb, + COMMON_CONFIG.disk_size_in_gb, + COMMON_CONFIG.vcpu_count) + if not custom_flv: + raise Exception("Failed to create custom flavor") + + if COMMON_CONFIG.mano_component == 'tacker': + self.tacker_client = os_sfc_utils.get_tacker_client() + os_sfc_utils.register_vim(self.tacker_client, + vim_file=COMMON_CONFIG.vim_file) + + self.ovs_logger = ovs_log.OVSLogger( + os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), + COMMON_CONFIG.functest_results_dir) + + self.network, self.router = openstack_sfc.\ + create_network_infrastructure(testcase_config.net_name, + testcase_config.subnet_name, + testcase_config.subnet_cidr, + testcase_config.router_name) + + self.sg = openstack_sfc.create_security_group( + testcase_config.secgroup_name) + + # Image for the vnf is registered + self.vnf_image_creator = openstack_sfc.register_glance_image( + COMMON_CONFIG.vnf_image_name, + COMMON_CONFIG.vnf_image_url, + COMMON_CONFIG.vnf_image_format, + 'public') + + # Image for the client/server is registered + self.image_creator = openstack_sfc.register_glance_image( + COMMON_CONFIG.image_name, + COMMON_CONFIG.image_url, + COMMON_CONFIG.image_format, + 'public') + + self.creators = openstack_sfc.creators + + odl_utils.get_odl_username_password() + + self.default_param_file = os.path.join( + COMMON_CONFIG.sfc_test_dir, + COMMON_CONFIG.vnfd_dir, + COMMON_CONFIG.vnfd_default_params_file) + + self.topo_seed = topo_shuffler.get_seed() + self.test_topology = topo_shuffler.topology(vnfs, openstack_sfc, + seed=self.topo_seed) + + logger.info('This test is run with the topology {0}' + .format(self.test_topology['id'])) + logger.info('Topology description: {0}' + .format(self.test_topology['description'])) + + self.server_instance, port_server = \ + openstack_sfc.create_instance(SERVER, COMMON_CONFIG.flavor, + self.image_creator, self.network, + self.sg, + self.test_topology['server'], + [SERVER + '-port']) + + self.client_instance, port_client = \ + openstack_sfc.create_instance(CLIENT, COMMON_CONFIG.flavor, + self.image_creator, self.network, + self.sg, + self.test_topology['client'], + [CLIENT + '-port']) + + logger.info('This test is run with the topology {0}'.format( + self.test_topology['id'])) + logger.info('Topology description: {0}'.format( + self.test_topology['description'])) + + if COMMON_CONFIG.installer_type != 'configByUser': + self.port_server = port_server[0] + self.port_client = port_client[0] + port_fixed_ips = self.port_server + for ip in port_fixed_ips: + self.server_ip = ip.get('ip_address') + logger.info("Server instance received private ip [{}]".format( + self.server_ip)) + else: + self.port_server = port_server + self.port_client = port_client + self.server_ip = self.server_instance.ports[0].ips[0]['ip_address'] + logger.info("Server instance received private ip [{}]".format( + self.server_ip)) + + def register_vnf_template(self, test_case_name, template_name): + """ Register the template which defines the VNF + + :param test_case_name: the name of the test case + :param template_name: name of the template + """ + + if COMMON_CONFIG.mano_component == 'tacker': + self.create_custom_vnfd(test_case_name, template_name) + + elif COMMON_CONFIG.mano_component == 'no-mano': + # networking-sfc does not have the template concept + pass + + def create_custom_vnfd(self, test_case_name, vnfd_name): + """Create VNF Descriptor (VNFD) + + :param test_case_name: the name of test case + :param vnfd_name: the name of vnfd + :return: vnfd + """ + + tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, + COMMON_CONFIG.vnfd_dir, test_case_name) + + os_sfc_utils.create_vnfd(self.tacker_client, + tosca_file=tosca_file, + vnfd_name=vnfd_name) + + def create_vnf(self, vnf_name, vnfd_name=None, vim_name=None, + symmetric=False): + """Create custom vnf + + :param vnf_name: name of the vnf + :param vnfd_name: name of the vnfd template (tacker) + :param vim_name: name of the vim (tacker) + :param symmetric: specifies whether this is part of the symmetric test + :return: av zone + """ + + logger.info('This test is run with the topology {0}'. + format(self.test_topology['id'])) + logger.info('Topology description: {0}' + .format(self.test_topology['description'])) + + if COMMON_CONFIG.mano_component == 'tacker': + os_sfc_utils.create_vnf_in_av_zone( + self.tacker_client, vnf_name, vnfd_name, vim_name, + self.default_param_file, self.test_topology[vnf_name]) + + self.vnf_id = os_sfc_utils.wait_for_vnf(self.tacker_client, + vnf_name=vnf_name) + if self.vnf_id is None: + raise Exception('ERROR while booting vnfs') + + elif COMMON_CONFIG.mano_component == 'no-mano': + av_zone = self.test_topology[vnf_name] + if symmetric: + ports = [vnf_name + '-port1', vnf_name + '-port2'] + else: + ports = [vnf_name + '-port'] + vnf_instance, vnf_port = \ + openstack_sfc.create_instance(vnf_name, COMMON_CONFIG.flavor, + self.vnf_image_creator, + self.network, + self.sg, + av_zone, + ports, + port_security=False) + + self.vnf_objects[vnf_name] = [vnf_instance, vnf_port] + logger.info("Creating VNF with name...%s", vnf_name) + logger.info("Port associated with VNF...%s", + self.vnf_objects[vnf_name][1]) + + def assign_floating_ip_client_server(self): + """Assign floating IPs on the router about server and the client + instances + :return: Floating IPs for client and server + """ + logger.info("Assigning floating IPs to client and server instances") + + self.client_floating_ip = openstack_sfc.assign_floating_ip( + self.client_instance, self.port_client) + self.server_floating_ip = openstack_sfc.assign_floating_ip( + self.server_instance, self.port_server) + + def assign_floating_ip_sfs(self): + """Assign floating IPs to service function + + :return: The list fips_sfs consist of the available IPs for service + functions + """ + + logger.info("Assigning floating IPs to service functions") + + if COMMON_CONFIG.mano_component == 'tacker': + vnf_ip = os_sfc_utils.get_vnf_ip(self.tacker_client, + vnf_id=self.vnf_id) + self.fips_sfs = openstack_sfc.assign_floating_ip_vnfs(self.router, + vnf_ip) + elif COMMON_CONFIG.mano_component == 'no-mano': + for vnf in self.vnfs: + # instance object is in [0] and port in [1] + vnf_instance = self.vnf_objects[vnf][0] + vnf_port = self.vnf_objects[vnf][1] + sf_floating_ip = openstack_sfc.\ + assign_floating_ip(vnf_instance, vnf_port[0]) + self.fips_sfs.append(sf_floating_ip) + + def check_floating_ips(self): + """Check the responsivness of the floating IPs + + :return: The responsivness of IPs in the fips_sfs list is checked + """ + + fips = [self.client_floating_ip, self.server_floating_ip] + + for sf in self.fips_sfs: + fips.append(sf) + + for ip in fips: + logger.info("Checking connectivity towards floating IP [%s]" % ip) + if not test_utils.ping(ip, retries=50, retry_timeout=3): + os_sfc_utils.get_tacker_items() + odl_utils.get_odl_items(self.odl_ip, self.odl_port) + raise Exception("Cannot ping floating IP [%s]" % ip) + logger.info("Successful ping to floating IP [%s]" % ip) + + if not test_utils.check_ssh(self.fips_sfs): + raise Exception("Cannot establish SSH connection to the SFs") + + def start_services_in_vm(self): + """Start the HTTP server in the server VM as well as the vxlan tool for + the SFs IPs included in the fips_sfs list + + :return: HTTP server and vxlan tools are started + """ + + logger.info("Starting HTTP server on %s" % self.server_floating_ip) + if not test_utils.start_http_server(self.server_floating_ip): + raise Exception('\033[91mFailed to start HTTP server on %s\033[0m' + % self.server_floating_ip) + + for sf_floating_ip in self.fips_sfs: + logger.info("Starting vxlan_tool on %s" % sf_floating_ip) + test_utils.start_vxlan_tool(sf_floating_ip) + + def present_results_ssh(self): + """Check whether the connection between server and client using + SSH protocol is blocked or not. + + :return: The results for the specific action of the scenario + """ + + logger.info("Test SSH") + if test_utils.is_ssh_blocked(self.client_floating_ip, self.server_ip): + results.add_to_summary(2, "PASS", "SSH Blocked") + else: + error = ('\033[91mTEST [FAILED] ==> SSH NOT BLOCKED\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", "SSH Works") + + return results + + def present_results_allowed_ssh(self): + """Check whether the connection between server and client using + SSH protocol is available or not. + + :return: The results for the specific action of the scenario + """ + + logger.info("Test SSH") + if not test_utils.is_ssh_blocked(self.client_floating_ip, + self.server_ip): + results.add_to_summary(2, "PASS", "SSH works") + else: + error = ('\033[91mTEST [FAILED] ==> SSH BLOCKED\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", "SSH is blocked") + + return results + + def remove_vnffg(self, par_vnffg_name, par_vnffgd_name): + """Delete the vnffg and the vnffgd items that have been created + during the test scenario. + + :param par_vnffg_name: The vnffg name of network components + :param par_vnffgd_name: The vnffgd name of network components + :return: Remove the vnffg and vnffgd components + """ + if COMMON_CONFIG.mano_component == 'tacker': + os_sfc_utils.delete_vnffg(self.tacker_client, + vnffg_name=par_vnffg_name) + + os_sfc_utils.delete_vnffgd(self.tacker_client, + vnffgd_name=par_vnffgd_name) + + elif COMMON_CONFIG.mano_component == 'no-mano': + # TODO: If we had a testcase where only one chains must be removed + # we would need to add the logic. Now it removes all of them + openstack_sfc.delete_chain() + openstack_sfc.delete_port_groups() + + def create_classifier(self, fc_name, port=85, + protocol='tcp', symmetric=False): + """Create the classifier component following the instructions from + relevant templates. + + :param fc_name: The name of the classifier + :param port: Input port number + :param protocol: Input protocol + :param symmetric: Check symmetric + :return: Create the classifier component + """ + + logger.info("Creating the classifier...") + + self.neutron_port = self.port_client + if COMMON_CONFIG.mano_component == 'no-mano': + openstack_sfc.create_classifier(self.neutron_port.id, + port, + protocol, + fc_name, + symmetric) + + elif COMMON_CONFIG.mano_component == 'tacker': + logger.info("Creating classifier with tacker is not supported") + + def create_vnffg(self, testcase_config_name, vnffgd_name, vnffg_name, + port=80, protocol='tcp', symmetric=False, vnf_index=-1): + """Create the vnffg components following the instructions from + relevant templates. + + :param testcase_config_name: The config input of the test case + :param vnffgd_name: The name of the vnffgd template + :param vnffg_name: The name for the vnffg + :param port: Input port number + :param protocol: Input protocol + :param symmetric: Check symmetric + :param vnf_index: Index to specify vnf + :return: Create the vnffg component + """ + + logger.info("Creating the vnffg...") + + if COMMON_CONFIG.mano_component == 'tacker': + tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, + COMMON_CONFIG.vnffgd_dir, + testcase_config_name) + + os_sfc_utils.create_vnffgd(self.tacker_client, + tosca_file=tosca_file, + vnffgd_name=vnffgd_name) + + self.neutron_port = self.port_client + + if symmetric: + server_ip_prefix = self.server_ip + '/32' + + os_sfc_utils.create_vnffg_with_param_file( + self.tacker_client, + vnffgd_name, + vnffg_name, + self.default_param_file, + self.neutron_port.id, + server_port=self.port_server.id, + server_ip=server_ip_prefix) + + else: + os_sfc_utils.create_vnffg_with_param_file( + self.tacker_client, + vnffgd_name, + vnffg_name, + self.default_param_file, + self.neutron_port.id) + + elif COMMON_CONFIG.mano_component == 'no-mano': + logger.info("Creating the vnffg without any mano component...") + port_groups = [] + if vnf_index == -1: + for vnf in self.vnfs: + # vnf_instance is in [0] and vnf_port in [1] + vnf_instance = self.vnf_objects[vnf][0] + vnf_port = self.vnf_objects[vnf][1] + if symmetric: + # VNFs have two ports + neutron_port1 = vnf_port[0] + neutron_port2 = vnf_port[1] + neutron_ports = [neutron_port1, neutron_port2] + else: + neutron_port1 = vnf_port[0] + neutron_ports = [neutron_port1] + + port_group = \ + openstack_sfc.create_port_groups(neutron_ports, + vnf_instance) + port_groups.append(port_group) + + else: + vnf = self.vnfs[vnf_index] + vnf_instance = self.vnf_objects[vnf][0] + vnf_port = self.vnf_objects[vnf][1] + if symmetric: + # VNFs have two ports + neutron_port1 = vnf_port[0] + neutron_port2 = vnf_port[1] + neutron_ports = [neutron_port1, neutron_port2] + else: + neutron_port1 = vnf_port[0] + neutron_ports = [neutron_port1] + + port_group = openstack_sfc.create_port_groups( + neutron_ports, vnf_instance) + port_groups.append(port_group) + + self.neutron_port = self.port_client + + if symmetric: + # We must pass the server_port and server_ip in the symmetric + # case. Otherwise ODL does not work well + server_ip_prefix = self.server_ip + '/32' + openstack_sfc.create_chain(port_groups, + self.neutron_port.id, + port, protocol, vnffg_name, + symmetric, + server_port=self.port_server.id, + server_ip=server_ip_prefix) + + else: + openstack_sfc.create_chain(port_groups, + self.neutron_port.id, + port, protocol, vnffg_name, + symmetric) + + def update_vnffg(self, testcase_config_name, vnffgd_name, vnffg_name, + port=80, protocol='tcp', symmetric=False, + vnf_index=0, fc_name='red'): + """Update the vnffg components following the instructions from + relevant templates. + + :param testcase_config_name: The config input of the test case + :param vnffgd_name: The name of the vnffgd template + :param vnffg_name: The name for the vnffg + :param port: To input port number + :param protocol: To input protocol + :param symmetric: To check symmetric + :param vnf_index: Index to identify vnf + :param fc_name: The name of the flow classifier + :return: Update the vnffg component + """ + + logger.info("Update the vnffg...") + + if COMMON_CONFIG.mano_component == 'no-mano': + port_groups = [] + for vnf in self.vnfs: + # vnf_instance is in [0] and vnf_port in [1] + vnf_instance = self.vnf_objects[vnf][0] + vnf_port = self.vnf_objects[vnf][1] + if symmetric: + # VNFs have two ports + neutron_port1 = vnf_port[0] + neutron_port2 = vnf_port[1] + neutron_ports = [neutron_port1, neutron_port2] + else: + neutron_port1 = vnf_port[0] + neutron_ports = [neutron_port1] + + port_group = \ + openstack_sfc.create_port_groups(neutron_ports, + vnf_instance) + port_groups.append(port_group) + + openstack_sfc.update_chain(vnffg_name, fc_name, symmetric) + + elif COMMON_CONFIG.mano_component == 'tacker': + logger.info("update for tacker is not supported") + + def swap_classifiers(self, vnffg_1_name, vnffg_2_name, symmetric=False): + """Interchange classifiers between port chains + + :param vnffg_1_name: Reference to port_chain_1 + :param vnffg_2_name: Reference to port_chain_2 + :param symmetric: To check symmetric + :return: Interchange the classifiers + """ + + if COMMON_CONFIG.mano_component == 'no-mano': + openstack_sfc.swap_classifiers(vnffg_1_name, + vnffg_2_name, + symmetric=False) + + def present_results_http(self): + """Check whether the connection between server and client using + HTTP protocol is blocked or not. + + :return: The results for the specific action of the scenario + """ + + logger.info("Test HTTP") + if test_utils.is_http_blocked(self.client_floating_ip, self.server_ip): + results.add_to_summary(2, "PASS", "HTTP Blocked") + else: + error = ('\033[91mTEST [FAILED] ==> HTTP WORKS\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", "HTTP works") + + return results + + def present_results_allowed_port_http(self, testcase_config): + """Check whether the connection between server and client using + HTTP protocol and for a specific port is available or not. + + :param testcase_config: The config input of the test case + :return: The results for the specific action of the scenario + """ + + allowed_port = testcase_config.source_port + logger.info("Test if HTTP from port %s works" % allowed_port) + if not test_utils.is_http_blocked( + self.client_floating_ip, self.server_ip, allowed_port): + results.add_to_summary(2, "PASS", "HTTP works") + else: + error = ('\033[91mTEST [FAILED] ==> HTTP BLOCKED\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", "HTTP is blocked") + + return results + + def present_results_blocked_port_http(self, testcase_config, + test='HTTP'): + """Check whether the connection between server and client using + HTTP protocol and for a specific port is blocked or not. + + :param testcase_config: The config input of the test case + :param test: custom test string to print on result summary + :return: The results for the specific action of the scenario + """ + + allowed_port = testcase_config.source_port + logger.info("Test if HTTP from port %s doesn't work" % allowed_port) + if test_utils.is_http_blocked( + self.client_floating_ip, self.server_ip, allowed_port): + results.add_to_summary(2, "PASS", test + " blocked") + else: + error = ('\033[91mTEST [FAILED] ==> HTTP WORKS\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", test + " works") + + return results + + def check_deletion(self): + """Check that the deletion of the chain has been completed sucessfully. + + :return: Check that the chain has been completed deleted without + leftovers. + """ + + if not odl_utils.\ + check_vnffg_deletion(self.odl_ip, self.odl_port, + self.ovs_logger, + [self.neutron_port], + self.client_instance.hypervisor_hostname, + self.compute_nodes): + logger.debug("The chains were not correctly removed") + raise Exception("Chains not correctly removed, test failed") + + def present_results_allowed_http(self): + """Check whether the connection between server and client using + HTTP protocol is available or not. + + :return: The results for the specific action of the scenario + """ + + if not test_utils.is_http_blocked(self.client_floating_ip, + self.server_ip): + results.add_to_summary(2, "PASS", "HTTP works") + else: + error = ('\033[91mTEST [FAILED] ==> HTTP BLOCKED\033[0m') + logger.error(error) + test_utils.capture_ovs_logs( + self.ovs_logger, self.controller_clients, self.compute_clients, + error) + results.add_to_summary(2, "FAIL", "HTTP is blocked") + + return results + + def vxlan_blocking_start(self, floating_ip, port_blocked): + """Start the vxlan tool for one floating IP and blocking + a specific port. + + :param floating_ip: Floating IP + :param port_blocked: Port + :return: The port for the floating IP is blocked + """ + + test_utils.stop_vxlan_tool(floating_ip) + logger.info("Starting HTTP firewall on %s" % floating_ip) + test_utils.start_vxlan_tool(floating_ip, block=port_blocked) + + def vxlan_blocking_stop(self, floating_ip): + """Stop the vxlan tool for a specific IP + + :param floating_ip: Floating IP + :return: The vxlan tool for the specific floating IP is stopped + """ + + logger.info("Starting HTTP firewall on %s" % floating_ip) + test_utils.stop_vxlan_tool(floating_ip) + + def vxlan_start_interface(self, floating_ip, interface, output, block): + """Start the vxlan tool for one floating IP and blocking + a specific interface. + + :param floating_ip: Floating IP + :param interface: Interface + :param output: output interface + :param block: port + :return: The interface or/and port for specific floating IP is blocked + """ + + logger.info("Starting vxlan_tool on %s" % floating_ip) + test_utils.start_vxlan_tool(floating_ip, interface=interface, + output=output, block=block) diff --git a/sfc/tests/functest/sfc_symmetric_chain.py b/sfc/tests/functest/sfc_symmetric_chain.py index 43599d62..cec45219 100644 --- a/sfc/tests/functest/sfc_symmetric_chain.py +++ b/sfc/tests/functest/sfc_symmetric_chain.py @@ -8,302 +8,114 @@ # # http://www.apache.org/licenses/LICENSE-2.0 # - -import os -import sys import threading import logging +import urllib3 -import sfc.lib.openstack_utils as os_sfc_utils import sfc.lib.odl_utils as odl_utils -import opnfv.utils.ovs_logger as ovs_log -from opnfv.deployment.factory import Factory as DeploymentFactory - import sfc.lib.config as sfc_config -import sfc.lib.test_utils as test_utils -from sfc.lib.results import Results -import sfc.lib.topology_shuffler as topo_shuffler - +from sfc.tests.functest import sfc_parent_function +""" logging configuration """ logger = logging.getLogger(__name__) - +COMMON_CONFIG = sfc_config.CommonConfig() CLIENT = "client" SERVER = "server" -COMMON_CONFIG = sfc_config.CommonConfig() -TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_symmetric_chain') - - -def main(): - deploymentHandler = DeploymentFactory.get_handler( - COMMON_CONFIG.installer_type, - COMMON_CONFIG.installer_ip, - COMMON_CONFIG.installer_user, - COMMON_CONFIG.installer_password, - COMMON_CONFIG.installer_key_file) - - cluster = COMMON_CONFIG.installer_cluster - all_nodes = (deploymentHandler.get_nodes({'cluster': cluster}) - if cluster is not None - else deploymentHandler.get_nodes()) - - controller_nodes = [node for node in all_nodes if node.is_controller()] - compute_nodes = [node for node in all_nodes if node.is_compute()] - - odl_ip, odl_port = odl_utils.get_odl_ip_port(all_nodes) - - results = Results(COMMON_CONFIG.line_length) - results.add_to_summary(0, "=") - results.add_to_summary(2, "STATUS", "SUBTEST") - results.add_to_summary(0, "=") - - openstack_sfc = os_sfc_utils.OpenStackSFC() - - tacker_client = os_sfc_utils.get_tacker_client() - - custom_flavor = openstack_sfc.create_flavor( - COMMON_CONFIG.flavor, - COMMON_CONFIG.ram_size_in_mb, - COMMON_CONFIG.disk_size_in_gb, - COMMON_CONFIG.vcpu_count) - if custom_flavor is None: - logger.error("Failed to create custom flavor") - sys.exit(1) - - controller_clients = test_utils.get_ssh_clients(controller_nodes) - compute_clients = test_utils.get_ssh_clients(compute_nodes) - - ovs_logger = ovs_log.OVSLogger( - os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), - COMMON_CONFIG.functest_results_dir) - - image_creator = openstack_sfc.register_glance_image( - COMMON_CONFIG.image_name, - COMMON_CONFIG.image_url, - COMMON_CONFIG.image_format, - 'public') - - network, router = openstack_sfc.create_network_infrastructure( - TESTCASE_CONFIG.net_name, - TESTCASE_CONFIG.subnet_name, - TESTCASE_CONFIG.subnet_cidr, - TESTCASE_CONFIG.router_name) - - sg = openstack_sfc.create_security_group(TESTCASE_CONFIG.secgroup_name) - - vnf_name = 'testVNF1' - topo_seed = topo_shuffler.get_seed() - testTopology = topo_shuffler.topology([vnf_name], openstack_sfc, - seed=topo_seed) - logger.info('This test is run with the topology {0}' - .format(testTopology['id'])) - logger.info('Topology description: {0}' - .format(testTopology['description'])) - - client_instance, client_creator = openstack_sfc.create_instance( - CLIENT, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology[CLIENT]) - - server_instance, server_creator = openstack_sfc.create_instance( - SERVER, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology[SERVER]) - - server_ip = server_instance.ports[0].ips[0]['ip_address'] - logger.info("Server instance received private ip [{}]".format(server_ip)) - - os_sfc_utils.register_vim(tacker_client, vim_file=COMMON_CONFIG.vim_file) - - tosca_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd) - - default_param_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - COMMON_CONFIG.vnfd_default_params_file) - - os_sfc_utils.create_vnfd( - tacker_client, - tosca_file=tosca_file, - vnfd_name='test-vnfd1') - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, - vnf_name, - 'test-vnfd1', - 'test-vim', - default_param_file, - testTopology[vnf_name]) - - vnf_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnf_name) - if vnf_id is None: - logger.error('ERROR while booting VNF') - sys.exit(1) - - tosca_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnffgd_dir, - TESTCASE_CONFIG.test_vnffgd) - os_sfc_utils.create_vnffgd( - tacker_client, - tosca_file=tosca_file, - vnffgd_name='test-vnffgd') - - client_port = openstack_sfc.get_client_port( - client_instance, - client_creator) - server_port = openstack_sfc.get_client_port( - server_instance, - server_creator) - - server_ip_prefix = server_ip + '/32' - - os_sfc_utils.create_vnffg_with_param_file( - tacker_client, - 'test-vnffgd', - 'test-vnffg', - default_param_file, - client_port.id, - server_port.id, - server_ip_prefix) - - # Start measuring the time it takes to implement the classification rules - t1 = threading.Thread( - target=wait_for_classification_rules, - args=(ovs_logger, compute_nodes, - openstack_sfc.get_compute_server(), server_port, - openstack_sfc.get_compute_client(), client_port, - odl_ip, odl_port,)) - - try: - t1.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) - - logger.info("Assigning floating IPs to instances") - client_floating_ip = openstack_sfc.assign_floating_ip(router, - client_instance, - client_creator) - server_floating_ip = openstack_sfc.assign_floating_ip(router, - server_instance, - server_creator) - - vnf_ip = os_sfc_utils.get_vnf_ip(tacker_client, vnf_id=vnf_id) - fips_sfs = openstack_sfc.assign_floating_ip_vnfs(router, [vnf_ip]) - sf_floating_ip = fips_sfs[0] - - fips = [client_floating_ip, server_floating_ip, sf_floating_ip] - - for ip in fips: - logger.info("Checking connectivity towards floating IP [%s]" % ip) - if not test_utils.ping(ip, retries=50, retry_timeout=3): - logger.error("Cannot ping floating IP [%s]" % ip) - os_sfc_utils.get_tacker_items() - odl_utils.get_odl_items(odl_ip, odl_port) - sys.exit(1) - logger.info("Successful ping to floating IP [%s]" % ip) - - if not test_utils.check_ssh([sf_floating_ip]): - logger.error("Cannot establish SSH connection to the SFs") - sys.exit(1) - - logger.info("Starting HTTP server on %s" % server_floating_ip) - if not test_utils.start_http_server(server_floating_ip): - logger.error('\033[91mFailed to start the HTTP server\033[0m') - sys.exit(1) - - logger.info("Starting vxlan_tool on %s" % sf_floating_ip) - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth0', - output='eth1') - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth1', - output='eth0') - - logger.info("Wait for ODL to update the classification rules in OVS") - t1.join() - - logger.info("Test HTTP") - if not test_utils.is_http_blocked(client_floating_ip, - server_ip, - TESTCASE_CONFIG.source_port): - results.add_to_summary(2, "PASS", "HTTP works") - else: - error = ('\033[91mTEST 1 [FAILED] ==> HTTP BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP blocked") - - logger.info("Changing the vxlan_tool to block HTTP request traffic") - - # Make SF1 block http request traffic - test_utils.stop_vxlan_tool(sf_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf_floating_ip) - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth0', - output='eth1', block="80") - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth1', - output='eth0') - - logger.info("Test HTTP again blocking request on SF1") - if test_utils.is_http_blocked(client_floating_ip, - server_ip, - TESTCASE_CONFIG.source_port): - results.add_to_summary(2, "PASS", "HTTP uplink blocked") - else: - error = ('\033[91mTEST 2 [FAILED] ==> HTTP WORKS\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP works") - - logger.info("Changing the vxlan_tool to block HTTP response traffic") - - # Make SF1 block response http traffic - test_utils.stop_vxlan_tool(sf_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf_floating_ip) - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth0', - output='eth1') - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth1', - output='eth0', - block=TESTCASE_CONFIG.source_port) - - logger.info("Test HTTP again blocking response on SF1") - if test_utils.is_http_blocked(client_floating_ip, - server_ip, - TESTCASE_CONFIG.source_port): - results.add_to_summary(2, "PASS", "HTTP downlink blocked") - else: - error = ('\033[91mTEST 3 [FAILED] ==> HTTP WORKS\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP works") - - logger.info("Changing the vxlan_tool to allow HTTP traffic") - - # Make SF1 allow http traffic - test_utils.stop_vxlan_tool(sf_floating_ip) - logger.info("Starting HTTP firewall on %s" % sf_floating_ip) - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth0', - output='eth1') - test_utils.start_vxlan_tool(sf_floating_ip, interface='eth1', - output='eth0') - - logger.info("Test HTTP") - if not test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP restored") - else: - error = ('\033[91mTEST 4 [FAILED] ==> HTTP BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP blocked") - return results.compile_summary(), openstack_sfc.creators +class SfcSymmetricChain(sfc_parent_function.SfcCommonTestCase): + """One client and one server are created using nova. + The server will be running a web server on port 80. + Then one Service Function (SF) is created using Tacker. + This service function will be running a firewall that + blocks the traffic in a specific port. + A symmetric service chain routing the traffic throught + this SF will be created as well. + The purpose is to check different HTTP traffic + combinations using firewall. + """ + + def run(self): + + logger.info("The test scenario %s is starting", __name__) + + self.register_vnf_template(self.testcase_config.test_vnfd, + 'test-vnfd1') + self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim', symmetric=True) + + self.create_vnffg(self.testcase_config.test_vnffgd, 'red-symmetric', + 'red_http', port=80, protocol='tcp', symmetric=True) + + # Start measuring the time it takes to implement the classification + # rules + t1 = threading.Thread(target=symmetric_wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.server_instance.hypervisor_hostname, + self.port_server, + self.client_instance.hypervisor_hostname, + self.port_client, + self.odl_ip, self.odl_port,)) + try: + t1.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) + + logger.info("Assigning floating IPs to instances") + self.assign_floating_ip_client_server() + + self.assign_floating_ip_sfs() + + self.check_floating_ips() -def wait_for_classification_rules(ovs_logger, compute_nodes, - server_compute, server_port, - client_compute, client_port, - odl_ip, odl_port): + self.start_services_in_vm() + + self.vxlan_start_interface(self.fips_sfs[0], 'eth0', 'eth1', None) + self.vxlan_start_interface(self.fips_sfs[0], 'eth1', 'eth0', None) + + logger.info("Wait for ODL to update the classification rules in OVS") + t1.join() + + results = self.present_results_allowed_port_http(self.testcase_config) + + self.vxlan_blocking_stop(self.fips_sfs[0]) + self.vxlan_start_interface(self.fips_sfs[0], 'eth0', 'eth1', "80") + self.vxlan_start_interface(self.fips_sfs[0], 'eth1', 'eth0', None) + + results = self.present_results_blocked_port_http(self.testcase_config, + 'HTTP uplink') + + self.vxlan_blocking_stop(self.fips_sfs[0]) + self.vxlan_start_interface(self.fips_sfs[0], 'eth0', 'eth1', None) + self.vxlan_start_interface(self.fips_sfs[0], 'eth1', 'eth0', + self.testcase_config.source_port) + + results = self.present_results_blocked_port_http(self.testcase_config, + 'HTTP downlink') + + self.vxlan_blocking_stop(self.fips_sfs[0]) + self.vxlan_start_interface(self.fips_sfs[0], 'eth0', 'eth1', None) + self.vxlan_start_interface(self.fips_sfs[0], 'eth1', 'eth0', None) + results = self.present_results_allowed_http() + + if __name__ == '__main__': + return results.compile_summary(), self.creators + + if __name__ == 'sfc.tests.functest.sfc_symmetric_chain': + return results.compile_summary(), self.creators + + def get_creators(self): + """Return the creators info, specially in case the info is not + returned due to an exception. + + :return: creators + """ + return self.creators + + +def symmetric_wait_for_classification_rules(ovs_logger, compute_nodes, + server_compute, server_port, + client_compute, client_port, + odl_ip, odl_port): if client_compute == server_compute: odl_utils.wait_for_classification_rules( ovs_logger, @@ -330,5 +142,14 @@ def wait_for_classification_rules(ovs_logger, compute_nodes, if __name__ == '__main__': - logging.config.fileConfig(COMMON_CONFIG.functest_logging_api) - main() + + # Disable InsecureRequestWarning errors when executing the SFC tests in XCI + urllib3.disable_warnings() + + TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_symmetric_chain') + supported_installers = ['fuel', 'apex', 'osa', 'compass'] + vnf_names = ['testVNF1'] + + test_run = SfcSymmetricChain(TESTCASE_CONFIG, supported_installers, + vnf_names) + test_run.run() diff --git a/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py b/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py index a5133f00..92c2711e 100644 --- a/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py +++ b/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py @@ -8,307 +8,120 @@ # http://www.apache.org/licenses/LICENSE-2.0 # -import os -import sys import threading import logging +import urllib3 -import sfc.lib.openstack_utils as os_sfc_utils import sfc.lib.odl_utils as odl_utils -import opnfv.utils.ovs_logger as ovs_log - import sfc.lib.config as sfc_config -import sfc.lib.test_utils as test_utils -from sfc.lib.results import Results -from opnfv.deployment.factory import Factory as DeploymentFactory -import sfc.lib.topology_shuffler as topo_shuffler - +from sfc.tests.functest import sfc_parent_function +""" logging configuration """ logger = logging.getLogger(__name__) -CLIENT = "client" -SERVER = "server" -COMMON_CONFIG = sfc_config.CommonConfig() -TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_two_chains_SSH_and_HTTP') - - -def main(): - deploymentHandler = DeploymentFactory.get_handler( - COMMON_CONFIG.installer_type, - COMMON_CONFIG.installer_ip, - COMMON_CONFIG.installer_user, - COMMON_CONFIG.installer_password, - COMMON_CONFIG.installer_key_file) - - installer_type = os.environ.get("INSTALLER_TYPE") - - supported_installers = ['fuel', 'apex', 'osa', 'compass'] - - if installer_type not in supported_installers: - logger.error( - '\033[91mYour installer is not supported yet\033[0m') - sys.exit(1) - - installer_ip = os.environ.get("INSTALLER_IP") - if not installer_ip: - logger.error( - '\033[91minstaller ip is not set\033[0m') - logger.error( - '\033[91mexport INSTALLER_IP=<ip>\033[0m') - sys.exit(1) - - cluster = COMMON_CONFIG.installer_cluster - openstack_nodes = (deploymentHandler.get_nodes({'cluster': cluster}) - if cluster is not None - else deploymentHandler.get_nodes()) - - controller_nodes = [node for node in openstack_nodes - if node.is_controller()] - compute_nodes = [node for node in openstack_nodes - if node.is_compute()] - - odl_ip, odl_port = odl_utils.get_odl_ip_port(openstack_nodes) - - for compute in compute_nodes: - logger.info("This is a compute: %s" % compute.ip) - - results = Results(COMMON_CONFIG.line_length) - results.add_to_summary(0, "=") - results.add_to_summary(2, "STATUS", "SUBTEST") - results.add_to_summary(0, "=") - - openstack_sfc = os_sfc_utils.OpenStackSFC() - - custom_flv = openstack_sfc.create_flavor( - COMMON_CONFIG.flavor, - COMMON_CONFIG.ram_size_in_mb, - COMMON_CONFIG.disk_size_in_gb, - COMMON_CONFIG.vcpu_count) - if not custom_flv: - logger.error("Failed to create custom flavor") - sys.exit(1) - - tacker_client = os_sfc_utils.get_tacker_client() - - controller_clients = test_utils.get_ssh_clients(controller_nodes) - compute_clients = test_utils.get_ssh_clients(compute_nodes) - - ovs_logger = ovs_log.OVSLogger( - os.path.join(COMMON_CONFIG.sfc_test_dir, 'ovs-logs'), - COMMON_CONFIG.functest_results_dir) - - image_creator = openstack_sfc.register_glance_image( - COMMON_CONFIG.image_name, - COMMON_CONFIG.image_url, - COMMON_CONFIG.image_format, - 'public') - network, router = openstack_sfc.create_network_infrastructure( - TESTCASE_CONFIG.net_name, - TESTCASE_CONFIG.subnet_name, - TESTCASE_CONFIG.subnet_cidr, - TESTCASE_CONFIG.router_name) +class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase): + """We create one client and one server using nova. + Then, 2 SFs are created using tacker. + Two chains are created, having one SF each. + The vxlan tool is used on both SFs. The purpose is to + check different HTTP and SSH traffic combinations. + """ - sg = openstack_sfc.create_security_group(TESTCASE_CONFIG.secgroup_name) + def run(self): - vnf_names = ['testVNF1', 'testVNF2'] - - topo_seed = topo_shuffler.get_seed() # change to None for nova av zone - testTopology = topo_shuffler.topology(vnf_names, openstack_sfc, - seed=topo_seed) - - logger.info('This test is run with the topology {0}' - .format(testTopology['id'])) - logger.info('Topology description: {0}' - .format(testTopology['description'])) - - client_instance, client_creator = openstack_sfc.create_instance( - CLIENT, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['client']) - - server_instance, server_creator = openstack_sfc.create_instance( - SERVER, COMMON_CONFIG.flavor, image_creator, network, sg, - av_zone=testTopology['server']) - - server_ip = server_instance.ports[0].ips[0]['ip_address'] - - os_sfc_utils.register_vim(tacker_client, vim_file=COMMON_CONFIG.vim_file) - - tosca_red = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd_red) - os_sfc_utils.create_vnfd(tacker_client, - tosca_file=tosca_red, - vnfd_name='test-vnfd1') - - tosca_blue = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - TESTCASE_CONFIG.test_vnfd_blue) - - os_sfc_utils.create_vnfd(tacker_client, - tosca_file=tosca_blue, - vnfd_name='test-vnfd2') + logger.info("The test scenario %s is starting", __name__) - default_param_file = os.path.join( - COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnfd_dir, - COMMON_CONFIG.vnfd_default_params_file) + self.register_vnf_template(self.testcase_config.test_vnfd_red, + 'test-vnfd1') + self.register_vnf_template(self.testcase_config.test_vnfd_blue, + 'test-vnfd2') - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, vnf_names[0], 'test-vnfd1', 'test-vim', - default_param_file, testTopology[vnf_names[0]]) - os_sfc_utils.create_vnf_in_av_zone( - tacker_client, vnf_names[1], 'test-vnfd2', 'test-vim', - default_param_file, testTopology[vnf_names[1]]) + self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim') + self.create_vnf(self.vnfs[1], 'test-vnfd2', 'test-vim') - vnf1_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnf_names[0]) - vnf2_id = os_sfc_utils.wait_for_vnf(tacker_client, vnf_name=vnf_names[1]) - if vnf1_id is None or vnf2_id is None: - logger.error('ERROR while booting vnfs') - sys.exit(1) + logger.info("Call Parent create_vnffg with index") + self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red', + 'red_http', port=80, protocol='tcp', + symmetric=False, vnf_index=0) - tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnffgd_dir, - TESTCASE_CONFIG.test_vnffgd_red) + self.create_vnffg(self.testcase_config.test_vnffgd_blue, 'blue', + 'blue_ssh', port=22, protocol='tcp', + symmetric=False, vnf_index=1) + self.create_classifier('dummy') - os_sfc_utils.create_vnffgd(tacker_client, - tosca_file=tosca_file, - vnffgd_name='red') + t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.odl_ip, self.odl_port, + self.client_instance.hypervisor_hostname, + [self.neutron_port],)) + try: + t1.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) - neutron_port = openstack_sfc.get_client_port(client_instance, - client_creator) - os_sfc_utils.create_vnffg_with_param_file(tacker_client, 'red', - 'red_http', - default_param_file, - neutron_port.id) + logger.info("Assigning floating IPs to instances") + self.assign_floating_ip_client_server() - # Start measuring the time it takes to implement the classification rules - t1 = threading.Thread(target=odl_utils.wait_for_classification_rules, - args=(ovs_logger, compute_nodes, odl_ip, - odl_port, openstack_sfc.get_compute_client(), - [neutron_port],)) + self.assign_floating_ip_sfs() - try: - t1.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) + self.check_floating_ips() + self.start_services_in_vm() + self.vxlan_blocking_start(self.fips_sfs[0], "80") + self.vxlan_blocking_start(self.fips_sfs[1], "22") - logger.info("Assigning floating IPs to instances") - client_floating_ip = openstack_sfc.assign_floating_ip(router, - client_instance, - client_creator) - server_floating_ip = openstack_sfc.assign_floating_ip(router, - server_instance, - server_creator) - fips_sfs = openstack_sfc.assign_floating_ip_vnfs(router) - sf1_floating_ip = fips_sfs[0] - sf2_floating_ip = fips_sfs[1] + logger.info("Wait for ODL to update the classification rules in OVS") + t1.join() - fips = [client_floating_ip, server_floating_ip, sf1_floating_ip, - sf2_floating_ip] + results = self.present_results_ssh() + results = self.present_results_http() - for ip in fips: - logger.info("Checking connectivity towards floating IP [%s]" % ip) - if not test_utils.ping(ip, retries=50, retry_timeout=3): - logger.error("Cannot ping floating IP [%s]" % ip) - os_sfc_utils.get_tacker_items() - odl_utils.get_odl_items(odl_ip, odl_port) - sys.exit(1) - logger.info("Successful ping to floating IP [%s]" % ip) + logger.info("Changing the classification") - if not test_utils.check_ssh([sf1_floating_ip, sf2_floating_ip]): - logger.error("Cannot establish SSH connection to the SFs") - sys.exit(1) + self.swap_classifiers('red_http', 'blue_ssh') - logger.info("Starting HTTP server on %s" % server_floating_ip) - if not test_utils.start_http_server(server_floating_ip): - logger.error('\033[91mFailed to start HTTP server on %s\033[0m' - % server_floating_ip) - sys.exit(1) + # Start measuring the time it takes to implement the classification + # rules + t2 = threading.Thread(target=odl_utils.wait_for_classification_rules, + args=(self.ovs_logger, self.compute_nodes, + self.odl_ip, self.odl_port, + self.client_instance.hypervisor_hostname, + [self.neutron_port],)) + try: + t2.start() + except Exception as e: + logger.error("Unable to start the thread that counts time %s" % e) - logger.info("Starting SSH firewall on %s" % sf1_floating_ip) - test_utils.start_vxlan_tool(sf1_floating_ip, block="22") - logger.info("Starting HTTP firewall on %s" % sf2_floating_ip) - test_utils.start_vxlan_tool(sf2_floating_ip, block="80") + logger.info("Wait for ODL to update the classification rules in OVS") + t2.join() - logger.info("Wait for ODL to update the classification rules in OVS") - t1.join() + results = self.present_results_allowed_http() + results = self.present_results_allowed_ssh() - logger.info("Test SSH") - if test_utils.is_ssh_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "SSH Blocked") - else: - error = ('\033[91mTEST 1 [FAILED] ==> SSH NOT BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "SSH Blocked") + if __name__ == '__main__': + return results.compile_summary(), self.creators - logger.info("Test HTTP") - if not test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP works") - else: - error = ('\033[91mTEST 2 [FAILED] ==> HTTP BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP works") + if __name__ == 'sfc.tests.functest.sfc_two_chains_SSH_and_HTTP': + return results.compile_summary(), self.creators - logger.info("Changing the classification") + def get_creators(self): + """Return the creators info, specially in case the info is not + returned due to an exception. - os_sfc_utils.delete_vnffg(tacker_client, vnffg_name='red_http_works') + :return: creators + """ + return self.creators - os_sfc_utils.delete_vnffgd(tacker_client, vnffgd_name='red') - tosca_file = os.path.join(COMMON_CONFIG.sfc_test_dir, - COMMON_CONFIG.vnffgd_dir, - TESTCASE_CONFIG.test_vnffgd_blue) - - os_sfc_utils.create_vnffgd(tacker_client, - tosca_file=tosca_file, - vnffgd_name='blue') - - os_sfc_utils.create_vnffg_with_param_file(tacker_client, 'blue', - 'blue_ssh', - default_param_file, - neutron_port) - - # Start measuring the time it takes to implement the classification rules - t2 = threading.Thread(target=odl_utils.wait_for_classification_rules, - args=(ovs_logger, compute_nodes, odl_ip, - odl_port, openstack_sfc.get_compute_client(), - [neutron_port],)) - try: - t2.start() - except Exception as e: - logger.error("Unable to start the thread that counts time %s" % e) - - logger.info("Wait for ODL to update the classification rules in OVS") - t2.join() - - logger.info("Test HTTP") - if test_utils.is_http_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "HTTP Blocked") - else: - error = ('\033[91mTEST 3 [FAILED] ==> HTTP WORKS\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "HTTP Blocked") - - logger.info("Test SSH") - if not test_utils.is_ssh_blocked(client_floating_ip, server_ip): - results.add_to_summary(2, "PASS", "SSH works") - else: - error = ('\033[91mTEST 4 [FAILED] ==> SSH BLOCKED\033[0m') - logger.error(error) - test_utils.capture_ovs_logs( - ovs_logger, controller_clients, compute_clients, error) - results.add_to_summary(2, "FAIL", "SSH works") +if __name__ == '__main__': - return results.compile_summary(), openstack_sfc.creators + # Disable InsecureRequestWarning errors when executing the SFC tests in XCI + urllib3.disable_warnings() + TESTCASE_CONFIG = sfc_config.TestcaseConfig('sfc_two_chains_SSH_and_HTTP') + supported_installers = ['fuel', 'apex', 'osa', 'compass'] + vnf_names = ['testVNF1', 'testVNF2'] -if __name__ == '__main__': - logging.config.fileConfig(COMMON_CONFIG.functest_logging_api) - main() + test_run = SfcTwoChainsSSHandHTTP(TESTCASE_CONFIG, supported_installers, + vnf_names) + test_run.run() diff --git a/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd-pike.yaml b/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd-pike.yaml deleted file mode 100644 index 3f10e6b8..00000000 --- a/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd-pike.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 -description: test-case2_HTTP Test - -topology_template: - description: topology-template-test2 - inputs: - net_src_port_id: - type: string - - node_templates: - Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker - description: creates path - properties: - id: 1 - policy: - type: ACL - criteria: - - network_src_port_id: {get_input: net_src_port_id} - - destination_port_range: 80-80 - - ip_proto: 6 - path: - - forwarder: test-vnfd1 - capability: CP1 - - groups: - VNFFG1: - type: tosca.groups.nfv.VNFFG - description: creates chain - properties: - vendor: tacker - version: 1.0 - number_of_endpoints: 1 - dependent_virtual_link: [VL1] - connection_point: [CP1] - constituent_vnfs: [test-vnfd1] - members: [Forwarding_path1] diff --git a/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd.yaml b/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd.yaml index 28b78ead..fd549079 100644 --- a/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd.yaml +++ b/sfc/tests/functest/vnffgd-templates/test-deletion-vnffgd.yaml @@ -10,16 +10,18 @@ topology_template: node_templates: Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker + type: tosca.nodes.nfv.FP.TackerV2 description: creates path properties: id: 1 policy: type: ACL criteria: - - network_src_port_id: {get_input: net_src_port_id} - destination_port_range: 80-80 - ip_proto: 6 + - name: http_classifier + classifier: + network_src_port_id: {get_input: net_src_port_id} + destination_port_range: 80-80 + ip_proto: 6 path: - forwarder: test-vnfd1 capability: CP1 diff --git a/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd-pike.yaml b/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd-pike.yaml deleted file mode 100644 index 27c7d545..00000000 --- a/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd-pike.yaml +++ /dev/null @@ -1,40 +0,0 @@ ---- -tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 -description: test-case1 - -topology_template: - description: topology-template-test1 - inputs: - net_src_port_id: - type: string - - node_templates: - Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker - description: creates path - properties: - id: 1 - policy: - type: ACL - criteria: - - network_src_port_id: {get_input: net_src_port_id} - - destination_port_range: 80-80 - - ip_proto: 6 - path: - - forwarder: test-vnfd1 - capability: CP1 - - forwarder: test-vnfd2 - capability: CP1 - - groups: - VNFFG1: - type: tosca.groups.nfv.VNFFG - description: creates chain - properties: - vendor: tacker - version: 1.0 - number_of_endpoints: 2 - dependent_virtual_link: [VL1, VL1] - connection_point: [CP1, CP1] - constituent_vnfs: [test-vnfd1, test-vnfd2] - members: [Forwarding_path1] diff --git a/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd.yaml b/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd.yaml index 544d6e8e..4dcc0f3c 100644 --- a/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd.yaml +++ b/sfc/tests/functest/vnffgd-templates/test-one-chain-vnffgd.yaml @@ -10,16 +10,18 @@ topology_template: node_templates: Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker + type: tosca.nodes.nfv.FP.TackerV2 description: creates path properties: id: 1 policy: type: ACL criteria: - - network_src_port_id: {get_input: net_src_port_id} - destination_port_range: 80-80 - ip_proto: 6 + - name: http_classifier + classifier: + network_src_port_id: {get_input: net_src_port_id} + destination_port_range: 80-80 + ip_proto: 6 path: - forwarder: test-vnfd1 capability: CP1 diff --git a/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml b/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml index 6b14df1b..371d25fe 100644 --- a/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml +++ b/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml @@ -14,18 +14,20 @@ topology_template: node_templates: Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker + type: tosca.nodes.nfv.FP.TackerV2 description: creates path properties: id: 1 policy: type: ACL criteria: - - network_src_port_id: {get_input: net_src_port_id} - - network_dst_port_id: {get_input: net_dst_port_id} - - ip_dst_prefix: {get_input: ip_dst_prefix} - - destination_port_range: 80-80 - - ip_proto: 6 + - name: http_classifier + classifier: + network_src_port_id: {get_input: net_src_port_id} + network_dst_port_id: {get_input: net_dst_port_id} + ip_dst_prefix: {get_input: ip_dst_prefix} + destination_port_range: 80-80 + ip_proto: 6 path: - forwarder: test-vnfd1 capability: CP1 diff --git a/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml-queens b/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml-queens deleted file mode 100644 index c40c447c..00000000 --- a/sfc/tests/functest/vnffgd-templates/test-symmetric-vnffgd.yaml-queens +++ /dev/null @@ -1,46 +0,0 @@ ---- -tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 -description: test-case-symmetric - -topology_template: - description: topology-template-test1 - inputs: - net_src_port_id: - type: string - net_dst_port_id: - type: string - ip_dst_prefix: - type: string - - node_templates: - Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker - description: creates path - properties: - id: 1 - policy: - type: ACL - criteria: - - network_src_port_id: {get_input: net_src_port_id} - network_dst_port_id: {get_input: net_dst_port_id} - ip_dst_prefix: {get_input: ip_dst_prefix} - destination_port_range: 80-80 - ip_proto: 6 - path: - - forwarder: test-vnfd1 - capability: CP1 - - forwarder: test-vnfd1 - capability: CP2 - - groups: - VNFFG1: - type: tosca.groups.nfv.VNFFG - description: creates chain - properties: - vendor: tacker - version: 1.0 - number_of_endpoints: 2 - dependent_virtual_link: [VL1, VL1] - connection_point: [CP1, CP2] - constituent_vnfs: [test-vnfd1, test-vnfd1] - members: [Forwarding_path1] diff --git a/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd1-pike.yaml b/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd1-pike.yaml deleted file mode 100644 index f0615e4e..00000000 --- a/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd1-pike.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 -description: test-case2_HTTP Test - -topology_template: - description: topology-template-test2 - inputs: - net_src_port_id: - type: string - - node_templates: - Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker - description: creates path - properties: - id: 1 - policy: - type: ACL - criteria: - - network_src_port_id: {get_input: net_src_port_id} - - destination_port_range: 22-80 - - ip_proto: 6 - path: - - forwarder: test-vnfd1 - capability: CP1 - - groups: - VNFFG1: - type: tosca.groups.nfv.VNFFG - description: creates chain - properties: - vendor: tacker - version: 1.0 - number_of_endpoints: 1 - dependent_virtual_link: [VL1] - connection_point: [CP1] - constituent_vnfs: [test-vnfd1] - members: [Forwarding_path1] diff --git a/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd2-pike.yaml b/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd2-pike.yaml deleted file mode 100644 index ec18c9d6..00000000 --- a/sfc/tests/functest/vnffgd-templates/test-two-chains-vnffgd2-pike.yaml +++ /dev/null @@ -1,39 +0,0 @@ ---- -tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 -description: test-case2_SSH Test - -topology_template: - description: topology-template-test2 - inputs: - net_src_port_id: - type: string - - - node_templates: - Forwarding_path1: - type: tosca.nodes.nfv.FP.Tacker - description: creates path - properties: - id: 2 - policy: - type: ACL - criteria: - - network_src_port_id: {get_input: net_src_port_id} - - destination_port_range: 22-80 - - ip_proto: 6 - path: - - forwarder: test-vnfd2 - capability: CP1 - - groups: - VNFFG1: - type: tosca.groups.nfv.VNFFG - description: creates chain - properties: - vendor: tacker - version: 1.0 - number_of_endpoints: 1 - dependent_virtual_link: [VL1] - connection_point: [CP1] - constituent_vnfs: [test-vnfd2] - members: [Forwarding_path1] |