Merge "Dnsmasq uses all agent IPs as nameservers"

This commit is contained in:
Jenkins 2014-02-11 09:06:33 +00:00 committed by Gerrit Code Review
commit a397dc8cfe
2 changed files with 108 additions and 0 deletions

View File

@ -16,6 +16,7 @@
# under the License. # under the License.
import abc import abc
import collections
import os import os
import re import re
import shutil import shutil
@ -459,6 +460,9 @@ class Dnsmasq(DhcpLocalProcess):
subnet_to_interface_ip = self._make_subnet_interface_ip_map() subnet_to_interface_ip = self._make_subnet_interface_ip_map()
options = [] options = []
dhcp_ips = collections.defaultdict(list)
subnet_idx_map = {}
for i, subnet in enumerate(self.network.subnets): for i, subnet in enumerate(self.network.subnets):
if not subnet.enable_dhcp: if not subnet.enable_dhcp:
continue continue
@ -466,6 +470,10 @@ class Dnsmasq(DhcpLocalProcess):
options.append( options.append(
self._format_option(i, 'dns-server', self._format_option(i, 'dns-server',
','.join(subnet.dns_nameservers))) ','.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 gateway = subnet.gateway_ip
host_routes = [] host_routes = []
@ -503,6 +511,22 @@ class Dnsmasq(DhcpLocalProcess):
self._format_option(port.id, opt.opt_name, opt.opt_value) self._format_option(port.id, opt.opt_name, opt.opt_value)
for opt in port.extra_dhcp_opts) 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') name = self.get_conf_file_name('opts')
utils.replace_file(name, '\n'.join(options)) utils.replace_file(name, '\n'.join(options))
return name return name

View File

@ -89,6 +89,30 @@ class FakeRouterPort:
self.extra_dhcp_opts = [] 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: class FakeV4HostRoute:
destination = '20.0.0.1/24' destination = '20.0.0.1/24'
nexthop = '20.0.0.1' nexthop = '20.0.0.1'
@ -124,6 +148,42 @@ class FakeV4SubnetGatewayRoute:
dns_nameservers = ['8.8.8.8'] 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: class FakeV6Subnet:
id = 'ffffffff-ffff-ffff-ffff-ffffffffffff' id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
ip_version = 6 ip_version = 6
@ -710,6 +770,30 @@ tag:tag1,249,%s,%s""".lstrip() % (fake_v6,
self.safe.assert_called_once_with('/foo/opts', expected) 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): def test_output_opts_file_single_dhcp(self):
expected = """ expected = """
tag:tag0,option:dns-server,8.8.8.8 tag:tag0,option:dns-server,8.8.8.8