diff --git a/neutron/agent/linux/ra.py b/neutron/agent/linux/ra.py index 66fa0129f1..6bdfea57c5 100644 --- a/neutron/agent/linux/ra.py +++ b/neutron/agent/linux/ra.py @@ -82,9 +82,15 @@ def _generate_radvd_conf(router_id, router_ports, dev_name_helper): def _spawn_radvd(router_id, radvd_conf, router_ns, root_helper): def callback(pid_file): + # we need to use -m syslog and f.e. not -m stderr (the default) + # or -m stderr_syslog so that radvd 2.0+ will close stderr and + # exit after daemonization; otherwise, the current thread will + # be locked waiting for result from radvd that won't ever come + # until the process dies radvd_cmd = ['radvd', '-C', '%s' % radvd_conf, - '-p', '%s' % pid_file] + '-p', '%s' % pid_file, + '-m', 'syslog'] return radvd_cmd radvd = external_process.ProcessManager(cfg.CONF, diff --git a/neutron/tests/unit/test_l3_agent.py b/neutron/tests/unit/test_l3_agent.py index 54ae156cf6..339dae14ec 100644 --- a/neutron/tests/unit/test_l3_agent.py +++ b/neutron/tests/unit/test_l3_agent.py @@ -27,6 +27,7 @@ from neutron.agent.common import config as agent_config from neutron.agent import l3_agent from neutron.agent import l3_ha_agent from neutron.agent.linux import interface +from neutron.agent.linux import ra from neutron.common import config as base_config from neutron.common import constants as l3_constants from neutron.common import exceptions as n_exc @@ -2315,6 +2316,38 @@ vrrp_instance VR_1 { self.assertFalse(nat.add_rule.called) nat.clear_rules_by_tag.assert_called_once_with('floating_ip') + def test_spawn_radvd(self): + router = prepare_router_data() + + conffile = '/fake/radvd.conf' + pidfile = '/fake/radvd.pid' + agent = l3_agent.L3NATAgent(HOSTNAME, self.conf) + + # we don't want the whole process manager to be mocked to be + # able to catch execute() calls + self.external_process_p.stop() + self.ip_cls_p.stop() + + get_pid_file_name = ('neutron.agent.linux.external_process.' + 'ProcessManager.get_pid_file_name') + with mock.patch('neutron.agent.linux.utils.execute') as execute: + with mock.patch(get_pid_file_name) as get_pid: + get_pid.return_value = pidfile + ra._spawn_radvd(router['id'], + conffile, + agent.get_ns_name(router['id']), + self.conf.root_helper) + cmd = execute.call_args[0][0] + + self.assertIn('radvd', cmd) + + _join = lambda *args: ' '.join(args) + + cmd = _join(*cmd) + self.assertIn(_join('-C', conffile), cmd) + self.assertIn(_join('-p', pidfile), cmd) + self.assertIn(_join('-m', 'syslog'), cmd) + class TestL3AgentEventHandler(base.BaseTestCase):