Handle the upgrade case for networks created before the SVI patch

Need to consider the case that networks created before the SVI patch
may not have the NetworkExtensionDb record created.

Change-Id: Ia548439b2d1b6d466cdcdd04eb46b2c57f93f3ab
This commit is contained in:
Kent Wu 2018-02-26 18:03:34 -08:00
parent 6cd5a90860
commit d75ce445e7
3 changed files with 90 additions and 14 deletions

View File

@ -0,0 +1,65 @@
# 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.
#
"""network_migration_for_svi
Revision ID: 1c564e737f9f
Revises: 804d991a3564
Create Date: 2018-02-27 00:00:00.000000
"""
# revision identifiers, used by Alembic.
revision = '1c564e737f9f'
down_revision = '804d991a3564'
from alembic import op
from alembic import util
from neutron.db import models_v2
import sqlalchemy as sa
from sqlalchemy.orm import lazyload
NetworkExtensionDb = sa.Table(
'apic_aim_network_extensions', sa.MetaData(),
sa.Column('network_id', sa.String(36), nullable=False),
sa.Column('external_network_dn', sa.String(1024)),
sa.Column('nat_type', sa.Enum('distributed', 'edge', '')),
sa.Column('svi', sa.Boolean),
sa.Column('bgp_enable', sa.Boolean,
server_default=sa.false(), nullable=False),
sa.Column('bgp_type', sa.Enum('default_export', ''),
server_default="default_export", nullable=False),
sa.Column('bgp_asn', sa.String(64),
server_default="0", nullable=False))
def upgrade():
session = sa.orm.Session(bind=op.get_bind(), autocommit=True)
with session.begin(subtransactions=True):
# Migrate networks.
net_dbs = (session.query(models_v2.Network)
.options(lazyload('*')).all())
for net_db in net_dbs:
util.msg("Migrating network: %s" % net_db)
# If this update is successful then it means its an external
# network with its DN set.
res = session.execute(NetworkExtensionDb.update().values(
svi=False).where(NetworkExtensionDb.c.network_id == net_db.id))
if res.rowcount == 0:
session.execute(NetworkExtensionDb.insert().values(
network_id=net_db.id, svi=False))
def downgrade():
pass

View File

@ -1 +1 @@
804d991a3564
1c564e737f9f

View File

@ -768,8 +768,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
sync_state = self._merge_status(aim_ctx, sync_state, vrf)
# SVI network with pre-existing l3out.
if (network_db.aim_extension_mapping.svi and
network_db.aim_extension_mapping.external_network_dn):
if self._is_preexisting_svi_db(network_db):
_, ext_net, _ = self._get_aim_external_stuff_db(session,
network_db)
if ext_net:
@ -818,7 +817,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# Limit 1 subnet per SVI network as each SVI interface
# in ACI can only have 1 primary addr
if network_db.aim_extension_mapping.svi:
if self._is_svi_db(network_db):
subnets_size = (session.query(models_v2.Subnet)
.filter(models_v2.Subnet.network_id == network_id)
.count())
@ -1270,8 +1269,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# SVI network with pre-existing l3out is not allowed to be
# connected to a router at this moment
if (network_db.aim_extension_mapping.svi and
network_db.aim_extension_mapping.external_network_dn):
if self._is_preexisting_svi_db(network_db):
raise exceptions.PreExistingSVICannotBeConnectedToRouter()
# Find the address_scope(s) for the new interface.
@ -1471,7 +1469,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# If external-gateway is set, handle external-connectivity changes.
# External network is not supported for SVI network for now.
if router.gw_port_id and not network_db.aim_extension_mapping.svi:
if router.gw_port_id and not self._is_svi_db(network_db):
net = self.plugin.get_network(context,
router.gw_port.network_id)
# If this is first interface-port, then that will determine
@ -1614,7 +1612,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# If external-gateway is set, handle external-connectivity changes.
# External network is not supproted for SVI network for now.
if router_db.gw_port_id and not network_db.aim_extension_mapping.svi:
if router_db.gw_port_id and not self._is_svi_db(network_db):
net = self.plugin.get_network(context,
router_db.gw_port.network_id)
# If this was the last interface for this VRF for this
@ -2322,7 +2320,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# NOTE: Must only be called for networks that are not yet
# attached to any router.
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
bd = self._get_network_bd(network_db.aim_mapping)
epg = self._get_network_epg(network_db.aim_mapping)
tenant_name = bd.tenant_name
@ -2336,7 +2334,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# sure routing is enabled.
LOG.debug("Moving network from tenant %(old)s to tenant %(new)s",
{'old': tenant_name, 'new': new_vrf.tenant_name})
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
bd = self.aim.get(aim_ctx, bd)
self.aim.delete(aim_ctx, bd)
bd.tenant_name = new_vrf.tenant_name
@ -2371,7 +2369,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
self.aim.delete(aim_ctx, old_l3out)
else:
# Just set VRF and enable routing.
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
bd = self.aim.update(aim_ctx, bd, enable_routing=True,
vrf_name=new_vrf.name)
else:
@ -2385,7 +2383,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
# Tenants have changed.
nets_to_notify.add(network_db.id)
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
return bd, epg
else:
ext_net = self._get_network_l3out_ext_net(network_db.aim_mapping)
@ -2412,7 +2410,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
LOG.debug("Moving network from tenant %(old)s to tenant %(new)s",
{'old': old_vrf.tenant_name, 'new': new_tenant_name})
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
bd = self._get_network_bd(network_db.aim_mapping)
bd = self.aim.get(aim_ctx, bd)
self.aim.delete(aim_ctx, bd)
@ -2445,7 +2443,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
self.aim.delete(aim_ctx, old_l3out)
else:
# Just set unrouted VRF and disable routing.
if not network_db.aim_extension_mapping.svi:
if not self._is_svi_db(network_db):
bd = self._get_network_bd(network_db.aim_mapping)
bd = self.aim.update(aim_ctx, bd, enable_routing=False,
vrf_name=new_vrf.name)
@ -2797,6 +2795,19 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
def _is_svi(self, network):
return network.get(cisco_apic.SVI)
def _is_svi_db(self, network_db):
if (network_db.aim_extension_mapping and
network_db.aim_extension_mapping.svi):
return True
return False
def _is_preexisting_svi_db(self, network_db):
if (network_db.aim_extension_mapping and
network_db.aim_extension_mapping.svi and
network_db.aim_extension_mapping.external_network_dn):
return True
return False
def _is_bgp_enabled(self, network):
return network.get(cisco_apic.BGP)