aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Buil <mbuil@suse.com>2018-08-27 18:11:11 +0200
committerManuel Buil <mbuil@suse.com>2018-08-31 16:37:09 +0200
commitbdad6faa1fafe7cd20ea96aa70a52178d62add63 (patch)
treef61454f7055c5252fd7f641235a695a43eff96b8
parentc0afe0534d46255cf52b85d152d0adc1c4487d83 (diff)
Decouple tacker from tests
Support n-sfc too and abstract a bit the MANO layer so that other MANO components can be inserted into the test Change-Id: I3fb59fbf40b4207bf1721092cd8ff0559e1d9d90 Signed-off-by: Manuel Buil <mbuil@suse.com>
-rw-r--r--requirements.txt2
-rw-r--r--sfc/lib/cleanup.py40
-rw-r--r--sfc/lib/config.py2
-rw-r--r--sfc/lib/odl_utils.py17
-rw-r--r--sfc/lib/openstack_utils.py134
-rw-r--r--sfc/tests/functest/config.yaml4
-rw-r--r--sfc/tests/functest/run_sfc_tests.py8
-rw-r--r--sfc/tests/functest/sfc_chain_deletion.py11
-rw-r--r--sfc/tests/functest/sfc_one_chain_two_service_functions.py11
-rw-r--r--sfc/tests/functest/sfc_parent_function.py236
-rw-r--r--sfc/tests/functest/sfc_symmetric_chain.py61
-rw-r--r--sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py10
-rw-r--r--sfc/unit_tests/unit/lib/test_cleanup.py84
-rw-r--r--sfc/unit_tests/unit/lib/test_odl_utils.py40
-rw-r--r--sfc/unit_tests/unit/lib/test_openstack_utils.py264
15 files changed, 688 insertions, 236 deletions
diff --git a/requirements.txt b/requirements.txt
index 3442097f..36189ea1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,6 +9,8 @@ xmltodict>=0.10.1 # MIT
python-keystoneclient>=3.8.0 # Apache-2.0
python-novaclient>=9.1.0 # Apache-2.0
python-tackerclient>=0.8.0 # Apache-2.0
+python-neutronclient>=6.9.0
+networking-sfc>=7.0.0
PyYAML>=3.12 # MIT
opnfv
snaps
diff --git a/sfc/lib/cleanup.py b/sfc/lib/cleanup.py
index e614867d..ee3ad689 100644
--- a/sfc/lib/cleanup.py
+++ b/sfc/lib/cleanup.py
@@ -75,6 +75,7 @@ def delete_vims():
# Creators is a list full of SNAPs objects
def delete_openstack_objects(creators):
+ logger.info("Deleting the openstack objects...")
for creator in reversed(creators):
try:
creator.clean()
@@ -97,26 +98,49 @@ def cleanup_odl(odl_ip, odl_port):
delete_odl_ietf_access_lists(odl_ip, odl_port)
-def cleanup(creators, odl_ip=None, odl_port=None):
+def cleanup_nsfc_objects():
+ '''
+ cleanup the networking-sfc objects created for the test
+ '''
+ # TODO Add n-sfc to snaps so that it can be removed through
+ # delete_openstack_objects
+ openstack_sfc = os_sfc_utils.OpenStackSFC()
+ openstack_sfc.delete_chain()
+ openstack_sfc.delete_port_groups()
+
+
+def cleanup_tacker_objects():
+ '''
+ cleanup the tacker objects created for the test
+ '''
delete_vnffgs()
delete_vnffgds()
delete_vnfs()
time.sleep(20)
delete_vnfds()
delete_vims()
+
+
+def cleanup_mano_objects(mano):
+ '''
+ Cleanup the mano objects (chains, classifiers, etc)
+ '''
+ if mano == 'tacker':
+ cleanup_tacker_objects()
+ elif mano == 'no-mano':
+ cleanup_nsfc_objects()
+
+
+def cleanup(creators, mano, odl_ip=None, odl_port=None):
+ cleanup_mano_objects(mano)
delete_openstack_objects(creators)
delete_untracked_security_groups()
if odl_ip is not None and odl_port is not None:
cleanup_odl(odl_ip, odl_port)
-def cleanup_from_bash(odl_ip=None, odl_port=None):
- delete_vnffgs()
- delete_vnffgds()
- delete_vnfs()
- time.sleep(20)
- delete_vnfds()
- delete_vims()
+def cleanup_from_bash(odl_ip=None, odl_port=None, mano='no-mano'):
+ cleanup_mano_objects(mano=mano)
if odl_ip is not None and odl_port is not None:
cleanup_odl(odl_ip, odl_port)
diff --git a/sfc/lib/config.py b/sfc/lib/config.py
index 541f6847..507142c9 100644
--- a/sfc/lib/config.py
+++ b/sfc/lib/config.py
@@ -88,6 +88,8 @@ class CommonConfig(object):
"defaults.image_format", self.config_file)
self.image_url = ft_utils.get_parameter_from_yaml(
"defaults.image_url", self.config_file)
+ self.mano_component = ft_utils.get_parameter_from_yaml(
+ "defaults.mano_component", self.config_file)
try:
self.vnf_image_name = ft_utils.get_parameter_from_yaml(
"defaults.vnf_image_name", self.config_file)
diff --git a/sfc/lib/odl_utils.py b/sfc/lib/odl_utils.py
index ebc6a873..85a8f86b 100644
--- a/sfc/lib/odl_utils.py
+++ b/sfc/lib/odl_utils.py
@@ -428,20 +428,3 @@ def check_vnffg_deletion(odl_ip, odl_port, ovs_logger, neutron_ports,
return False
return True
-
-
-def create_chain(tacker_client, default_param_file, neutron_port,
- COMMON_CONFIG, TESTCASE_CONFIG):
-
- 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')
-
- os_sfc_utils.create_vnffg_with_param_file(tacker_client, 'red',
- 'red_http',
- default_param_file,
- neutron_port.id)
diff --git a/sfc/lib/openstack_utils.py b/sfc/lib/openstack_utils.py
index b8deb144..06d19eaa 100644
--- a/sfc/lib/openstack_utils.py
+++ b/sfc/lib/openstack_utils.py
@@ -134,15 +134,17 @@ class OpenStackSFC:
return sec_group
def create_instance(self, vm_name, flavor_name, image_creator, network,
- secgrp, av_zone):
+ secgrp, av_zone, ports):
logger.info("Creating the instance {}...".format(vm_name))
- port_settings = PortConfig(name=vm_name + '-port',
- network_name=network.name)
+ port_settings = []
+ for port in ports:
+ port_settings.append(PortConfig(name=port,
+ network_name=network.name))
instance_settings = VmInstanceConfig(
name=vm_name, flavor=flavor_name,
security_group_names=str(secgrp.name),
- port_settings=[port_settings],
+ port_settings=port_settings,
availability_zone=av_zone)
instance_creator = cr_inst.OpenStackVmInstance(
@@ -249,11 +251,12 @@ class OpenStackSFC:
return fips
- def get_client_port(self, vm, vm_creator):
+ def get_instance_port(self, vm, vm_creator, port_name=None):
'''
Get the neutron port id of the client
'''
- port_name = vm.name + "-port"
+ if not port_name:
+ port_name = vm.name + "-port"
port = vm_creator.get_port_by_name(port_name)
if port is not None:
return port
@@ -273,6 +276,125 @@ class OpenStackSFC:
for sg in sec_groups:
neutron_utils.delete_security_group(self.neutron, sg)
+ def wait_for_vnf(self, vnf_creator):
+ '''
+ Waits for VNF to become active
+ '''
+ return vnf_creator.vm_active(block=True, poll_interval=5)
+
+ def create_port_groups(self, vnf_ports, vm_instance):
+ '''
+ Creates a networking-sfc port pair and group
+ '''
+ logger.info("Creating the port pairs...")
+ port_pair = dict()
+ port_pair['name'] = vm_instance.name + '-connection-points'
+ port_pair['description'] = 'port pair for ' + vm_instance.name
+
+ # In the symmetric testcase ingres != egress (VNF has 2 interfaces)
+ if len(vnf_ports) == 1:
+ port_pair['ingress'] = vnf_ports[0].id
+ port_pair['egress'] = vnf_ports[0].id
+ elif len(vnf_ports) == 2:
+ port_pair['ingress'] = vnf_ports[0].id
+ port_pair['egress'] = vnf_ports[1].id
+ else:
+ logger.error("Only SFs with one or two ports are supported")
+ raise Exception("Failed to create port pairs")
+ port_pair_info = \
+ self.neutron.create_sfc_port_pair({'port_pair': port_pair})
+ if not port_pair_info:
+ logger.warning("Chain creation failed due to port pair "
+ "creation failed for vnf %(vnf)s",
+ {'vnf': vm_instance.name})
+ return None
+
+ logger.info("Creating the port pair groups...")
+ port_pair_group = {}
+ port_pair_group['name'] = vm_instance.name + '-port-pair-group'
+ port_pair_group['description'] = \
+ 'port pair group for ' + vm_instance.name
+ port_pair_group['port_pairs'] = []
+ port_pair_group['port_pairs'].append(port_pair_info['port_pair']['id'])
+ ppg_config = {'port_pair_group': port_pair_group}
+ port_pair_group_info = \
+ self.neutron.create_sfc_port_pair_group(ppg_config)
+ if not port_pair_group_info:
+ logger.warning("Chain creation failed due to port pair group "
+ "creation failed for vnf "
+ "%(vnf)", vm_instance.name)
+ return None
+
+ return port_pair_group_info['port_pair_group']['id']
+
+ def create_chain(self, port_groups, neutron_port, port, protocol,
+ vnffg_name, symmetrical, server_port=None,
+ server_ip=None):
+ '''
+ Create the classifier
+ '''
+ logger.info("Creating the classifier...")
+
+ if symmetrical:
+ sfc_classifier_params = {'name': vnffg_name + '-classifier',
+ 'destination_ip_prefix': server_ip,
+ 'logical_source_port': neutron_port,
+ 'logical_destination_port': server_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'protocol': protocol}
+ else:
+ sfc_classifier_params = {'name': vnffg_name + '-classifier',
+ 'logical_source_port': neutron_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'protocol': protocol}
+
+ fc_config = {'flow_classifier': sfc_classifier_params}
+ fc_info = \
+ self.neutron.create_sfc_flow_classifier(fc_config)
+
+ logger.info("Creating the chain...")
+ port_chain = {}
+ port_chain['name'] = vnffg_name + '-port-chain'
+ port_chain['description'] = 'port-chain for SFC'
+ port_chain['port_pair_groups'] = port_groups
+ port_chain['flow_classifiers'] = []
+ port_chain['flow_classifiers'].append(fc_info['flow_classifier']['id'])
+ if symmetrical:
+ port_chain['chain_parameters'] = {}
+ port_chain['chain_parameters']['symmetric'] = True
+ chain_config = {'port_chain': port_chain}
+ return self.neutron.create_sfc_port_chain(chain_config)
+
+ def delete_port_groups(self):
+ '''
+ Delete all port groups and port pairs
+ '''
+ logger.info("Deleting the port groups...")
+ ppg_list = self.neutron.list_sfc_port_pair_groups()['port_pair_groups']
+ for ppg in ppg_list:
+ self.neutron.delete_sfc_port_pair_group(ppg['id'])
+
+ logger.info("Deleting the port pairs...")
+ pp_list = self.neutron.list_sfc_port_pairs()['port_pairs']
+ for pp in pp_list:
+ self.neutron.delete_sfc_port_pair(pp['id'])
+
+ def delete_chain(self):
+ '''
+ Delete the classifiers and the chains
+ '''
+ logger.info("Deleting the chain...")
+ pc_list = self.neutron.list_sfc_port_chains()['port_chains']
+ for pc in pc_list:
+ self.neutron.delete_sfc_port_chain(pc['id'])
+
+ logger.info("Deleting the classifiers...")
+ fc_list = self.neutron.list_sfc_flow_classifiers()['flow_classifiers']
+ for fc in fc_list:
+ self.neutron.delete_sfc_flow_classifier(fc['id'])
+
# TACKER SECTION #
def get_tacker_client_version():
diff --git a/sfc/tests/functest/config.yaml b/sfc/tests/functest/config.yaml
index 0144352e..d595f0cf 100644
--- a/sfc/tests/functest/config.yaml
+++ b/sfc/tests/functest/config.yaml
@@ -25,6 +25,10 @@ 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
diff --git a/sfc/tests/functest/run_sfc_tests.py b/sfc/tests/functest/run_sfc_tests.py
index 6fe211bf..2f72acb5 100644
--- a/sfc/tests/functest/run_sfc_tests.py
+++ b/sfc/tests/functest/run_sfc_tests.py
@@ -176,7 +176,9 @@ class SfcFunctest(testcase.TestCase):
result = {'status': 'FAILED'}
creators = tc_instance.get_creators()
if self.cleanup_flag is True:
- sfc_cleanup.cleanup(creators, odl_ip=odl_ip,
+ sfc_cleanup.cleanup(creators,
+ COMMON_CONFIG.mano_component,
+ odl_ip=odl_ip,
odl_port=odl_port)
cleanup_run_flag = True
end_time = time.time()
@@ -198,7 +200,9 @@ class SfcFunctest(testcase.TestCase):
self.details.update({test_name: dic})
if cleanup_run_flag is not True and self.cleanup_flag is True:
- sfc_cleanup.cleanup(creators, odl_ip=odl_ip,
+ sfc_cleanup.cleanup(creators,
+ COMMON_CONFIG.mano_component,
+ odl_ip=odl_ip,
odl_port=odl_port)
self.stop_time = time.time()
diff --git a/sfc/tests/functest/sfc_chain_deletion.py b/sfc/tests/functest/sfc_chain_deletion.py
index 527dc822..3944cf90 100644
--- a/sfc/tests/functest/sfc_chain_deletion.py
+++ b/sfc/tests/functest/sfc_chain_deletion.py
@@ -32,11 +32,12 @@ class SfcChainDeletion(sfc_parent_function.SfcCommonTestCase):
def run(self):
logger.info("The test scenario %s is starting", __name__)
- self.create_custom_vnfd(self.testcase_config.test_vnfd_red,
- 'test-vnfd1')
+ self.register_vnf_template(self.testcase_config.test_vnfd_red,
+ 'test-vnfd1')
self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim')
- self.create_chain(self.testcase_config)
+ self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red',
+ 'red_http', port=80, protocol='tcp', symmetric=False)
t1 = threading.Thread(target=odl_utils.wait_for_classification_rules,
args=(self.ovs_logger, self.compute_nodes,
@@ -63,7 +64,9 @@ class SfcChainDeletion(sfc_parent_function.SfcCommonTestCase):
self.remove_vnffg('red_http', 'red')
self.check_deletion()
- self.create_chain(self.testcase_config)
+ self.create_vnffg(self.testcase_config.test_vnffgd_red, 'blue',
+ 'blue_http', port=80, protocol='tcp',
+ symmetric=False, only_chain=True)
t2 = threading.Thread(target=odl_utils.wait_for_classification_rules,
args=(self.ovs_logger, self.compute_nodes,
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 039cf625..38d6176f 100644
--- a/sfc/tests/functest/sfc_one_chain_two_service_functions.py
+++ b/sfc/tests/functest/sfc_one_chain_two_service_functions.py
@@ -29,16 +29,17 @@ class SfcOneChainTwoServiceTC(sfc_parent_function.SfcCommonTestCase):
def run(self):
logger.info("The test scenario %s is starting", __name__)
- self.create_custom_vnfd(self.testcase_config.test_vnfd_red,
- 'test-vnfd1')
- self.create_custom_vnfd(self.testcase_config.test_vnfd_blue,
- 'test-vnfd2')
+
+ self.register_vnf_template(self.testcase_config.test_vnfd_red,
+ 'test-vnfd1')
+ self.register_vnf_template(self.testcase_config.test_vnfd_blue,
+ 'test-vnfd2')
self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim')
self.create_vnf(self.vnfs[1], 'test-vnfd2', 'test-vim')
self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red',
- 'red_http')
+ '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,
diff --git a/sfc/tests/functest/sfc_parent_function.py b/sfc/tests/functest/sfc_parent_function.py
index 6af8e8ec..d93b2fbf 100644
--- a/sfc/tests/functest/sfc_parent_function.py
+++ b/sfc/tests/functest/sfc_parent_function.py
@@ -51,11 +51,15 @@ class SfcCommonTestCase(object):
self.vnf_id = None
self.client_floating_ip = None
self.server_floating_ip = None
- self.fips_sfs = None
+ self.fips_sfs = []
self.neutron_port = None
+ self.vnf_objects = dict()
self.testcase_config = testcase_config
self.vnfs = vnfs
+ # n-sfc variables
+ self.port_groups = []
+
self.prepare_env(testcase_config, supported_installers, vnfs)
def prepare_env(self, testcase_config, supported_installers, vnfs):
@@ -117,9 +121,10 @@ class SfcCommonTestCase(object):
self.controller_clients = test_utils.get_ssh_clients(controller_nodes)
self.compute_clients = test_utils.get_ssh_clients(self.compute_nodes)
- self.tacker_client = os_sfc_utils.get_tacker_client()
- os_sfc_utils.register_vim(self.tacker_client,
- vim_file=COMMON_CONFIG.vim_file)
+ 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'),
@@ -170,13 +175,15 @@ class SfcCommonTestCase(object):
openstack_sfc.create_instance(SERVER, COMMON_CONFIG.flavor,
self.image_creator, self.network,
self.sg,
- self.test_topology['server'])
+ self.test_topology['server'],
+ [SERVER + '-port'])
self.client_instance, self.client_creator = \
openstack_sfc.create_instance(CLIENT, COMMON_CONFIG.flavor,
self.image_creator, self.network,
self.sg,
- self.test_topology['client'])
+ 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(
@@ -186,6 +193,20 @@ class SfcCommonTestCase(object):
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)
@@ -201,12 +222,14 @@ class SfcCommonTestCase(object):
tosca_file=tosca_file,
vnfd_name=vnfd_name)
- def create_vnf(self, vnf_names, vnfd_name, vim_name):
- """Create vnf
+ def create_vnf(self, vnf_name, vnfd_name=None, vim_name=None,
+ symmetric=False):
+ """Create custom vnf
- :param vnf_names: names of available vnf(s)
+ :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
"""
@@ -215,14 +238,35 @@ class SfcCommonTestCase(object):
logger.info('Topology description: {0}'
.format(self.test_topology['description']))
- os_sfc_utils.create_vnf_in_av_zone(
- self.tacker_client, vnf_names, vnfd_name, vim_name,
- self.default_param_file, self.test_topology[vnf_names])
-
- self.vnf_id = os_sfc_utils.wait_for_vnf(self.tacker_client,
- vnf_name=vnf_names)
- if self.vnf_id is None:
- raise Exception('ERROR while booting vnfs')
+ 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_creator = \
+ openstack_sfc.create_instance(vnf_name, COMMON_CONFIG.flavor,
+ self.vnf_image_creator,
+ self.network,
+ self.sg,
+ av_zone,
+ ports)
+
+ if not openstack_sfc.wait_for_vnf(vnf_creator):
+ raise Exception('ERROR while booting vnf %s' % vnf_name)
+
+ self.creators.append(vnf_creator)
+ self.vnf_objects[vnf_name] = [vnf_creator, vnf_instance]
def assign_floating_ip_client_server(self):
"""Assign floating IPs on the router about server and the client
@@ -238,18 +282,28 @@ class SfcCommonTestCase(object):
self.server_floating_ip = openstack_sfc.assign_floating_ip(
self.router, self.server_instance, self.server_creator)
- def assign_floating_ip_sfs(self, vnf_ip=None):
+ def assign_floating_ip_sfs(self):
"""Assign floating IPs to service function
- :param vnf_ip: IP of vnf - optional
:return: The list fips_sfs consist of the available IPs for service
functions
"""
logger.info("Assigning floating IPs to service functions")
- self.fips_sfs = openstack_sfc.assign_floating_ip_vnfs(self.router,
- vnf_ip)
+ 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:
+ # creator object is in [0] and instance in [1]
+ vnf_instance = self.vnf_objects[vnf][1]
+ vnf_creator = self.vnf_objects[vnf][0]
+ sf_floating_ip = openstack_sfc.assign_floating_ip(
+ self.router, vnf_instance, vnf_creator)
+ self.fips_sfs.append(sf_floating_ip)
def check_floating_ips(self):
"""Check the responsivness of the floating IPs
@@ -338,37 +392,122 @@ class SfcCommonTestCase(object):
: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_vnffg(self.tacker_client,
- vnffg_name=par_vnffg_name)
+ os_sfc_utils.delete_vnffgd(self.tacker_client,
+ vnffgd_name=par_vnffgd_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()
- def create_vnffg(self, testcase_config_name, vnf_name, conn_name):
+ def create_vnffg(self, testcase_config_name, vnffgd_name, vnffg_name,
+ port=80, protocol='tcp', symmetric=False,
+ only_chain=False):
"""Create the vnffg components following the instructions from
relevant templates.
:param testcase_config_name: The config input of the test case
- :param vnf_name: The name of the vnf
- :param conn_name: Protocol type / name of the component
+ :param vnffgd_name: The name of the vnffgd template
+ :param vnffg_name: The name for the vnffg
:return: Create the vnffg component
"""
- 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=vnf_name)
-
- self.neutron_port = openstack_sfc.get_client_port(self.client_instance,
- self.client_creator)
- os_sfc_utils.create_vnffg_with_param_file(self.tacker_client, vnf_name,
- conn_name,
- self.default_param_file,
- self.neutron_port.id)
+ 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 = \
+ openstack_sfc.get_instance_port(self.client_instance,
+ self.client_creator)
+
+ if symmetric:
+ server_port = openstack_sfc.get_instance_port(
+ self.server_instance,
+ self.server_creator)
+ 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=server_port.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':
+ if not only_chain:
+ for vnf in self.vnfs:
+ # creator object is in [0] and instance in [1]
+ vnf_instance = self.vnf_objects[vnf][1]
+ vnf_creator = self.vnf_objects[vnf][0]
+ if symmetric:
+ # VNFs have two ports
+ p1 = vnf_instance.name + '-port1'
+ neutron_port1 = \
+ openstack_sfc.get_instance_port(vnf_instance,
+ vnf_creator,
+ port_name=p1)
+ p2 = vnf_instance.name + '-port2'
+ neutron_port2 = \
+ openstack_sfc.get_instance_port(vnf_instance,
+ vnf_creator,
+ port_name=p2)
+ neutron_ports = [neutron_port1, neutron_port2]
+
+ else:
+ neutron_port1 = \
+ openstack_sfc.get_instance_port(vnf_instance,
+ vnf_creator)
+ neutron_ports = [neutron_port1]
+
+ port_group = \
+ openstack_sfc.create_port_groups(neutron_ports,
+ vnf_instance)
+
+ self.port_groups.append(port_group)
+ self.neutron_port = \
+ openstack_sfc.get_instance_port(self.client_instance,
+ self.client_creator)
+
+ if symmetric:
+ # We must pass the server_port and server_ip in the symmetric
+ # case. Otherwise ODL does not work well
+ server_port = openstack_sfc.get_instance_port(
+ self.server_instance,
+ self.server_creator)
+ server_ip_prefix = self.server_ip + '/32'
+ openstack_sfc.create_chain(self.port_groups,
+ self.neutron_port.id,
+ port, protocol, vnffg_name,
+ symmetric,
+ server_port=server_port.id,
+ server_ip=server_ip_prefix)
+
+ else:
+ openstack_sfc.create_chain(self.port_groups,
+ self.neutron_port.id,
+ port, protocol, vnffg_name,
+ symmetric)
def present_results_http(self):
"""Check whether the connection between server and client using
@@ -438,19 +577,6 @@ class SfcCommonTestCase(object):
return results
- def create_chain(self, testcase_config):
- """Create a connection chain for the test scenario purposes
-
- :param testcase_config: The config input of the test case
- :return: Create the proper chain for the specific test scenario
- """
-
- self.neutron_port = openstack_sfc.get_client_port(self.client_instance,
- self.client_creator)
- odl_utils.create_chain(self.tacker_client, self.default_param_file,
- self.neutron_port, COMMON_CONFIG,
- testcase_config)
-
def check_deletion(self):
"""Check that the deletion of the chain has been completed sucessfully.
diff --git a/sfc/tests/functest/sfc_symmetric_chain.py b/sfc/tests/functest/sfc_symmetric_chain.py
index 1b57a244..4593d8c6 100644
--- a/sfc/tests/functest/sfc_symmetric_chain.py
+++ b/sfc/tests/functest/sfc_symmetric_chain.py
@@ -8,13 +8,10 @@
#
# 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 sfc.lib.config as sfc_config
from sfc.tests.functest import sfc_parent_function
@@ -24,7 +21,6 @@ logger = logging.getLogger(__name__)
COMMON_CONFIG = sfc_config.CommonConfig()
CLIENT = "client"
SERVER = "server"
-openstack_sfc = os_sfc_utils.OpenStackSFC()
class SfcSymmetricChain(sfc_parent_function.SfcCommonTestCase):
@@ -42,54 +38,21 @@ class SfcSymmetricChain(sfc_parent_function.SfcCommonTestCase):
def run(self):
logger.info("The test scenario %s is starting", __name__)
- self.create_custom_vnfd(self.testcase_config.test_vnfd, 'test-vnfd1')
- self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim')
-
- if self.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,
- self.testcase_config.test_vnffgd)
- os_sfc_utils.create_vnffgd(
- self.tacker_client,
- tosca_file=tosca_file,
- vnffgd_name='test-vnffgd')
-
- client_port = openstack_sfc.get_client_port(
- self.client_instance,
- self.client_creator)
- server_port = openstack_sfc.get_client_port(
- self.server_instance,
- self.server_creator)
-
- server_ip_prefix = self.server_ip + '/32'
-
- 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_vnffg_with_param_file(
- self.tacker_client,
- 'test-vnffgd',
- 'test-vnffg',
- default_param_file,
- client_port.id,
- server_port.id,
- server_ip_prefix)
+
+ 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=wait_for_classification_rules,
args=(self.ovs_logger, self.compute_nodes,
- self.server_instance.compute_host,
- server_port,
+ self.odl_ip, self.odl_port,
self.client_instance.compute_host,
- client_port, self.odl_ip,
- self.odl_port,))
-
+ [self.neutron_port],))
try:
t1.start()
except Exception as e:
@@ -98,9 +61,7 @@ class SfcSymmetricChain(sfc_parent_function.SfcCommonTestCase):
logger.info("Assigning floating IPs to instances")
self.assign_floating_ip_client_server()
- vnf_ip = os_sfc_utils.get_vnf_ip(self.tacker_client,
- vnf_id=self.vnf_id)
- self.assign_floating_ip_sfs(vnf_ip)
+ self.assign_floating_ip_sfs()
self.check_floating_ips()
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 b8fc2826..e30967b9 100644
--- a/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py
+++ b/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py
@@ -32,16 +32,16 @@ class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase):
logger.info("The test scenario %s is starting", __name__)
- self.create_custom_vnfd(self.testcase_config.test_vnfd_red,
- 'test-vnfd1')
- self.create_custom_vnfd(self.testcase_config.test_vnfd_blue,
- 'test-vnfd2')
+ self.register_vnf_template(self.testcase_config.test_vnfd_red,
+ 'test-vnfd1')
+ self.register_vnf_template(self.testcase_config.test_vnfd_blue,
+ 'test-vnfd2')
self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim')
self.create_vnf(self.vnfs[1], 'test-vnfd2', 'test-vim')
self.create_vnffg(self.testcase_config.test_vnffgd_red, 'red',
- 'red_http')
+ 'red_http', port=80, protocol='tcp', symmetric=False)
t1 = threading.Thread(target=odl_utils.wait_for_classification_rules,
args=(self.ovs_logger, self.compute_nodes,
diff --git a/sfc/unit_tests/unit/lib/test_cleanup.py b/sfc/unit_tests/unit/lib/test_cleanup.py
index 5ec4261e..b83e229f 100644
--- a/sfc/unit_tests/unit/lib/test_cleanup.py
+++ b/sfc/unit_tests/unit/lib/test_cleanup.py
@@ -262,8 +262,10 @@ class SfcCleanupTesting(unittest.TestCase):
mock_log.assert_has_calls(log_calls)
mock_del_vim.assert_has_calls(del_calls)
+ @patch('sfc.lib.cleanup.logger.info')
@patch('sfc.lib.cleanup.logger.error')
- def test_delete_openstack_objects_exception(self, mock_log):
+ def test_delete_openstack_objects_exception(self, mock_log_err,
+ mock_log_info):
"""
Check the proper functionality of the delete_openstack_objects
@@ -283,11 +285,13 @@ class SfcCleanupTesting(unittest.TestCase):
mock_creator_objs_list = [mock_creator_obj_one, mock_creator_obj_two]
log_calls = [call('Unexpected error cleaning - %s', exception_two),
- call('Unexpected error cleaning - %s', exception_one)]
+ call('Unexpected error cleaning - %s', exception_one),
+ call('Deleting the openstack objects...')]
cleanup.delete_openstack_objects(mock_creator_objs_list)
- mock_log.assert_has_calls(log_calls)
+ mock_log_err.assert_has_calls(log_calls[:2])
+ mock_log_info.assert_has_calls(log_calls[2:])
@patch('sfc.lib.openstack_utils.OpenStackSFC', autospec=True)
def test_delete_untracked_security_groups(self,
@@ -314,53 +318,71 @@ class SfcCleanupTesting(unittest.TestCase):
mock_del_odl_res.assert_has_calls(odl_res_calls)
mock_del_odl_ietf.assert_called_once_with(self.odl_ip, self.odl_port)
+ @patch('sfc.lib.openstack_utils.OpenStackSFC', autospec=True)
+ def test_cleanup_nsfc_objects(self, mock_os_sfc):
+ mock_os_sfc_ins = mock_os_sfc.return_value
+ cleanup.cleanup_nsfc_objects()
+ mock_os_sfc_ins.delete_chain.assert_called_once()
+ mock_os_sfc_ins.delete_port_groups.assert_called_once()
+
@patch('time.sleep')
- @patch('sfc.lib.cleanup.delete_openstack_objects')
- @patch('sfc.lib.cleanup.cleanup_odl')
- def test_cleanup(self,
- mock_cleanup_odl,
- mock_del_os_obj,
- mock_time):
+ def test_cleanup_tacker_objects(self, mock_time):
mock_dict = {'delete_vnffgs': DEFAULT,
'delete_vnffgds': DEFAULT,
'delete_vnfs': DEFAULT,
'delete_vnfds': DEFAULT,
- 'delete_vims': DEFAULT,
- 'delete_untracked_security_groups': DEFAULT}
+ 'delete_vims': DEFAULT}
with patch.multiple('sfc.lib.cleanup',
**mock_dict) as mock_values:
-
- cleanup.cleanup(['creator_one', 'creator_two'],
- self.odl_ip,
- self.odl_port)
+ cleanup.cleanup_tacker_objects()
for key in mock_values:
mock_values[key].assert_called_once()
+
+ mock_time.assert_called_once_with(20)
+
+ @patch('sfc.lib.cleanup.cleanup_tacker_objects')
+ def test_cleanup_mano_objects_tacker(self, mock_cleanup_tacker):
+ cleanup.cleanup_mano_objects('tacker')
+ mock_cleanup_tacker.assert_called_once()
+
+ @patch('sfc.lib.cleanup.cleanup_nsfc_objects')
+ def test_cleanup_mano_objects_nsfc(self, mock_cleanup_nsfc):
+ cleanup.cleanup_mano_objects('no-mano')
+ mock_cleanup_nsfc.assert_called_once()
+
+ @patch('sfc.lib.cleanup.delete_untracked_security_groups')
+ @patch('sfc.lib.cleanup.cleanup_mano_objects')
+ @patch('sfc.lib.cleanup.delete_openstack_objects')
+ @patch('sfc.lib.cleanup.cleanup_odl')
+ def test_cleanup(self,
+ mock_cleanup_odl,
+ mock_del_os_obj,
+ mock_cleanup_mano,
+ mock_untr_sec_grps):
+
+ cleanup.cleanup(['creator_one', 'creator_two'],
+ 'mano',
+ self.odl_ip,
+ self.odl_port)
+
mock_cleanup_odl.assert_called_once_with(self.odl_ip,
self.odl_port)
mock_del_os_obj.assert_called_once_with(['creator_one', 'creator_two'])
- mock_time.assert_called_once_with(20)
+ mock_cleanup_mano.assert_called_once_with('mano')
+ mock_untr_sec_grps.assert_called_once()
- @patch('time.sleep')
+ @patch('sfc.lib.cleanup.cleanup_mano_objects')
@patch('sfc.lib.cleanup.cleanup_odl')
def test_cleanup_from_bash(self,
mock_cleanup_odl,
- mock_time):
-
- mock_dict = {'delete_vnffgs': DEFAULT,
- 'delete_vnffgds': DEFAULT,
- 'delete_vnfs': DEFAULT,
- 'delete_vnfds': DEFAULT,
- 'delete_vims': DEFAULT}
- with patch.multiple('sfc.lib.cleanup',
- **mock_dict) as mock_values:
+ mock_cleanup_mano):
- cleanup.cleanup_from_bash(self.odl_ip,
- self.odl_port)
+ cleanup.cleanup_from_bash(self.odl_ip,
+ self.odl_port,
+ 'mano')
- for key in mock_values:
- mock_values[key].assert_called_once()
mock_cleanup_odl.assert_called_once_with(self.odl_ip,
self.odl_port)
- mock_time.assert_called_once_with(20)
+ mock_cleanup_mano.assert_called_once_with(mano='mano')
diff --git a/sfc/unit_tests/unit/lib/test_odl_utils.py b/sfc/unit_tests/unit/lib/test_odl_utils.py
index d151a1ca..17ad88f5 100644
--- a/sfc/unit_tests/unit/lib/test_odl_utils.py
+++ b/sfc/unit_tests/unit/lib/test_odl_utils.py
@@ -733,43 +733,3 @@ class SfcOdlUtilsTesting(unittest.TestCase):
'compute_nodes')
assert mock_sleep.call_count == 2
mock_log.assert_not_called()
-
- @patch('os.path.join', autospec=True)
- @patch('sfc.lib.odl_utils.os_sfc_utils.create_vnffg_with_param_file',
- autospec=True)
- @patch('sfc.lib.odl_utils.os_sfc_utils.create_vnffgd', autospec=True)
- def test_create_chain(self, mock_create_vnffgd,
- mock_create_vnffg_with_param_file,
- mock_join):
- """
- Checks the proper functionality of create_chain
- function
- """
-
- mock_join.return_value = '/tosca_file'
- mock_neutron = Mock()
- mock_common_config = Mock()
- mock_testcase_config = Mock()
- mock_common_config.vnffgd_dir = 'mock_vnffgd_dir'
- mock_common_config.sfc_test_dir = 'mock_sfc_test_dir'
- mock_testcase_config.test_vnffgd_red = 'mock_test_vnffgd_red'
- mock_neutron.id = 'mock_id'
-
- odl_utils.create_chain('tacker_client',
- 'default_param_file',
- mock_neutron,
- mock_common_config,
- mock_testcase_config)
-
- mock_join.assert_called_once_with('mock_sfc_test_dir',
- 'mock_vnffgd_dir',
- 'mock_test_vnffgd_red')
- mock_create_vnffgd.assert_called_once_with('tacker_client',
- tosca_file='/tosca_file',
- vnffgd_name='red')
- mock_create_vnffg_with_param_file.assert_called_once_with(
- 'tacker_client',
- 'red',
- 'red_http',
- 'default_param_file',
- 'mock_id')
diff --git a/sfc/unit_tests/unit/lib/test_openstack_utils.py b/sfc/unit_tests/unit/lib/test_openstack_utils.py
index bc08a184..595f09b5 100644
--- a/sfc/unit_tests/unit/lib/test_openstack_utils.py
+++ b/sfc/unit_tests/unit/lib/test_openstack_utils.py
@@ -265,7 +265,8 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
"""
vm_con_ins = mock_vm_instance_config.return_value
- pc_ins = mock_port_config.return_value
+ pc_inss = ['pc_config1', 'pc_config2']
+ mock_port_config.side_effect = pc_inss
os_vm_ins = mock_os_vm_instance.return_value
os_vm_ins_cre = os_vm_ins.create.return_value
expected = (os_vm_ins_cre, os_vm_ins)
@@ -277,19 +278,21 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
img_cre.image_settings = 'image_settings'
log_calls = [call('Creating the instance vm_name...')]
-
+ pc_calls = [call(name='port1', network_name='nw_name'),
+ call(name='port2', network_name='nw_name')]
result = self.os_sfc.create_instance('vm_name',
'flavor_name',
img_cre,
network,
secgrp,
- 'av_zone')
+ 'av_zone',
+ ['port1', 'port2'])
self.assertEqual(expected, result)
mock_vm_instance_config.assert_called_once_with(name='vm_name',
flavor='flavor_name',
security_group_names=''
'sec_grp',
- port_settings=[pc_ins],
+ port_settings=pc_inss,
availability_zone='av'
'_zone')
mock_os_vm_instance.assert_called_once_with(self.os_creds,
@@ -297,6 +300,7 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
'image_settings')
self.assertEqual([os_vm_ins], self.os_sfc.creators)
mock_log.info.assert_has_calls(log_calls)
+ mock_port_config.assert_has_calls(pc_calls)
@patch('sfc.lib.openstack_utils.nova_utils.get_hypervisor_hosts',
autospec=True)
@@ -510,9 +514,9 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
@patch('sfc.lib.openstack_utils.logger', autospec=True)
@patch('sfc.lib.openstack_utils.cr_inst.OpenStackVmInstance',
autospec=True)
- def test_get_client_port_raised_exceptioin(self,
- mock_os_vm,
- mock_log):
+ def test_get_instance_port_raised_exceptioin(self,
+ mock_os_vm,
+ mock_log):
"""
Checks the proper functionality of get_client_port
function when no port is returned
@@ -527,7 +531,7 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
" with name mock_vm_name-port")]
with self.assertRaises(Exception) as cm:
- self.os_sfc.get_client_port(mock_vm, mock_os_vm_ins)
+ self.os_sfc.get_instance_port(mock_vm, mock_os_vm_ins)
self.assertEqual(cm.exception.message, ErrorMSG)
mock_log.error.assert_has_calls(log_calls)
@@ -535,9 +539,9 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
@patch('sfc.lib.openstack_utils.logger', autospec=True)
@patch('sfc.lib.openstack_utils.cr_inst.OpenStackVmInstance',
autospec=True)
- def test_get_client_port(self,
- mock_os_vm,
- mock_log):
+ def test_get_instance_port(self,
+ mock_os_vm,
+ mock_log):
"""
Checks the proper functionality of get_client_port
function when no port is returned
@@ -547,7 +551,7 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
mock_vm = Mock()
mock_vm.name = 'mock_vm_name'
mock_os_vm_ins.get_port_by_name.return_value = 'mock_port'
- result = self.os_sfc.get_client_port(mock_vm, mock_os_vm_ins)
+ result = self.os_sfc.get_instance_port(mock_vm, mock_os_vm_ins)
self.assertEqual('mock_port', result)
@patch('sfc.lib.openstack_utils.neutron_utils.list_security_groups',
@@ -569,9 +573,243 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
mock_list_security_groups.assert_called_once_with(self.neutron)
mock_delete_security_group.assert_has_calls(del_calls)
+ @patch('snaps.openstack.create_instance.OpenStackVmInstance',
+ autospec=True)
+ def test_wait_for_vnf(self, mock_osvminstance):
+ """
+ Checks the method wait_for_vnf
+ """
-class SfcTackerSectionTesting(unittest.TestCase):
+ mock_osvm_ins = mock_osvminstance.return_value
+ mock_osvm_ins.vm_active.return_value = True
+ result = self.os_sfc.wait_for_vnf(mock_osvm_ins)
+ self.assertTrue(result)
+
+ @patch('snaps.domain.vm_inst.VmInst', autospec=True)
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_port_groups_raises_exception(self, mock_log, mock_vm):
+ """
+ Checks the create_port_groups when length of ports is greater than 2
+ """
+ mock_vm_ins = mock_vm.return_value
+ mock_vm_ins.name = 'vm'
+ log_calls_info = [call('Creating the port pairs...')]
+ log_calls_err = [call('Only SFs with one or two ports are supported')]
+ exception_message = "Failed to create port pairs"
+ vnf_ports = ['p1', 'p2', 'p3']
+ with self.assertRaises(Exception) as cm:
+ self.os_sfc.create_port_groups(vnf_ports, mock_vm_ins)
+ self.assertEqual(exception_message, cm.exception.message)
+ mock_log.info.assert_has_calls(log_calls_info)
+ mock_log.error.assert_has_calls(log_calls_err)
+
+ @patch('snaps.domain.network.Port', autospec=True)
+ @patch('snaps.domain.vm_inst.VmInst', autospec=True)
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_port_groups_returns_none_from_pp(self, mock_log,
+ mock_vm,
+ mock_port):
+ """
+ Checks the create_port_groups when something goes wrong in port pair
+ creation
+ """
+ mock_vm_ins = mock_vm.return_value
+ mock_vm_ins.name = 'vm'
+ log_calls_info = [call('Creating the port pairs...')]
+ log_calls_warn = [call('Chain creation failed due to port pair '
+ 'creation failed for vnf %(vnf)s', {'vnf': 'vm'})]
+ mock_port_ins = mock_port.return_value
+ mock_port_ins2 = mock_port.return_value
+ mock_port_ins.id = '123abc'
+ mock_port_ins2.id = '456def'
+ self.neutron.create_sfc_port_pair.return_value = None
+ result = self.os_sfc.create_port_groups(
+ [mock_port_ins, mock_port_ins2], mock_vm_ins)
+ self.assertIsNone(result)
+ mock_log.info.assert_has_calls(log_calls_info)
+ mock_log.warning.assert_has_calls(log_calls_warn)
+
+ @patch('snaps.domain.network.Port', autospec=True)
+ @patch('snaps.domain.vm_inst.VmInst', autospec=True)
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_port_groups_returns_none_from_ppg(self, mock_log,
+ mock_vm,
+ mock_port):
+ """
+ Checks the create_port_groups when something goes wrong in port pair
+ group creation
+ """
+ mock_vm_ins = mock_vm.return_value
+ mock_vm_ins.name = 'vm'
+ log_calls_info = [call('Creating the port pairs...'),
+ call('Creating the port pair groups...')]
+ log_calls_warn = [call('Chain creation failed due to port pair group '
+ 'creation failed for vnf %(vnf)', 'vm')]
+ mock_port_ins = mock_port.return_value
+ mock_port_ins.id = '123abc'
+ self.neutron.create_sfc_port_pair.return_value = \
+ {'port_pair': {'id': 'pp_id'}}
+ self.neutron.create_sfc_port_pair_group.return_value = None
+ result = self.os_sfc.create_port_groups([mock_port_ins], mock_vm_ins)
+ self.assertIsNone(result)
+ mock_log.info.assert_has_calls(log_calls_info)
+ mock_log.warning.assert_has_calls(log_calls_warn)
+
+ @patch('snaps.domain.network.Port', autospec=True)
+ @patch('snaps.domain.vm_inst.VmInst', autospec=True)
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_port_groups_returns_id(self, mock_log, mock_osvm,
+ mock_port):
+ """
+ Checks the create_port_groups when everything goes as expected
+ """
+
+ log_calls_info = [call('Creating the port pairs...'),
+ call('Creating the port pair groups...')]
+ mock_port_ins = mock_port.return_value
+ mock_port_ins.id = '123abc'
+ mock_osvm_ins = mock_osvm.return_value
+ mock_osvm_ins.name = 'vm'
+ expected_port_pair = {'name': 'vm-connection-points',
+ 'description': 'port pair for vm',
+ 'ingress': '123abc',
+ 'egress': '123abc'}
+ self.neutron.create_sfc_port_pair.return_value = \
+ {'port_pair': {'id': 'pp_id'}}
+ self.neutron.create_sfc_port_pair_group.return_value = \
+ {'port_pair_group': {'id': 'pp_id'}}
+ expected_port_pair_gr = {'name': 'vm-port-pair-group',
+ 'description': 'port pair group for vm',
+ 'port_pairs': ['pp_id']}
+
+ self.os_sfc.create_port_groups([mock_port_ins], mock_osvm_ins)
+ self.neutron.create_sfc_port_pair.assert_has_calls(
+ [call({'port_pair': expected_port_pair})])
+ self.neutron.create_sfc_port_pair_group.assert_has_calls(
+ [call({'port_pair_group': expected_port_pair_gr})])
+ mock_log.info.assert_has_calls(log_calls_info)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_chain(self, mock_log):
+ """
+ Checks the create_chain method
+ """
+
+ log_calls = [call('Creating the classifier...'),
+ call('Creating the chain...')]
+ port_groups = ['1a', '2b']
+ neutron_port = 'neutron_port_id'
+ port = 80
+ protocol = 'tcp'
+ vnffg_name = 'red_http'
+ symmetrical = False
+ self.neutron.create_sfc_flow_classifier.return_value = \
+ {'flow_classifier': {'id': 'fc_id'}}
+ self.neutron.create_sfc_port_chain.return_value = \
+ {'port_chain': {'id': 'pc_id'}}
+
+ expected_sfc_classifier_params = {'name': vnffg_name + '-classifier',
+ 'logical_source_port': neutron_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'protocol': protocol}
+ expected_chain_config = {'name': vnffg_name + '-port-chain',
+ 'description': 'port-chain for SFC',
+ 'port_pair_groups': port_groups,
+ 'flow_classifiers': ['fc_id']}
+
+ self.os_sfc.create_chain(port_groups, neutron_port, port,
+ protocol, vnffg_name, symmetrical)
+
+ self.neutron.create_sfc_flow_classifier.assert_has_calls(
+ [call({'flow_classifier': expected_sfc_classifier_params})])
+ self.neutron.create_sfc_port_chain.assert_has_calls(
+ [call({'port_chain': expected_chain_config})])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_chain_symmetric(self, mock_log):
+ """
+ Checks the create_chain method
+ """
+
+ log_calls = [call('Creating the classifier...'),
+ call('Creating the chain...')]
+ port_groups = ['1a', '2b']
+ neutron_port = 'neutron_port_id'
+ port = 80
+ protocol = 'tcp'
+ vnffg_name = 'red_http'
+ symmetrical = True
+ serv_p = '123abc'
+ server_ip = '1.1.1.2'
+ self.neutron.create_sfc_flow_classifier.return_value = \
+ {'flow_classifier': {'id': 'fc_id'}}
+ self.neutron.create_sfc_port_chain.return_value = \
+ {'port_chain': {'id': 'pc_id'}}
+
+ expected_sfc_classifier_params = {'name': vnffg_name + '-classifier',
+ 'logical_source_port': neutron_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'destination_ip_prefix': server_ip,
+ 'logical_destination_port': serv_p,
+ 'protocol': protocol}
+ expected_chain_config = {'name': vnffg_name + '-port-chain',
+ 'description': 'port-chain for SFC',
+ 'port_pair_groups': port_groups,
+ 'flow_classifiers': ['fc_id'],
+ 'chain_parameters': {'symmetric': True}}
+
+ self.os_sfc.create_chain(port_groups, neutron_port, port,
+ protocol, vnffg_name, symmetrical,
+ server_port=serv_p, server_ip=server_ip)
+
+ self.neutron.create_sfc_flow_classifier.assert_has_calls(
+ [call({'flow_classifier': expected_sfc_classifier_params})])
+ self.neutron.create_sfc_port_chain.assert_has_calls(
+ [call({'port_chain': expected_chain_config})])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_delete_port_groups(self, mock_log):
+ """
+ Checks the delete_port_groups method
+ """
+ log_calls = [call('Deleting the port groups...'),
+ call('Deleting the port pairs...')]
+ self.neutron.list_sfc_port_pair_groups.return_value = \
+ {'port_pair_groups': [{'id': 'id_ppg1'}, {'id': 'id_ppg2'}]}
+ self.neutron.list_sfc_port_pairs.return_value = \
+ {'port_pairs': [{'id': 'id_pp1'}, {'id': 'id_pp2'}]}
+ self.os_sfc.delete_port_groups()
+
+ self.neutron.delete_sfc_port_pair_group.assert_has_calls(
+ [call('id_ppg1'), call('id_ppg2')])
+ self.neutron.delete_sfc_port_pair.assert_has_calls(
+ [call('id_pp1'), call('id_pp2')])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_delete_chain(self, mock_log):
+ """
+ Checks the delete_chain method
+ """
+ log_calls = [call('Deleting the chain...'),
+ call('Deleting the classifiers...')]
+ self.neutron.list_sfc_port_chains.return_value = \
+ {'port_chains': [{'id': 'id_pc1'}]}
+ self.neutron.list_sfc_flow_classifiers.return_value = \
+ {'flow_classifiers': [{'id': 'id_fc1'}]}
+ self.os_sfc.delete_chain()
+ self.neutron.delete_sfc_port_chain.assert_has_calls([call('id_pc1')])
+ self.neutron.delete_sfc_flow_classifier.assert_has_calls(
+ [call('id_fc1')])
+ mock_log.info.assert_has_calls(log_calls)
+
+
+class SfcTackerSectionTesting(unittest.TestCase):
def setUp(self):
self.patcher = patch.object(tacker_client, 'Client', autospec=True)
self.mock_tacker_client = self.patcher.start().return_value