Dnsmasq uses all agent IPs as nameservers

Add dhcp option which provides all agent IPs
which will be used as nameserver entries when
neutron uses multiple dhcp agent per network and
when there is no dns nameserver provided by the
neutron server.

Change-Id: I639a844bba212a731616851ff479a5e735612cf8
Closes-bug: #1259482
This commit is contained in:
Sylvain Afchain 2013-12-04 21:01:06 +01:00
parent 8d13b71442
commit 2afff147c4
2 changed files with 108 additions and 0 deletions

View File

@ -16,6 +16,7 @@
# under the License.
import abc
import collections
import os
import re
import shutil
@ -442,6 +443,9 @@ class Dnsmasq(DhcpLocalProcess):
subnet_to_interface_ip = self._make_subnet_interface_ip_map()
options = []
dhcp_ips = collections.defaultdict(list)
subnet_idx_map = {}
for i, subnet in enumerate(self.network.subnets):
if not subnet.enable_dhcp:
continue
@ -449,6 +453,10 @@ class Dnsmasq(DhcpLocalProcess):
options.append(
self._format_option(i, 'dns-server',
','.join(subnet.dns_nameservers)))
else:
# use the dnsmasq ip as nameservers only if there is no
# dns-server submitted by the server
subnet_idx_map[subnet.id] = i
gateway = subnet.gateway_ip
host_routes = []
@ -486,6 +494,22 @@ class Dnsmasq(DhcpLocalProcess):
self._format_option(port.id, opt.opt_name, opt.opt_value)
for opt in port.extra_dhcp_opts)
# provides all dnsmasq ip as dns-server if there is more than
# one dnsmasq for a subnet and there is no dns-server submitted
# by the server
if port.device_owner == 'network:dhcp':
for ip in port.fixed_ips:
i = subnet_idx_map.get(ip.subnet_id)
if i is None:
continue
dhcp_ips[i].append(ip.ip_address)
for i, ips in dhcp_ips.items():
if len(ips) > 1:
options.append(self._format_option(i,
'dns-server',
','.join(ips)))
name = self.get_conf_file_name('opts')
utils.replace_file(name, '\n'.join(options))
return name

View File

@ -89,6 +89,30 @@ class FakeRouterPort:
self.extra_dhcp_opts = []
class FakePortMultipleAgents1:
id = 'rrrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr'
admin_state_up = True
device_owner = 'network:dhcp'
fixed_ips = [FakeIPAllocation('192.168.0.5',
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
mac_address = '00:00:0f:dd:dd:dd'
def __init__(self):
self.extra_dhcp_opts = []
class FakePortMultipleAgents2:
id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
admin_state_up = True
device_owner = 'network:dhcp'
fixed_ips = [FakeIPAllocation('192.168.0.6',
'dddddddd-dddd-dddd-dddd-dddddddddddd')]
mac_address = '00:00:0f:ee:ee:ee'
def __init__(self):
self.extra_dhcp_opts = []
class FakeV4HostRoute:
destination = '20.0.0.1/24'
nexthop = '20.0.0.1'
@ -124,6 +148,42 @@ class FakeV4SubnetGatewayRoute:
dns_nameservers = ['8.8.8.8']
class FakeV4SubnetMultipleAgentsWithoutDnsProvided:
id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
ip_version = 4
cidr = '192.168.0.0/24'
gateway_ip = '192.168.0.1'
enable_dhcp = True
dns_nameservers = []
host_routes = []
class FakeV4MultipleAgentsWithoutDnsProvided:
id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
subnets = [FakeV4SubnetMultipleAgentsWithoutDnsProvided()]
ports = [FakePort1(), FakePort2(), FakePort3(), FakeRouterPort(),
FakePortMultipleAgents1(), FakePortMultipleAgents2()]
namespace = 'qdhcp-ns'
class FakeV4SubnetMultipleAgentsWithDnsProvided:
id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
ip_version = 4
cidr = '192.168.0.0/24'
gateway_ip = '192.168.0.1'
enable_dhcp = True
dns_nameservers = ['8.8.8.8']
host_routes = []
class FakeV4MultipleAgentsWithDnsProvided:
id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
subnets = [FakeV4SubnetMultipleAgentsWithDnsProvided()]
ports = [FakePort1(), FakePort2(), FakePort3(), FakeRouterPort(),
FakePortMultipleAgents1(), FakePortMultipleAgents2()]
namespace = 'qdhcp-ns'
class FakeV6Subnet:
id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
ip_version = 6
@ -716,6 +776,30 @@ tag:tag1,249,%s,%s""".lstrip() % (fake_v6,
self.safe.assert_called_once_with('/foo/opts', expected)
def test_output_opts_file_multiple_agents_without_dns_provided(self):
expected = """
tag:tag0,option:router,192.168.0.1
tag:tag0,option:dns-server,192.168.0.5,192.168.0.6""".lstrip()
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
conf_fn.return_value = '/foo/opts'
dm = dhcp.Dnsmasq(self.conf,
FakeV4MultipleAgentsWithoutDnsProvided(),
version=float(2.59))
dm._output_opts_file()
self.safe.assert_called_once_with('/foo/opts', expected)
def test_output_opts_file_multiple_agents_with_dns_provided(self):
expected = """
tag:tag0,option:dns-server,8.8.8.8
tag:tag0,option:router,192.168.0.1""".lstrip()
with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
conf_fn.return_value = '/foo/opts'
dm = dhcp.Dnsmasq(self.conf,
FakeV4MultipleAgentsWithDnsProvided(),
version=float(2.59))
dm._output_opts_file()
self.safe.assert_called_once_with('/foo/opts', expected)
def test_output_opts_file_single_dhcp(self):
expected = """
tag:tag0,option:dns-server,8.8.8.8