From 8fb69a4633e87446eadd7f0173a0168f78604cbe Mon Sep 17 00:00:00 2001 From: Bertrand Lallau Date: Wed, 11 Jun 2014 15:46:58 +0200 Subject: [PATCH] Dnsmasq config files syntax issue when dhcp_domain is empty When using dhcp-agent with the following property dhcp_domain="" addn_hosts and host files genererated for Dnsmasq have wrong syntax concerning hostname parameter (dot char at the end). As described in RFC-952 the hostname grammar is as follows: ::= *["."] ::= [*[]] Hence it can't be conclude with a dot char. Dnsmasq process is waiting for a hostname (2nd parameter) in the following files: "addn_hosts" file contains: 20.0.0.3 host-20-0-0-3. host-20-0-0-3 "host" file contains: fa:16:3e:bf:e1:e4,host-20-0-0-3.,20.0.0.3 With the patch you will get: "addn_hosts": 20.0.0.3 host-20-0-0-3 host-20-0-0-3 "host": fa:16:3e:bf:e1:e4,host-20-0-0-3,20.0.0.3 Change-Id: I4c10169019becaed6b2968b74f03ef356244a057 Closes-Bug: #1326256 --- neutron/agent/linux/dhcp.py | 6 +++-- neutron/tests/unit/test_linux_dhcp.py | 36 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/neutron/agent/linux/dhcp.py b/neutron/agent/linux/dhcp.py index 7ea1cdb9381..266c125a2a7 100644 --- a/neutron/agent/linux/dhcp.py +++ b/neutron/agent/linux/dhcp.py @@ -454,7 +454,7 @@ class Dnsmasq(DhcpLocalProcess): port, # a DictModel instance representing the port. alloc, # a DictModel instance of the allocated ip and subnet. host_name, # Host name. - name, # Host name and domain name in the format 'hostname.domain'. + name, # Canonical hostname in the format 'hostname[.domain]'. ) """ v6_nets = dict((subnet.id, subnet) for subnet in @@ -471,7 +471,9 @@ class Dnsmasq(DhcpLocalProcess): continue hostname = 'host-%s' % alloc.ip_address.replace( '.', '-').replace(':', '-') - fqdn = '%s.%s' % (hostname, self.conf.dhcp_domain) + fqdn = hostname + if self.conf.dhcp_domain: + fqdn = '%s.%s' % (fqdn, self.conf.dhcp_domain) yield (port, alloc, hostname, fqdn) def _output_hosts_file(self): diff --git a/neutron/tests/unit/test_linux_dhcp.py b/neutron/tests/unit/test_linux_dhcp.py index 14b80c79219..a7c9671fc1b 100644 --- a/neutron/tests/unit/test_linux_dhcp.py +++ b/neutron/tests/unit/test_linux_dhcp.py @@ -767,8 +767,12 @@ class TestDnsmasq(TestBase): self._test_spawn(['--conf-file=/foo', '--domain=openstacklocal']) def test_spawn_no_dhcp_domain(self): + (exp_host_name, exp_host_data, + exp_addn_name, exp_addn_data) = self._test_no_dhcp_domain_alloc_data self.conf.set_override('dhcp_domain', '') self._test_spawn(['--conf-file=']) + self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data), + mock.call(exp_addn_name, exp_addn_data)]) def test_spawn_no_dnsmasq_ipv6_mode(self): network = FakeV6Network() @@ -1062,6 +1066,38 @@ tag:tag0,option:router""".lstrip() self.safe.assert_called_once_with('/foo/opts', expected) + @property + def _test_no_dhcp_domain_alloc_data(self): + exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host' + exp_host_data = ('00:00:80:aa:bb:cc,host-192-168-0-2,' + '192.168.0.2\n' + '00:00:f3:aa:bb:cc,host-fdca-3ba5-a17a-4ba3--2,' + '[fdca:3ba5:a17a:4ba3::2]\n' + '00:00:0f:aa:bb:cc,host-192-168-0-3,' + '192.168.0.3\n' + '00:00:0f:aa:bb:cc,host-fdca-3ba5-a17a-4ba3--3,' + '[fdca:3ba5:a17a:4ba3::3]\n' + '00:00:0f:rr:rr:rr,host-192-168-0-1,' + '192.168.0.1\n').lstrip() + exp_addn_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/addn_hosts' + exp_addn_data = ( + '192.168.0.2\t' + 'host-192-168-0-2 host-192-168-0-2\n' + 'fdca:3ba5:a17a:4ba3::2\t' + 'host-fdca-3ba5-a17a-4ba3--2 ' + 'host-fdca-3ba5-a17a-4ba3--2\n' + '192.168.0.3\thost-192-168-0-3 ' + 'host-192-168-0-3\n' + 'fdca:3ba5:a17a:4ba3::3\t' + 'host-fdca-3ba5-a17a-4ba3--3 ' + 'host-fdca-3ba5-a17a-4ba3--3\n' + '192.168.0.1\t' + 'host-192-168-0-1 ' + 'host-192-168-0-1\n' + ).lstrip() + return (exp_host_name, exp_host_data, + exp_addn_name, exp_addn_data) + @property def _test_reload_allocation_data(self): exp_host_name = '/dhcp/cccccccc-cccc-cccc-cccc-cccccccccccc/host'