Fix `external-gateway-multihoming` API extension definition

The new field ``external-gateways`` added in the API extension
``external-gateway-multihoming`` didn't have the ``enforce_policy`` flag
defined and the validate parameters didn't provide the needed
information to the Neutron policy to build a correct rule match.
Now this field copies the ``ext-gw-mode`` extension validator used in
the ``external_gateway_info`` field.

The validator type ``list_of_dict_or_nodata`` is currently not
recognized by the Neutron policy as an iterable validator [1]; this
code must be changed in Neutron in order to accept this new defined
validator that is not a dictionary but a list of dictionaries.

[1]86f94de99a/neutron/policy.py (L142)

Closes-Bug: #2098109
Change-Id: I592f7ff0673c15276e9da0054fd38f7ad96f795a
This commit is contained in:
Rodolfo Alonso Hernandez
2025-02-18 06:43:19 +00:00
parent 5aaa572a02
commit bf21a6dcd4
2 changed files with 22 additions and 35 deletions

View File

@@ -12,6 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import typing
from neutron_lib.api.definitions import l3
from neutron_lib.api.definitions import l3_ext_gw_mode
@@ -26,6 +29,11 @@ DESCRIPTION = 'Allow multiple external gateway ports per router'
UPDATED_TIMESTAMP = '2023-01-18T00:00:00-00:00'
RESOURCE_NAME = l3.ROUTER
COLLECTION_NAME = l3.ROUTERS
external_gw_info_validate: typing.Dict[str, typing.Any] = copy.deepcopy(
l3_ext_gw_mode.RESOURCE_ATTRIBUTE_MAP[COLLECTION_NAME][l3.EXTERNAL_GW_INFO]
['validate']['type:dict_or_nodata']
)
RESOURCE_ATTRIBUTE_MAP = {
COLLECTION_NAME: {
EXTERNAL_GATEWAYS: {
@@ -33,7 +41,10 @@ RESOURCE_ATTRIBUTE_MAP = {
'allow_put': False,
'is_visible': True,
'default': None,
'validate': {'type:external_gw_info_list': None},
'enforce_policy': True,
'validate': {
'type:list_of_dict_or_nodata': external_gw_info_validate
},
},
},
}

View File

@@ -28,7 +28,7 @@ from neutron_lib._i18n import _
from neutron_lib import constants
from neutron_lib import exceptions as n_exc
from neutron_lib.plugins import directory
from neutron_lib.services.qos import constants as qos_consts
LOG = logging.getLogger(__name__)
@@ -1211,40 +1211,17 @@ def validate_ethertype(ethertype, valid_values=None):
return _(msg) % msg_data
def validate_external_gw_info(data, valid_values=None):
"""Validate data is an external_gateway_info.
def validate_list_of_dict_or_nodata(data, valid_values=None):
"""Validate a list of dictionaries.
:param data: The data to validate.
:param valid_values: Not used!
:param data: The data to validate. The data could be an empty list or None.
:param valid_values: The optional list of keys that must be contained in
data.
:returns: None if valid, error string otherwise.
"""
# See https://github.com/PyCQA/pylint/issues/850
# pylint: disable=import-outside-toplevel,cyclic-import
from neutron_lib.api import converters
return validate_dict_or_nodata(
data,
key_specs={
'network_id': {'type:uuid': None, 'required': True},
'external_fixed_ips': {'type:fixed_ips': None, 'required': False},
'enable_snat': {'type:boolean': None, 'required': False,
'convert_to': converters.convert_to_boolean},
qos_consts.QOS_POLICY_ID: {
'type:uuid_or_none': None,
'required': False
}
}
)
def validate_external_gw_info_list(data, valid_values=None):
"""Validate data is a list of external_gateway_info.
:param data: The data to validate.
:param valid_values: Not used!
:returns: None if valid, error string otherwise.
"""
if data is not None:
return _validate_list_of_items(validate_external_gw_info, data)
if data:
return _validate_list_of_items(validate_dict_or_nodata, data,
**valid_values)
# Dictionary that maintains a list of validation functions
@@ -1298,8 +1275,7 @@ validators = {'type:dict': validate_dict,
'type:list_of_subnets_or_none': validate_subnet_list_or_none,
'type:list_of_subnet_service_types':
validate_subnet_service_types,
'type:external_gw_info': validate_external_gw_info,
'type:external_gw_info_list': validate_external_gw_info_list,
'type:list_of_dict_or_nodata': validate_list_of_dict_or_nodata,
}