]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Don't write DHCP opts for SLAAC entries
authorKevin Benton <blak111@gmail.com>
Fri, 18 Sep 2015 14:15:45 +0000 (07:15 -0700)
committerKevin Benton <blak111@gmail.com>
Fri, 18 Sep 2015 17:38:39 +0000 (10:38 -0700)
Change I81b4669eadaa9119e08c6a5e1d2a7b5959babdcc
caused DHCP options to be written for SLAAC entries
when they previously were not. This restores the previous
behavior.

Closes-Bug: #1499054
Change-Id: I81400305f166d62aa4612aab54602abb8178b64c

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

index c79f6577dbedd57976991f1678478afff0b14f55..d47abfca1ec7a984de6dd370298f582c6b9c736f 100644 (file)
@@ -512,7 +512,9 @@ class Dnsmasq(DhcpLocalProcess):
                     # an IPv6 address because of stateless DHCPv6 network.
             host_name,  # Host name.
             name,  # Canonical hostname in the format 'hostname[.domain]'.
-            no_dhcp,  # A flag indicating that the address doesn't need DHCP.
+            no_dhcp,  # A flag indicating that the address doesn't need a DHCP
+                      # IP address.
+            no_opts,  # A flag indication that options shouldn't be written
         )
         """
         v6_nets = dict((subnet.id, subnet) for subnet in
@@ -528,10 +530,14 @@ class Dnsmasq(DhcpLocalProcess):
                 dns_ip_map = {d.ip_address: d for d in dns_assignment}
             for alloc in fixed_ips:
                 no_dhcp = False
+                no_opts = False
                 if alloc.subnet_id in v6_nets:
                     addr_mode = v6_nets[alloc.subnet_id].ipv6_address_mode
                     no_dhcp = addr_mode in (constants.IPV6_SLAAC,
                                             constants.DHCPV6_STATELESS)
+                    # we don't setup anything for SLAAC. It doesn't make sense
+                    # to provide options for a client that won't use DHCP
+                    no_opts = addr_mode == constants.IPV6_SLAAC
 
                 # If dns_name attribute is supported by ports API, return the
                 # dns_assignment generated by the Neutron server. Otherwise,
@@ -545,7 +551,7 @@ class Dnsmasq(DhcpLocalProcess):
                     fqdn = hostname
                     if self.conf.dhcp_domain:
                         fqdn = '%s.%s' % (fqdn, self.conf.dhcp_domain)
-                yield (port, alloc, hostname, fqdn, no_dhcp)
+                yield (port, alloc, hostname, fqdn, no_dhcp, no_opts)
 
     def _get_port_extra_dhcp_opts(self, port):
         return getattr(port, edo_ext.EXTRADHCPOPTS, False)
@@ -577,7 +583,8 @@ class Dnsmasq(DhcpLocalProcess):
             timestamp = int(time.time()) + self.conf.dhcp_lease_duration
         dhcp_enabled_subnet_ids = [s.id for s in self.network.subnets
                                    if s.enable_dhcp]
-        for (port, alloc, hostname, name, no_dhcp) in self._iter_hosts():
+        for host_tuple in self._iter_hosts():
+            port, alloc, hostname, name, no_dhcp, no_opts = host_tuple
             # don't write ip address which belongs to a dhcp disabled subnet
             # or an IPv6 SLAAC/stateless subnet
             if no_dhcp or alloc.subnet_id not in dhcp_enabled_subnet_ids:
@@ -627,9 +634,10 @@ class Dnsmasq(DhcpLocalProcess):
                                    if s.enable_dhcp]
         # NOTE(ihrachyshka): the loop should not log anything inside it, to
         # avoid potential performance drop when lots of hosts are dumped
-        for (port, alloc, hostname, name, no_dhcp) in self._iter_hosts():
+        for host_tuple in self._iter_hosts():
+            port, alloc, hostname, name, no_dhcp, no_opts = host_tuple
             if no_dhcp:
-                if self._get_port_extra_dhcp_opts(port):
+                if not no_opts and self._get_port_extra_dhcp_opts(port):
                     buf.write('%s,%s%s\n' %
                               (port.mac_address, 'set:', port.id))
                 continue
@@ -722,7 +730,8 @@ class Dnsmasq(DhcpLocalProcess):
         file.
         """
         buf = six.StringIO()
-        for (port, alloc, hostname, fqdn, no_dhcp) in self._iter_hosts():
+        for host_tuple in self._iter_hosts():
+            port, alloc, hostname, fqdn, no_dhcp, no_opts = host_tuple
             # It is compulsory to write the `fqdn` before the `hostname` in
             # order to obtain it in PTR responses.
             if alloc:
index 929cc2d35d6ce9fc12bf092d8372c6868ea72b1e..c28c51c9233e5a5af9c8a2bba3c2e3fa158494aa 100644 (file)
@@ -729,6 +729,19 @@ class FakeDualStackNetworkSingleDHCP(object):
     ports = [FakePort1(), FakePort4(), FakeRouterPort()]
 
 
+class FakeDualStackNetworkingSingleDHCPTags(object):
+    id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee'
+
+    subnets = [FakeV4Subnet(), FakeV6SubnetSlaac()]
+    ports = [FakePort1(), FakePort4(), FakeRouterPort()]
+
+    def __init__(self):
+        for port in self.ports:
+            port.extra_dhcp_opts = [
+                DhcpOpt(opt_name='tag:ipxe,bootfile-name',
+                        opt_value='pxelinux.0')]
+
+
 class FakeV4NetworkMultipleTags(object):
     id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
     subnets = [FakeV4Subnet()]
@@ -1852,6 +1865,19 @@ class TestDnsmasq(TestBase):
         self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data),
                                     mock.call(exp_opt_name, exp_opt_data)])
 
+    def test_host_file_on_net_with_v6_slaac_and_v4(self):
+        exp_host_name = '/dhcp/eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee/host'
+        exp_host_data = (
+            '00:00:80:aa:bb:cc,host-192-168-0-2.openstacklocal.,192.168.0.2,'
+            'set:eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee\n'
+            '00:16:3E:C2:77:1D,host-192-168-0-4.openstacklocal.,192.168.0.4,'
+            'set:gggggggg-gggg-gggg-gggg-gggggggggggg\n00:00:0f:rr:rr:rr,'
+            'host-192-168-0-1.openstacklocal.,192.168.0.1,'
+            'set:rrrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr\n').lstrip()
+        dm = self._get_dnsmasq(FakeDualStackNetworkingSingleDHCPTags())
+        dm._output_hosts_file()
+        self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data)])
+
     def test_host_and_opts_file_on_net_with_V6_stateless_and_V4_subnets(
                                                                     self):
         exp_host_name = '/dhcp/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb/host'