Parse dhcp leases file in a more robust way

It turns out that in environments with a big number of VMs, sometimes
the neutron dhcp agent fails to read the dhcp lease file because some
lines with the ipv4/ipv6 entries don't have enough fields and causes the
dhcp agent to fail.

When this happens the agent calls sync_state to
fully resync the agent state, that causes a serious performance problems
in scale environments.

We need to be more robust reading the file to handle these exceptions.

Co-authored-by: stephen-ma
Partial-Bug: #1788556

Change-Id: Ia681a5e929df5bf8c97ae9445876c306c34061b5
This commit is contained in:
aojeagarcia 2018-08-22 10:41:14 +02:00 committed by Brian Haley
parent 0980ec0a8d
commit 8a3ff8a19e
2 changed files with 16 additions and 2 deletions

View File

@ -816,6 +816,10 @@ class Dnsmasq(DhcpLocalProcess):
filename)
continue
parts = l.strip().split()
if len(parts) != 5:
LOG.warning('Invalid lease entry %s found in %s '
'lease file, ignoring', parts, filename)
continue
(iaid, ip, client_id) = parts[1], parts[2], parts[4]
ip = ip.strip('[]')
if (ip_version and

View File

@ -2359,7 +2359,7 @@ class TestDnsmasq(TestBase):
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc",
'client2')]), leases)
def _test_read_leases_file_leases(self, ip_version):
def _test_read_leases_file_leases(self, ip_version, add_bad_line=False):
filename = '/path/to/file'
lines = [
"1472673289 aa:bb:cc:00:00:02 192.168.1.2 host-192-168-1-2 *",
@ -2373,11 +2373,16 @@ class TestDnsmasq(TestBase):
"1472599048 1044800003 [2001:DB8::c] host-2001-db8--c "
"00:04:4f:f0:cd:ca:5e:77:41:bc:9d:7f:5c:33:31:37:5d:80:77:b4"
]
bad_line = '1472673289 aa:bb:cc:00:00:05 192.168.1.5 host-192.168-1-5'
if add_bad_line:
lines.append(bad_line)
mock_open = self.useFixture(
tools.OpenFixture(filename, '\n'.join(lines))).mock_open
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
with mock.patch('os.path.exists', return_value=True):
with mock.patch('os.path.exists', return_value=True), \
mock.patch.object(dhcp.LOG, 'warning') as mock_log_warn:
leases = dnsmasq._read_leases_file_leases(filename, ip_version)
server_id = '00:01:00:01:02:03:04:05:06:07:08:09:0a:0b'
entry1 = {'iaid': '1044800001',
@ -2426,6 +2431,8 @@ class TestDnsmasq(TestBase):
mock_open.assert_called_once_with(filename)
self.assertEqual(expected, leases)
if add_bad_line:
self.assertTrue(mock_log_warn.called)
def test_read_v6_leases_file_leases(self):
self._test_read_leases_file_leases(constants.IP_VERSION_6)
@ -2436,6 +2443,9 @@ class TestDnsmasq(TestBase):
def test_read_all_leases_file_leases(self):
self._test_read_leases_file_leases(None)
def test_read_all_leases_file_leases_with_bad_line(self):
self._test_read_leases_file_leases(None, True)
def test_make_subnet_interface_ip_map(self):
with mock.patch('neutron.agent.linux.ip_lib.IPDevice') as ip_dev:
ip_dev.return_value.addr.list.return_value = [