Use top-level contract references
Contract references in aci-integration-module (AIM) were previously created or destroyed by modifying list members of the ExternalNetwork resource. This caused problems when the ExternalNetwork was monitored state but the contract references were meant to be configured state, as the view of the monitored universe/state could be inconsistent from time to time, causing the contract references to inadvertently get deleted. A recent commit (9076bd8738e27052e75ec53052e509c54c4b91ea) in AIM made the contract references top-level resources, so that their creation or removal can only be made directly. The aim_lib module was changed to support passing lists of provided and consumed contracts expclicitly, in order to adopt these changes. Change-Id: I14b01bea751823c3e3b70df3e7f41ea5babd9522
This commit is contained in:
parent
d1f32d9958
commit
2e5ec528b6
@ -330,11 +330,27 @@ def do_ap_name_change(session, conf=None):
|
||||
eid = (ext_net.tenant_name, ext_net.l3out_name, ext_net.name)
|
||||
for vrf in vrfs:
|
||||
if eid in clone_ext_nets:
|
||||
ext_net.provided_contract_names = clone_ext_nets[
|
||||
eid].provided_contract_names
|
||||
ext_net.consumed_contract_names = clone_ext_nets[
|
||||
eid].consumed_contract_names
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf)
|
||||
p_cons = clone_ext_nets[eid].provided_contract_names
|
||||
c_cons = clone_ext_nets[eid].provided_contract_names
|
||||
prov = []
|
||||
cons = []
|
||||
ext_net = clone_ext_nets[eid]
|
||||
for p_con in p_cons:
|
||||
prov.append(
|
||||
aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.ext_net_name,
|
||||
name=p_con.name))
|
||||
for c_con in c_cons:
|
||||
cons.append(
|
||||
aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.ext_net_name,
|
||||
name=p_con.name))
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf,
|
||||
provided_contracts=prov, consumed_contracts=cons)
|
||||
|
||||
|
||||
def do_apic_aim_security_group_migration(session):
|
||||
|
@ -743,6 +743,26 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
res = aim_resource.QosDppPol(**i)
|
||||
self.aim.create(aim_ctx, res, overwrite=True)
|
||||
|
||||
def _create_external_epg_contract(self, aim_ctx, klass,
|
||||
ext_net, contract):
|
||||
new_contract = klass(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name)
|
||||
self.aim.create(aim_ctx, new_contract, overwrite=True)
|
||||
|
||||
def _delete_external_epg_contract(self, aim_ctx, klass,
|
||||
ext_net, contract):
|
||||
old_contract = klass(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name)
|
||||
old_contract_db = self.aim.get(aim_ctx, old_contract)
|
||||
if old_contract_db:
|
||||
self.aim.delete(aim_ctx, old_contract_db)
|
||||
|
||||
def create_qos_policy_precommit(self, context, policy):
|
||||
"""Create a QoS policy.
|
||||
:param context: neutron api request context
|
||||
@ -2347,16 +2367,24 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
# this could be internal or external EPG
|
||||
epg = self.aim.get(aim_ctx, epg)
|
||||
if epg:
|
||||
contracts = epg.consumed_contract_names
|
||||
if contract.name not in contracts:
|
||||
contracts.append(contract.name)
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
consumed_contract_names=contracts)
|
||||
contracts = epg.provided_contract_names
|
||||
if contract.name not in contracts:
|
||||
contracts.append(contract.name)
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
provided_contract_names=contracts)
|
||||
if isinstance(epg, aim_resource.ExternalNetwork):
|
||||
self._create_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
epg, contract)
|
||||
self._create_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkConsumedContract,
|
||||
epg, contract)
|
||||
else:
|
||||
contracts = epg.consumed_contract_names
|
||||
if contract.name not in contracts:
|
||||
contracts.append(contract.name)
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
consumed_contract_names=contracts)
|
||||
contracts = epg.provided_contract_names
|
||||
if contract.name not in contracts:
|
||||
contracts.append(contract.name)
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
provided_contract_names=contracts)
|
||||
|
||||
# If external-gateway is set, handle external-connectivity changes.
|
||||
# External network is not supported for SVI network for now.
|
||||
@ -2458,16 +2486,23 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
# Contract.
|
||||
if router_id not in router_ids and epg:
|
||||
epg = self.aim.get(aim_ctx, epg)
|
||||
if isinstance(epg, aim_resource.ExternalNetwork):
|
||||
self._delete_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
epg, contract)
|
||||
self._delete_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkConsumedContract,
|
||||
epg, contract)
|
||||
else:
|
||||
contracts = [name for name in epg.consumed_contract_names
|
||||
if name != contract.name]
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
consumed_contract_names=contracts)
|
||||
|
||||
contracts = [name for name in epg.consumed_contract_names
|
||||
if name != contract.name]
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
consumed_contract_names=contracts)
|
||||
|
||||
contracts = [name for name in epg.provided_contract_names
|
||||
if name != contract.name]
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
provided_contract_names=contracts)
|
||||
contracts = [name for name in epg.provided_contract_names
|
||||
if name != contract.name]
|
||||
epg = self.aim.update(aim_ctx, epg,
|
||||
provided_contract_names=contracts)
|
||||
|
||||
nets_to_notify = set()
|
||||
ports_to_notify = set()
|
||||
@ -4812,17 +4847,37 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
vrf = aim_resource.VRF(tenant_name=vrf.tenant_name, name=vrf.name)
|
||||
rtr_dbs = self._get_routers_for_vrf(session, vrf)
|
||||
|
||||
prov = set()
|
||||
cons = set()
|
||||
prov_dict = {}
|
||||
cons_dict = {}
|
||||
|
||||
def update_contracts(router):
|
||||
def update_contracts(router, ext_net):
|
||||
contract = self._map_router(session, router, True)
|
||||
prov.add(contract.name)
|
||||
cons.add(contract.name)
|
||||
prov_dict[
|
||||
contract.name] = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name)
|
||||
cons_dict[
|
||||
contract.name] = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name)
|
||||
|
||||
r_info = self.get_router_extn_db(session, router['id'])
|
||||
prov.update(r_info[a_l3.EXTERNAL_PROVIDED_CONTRACTS])
|
||||
cons.update(r_info[a_l3.EXTERNAL_CONSUMED_CONTRACTS])
|
||||
for p_con in r_info[a_l3.EXTERNAL_PROVIDED_CONTRACTS]:
|
||||
prov_dict[
|
||||
p_con] = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name, name=p_con)
|
||||
for c_con in r_info[a_l3.EXTERNAL_CONSUMED_CONTRACTS]:
|
||||
cons_dict[
|
||||
c_con] = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name, name=c_con)
|
||||
|
||||
if old_network:
|
||||
_, ext_net, ns = self._get_aim_nat_strategy(old_network)
|
||||
@ -4833,15 +4888,19 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
rtr_old = [r for r in rtr_dbs
|
||||
if (r.gw_port_id and
|
||||
r.gw_port.network_id in eqv_nets)]
|
||||
prov = set()
|
||||
cons = set()
|
||||
prov_dict = {}
|
||||
cons_dict = {}
|
||||
for r in rtr_old:
|
||||
update_contracts(r)
|
||||
update_contracts(r, ext_net)
|
||||
|
||||
if rtr_old:
|
||||
ext_net.provided_contract_names = sorted(prov)
|
||||
ext_net.consumed_contract_names = sorted(cons)
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf)
|
||||
prov_list = list(prov_dict.values())
|
||||
cons_list = list(cons_dict.values())
|
||||
provided = sorted(prov_list, key=lambda x: x.name)
|
||||
consumed = sorted(cons_list, key=lambda x: x.name)
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf,
|
||||
provided_contracts=provided,
|
||||
consumed_contracts=consumed)
|
||||
else:
|
||||
ns.disconnect_vrf(aim_ctx, ext_net, vrf)
|
||||
if new_network:
|
||||
@ -4853,14 +4912,18 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
rtr_new = [r for r in rtr_dbs
|
||||
if (r.gw_port_id and
|
||||
r.gw_port.network_id in eqv_nets)]
|
||||
prov = set()
|
||||
cons = set()
|
||||
prov_dict = {}
|
||||
cons_dict = {}
|
||||
for r in rtr_new:
|
||||
update_contracts(r)
|
||||
update_contracts(router)
|
||||
ext_net.provided_contract_names = sorted(prov)
|
||||
ext_net.consumed_contract_names = sorted(cons)
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf)
|
||||
update_contracts(r, ext_net)
|
||||
update_contracts(router, ext_net)
|
||||
prov_list = list(prov_dict.values())
|
||||
cons_list = list(cons_dict.values())
|
||||
provided = sorted(prov_list, key=lambda x: x.name)
|
||||
consumed = sorted(cons_list, key=lambda x: x.name)
|
||||
ns.connect_vrf(aim_ctx, ext_net, vrf,
|
||||
provided_contracts=provided,
|
||||
consumed_contracts=consumed)
|
||||
|
||||
def _is_port_bound(self, port):
|
||||
return port.get(portbindings.VIF_TYPE) not in [
|
||||
@ -6507,6 +6570,10 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
mgr.register_aim_resource_class(aim_resource.ContractSubject)
|
||||
mgr.register_aim_resource_class(aim_resource.EndpointGroup)
|
||||
mgr.register_aim_resource_class(aim_resource.ExternalNetwork)
|
||||
mgr.register_aim_resource_class(
|
||||
aim_resource.ExternalNetworkProvidedContract)
|
||||
mgr.register_aim_resource_class(
|
||||
aim_resource.ExternalNetworkConsumedContract)
|
||||
mgr.register_aim_resource_class(aim_resource.ExternalSubnet)
|
||||
mgr.register_aim_resource_class(aim_resource.Filter)
|
||||
mgr.register_aim_resource_class(aim_resource.FilterEntry)
|
||||
@ -7209,12 +7276,30 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
for router_id in routers:
|
||||
contract = self._map_router(
|
||||
mgr.expected_session, router_dbs[router_id], True)
|
||||
prov.add(contract.name)
|
||||
cons.add(contract.name)
|
||||
prov.update(router_ext_prov[router_id])
|
||||
cons.update(router_ext_cons[router_id])
|
||||
ext_net.provided_contract_names = sorted(prov)
|
||||
ext_net.consumed_contract_names = sorted(cons)
|
||||
prov.add(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name))
|
||||
cons.add(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=contract.name))
|
||||
for p_con in router_ext_prov[router_id]:
|
||||
prov.add(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=p_con))
|
||||
for c_con in router_ext_cons[router_id]:
|
||||
cons.add(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=ext_net.tenant_name,
|
||||
l3out_name=ext_net.l3out_name,
|
||||
ext_net_name=ext_net.name,
|
||||
name=c_con))
|
||||
provided = sorted(prov, key=lambda x: x.name)
|
||||
consumed = sorted(cons, key=lambda x: x.name)
|
||||
int_vrf = int_vrfs[key]
|
||||
|
||||
# Keep only the identity attributes of the VRF so that
|
||||
@ -7224,7 +7309,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||
# of the L3Outside's display_name.
|
||||
int_vrf = aim_resource.VRF(
|
||||
tenant_name=int_vrf.tenant_name, name=int_vrf.name)
|
||||
ns.connect_vrf(mgr.expected_aim_ctx, ext_net, int_vrf)
|
||||
ns.connect_vrf(mgr.expected_aim_ctx, ext_net, int_vrf,
|
||||
provided_contracts=provided, consumed_contracts=consumed)
|
||||
|
||||
return bd, epg, vrf
|
||||
|
||||
|
@ -584,10 +584,20 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
||||
contract = self._get_flc_contract(prov_group, sg)
|
||||
# TODO(ivar): if provider/consumer are in different tenants, export
|
||||
# the contract
|
||||
if contract.name not in cons_group.consumed_contract_names:
|
||||
cons_group.consumed_contract_names.append(contract.name)
|
||||
if contract.name not in prov_group.provided_contract_names:
|
||||
prov_group.provided_contract_names.append(contract.name)
|
||||
if isinstance(cons_group, aim_resource.ExternalNetwork):
|
||||
self.aim_mech._create_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkConsumedContract,
|
||||
cons_group, contract)
|
||||
else:
|
||||
if contract.name not in cons_group.consumed_contract_names:
|
||||
cons_group.consumed_contract_names.append(contract.name)
|
||||
if isinstance(prov_group, aim_resource.ExternalNetwork):
|
||||
self.aim_mech._create_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
prov_group, contract)
|
||||
else:
|
||||
if contract.name not in prov_group.provided_contract_names:
|
||||
prov_group.provided_contract_names.append(contract.name)
|
||||
self.aim.create(aim_ctx, cons_group, overwrite=True)
|
||||
self.aim.create(aim_ctx, prov_group, overwrite=True)
|
||||
|
||||
@ -651,18 +661,44 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
||||
contract = self._get_flc_contract(p_group, sg)
|
||||
try:
|
||||
if prefix == FLOWC_SRC:
|
||||
epg.consumed_contract_names.remove(contract.name)
|
||||
if isinstance(epg, aim_resource.ExternalNetwork):
|
||||
self.aim_mech._delete_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkConsumedContract,
|
||||
epg, contract)
|
||||
else:
|
||||
epg.consumed_contract_names.remove(contract.name)
|
||||
else:
|
||||
epg.provided_contract_names.remove(contract.name)
|
||||
if isinstance(epg, aim_resource.ExternalNetwork):
|
||||
self.aim_mech._delete_external_epg_contract(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
epg, contract)
|
||||
else:
|
||||
epg.provided_contract_names.remove(contract.name)
|
||||
except ValueError:
|
||||
LOG.warning("Contract %(name)s not present in EPG %(epg)s",
|
||||
{'name': contract.name, 'epg': epg})
|
||||
else:
|
||||
epg = 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, epg, cascade=True)
|
||||
if ext_net:
|
||||
if isinstance(epg, aim_resource.ExternalNetwork):
|
||||
contract_params = {
|
||||
'tenant_name': ext_net.tenant_name,
|
||||
'l3out_name': ext_net.l3out_name,
|
||||
'ext_net_name': ext_net.name}
|
||||
p_cons = self.aim.find(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
**contract_params)
|
||||
c_cons = self.aim.find(aim_ctx,
|
||||
aim_resource.ExternalNetworkProvidedContract,
|
||||
**contract_params)
|
||||
if not p_cons and not c_cons:
|
||||
# Only remove if completely empty
|
||||
self.aim.delete(aim_ctx, epg, cascade=True)
|
||||
else:
|
||||
if (not epg.consumed_contract_names and
|
||||
not epg.provided_contract_names):
|
||||
# Only remove if completely empty
|
||||
self.aim.delete(aim_ctx, epg, cascade=True)
|
||||
|
||||
def _get_chains_by_classifier_id(self, plugin_context, flowc_id):
|
||||
context = plugin_context
|
||||
|
@ -8179,33 +8179,54 @@ class TestExternalConnectivityBase(object):
|
||||
|
||||
# Connect the router interfaces to the subnets
|
||||
vrf_objs = {}
|
||||
rtr_contracts = {}
|
||||
for tenant, router_list in six.iteritems(objs):
|
||||
tenant_aname = self.name_mapper.project(None, tenant)
|
||||
a_vrf = aim_resource.VRF(tenant_name=tenant_aname,
|
||||
name='DefaultVRF')
|
||||
a_ext_net = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
prov = []
|
||||
cons = []
|
||||
for router, subnets, addr_scope in router_list:
|
||||
if addr_scope:
|
||||
a_vrf.name = self.name_mapper.address_scope(
|
||||
None, addr_scope['id'])
|
||||
self.fix_l3out_vrf(self.t1_aname, 'l1', a_vrf.name)
|
||||
contract = self.name_mapper.router(None, router['id'])
|
||||
a_ext_net.provided_contract_names.append(contract)
|
||||
a_ext_net.provided_contract_names.extend(
|
||||
router[PROV])
|
||||
a_ext_net.provided_contract_names.sort()
|
||||
a_ext_net.consumed_contract_names.append(contract)
|
||||
a_ext_net.consumed_contract_names.extend(
|
||||
router[CONS])
|
||||
a_ext_net.consumed_contract_names.sort()
|
||||
prov.append(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name,
|
||||
name=contract))
|
||||
cons.append(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name,
|
||||
name=contract))
|
||||
for con in router[PROV]:
|
||||
prov.append(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name,
|
||||
name=con))
|
||||
for con in router[CONS]:
|
||||
cons.append(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name,
|
||||
name=con))
|
||||
|
||||
for idx in range(0, len(subnets)):
|
||||
self.mock_ns.reset_mock()
|
||||
self._router_interface_action('add', router['id'],
|
||||
subnets[idx]['id'], None)
|
||||
if idx == 0:
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net, a_vrf)
|
||||
provided = sorted(prov, key=lambda x: x.name)
|
||||
consumed = sorted(cons, key=lambda x: x.name)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net, a_vrf,
|
||||
provided_contracts=provided,
|
||||
consumed_contracts=consumed)
|
||||
else:
|
||||
cv.assert_not_called()
|
||||
|
||||
@ -8216,6 +8237,7 @@ class TestExternalConnectivityBase(object):
|
||||
self._check_bd_l3out(aim_ctx, aim_bd, 'l1')
|
||||
|
||||
self._validate()
|
||||
rtr_contracts[router['id']] = (prov, cons)
|
||||
vrf_objs[tenant] = a_ext_net
|
||||
|
||||
# Remove the router interfaces
|
||||
@ -8226,17 +8248,30 @@ class TestExternalConnectivityBase(object):
|
||||
a_ext_net = vrf_objs.pop(tenant)
|
||||
num_router = len(router_list)
|
||||
for router, subnets, addr_scope in router_list:
|
||||
prov, cons = rtr_contracts[router['id']]
|
||||
if addr_scope:
|
||||
a_vrf.name = self.name_mapper.address_scope(
|
||||
None, addr_scope['id'])
|
||||
self.fix_l3out_vrf(self.t1_aname, 'l1', a_vrf.name)
|
||||
contract = self.name_mapper.router(None, router['id'])
|
||||
a_ext_net.provided_contract_names.remove(contract)
|
||||
a_ext_net.consumed_contract_names.remove(contract)
|
||||
prov.remove(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name, name=contract))
|
||||
cons.remove(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name, name=contract))
|
||||
for c in router[PROV]:
|
||||
a_ext_net.provided_contract_names.remove(c)
|
||||
prov.remove(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name, name=c))
|
||||
for c in router[CONS]:
|
||||
a_ext_net.consumed_contract_names.remove(c)
|
||||
cons.remove(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net.tenant_name,
|
||||
l3out_name=a_ext_net.l3out_name,
|
||||
ext_net_name=a_ext_net.name, name=c))
|
||||
|
||||
for idx in range(0, len(subnets)):
|
||||
self.mock_ns.reset_mock()
|
||||
@ -8250,8 +8285,12 @@ class TestExternalConnectivityBase(object):
|
||||
if idx == len(subnets) - 1:
|
||||
num_router -= 1
|
||||
if num_router:
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net,
|
||||
a_vrf)
|
||||
provided = sorted(prov, key=lambda x: x.name)
|
||||
consumed = sorted(cons, key=lambda x: x.name)
|
||||
cv.assert_called_once_with(
|
||||
mock.ANY, a_ext_net, a_vrf,
|
||||
provided_contracts=provided,
|
||||
consumed_contracts=consumed)
|
||||
else:
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_net,
|
||||
a_vrf)
|
||||
@ -8333,10 +8372,27 @@ class TestExternalConnectivityBase(object):
|
||||
ext_net1['id']}}})
|
||||
contract = self.name_mapper.router(None, router['id'])
|
||||
a_ext_net1 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1',
|
||||
provided_contract_names=sorted(['pr-1', contract]),
|
||||
consumed_contract_names=sorted(['co-1', contract]))
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf)
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
p1_ext1 = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name='pr-1')
|
||||
prc_ext1 = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
c1_ext1 = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name='co-1')
|
||||
crc_ext1 = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
provided = sorted([prc_ext1, p1_ext1], key=lambda x: x.name)
|
||||
consumed = sorted([crc_ext1, c1_ext1], key=lambda x: x.name)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf,
|
||||
provided_contracts=provided, consumed_contracts=consumed)
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._update('routers', router['id'],
|
||||
@ -8344,39 +8400,58 @@ class TestExternalConnectivityBase(object):
|
||||
{'external_gateway_info': {'network_id':
|
||||
ext_net2['id']}}})
|
||||
a_ext_net2 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2',
|
||||
provided_contract_names=sorted(['pr-1', contract]),
|
||||
consumed_contract_names=sorted(['co-1', contract]))
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2')
|
||||
p1_ext2 = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net2.tenant_name,
|
||||
l3out_name=a_ext_net2.l3out_name,
|
||||
ext_net_name=a_ext_net2.name, name='pr-1')
|
||||
prc_ext2 = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net2.tenant_name,
|
||||
l3out_name=a_ext_net2.l3out_name,
|
||||
ext_net_name=a_ext_net2.name, name=contract)
|
||||
c1_ext2 = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net2.tenant_name,
|
||||
l3out_name=a_ext_net2.l3out_name,
|
||||
ext_net_name=a_ext_net2.name, name='co-1')
|
||||
c2_ext2 = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net2.tenant_name,
|
||||
l3out_name=a_ext_net2.l3out_name,
|
||||
ext_net_name=a_ext_net2.name, name='co-2')
|
||||
crc_ext2 = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net2.tenant_name,
|
||||
l3out_name=a_ext_net2.l3out_name,
|
||||
ext_net_name=a_ext_net2.name, name=contract)
|
||||
a_ext_net1.provided_contract_names = []
|
||||
a_ext_net1.consumed_contract_names = []
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf)
|
||||
provided = sorted([prc_ext2, p1_ext2], key=lambda x: x.name)
|
||||
consumed = sorted([crc_ext2, c1_ext2], key=lambda x: x.name)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf,
|
||||
provided_contracts=provided, consumed_contracts=consumed)
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._update('routers', router['id'],
|
||||
{'router':
|
||||
{PROV: []}})
|
||||
a_ext_net2 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2',
|
||||
provided_contract_names=sorted([contract]),
|
||||
consumed_contract_names=sorted(['co-1', contract]))
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf)
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2')
|
||||
consumed = sorted([crc_ext2, c1_ext2], key=lambda x: x.name)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf,
|
||||
provided_contracts=[prc_ext2], consumed_contracts=consumed)
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._update('routers', router['id'],
|
||||
{'router':
|
||||
{CONS: ['co-1', 'co-2']}})
|
||||
a_ext_net2 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2',
|
||||
provided_contract_names=sorted([contract]),
|
||||
consumed_contract_names=sorted(['co-1', 'co-2', contract]))
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf)
|
||||
tenant_name=self.t1_aname, l3out_name='l2', name='n2')
|
||||
consumed = sorted([crc_ext2, c1_ext2, c2_ext2], key=lambda x: x.name)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf,
|
||||
provided_contracts=[prc_ext2], consumed_contracts=consumed)
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._update('routers', router['id'],
|
||||
{'router': {'external_gateway_info': {}}})
|
||||
a_ext_net2.provided_contract_names = []
|
||||
a_ext_net2.consumed_contract_names = []
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_net2, a_vrf)
|
||||
|
||||
def test_router_gateway(self):
|
||||
@ -8482,40 +8557,62 @@ class TestExternalConnectivityBase(object):
|
||||
self._validate()
|
||||
|
||||
self._add_external_gateway_to_router(routers[0], ext_nets[0])
|
||||
a_ext_nets[0].provided_contract_names = [contracts[0]]
|
||||
a_ext_nets[0].consumed_contract_names = [contracts[0]]
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[0], a_vrf)
|
||||
prov_ext1 = []
|
||||
cons_ext1 = []
|
||||
for con in contracts:
|
||||
prov_ext1.append(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_nets[0].tenant_name,
|
||||
l3out_name=a_ext_nets[0].l3out_name,
|
||||
ext_net_name=a_ext_nets[0].name, name=con))
|
||||
cons_ext1.append(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_nets[0].tenant_name,
|
||||
l3out_name=a_ext_nets[0].l3out_name,
|
||||
ext_net_name=a_ext_nets[0].name, name=con))
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[0], a_vrf,
|
||||
provided_contracts=[prov_ext1[0]],
|
||||
consumed_contracts=[cons_ext1[0]])
|
||||
self._validate()
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
prov_ext2 = []
|
||||
cons_ext2 = []
|
||||
for con in contracts:
|
||||
prov_ext2.append(aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_nets[1].tenant_name,
|
||||
l3out_name=a_ext_nets[1].l3out_name,
|
||||
ext_net_name=a_ext_nets[1].name, name=con))
|
||||
cons_ext2.append(aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_nets[1].tenant_name,
|
||||
l3out_name=a_ext_nets[1].l3out_name,
|
||||
ext_net_name=a_ext_nets[1].name, name=con))
|
||||
self._add_external_gateway_to_router(routers[1], ext_nets[1])
|
||||
if shared_l3out:
|
||||
a_ext_nets[1].provided_contract_names = sorted(contracts)
|
||||
a_ext_nets[1].consumed_contract_names = sorted(contracts)
|
||||
provided = sorted(prov_ext2, key=lambda x: x.name)
|
||||
consumed = sorted(cons_ext2, key=lambda x: x.name)
|
||||
p_con = provided
|
||||
c_con = consumed
|
||||
else:
|
||||
a_ext_nets[1].provided_contract_names = [contracts[1]]
|
||||
a_ext_nets[1].consumed_contract_names = [contracts[1]]
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[1], a_vrf)
|
||||
p_con = [prov_ext2[1]]
|
||||
c_con = [cons_ext2[1]]
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[1], a_vrf,
|
||||
provided_contracts=p_con,
|
||||
consumed_contracts=c_con)
|
||||
self._validate()
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._router_interface_action('remove', routers[0], sub1['id'], None)
|
||||
if shared_l3out:
|
||||
a_ext_nets[0].provided_contract_names = [contracts[1]]
|
||||
a_ext_nets[0].consumed_contract_names = [contracts[1]]
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[0], a_vrf)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_nets[0], a_vrf,
|
||||
provided_contracts=[prov_ext2[1]],
|
||||
consumed_contracts=[cons_ext2[1]])
|
||||
dv.assert_not_called()
|
||||
else:
|
||||
a_ext_nets[0].provided_contract_names = []
|
||||
a_ext_nets[0].consumed_contract_names = []
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_nets[0], a_vrf)
|
||||
cv.assert_not_called()
|
||||
self._validate()
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
self._router_interface_action('remove', routers[1], sub1['id'], None)
|
||||
a_ext_nets[1].provided_contract_names = []
|
||||
a_ext_nets[1].consumed_contract_names = []
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_nets[1], a_vrf)
|
||||
self._validate()
|
||||
|
||||
@ -8786,9 +8883,15 @@ class TestExternalConnectivityBase(object):
|
||||
|
||||
contract = self.name_mapper.router(None, router['id'])
|
||||
a_ext_net1 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1',
|
||||
provided_contract_names=[contract],
|
||||
consumed_contract_names=[contract])
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
prov = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
cons = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
a_ext_net1_no_contracts = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
|
||||
@ -8802,7 +8905,8 @@ class TestExternalConnectivityBase(object):
|
||||
a_vrf1 = aim_resource.VRF(
|
||||
tenant_name=self.name_mapper.project(None, 'tenant_1'),
|
||||
name='DefaultVRF')
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf1)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf1,
|
||||
provided_contracts=[prov], consumed_contracts=[cons])
|
||||
dv.assert_not_called()
|
||||
|
||||
# 2. Create shared network net2 in tenant tenant_2, then connect
|
||||
@ -8816,7 +8920,8 @@ class TestExternalConnectivityBase(object):
|
||||
a_vrf2 = aim_resource.VRF(
|
||||
tenant_name=self.name_mapper.project(None, 'tenant_2'),
|
||||
name='DefaultVRF')
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf2)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf2,
|
||||
provided_contracts=[prov], consumed_contracts=[cons])
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_net1_no_contracts, a_vrf1)
|
||||
|
||||
# 3. Create unshared network net3 in tenant test-tenant, then connect
|
||||
@ -8839,7 +8944,8 @@ class TestExternalConnectivityBase(object):
|
||||
# 5. Disconnect net2 from r1
|
||||
self.mock_ns.reset_mock()
|
||||
self._router_interface_action('remove', router['id'], sub2['id'], None)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf1)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, a_vrf1,
|
||||
provided_contracts=[prov], consumed_contracts=[cons])
|
||||
dv.assert_called_once_with(mock.ANY, a_ext_net1_no_contracts, a_vrf2)
|
||||
|
||||
# 6. Disconnect net1 from r1
|
||||
@ -8881,9 +8987,15 @@ class TestExternalConnectivityBase(object):
|
||||
|
||||
contract = self.name_mapper.router(None, router['id'])
|
||||
a_ext_net1 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1',
|
||||
provided_contract_names=[contract],
|
||||
consumed_contract_names=[contract])
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
prov = aim_resource.ExternalNetworkProvidedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
cons = aim_resource.ExternalNetworkConsumedContract(
|
||||
tenant_name=a_ext_net1.tenant_name,
|
||||
l3out_name=a_ext_net1.l3out_name,
|
||||
ext_net_name=a_ext_net1.name, name=contract)
|
||||
|
||||
# create private stuff
|
||||
net = self._make_network(self.fmt, 'net1', True)['network']
|
||||
@ -8895,12 +9007,11 @@ class TestExternalConnectivityBase(object):
|
||||
dv.assert_not_called()
|
||||
|
||||
self._router_interface_action('add', router['id'], subnet['id'], None)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, vrf)
|
||||
cv.assert_called_once_with(mock.ANY, a_ext_net1, vrf,
|
||||
provided_contracts=[prov], consumed_contracts=[cons])
|
||||
dv.assert_not_called()
|
||||
|
||||
self.mock_ns.reset_mock()
|
||||
a_ext_net1.provided_contract_names = []
|
||||
a_ext_net1.consumed_contract_names = []
|
||||
self._router_interface_action('remove', router['id'], subnet['id'],
|
||||
None)
|
||||
cv.assert_not_called()
|
||||
|
@ -479,10 +479,18 @@ class TestAIMServiceFunctionChainingBase(test_aim_base.AIMBaseTestCase):
|
||||
self.assertIsNotNone(ext_sub)
|
||||
|
||||
self.assertIsNotNone(ext_net)
|
||||
self.assertTrue(
|
||||
contract.name in (ext_net.consumed_contract_names if
|
||||
pref == 'src_' else
|
||||
ext_net.provided_contract_names),
|
||||
ext_contract_params = {
|
||||
'tenant_name': ext_net.tenant_name,
|
||||
'l3out_name': ext_net.l3out_name,
|
||||
'ext_net_name': ext_net.name}
|
||||
if pref == 'src_':
|
||||
klass = aim_res.ExternalNetworkConsumedContract
|
||||
else:
|
||||
klass = aim_res.ExternalNetworkProvidedContract
|
||||
contracts = self.aim_mgr.find(ctx, klass,
|
||||
**ext_contract_params)
|
||||
contract_names = [c.name for c in contracts]
|
||||
self.assertTrue(contract.name in contract_names,
|
||||
"%s not in ext net %s" % (contract.name,
|
||||
ext_net.__dict__))
|
||||
else:
|
||||
@ -1390,10 +1398,19 @@ class TestPortChain(TestAIMServiceFunctionChainingBase):
|
||||
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))
|
||||
ext_params = {
|
||||
'tenant_name': ext_net.tenant_name,
|
||||
'l3out_name': ext_net.l3out_name,
|
||||
'ext_net_name': ext_net.name}
|
||||
prov = self.aim_mgr.find(self._aim_context,
|
||||
aim_res.ExternalNetworkProvidedContract,
|
||||
**ext_params)
|
||||
self.assertEqual(2, len(prov))
|
||||
self.delete_port_chain(pc1['id'])
|
||||
ext_net = self.aim_mgr.get(self._aim_context, ext_net)
|
||||
self.assertEqual(1, len(ext_net.provided_contract_names))
|
||||
prov = self.aim_mgr.find(self._aim_context,
|
||||
aim_res.ExternalNetworkProvidedContract,
|
||||
**ext_params)
|
||||
self.assertEqual(1, len(prov))
|
||||
self.delete_port_chain(pc2['id'])
|
||||
self.assertIsNone(self.aim_mgr.get(self._aim_context, ext_net))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user