Multi External Network Coexisting
Support for having networks with and without the multi_ext_nets extension
to share the same L3Outside.
Change-Id: Ia2daff31059437ed83813d93d98865131f2919b5
(cherry picked from commit 4f5f8aa66f
)
This commit is contained in:
parent
807b8fb07e
commit
14299b08dd
|
@ -153,8 +153,3 @@ 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. ")
|
||||
|
|
|
@ -448,6 +448,18 @@ class ExtensionDbMixin(object):
|
|||
|
||||
return [i[0] for i in ids]
|
||||
|
||||
def get_network_ids_by_l3out_dn_filter_multi(self, session, dn,
|
||||
wanted_multi_val=False):
|
||||
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 = query(session).params(dn=dn)
|
||||
|
||||
return [i[0] for i in ids if i[1] is wanted_multi_val]
|
||||
|
||||
def get_svi_network_ids_by_l3out_dn(self, session, dn, lock_update=False):
|
||||
query = BAKERY(lambda s: s.query(
|
||||
NetworkExtensionDb.network_id))
|
||||
|
|
|
@ -823,14 +823,6 @@ 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,
|
||||
epg_name=wanted_epg_name)
|
||||
|
@ -1225,18 +1217,22 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
|||
# REVISIT: lock_update=True is needed to handle races. Find
|
||||
# alternative solutions since Neutron discourages using such
|
||||
# queries.
|
||||
cidrs_to_delete = self.get_external_cidrs_by_net_id(
|
||||
session, current['id'])
|
||||
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)
|
||||
ns.delete_external_network(aim_ctx, ext_net,
|
||||
cidrs=cidrs_to_delete)
|
||||
other_nets = set(
|
||||
self.get_network_ids_by_l3out_dn(
|
||||
session, l3out.dn, lock_update=True))
|
||||
self.get_network_ids_by_l3out_dn_filter_multi(
|
||||
session, l3out.dn, False))
|
||||
other_nets.discard(current['id'])
|
||||
if not other_nets:
|
||||
ns.delete_l3outside(aim_ctx, l3out)
|
||||
ns.delete_l3outside(aim_ctx, l3out,
|
||||
cidrs=cidrs_to_delete)
|
||||
|
||||
elif self._is_svi(current):
|
||||
l3out, ext_net, _ = self._get_aim_external_objects(current)
|
||||
|
|
|
@ -8079,11 +8079,13 @@ class TestExternalConnectivityBase(object):
|
|||
self._delete('networks', net1['id'])
|
||||
self.mock_ns.delete_l3outside.assert_called_once_with(
|
||||
mock.ANY,
|
||||
aim_resource.L3Outside(tenant_name=self.t1_aname, name='l1'))
|
||||
aim_resource.L3Outside(tenant_name=self.t1_aname, name='l1'),
|
||||
cidrs=['33.33.33.0/30'])
|
||||
self.mock_ns.delete_external_network.assert_called_once_with(
|
||||
mock.ANY,
|
||||
aim_resource.ExternalNetwork(
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1'))
|
||||
tenant_name=self.t1_aname, l3out_name='l1', name='n1'),
|
||||
cidrs=['33.33.33.0/30'])
|
||||
|
||||
# create with default CIDR
|
||||
self.mock_ns.reset_mock()
|
||||
|
@ -9249,15 +9251,15 @@ class TestExternalConnectivityBase(object):
|
|||
self._delete('networks', net1['id'])
|
||||
self.mock_ns.delete_l3outside.assert_not_called()
|
||||
self.mock_ns.delete_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net)
|
||||
mock.ANY, a_ext_net, cidrs=['0.0.0.0/0'])
|
||||
|
||||
# delete net3
|
||||
self.mock_ns.reset_mock()
|
||||
self._delete('networks', net3['id'])
|
||||
self.mock_ns.delete_l3outside.assert_called_once_with(
|
||||
mock.ANY, a_l3out)
|
||||
mock.ANY, a_l3out, cidrs=['0.0.0.0/0'])
|
||||
self.mock_ns.delete_external_network.assert_called_once_with(
|
||||
mock.ANY, a_ext_net3)
|
||||
mock.ANY, a_ext_net3, cidrs=['0.0.0.0/0'])
|
||||
|
||||
def test_shared_l3out_external_subnet_overlap(self):
|
||||
net1 = self._make_ext_network('net1', dn=self.dn_t1_l1_n1)
|
||||
|
|
Loading…
Reference in New Issue