continue
break
+ self.metadata_driver = None
+ if self.conf.enable_metadata_proxy:
+ self.metadata_driver = metadata_driver.MetadataDriver(self)
+
self.namespaces_manager = namespace_manager.NamespaceManager(
self.conf,
self.driver,
- self.conf.use_namespaces)
+ self.conf.use_namespaces,
+ self.metadata_driver)
self._queue = queue.RouterProcessingQueue()
super(L3NATAgent, self).__init__(conf=self.conf)
self.target_ex_net_id = None
self.use_ipv6 = ipv6_utils.is_enabled()
- if self.conf.enable_metadata_proxy:
- self.metadata_driver = metadata_driver.MetadataDriver(self)
-
def _check_config_params(self):
"""Check items in configuration files.
from neutron.agent.l3 import dvr_snat_ns
from neutron.agent.l3 import namespaces
+from neutron.agent.linux import external_process
from neutron.agent.linux import ip_lib
from neutron.i18n import _LE
agent restarts gracefully.
"""
- def __init__(self, agent_conf, driver, clean_stale):
+ def __init__(self, agent_conf, driver, clean_stale, metadata_driver=None):
"""Initialize the NamespaceManager.
:param agent_conf: configuration from l3 agent
:param driver: to perform operations on devices
:param clean_stale: Whether to try to clean stale namespaces
+ :param metadata_driver: used to cleanup stale metadata proxy processes
"""
self.agent_conf = agent_conf
self.driver = driver
self._clean_stale = clean_stale
+ self.metadata_driver = metadata_driver
+ if metadata_driver:
+ self.process_monitor = external_process.ProcessMonitor(
+ config=agent_conf,
+ resource_type='router')
def __enter__(self):
self._all_namespaces = set()
self.driver,
use_ipv6=False)
try:
+ if self.metadata_driver:
+ # cleanup stale metadata proxy processes first
+ self.metadata_driver.destroy_monitored_metadata_proxy(
+ self.process_monitor, ns_id, self.agent_conf)
ns.delete()
except RuntimeError:
LOG.exception(_LE('Failed to destroy stale namespace %s'), ns)
super(NamespaceManagerTestFramework, self).setUp()
self.agent_conf = mock.MagicMock()
self.agent_conf.router_delete_namespaces = True
+ self.metadata_driver_mock = mock.Mock()
self.namespace_manager = namespace_manager.NamespaceManager(
- self.agent_conf, driver=None, clean_stale=True)
+ self.agent_conf, driver=None, clean_stale=True,
+ metadata_driver=self.metadata_driver_mock)
def _create_namespace(self, router_id, ns_class):
namespace = ns_class(router_id, self.agent_conf, driver=None,
def test_namespace_manager(self):
router_id = _uuid()
+ router_id_to_delete = _uuid()
to_keep = set()
to_delete = set()
to_retrieve = set()
namespaces.RouterNamespace))
to_keep.add(self._create_namespace(router_id,
dvr_snat_ns.SnatNamespace))
- to_delete.add(self._create_namespace(_uuid(),
+ to_delete.add(self._create_namespace(router_id_to_delete,
dvr_snat_ns.SnatNamespace))
to_retrieve = to_keep | to_delete
for ns_name in to_keep:
self.assertTrue(self._namespace_exists(ns_name))
for ns_name in to_delete:
+ (self.metadata_driver_mock.destroy_monitored_metadata_proxy.
+ assert_called_once_with(mock.ANY,
+ router_id_to_delete,
+ self.agent_conf))
self.assertFalse(self._namespace_exists(ns_name))
class L3AgentTestFramework(base.BaseSudoTestCase):
def setUp(self):
super(L3AgentTestFramework, self).setUp()
- mock.patch('neutron.agent.l3.agent.L3PluginApi').start()
+ self.mock_plugin_api = mock.patch(
+ 'neutron.agent.l3.agent.L3PluginApi').start().return_value
mock.patch('neutron.agent.rpc.PluginReportStateAPI').start()
self.agent = self._configure_agent('agent1')
routers_to_keep = []
routers_to_delete = []
ns_names_to_retrieve = set()
+ routers_info_to_delete = []
for i in range(2):
routers_to_keep.append(self.generate_router_info(False))
- self.manage_router(self.agent, routers_to_keep[i])
- ns_names_to_retrieve.add(namespaces.NS_PREFIX +
- routers_to_keep[i]['id'])
+ ri = self.manage_router(self.agent, routers_to_keep[i])
+ ns_names_to_retrieve.add(ri.ns_name)
for i in range(2):
routers_to_delete.append(self.generate_router_info(False))
- self.manage_router(self.agent, routers_to_delete[i])
- ns_names_to_retrieve.add(namespaces.NS_PREFIX +
- routers_to_delete[i]['id'])
+ ri = self.manage_router(self.agent, routers_to_delete[i])
+ routers_info_to_delete.append(ri)
+ ns_names_to_retrieve.add(ri.ns_name)
# Mock the plugin RPC API to Simulate a situation where the agent
# was handling the 4 routers created above, it went down and after
# starting up again, two of the routers were deleted via the API
- mocked_get_routers = (
- neutron_l3_agent.L3PluginApi.return_value.get_routers)
- mocked_get_routers.return_value = routers_to_keep
+ self.mock_plugin_api.get_routers.return_value = routers_to_keep
+ # also clear agent router_info as it will be after restart
+ self.agent.router_info = {}
# Synchonize the agent with the plug-in
with mock.patch.object(namespace_manager.NamespaceManager, 'list_all',
# Mock the plugin RPC API so a known external network id is returned
# when the router updates are processed by the agent
external_network_id = _uuid()
- mocked_get_external_network_id = (
- neutron_l3_agent.L3PluginApi.return_value.get_external_network_id)
- mocked_get_external_network_id.return_value = external_network_id
+ self.mock_plugin_api.get_external_network_id.return_value = (
+ external_network_id)
# Plug external_gateway_info in the routers that are not going to be
# deleted by the agent when it processes the updates. Otherwise,
# Have the agent process the update from the plug-in and verify
# expected behavior
- for _ in routers_to_keep + routers_to_delete:
+ for _ in routers_to_keep:
self.agent._process_router_update()
for i in range(2):
self.assertTrue(self._namespace_exists(namespaces.NS_PREFIX +
routers_to_keep[i]['id']))
for i in range(2):
- self.assertNotIn(routers_to_delete[i]['id'],
+ self.assertNotIn(routers_info_to_delete[i].router_id,
self.agent.router_info)
- self.assertFalse(self._namespace_exists(
- namespaces.NS_PREFIX + routers_to_delete[i]['id']))
+ self._assert_router_does_not_exist(routers_info_to_delete[i])
def _router_lifecycle(self, enable_ha, ip_version=4,
dual_stack=False, v6_ext_gw_with_sub=True):
self, agent_mode, **dvr_router_kwargs):
self.agent.conf.agent_mode = agent_mode
router_info = self.generate_dvr_router_info(**dvr_router_kwargs)
- mocked_ext_net_id = (
- neutron_l3_agent.L3PluginApi.return_value.get_external_network_id)
- mocked_ext_net_id.return_value = (
+ self.mock_plugin_api.get_external_network_id.return_value = (
router_info['_floatingips'][0]['floating_network_id'])
router = self.manage_router(self.agent, router_info)
fip_ns = router.fip_ns.get_name()
# gateway_port information before the l3_agent will create it.
# The port returned needs to have the same information as
# router_info['gw_port']
- mocked_gw_port = (
- neutron_l3_agent.L3PluginApi.return_value.get_agent_gateway_port)
- mocked_gw_port.return_value = router_info['gw_port']
+ self.mock_plugin_api.get_agent_gateway_port.return_value = router_info[
+ 'gw_port']
# We also need to mock the get_external_network_id method to
# get the correct fip namespace.
- mocked_ext_net_id = (
- neutron_l3_agent.L3PluginApi.return_value.get_external_network_id)
- mocked_ext_net_id.return_value = (
+ self.mock_plugin_api.get_external_network_id.return_value = (
router_info['_floatingips'][0]['floating_network_id'])
# With all that set we can now ask the l3_agent to
agent.periodic_sync_routers_task(agent.context)
self.assertFalse(agent.namespaces_manager._clean_stale)
+ def test_periodic_sync_routers_task_call_clean_stale_meta_proxies(self):
+ agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+ stale_router_ids = [_uuid(), _uuid()]
+ active_routers = [{'id': _uuid()}, {'id': _uuid()}]
+ self.plugin_api.get_routers.return_value = active_routers
+ namespace_list = [namespaces.NS_PREFIX + r_id
+ for r_id in stale_router_ids]
+ namespace_list += [namespaces.NS_PREFIX + r['id']
+ for r in active_routers]
+ self.mock_ip.get_namespaces.return_value = namespace_list
+ driver = metadata_driver.MetadataDriver
+ with mock.patch.object(
+ driver, 'destroy_monitored_metadata_proxy') as destroy_proxy:
+ agent.periodic_sync_routers_task(agent.context)
+
+ expected_calls = [mock.call(mock.ANY, r_id, agent.conf)
+ for r_id in stale_router_ids]
+ self.assertEqual(len(stale_router_ids), destroy_proxy.call_count)
+ destroy_proxy.assert_has_calls(expected_calls, any_order=True)
+
def test_router_info_create(self):
id = _uuid()
ri = l3router.RouterInfo(id, {}, **self.ri_kwargs)