Work around a potential bug in dnsmasq's config parser.

It seems that dnsmasq sometimes mistakes IPV6 addresses in dhcp-host config
options for hardware addresses;  to work around this, only ever specify *one*
IPv4 and IPv6 address for the dhcp-host config value.

Closes-bug: 1545054
Change-Id: I8f508bf12a09efb46027737f3d1d285aef826f67
This commit is contained in:
Ryan Petrello 2016-02-18 12:51:00 -05:00
parent 8843fc2f70
commit dae911ea41
2 changed files with 45 additions and 9 deletions

View File

@ -15,8 +15,12 @@
# under the License.
import operator
import os
import time
import itertools
import netaddr
from astara_router.drivers import base
from astara_router import utils
@ -123,14 +127,21 @@ class DHCPManager(base.Manager):
for r in subnet.host_routes
)
config.extend(
'dhcp-host=%s,%s,%s' % (
a.mac_address,
','.join('[%s]' % ip if ':' in ip else ip
for ip in a.dhcp_addresses),
a.hostname)
for a in network.address_allocations
)
for a in network.address_allocations:
dhcp_addresses = sorted(map(netaddr.IPAddress, a.dhcp_addresses))
groups = itertools.groupby(dhcp_addresses,
key=operator.attrgetter('version'))
dhcp_addresses = [str(next(members)) for k, members in groups]
config.extend([
'dhcp-host=%s,%s,%s' % (
a.mac_address,
','.join(
'[%s]' % ip if ':' in ip else ip
for ip in dhcp_addresses
),
a.hostname
)
])
return '\n'.join(config)

View File

@ -124,13 +124,38 @@ class DnsmasqTestCase(TestCase):
'dhcp-host=fa:da:fa:da:fa:da:,192.168.1.2,192-168-1-2.local'
]), config
def test_build_dhcp_config_multiple_ips(self):
many_ips = mock.Mock()
many_ips.subnets = [ext_subnet]
many_ips.is_internal_network = False
many_ips.is_external_network = True
many_ips.is_tenant_network = False
many_ips.interface.ifname = 'ge0'
many_ips.address_allocations = [models.Allocation(
'fa:da:fa:da:fa:da:',
{'192.168.1.2': True, '192.168.1.3': True, '192.168.1.4': True, 'dead:beef::2': True}, # ip: DHCP enabled
'192-168-1-2.local',
'e3300819-d7b9-4d8d-9d7c-a6380ff78ca7'
)]
config = self.mgr._build_dhcp_config('ge0', many_ips)
assert config == '\n'.join([
'interface=ge0',
'dhcp-range=set:ge0_0,dead:beef::,static,86400s',
'dhcp-option=tag:ge0_0,option6:dns-server,8.8.8.8',
'dhcp-option=tag:ge0_0,option6:dns-server,8.8.4.4',
('dhcp-option=tag:ge0_0,option6:classless-static-route,'
'172.16.0.0/16,192.168.1.1'),
'dhcp-host=fa:da:fa:da:fa:da:,192.168.1.2,[dead:beef::2],192-168-1-2.local',
]), config
def test_build_dhcp_config_int(self):
config = self.mgr._build_dhcp_config('ge1', int_net)
assert config == '\n'.join([
'interface=ge1',
'dhcp-range=set:ge1_0,9.9.9.0,static,86400s',
'dhcp-range=set:ge1_1,face::,static,86400s',
'dhcp-host=fb:db:fb:db:fb:db,[face::2],9.9.9.2,9-9-9-2.local',
'dhcp-host=fb:db:fb:db:fb:db,9.9.9.2,[face::2],9-9-9-2.local',
]), config
def test_restart(self):