api: canonicalize ipv6 addresses in subnet:allocation_pools field

Before the patch, `start` and `end` addresses in `allocation_pools` were
never canonicalized because an invalid converter was used for this field
that assumed a string as an input format, and not a list of dicts with
`start` and `end` keys, which is the correct format for the field.

The original invalid converter was added in
Ibef0bd9a2f7b7dd8ddccc183f17aa31e426c7fd0.

Related-Bug: #1531103
Change-Id: If768ab6a5f92d200841a734087bbc8fba8870dc6
This commit is contained in:
Ihar Hrachyshka
2024-05-03 18:56:27 -04:00
parent 8b6c769789
commit e9275425db
4 changed files with 59 additions and 1 deletions

View File

@@ -182,6 +182,28 @@ def convert_to_list(data):
return [data]
def convert_allocation_pools_to_canonical_format(value):
"""Convert allocation pools to canonical format.
:param value: The allocation pools which need to be checked.
:returns: Allocation pools with addresses in canonical format.
:raises InvalidInput: If the value is not a list of allocation pools.
"""
if value is None:
return []
try:
return [
{
k: convert_ip_to_canonical_format(v)
for k, v in pool.items()
}
for pool in value
]
except Exception as e:
raise n_exc.InvalidInput(
error_message=_("Invalid data format for allocation pools")) from e
def convert_ip_to_canonical_format(value):
"""IP Address is validated and then converted to canonical format.

View File

@@ -84,7 +84,9 @@ RESOURCE_ATTRIBUTE_MAP = {
'allocation_pools': {
'allow_post': True, 'allow_put': True,
'default': constants.ATTR_NOT_SPECIFIED,
'convert_to': converters.convert_ip_to_canonical_format,
'convert_to': (
converters.convert_allocation_pools_to_canonical_format
),
'validate': {'type:ip_pools': None},
'is_visible': True},
'dns_nameservers': {'allow_post': True, 'allow_put': True,

View File

@@ -210,6 +210,35 @@ class TestConvertIPv6AddrCanonicalFormat(base.BaseTestCase):
self.assertEqual('2001:db8:0:1:1:1:1:1/128', result)
class TestConvertAllocationPoolsCanonicalFormat(base.BaseTestCase):
def test_convert_allocation_pools_to_canonical_format_noop(self):
pools = [{'start': '1.1.1.1', 'end': '1.1.1.100'}]
result = converters.convert_allocation_pools_to_canonical_format(pools)
self.assertEqual(pools, result)
def test_convert_allocation_pools_to_canonical_format(self):
pools = [
{'start': 'Fe80:0:0:0:0:0:0:1', 'end': 'Fe80:0:0:0:0:0:0:100'},
]
result = converters.convert_allocation_pools_to_canonical_format(pools)
expected = [
{'start': 'fe80::1', 'end': 'fe80::100'},
]
self.assertEqual(expected, result)
def test_convert_allocation_pools_to_canonical_format_None(self):
result = converters.convert_allocation_pools_to_canonical_format(None)
self.assertEqual([], result)
def test_convert_allocation_pools_to_canonical_format_invalid_data(self):
self.assertRaises(
n_exc.InvalidInput,
converters.convert_allocation_pools_to_canonical_format,
'10.0.0.0/24')
class TestConvertIPv6CIDRCanonicalFormat(base.BaseTestCase):
def test_convert_ipv4_address_with_CIDR(self):

View File

@@ -0,0 +1,5 @@
---
fixes:
- |
The ``subnet:allocation_pools`` field IPv6 addresses are now converted to
their canonical format.