Fixes order of route entries.
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
This commit is contained in:
parent
78eb1a0d53
commit
30d6c8e7d4
@ -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):
|
||||
|
@ -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'
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user