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,6 +2367,14 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
# this could be internal or external EPG
|
||||
epg = self.aim.get(aim_ctx, epg)
|
||||
if epg:
|
||||
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)
|
||||
|
@ -2458,7 +2486,14 @@ 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,
|
||||
|
@ -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,8 +584,18 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
|||
contract = self._get_flc_contract(prov_group, sg)
|
||||
# TODO(ivar): if provider/consumer are in different tenants, export
|
||||
# the contract
|
||||
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)
|
||||
|
@ -651,7 +661,17 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
|||
contract = self._get_flc_contract(p_group, sg)
|
||||
try:
|
||||
if prefix == FLOWC_SRC:
|
||||
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:
|
||||
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:
|
||||
|
@ -659,9 +679,25 @@ class SfcAIMDriver(SfcAIMDriverBase):
|
|||
{'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
|
||||
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):
|
||||
|
|
|
@ -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