Merge "Send VRF notifications"
This commit is contained in:
commit
5a9991f18f
|
@ -1023,9 +1023,29 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
if subnets_size > 1:
|
if subnets_size > 1:
|
||||||
raise exceptions.OnlyOneSubnetInSVINetwork()
|
raise exceptions.OnlyOneSubnetInSVINetwork()
|
||||||
|
|
||||||
|
if network_db.aim_mapping:
|
||||||
|
# Provide VRF notifications if creating subnets in
|
||||||
|
# unscoped networks.
|
||||||
|
# REVISIT: We may need to handle VRF notifications for
|
||||||
|
# external networks as well.
|
||||||
|
vrf = self._get_network_vrf(network_db.aim_mapping)
|
||||||
|
if (vrf and (self._is_unrouted_vrf(vrf) or
|
||||||
|
self._is_default_vrf(vrf))
|
||||||
|
and not network_db.external):
|
||||||
|
vrfs_to_notify = self._add_vrf_notification(vrf)
|
||||||
|
self._notify_vrf_update(context._plugin_context,
|
||||||
|
vrfs_to_notify)
|
||||||
|
|
||||||
# Neutron subnets in non-external networks are mapped to AIM
|
# Neutron subnets in non-external networks are mapped to AIM
|
||||||
# Subnets as they are added to routers as interfaces.
|
# Subnets as they are added to routers as interfaces.
|
||||||
|
|
||||||
|
def _is_unrouted_vrf(self, vrf):
|
||||||
|
return (vrf.tenant_name == COMMON_TENANT_NAME and
|
||||||
|
vrf.name == self.apic_system_id + '_' + UNROUTED_VRF_NAME)
|
||||||
|
|
||||||
|
def _is_default_vrf(self, vrf):
|
||||||
|
return vrf.name == DEFAULT_VRF_NAME
|
||||||
|
|
||||||
def update_subnet_precommit(self, context):
|
def update_subnet_precommit(self, context):
|
||||||
current = context.current
|
current = context.current
|
||||||
original = context.original
|
original = context.original
|
||||||
|
@ -1097,6 +1117,19 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
ns.delete_subnet(aim_ctx, l3out,
|
ns.delete_subnet(aim_ctx, l3out,
|
||||||
self._subnet_to_gw_ip_mask(current))
|
self._subnet_to_gw_ip_mask(current))
|
||||||
|
|
||||||
|
if network_db.aim_mapping:
|
||||||
|
# Provide VRF notifications if deleting subnets from
|
||||||
|
# unscoped networks.
|
||||||
|
# REVISIT: We may need to handle VRF notifications for
|
||||||
|
# external networks as well.
|
||||||
|
vrf = self._get_network_vrf(network_db.aim_mapping)
|
||||||
|
if (vrf and (self._is_unrouted_vrf(vrf) or
|
||||||
|
self._is_default_vrf(vrf))
|
||||||
|
and not network_db.external):
|
||||||
|
vrfs_to_notify = self._add_vrf_notification(vrf)
|
||||||
|
self._notify_vrf_update(context._plugin_context,
|
||||||
|
vrfs_to_notify)
|
||||||
|
|
||||||
# Non-external neutron subnets are unmapped from AIM Subnets as
|
# Non-external neutron subnets are unmapped from AIM Subnets as
|
||||||
# they are removed from routers.
|
# they are removed from routers.
|
||||||
|
|
||||||
|
@ -1166,6 +1199,20 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
|
|
||||||
self.extend_subnet_dict_bulk(session, [(result, subnet_db)])
|
self.extend_subnet_dict_bulk(session, [(result, subnet_db)])
|
||||||
|
|
||||||
|
def _notify_vrf_for_scope(self, context):
|
||||||
|
session = context._plugin_context.session
|
||||||
|
scope_id = context.current['address_scope_id']
|
||||||
|
mapping = self._get_address_scope_mapping(session, scope_id)
|
||||||
|
if mapping:
|
||||||
|
vrf = self._get_address_scope_vrf(mapping)
|
||||||
|
if vrf:
|
||||||
|
vrfs_to_notify = self._add_vrf_notification(vrf)
|
||||||
|
self._notify_vrf_update(context._plugin_context,
|
||||||
|
vrfs_to_notify)
|
||||||
|
|
||||||
|
def create_subnetpool_precommit(self, context):
|
||||||
|
self._notify_vrf_for_scope(context)
|
||||||
|
|
||||||
def update_subnetpool_precommit(self, context):
|
def update_subnetpool_precommit(self, context):
|
||||||
current = context.current
|
current = context.current
|
||||||
original = context.original
|
original = context.original
|
||||||
|
@ -1216,6 +1263,14 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
# just reject the update.
|
# just reject the update.
|
||||||
raise exceptions.ScopeUpdateNotSupported()
|
raise exceptions.ScopeUpdateNotSupported()
|
||||||
|
|
||||||
|
current_prefixes = set(current['prefixes'])
|
||||||
|
original_prefixes = set(original['prefixes'])
|
||||||
|
if current_scope_id and current_prefixes != original_prefixes:
|
||||||
|
self._notify_vrf_for_scope(context)
|
||||||
|
|
||||||
|
def delete_subnetpool_precommit(self, context):
|
||||||
|
self._notify_vrf_for_scope(context)
|
||||||
|
|
||||||
def create_address_scope_precommit(self, context):
|
def create_address_scope_precommit(self, context):
|
||||||
current = context.current
|
current = context.current
|
||||||
LOG.debug("APIC AIM MD creating address scope: %s", current)
|
LOG.debug("APIC AIM MD creating address scope: %s", current)
|
||||||
|
@ -1637,6 +1692,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
raise exceptions.NonIsomorphicNetworkRoutingUnsupported()
|
raise exceptions.NonIsomorphicNetworkRoutingUnsupported()
|
||||||
|
|
||||||
nets_to_notify = set()
|
nets_to_notify = set()
|
||||||
|
vrfs_to_notify = set()
|
||||||
ports_to_notify = set()
|
ports_to_notify = set()
|
||||||
router_topo_moved = False
|
router_topo_moved = False
|
||||||
|
|
||||||
|
@ -1677,7 +1733,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
vrf = self._ensure_default_vrf(aim_ctx, intf_vrf)
|
vrf = self._ensure_default_vrf(aim_ctx, intf_vrf)
|
||||||
self._move_topology(
|
self._move_topology(
|
||||||
context, aim_ctx, router_topology, router_vrf, vrf,
|
context, aim_ctx, router_topology, router_vrf, vrf,
|
||||||
nets_to_notify)
|
nets_to_notify, vrfs_to_notify)
|
||||||
router_topo_moved = True
|
router_topo_moved = True
|
||||||
self._cleanup_default_vrf(aim_ctx, router_vrf)
|
self._cleanup_default_vrf(aim_ctx, router_vrf)
|
||||||
elif router_shared_net:
|
elif router_shared_net:
|
||||||
|
@ -1688,7 +1744,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
if net_intfs:
|
if net_intfs:
|
||||||
self._move_topology(
|
self._move_topology(
|
||||||
context, aim_ctx, intf_topology, intf_vrf, vrf,
|
context, aim_ctx, intf_topology, intf_vrf, vrf,
|
||||||
nets_to_notify)
|
nets_to_notify, vrfs_to_notify)
|
||||||
self._cleanup_default_vrf(aim_ctx, intf_vrf)
|
self._cleanup_default_vrf(aim_ctx, intf_vrf)
|
||||||
else:
|
else:
|
||||||
# This should never happen.
|
# This should never happen.
|
||||||
|
@ -1708,10 +1764,12 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
# First interface for network.
|
# First interface for network.
|
||||||
if network_db.aim_mapping.epg_name:
|
if network_db.aim_mapping.epg_name:
|
||||||
bd, epg = self._associate_network_with_vrf(
|
bd, epg = self._associate_network_with_vrf(
|
||||||
context, aim_ctx, network_db, vrf, nets_to_notify)
|
context, aim_ctx, network_db, vrf, nets_to_notify,
|
||||||
|
scope_id, vrfs_to_notify)
|
||||||
elif network_db.aim_mapping.l3out_name:
|
elif network_db.aim_mapping.l3out_name:
|
||||||
l3out, epg = self._associate_network_with_vrf(
|
l3out, epg = self._associate_network_with_vrf(
|
||||||
context, aim_ctx, network_db, vrf, nets_to_notify)
|
context, aim_ctx, network_db, vrf, nets_to_notify,
|
||||||
|
scope_id, vrfs_to_notify)
|
||||||
else:
|
else:
|
||||||
# Network is already routed.
|
# Network is already routed.
|
||||||
#
|
#
|
||||||
|
@ -1795,6 +1853,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
ports_to_notify.update(port_ids)
|
ports_to_notify.update(port_ids)
|
||||||
if ports_to_notify:
|
if ports_to_notify:
|
||||||
self._notify_port_update_bulk(context, ports_to_notify)
|
self._notify_port_update_bulk(context, ports_to_notify)
|
||||||
|
if vrfs_to_notify:
|
||||||
|
self._notify_vrf_update(context, vrfs_to_notify)
|
||||||
|
|
||||||
def remove_router_interface(self, context, router_id, port, subnets):
|
def remove_router_interface(self, context, router_id, port, subnets):
|
||||||
LOG.debug("APIC AIM MD removing subnets %(subnets)s from router "
|
LOG.debug("APIC AIM MD removing subnets %(subnets)s from router "
|
||||||
|
@ -1867,6 +1927,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
provided_contract_names=contracts)
|
provided_contract_names=contracts)
|
||||||
|
|
||||||
nets_to_notify = set()
|
nets_to_notify = set()
|
||||||
|
vrfs_to_notify = set()
|
||||||
ports_to_notify = set()
|
ports_to_notify = set()
|
||||||
router_topo_moved = False
|
router_topo_moved = False
|
||||||
|
|
||||||
|
@ -1888,7 +1949,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
intf_vrf = self._ensure_default_vrf(aim_ctx, intf_vrf)
|
intf_vrf = self._ensure_default_vrf(aim_ctx, intf_vrf)
|
||||||
self._move_topology(
|
self._move_topology(
|
||||||
context, aim_ctx, intf_topology, old_vrf, intf_vrf,
|
context, aim_ctx, intf_topology, old_vrf, intf_vrf,
|
||||||
nets_to_notify)
|
nets_to_notify, vrfs_to_notify)
|
||||||
|
|
||||||
# See if the router's topology must be moved.
|
# See if the router's topology must be moved.
|
||||||
router_topology = self._router_topology(session, router_db.id)
|
router_topology = self._router_topology(session, router_db.id)
|
||||||
|
@ -1901,14 +1962,15 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
router_vrf = self._ensure_default_vrf(aim_ctx, router_vrf)
|
router_vrf = self._ensure_default_vrf(aim_ctx, router_vrf)
|
||||||
self._move_topology(
|
self._move_topology(
|
||||||
context, aim_ctx, router_topology, old_vrf, router_vrf,
|
context, aim_ctx, router_topology, old_vrf, router_vrf,
|
||||||
nets_to_notify)
|
nets_to_notify, vrfs_to_notify)
|
||||||
router_topo_moved = True
|
router_topo_moved = True
|
||||||
|
|
||||||
# If network is no longer connected to any router, make the
|
# If network is no longer connected to any router, make the
|
||||||
# network's BD unrouted.
|
# network's BD unrouted.
|
||||||
if not router_ids:
|
if not router_ids:
|
||||||
self._dissassociate_network_from_vrf(
|
self._dissassociate_network_from_vrf(
|
||||||
context, aim_ctx, network_db, old_vrf, nets_to_notify)
|
context, aim_ctx, network_db, old_vrf, nets_to_notify,
|
||||||
|
scope_id, vrfs_to_notify)
|
||||||
if scope_id == NO_ADDR_SCOPE:
|
if scope_id == NO_ADDR_SCOPE:
|
||||||
self._cleanup_default_vrf(aim_ctx, old_vrf)
|
self._cleanup_default_vrf(aim_ctx, old_vrf)
|
||||||
|
|
||||||
|
@ -1957,6 +2019,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
ports_to_notify.update(port_ids)
|
ports_to_notify.update(port_ids)
|
||||||
if ports_to_notify:
|
if ports_to_notify:
|
||||||
self._notify_port_update_bulk(context, ports_to_notify)
|
self._notify_port_update_bulk(context, ports_to_notify)
|
||||||
|
if vrfs_to_notify:
|
||||||
|
self._notify_vrf_update(context, vrfs_to_notify)
|
||||||
|
|
||||||
def bind_port(self, context):
|
def bind_port(self, context):
|
||||||
port = context.current
|
port = context.current
|
||||||
|
@ -2745,7 +2809,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
return rtr_dbs
|
return rtr_dbs
|
||||||
|
|
||||||
def _associate_network_with_vrf(self, ctx, aim_ctx, network_db, new_vrf,
|
def _associate_network_with_vrf(self, ctx, aim_ctx, network_db, new_vrf,
|
||||||
nets_to_notify):
|
nets_to_notify, scope_id, vrfs_to_notify):
|
||||||
LOG.debug("Associating previously unrouted network %(net_id)s named "
|
LOG.debug("Associating previously unrouted network %(net_id)s named "
|
||||||
"'%(net_name)s' in project %(net_tenant)s with VRF %(vrf)s",
|
"'%(net_name)s' in project %(net_tenant)s with VRF %(vrf)s",
|
||||||
{'net_id': network_db.id, 'net_name': network_db.name,
|
{'net_id': network_db.id, 'net_name': network_db.name,
|
||||||
|
@ -2817,6 +2881,13 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
# Tenants have changed.
|
# Tenants have changed.
|
||||||
nets_to_notify.add(network_db.id)
|
nets_to_notify.add(network_db.id)
|
||||||
|
|
||||||
|
# Notify VRFs not associated with address_scopes that the
|
||||||
|
# subnet CIDRs within them have changed.
|
||||||
|
old_vrf = self._get_network_vrf(network_db.aim_mapping)
|
||||||
|
if self._is_default_vrf(new_vrf):
|
||||||
|
self._add_vrf_notification(new_vrf, vrfs_to_notify)
|
||||||
|
self._add_vrf_notification(old_vrf, vrfs_to_notify)
|
||||||
|
|
||||||
if not self._is_svi_db(network_db):
|
if not self._is_svi_db(network_db):
|
||||||
return bd, epg
|
return bd, epg
|
||||||
else:
|
else:
|
||||||
|
@ -2824,7 +2895,8 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
return l3out, ext_net
|
return l3out, ext_net
|
||||||
|
|
||||||
def _dissassociate_network_from_vrf(self, ctx, aim_ctx, network_db,
|
def _dissassociate_network_from_vrf(self, ctx, aim_ctx, network_db,
|
||||||
old_vrf, nets_to_notify):
|
old_vrf, nets_to_notify, scope_id,
|
||||||
|
vrfs_to_notify):
|
||||||
LOG.debug("Dissassociating network %(net_id)s named '%(net_name)s' in "
|
LOG.debug("Dissassociating network %(net_id)s named '%(net_name)s' in "
|
||||||
"project %(net_tenant)s from VRF %(vrf)s",
|
"project %(net_tenant)s from VRF %(vrf)s",
|
||||||
{'net_id': network_db.id, 'net_name': network_db.name,
|
{'net_id': network_db.id, 'net_name': network_db.name,
|
||||||
|
@ -2896,8 +2968,20 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
# Tenants have changed.
|
# Tenants have changed.
|
||||||
nets_to_notify.add(network_db.id)
|
nets_to_notify.add(network_db.id)
|
||||||
|
|
||||||
|
# Notify VRFs not associated with address_scopes that the
|
||||||
|
# subnet CIDRs within them have changed
|
||||||
|
if self._is_default_vrf(old_vrf):
|
||||||
|
self._add_vrf_notification(old_vrf, vrfs_to_notify)
|
||||||
|
self._add_vrf_notification(new_vrf, vrfs_to_notify)
|
||||||
|
|
||||||
|
def _add_vrf_notification(self, vrf, vrfs_to_notify=None):
|
||||||
|
vrfs_to_notify = set() if vrfs_to_notify is None else vrfs_to_notify
|
||||||
|
vrf_to_notify = '%s %s' % (vrf.tenant_name, vrf.name)
|
||||||
|
vrfs_to_notify.add(vrf_to_notify)
|
||||||
|
return vrfs_to_notify
|
||||||
|
|
||||||
def _move_topology(self, ctx, aim_ctx, topology, old_vrf, new_vrf,
|
def _move_topology(self, ctx, aim_ctx, topology, old_vrf, new_vrf,
|
||||||
nets_to_notify):
|
nets_to_notify, vrfs_to_notify):
|
||||||
LOG.info("Moving routed networks %(topology)s from VRF "
|
LOG.info("Moving routed networks %(topology)s from VRF "
|
||||||
"%(old_vrf)s to VRF %(new_vrf)s",
|
"%(old_vrf)s to VRF %(new_vrf)s",
|
||||||
{'topology': topology.keys(),
|
{'topology': topology.keys(),
|
||||||
|
@ -2976,6 +3060,9 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
# EPGs' Tenants have changed.
|
# EPGs' Tenants have changed.
|
||||||
nets_to_notify.update(topology.keys())
|
nets_to_notify.update(topology.keys())
|
||||||
|
|
||||||
|
self._add_vrf_notification(old_vrf, vrfs_to_notify)
|
||||||
|
self._add_vrf_notification(new_vrf, vrfs_to_notify)
|
||||||
|
|
||||||
def _router_topology(self, session, router_id):
|
def _router_topology(self, session, router_id):
|
||||||
LOG.debug("Getting topology for router %s", router_id)
|
LOG.debug("Getting topology for router %s", router_id)
|
||||||
visited_networks = {}
|
visited_networks = {}
|
||||||
|
@ -3480,6 +3567,7 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
portbindings.VIF_TYPE_BINDING_FAILED]
|
portbindings.VIF_TYPE_BINDING_FAILED]
|
||||||
|
|
||||||
def _notify_port_update(self, plugin_context, port_id):
|
def _notify_port_update(self, plugin_context, port_id):
|
||||||
|
# REVISIT: Avoid getting the port resource, if possible.
|
||||||
port = self.plugin.get_port(plugin_context.elevated(), port_id)
|
port = self.plugin.get_port(plugin_context.elevated(), port_id)
|
||||||
if self._is_port_bound(port):
|
if self._is_port_bound(port):
|
||||||
LOG.debug("Enqueing notify for port %s", port['id'])
|
LOG.debug("Enqueing notify for port %s", port['id'])
|
||||||
|
@ -3524,6 +3612,15 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
|
||||||
for p_id in port_ids:
|
for p_id in port_ids:
|
||||||
self._notify_port_update(plugin_context, p_id)
|
self._notify_port_update(plugin_context, p_id)
|
||||||
|
|
||||||
|
def _notify_vrf_update(self, plugin_context, vrfs_to_notify):
|
||||||
|
txn = local_api.get_outer_transaction(
|
||||||
|
plugin_context.session.transaction)
|
||||||
|
for vrf in vrfs_to_notify:
|
||||||
|
local_api.send_or_queue_notification(plugin_context.session,
|
||||||
|
txn, self.notifier,
|
||||||
|
'opflex_notify_vrf',
|
||||||
|
[plugin_context, vrf])
|
||||||
|
|
||||||
def get_or_allocate_snat_ip(self, plugin_context, host_or_vrf,
|
def get_or_allocate_snat_ip(self, plugin_context, host_or_vrf,
|
||||||
ext_network):
|
ext_network):
|
||||||
"""Fetch or allocate SNAT IP on the external network.
|
"""Fetch or allocate SNAT IP on the external network.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue