]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fixes order of route entries.
authorGary Kotton <gkotton@redhat.com>
Mon, 26 Nov 2012 17:07:12 +0000 (17:07 +0000)
committerGary Kotton <gkotton@redhat.com>
Tue, 27 Nov 2012 19:52:53 +0000 (19:52 +0000)
Fixes bug 1083238

This patch makes sure that a route entry for dnsmasq is placed first
before any others (for example the l3-agent one). This makes DHCP work
when network namespaces are disabled.

Change-Id: I241a8e30127d614f7582e10d999521f6486e5255

quantum/agent/dhcp_agent.py
quantum/agent/linux/ip_lib.py
quantum/tests/unit/test_linux_ip_lib.py

index 773b90fcc81723b8b7fc061a245eb219aff0bfb7..ffa8d104354d462d499aa87b6b6568995650c560 100644 (file)
@@ -443,6 +443,11 @@ class DeviceManager(object):
         self.driver.init_l3(interface_name, ip_cidrs,
                             namespace=namespace)
 
+        # ensure that the dhcp interface is first in the list
+        if namespace is None:
+            device = ip_lib.IPDevice(interface_name, self.conf.root_helper)
+            device.route.pullup_route(interface_name)
+
         return interface_name
 
     def destroy(self, network, device_name):
index 510dcec610f369c9650d0462abf0a162bc6fa181..78157d39eecd364fe566d1b4a28a87d3cabfac69 100644 (file)
@@ -327,6 +327,46 @@ class IpRouteCommand(IpDeviceCommandBase):
 
         return retval
 
+    def pullup_route(self, interface_name):
+        """
+        Ensures that the route entry for the interface is before all
+        others on the same subnet.
+        """
+        device_list = []
+        device_route_list_lines = self._run('list', 'proto', 'kernel',
+                                            'dev', interface_name).split('\n')
+        for device_route_line in device_route_list_lines:
+            try:
+                subnet = device_route_line.split()[0]
+            except:
+                continue
+            subnet_route_list_lines = self._run('list', 'proto', 'kernel',
+                                                'match', subnet).split('\n')
+            for subnet_route_line in subnet_route_list_lines:
+                i = iter(subnet_route_line.split())
+                while(i.next() != 'dev'):
+                    pass
+                device = i.next()
+                try:
+                    while(i.next() != 'src'):
+                        pass
+                    src = i.next()
+                except:
+                    src = ''
+                if device != interface_name:
+                    device_list.append((device, src))
+                else:
+                    break
+
+            for (device, src) in device_list:
+                self._as_root('del', subnet, 'dev', device)
+                if (src != ''):
+                    self._as_root('append', subnet, 'proto', 'kernel',
+                                  'src', src, 'dev', device)
+                else:
+                    self._as_root('append', subnet, 'proto', 'kernel',
+                                  'dev', device)
+
 
 class IpNetnsCommand(IpCommandBase):
     COMMAND = 'netns'
index c7f96918afb65882ac4912d973a24f47960a8f1e..502c0ca887a749cd18e997c600f7487ef85e4e83 100644 (file)
@@ -72,6 +72,13 @@ GATEWAY_SAMPLE4 = ("""
 default via 10.35.19.254
 """)
 
+DEVICE_ROUTE_SAMPLE = ("10.0.0.0/24  scope link  src 10.0.0.2")
+
+SUBNET_SAMPLE1 = ("10.0.0.0/24 dev qr-23380d11-d2  scope link  src 10.0.0.1\n"
+                  "10.0.0.0/24 dev tap1d7888a7-10  scope link  src 10.0.0.2")
+SUBNET_SAMPLE2 = ("10.0.0.0/24 dev tap1d7888a7-10  scope link  src 10.0.0.2\n"
+                  "10.0.0.0/24 dev qr-23380d11-d2  scope link  src 10.0.0.1")
+
 
 class TestSubProcessBase(unittest.TestCase):
     def setUp(self):
@@ -543,6 +550,34 @@ class TestIpRouteCommand(TestIPCmdBase):
             self.assertEquals(self.route_cmd.get_gateway(),
                               test_case['expected'])
 
+    def test_pullup_route(self):
+        # interface is not the first in the list - requires
+        # deleting and creating existing entries
+        output = [DEVICE_ROUTE_SAMPLE, SUBNET_SAMPLE1]
+
+        def pullup_side_effect(self, *args):
+            result = output.pop(0)
+            return result
+
+        self.parent._run = mock.Mock(side_effect=pullup_side_effect)
+        self.route_cmd.pullup_route('tap1d7888a7-10')
+        self._assert_sudo([], ('del', '10.0.0.0/24', 'dev', 'qr-23380d11-d2'))
+        self._assert_sudo([], ('append', '10.0.0.0/24', 'proto', 'kernel',
+                               'src', '10.0.0.1', 'dev', 'qr-23380d11-d2'))
+
+    def test_pullup_route_first(self):
+        # interface is first in the list - no changes
+        output = [DEVICE_ROUTE_SAMPLE, SUBNET_SAMPLE2]
+
+        def pullup_side_effect(self, *args):
+            result = output.pop(0)
+            return result
+
+        self.parent._run = mock.Mock(side_effect=pullup_side_effect)
+        self.route_cmd.pullup_route('tap1d7888a7-10')
+        # Check two calls - device get and subnet get
+        self.assertEqual(len(self.parent._run.mock_calls), 2)
+
 
 class TestIpNetnsCommand(TestIPCmdBase):
     def setUp(self):