]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Enable adding new tag with options
authorTan Lin <tan.lin.good@gmail.com>
Thu, 23 Oct 2014 11:00:22 +0000 (19:00 +0800)
committerLin Tan <tan.lin.good@gmail.com>
Thu, 15 Jan 2015 01:23:01 +0000 (09:23 +0800)
It is useful to add a new tag when update the options
with dnsmasq.
We have a use case in Ironic to support ipxe with dnsmasq.
It looks like this:
dhcp_opts.append({'opt_name': 'tag:!ipxe,bootfile-name',
                  'opt_value': CONF.pxe.pxe_bootfile_name})

Change-Id: Idfaae9e8f8b7582f988e9da8707ef7d4823c6ff4
Closes-Bug: #1384577

neutron/agent/linux/dhcp.py
neutron/tests/unit/test_linux_dhcp.py

index 534d27969bd2f7dc74ba455d46edd61f66ba5752..2dba7fa7792ddf2d011a7d9f91175df71754e167 100644 (file)
@@ -719,6 +719,10 @@ class Dnsmasq(DhcpLocalProcess):
     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
@@ -728,8 +732,11 @@ class Dnsmasq(DhcpLocalProcess):
                 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):
index 98b5beaab8825f620a0c9b422e16e5a2f847b47f..991aabb4acd74f5cebda2e4863cbb3e48b4f337c 100644 (file)
@@ -472,6 +472,17 @@ class FakeDualStackNetworkSingleDHCP(object):
     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]}
 
@@ -1054,6 +1065,25 @@ class TestDnsmasq(TestBase):
 
         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'