Merge "Ensure that l3 agent does not crash on restart"
This commit is contained in:
commit
a5a4e5f2f9
@ -29,6 +29,7 @@ from quantum.agent.common import config
|
||||
from quantum.agent.linux import interface
|
||||
from quantum.agent.linux import ip_lib
|
||||
from quantum.agent.linux import iptables_manager
|
||||
from quantum.agent.linux import utils
|
||||
from quantum.db import l3_db
|
||||
from quantum.openstack.common import cfg
|
||||
from quantum.openstack.common import importutils
|
||||
@ -147,22 +148,19 @@ class L3NATAgent(object):
|
||||
def _destroy_router_namespace(self, namespace):
|
||||
ns_ip = ip_lib.IPWrapper(self.conf.root_helper,
|
||||
namespace=namespace)
|
||||
for d in ns_ip.get_devices():
|
||||
for d in ns_ip.get_devices(exclude_loopback=True):
|
||||
if d.name.startswith(INTERNAL_DEV_PREFIX):
|
||||
# device is on default bridge
|
||||
self.driver.unplug(d.name)
|
||||
self.driver.unplug(d.name, namespace=namespace)
|
||||
elif d.name.startswith(EXTERNAL_DEV_PREFIX):
|
||||
self.driver.unplug(d.name,
|
||||
bridge=self.conf.external_network_bridge)
|
||||
if self.conf.use_namespaces:
|
||||
ns_ip.netns.delete(namespace)
|
||||
bridge=self.conf.external_network_bridge,
|
||||
namespace=namespace)
|
||||
#(TODO) Address the failure for the deletion of the namespace
|
||||
|
||||
def _create_router_namespace(self, ri):
|
||||
ip_wrapper_root = ip_lib.IPWrapper(self.conf.root_helper)
|
||||
ip_wrapper_root.netns.add(ri.ns_name())
|
||||
|
||||
ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
|
||||
namespace=ri.ns_name())
|
||||
ip_wrapper = ip_wrapper_root.ensure_namespace(ri.ns_name())
|
||||
ip_wrapper.netns.execute(['sysctl', '-w', 'net.ipv4.ip_forward=1'])
|
||||
|
||||
def daemon_loop(self):
|
||||
@ -364,10 +362,13 @@ class L3NATAgent(object):
|
||||
gw_ip = ex_gw_port['subnet']['gateway_ip']
|
||||
if ex_gw_port['subnet']['gateway_ip']:
|
||||
cmd = ['route', 'add', 'default', 'gw', gw_ip]
|
||||
ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
|
||||
namespace=ri.ns_name())
|
||||
if self.conf.use_namespaces:
|
||||
ip_wrapper.netns.execute(cmd)
|
||||
ip_wrapper = ip_lib.IPWrapper(self.conf.root_helper,
|
||||
namespace=ri.ns_name())
|
||||
ip_wrapper.netns.execute(cmd, check_exit_code=False)
|
||||
else:
|
||||
utils.execute(cmd, check_exit_code=False,
|
||||
root_helper=self.conf.root_helper)
|
||||
|
||||
for (c, r) in self.external_gateway_filter_rules():
|
||||
ri.iptables_manager.ipv4['filter'].add_rule(c, r)
|
||||
@ -384,7 +385,8 @@ class L3NATAgent(object):
|
||||
root_helper=self.conf.root_helper,
|
||||
namespace=ri.ns_name()):
|
||||
self.driver.unplug(interface_name,
|
||||
bridge=self.conf.external_network_bridge)
|
||||
bridge=self.conf.external_network_bridge,
|
||||
namespace=ri.ns_name())
|
||||
|
||||
ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
|
||||
for c, r in self.external_gateway_filter_rules():
|
||||
@ -442,7 +444,7 @@ class L3NATAgent(object):
|
||||
if ip_lib.device_exists(interface_name,
|
||||
root_helper=self.conf.root_helper,
|
||||
namespace=ri.ns_name()):
|
||||
self.driver.unplug(interface_name)
|
||||
self.driver.unplug(interface_name, namespace=ri.ns_name())
|
||||
|
||||
if ex_gw_port:
|
||||
ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address']
|
||||
|
@ -154,10 +154,6 @@ class OVSInterfaceDriver(LinuxInterfaceDriver):
|
||||
bridge = ovs_lib.OVSBridge(bridge, self.conf.root_helper)
|
||||
bridge.delete_port(device_name)
|
||||
|
||||
if namespace:
|
||||
ip = ip_lib.IPWrapper(self.conf.root_helper, namespace)
|
||||
ip.garbage_collect_namespace()
|
||||
|
||||
|
||||
class BridgeInterfaceDriver(LinuxInterfaceDriver):
|
||||
"""Driver for creating bridge interfaces."""
|
||||
@ -200,10 +196,6 @@ class BridgeInterfaceDriver(LinuxInterfaceDriver):
|
||||
LOG.error(_("Failed unplugging interface '%s'") %
|
||||
device_name)
|
||||
|
||||
if namespace:
|
||||
ip = ip_lib.IPWrapper(self.conf.root_helper, namespace)
|
||||
ip.garbage_collect_namespace()
|
||||
|
||||
|
||||
class RyuInterfaceDriver(OVSInterfaceDriver):
|
||||
"""Driver for creating a Ryu OVS interface."""
|
||||
|
@ -338,7 +338,7 @@ class IpNetnsCommand(IpCommandBase):
|
||||
def delete(self, name):
|
||||
self._as_root('delete', name, use_root_namespace=True)
|
||||
|
||||
def execute(self, cmds, addl_env={}):
|
||||
def execute(self, cmds, addl_env={}, check_exit_code=True):
|
||||
if not self._parent.root_helper:
|
||||
raise exceptions.SudoRequired()
|
||||
elif not self._parent.namespace:
|
||||
@ -347,7 +347,8 @@ class IpNetnsCommand(IpCommandBase):
|
||||
return utils.execute(
|
||||
['%s=%s' % pair for pair in addl_env.items()] +
|
||||
['ip', 'netns', 'exec', self._parent.namespace] + list(cmds),
|
||||
root_helper=self._parent.root_helper)
|
||||
root_helper=self._parent.root_helper,
|
||||
check_exit_code=check_exit_code)
|
||||
|
||||
def exists(self, name):
|
||||
output = self._as_root('list', options='o', use_root_namespace=True)
|
||||
|
@ -331,7 +331,8 @@ class TestDhcpLocalProcess(TestBase):
|
||||
|
||||
self.assertFalse(delegate.called)
|
||||
exp_args = ['ip', 'netns', 'exec', 'qdhcp-ns', 'kill', '-9', 5]
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo')
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
|
||||
def test_disable(self):
|
||||
attrs_to_mock = dict([(a, mock.DEFAULT) for a in
|
||||
@ -348,7 +349,8 @@ class TestDhcpLocalProcess(TestBase):
|
||||
|
||||
delegate.assert_has_calls([mock.call.destroy(network, 'tap0')])
|
||||
exp_args = ['ip', 'netns', 'exec', 'qdhcp-ns', 'kill', '-9', 5]
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo')
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
|
||||
def test_pid(self):
|
||||
with mock.patch('__builtin__.open') as mock_open:
|
||||
@ -452,7 +454,8 @@ class TestDnsmasq(TestBase):
|
||||
dm.spawn_process()
|
||||
self.assertTrue(mocks['_output_opts_file'].called)
|
||||
self.execute.assert_called_once_with(expected,
|
||||
root_helper='sudo')
|
||||
root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
|
||||
def test_spawn(self):
|
||||
self._test_spawn([])
|
||||
@ -539,7 +542,8 @@ tag:tag1,option:classless-static-route,%s,%s""".lstrip() % (fake_v6,
|
||||
|
||||
self.safe.assert_has_calls([mock.call(exp_host_name, exp_host_data),
|
||||
mock.call(exp_opt_name, exp_opt_data)])
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo')
|
||||
self.execute.assert_called_once_with(exp_args, root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
|
||||
def _test_lease_relay_script_helper(self, action, lease_remaining,
|
||||
path_exists=True):
|
||||
|
@ -580,7 +580,8 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
||||
self.netns_cmd.execute(['ip', 'link', 'list'])
|
||||
execute.assert_called_once_with(['ip', 'netns', 'exec', 'ns', 'ip',
|
||||
'link', 'list'],
|
||||
root_helper='sudo')
|
||||
root_helper='sudo',
|
||||
check_exit_code=True)
|
||||
|
||||
def test_execute_env_var_prepend(self):
|
||||
self.parent.namespace = 'ns'
|
||||
@ -590,7 +591,7 @@ class TestIpNetnsCommand(TestIPCmdBase):
|
||||
execute.assert_called_once_with(
|
||||
['FOO=1', 'BAR=2', 'ip', 'netns', 'exec', 'ns', 'ip', 'link',
|
||||
'list'],
|
||||
root_helper='sudo')
|
||||
root_helper='sudo', check_exit_code=True)
|
||||
|
||||
|
||||
class TestDeviceExists(unittest.TestCase):
|
||||
|
Loading…
x
Reference in New Issue
Block a user