Browse Source

Merge "Do not release DHCP lease when no client ID is set on port"

Zuul 1 month ago
parent
commit
7041c25483
2 changed files with 56 additions and 0 deletions
  1. 13
    0
      neutron/agent/linux/dhcp.py
  2. 43
    0
      neutron/tests/unit/agent/linux/test_dhcp.py

+ 13
- 0
neutron/agent/linux/dhcp.py View File

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

+ 43
- 0
neutron/tests/unit/agent/linux/test_dhcp.py View File

@@ -2263,6 +2263,49 @@ class TestDnsmasq(TestBase):
2263 2263
         dnsmasq._release_lease.assert_called_once_with(
2264 2264
             mac1, ip1, constants.IP_VERSION_4, client_id1, 'server_id', mac1)
2265 2265
 
2266
+    def test_release_unused_leases_one_lease_with_client_id_none(self):
2267
+        dnsmasq = self._get_dnsmasq(FakeDualNetwork())
2268
+
2269
+        ip1 = '192.168.0.2'
2270
+        mac1 = '00:00:80:aa:bb:cc'
2271
+        client_id1 = 'client1'
2272
+        ip2 = '192.168.0.4'
2273
+        mac2 = '00:16:3E:C2:77:1D'
2274
+        client_id2 = 'test4'
2275
+        ip6 = '2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d'
2276
+
2277
+        old_leases = set([(ip1, mac1, client_id1), (ip2, mac2, None)])
2278
+        dnsmasq._read_hosts_file_leases = mock.Mock(return_value=old_leases)
2279
+        dnsmasq._output_hosts_file = mock.Mock()
2280
+        # Because the lease release code could fire multiple times, the
2281
+        # second read of the lease file must not have the entries that
2282
+        # would have been released.
2283
+        dnsmasq._read_leases_file_leases = mock.Mock(
2284
+            side_effect=[{ip6: {'iaid': 0xff,
2285
+                                'client_id': 'client_id',
2286
+                                'server_id': 'server_id'},
2287
+                          ip1: {'iaid': mac1,
2288
+                                'client_id': client_id1,
2289
+                                'server_id': 'server_id'},
2290
+                          ip2: {'iaid': mac2,
2291
+                                'client_id': client_id2,
2292
+                                'server_id': 'server_id'}
2293
+                          },
2294
+                         {ip6: {'iaid': 0xff,
2295
+                                'client_id': 'client_id',
2296
+                                'server_id': 'server_id'},
2297
+                          ip2: {'iaid': mac2,
2298
+                                'client_id': client_id2,
2299
+                                'server_id': 'server_id'}
2300
+                          }])
2301
+        dnsmasq._release_lease = mock.Mock()
2302
+        dnsmasq.network.ports = [FakePort4()]
2303
+
2304
+        dnsmasq._release_unused_leases()
2305
+
2306
+        dnsmasq._release_lease.assert_called_once_with(
2307
+            mac1, ip1, constants.IP_VERSION_4, client_id1, 'server_id', mac1)
2308
+
2266 2309
     def test_release_unused_leases_one_lease_from_leases_file(self):
2267 2310
         # leases file has a stale entry that is not in the host file
2268 2311
         dnsmasq = self._get_dnsmasq(FakeDualNetwork())

Loading…
Cancel
Save