aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sfc/lib/cleanup.py6
-rw-r--r--sfc/lib/odl_utils.py31
-rw-r--r--sfc/lib/openstack_utils.py57
-rw-r--r--sfc/tests/functest/config.yaml6
-rw-r--r--sfc/tests/functest/sfc_parent_function.py124
-rw-r--r--sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py24
-rw-r--r--sfc/unit_tests/unit/lib/test_cleanup.py5
-rw-r--r--sfc/unit_tests/unit/lib/test_odl_utils.py26
-rw-r--r--sfc/unit_tests/unit/lib/test_openstack_utils.py91
9 files changed, 335 insertions, 35 deletions
diff --git a/sfc/lib/cleanup.py b/sfc/lib/cleanup.py
index 7ac7903a..214ff1cb 100644
--- a/sfc/lib/cleanup.py
+++ b/sfc/lib/cleanup.py
@@ -83,9 +83,9 @@ def delete_untracked_security_groups():
def cleanup_odl(odl_ip, odl_port):
delete_odl_resources(odl_ip, odl_port, 'service-function-forwarder')
- delete_odl_resources(odl_ip, odl_port, 'service-function-chain')
- delete_odl_resources(odl_ip, odl_port, 'service-function-path')
- delete_odl_resources(odl_ip, odl_port, 'service-function')
+ # delete_odl_resources(odl_ip, odl_port, 'service-function-chain')
+ # delete_odl_resources(odl_ip, odl_port, 'service-function-path')
+ # delete_odl_resources(odl_ip, odl_port, 'service-function')
delete_odl_ietf_access_lists(odl_ip, odl_port)
diff --git a/sfc/lib/odl_utils.py b/sfc/lib/odl_utils.py
index 031aaa5f..459c83ec 100644
--- a/sfc/lib/odl_utils.py
+++ b/sfc/lib/odl_utils.py
@@ -10,7 +10,8 @@ import time
import sfc.lib.openstack_utils as os_sfc_utils
logger = logging.getLogger(__name__)
-
+odl_username = 'admin'
+odl_password = 'admin'
ODL_MODULE_EXCEPTIONS = {
"service-function-path-state": "service-function-path"
@@ -201,6 +202,11 @@ def wait_for_classification_rules(ovs_logger, compute_nodes, odl_ip, odl_port,
time.sleep(3)
while timeout > 0:
+ # When swapping classifiers promised_rsps update takes time to
+ # get updated
+ # TODO: Need to optimise this code
+ promised_rsps = promised_rsps_in_compute(odl_ip, odl_port,
+ neutron_ports)
logger.info("RSPs in ODL Operational DataStore"
"for compute '{}':".format(compute_name))
logger.info("{0}".format(promised_rsps))
@@ -246,6 +252,17 @@ def get_odl_ip_port(nodes):
return ip, port
+def get_odl_username_password():
+ local_ml2_conf_file = os.path.join(os.getcwd(), 'ml2_conf.ini')
+ con_par = ConfigParser.RawConfigParser()
+ con_par.read(local_ml2_conf_file)
+ global odl_username
+ odl_username = con_par.get('ml2_odl', 'username')
+ global odl_password
+ odl_password = con_par.get('ml2_odl', 'password')
+ return odl_username, odl_password
+
+
def pluralize(resource):
plural = ODL_PLURAL_EXCEPTIONS.get(resource, None)
if not plural:
@@ -261,11 +278,11 @@ def get_module(resource):
def format_odl_resource_list_url(odl_ip, odl_port, resource,
- datastore='config', odl_user='admin',
- odl_pwd='admin'):
+ datastore='config', odl_user=odl_username,
+ odl_pwd=odl_password):
return ('http://{usr}:{pwd}@{ip}:{port}/restconf/{ds}/{rsrc}:{rsrcs}'
- .format(usr=odl_user, pwd=odl_pwd, ip=odl_ip, port=odl_port,
- ds=datastore, rsrc=get_module(resource),
+ .format(usr=odl_username, pwd=odl_password, ip=odl_ip,
+ port=odl_port, ds=datastore, rsrc=get_module(resource),
rsrcs=pluralize(resource)))
@@ -315,10 +332,10 @@ def odl_acl_types_names(acl_json):
def format_odl_acl_list_url(odl_ip, odl_port,
- odl_user='admin', odl_pwd='admin'):
+ odl_user=odl_username, odl_pwd=odl_password):
acl_list_url = ('http://{usr}:{pwd}@{ip}:{port}/restconf/config/'
'ietf-access-control-list:access-lists'
- .format(usr=odl_user, pwd=odl_pwd,
+ .format(usr=odl_username, pwd=odl_password,
ip=odl_ip, port=odl_port))
return acl_list_url
diff --git a/sfc/lib/openstack_utils.py b/sfc/lib/openstack_utils.py
index 3d620e2b..8bc4543a 100644
--- a/sfc/lib/openstack_utils.py
+++ b/sfc/lib/openstack_utils.py
@@ -400,6 +400,31 @@ class OpenStackSFC:
return port_pair_group_info['port_pair_group']['id']
+ def create_classifier(self, neutron_port, port, protocol, fc_name,
+ symmetrical, server_port=None, server_ip=None):
+ '''
+ Create the classifier
+ '''
+ logger.info("Creating the classifier...")
+
+ if symmetrical:
+ sfc_classifier_params = {'name': fc_name,
+ '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': fc_name,
+ 'logical_source_port': neutron_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'protocol': protocol}
+
+ fc_config = {'flow_classifier': sfc_classifier_params}
+ self.neutron_client.create_sfc_flow_classifier(fc_config)
+
def create_chain(self, port_groups, neutron_port, port, protocol,
vnffg_name, symmetrical, server_port=None,
server_ip=None):
@@ -440,6 +465,38 @@ class OpenStackSFC:
chain_config = {'port_chain': port_chain}
return self.neutron_client.create_sfc_port_chain(chain_config)
+ def update_chain(self, vnffg_name, fc_name, symmetrical):
+ '''
+ Update the new Flow Classifier ID
+ '''
+ fc_id = self.neutron_client.find_resource('flow_classifier',
+ fc_name)['id']
+ logger.info("Update the chain...")
+ port_chain = {}
+ port_chain['name'] = vnffg_name + '-port-chain'
+ port_chain['flow_classifiers'] = []
+ port_chain['flow_classifiers'].append(fc_id)
+ if symmetrical:
+ port_chain['chain_parameters'] = {}
+ port_chain['chain_parameters']['symmetric'] = True
+ chain_config = {'port_chain': port_chain}
+ pc_id = self.neutron_client.find_resource('port_chain',
+ port_chain['name'])['id']
+ return self.neutron_client.update_sfc_port_chain(pc_id, chain_config)
+
+ def swap_classifiers(self, vnffg_1_name, vnffg_2_name, symmetric=False):
+
+ '''
+ Swap Classifiers
+ '''
+ logger.info("Swap classifiers...")
+
+ self.update_chain(vnffg_1_name, 'dummy', symmetric)
+ vnffg_1_classifier_name = vnffg_1_name + '-classifier'
+ self.update_chain(vnffg_2_name, vnffg_1_classifier_name, symmetric)
+ vnffg_2_classifier_name = vnffg_2_name + '-classifier'
+ self.update_chain(vnffg_1_name, vnffg_2_classifier_name, symmetric)
+
def delete_port_groups(self):
'''
Delete all port groups and port pairs
diff --git a/sfc/tests/functest/config.yaml b/sfc/tests/functest/config.yaml
index d595f0cf..021b4c39 100644
--- a/sfc/tests/functest/config.yaml
+++ b/sfc/tests/functest/config.yaml
@@ -60,7 +60,7 @@ testcases:
sfc_two_chains_SSH_and_HTTP:
class_name: "SfcTwoChainsSSHandHTTP"
- enabled: false
+ enabled: true
order: 1
description: "ODL-SFC tests with two chains and one SF per chain"
net_name: example-net
@@ -84,7 +84,7 @@ testcases:
sfc_symmetric_chain:
class_name: "SfcSymmetricChain"
- enabled: false
+ enabled: true
order: 2
description: "Verify the behavior of a symmetric service chain"
net_name: example-net
@@ -106,7 +106,7 @@ testcases:
sfc_chain_deletion:
class_name: "SfcChainDeletion"
- enabled: false
+ enabled: true
order: 3
description: "Verify if chains work correctly after deleting one"
net_name: example-net
diff --git a/sfc/tests/functest/sfc_parent_function.py b/sfc/tests/functest/sfc_parent_function.py
index 9558eb8c..40d5d1a1 100644
--- a/sfc/tests/functest/sfc_parent_function.py
+++ b/sfc/tests/functest/sfc_parent_function.py
@@ -154,6 +154,7 @@ class SfcCommonTestCase(object):
self.creators = openstack_sfc.creators
self.odl_ip, self.odl_port = odl_utils.get_odl_ip_port(openstack_nodes)
+ odl_utils.get_odl_username_password()
self.default_param_file = os.path.join(
COMMON_CONFIG.sfc_test_dir,
@@ -267,6 +268,9 @@ class SfcCommonTestCase(object):
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
@@ -403,14 +407,43 @@ class SfcCommonTestCase(object):
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):
+ 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
"""
@@ -448,9 +481,29 @@ class SfcCommonTestCase(object):
self.neutron_port.id)
elif COMMON_CONFIG.mano_component == 'no-mano':
+ logger.info("Creating the vnffg without any mano component...")
port_groups = []
- for vnf in self.vnfs:
- # vnf_instance is in [0] and vnf_port in [1]
+ 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:
@@ -462,10 +515,9 @@ class SfcCommonTestCase(object):
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)
+ port_group = openstack_sfc.create_port_groups(
+ neutron_ports, vnf_instance)
+ port_groups.append(port_group)
self.neutron_port = self.port_client
@@ -486,6 +538,64 @@ class SfcCommonTestCase(object):
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.
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 0cfbea22..92c2711e 100644
--- a/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py
+++ b/sfc/tests/functest/sfc_two_chains_SSH_and_HTTP.py
@@ -40,8 +40,15 @@ class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase):
self.create_vnf(self.vnfs[0], 'test-vnfd1', 'test-vim')
self.create_vnf(self.vnfs[1], 'test-vnfd2', 'test-vim')
+ 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)
+ 'red_http', port=80, protocol='tcp',
+ symmetric=False, vnf_index=0)
+
+ 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')
t1 = threading.Thread(target=odl_utils.wait_for_classification_rules,
args=(self.ovs_logger, self.compute_nodes,
@@ -60,21 +67,18 @@ class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase):
self.check_floating_ips()
self.start_services_in_vm()
- self.vxlan_blocking_start(self.fips_sfs[0], "22")
- self.vxlan_blocking_start(self.fips_sfs[1], "80")
+ self.vxlan_blocking_start(self.fips_sfs[0], "80")
+ self.vxlan_blocking_start(self.fips_sfs[1], "22")
logger.info("Wait for ODL to update the classification rules in OVS")
t1.join()
results = self.present_results_ssh()
- results = self.present_results_allowed_http()
+ results = self.present_results_http()
logger.info("Changing the classification")
- self.remove_vnffg('red_http', 'red')
-
- self.create_vnffg(self.testcase_config.test_vnffgd_blue, 'blue',
- 'blue_ssh')
+ self.swap_classifiers('red_http', 'blue_ssh')
# Start measuring the time it takes to implement the classification
# rules
@@ -82,7 +86,7 @@ class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase):
args=(self.ovs_logger, self.compute_nodes,
self.odl_ip, self.odl_port,
self.client_instance.hypervisor_hostname,
- self.neutron_port,))
+ [self.neutron_port],))
try:
t2.start()
except Exception as e:
@@ -91,7 +95,7 @@ class SfcTwoChainsSSHandHTTP(sfc_parent_function.SfcCommonTestCase):
logger.info("Wait for ODL to update the classification rules in OVS")
t2.join()
- results = self.present_results_http()
+ results = self.present_results_allowed_http()
results = self.present_results_allowed_ssh()
if __name__ == '__main__':
diff --git a/sfc/unit_tests/unit/lib/test_cleanup.py b/sfc/unit_tests/unit/lib/test_cleanup.py
index 8e68ce5b..e6f59d23 100644
--- a/sfc/unit_tests/unit/lib/test_cleanup.py
+++ b/sfc/unit_tests/unit/lib/test_cleanup.py
@@ -275,10 +275,7 @@ class SfcCleanupTesting(unittest.TestCase):
def test_cleanup_odl(self,
mock_del_odl_ietf,
mock_del_odl_res):
- resources = ['service-function-forwarder',
- 'service-function-chain',
- 'service-function-path',
- 'service-function']
+ resources = ['service-function-forwarder']
odl_res_calls = [call(self.odl_ip, self.odl_port, item)
for item in resources]
diff --git a/sfc/unit_tests/unit/lib/test_odl_utils.py b/sfc/unit_tests/unit/lib/test_odl_utils.py
index 04eeeff2..1dfcf1ed 100644
--- a/sfc/unit_tests/unit/lib/test_odl_utils.py
+++ b/sfc/unit_tests/unit/lib/test_odl_utils.py
@@ -331,11 +331,35 @@ class SfcOdlUtilsTesting(unittest.TestCase):
'/etc/ml2_conf.ini')
mock_rawconfigparser.return_value.read.assert_called_once_with(
'/etc/ml2_conf.ini')
- mock_rawconfigparser.return_value.get.assert_called_once_with(
+ mock_rawconfigparser.return_value.get.assert_called_with(
'ml2_odl', 'url')
mock_search.assert_called_once_with(r'[0-9]+(?:\.[0-9]+){3}\:[0-9]+',
'config')
+ @patch('re.search', autospec=True)
+ @patch('ConfigParser.RawConfigParser', autospec=True)
+ @patch('os.getcwd', autospec=True, return_value='/etc')
+ @patch('os.path.join', autospec=True, return_value='/etc/ml2_conf.ini')
+ def test_get_odl_username_password(self, mock_join,
+ mock_getcwd,
+ mock_rawconfigparser,
+ mock_search):
+ """
+ Check the proper functionality of get odl_username_password
+ function
+ """
+
+ mock_rawconfigparser.return_value.get.return_value = 'odl_username'
+ result = odl_utils.get_odl_username_password()
+ self.assertEqual(('odl_username'), result[0])
+ mock_getcwd.assert_called_once_with()
+ mock_join.assert_called_once_with('/etc', 'ml2_conf.ini')
+ mock_rawconfigparser.return_value.read.assert_called_once_with(
+ '/etc/ml2_conf.ini')
+ mock_rawconfigparser.return_value.get.return_value = 'odl_password'
+ result = odl_utils.get_odl_username_password()
+ self.assertEqual(('odl_password'), result[1])
+
def test_pluralize(self):
"""
Checks the proper functionality of pluralize
diff --git a/sfc/unit_tests/unit/lib/test_openstack_utils.py b/sfc/unit_tests/unit/lib/test_openstack_utils.py
index ffaace68..8915c45d 100644
--- a/sfc/unit_tests/unit/lib/test_openstack_utils.py
+++ b/sfc/unit_tests/unit/lib/test_openstack_utils.py
@@ -1034,6 +1034,64 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
mock_log.info.assert_has_calls(log_calls_info)
@patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_classifier(self, mock_log):
+ """
+ Checks the create_classifier method
+ """
+
+ log_calls = [call('Creating the classifier...')]
+ neutron_port = 'neutron_port_id'
+ port = 80
+ protocol = 'tcp'
+ fc_name = 'red_http'
+ symmetrical = False
+ self.neutron_client.create_sfc_flow_classifier.return_value = \
+ {'flow_classifier': {'id': 'fc_id'}}
+
+ expected_sfc_classifier_params = {'name': fc_name,
+ 'logical_source_port': neutron_port,
+ 'destination_port_range_min': port,
+ 'destination_port_range_max': port,
+ 'protocol': protocol}
+ self.os_sfc.create_classifier(neutron_port, port,
+ protocol, fc_name, symmetrical)
+ self.neutron_client.create_sfc_flow_classifier.assert_has_calls(
+ [call({'flow_classifier': expected_sfc_classifier_params})])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_create_classifier_symmetric(self, mock_log):
+ """
+ Checks the create_chain method
+ """
+
+ log_calls = [call('Creating the classifier...')]
+ neutron_port = 'neutron_port_id'
+ port = 80
+ protocol = 'tcp'
+ fc_name = 'red_http'
+ symmetrical = True
+ serv_p = '123'
+ server_ip = '1.1.1.2'
+ self.neutron_client.create_sfc_flow_classifier.return_value = \
+ {'flow_classifier': {'id': 'fc_id'}}
+
+ expected_sfc_classifier_params = {'name': fc_name,
+ '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}
+ self.os_sfc.create_classifier(neutron_port, port,
+ protocol, fc_name, symmetrical,
+ server_port='123',
+ server_ip='1.1.1.2')
+ self.neutron_client.create_sfc_flow_classifier.assert_has_calls(
+ [call({'flow_classifier': expected_sfc_classifier_params})])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
def test_create_chain(self, mock_log):
"""
Checks the create_chain method
@@ -1116,6 +1174,39 @@ class SfcOpenStackUtilsTesting(unittest.TestCase):
mock_log.info.assert_has_calls(log_calls)
@patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_update_chain_symmetric(self, mock_log):
+ """
+ Checks the update_chain method
+ """
+
+ log_calls = [call('Update the chain...')]
+ vnffg_name = 'red_http'
+ fc_name = 'blue_ssh'
+ symmetrical = True
+ self.neutron_client.find_resource.return_value = \
+ {'id': 'fc_id'}
+ expected_chain_config = {'name': vnffg_name + '-port-chain',
+ 'flow_classifiers': ['fc_id'],
+ 'chain_parameters': {'symmetric': True}}
+ self.os_sfc.update_chain(vnffg_name, fc_name, symmetrical)
+ self.neutron_client.update_sfc_port_chain.assert_has_calls(
+ [call('fc_id', {'port_chain': expected_chain_config})])
+ mock_log.info.assert_has_calls(log_calls)
+
+ @patch('sfc.lib.openstack_utils.logger', autospec=True)
+ def test_swap_classifiers(self, mock_log):
+ """
+ Checks the swap_classifiers method
+ """
+
+ log_calls = [call('Swap classifiers...')]
+ vnffg_1_name = 'red_http'
+ vnffg_2_name = 'blue_ssh'
+ symmetrical = False
+ self.os_sfc.swap_classifiers(vnffg_1_name, vnffg_2_name, symmetrical)
+ 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