diff --git a/astara_router/drivers/dnsmasq.py b/astara_router/drivers/dnsmasq.py index 11dbf69..6bd3f07 100644 --- a/astara_router/drivers/dnsmasq.py +++ b/astara_router/drivers/dnsmasq.py @@ -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) diff --git a/test/unit/drivers/test_dnsmasq.py b/test/unit/drivers/test_dnsmasq.py index 8848519..b1f2e2c 100644 --- a/test/unit/drivers/test_dnsmasq.py +++ b/test/unit/drivers/test_dnsmasq.py @@ -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):