]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Use 0.0.0.0/0 host route as router option
authorVishvananda Ishaya <vishvananda@gmail.com>
Mon, 10 Jun 2013 21:37:26 +0000 (14:37 -0700)
committerVishvananda Ishaya <vishvananda@gmail.com>
Wed, 26 Jun 2013 18:01:11 +0000 (11:01 -0700)
There is a currently a hacky way to get the dhcp-agent to hand out a
gateway route using a host route on the subnet. If you pass a route
that has 0.0.0.0/0 as its destination, dnsmasq will pass it as a static
route. Unfortunately it will also pass the router option if the subnet
has a gateway set. This is inconsistent and precludes users from options
that are available in nova-network like using an external gateway.

This patch fixes things by allowing a 0.0.0.0/0 host route to override
the router setting passed by dnsmasq. This prevents the situation
where dnsmasq hands out two default routes.

Change-Id: Ia70223070bfd437f1c2eb48fde94491d7ee61fcb

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

index 54f620d78300d90a49e580fbd06518ba061fb82e..fb1a68705f879989640b1dadc08117b9b30267e9 100644 (file)
@@ -367,8 +367,13 @@ class Dnsmasq(DhcpLocalProcess):
                     self._format_option(i, 'dns-server',
                                         ','.join(subnet.dns_nameservers)))
 
-            host_routes = ["%s,%s" % (hr.destination, hr.nexthop)
-                           for hr in subnet.host_routes]
+            gateway = subnet.gateway_ip
+            host_routes = []
+            for hr in subnet.host_routes:
+                if hr.destination == "0.0.0.0/0":
+                    gateway = hr.nexthop
+                else:
+                    host_routes.append("%s,%s" % (hr.destination, hr.nexthop))
 
             # Add host routes for isolated network segments
             enable_metadata = (
@@ -388,9 +393,8 @@ class Dnsmasq(DhcpLocalProcess):
                                         ','.join(host_routes)))
 
             if subnet.ip_version == 4:
-                if subnet.gateway_ip:
-                    options.append(self._format_option(i, 'router',
-                                                       subnet.gateway_ip))
+                if gateway:
+                    options.append(self._format_option(i, 'router', gateway))
                 else:
                     options.append(self._format_option(i, 'router'))
 
index 0590922805e9a122f01d97ff5ca001980f71d4a6..ed2f89f4e50a73a64a72cda40f105a23f449ff96 100644 (file)
@@ -60,6 +60,11 @@ class FakeV4HostRoute:
     nexthop = '20.0.0.1'
 
 
+class FakeV4HostRouteGateway:
+    destination = '0.0.0.0/0'
+    nexthop = '10.0.0.1'
+
+
 class FakeV6HostRoute:
     destination = 'gdca:3ba5:a17a:4ba3::/64'
     nexthop = 'gdca:3ba5:a17a:4ba3::1'
@@ -75,6 +80,16 @@ class FakeV4Subnet:
     dns_nameservers = ['8.8.8.8']
 
 
+class FakeV4SubnetGatewayRoute:
+    id = 'dddddddd-dddd-dddd-dddd-dddddddddddd'
+    ip_version = 4
+    cidr = '192.168.0.0/24'
+    gateway_ip = '192.168.0.1'
+    enable_dhcp = True
+    host_routes = [FakeV4HostRouteGateway]
+    dns_nameservers = ['8.8.8.8']
+
+
 class FakeV6Subnet:
     id = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
     ip_version = 6
@@ -123,6 +138,12 @@ class FakeDualNetwork:
     ports = [FakePort1(), FakePort2(), FakePort3()]
 
 
+class FakeDualNetworkGatewayRoute:
+    id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
+    subnets = [FakeV4SubnetGatewayRoute(), FakeV6Subnet()]
+    ports = [FakePort1(), FakePort2(), FakePort3()]
+
+
 class FakeDualNetworkSingleDHCP:
     id = 'cccccccc-cccc-cccc-cccc-cccccccccccc'
     subnets = [FakeV4Subnet(), FakeV4SubnetNoDHCP()]
@@ -495,6 +516,25 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
 
         self.safe.assert_called_once_with('/foo/opts', expected)
 
+    def test_output_opts_file_gateway_route(self):
+        fake_v6 = 'gdca:3ba5:a17a:4ba3::1'
+        fake_v6_cidr = 'gdca:3ba5:a17a:4ba3::/64'
+        expected = """
+tag:tag0,option:dns-server,8.8.8.8
+tag:tag0,option:router,10.0.0.1
+tag:tag1,option:dns-server,%s
+tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
+                                                            fake_v6_cidr,
+                                                            fake_v6)
+
+        with mock.patch.object(dhcp.Dnsmasq, 'get_conf_file_name') as conf_fn:
+            conf_fn.return_value = '/foo/opts'
+            dm = dhcp.Dnsmasq(self.conf, FakeDualNetworkGatewayRoute(),
+                              version=float(2.59))
+            dm._output_opts_file()
+
+        self.safe.assert_called_once_with('/foo/opts', expected)
+
     def test_output_opts_file_single_dhcp(self):
         expected = """
 tag:tag0,option:dns-server,8.8.8.8