File 0009-Fix-l3-agent-crash-on-routers-without-ha-state.patch of Package openstack-neutron
Index: neutron-9.4.2.dev21/neutron/agent/l3/agent.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/agent/l3/agent.py
+++ neutron-9.4.2.dev21/neutron/agent/l3/agent.py
@@ -473,13 +473,14 @@ class L3NATAgent(ha.AgentMixin,
self.l3_ext_manager.add_router(self.context, router)
def _process_updated_router(self, router):
+ ri = self.router_info[router['id']]
is_dvr_only_agent = (
self.conf.agent_mode == lib_const.L3_AGENT_MODE_DVR)
+ is_ha_router = getattr(ri, 'ha_state', None) is not None
# For HA routers check that DB state matches actual state
- if router.get('ha') and not is_dvr_only_agent:
+ if router.get('ha') and not is_dvr_only_agent and is_ha_router:
self.check_ha_state_for_router(
router['id'], router.get(l3_constants.HA_ROUTER_STATE_KEY))
- ri = self.router_info[router['id']]
ri.router = router
registry.notify(resources.ROUTER, events.BEFORE_UPDATE,
self, router=ri)
Index: neutron-9.4.2.dev21/neutron/tests/functional/agent/l3/test_dvr_router.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/tests/functional/agent/l3/test_dvr_router.py
+++ neutron-9.4.2.dev21/neutron/tests/functional/agent/l3/test_dvr_router.py
@@ -958,8 +958,8 @@ class TestDvrRouter(framework.L3AgentTes
self.assertFalse(sg_device)
self.assertTrue(qg_device)
- def _mocked_dvr_ha_router(self, agent, enable_gw=True):
- r_info = self.generate_dvr_router_info(enable_ha=True,
+ def _mocked_dvr_ha_router(self, agent, enable_ha=True, enable_gw=True):
+ r_info = self.generate_dvr_router_info(enable_ha=enable_ha,
enable_snat=True,
agent=agent,
enable_gw=enable_gw)
@@ -991,14 +991,19 @@ class TestDvrRouter(framework.L3AgentTes
br_int_1.add_port(veth1.name)
br_int_2.add_port(veth2.name)
- def _create_dvr_ha_router(self, agent, enable_gw=True):
+ def _create_dvr_ha_router(self, agent, enable_gw=True, ha_interface=True):
get_ns_name = mock.patch.object(namespaces.RouterNamespace,
'_get_ns_name').start()
get_snat_ns_name = mock.patch.object(dvr_snat_ns.SnatNamespace,
'get_snat_ns_name').start()
(r_info,
mocked_r_ns_name,
- mocked_r_snat_ns_name) = self._mocked_dvr_ha_router(agent, enable_gw)
+ mocked_r_snat_ns_name) = self._mocked_dvr_ha_router(
+ agent, ha_interface, enable_gw)
+
+ if not ha_interface:
+ r_info['ha'] = True
+
get_ns_name.return_value = mocked_r_ns_name
get_snat_ns_name.return_value = mocked_r_snat_ns_name
router = self.manage_router(agent, r_info)
@@ -1076,6 +1081,26 @@ class TestDvrRouter(framework.L3AgentTes
def test_dvr_ha_router_failover_without_gw(self):
self._test_dvr_ha_router_failover(enable_gw=False)
+ def test_dvr_non_ha_router_update(self):
+ self._setup_dvr_ha_agents()
+ self._setup_dvr_ha_bridges()
+
+ router1 = self._create_dvr_ha_router(self.agent)
+ router2 = self._create_dvr_ha_router(self.failover_agent,
+ ha_interface=False)
+
+ r1_chsfr = mock.patch.object(self.agent,
+ 'check_ha_state_for_router').start()
+ r2_chsfr = mock.patch.object(self.failover_agent,
+ 'check_ha_state_for_router').start()
+
+ utils.wait_until_true(lambda: router1.ha_state == 'master')
+
+ self.agent._process_updated_router(router1.router)
+ self.assertTrue(r1_chsfr.called)
+ self.failover_agent._process_updated_router(router2.router)
+ self.assertFalse(r2_chsfr.called)
+
def _setup_dvr_router_static_routes(
self, router_namespace=True, check_fpr_int_rule_delete=False):
"""Test to validate the extra routes on dvr routers."""
Index: neutron-9.4.2.dev21/neutron/tests/unit/agent/l3/test_agent.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/tests/unit/agent/l3/test_agent.py
+++ neutron-9.4.2.dev21/neutron/tests/unit/agent/l3/test_agent.py
@@ -2249,9 +2249,10 @@ class TestBasicRouterOperations(BasicRou
'distributed': True, 'ha': True,
'external_gateway_info': {}, 'routes': [],
'admin_state_up': True}
-
- agent._process_router_if_compatible(router)
- self.assertIn(router['id'], agent.router_info)
+ with mock.patch.object(agent, 'check_ha_state_for_router') as chsfr:
+ agent._process_router_if_compatible(router)
+ self.assertIn(router['id'], agent.router_info)
+ self.assertFalse(chsfr.called)
def test_process_router_if_compatible_with_no_ext_net_in_conf(self):
self.conf.set_override('external_network_bridge', 'br-ex')