Update auto-addresses on MAC change

On MAC update add an entry for auto-addressed IPs so
that they get removed and re-allocated.

Also add a check to ensure the length of fixed_ips in the result
is what was expected i.e. ensure we replaced the IP's(as is the current
behaviour) and not just added to the list.

Change-Id: Id1eadce7a18ba82d6c1a42f1afb0267f076f9308
Closes-Bug: #1671548
This commit is contained in:
Derek Higgins 2017-04-20 07:25:26 +01:00
parent 233a68d27c
commit 46d1a890e7
2 changed files with 30 additions and 2 deletions

View File

@ -335,6 +335,25 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
def update_port_with_ips(self, context, host, db_port, new_port, new_mac):
changes = self.Changes(add=[], original=[], remove=[])
auto_assign_subnets = []
if new_mac:
original = self._make_port_dict(db_port, process_extensions=False)
if original.get('mac_address') != new_mac:
original_ips = original.get('fixed_ips', [])
new_ips = new_port.setdefault('fixed_ips', original_ips)
new_ips_subnets = [new_ip['subnet_id'] for new_ip in new_ips]
for orig_ip in original_ips:
if ipv6_utils.is_eui64_address(orig_ip.get('ip_address')):
subnet_to_delete = {}
subnet_to_delete['subnet_id'] = orig_ip['subnet_id']
subnet_to_delete['delete_subnet'] = True
auto_assign_subnets.append(subnet_to_delete)
try:
i = new_ips_subnets.index(orig_ip['subnet_id'])
new_ips[i] = subnet_to_delete
except ValueError:
new_ips.append(subnet_to_delete)
if 'fixed_ips' in new_port:
original = self._make_port_dict(db_port,
process_extensions=False)
@ -362,6 +381,14 @@ class IpamPluggableBackend(ipam_backend_mixin.IpamBackendMixin):
self._update_db_port(context, db_port, new_port, network_id,
new_mac)
getattr(db_port, 'fixed_ips') # refresh relationship before return
if auto_assign_subnets:
port_copy = copy.deepcopy(original)
port_copy.update(new_port)
port_copy['fixed_ips'] = auto_assign_subnets
self.allocate_ips_for_port_and_store(context,
{'port': port_copy}, port_copy['id'])
except Exception:
with excutils.save_and_reraise_exception():
if 'fixed_ips' in new_port:

View File

@ -1381,8 +1381,6 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
subnet_cidr = subnet['subnet']['cidr']
eui_addr = str(netutils.get_ipv6_addr_by_EUI64(subnet_cidr,
port_mac))
# TODO(kevinbenton): remove after bug 1671548 fix
eui_addr = mock.ANY
fip = {'ip_address': eui_addr,
'subnet_id': subnet['subnet']['id']}
self.assertIn(fip, new_port['port']['fixed_ips'])
@ -1408,6 +1406,9 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s
self.assertEqual(new_mac, result['port']['mac_address'])
if updated_fixed_ips is None:
self._verify_ips_after_mac_change(port, result)
else:
self.assertEqual(len(updated_fixed_ips),
len(result['port']['fixed_ips']))
else:
error = self.deserialize(self.fmt, res)
self.assertEqual(expected_error,