Fixes dnsmasq host file parsing with "addr6_list"
This patch fixes: - The IPv6 tag added in the "host" file if is supported in dnsmasq. That shifts all other parameters in the register. - IPv6 registers can have more than one IP address; in this case, the method "_read_hosts_file_leases" should return a tuple per IP address. Change-Id: I4d0bc1eb9448366d8f1b2dacc9c5c2e4e6958253 Closes-Bug: #1884105 (cherry picked from commit8eb4955bb6
) (cherry picked from commit68706b556b
)
This commit is contained in:
parent
c5e00e551c
commit
b4707c1691
|
@ -28,6 +28,7 @@ from neutron_lib.utils import file as file_utils
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import fileutils
|
from oslo_utils import fileutils
|
||||||
|
from oslo_utils import netutils
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
@ -835,6 +836,11 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
str(DHCP_OPT_CLIENT_ID_NUM)):
|
str(DHCP_OPT_CLIENT_ID_NUM)):
|
||||||
return opt.opt_value
|
return opt.opt_value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _parse_ip_addresses(ip_list):
|
||||||
|
ip_list = [ip.strip('[]') for ip in ip_list]
|
||||||
|
return [ip for ip in ip_list if netutils.is_valid_ip(ip)]
|
||||||
|
|
||||||
def _read_hosts_file_leases(self, filename):
|
def _read_hosts_file_leases(self, filename):
|
||||||
leases = set()
|
leases = set()
|
||||||
try:
|
try:
|
||||||
|
@ -846,11 +852,14 @@ class Dnsmasq(DhcpLocalProcess):
|
||||||
if host[1].startswith('set:'):
|
if host[1].startswith('set:'):
|
||||||
continue
|
continue
|
||||||
if host[1].startswith(self._ID):
|
if host[1].startswith(self._ID):
|
||||||
ip = host[3].strip('[]')
|
ips = self._parse_ip_addresses(host[3:])
|
||||||
client_id = host[1][len(self._ID):]
|
client_id = host[1][len(self._ID):]
|
||||||
|
elif host[1].startswith('tag:'):
|
||||||
|
ips = self._parse_ip_addresses(host[3:])
|
||||||
else:
|
else:
|
||||||
ip = host[2].strip('[]')
|
ips = self._parse_ip_addresses(host[2:])
|
||||||
leases.add((ip, mac, client_id))
|
for ip in ips:
|
||||||
|
leases.add((ip, mac, client_id))
|
||||||
except (OSError, IOError):
|
except (OSError, IOError):
|
||||||
LOG.debug('Error while reading hosts file %s', filename)
|
LOG.debug('Error while reading hosts file %s', filename)
|
||||||
return leases
|
return leases
|
||||||
|
|
|
@ -2572,51 +2572,57 @@ class TestDnsmasq(TestBase):
|
||||||
def test_release_unused_leases_one_lease_mult_times_removed(self):
|
def test_release_unused_leases_one_lease_mult_times_removed(self):
|
||||||
self._test_release_unused_leases_one_lease_mult_times(True)
|
self._test_release_unused_leases_one_lease_mult_times(True)
|
||||||
|
|
||||||
def test_read_hosts_file_leases(self):
|
def test__parse_ip_addresses(self):
|
||||||
|
ip_list = ['192.168.0.1', '[fdca:3ba5:a17a::1]', 'no_ip_address']
|
||||||
|
self.assertEqual(['192.168.0.1', 'fdca:3ba5:a17a::1'],
|
||||||
|
dhcp.Dnsmasq._parse_ip_addresses(ip_list))
|
||||||
|
|
||||||
|
def _test_read_hosts_file_leases(self, lines, expected_result):
|
||||||
filename = '/path/to/file'
|
filename = '/path/to/file'
|
||||||
lines = ["00:00:80:aa:bb:cc,inst-name,192.168.0.1",
|
|
||||||
"00:00:80:aa:bb:cc,inst-name,[fdca:3ba5:a17a::1]"]
|
|
||||||
mock_open = self.useFixture(
|
mock_open = self.useFixture(
|
||||||
lib_fixtures.OpenFixture(filename, '\n'.join(lines))).mock_open
|
lib_fixtures.OpenFixture(filename, '\n'.join(lines))).mock_open
|
||||||
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
|
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
|
||||||
leases = dnsmasq._read_hosts_file_leases(filename)
|
leases = dnsmasq._read_hosts_file_leases(filename)
|
||||||
|
self.assertEqual(expected_result, leases)
|
||||||
self.assertEqual(set([("192.168.0.1", "00:00:80:aa:bb:cc", None),
|
|
||||||
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc",
|
|
||||||
None)]), leases)
|
|
||||||
mock_open.assert_called_once_with(filename)
|
mock_open.assert_called_once_with(filename)
|
||||||
|
|
||||||
|
def test_read_hosts_file_leases(self):
|
||||||
|
lines = ["00:00:80:aa:bb:cc,inst-name,192.168.0.1",
|
||||||
|
"00:00:80:aa:bb:cc,inst-name,[fdca:3ba5:a17a::1]"]
|
||||||
|
result = {("192.168.0.1", "00:00:80:aa:bb:cc", None),
|
||||||
|
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc", None)}
|
||||||
|
self._test_read_hosts_file_leases(lines, result)
|
||||||
|
|
||||||
def test_read_hosts_file_leases_with_client_id(self):
|
def test_read_hosts_file_leases_with_client_id(self):
|
||||||
filename = '/path/to/file'
|
|
||||||
lines = ["00:00:80:aa:bb:cc,id:client1,inst-name,192.168.0.1",
|
lines = ["00:00:80:aa:bb:cc,id:client1,inst-name,192.168.0.1",
|
||||||
"00:00:80:aa:bb:cc,id:client2,inst-name,"
|
"00:00:80:aa:bb:cc,id:client2,inst-name,"
|
||||||
"[fdca:3ba5:a17a::1]"]
|
"[fdca:3ba5:a17a::1]"]
|
||||||
mock_open = self.useFixture(
|
result = {("192.168.0.1", "00:00:80:aa:bb:cc", 'client1'),
|
||||||
lib_fixtures.OpenFixture(filename, '\n'.join(lines))).mock_open
|
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc", 'client2')}
|
||||||
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
|
self._test_read_hosts_file_leases(lines, result)
|
||||||
leases = dnsmasq._read_hosts_file_leases(filename)
|
|
||||||
|
|
||||||
self.assertEqual(set([("192.168.0.1", "00:00:80:aa:bb:cc", 'client1'),
|
|
||||||
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc",
|
|
||||||
'client2')]), leases)
|
|
||||||
mock_open.assert_called_once_with(filename)
|
|
||||||
|
|
||||||
def test_read_hosts_file_leases_with_stateless_IPv6_tag(self):
|
def test_read_hosts_file_leases_with_stateless_IPv6_tag(self):
|
||||||
filename = self.get_temp_file_path('leases')
|
lines = [
|
||||||
with open(filename, "w") as leasesfile:
|
"00:00:80:aa:bb:cc,id:client1,inst-name,192.168.0.1",
|
||||||
lines = [
|
"00:00:80:aa:bb:cc,set:ccccccccc-cccc-cccc-cccc-cccccccc",
|
||||||
"00:00:80:aa:bb:cc,id:client1,inst-name,192.168.0.1\n",
|
"00:00:80:aa:bb:cc,id:client2,inst-name,[fdca:3ba5:a17a::1]"]
|
||||||
"00:00:80:aa:bb:cc,set:ccccccccc-cccc-cccc-cccc-cccccccc\n",
|
result = {("192.168.0.1", "00:00:80:aa:bb:cc", 'client1'),
|
||||||
"00:00:80:aa:bb:cc,id:client2,inst-name,[fdca:3ba5:a17a::1]\n"]
|
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc", 'client2')}
|
||||||
for line in lines:
|
self._test_read_hosts_file_leases(lines, result)
|
||||||
leasesfile.write(line)
|
|
||||||
|
|
||||||
dnsmasq = self._get_dnsmasq(FakeDualNetwork())
|
def test_read_hosts_file_leases_with_IPv6_tag_and_multiple_ips(self):
|
||||||
leases = dnsmasq._read_hosts_file_leases(filename)
|
lines = [
|
||||||
|
"00:00:80:aa:bb:cc,id:client1,inst-name,192.168.0.1",
|
||||||
self.assertEqual(set([("192.168.0.1", "00:00:80:aa:bb:cc", 'client1'),
|
"00:00:80:aa:bb:cc,set:ccccccccc-cccc-cccc-cccc-cccccccc",
|
||||||
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc",
|
"00:00:80:aa:bb:cc,tag:dhcpv6,inst-name,[fdca:3ba5:a17a::1],"
|
||||||
'client2')]), leases)
|
"[fdca:3ba5:a17a::2],[fdca:3ba5:a17a::3],[fdca:3ba5:a17a::4],"
|
||||||
|
"set:port-fe2baee9-aba9-4b67-be03-be4aeee40cca"]
|
||||||
|
result = {("192.168.0.1", "00:00:80:aa:bb:cc", 'client1'),
|
||||||
|
("fdca:3ba5:a17a::1", "00:00:80:aa:bb:cc", None),
|
||||||
|
("fdca:3ba5:a17a::2", "00:00:80:aa:bb:cc", None),
|
||||||
|
("fdca:3ba5:a17a::3", "00:00:80:aa:bb:cc", None),
|
||||||
|
("fdca:3ba5:a17a::4", "00:00:80:aa:bb:cc", None)}
|
||||||
|
self._test_read_hosts_file_leases(lines, result)
|
||||||
|
|
||||||
def _test_read_leases_file_leases(self, ip_version, add_bad_line=False):
|
def _test_read_leases_file_leases(self, ip_version, add_bad_line=False):
|
||||||
filename = '/path/to/file'
|
filename = '/path/to/file'
|
||||||
|
|
Loading…
Reference in New Issue