Add custom range parameters on port_range validator

To maintain the behavior of port forwarding
validations that denies the port number 0 when
creating a new port forwarding rule for floating
IPs, we will need to extend the
'validate_port_range_or_none' validator to allow
us to define the acceptable port ranges when
validating a value.

This patch is one of a series of patches
to implement floating ip port forwarding with
port ranges.

The specification is defined in:
https://github.com/openstack/neutron-specs/blob/master/specs/wallaby/port-forwarding-port-ranges.rst

Change-Id: I0e11885e15616509942d60fbced3ff8e14cac654
Implements: blueprint floatingips-portforwarding-ranges
Related-Bug: #1885921
This commit is contained in:
Pedro Henrique 2022-03-07 11:56:18 -03:00
parent f765e3c21c
commit 1dde6c24b7
3 changed files with 31 additions and 6 deletions

View File

@ -27,14 +27,14 @@ SUB_RESOURCE_ATTRIBUTE_MAP = {
'parameters': {
EXTERNAL_PORT_RANGE: {
'allow_post': True, 'allow_put': True,
'validate': {'type:port_range': None},
'validate': {'type:port_range': [1, 65535]},
'is_visible': True,
'is_sort_key': True,
'is_filter': True,
'default': None},
INTERNAL_PORT_RANGE: {
'allow_post': True, 'allow_put': True,
'validate': {'type:port_range': None},
'validate': {'type:port_range': [1, 65535]},
'is_visible': True,
'default': None},
pfw.EXTERNAL_PORT: {

View File

@ -1038,13 +1038,17 @@ def validate_port_range_or_none(data, valid_values=None):
"""Validate data is a range of TCP/UDP port numbers
:param data: The data to validate
:param valid_values: Not used!
:returns: None if data is an int between 0 and 65535, or two ints between 0
and 65535 with a colon between them, otherwise a human readable message
as to why data is invalid.
:param valid_values: valid port range, default is [0, 65535]
:returns: None if data is a valid port between the values defined in the
valid_values param, or two valid ports between the values defined in
the valid_values param with a colon between them, otherwise a human
readable message as to why data is invalid.
"""
if data is None:
return
min_value, max_value = valid_values or [0, 65535]
data = str(data)
ports = data.split(':')
if len(ports) > 2:
@ -1060,6 +1064,11 @@ def validate_port_range_or_none(data, valid_values=None):
msg = _("Invalid port: %s") % p
LOG.debug(msg)
return msg
if max_value < int(p) or int(p) < min_value:
msg = "Invalid port: %s, the port must be in the range " \
"[%s, %s]"
LOG.debug(msg, p, min_value, max_value)
return _(msg) % (p, min_value, max_value)
if len(ports) > 1 and int(ports[0]) > int(ports[1]):
msg = _("First port in a port range must be lower than the second "
"port")

View File

@ -1299,6 +1299,22 @@ class TestValidateIPSubnetNone(base.BaseTestCase):
class TestPortRangeValidation(base.BaseTestCase):
def test_valid_port_specific_range(self):
result = validators.validate_port_range_or_none("4:5",
[1, 65535])
self.assertIsNone(result)
def test_invalid_port_specific_range(self):
result = validators.validate_port_range_or_none("4:500000",
[1, 65535])
self.assertEqual(u"Invalid port: 500000", result)
def test_invalid_port_for_specific_range(self):
result = validators.validate_port_range_or_none("0:10",
[1, 65535])
self.assertEqual(u"Invalid port: 0, the port must be in"
u" the range [1, 65535]", result)
def test_valid_port(self):
result = validators.validate_port_range_or_none("80")
self.assertIsNone(result)