Improve bottom allocation pool calculation
1. What is the problem Current bottom allocation pool calculation only merges the top gateway ip with one ip range, so if the top gateway ip can connect two ip ranges, the two ranges are not merged. For example, pools: [x.x.x.2, x.x.x.5], [x.x.x.7, x.x.x.10] top gateway ip: x.x.x.6 after merge, the pools become: [x.x.x.2, x.x.x.6], [x.x.x.7, x.x.x.10] while should be: [x.x.x.2, x.x.x.10] 2. What is the solution to the problem Rewrite the calculation method to merge two ranges if they are connected by the top gateway ip. 3. What the features need to be implemented to the Tricircle No new features. Change-Id: I4d56e9c992a3ad1106918551a3b4c23d09264928 Closes-Bug: #1657621
This commit is contained in:
parent
ed02562d76
commit
f0b6233181
|
@ -227,47 +227,82 @@ class NetworkHelper(object):
|
|||
return body
|
||||
|
||||
@staticmethod
|
||||
def get_bottom_subnet_pools(t_subnet, gateway_ip):
|
||||
"""Get bottom subnet allocation pools
|
||||
def _find_ip_range(pool, gateway_ip):
|
||||
ret_pools = []
|
||||
ip_range = netaddr.IPRange(pool['start'], pool['end'])
|
||||
ip_num = len(ip_range)
|
||||
for i, ip in enumerate(ip_range):
|
||||
if gateway_ip == ip:
|
||||
if i > 0:
|
||||
ret_pools.append({'start': ip_range[0].format(),
|
||||
'end': ip_range[i - 1].format()})
|
||||
if i < ip_num - 1:
|
||||
ret_pools.append(
|
||||
{'start': ip_range[i + 1].format(),
|
||||
'end': ip_range[ip_num - 1].format()})
|
||||
return ret_pools
|
||||
|
||||
:param t_subnet: top subnet
|
||||
:param gateway_ip: bottom subnet gateway ip
|
||||
:return: bottom subnet allocation pools
|
||||
"""
|
||||
pools = t_subnet['allocation_pools']
|
||||
t_gateway_ip = t_subnet['gateway_ip']
|
||||
@staticmethod
|
||||
def _split_pools_by_bottom_gateway_ip(pools, gateway_ip):
|
||||
new_pools = []
|
||||
g_ip = netaddr.IPAddress(gateway_ip)
|
||||
ip_found = False
|
||||
ip_merged = False
|
||||
for pool in pools:
|
||||
if ip_found:
|
||||
new_pools.append({'start': pool['start'],
|
||||
'end': pool['end']})
|
||||
continue
|
||||
ip_range = netaddr.IPRange(pool['start'], pool['end'])
|
||||
if not ip_merged:
|
||||
ip_range, ip_merged = NetworkHelper._merge_ip_range(
|
||||
ip_range, t_gateway_ip)
|
||||
|
||||
ip_num = len(ip_range)
|
||||
for i, ip in enumerate(ip_range):
|
||||
if g_ip == ip:
|
||||
ip_found = True
|
||||
if i > 0:
|
||||
new_pools.append({'start': ip_range[0].format(),
|
||||
'end': ip_range[i - 1].format()})
|
||||
if i < ip_num - 1:
|
||||
new_pools.append(
|
||||
{'start': ip_range[i + 1].format(),
|
||||
'end': ip_range[ip_num - 1].format()})
|
||||
break
|
||||
ret_pools = NetworkHelper._find_ip_range(pool, g_ip)
|
||||
if ret_pools:
|
||||
ip_found = True
|
||||
new_pools.extend(ret_pools)
|
||||
if not ip_found:
|
||||
new_pools.extend(pools)
|
||||
if not ip_merged:
|
||||
new_pools.insert(0, {'start': t_gateway_ip, 'end': t_gateway_ip})
|
||||
return new_pools
|
||||
|
||||
@staticmethod
|
||||
def _merge_pools_by_top_gateway_ip(pools, gateway_ip):
|
||||
new_ranges = []
|
||||
merged_set = netaddr.IPSet()
|
||||
for pool in pools:
|
||||
ip_range = netaddr.IPRange(pool['start'], pool['end'])
|
||||
ip_range, ip_merged = NetworkHelper._merge_ip_range(
|
||||
ip_range, gateway_ip)
|
||||
if not ip_merged:
|
||||
new_ranges.append(ip_range)
|
||||
else:
|
||||
# if range1 + gateway_ip is contiguous, range2 + gateway_ip is
|
||||
# contiguous, then range1 + range2 + gateway_ip is contiguous,
|
||||
# so we add them in the same ip set
|
||||
merged_set.add(ip_range)
|
||||
new_pools = []
|
||||
for new_range in new_ranges:
|
||||
new_pools.append({'start': new_range[0].format(),
|
||||
'end': new_range[len(new_range) - 1].format()})
|
||||
if merged_set:
|
||||
merged_range = merged_set.iprange()
|
||||
new_pools.append(
|
||||
{'start': merged_range[0].format(),
|
||||
'end': merged_range[len(merged_range) - 1].format()})
|
||||
else:
|
||||
new_pools.append({'start': gateway_ip, 'end': gateway_ip})
|
||||
return new_pools
|
||||
|
||||
@staticmethod
|
||||
def get_bottom_subnet_pools(t_subnet, b_gateway_ip):
|
||||
"""Get bottom subnet allocation pools
|
||||
|
||||
:param t_subnet: top subnet
|
||||
:param b_gateway_ip: bottom subnet gateway ip
|
||||
:return: bottom subnet allocation pools
|
||||
"""
|
||||
pools = t_subnet['allocation_pools']
|
||||
t_gateway_ip = t_subnet['gateway_ip']
|
||||
new_pools = NetworkHelper._split_pools_by_bottom_gateway_ip(
|
||||
pools, b_gateway_ip)
|
||||
return NetworkHelper._merge_pools_by_top_gateway_ip(new_pools,
|
||||
t_gateway_ip)
|
||||
|
||||
@staticmethod
|
||||
def get_create_subnet_body(project_id, t_subnet, b_net_id, gateway_ip):
|
||||
"""Get request body to create bottom subnet
|
||||
|
|
|
@ -1909,8 +1909,9 @@ class PluginTest(unittest.TestCase,
|
|||
bottom_allocation_pools = [{'start': '10.0.1.2', 'end': '10.0.1.2'},
|
||||
{'start': '10.0.1.10', 'end': '10.0.1.24'},
|
||||
{'start': '10.0.1.26', 'end': '10.0.1.254'}]
|
||||
self.assertEqual(bottom_subnet['allocation_pools'],
|
||||
bottom_allocation_pools)
|
||||
six.assertCountEqual(self,
|
||||
bottom_subnet['allocation_pools'],
|
||||
bottom_allocation_pools)
|
||||
six.assertCountEqual(self,
|
||||
bottom_subnet['host_routes'],
|
||||
body_copy['subnet']['host_routes'])
|
||||
|
|
|
@ -76,3 +76,15 @@ class HelperTest(unittest.TestCase):
|
|||
{'start': '10.0.1.20', 'end': '10.0.1.254'}],
|
||||
body['subnet']['allocation_pools'])
|
||||
self.assertEqual('10.0.1.5', body['subnet']['gateway_ip'])
|
||||
|
||||
t_subnet['gateway_ip'] = '10.0.1.11'
|
||||
t_subnet['allocation_pools'] = [
|
||||
{'start': '10.0.1.2', 'end': '10.0.1.10'},
|
||||
{'start': '10.0.1.12', 'end': '10.0.1.254'}]
|
||||
body = self.helper.get_create_subnet_body(project_id, t_subnet,
|
||||
b_net_id, '10.0.1.5')
|
||||
six.assertCountEqual(self,
|
||||
[{'start': '10.0.1.2', 'end': '10.0.1.4'},
|
||||
{'start': '10.0.1.6', 'end': '10.0.1.254'}],
|
||||
body['subnet']['allocation_pools'])
|
||||
self.assertEqual('10.0.1.5', body['subnet']['gateway_ip'])
|
||||
|
|
|
@ -302,7 +302,7 @@ class PluginTest(unittest.TestCase):
|
|||
b_port.pop('name')
|
||||
self.assertDictEqual(net, b_net)
|
||||
self.assertDictEqual(subnet, b_subnet)
|
||||
self.assertListEqual(pool_range, b_pool_range)
|
||||
self.assertSetEqual(set(pool_range), set(b_pool_range))
|
||||
self.assertEqual('vlan', b_net_type)
|
||||
self.assertDictEqual(port, b_port)
|
||||
|
||||
|
|
Loading…
Reference in New Issue