Support for multi external networks extention
The multi external networks extention allows multiple external networks to be associated with a single L3Outside. Change-Id: Ib872d8661fae321270130b4986d7d21249919ae6
This commit is contained in:
parent
f9c7a63f7a
commit
2edc1ab5c5
|
@ -0,0 +1,38 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""add l3out multiple epgs network extension
|
||||
|
||||
Revision ID: 8c5b556b4df1
|
||||
Revises: e29a84f6a15f
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '8c5b556b4df1'
|
||||
down_revision = 'e29a84f6a15f'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import sql
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('apic_aim_network_extensions',
|
||||
sa.Column('multi_ext_nets', sa.Boolean,
|
||||
nullable=False, server_default=sql.false()))
|
||||
pass
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
|
@ -1 +1 @@
|
|||
e29a84f6a15f
|
||||
8c5b556b4df1
|
||||
|
|
|
@ -54,6 +54,7 @@ POLICY_ENFORCEMENT_PREF = 'apic:policy_enforcement_pref'
|
|||
SNAT_SUBNET_ONLY = 'apic:snat_subnet_only'
|
||||
EPG_SUBNET = 'apic:epg_subnet'
|
||||
NO_NAT_CIDRS = 'apic:no_nat_cidrs'
|
||||
MULTI_EXT_NETS = 'apic:multi_ext_nets'
|
||||
|
||||
BD = 'BridgeDomain'
|
||||
EPG = 'EndpointGroup'
|
||||
|
@ -361,6 +362,11 @@ NET_ATTRIBUTES = {
|
|||
'convert_to': convert_apic_none_to_empty_list,
|
||||
'validate': {'type:list_of_unique_strings': None},
|
||||
},
|
||||
MULTI_EXT_NETS: {
|
||||
'allow_post': True, 'allow_put': False,
|
||||
'is_visible': True, 'default': False,
|
||||
'convert_to': conv.convert_to_boolean,
|
||||
},
|
||||
}
|
||||
|
||||
EXT_NET_ATTRIBUTES = {
|
||||
|
|
|
@ -153,3 +153,8 @@ class InvalidNetworkForErspanSession(exceptions.BadRequest):
|
|||
|
||||
class SnatPoolCannotBeUsedForGatewayIp(exceptions.BadRequest):
|
||||
message = _("Snat only subnet cannot be used to assign network gateway.")
|
||||
|
||||
|
||||
class MultiExtNetworkMixing(exceptions.BadRequest):
|
||||
message = _("All external networks associated with a l3out must "
|
||||
"use the same apic:multi_ext_nets setting. ")
|
||||
|
|
|
@ -79,6 +79,7 @@ class NetworkExtensionDb(model_base.BASEV2):
|
|||
nested_domain_infra_vlan = sa.Column(sa.Integer, nullable=True)
|
||||
nested_domain_service_vlan = sa.Column(sa.Integer, nullable=True)
|
||||
nested_domain_node_network_vlan = sa.Column(sa.Integer, nullable=True)
|
||||
multi_ext_nets = sa.Column(sa.Boolean, default=False, nullable=False)
|
||||
|
||||
|
||||
class NetworkExtensionCidrDb(model_base.BASEV2):
|
||||
|
@ -369,6 +370,7 @@ class ExtensionDbMixin(object):
|
|||
'policy_enforcement_pref']
|
||||
net_res[cisco_apic.NO_NAT_CIDRS] = [
|
||||
c.cidr for c in db_no_nat_cidrs]
|
||||
net_res[cisco_apic.MULTI_EXT_NETS] = db_obj['multi_ext_nets']
|
||||
if net_res.get(cisco_apic.EXTERNAL_NETWORK):
|
||||
net_res[cisco_apic.EXTERNAL_CIDRS] = [c.cidr for c in db_cidrs]
|
||||
return net_res
|
||||
|
@ -417,6 +419,8 @@ class ExtensionDbMixin(object):
|
|||
if cisco_apic.POLICY_ENFORCEMENT_PREF in res_dict:
|
||||
db_obj['policy_enforcement_pref'] = res_dict[
|
||||
cisco_apic.POLICY_ENFORCEMENT_PREF]
|
||||
if cisco_apic.MULTI_EXT_NETS in res_dict:
|
||||
db_obj['multi_ext_nets'] = res_dict[cisco_apic.MULTI_EXT_NETS]
|
||||
session.add(db_obj)
|
||||
|
||||
if cisco_apic.EXTERNAL_CIDRS in res_dict:
|
||||
|
@ -513,6 +517,15 @@ class ExtensionDbMixin(object):
|
|||
|
||||
return [c[0] for c in cidrs]
|
||||
|
||||
def get_external_cidrs_by_net_id(self, session, nid):
|
||||
query = BAKERY(lambda s: s.query(
|
||||
NetworkExtensionCidrDb.cidr))
|
||||
query += lambda q: q.filter_by(
|
||||
network_id=sa.bindparam('nid'))
|
||||
cidrs = query(session).params(nid=nid)
|
||||
|
||||
return [i[0] for i in cidrs]
|
||||
|
||||
def get_subnet_extn_db(self, session, subnet_id):
|
||||
query = BAKERY(lambda s: s.query(
|
||||
SubnetExtensionDb))
|
||||
|
@ -590,6 +603,17 @@ class ExtensionDbMixin(object):
|
|||
c_contracts.append(db_contract['contract_name'])
|
||||
return attr_dict
|
||||
|
||||
def get_network_ids_and_multi_by_l3out_dn(self, session, dn):
|
||||
query = BAKERY(lambda s: s.query(
|
||||
NetworkExtensionDb.network_id,
|
||||
NetworkExtensionDb.multi_ext_nets))
|
||||
query += lambda q: q.filter(
|
||||
NetworkExtensionDb.external_network_dn.like(
|
||||
sa.bindparam('dn') + "/%"))
|
||||
ids_and_multis = query(session).params(dn=dn)
|
||||
|
||||
return [(i[0], i[1]) for i in ids_and_multis]
|
||||
|
||||
def _update_list_attr(self, session, db_model, column,
|
||||
new_values, **filters):
|
||||
if new_values is None:
|
||||
|
|
|
@ -137,6 +137,7 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
|
|||
is_bgp_enabled = data.get(cisco_apic.BGP, False)
|
||||
bgp_type = data.get(cisco_apic.BGP_TYPE, "default_export")
|
||||
asn = data.get(cisco_apic.BGP_ASN, "0")
|
||||
use_multi_ext_nets = data.get(cisco_apic.MULTI_EXT_NETS, False)
|
||||
self.validate_bgp_params(data)
|
||||
res_dict = {cisco_apic.SVI: is_svi,
|
||||
cisco_apic.BGP: is_bgp_enabled,
|
||||
|
@ -162,6 +163,7 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
|
|||
data.get(cisco_apic.POLICY_ENFORCEMENT_PREF, "unenforced"),
|
||||
cisco_apic.NO_NAT_CIDRS:
|
||||
data.get(cisco_apic.NO_NAT_CIDRS),
|
||||
cisco_apic.MULTI_EXT_NETS: use_multi_ext_nets,
|
||||
}
|
||||
if cisco_apic.VLANS_LIST in (data.get(
|
||||
cisco_apic.NESTED_DOMAIN_ALLOWED_VLANS) or {}):
|
||||
|
@ -225,8 +227,9 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
|
|||
cisco_apic.EXTRA_CONSUMED_CONTRACTS,
|
||||
cisco_apic.EPG_CONTRACT_MASTERS,
|
||||
cisco_apic.POLICY_ENFORCEMENT_PREF,
|
||||
cisco_apic.NO_NAT_CIDRS]
|
||||
if not(set(update_attrs) & set(data.keys())):
|
||||
cisco_apic.NO_NAT_CIDRS,
|
||||
cisco_apic.MULTI_EXT_NETS]
|
||||
if not (set(update_attrs) & set(data.keys())):
|
||||
return
|
||||
|
||||
res_dict = {}
|
||||
|
@ -246,7 +249,8 @@ class ApicExtensionDriver(api_plus.ExtensionDriver,
|
|||
cisco_apic.EXTRA_CONSUMED_CONTRACTS,
|
||||
cisco_apic.EPG_CONTRACT_MASTERS,
|
||||
cisco_apic.POLICY_ENFORCEMENT_PREF,
|
||||
cisco_apic.NO_NAT_CIDRS]
|
||||
cisco_apic.NO_NAT_CIDRS,
|
||||
cisco_apic.MULTI_EXT_NETS]
|
||||
for e_k in ext_keys:
|
||||
if e_k in data:
|
||||
res_dict.update({e_k: data[e_k]})
|
||||
|
|
|
@ -809,6 +809,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
aim_ctx = aim_context.AimContext(session)
|
||||
|
||||
is_ext = self._is_external(current)
|
||||
multi_ext_nets_enb = self._is_multi_ext_nets_enabled(current)
|
||||
wanted_epg_name = current['id'] if multi_ext_nets_enb else None
|
||||
is_svi = self._is_svi(current)
|
||||
|
||||
if ((current[cisco_apic.EXTRA_PROVIDED_CONTRACTS] or
|
||||
|
@ -830,17 +832,28 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
l3out, ext_net, ns = self._get_aim_nat_strategy(current)
|
||||
if not ext_net:
|
||||
return # Unmanaged external network
|
||||
|
||||
other_nets = self.get_network_ids_and_multi_by_l3out_dn(
|
||||
session, l3out.dn)
|
||||
other_nets = [value for value in other_nets
|
||||
if value[0] != current['id']]
|
||||
if len(other_nets) > 0 and other_nets[0][1] != multi_ext_nets_enb:
|
||||
raise exceptions.MultiExtNetworkMixing()
|
||||
|
||||
domains = self._get_vmm_domains(aim_ctx, ns)
|
||||
ns.create_l3outside(aim_ctx, l3out, vmm_domains=domains)
|
||||
ns.create_external_network(aim_ctx, ext_net)
|
||||
ns.create_l3outside(aim_ctx, l3out, vmm_domains=domains,
|
||||
epg_name=wanted_epg_name)
|
||||
ns.create_external_network(aim_ctx, ext_net,
|
||||
epg_name=wanted_epg_name)
|
||||
# Get external CIDRs for all external networks that share
|
||||
# this APIC external network.
|
||||
cidrs = sorted(
|
||||
self.get_external_cidrs_by_ext_net_dn(
|
||||
session, ext_net.dn, lock_update=True))
|
||||
session, ext_net.dn))
|
||||
ns.update_external_cidrs(aim_ctx, ext_net, cidrs)
|
||||
|
||||
for resource in ns.get_l3outside_resources(aim_ctx, l3out):
|
||||
for resource in ns.get_l3outside_resources(aim_ctx, l3out,
|
||||
epg_name=wanted_epg_name):
|
||||
if isinstance(resource, aim_resource.BridgeDomain):
|
||||
bd = resource
|
||||
elif isinstance(resource, aim_resource.EndpointGroup):
|
||||
|
@ -1207,21 +1220,33 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
l3out, ext_net, ns = self._get_aim_nat_strategy(current)
|
||||
if not ext_net:
|
||||
return # Unmanaged external network
|
||||
# REVISIT: lock_update=True is needed to handle races. Find
|
||||
# alternative solutions since Neutron discourages using such
|
||||
# queries.
|
||||
other_nets = set(
|
||||
self.get_network_ids_by_ext_net_dn(
|
||||
session, ext_net.dn, lock_update=True))
|
||||
other_nets.discard(current['id'])
|
||||
if not other_nets:
|
||||
ns.delete_external_network(aim_ctx, ext_net)
|
||||
other_nets = set(
|
||||
self.get_network_ids_by_l3out_dn(
|
||||
session, l3out.dn, lock_update=True))
|
||||
other_nets.discard(current['id'])
|
||||
if not other_nets:
|
||||
ns.delete_l3outside(aim_ctx, l3out)
|
||||
multi_ext_nets_enb = self._is_multi_ext_nets_enabled(current)
|
||||
|
||||
if multi_ext_nets_enb:
|
||||
cidrs_to_delete = self.get_external_cidrs_by_net_id(
|
||||
session, current['id'])
|
||||
ns.delete_external_network(aim_ctx, ext_net,
|
||||
epg_name=current['id'],
|
||||
cidrs=cidrs_to_delete)
|
||||
ns.delete_l3outside(aim_ctx, l3out, epg_name=current['id'],
|
||||
cidrs=cidrs_to_delete)
|
||||
else:
|
||||
# REVISIT: lock_update=True is needed to handle races. Find
|
||||
# alternative solutions since Neutron discourages using such
|
||||
# queries.
|
||||
other_nets = set(
|
||||
self.get_network_ids_by_ext_net_dn(
|
||||
session, ext_net.dn, lock_update=True))
|
||||
other_nets.discard(current['id'])
|
||||
if not other_nets:
|
||||
ns.delete_external_network(aim_ctx, ext_net)
|
||||
other_nets = set(
|
||||
self.get_network_ids_by_l3out_dn(
|
||||
session, l3out.dn, lock_update=True))
|
||||
other_nets.discard(current['id'])
|
||||
if not other_nets:
|
||||
ns.delete_l3outside(aim_ctx, l3out)
|
||||
|
||||
elif self._is_svi(current):
|
||||
l3out, ext_net, _ = self._get_aim_external_objects(current)
|
||||
aim_l3out = self.aim.get(aim_ctx, l3out)
|
||||
|
@ -4768,6 +4793,9 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
def _is_bgp_enabled(self, network):
|
||||
return network.get(cisco_apic.BGP)
|
||||
|
||||
def _is_multi_ext_nets_enabled(self, network):
|
||||
return network.get(cisco_apic.MULTI_EXT_NETS)
|
||||
|
||||
def _nat_type_to_strategy(self, nat_type):
|
||||
ns_cls = nat_strategy.DistributedNatStrategy
|
||||
if nat_type == '':
|
||||
|
@ -7130,6 +7158,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
cisco_apic.NESTED_DOMAIN_INFRA_VLAN: None,
|
||||
cisco_apic.NESTED_DOMAIN_SERVICE_VLAN: None,
|
||||
cisco_apic.NESTED_DOMAIN_NODE_NETWORK_VLAN: None,
|
||||
cisco_apic.MULTI_EXT_NETS: False,
|
||||
}
|
||||
if net_db.aim_mapping and net_db.aim_mapping.get(cisco_apic.BD):
|
||||
res_dict.update({cisco_apic.BD: net_db.aim_mapping[cisco_apic.BD]})
|
||||
|
|
|
@ -359,7 +359,8 @@ class ApicAimTestCase(test_address_scope.AddressScopeTestCase,
|
|||
ACTIVE_ACTIVE_AAP, EPG_SUBNET,
|
||||
CIDR, PROV, CONS, SVI,
|
||||
BGP, BGP_TYPE, ASN,
|
||||
'provider:network_type'
|
||||
'provider:network_type',
|
||||
'apic:multi_ext_nets'
|
||||
)
|
||||
self.name_mapper = apic_mapper.APICNameMapper()
|
||||
self.t1_aname = self.name_mapper.project(None, 't1')
|
||||
|
@ -449,7 +450,8 @@ class ApicAimTestCase(test_address_scope.AddressScopeTestCase,
|
|||
self.fmt)
|
||||
return self.deserialize(self.fmt, req.get_response(self.api))
|
||||
|
||||
def _make_ext_network(self, name, dn=None, nat_type=None, cidrs=None):
|
||||
def _make_ext_network(self, name, dn=None, nat_type=None, cidrs=None,
|
||||
multi_ext_nets=False):
|
||||
kwargs = {'router:external': True}
|
||||
if dn:
|
||||
kwargs[DN] = {'ExternalNetwork': dn}
|
||||
|
@ -459,6 +461,8 @@ class ApicAimTestCase(test_address_scope.AddressScopeTestCase,
|
|||
kwargs['apic:nat_type'] = self.nat_type
|
||||
if cidrs:
|
||||
kwargs[CIDR] = cidrs
|
||||
if multi_ext_nets:
|
||||
kwargs['apic:multi_ext_nets'] = True
|
||||
|
||||
return self._make_network(self.fmt, name, True,
|
||||
arg_list=self.extension_attributes,
|
||||
|
@ -4114,8 +4118,10 @@ class TestSyncState(ApicAimTestCase):
|
|||
TestSyncState._mocked_get_statuses):
|
||||
self._test_router('error')
|
||||
|
||||
def _test_external_network(self, expected_state, dn=None, msg=None):
|
||||
net = self._make_ext_network('net1', dn=dn)
|
||||
def _test_external_network(self, expected_state, dn=None, msg=None,
|
||||
multi_ext_nets=True):
|
||||
net = self._make_ext_network('net1', dn=dn,
|
||||
multi_ext_nets=multi_ext_nets)
|
||||
self.assertEqual(expected_state, net['apic:synchronization_state'],
|
||||
msg)
|
||||
net = self._show('networks', net['id'])['network']
|
||||
|
@ -4156,6 +4162,38 @@ class TestSyncState(ApicAimTestCase):
|
|||
dn=self.dn_t1_l1_n1,
|
||||
msg='%s' % a_res)
|
||||
|
||||
def test_external_network_multi_ext_networks(self):
|
||||
ext_net = aim_resource.ExternalNetwork.from_dn(self.dn_t1_l1_n1)
|
||||
ext_net.monitored = True
|
||||
aim_ctx = aim_context.AimContext(self.db_session)
|
||||
self.aim_mgr.create(aim_ctx, ext_net)
|
||||
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status',
|
||||
TestSyncState._get_synced_status):
|
||||
with mock.patch('aim.aim_manager.AimManager.get_statuses',
|
||||
TestSyncState._mocked_get_statuses):
|
||||
self._test_external_network('synced',
|
||||
dn=self.dn_t1_l1_n1,
|
||||
multi_ext_nets=True)
|
||||
|
||||
for expected_status, status_func in [
|
||||
('build', TestSyncState._get_pending_status_for_type),
|
||||
('error', TestSyncState._get_failed_status_for_type)]:
|
||||
for a_res in [aim_resource.ExternalNetwork,
|
||||
aim_resource.EndpointGroup,
|
||||
aim_resource.BridgeDomain,
|
||||
aim_resource.VRF]:
|
||||
def get_status(self, context, resource, create_if_absent=True):
|
||||
return status_func(context, resource, a_res)
|
||||
with mock.patch('aim.aim_manager.AimManager.get_status',
|
||||
get_status):
|
||||
with mock.patch('aim.aim_manager.AimManager.get_statuses',
|
||||
TestSyncState._mocked_get_statuses):
|
||||
self._test_external_network(expected_status,
|
||||
dn=self.dn_t1_l1_n1,
|
||||
msg='%s' % a_res,
|
||||
multi_ext_nets=True)
|
||||
|
||||
def test_unmanaged_external_network(self):
|
||||
self._test_external_network('build')
|
||||
|
||||
|
@ -7262,6 +7300,94 @@ class TestExtensionAttributes(ApicAimTestCase):
|
|||
self.assertFalse(extn.get_network_extn_db(session, net1['id']))
|
||||
self.assertFalse(extn.get_network_extn_db(session, net2['id']))
|
||||
|
||||
def test_external_network_with_multi_nets_lifecycle(self):
|
||||
session = db_api.get_reader_session()
|
||||
extn = extn_db.ExtensionDbMixin()
|
||||
|
||||
# create with APIC DN, nat_typeand default CIDR
|
||||
net1 = self._make_ext_network('net1',
|
||||
dn=self.dn_t1_l1_n1,
|
||||
nat_type='',
|
||||
multi_ext_nets=True)
|
||||
|
||||
self.assertEqual(self.dn_t1_l1_n1,
|
||||
net1[DN]['ExternalNetwork'])
|
||||
self.assertEqual('', net1['apic:nat_type'])
|
||||
self.assertEqual(['0.0.0.0/0'], net1[CIDR])
|
||||
|
||||
net1 = self._list(
|
||||
'networks', query_params=('id=%s' % net1['id']))['networks'][0]
|
||||
self.assertEqual(self.dn_t1_l1_n1,
|
||||
net1[DN]['ExternalNetwork'])
|
||||
self.assertEqual('', net1['apic:nat_type'])
|
||||
self.assertEqual(['0.0.0.0/0'], net1[CIDR])
|
||||
|
||||
# create with nat_type set to default, and CIDR specified
|
||||
net2 = self._make_ext_network('net2',
|
||||
dn=self.dn_t1_l2_n2,
|
||||
cidrs=['5.5.5.0/24', '10.20.0.0/16'],
|
||||
multi_ext_nets=True)
|
||||
self.assertEqual('distributed', net2['apic:nat_type'])
|
||||
self.assertEqual(['10.20.0.0/16', '5.5.5.0/24'],
|
||||
sorted(net2[CIDR]))
|
||||
|
||||
net2 = self._list(
|
||||
'networks', query_params=('id=%s' % net2['id']))['networks'][0]
|
||||
self.assertEqual('distributed', net2['apic:nat_type'])
|
||||
self.assertEqual(['10.20.0.0/16', '5.5.5.0/24'],
|
||||
sorted(net2[CIDR]))
|
||||
|
||||
# update CIDR
|
||||
net2 = self._update('networks', net2['id'],
|
||||
{'network': {CIDR: ['20.20.30.0/24']}})['network']
|
||||
self.assertEqual('distributed', net2['apic:nat_type'])
|
||||
self.assertEqual(['20.20.30.0/24'], net2[CIDR])
|
||||
|
||||
net2 = self._list(
|
||||
'networks', query_params=('id=%s' % net2['id']))['networks'][0]
|
||||
self.assertEqual('distributed', net2['apic:nat_type'])
|
||||
self.assertEqual(['20.20.30.0/24'], net2[CIDR])
|
||||
|
||||
net2 = self._update('networks', net2['id'],
|
||||
{'network': {CIDR: []}})['network']
|
||||
self.assertEqual([], net2[CIDR])
|
||||
|
||||
net2 = self._list(
|
||||
'networks', query_params=('id=%s' % net2['id']))['networks'][0]
|
||||
self.assertEqual([], net2[CIDR])
|
||||
|
||||
# create without APIC DN -> this is an unmanaged network
|
||||
net3 = self._make_ext_network('net3')
|
||||
self.assertTrue(DN not in net3 or 'ExternalNetwork' not in net3[DN])
|
||||
self.assertFalse('apic:nat_type' in net3)
|
||||
self.assertFalse(CIDR in net3)
|
||||
|
||||
net3 = self._list(
|
||||
'networks', query_params=('id=%s' % net3['id']))['networks'][0]
|
||||
self.assertTrue(DN not in net3 or 'ExternalNetwork' not in net3[DN])
|
||||
self.assertFalse('apic:nat_type' in net3)
|
||||
self.assertFalse(CIDR in net3)
|
||||
|
||||
# updating CIDR of unmanaged network is no-op
|
||||
net3 = self._update('networks', net3['id'],
|
||||
{'network': {CIDR: ['30.30.20.0/24']}})['network']
|
||||
self.assertTrue(DN not in net3 or 'ExternalNetwork' not in net3[DN])
|
||||
self.assertFalse('apic:nat_type' in net3)
|
||||
self.assertFalse(CIDR in net3)
|
||||
|
||||
net3 = self._list(
|
||||
'networks', query_params=('id=%s' % net3['id']))['networks'][0]
|
||||
self.assertTrue(DN not in net3 or 'ExternalNetwork' not in net3[DN])
|
||||
self.assertFalse('apic:nat_type' in net3)
|
||||
self.assertFalse(CIDR in net3)
|
||||
|
||||
# delete the external networks
|
||||
self._delete('networks', net2['id'])
|
||||
self._delete('networks', net1['id'])
|
||||
|
||||
self.assertFalse(extn.get_network_extn_db(session, net1['id']))
|
||||
self.assertFalse(extn.get_network_extn_db(session, net2['id']))
|
||||
|
||||
def test_external_network_fail(self):
|
||||
# APIC DN not specified
|
||||
resp = self._create_network(self.fmt, 'net1', True,
|
||||
|
@ -8033,11 +8159,11 @@ class TestExternalConnectivityBase(object):
|
|||
self.mock_ns.create_l3outside.assert_called_once_with(
|
||||
mock.ANY,
|
||||
aim_resource.L3Outside(tenant_name=self.t1_aname, name='l1'),
|
||||
vmm_domains=[])
|
||||
vmm_domains=[], epg_name=None)
|
||||
a_ext_net = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, epg_name=None)
|
||||
self.mock_ns.update_external_cidrs.assert_called_once_with(
|
||||
mock.ANY, a_ext_net, ['20.10.0.0/16', '4.4.4.0/24'])
|
||||
ext_epg = aim_resource.EndpointGroup(
|
||||
|
@ -8086,7 +8212,7 @@ class TestExternalConnectivityBase(object):
|
|||
self._make_ext_network('net2',
|
||||
dn=self.dn_t1_l1_n1)
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, epg_name=None)
|
||||
self.mock_ns.update_external_cidrs.assert_called_once_with(
|
||||
mock.ANY, a_ext_net, ['0.0.0.0/0'])
|
||||
self._validate()
|
||||
|
@ -9161,11 +9287,11 @@ class TestExternalConnectivityBase(object):
|
|||
self.mock_ns.create_l3outside.assert_called_once_with(
|
||||
mock.ANY,
|
||||
aim_resource.L3Outside(tenant_name=self.t1_aname, name='l1'),
|
||||
vmm_domains=vmm_domains)
|
||||
vmm_domains=vmm_domains, epg_name=None)
|
||||
a_ext_net = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, epg_name=None)
|
||||
self.mock_ns.update_external_cidrs.assert_called_once_with(
|
||||
mock.ANY, a_ext_net, ['20.10.0.0/16', '4.4.4.0/24'])
|
||||
ext_epg = self.aim_mgr.find(aim_ctx, aim_resource.EndpointGroup,
|
||||
|
@ -9214,17 +9340,17 @@ class TestExternalConnectivityBase(object):
|
|||
a_ext_net = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1')
|
||||
self.mock_ns.create_l3outside.assert_called_once_with(
|
||||
mock.ANY, a_l3out, vmm_domains=[])
|
||||
mock.ANY, a_l3out, vmm_domains=[], epg_name=None)
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, epg_name=None)
|
||||
|
||||
# create second network that shares APIC l3out and external-network
|
||||
self.mock_ns.reset_mock()
|
||||
net2 = self._make_ext_network('net2', dn=self.dn_t1_l1_n1)
|
||||
self.mock_ns.create_l3outside.assert_called_once_with(
|
||||
mock.ANY, a_l3out, vmm_domains=[])
|
||||
mock.ANY, a_l3out, vmm_domains=[], epg_name=None)
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, epg_name=None)
|
||||
|
||||
# create third network that shares APIC l3out only
|
||||
self.mock_ns.reset_mock()
|
||||
|
@ -9233,9 +9359,9 @@ class TestExternalConnectivityBase(object):
|
|||
a_ext_net3 = aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n2')
|
||||
self.mock_ns.create_l3outside.assert_called_once_with(
|
||||
mock.ANY, a_l3out, vmm_domains=[])
|
||||
mock.ANY, a_l3out, vmm_domains=[], epg_name=None)
|
||||
self.mock_ns.create_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net3)
|
||||
mock.ANY, a_ext_net3, epg_name=None)
|
||||
|
||||
# delete net2
|
||||
self.mock_ns.reset_mock()
|
||||
|
|
Loading…
Reference in New Issue