File 0001-Keep-HA-ports-info-for-HA-router-during-entire-lifecycle.patch of Package openstack-neutron
Index: neutron-9.4.2.dev21/neutron/agent/l3/ha_router.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/agent/l3/ha_router.py
+++ neutron-9.4.2.dev21/neutron/agent/l3/ha_router.py
@@ -110,7 +110,7 @@ class HaRouter(router.RouterInfo):
raise Exception(msg)
super(HaRouter, self).initialize(process_monitor)
- self.ha_port = ha_port
+ self.set_ha_port()
self._init_keepalived_manager(process_monitor)
self.ha_network_added()
self.update_initial_state(self.state_change_callback)
@@ -436,10 +436,23 @@ class HaRouter(router.RouterInfo):
self.ha_network_removed()
super(HaRouter, self).delete(agent)
+ def set_ha_port(self):
+ ha_port = self.router.get(n_consts.HA_INTERFACE_KEY)
+ if not ha_port:
+ return
+ # NOTE: once HA port is set, it MUST remain this value no matter what
+ # the server return. Because there is race condition between l3-agent
+ # side sync router info for processing and server side router deleting.
+ # TODO(liuyulong): make sure router HA ports never change.
+ if not self.ha_port or (self.ha_port and
+ self.ha_port['status'] != ha_port['status']):
+ self.ha_port = ha_port
+
def process(self, agent):
super(HaRouter, self).process(agent)
- self.ha_port = self.router.get(n_consts.HA_INTERFACE_KEY)
+ self.set_ha_port()
+ LOG.debug("Processing HA router with HA port: %s", self.ha_port)
if (self.ha_port and
self.ha_port['status'] == n_consts.PORT_STATUS_ACTIVE):
self.enable_keepalived()
Index: neutron-9.4.2.dev21/neutron/tests/unit/agent/l3/test_ha_router.py
===================================================================
--- neutron-9.4.2.dev21.orig/neutron/tests/unit/agent/l3/test_ha_router.py
+++ neutron-9.4.2.dev21/neutron/tests/unit/agent/l3/test_ha_router.py
@@ -15,6 +15,7 @@
import signal
import mock
+from neutron_lib import constants as n_consts
from oslo_utils import uuidutils
from neutron.agent.l3 import ha_router
@@ -116,3 +117,31 @@ class TestBasicRouterOperations(base.Bas
ri.remove_floating_ip(device, fip_cidr)
self.assertTrue(super_remove_floating_ip.called)
+
+ def test_set_ha_port(self):
+ ri = self._create_router()
+ self.assertIsNone(ri.ha_port)
+
+ ri.router = {}
+ ri.set_ha_port()
+ self.assertIsNone(ri.ha_port)
+
+ # HA_INTERFACE_KEY from None to some value
+ ri.router = {n_consts.HA_INTERFACE_KEY: {"id": _uuid(),
+ "status": "DOWN"}}
+ ri.set_ha_port()
+ self.assertIsNotNone(ri.ha_port)
+ self.assertEqual('DOWN', ri.ha_port["status"])
+
+ # HA port state change
+ ri.router = {n_consts.HA_INTERFACE_KEY: {"id": _uuid(),
+ "status": "ACTIVE"}}
+ ri.set_ha_port()
+ self.assertIsNotNone(ri.ha_port)
+ self.assertEqual('ACTIVE', ri.ha_port["status"])
+
+ ri.router = {}
+ ri.set_ha_port()
+ # neutron server return empty HA_INTERFACE_KEY, but
+ # agent side router info should remain the original value.
+ self.assertIsNotNone(ri.ha_port)