Do not install centralized FIP if HA port is down

The issue scenario happens when we disassociate a floating IP
while the 'master' router host is restarted or powered-off.

When the L3 agent is powered-on again, the HA router state config
still remains 'master', but the ha port is down. And the message
queue still has one 'router_update' message (floating IP
disassociate message), so the L3 agent will sync this router info
at least twice during the restart, one is the router_update, the
other is the L3 agent full-sync.

The first one will add the centralized FIP to the qg-device, because
the router state is 'master'. So for DVR HA routers, only add the
centralized floating IP to the qg-device in the snat-namespace when
the HA port is up. For the restart procedure, if the HA port is up,
but the router is set to 'backup', do not add the floating IP.

Closes-Bug: #1794305
Change-Id: Ib39fe7dcd437a867c69852885c461a594167f6a1
This commit is contained in:
LIU Yulong 2018-09-26 15:58:11 +08:00 committed by Brian Haley
parent 56bcb6fe0a
commit 656a8f8729
2 changed files with 29 additions and 11 deletions

View File

@ -61,7 +61,10 @@ class DvrEdgeHaRouter(dvr_edge_router.DvrEdgeRouter,
interface_name = self.get_snat_external_device_interface_name(
self.get_ex_gw_port())
self._add_vip(fip_cidr, interface_name)
if self.is_router_master():
self.ha_port = self.router.get(constants.HA_INTERFACE_KEY)
if (self.is_router_master() and self.ha_port and
self.ha_port['status'] == constants.PORT_STATUS_ACTIVE):
return super(DvrEdgeHaRouter, self).add_centralized_floatingip(
fip, fip_cidr)
else:

View File

@ -814,11 +814,13 @@ class TestDvrRouterOperations(base.BaseTestCase):
@mock.patch.object(dvr_edge_rtr.DvrEdgeRouter,
'add_centralized_floatingip')
def test_add_centralized_floatingip(self,
super_add_centralized_floatingip):
def test_add_centralized_floatingip_dvr_ha(
self,
super_add_centralized_floatingip):
agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
agent.conf.agent_mode = lib_constants.L3_AGENT_MODE_DVR_SNAT
router = l3_test_common.prepare_router_data(num_internal_ports=2)
router = l3_test_common.prepare_router_data(
num_internal_ports=2, enable_ha=True)
router['gw_port_host'] = HOSTNAME
self.mock_driver.unplug.reset_mock()
self._set_ri_kwargs(agent, router['id'], router)
@ -834,13 +836,26 @@ class TestDvrRouterOperations(base.BaseTestCase):
ri._add_vip.assert_called_once_with(fip_cidr, interface_name)
super_add_centralized_floatingip.assert_not_called()
ri1 = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs)
ri1.is_router_master = mock.Mock(return_value=True)
ri1._add_vip = mock.Mock()
interface_name = ri1.get_snat_external_device_interface_name(
ri1.get_ex_gw_port())
ri1.add_centralized_floatingip(fip, fip_cidr)
ri1._add_vip.assert_called_once_with(fip_cidr, interface_name)
router[lib_constants.HA_INTERFACE_KEY]['status'] = 'DOWN'
self._set_ri_kwargs(agent, router['id'], router)
ri_1 = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs)
ri_1.is_router_master = mock.Mock(return_value=True)
ri_1._add_vip = mock.Mock()
interface_name = ri_1.get_snat_external_device_interface_name(
ri_1.get_ex_gw_port())
ri_1.add_centralized_floatingip(fip, fip_cidr)
ri_1._add_vip.assert_called_once_with(fip_cidr, interface_name)
super_add_centralized_floatingip.assert_not_called()
router[lib_constants.HA_INTERFACE_KEY]['status'] = 'ACTIVE'
self._set_ri_kwargs(agent, router['id'], router)
ri_2 = dvr_edge_ha_rtr.DvrEdgeHaRouter(HOSTNAME, [], **self.ri_kwargs)
ri_2.is_router_master = mock.Mock(return_value=True)
ri_2._add_vip = mock.Mock()
interface_name = ri_2.get_snat_external_device_interface_name(
ri_2.get_ex_gw_port())
ri_2.add_centralized_floatingip(fip, fip_cidr)
ri_2._add_vip.assert_called_once_with(fip_cidr, interface_name)
super_add_centralized_floatingip.assert_called_once_with(fip,
fip_cidr)