Make sure flow classifier removal doesn't effect other chains
Some flow classifiers can share the same provider/consumer network. When removed from a chain, we need to make sure we don't unset the corresponding contract for other chains sharing the same provider. Change-Id: I196850de422b1ba6da9598c81f2e7e5f24b643a0
This commit is contained in:
parent
96bcf44602
commit
8a7375f10b
gbpservice/neutron
@ -619,30 +619,31 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
||||
aim_ctx = aim_context.AimContext(plugin_context.session)
|
||||
l3out = self.aim_mech._get_svi_net_l3out(net)
|
||||
cidr = netaddr.IPNetwork(cidr)
|
||||
epg = None
|
||||
ext_net = None
|
||||
if l3out:
|
||||
if cidr.prefixlen != 0:
|
||||
ext_net = aim_resource.ExternalNetwork(
|
||||
tenant_name=l3out.tenant_name, l3out_name=l3out.name,
|
||||
name=flc_aid, display_name=flc_aname)
|
||||
self.aim.delete(aim_ctx, ext_net, cascade=True)
|
||||
else:
|
||||
ext_net = self.aim_mech._get_svi_default_external_epg(net)
|
||||
epg = self.aim.get(aim_ctx, ext_net)
|
||||
else:
|
||||
epg = self.aim.get(
|
||||
aim_ctx, self.aim_mech._get_svi_default_external_epg(net))
|
||||
else:
|
||||
epg = self.aim.get(aim_ctx, self.aim_mech._get_epg_by_network_id(
|
||||
plugin_context.session, net['id']))
|
||||
if epg:
|
||||
contract = self._get_flc_contract(plugin_context.session, flowc,
|
||||
tenant)
|
||||
try:
|
||||
if prefix == FLOWC_SRC:
|
||||
epg.consumed_contract_names.remove(contract.name)
|
||||
else:
|
||||
epg.provided_contract_names.remove(contract.name)
|
||||
self.aim.create(aim_ctx, epg, overwrite=True)
|
||||
except ValueError:
|
||||
pass
|
||||
if prefix == FLOWC_SRC:
|
||||
epg.consumed_contract_names.remove(contract.name)
|
||||
else:
|
||||
epg.provided_contract_names.remove(contract.name)
|
||||
self.aim.create(aim_ctx, epg, overwrite=True)
|
||||
if (ext_net and not epg.consumed_contract_names and not
|
||||
epg.provided_contract_names):
|
||||
# Only remove external network if completely empty
|
||||
self.aim.delete(aim_ctx, ext_net, cascade=True)
|
||||
|
||||
def _get_chains_by_classifier_id(self, plugin_context, flowc_id):
|
||||
context = plugin_context
|
||||
|
@ -305,7 +305,7 @@ class TestAIMServiceFunctionChainingBase(test_aim_base.AIMBaseTestCase):
|
||||
'mac': eprt['mac_address']} for eprt in eprts]),
|
||||
erp.destinations)
|
||||
|
||||
def _verify_pc_mapping(self, pc):
|
||||
def _verify_pc_mapping(self, pc, multiple=False):
|
||||
ctx = self._aim_context
|
||||
flowcs = [self.show_flow_classifier(x)['flow_classifier'] for x in
|
||||
pc['flow_classifiers']]
|
||||
@ -314,19 +314,22 @@ class TestAIMServiceFunctionChainingBase(test_aim_base.AIMBaseTestCase):
|
||||
for flowc in flowcs])
|
||||
ppgs = [self.show_port_pair_group(x)['port_pair_group'] for x in
|
||||
pc['port_pair_groups']]
|
||||
self.assertEqual(
|
||||
len(flowcs), len(self.aim_mgr.find(ctx, aim_res.Contract)))
|
||||
self.assertEqual(
|
||||
len(flowcs), len(self.aim_mgr.find(ctx, aim_res.ContractSubject)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants) * len(ppgs),
|
||||
len(self.aim_mgr.find(ctx, aim_sg.DeviceClusterContext)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants) * len(ppgs) * 2,
|
||||
len(self.aim_mgr.find(ctx, aim_sg.DeviceClusterInterfaceContext)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants),
|
||||
len(self.aim_mgr.find(ctx, aim_sg.ServiceGraph)))
|
||||
if not multiple:
|
||||
self.assertEqual(
|
||||
len(flowcs), len(self.aim_mgr.find(ctx, aim_res.Contract)))
|
||||
self.assertEqual(
|
||||
len(flowcs), len(self.aim_mgr.find(ctx,
|
||||
aim_res.ContractSubject)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants) * len(ppgs),
|
||||
len(self.aim_mgr.find(ctx, aim_sg.DeviceClusterContext)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants) * len(ppgs) * 2,
|
||||
len(self.aim_mgr.find(ctx,
|
||||
aim_sg.DeviceClusterInterfaceContext)))
|
||||
self.assertEqual(
|
||||
len(flowc_tenants),
|
||||
len(self.aim_mgr.find(ctx, aim_sg.ServiceGraph)))
|
||||
for flowc in flowcs:
|
||||
src_net = self._show_network(
|
||||
flowc['l7_parameters']['logical_source_network'])
|
||||
@ -375,7 +378,9 @@ class TestAIMServiceFunctionChainingBase(test_aim_base.AIMBaseTestCase):
|
||||
self.assertTrue(
|
||||
contract.name in (ext_net.consumed_contract_names if
|
||||
pref == 'src_' else
|
||||
ext_net.provided_contract_names))
|
||||
ext_net.provided_contract_names),
|
||||
"%s not in ext net %s" % (contract.name,
|
||||
ext_net.__dict__))
|
||||
else:
|
||||
epg = self.aim_mgr.get(
|
||||
ctx, aim_res.EndpointGroup.from_dn(
|
||||
@ -1022,6 +1027,50 @@ class TestPortChain(TestAIMServiceFunctionChainingBase):
|
||||
ppg3['id'], ppg4['id']],
|
||||
expected_res_status=500)
|
||||
|
||||
def test_pc_move_fc(self):
|
||||
fc = self._create_simple_flowc(src_svi=self.src_svi,
|
||||
dst_svi=self.dst_svi)
|
||||
fcs = [fc]
|
||||
for i in range(3):
|
||||
fcs.append(self.create_flow_classifier(
|
||||
l7_parameters={
|
||||
'logical_source_network': fc[
|
||||
'l7_parameters']['logical_source_network'],
|
||||
'logical_destination_network': fc[
|
||||
'l7_parameters']['logical_destination_network']},
|
||||
source_ip_prefix='192.168.%s.0/24' % (i + 3),
|
||||
destination_ip_prefix=fc['destination_ip_prefix'],
|
||||
expected_res_status=201)['flow_classifier'])
|
||||
# We have four FCs
|
||||
ppg1 = self._create_simple_ppg(pairs=1)
|
||||
ppg2 = self._create_simple_ppg(pairs=1)
|
||||
pc1 = self.create_port_chain(port_pair_groups=[ppg1['id']],
|
||||
flow_classifiers=[fcs[0]['id'],
|
||||
fcs[1]['id']],
|
||||
expected_res_status=201)['port_chain']
|
||||
pc2 = self.create_port_chain(port_pair_groups=[ppg2['id']],
|
||||
flow_classifiers=[fcs[2]['id'],
|
||||
fcs[3]['id']],
|
||||
expected_res_status=201)['port_chain']
|
||||
self._verify_pc_mapping(pc1, multiple=True)
|
||||
self._verify_pc_mapping(pc2, multiple=True)
|
||||
# Remove FC 2
|
||||
pc1 = self.update_port_chain(pc1['id'],
|
||||
flow_classifiers=[fcs[0]['id']],
|
||||
expected_res_status=200)['port_chain']
|
||||
self._verify_pc_mapping(pc1, multiple=True)
|
||||
self._verify_pc_mapping(pc2, multiple=True)
|
||||
if self.dst_svi:
|
||||
self.delete_port_chain(pc1['id'])
|
||||
dst_net_id = fc['l7_parameters']['logical_destination_network']
|
||||
ext_net = self.aim_mgr.find(
|
||||
self._aim_context, aim_res.ExternalNetwork,
|
||||
name=fc['destination_ip_prefix'].replace(
|
||||
'/', '_') + '_' + 'net_' + dst_net_id)[0]
|
||||
self.assertEqual(2, len(ext_net.provided_contract_names))
|
||||
self.delete_port_chain(pc2['id'])
|
||||
self.assertIsNone(self.aim_mgr.get(self._aim_context, ext_net))
|
||||
|
||||
|
||||
class TestPortChainSVI(TestPortChain):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user