diff --git a/neutron/db/db_base_plugin_common.py b/neutron/db/db_base_plugin_common.py index a903da17144..3c08d83d57a 100644 --- a/neutron/db/db_base_plugin_common.py +++ b/neutron/db/db_base_plugin_common.py @@ -302,11 +302,6 @@ class DbBasePluginCommon(object): return subnet_obj.Route.get_objects(context, subnet_id=subnet_id) - def _get_router_gw_ports_by_network(self, context, network_id): - return port_obj.Port.get_objects( - context, network_id=network_id, - device_owner=constants.DEVICE_OWNER_ROUTER_GW) - @db_api.CONTEXT_READER def _get_subnets_by_network(self, context, network_id): return subnet_obj.Subnet.get_objects(context, network_id=network_id) diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 0e8aae5a335..5b733a4cac0 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -73,7 +73,6 @@ from neutron.objects import network as network_obj from neutron.objects import ports as port_obj from neutron.objects import subnet as subnet_obj from neutron.objects import subnetpool as subnetpool_obj -from neutron.services.ovn_l3 import plugin as l3_ovn LOG = logging.getLogger(__name__) @@ -807,47 +806,10 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, def _update_router_gw_ports(self, context, network, subnet): l3plugin = directory.get_plugin(plugin_constants.L3) - if l3plugin: - s = subnet_obj.Subnet.get_object(context, id=subnet['id']) - service_types = s.service_types - update_types = ['', constants.DEVICE_OWNER_ROUTER_GW] - if (not isinstance(l3plugin, l3_ovn.OVNL3RouterPlugin) and - subnet['ip_version'] == constants.IP_VERSION_4 and - all(s not in update_types for s in service_types)): - return - gw_ports = self._get_router_gw_ports_by_network(context, - network['id']) - router_ids = [p.device_id for p in gw_ports] - for id in router_ids: - try: - self._update_router_gw_port(context, id, network, subnet) - except l3_exc.RouterNotFound: - LOG.debug("Router %(id)s was concurrently deleted while " - "updating GW port for subnet %(s)s", - {'id': id, 's': subnet}) - - def _update_router_gw_port(self, context, router_id, network, subnet): - l3plugin = directory.get_plugin(plugin_constants.L3) - ctx_admin = context.elevated() - ext_subnets_dict = {s['id']: s for s in network['subnets']} - router = l3plugin.get_router(ctx_admin, router_id) - external_gateway_info = router['external_gateway_info'] - # Get all stateful (i.e. non-SLAAC/DHCPv6-stateless) fixed ips - fips = [f for f in external_gateway_info['external_fixed_ips'] - if not ipv6_utils.is_auto_address_subnet( - ext_subnets_dict[f['subnet_id']])] - num_fips = len(fips) - # Don't add the fixed IP to the port if it already - # has a stateful fixed IP of the same IP version - if num_fips > 1: - return - if num_fips == 1 and netaddr.IPAddress( - fips[0]['ip_address']).version == subnet['ip_version']: - return - external_gateway_info['external_fixed_ips'].append( - {'subnet_id': subnet['id']}) - info = {'router': {'external_gateway_info': external_gateway_info}} - l3plugin.update_router(ctx_admin, router_id, info) + # The hasattr check for customized l3 plugins that may have no such + # function. + if l3plugin and hasattr(l3plugin, "update_router_gw_ports"): + l3plugin.update_router_gw_ports(context, network, subnet) @db_api.retry_if_session_inactive() def _create_subnet_postcommit(self, context, result, diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index ab9b169ff89..48bcc1a21ba 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -2322,3 +2322,51 @@ class L3_NAT_db_mixin(L3_NAT_dbonly_mixin, L3RpcNotifierMixin): if rp.port_type == old_owner: rp.port_type = new_owner rp.port.device_owner = new_owner + + def _get_router_gw_ports_by_network(self, context, network_id): + return port_obj.Port.get_objects( + context, network_id=network_id, + device_owner=constants.DEVICE_OWNER_ROUTER_GW) + + def _update_router_gateway_ports(self, context, network, subnet): + gw_ports = self._get_router_gw_ports_by_network(context, + network['id']) + router_ids = [p.device_id for p in gw_ports] + for id in router_ids: + try: + self._update_router_gw_port(context, id, network, subnet) + except l3_exc.RouterNotFound: + LOG.debug("Router %(id)s was concurrently deleted while " + "updating GW port for subnet %(s)s", + {'id': id, 's': subnet}) + + def update_router_gw_ports(self, context, network, subnet): + s = subnet_obj.Subnet.get_object(context, id=subnet['id']) + service_types = s.service_types + update_types = ['', constants.DEVICE_OWNER_ROUTER_GW] + if (subnet['ip_version'] == constants.IP_VERSION_4 and + all(s not in update_types for s in service_types)): + return + self._update_router_gateway_ports(context, network, subnet) + + def _update_router_gw_port(self, context, router_id, network, subnet): + ctx_admin = context.elevated() + ext_subnets_dict = {s['id']: s for s in network['subnets']} + router = self.get_router(ctx_admin, router_id) + external_gateway_info = router['external_gateway_info'] + # Get all stateful (i.e. non-SLAAC/DHCPv6-stateless) fixed ips + fips = [f for f in external_gateway_info['external_fixed_ips'] + if not ipv6_utils.is_auto_address_subnet( + ext_subnets_dict[f['subnet_id']])] + num_fips = len(fips) + # Don't add the fixed IP to the port if it already + # has a stateful fixed IP of the same IP version + if num_fips > 1: + return + if num_fips == 1 and netaddr.IPAddress( + fips[0]['ip_address']).version == subnet['ip_version']: + return + external_gateway_info['external_fixed_ips'].append( + {'subnet_id': subnet['id']}) + info = {'router': {'external_gateway_info': external_gateway_info}} + self.update_router(ctx_admin, router_id, info) diff --git a/neutron/services/ovn_l3/plugin.py b/neutron/services/ovn_l3/plugin.py index fe40baf7161..d21eefed836 100644 --- a/neutron/services/ovn_l3/plugin.py +++ b/neutron/services/ovn_l3/plugin.py @@ -395,3 +395,6 @@ class OVNL3RouterPlugin(service_base.ServicePluginBase, @resource_extend.extends([l3_apidef.ROUTERS]) def add_flavor_id(router_res, router_db): router_res['flavor_id'] = router_db['flavor_id'] + + def update_router_gw_ports(self, context, network, subnet): + self._update_router_gateway_ports(context, network, subnet) diff --git a/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py b/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py index ac2aac1cdc4..47f02e92893 100644 --- a/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py +++ b/neutron/tests/functional/services/l3_router/test_l3_dvr_ha_router_plugin.py @@ -332,7 +332,7 @@ class L3DvrHATestCase(test_l3_dvr_router_plugin.L3DvrTestCase): def _check_snat_external_gateway_presence(self, ext_net, router, gw_count): ext_net_id = ext_net['network']['id'] - gw_port = (self.l3_plugin._core_plugin. + gw_port = (self.l3_plugin. _get_router_gw_ports_by_network(self.context, ext_net_id)) self.assertEqual(gw_count, len(gw_port)) if gw_count > 1: