Pre-existing SVI networks can not use the same L3out

Each SVI network will have its own vlan so it doesn't make sense to do so.
In this patch it will prevent another pre-existing SVI network to be created
if the L3out is already used by another pre-existing SVI network.

Change-Id: I9cf6fcde284325acbc94c0fdc3b0f823ff888446
This commit is contained in:
Kent Wu 2018-03-01 14:43:25 -08:00
parent 93087d4e5e
commit 3309deadb3
4 changed files with 37 additions and 2 deletions

View File

@ -60,6 +60,11 @@ class PreExistingSVICannotBeConnectedToRouter(exceptions.BadRequest):
"be connected to a router.")
class PreExistingSVICannotUseSameL3out(exceptions.BadRequest):
message = _("Can not create a SVI network with pre-existing l3out "
"if that l3out has been used by another SVI network.")
class OnlyOneSubnetInSVINetwork(exceptions.BadRequest):
message = _("Only one subnet is allowed in SVI network.")

View File

@ -17,6 +17,7 @@ from neutron.db import models_v2
from neutron_lib.db import model_base
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.sql.expression import true
from gbpservice.neutron.extensions import cisco_apic
from gbpservice.neutron.extensions import cisco_apic_l3
@ -140,6 +141,14 @@ class ExtensionDbMixin(object):
ids = ids.with_lockmode('update')
return [i[0] for i in ids]
def get_svi_network_ids_by_l3out_dn(self, session, dn, lock_update=False):
ids = session.query(NetworkExtensionDb.network_id).filter(
NetworkExtensionDb.external_network_dn.like(dn + "/%"),
NetworkExtensionDb.svi == true())
if lock_update:
ids = ids.with_lockmode('update')
return [i[0] for i in ids]
def get_external_cidrs_by_ext_net_dn(self, session, dn, lock_update=False):
ctab = NetworkExtensionCidrDb
ntab = NetworkExtensionDb

View File

@ -499,10 +499,18 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
elif isinstance(resource, aim_resource.VRF):
vrf = resource
elif self._is_svi(current):
_, ext_net, _ = self._get_aim_external_objects(current)
l3out, ext_net, _ = self._get_aim_external_objects(current)
if ext_net:
extn_db = extension_db.ExtensionDbMixin()
other_nets = set(
extn_db.get_svi_network_ids_by_l3out_dn(session, l3out.dn,
lock_update=True))
other_nets.discard(current['id'])
if other_nets:
raise exceptions.PreExistingSVICannotUseSameL3out()
# This means no DN is being provided. Then we should try to create
# the l3out automatically
if not ext_net:
else:
tenant_aname = self.name_mapper.project(session,
current['tenant_id'])
vrf = self._map_unrouted_vrf()

View File

@ -1379,6 +1379,19 @@ class TestAimMapping(ApicAimTestCase):
n_context.get_admin_context(), router_id,
{'subnet_id': subnet1_id})
def test_preexist_svi_can_not_use_same_l3out(self):
self._make_network(
self.fmt, 'net1', True, arg_list=self.extension_attributes,
**{'apic:svi': 'True',
DN: {'ExternalNetwork': self.dn_t1_l1_n1}})
# Create another SVI network with same l3out should fail.
self.assertRaises(webob.exc.HTTPClientError, self._make_network,
self.fmt, 'net2', True,
arg_list=self.extension_attributes,
**{'apic:svi': 'True',
DN: {'ExternalNetwork': self.dn_t1_l1_n1}})
def test_only_one_subnet_allowed_in_svi(self):
# Create network.
net_resp = self._make_network(