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.

Conflicts:
    neutron/agent/linux/dhcp.py: due to 
    If9aa76fcf121c0e61a7c08088006c5873faee56e missing
        (translation guideline changed in pike - 
        _LW is still there in ocata)
    neutron/tests/unit/agent/linux/test_dhcp.py:
    due to not having Ic1864f7efbc94db1369ac7f3e2879fda86f95a11 in ocata

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

Change-Id: Ia681a5e929df5bf8c97ae9445876c306c34061b5
(cherry picked from commit 8a3ff8a19e)
This commit is contained in:
aojeagarcia 2018-08-22 10:41:14 +02:00 committed by Antonio Ojea
parent bcc9769b02
commit bb3dbf371c
2 changed files with 20 additions and 2 deletions

View File

@ -795,6 +795,11 @@ class Dnsmasq(DhcpLocalProcess):
filename)
continue
parts = l.strip().split()
if len(parts) != 5:
LOG.warning(_LW('Invalid lease entry %(lease)s found'
'in %(file)s lease file, ignoring'),
{'lease': parts, 'file': filename})
continue
(iaid, ip, client_id) = parts[1], parts[2], parts[4]
ip = ip.strip('[]')
if netaddr.IPAddress(ip).version == constants.IP_VERSION_4:

View File

@ -1954,7 +1954,7 @@ class TestDnsmasq(TestBase):
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc",
'client2')]), leases)
def test_read_v6_leases_file_leases(self):
def _test_read_leases_file_leases(self, add_bad_line=False):
filename = '/path/to/file'
lines = [
"1472673289 aa:bb:cc:00:00:01 192.168.1.2 host-192-168-1-2 *",
@ -1968,11 +1968,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_v6_leases_file_leases(filename)
server_id = '00:01:00:01:02:03:04:05:06:07:08:09:0a:0b'
entry1 = {'iaid': '1044800001',
@ -1998,6 +2003,14 @@ class TestDnsmasq(TestBase):
self.assertEqual(expected, leases)
mock_open.assert_called_once_with(filename)
if add_bad_line:
self.assertTrue(mock_log_warn.called)
def test_read_v6_leases_file_leases(self):
self._test_read_leases_file_leases(False)
def test_read_all_leases_file_leases_with_bad_line(self):
self._test_read_leases_file_leases(True)
def test_make_subnet_interface_ip_map(self):
with mock.patch('neutron.agent.linux.ip_lib.IPDevice') as ip_dev: