Merge "Do not release DHCP lease when no client ID is set on port" into stable/rocky

This commit is contained in:
Zuul 2019-03-22 23:23:52 +00:00 committed by Gerrit Code Review
commit cfb6e0eb72
2 changed files with 56 additions and 0 deletions

View File

@ -861,6 +861,19 @@ class Dnsmasq(DhcpLocalProcess):
if not entries_to_release: if not entries_to_release:
return return
# If the VM advertises a client ID in its lease, but its not set in
# the port's Extra DHCP Opts, the lease will not be filtered above.
# Release the lease only if client ID is set in port DB and a mismatch
# Otherwise the lease is released when other ports are deleted/updated
entries_with_no_client_id = set()
for ip, mac, client_id in entries_to_release:
if client_id:
entry_no_client_id = (ip, mac, None)
if (entry_no_client_id in old_leases and
entry_no_client_id in new_leases):
entries_with_no_client_id.add((ip, mac, client_id))
entries_to_release -= entries_with_no_client_id
# Try DHCP_RELEASE_TRIES times to release a lease, re-reading the # Try DHCP_RELEASE_TRIES times to release a lease, re-reading the
# file each time to see if it's still there. We loop +1 times to # file each time to see if it's still there. We loop +1 times to
# check the lease file one last time before logging any remaining # check the lease file one last time before logging any remaining

View File

@ -2205,6 +2205,49 @@ class TestDnsmasq(TestBase):
dnsmasq._release_lease.assert_called_once_with( dnsmasq._release_lease.assert_called_once_with(
mac1, ip1, constants.IP_VERSION_4, client_id1, 'server_id', mac1) mac1, ip1, constants.IP_VERSION_4, client_id1, 'server_id', mac1)
def test_release_unused_leases_one_lease_with_client_id_none(self):
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
ip1 = '192.168.0.2'
mac1 = '00:00:80:aa:bb:cc'
client_id1 = 'client1'
ip2 = '192.168.0.4'
mac2 = '00:16:3E:C2:77:1D'
client_id2 = 'test4'
ip6 = '2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d'
old_leases = set([(ip1, mac1, client_id1), (ip2, mac2, None)])
dnsmasq._read_hosts_file_leases = mock.Mock(return_value=old_leases)
dnsmasq._output_hosts_file = mock.Mock()
# Because the lease release code could fire multiple times, the
# second read of the lease file must not have the entries that
# would have been released.
dnsmasq._read_leases_file_leases = mock.Mock(
side_effect=[{ip6: {'iaid': 0xff,
'client_id': 'client_id',
'server_id': 'server_id'},
ip1: {'iaid': mac1,
'client_id': client_id1,
'server_id': 'server_id'},
ip2: {'iaid': mac2,
'client_id': client_id2,
'server_id': 'server_id'}
},
{ip6: {'iaid': 0xff,
'client_id': 'client_id',
'server_id': 'server_id'},
ip2: {'iaid': mac2,
'client_id': client_id2,
'server_id': 'server_id'}
}])
dnsmasq._release_lease = mock.Mock()
dnsmasq.network.ports = [FakePort4()]
dnsmasq._release_unused_leases()
dnsmasq._release_lease.assert_called_once_with(
mac1, ip1, constants.IP_VERSION_4, client_id1, 'server_id', mac1)
def test_release_unused_leases_one_lease_from_leases_file(self): def test_release_unused_leases_one_lease_from_leases_file(self):
# leases file has a stale entry that is not in the host file # leases file has a stale entry that is not in the host file
dnsmasq = self._get_dnsmasq(FakeDualNetwork()) dnsmasq = self._get_dnsmasq(FakeDualNetwork())