From f9e40971e94e4fd239fcf7537b0f1200fbd4ee0f Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Sun, 14 Jan 2024 10:20:12 +0000 Subject: [PATCH] Forbid the subnet gateway IP deletion if a router interface is attached When a router interface is created, the corresponding subnet gateway IP is tested first [1]. If the subnet has no gateway IP, the router interface cannot be created. This IP will be assigned to this port. The Neutron API also prevents from modifying the subnet gateway IP if assigned to a router interface [2]. However the API is not preventing the subnet gateway IP deletion. This patch is adding this check. This patch is being tested in the neutron-tempest-plugin [3]. [1]https://github.com/openstack/neutron/blob/de58c1b99523104a471420ef0468147f13c9e98d/neutron/db/l3_db.py#L902-L904 [2]https://github.com/openstack/neutron/blob/de58c1b99523104a471420ef0468147f13c9e98d/neutron/db/db_base_plugin_v2.py#L715 [3]https://review.opendev.org/c/openstack/neutron-tempest-plugin/+/904710 Closes-Bug: #2036423 Change-Id: I4c7b399a3a052749abdb88fb50be628ee91b63a0 --- neutron/db/db_base_plugin_v2.py | 37 +++++++++++-------- ...ion-router-interface-072a18373f920ed9.yaml | 6 +++ 2 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 releasenotes/notes/forbid-subnet-gwip-deletion-router-interface-072a18373f920ed9.yaml diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 972de5b2604..9e8fac4f56d 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -688,32 +688,39 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, "supported if enable_dhcp is True.") raise exc.InvalidInput(error_message=error_message) - if validators.is_attr_set(s.get('gateway_ip')): - self._validate_ip_version(ip_ver, s['gateway_ip'], 'gateway_ip') - if has_cidr: - is_gateway_not_valid = ( - ipam.utils.check_gateway_invalid_in_subnet( - s['cidr'], s['gateway_ip'])) - if is_gateway_not_valid: - error_message = _("Gateway is not valid on subnet") - raise exc.InvalidInput(error_message=error_message) - # Ensure the gateway IP is not assigned to any port - # skip this check in case of create (s parameter won't have id) + gateway_ip = s.get('gateway_ip', constants.ATTR_NOT_SPECIFIED) + if validators.is_attr_set(gateway_ip) or gateway_ip is None: + # Validate the gateway IP, if defined in the request. + if s['gateway_ip']: + self._validate_ip_version(ip_ver, gateway_ip, 'gateway_ip') + if has_cidr: + is_gateway_not_valid = ( + ipam.utils.check_gateway_invalid_in_subnet( + s['cidr'], gateway_ip)) + if is_gateway_not_valid: + error_message = _("Gateway is not valid on subnet") + raise exc.InvalidInput(error_message=error_message) + + # Ensure the current subnet gateway IP is not assigned to any port. + # The subnet gateway IP cannot be modified or removed if in use + # (assigned to a router interface). + # Skip this check in case of create (s parameter won't have id). # NOTE(salv-orlando): There is slight chance of a race, when # a subnet-update and a router-interface-add operation are # executed concurrently - s_gateway_ip = netaddr.IPAddress(s['gateway_ip']) + s_gateway_ip = (netaddr.IPAddress(gateway_ip) if gateway_ip else + None) if (cur_subnet and s_gateway_ip != cur_subnet['gateway_ip'] and not ipv6_utils.is_ipv6_pd_enabled(s)): - gateway_ip = str(cur_subnet['gateway_ip']) + current_gateway_ip = str(cur_subnet['gateway_ip']) alloc = port_obj.IPAllocation.get_alloc_routerports( - context, cur_subnet['id'], gateway_ip=gateway_ip, + context, cur_subnet['id'], gateway_ip=current_gateway_ip, first=True) if alloc and alloc.port_id: raise exc.GatewayIpInUse( - ip_address=gateway_ip, + ip_address=current_gateway_ip, port_id=alloc.port_id) if validators.is_attr_set(s.get('dns_nameservers')): diff --git a/releasenotes/notes/forbid-subnet-gwip-deletion-router-interface-072a18373f920ed9.yaml b/releasenotes/notes/forbid-subnet-gwip-deletion-router-interface-072a18373f920ed9.yaml new file mode 100644 index 00000000000..f830f329520 --- /dev/null +++ b/releasenotes/notes/forbid-subnet-gwip-deletion-router-interface-072a18373f920ed9.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + [`bug 2036423 `_] + Now it is not possible to delete a subnet gateway IP if that subnet has a + router interface; the subnet gateway IP modification was already forbidden.