def _format_option(self, ip_version, tag, option, *args):
"""Format DHCP option by option name or code."""
option = str(option)
+ pattern = "(tag:(.*),)?(.*)$"
+ matches = re.match(pattern, option)
+ extra_tag = matches.groups()[0]
+ option = matches.groups()[2]
if isinstance(tag, int):
tag = self._TAG_PREFIX % tag
option = 'option:%s' % option
else:
option = 'option6:%s' % option
-
- return ','.join(('tag:' + tag, '%s' % option) + args)
+ if extra_tag:
+ tags = ('tag:' + tag, extra_tag[:-1], '%s' % option)
+ else:
+ tags = ('tag:' + tag, '%s' % option)
+ return ','.join(tags + args)
@staticmethod
def _convert_to_literal_addrs(ip_version, ips):
ports = [FakePort1(), FakePort4(), FakeRouterPort()]
+class FakeV4NetworkMultipleTags(object):
+ id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
+ subnets = [FakeV4Subnet()]
+ ports = [FakePort1(), FakeRouterPort()]
+ namespace = 'qdhcp-ns'
+
+ def __init__(self):
+ self.ports[0].extra_dhcp_opts = [
+ DhcpOpt(opt_name='tag:ipxe,bootfile-name', opt_value='pxelinux.0')]
+
+
class LocalChild(dhcp.DhcpLocalProcess):
PORTS = {4: [4], 6: [6]}
self._test_output_opts_file(expected, FakeDualV4Pxe3Ports())
+ def test_output_opts_file_multiple_tags(self):
+ expected = (
+ 'tag:tag0,option:dns-server,8.8.8.8\n'
+ 'tag:tag0,option:classless-static-route,20.0.0.1/24,20.0.0.1,'
+ '0.0.0.0/0,192.168.0.1\n'
+ 'tag:tag0,249,20.0.0.1/24,20.0.0.1,0.0.0.0/0,192.168.0.1\n'
+ 'tag:tag0,option:router,192.168.0.1\n'
+ 'tag:eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee,'
+ 'tag:ipxe,option:bootfile-name,pxelinux.0')
+ expected = expected.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, FakeV4NetworkMultipleTags(),
+ version=dhcp.Dnsmasq.MINIMUM_VERSION)
+ dm._output_opts_file()
+
+ 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'