From 3d99147e732ab4cdad0b8243e5fabb6a8954aa72 Mon Sep 17 00:00:00 2001 From: LIU Yulong Date: Wed, 24 Apr 2019 14:19:36 +0800 Subject: [PATCH] Ensure dvr ha router gateway port binding host There are some extreme conditions which will result the unbound router gateway port. Then all the centralized floating IPs will not be reachable since the gateway port was set to 4095 tag. This patch adds the HA status to the router related port processing code path. If it is HA router, the gateway port will go to the right HA router processing code branch. Closes-Bug: #1827754 Change-Id: Ida1c9f3a38171ea82adc2f11cb17945d6e2434be --- neutron/api/rpc/handlers/l3_rpc.py | 11 ++++++++++- neutron/db/l3_hamode_db.py | 10 ++++++++++ neutron/tests/unit/extensions/test_l3.py | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/neutron/api/rpc/handlers/l3_rpc.py b/neutron/api/rpc/handlers/l3_rpc.py index 15cd0737bf1..5ebecb706bb 100644 --- a/neutron/api/rpc/handlers/l3_rpc.py +++ b/neutron/api/rpc/handlers/l3_rpc.py @@ -147,7 +147,8 @@ class L3RpcCallback(object): self._ensure_host_set_on_port(context, gw_port_host, router.get('gw_port'), - router['id']) + router['id'], + ha_router_port=router.get('ha')) for p in router.get(constants.SNAT_ROUTER_INTF_KEY, []): self._ensure_host_set_on_port( context, gw_port_host, p, router['id'], @@ -187,6 +188,10 @@ class L3RpcCallback(object): # All ports, including ports created for SNAT'ing for # DVR are handled here try: + LOG.debug("Updating router %(router)s port %(port)s " + "binding host %(host)s", + {"router": router_id, "port": port['id'], + "host": host}) self.plugin.update_port( context, port['id'], @@ -213,6 +218,10 @@ class L3RpcCallback(object): # port binding will be corrected when an active is # elected. try: + LOG.debug("Updating router %(router)s port %(port)s " + "binding host %(host)s", + {"router": router_id, "port": port['id'], + "host": host}) self.plugin.update_port( context, port['id'], diff --git a/neutron/db/l3_hamode_db.py b/neutron/db/l3_hamode_db.py index a0c75d71424..435178420ae 100644 --- a/neutron/db/l3_hamode_db.py +++ b/neutron/db/l3_hamode_db.py @@ -760,6 +760,16 @@ class L3_HA_NAT_db_mixin(l3_dvr_db.L3_NAT_with_dvr_db_mixin, ha_binding_agent.host == gateway_port_binding_host): return ha_binding_agent.host + LOG.debug("No gateway port host retrieved. HA router %(router_id)s " + "gateway port %(gw_port_id)s " + "binding host: %(host)s, status: %(status)s, " + "router HA bindings: %(ha_bindings)s", + {"router_id": router_id, + "gw_port_id": gateway_port['id'], + "host": gateway_port_binding_host, + "status": gateway_port_status, + "ha_bindings": ha_bindings}) + def is_ha_router(router): """Return True if router to be handled is ha.""" diff --git a/neutron/tests/unit/extensions/test_l3.py b/neutron/tests/unit/extensions/test_l3.py index 925ce8f47c0..c12fae01a79 100644 --- a/neutron/tests/unit/extensions/test_l3.py +++ b/neutron/tests/unit/extensions/test_l3.py @@ -4203,6 +4203,21 @@ class L3RpcCallbackTestCase(base.BaseTestCase): actual_message = mock_log.call_args[0][0] % mock_log.call_args[0][1] self.assertEqual(expected_message, actual_message) + def test__ensure_host_set_on_ports_dvr_ha_router_with_gatway(self): + context = mock.Mock() + host = "fake_host" + router_id = 'foo_router_id' + router = {"id": router_id, + "gw_port_host": host, + "gw_port": {"id": "foo_port_id"}, + "distributed": True, + "ha": True} + mock__ensure = mock.Mock() + self.l3_rpc_cb._ensure_host_set_on_port = mock__ensure + self.l3_rpc_cb._ensure_host_set_on_ports(context, host, [router]) + mock__ensure.assert_called_once_with( + context, host, router["gw_port"], router_id, ha_router_port=True) + class L3AgentDbIntTestCase(L3BaseForIntTests, L3AgentDbTestCaseBase):