subnet create - segment aware auto-addr allocation
When creating additional subnets with ipv6 auto-addressing
ip allocation was added to existing ports without filtering
on current allocation's segment.
This adds fitering to only add auto-address allocation when
the new subnet is on the same segment as the ports current
ipam allocations.
Related: rhbz#1803989
Related-Bug: #1864225
Related-Bug: #1865138
Closes-Bug: #1864333
Change-Id: I75ae14c64db076434ca9897ba9a6d97702e233ad
(cherry picked from commit 3d3dc60408
)
This commit is contained in:
parent
16687e39b6
commit
c4264b7ded
|
@ -530,6 +530,22 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
|
|||
ipam_driver = driver.Pool.get_instance(None, context)
|
||||
factory = ipam_driver.get_address_request_factory()
|
||||
for port in ports:
|
||||
# Find candidate subnets based on host_id and existing
|
||||
# fixed_ips. This will filter subnets on other segments. Only
|
||||
# allocate if this subnet is a valid candidate.
|
||||
p = self._make_port_dict(port)
|
||||
fixed_configured = (p['fixed_ips'] is not
|
||||
constants.ATTR_NOT_SPECIFIED)
|
||||
subnet_candidates = obj_subnet.Subnet.find_candidate_subnets(
|
||||
context,
|
||||
network_id,
|
||||
p.get(portbindings.HOST_ID),
|
||||
p.get('device_owner'),
|
||||
fixed_configured,
|
||||
p.get('fixed_ips'))
|
||||
if subnet['id'] not in [s['id'] for s in subnet_candidates]:
|
||||
continue
|
||||
|
||||
ip = {'subnet_id': subnet['id'],
|
||||
'subnet_cidr': subnet['cidr'],
|
||||
'eui64_address': True,
|
||||
|
|
|
@ -1719,6 +1719,78 @@ class TestSegmentAwareIpam(SegmentAwareIpamTestCase):
|
|||
self.assertNotIn(subnet_b0['subnet']['id'], res_subnet_ids)
|
||||
self.assertNotIn(subnet_b1['subnet']['id'], res_subnet_ids)
|
||||
|
||||
def test_slaac_segment_aware_add_subnet(self):
|
||||
(network, segment_a, segment_b, subnet_a0, subnet_a1, subnet_b0,
|
||||
subnet_b1) = self._create_net_two_segments_four_slaac_subnets()
|
||||
|
||||
# Create a port with no IP address (since there is no subnet)
|
||||
port_deferred = self._create_deferred_ip_port(network)
|
||||
self._validate_deferred_ip_allocation(port_deferred['port']['id'])
|
||||
|
||||
# Create two ports, port_a with subnet_a0 in fixed_ips and port_b
|
||||
# with subnet_b0 in fixed_ips
|
||||
port_a = self._create_port_and_show(
|
||||
network, fixed_ips=[{'subnet_id': subnet_a0['subnet']['id']}])
|
||||
port_b = self._create_port_and_show(
|
||||
network, fixed_ips=[{'subnet_id': subnet_b0['subnet']['id']}])
|
||||
self._validate_immediate_ip_allocation(port_a['port']['id'])
|
||||
self._validate_immediate_ip_allocation(port_b['port']['id'])
|
||||
self.assertEqual(2, len(port_a['port']['fixed_ips']))
|
||||
self.assertEqual(2, len(port_b['port']['fixed_ips']))
|
||||
|
||||
# Add another subnet on segment_a
|
||||
subnet_a2 = self._create_test_slaac_subnet_with_segment(
|
||||
network, segment_a, '2001:db8:a:2::/64')
|
||||
# The port with deferred allocation should not have an allocation
|
||||
req = self.new_show_request('ports', port_deferred['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
port_deferred = self.deserialize(self.fmt, res)
|
||||
self._validate_deferred_ip_allocation(port_deferred['port']['id'])
|
||||
self.assertEqual(0, len(port_deferred['port']['fixed_ips']))
|
||||
# port_a should get an allocation on the new subnet.
|
||||
# port_b does not get an allocation.
|
||||
req = self.new_show_request('ports', port_a['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
port_a = self.deserialize(self.fmt, res)
|
||||
req = self.new_show_request('ports', port_b['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
port_b = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(3, len(port_a['port']['fixed_ips']))
|
||||
self.assertEqual(2, len(port_b['port']['fixed_ips']))
|
||||
port_a_snet_ids = [f['subnet_id'] for f in port_a['port']['fixed_ips']]
|
||||
self.assertIn(subnet_a2['subnet']['id'], port_a_snet_ids)
|
||||
|
||||
def test_slaac_segment_aware_delete_subnet(self):
|
||||
(network, segment_a, segment_b, subnet_a0, subnet_a1, subnet_b0,
|
||||
subnet_b1) = self._create_net_two_segments_four_slaac_subnets()
|
||||
|
||||
# Create two ports, port_a with subnet_a0 in fixed_ips and port_b
|
||||
# with subnet_b0 in fixed_ips
|
||||
port_a = self._create_port_and_show(
|
||||
network, fixed_ips=[{'subnet_id': subnet_a0['subnet']['id']}])
|
||||
port_b = self._create_port_and_show(
|
||||
network, fixed_ips=[{'subnet_id': subnet_b0['subnet']['id']}])
|
||||
self._validate_immediate_ip_allocation(port_a['port']['id'])
|
||||
self._validate_immediate_ip_allocation(port_b['port']['id'])
|
||||
self.assertEqual(2, len(port_a['port']['fixed_ips']))
|
||||
self.assertEqual(2, len(port_b['port']['fixed_ips']))
|
||||
|
||||
# Delete subnet_b1 on segment_b, port_a should keep it's allocations
|
||||
# on the new subnet. Allocation for deleted subnet removed on port_b.
|
||||
req = self.new_delete_request('subnets', subnet_b1['subnet']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(webob.exc.HTTPNoContent.code, res.status_int)
|
||||
req = self.new_show_request('ports', port_a['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
port_a = self.deserialize(self.fmt, res)
|
||||
req = self.new_show_request('ports', port_b['port']['id'])
|
||||
res = req.get_response(self.api)
|
||||
port_b = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(2, len(port_a['port']['fixed_ips']))
|
||||
self.assertEqual(1, len(port_b['port']['fixed_ips']))
|
||||
port_b_snet_ids = [f['subnet_id'] for f in port_b['port']['fixed_ips']]
|
||||
self.assertNotIn(subnet_b1['subnet']['id'], port_b_snet_ids)
|
||||
|
||||
|
||||
class TestSegmentAwareIpamML2(TestSegmentAwareIpam):
|
||||
|
||||
|
|
Loading…
Reference in New Issue