Improve netenv validation and add IPv6 tests

This patch improves the network environment validation to work with very
large IP ranges (when using IPv6).

Prior to this patch the validation would check for every IP within an IP
ranges to see if it was inside (valid) or outside (invalid) of a subnet.
This isn't feasible for many IPv6 cases when IP ranges can be very
large. Instead of comparing each IP this patch checks the
netaddr.IPRange object as a whole against the subnet.

Change-Id: Icbd2e6483c991835d62429d06b5745742186b5c5
This commit is contained in:
Florian Fuchs 2017-12-21 15:05:20 +01:00
parent 3d732165e1
commit 942b047295
2 changed files with 63 additions and 9 deletions

View File

@ -342,6 +342,10 @@ class TestCheckCidrOverlap(base.TestCase):
errors = validation.check_cidr_overlap(['172.16.0.0/24'])
self.assertEqual([], errors)
def test_single_network_ipv6(self):
errors = validation.check_cidr_overlap(['fd00:fd00:fd00:2000::/64'])
self.assertEqual([], errors)
def test_non_overlapping_networks(self):
networks = ['172.16.0.0/24', '172.17.0.0/24']
errors = validation.check_cidr_overlap(networks)
@ -354,6 +358,22 @@ class TestCheckCidrOverlap(base.TestCase):
self.assertEqual('Networks 172.16.0.0/24 and 172.16.0.0/24 overlap.',
errors[0])
def test_identical_networks_ipv6(self):
networks = ['fd00:fd00:fd00:2000::/64', 'fd00:fd00:fd00:2000::/64']
errors = validation.check_cidr_overlap(networks)
self.assertEqual(len(errors), 1)
self.assertEqual('Networks fd00:fd00:fd00:2000::/64 and '
'fd00:fd00:fd00:2000::/64 overlap.',
errors[0])
def test_first_cidr_is_subset_of_second_ipv6(self):
networks = ['fd00:fd00:fd00:2000::/126', 'fd00:fd00:fd00:2000::/124']
errors = validation.check_cidr_overlap(networks)
self.assertEqual(len(errors), 1)
self.assertEqual('Networks fd00:fd00:fd00:2000::/126 and '
'fd00:fd00:fd00:2000::/124 overlap.',
errors[0])
def test_first_cidr_is_subset_of_second(self):
networks = ['172.16.10.0/24', '172.16.0.0/16']
errors = validation.check_cidr_overlap(networks)
@ -368,6 +388,14 @@ class TestCheckCidrOverlap(base.TestCase):
self.assertEqual('Networks 172.16.0.0/16 and 172.16.10.0/24 overlap.',
errors[0])
def test_second_cidr_is_subset_of_first_ipv6(self):
networks = ['fd00:fd00:fd00:2000::/124', 'fd00:fd00:fd00:2000::/126']
errors = validation.check_cidr_overlap(networks)
self.assertEqual(len(errors), 1)
self.assertEqual('Networks fd00:fd00:fd00:2000::/124 and '
'fd00:fd00:fd00:2000::/126 overlap.',
errors[0])
def test_multiple_overlapping_networks(self):
networks = ['172.16.0.0/16', '172.16.10.0/24',
'172.16.11.0/23', '172.17.0.0/24']
@ -472,6 +500,20 @@ class TestCheckAllocationPoolsPairing(base.TestCase):
self.assertEqual(len(errors), 1)
self.assertIn('outside of subnet StorageNetCidr', errors[0])
def test_pool_outside_cidr_ipv6(self):
filedata = {
'StorageNetCidr': 'fd00:fd00:fd00:3000::10/125',
}
pools = {
'StorageAllocationPools': [
{'start': 'fd00:fd00:fd00:3000::10',
'end': 'fd00:fd00:fd00:3000::18'}
]
}
errors = validation.check_allocation_pools_pairing(filedata, pools)
self.assertEqual(len(errors), 1)
self.assertIn('outside of subnet StorageNetCidr', errors[0])
def test_multiple_ranges_and_pools(self):
filedata = {
'StorageNetCidr': '172.18.0.0/24',
@ -490,6 +532,19 @@ class TestCheckAllocationPoolsPairing(base.TestCase):
errors = validation.check_allocation_pools_pairing(filedata, pools)
self.assertEqual([], errors)
def test_pool_very_large_range_ipv6(self):
filedata = {
'StorageNetCidr': 'fd00:fd00:fd00:3000::/64',
}
pools = {
'StorageAllocationPools': [
{'start': 'fd00:fd00:fd00:3000::10',
'end': 'fd00:fd00:fd00:3000:ffff:ffff:ffff:fffe'}
]
}
errors = validation.check_allocation_pools_pairing(filedata, pools)
self.assertEqual([], errors)
class TestStaticIpPoolCollision(base.TestCase):

View File

@ -287,15 +287,14 @@ def check_allocation_pools_pairing(filedata, pools):
errors.append('Invalid IP network: {}'.format(network))
continue
for ranges in pool_objs:
for range in ranges:
if range not in subnet_obj:
errors.append('Allocation pool {} {} outside of subnet'
' {}: {}'.format(poolitem,
pooldata,
subnet_item,
subnet_obj))
break
for range in pool_objs:
if range not in subnet_obj:
errors.append('Allocation pool {} {} outside of subnet'
' {}: {}'.format(poolitem,
pooldata,
subnet_item,
subnet_obj))
break
return errors