From 83ca27f52ae994660eb9cb9cd040dc409b417452 Mon Sep 17 00:00:00 2001 From: rossella Date: Wed, 8 Jun 2016 17:18:51 +0200 Subject: [PATCH] After a migration clean up the floating ip on the source host When a VM is migrated that has a floating IP associated, the L3 agent on the source host should be notified when the migration is over. If the router on the source host is not going to be removed (there are other ports using it) then we should nofity that the floating IP needs to be cleaned up. Change-Id: Iad6fbad06cdd33380ef536e6360fd90375ed380d Closes-bug: #1585165 (cherry picked from commit a1f06fd707ffe663e09f2675316257c8dc528d47) --- neutron/db/l3_dvrscheduler_db.py | 7 +++ .../unit/scheduler/test_l3_agent_scheduler.py | 47 +++++++++++++++---- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/neutron/db/l3_dvrscheduler_db.py b/neutron/db/l3_dvrscheduler_db.py index 236d86e2358..5f31a4d91bf 100644 --- a/neutron/db/l3_dvrscheduler_db.py +++ b/neutron/db/l3_dvrscheduler_db.py @@ -428,6 +428,13 @@ def _notify_l3_agent_port_update(resource, event, trigger, **kwargs): } _notify_port_delete( event, resource, trigger, **removed_router_args) + fip = l3plugin._get_floatingip_on_port(context, + port_id=original_port['id']) + if fip and not (removed_routers and + fip['router_id'] in removed_routers): + l3plugin.l3_rpc_notifier.routers_updated_on_host( + context, [fip['router_id']], + original_port[portbindings.HOST_ID]) if not is_new_device_dvr_serviced: return is_new_port_binding_changed = ( diff --git a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py index 2c8206f565d..6adf623266f 100644 --- a/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py +++ b/neutron/tests/unit/scheduler/test_l3_agent_scheduler.py @@ -1116,7 +1116,29 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase): self.adminContext, kwargs.get('port')) self.assertFalse(l3plugin.dvr_handle_new_service_port.called) - def test__notify_l3_agent_update_port_with_port_binding_change(self): + def test__notify_l3_agent_port_binding_change(self): + self._test__notify_l3_agent_port_binding_change() + + def test__notify_l3_agent_port_binding_change_removed_routers(self): + router_to_remove = [{'agent_id': 'foo_agent', + 'router_id': 'foo_id', + 'host': 'vm-host1'}] + self._test__notify_l3_agent_port_binding_change(router_to_remove) + + def test__notify_l3_agent_port_binding_change_removed_routers_fip(self): + fip = {'router_id': 'router_id'} + router_to_remove = [{'agent_id': 'foo_agent', + 'router_id': 'foo_id', + 'host': 'vm-host1'}] + self._test__notify_l3_agent_port_binding_change(router_to_remove, fip) + + def test__notify_l3_agent_port_binding_change_with_fip(self): + fip = {'router_id': 'router_id'} + self._test__notify_l3_agent_port_binding_change(None, fip) + + def _test__notify_l3_agent_port_binding_change(self, + routers_to_remove=None, + fip=None): source_host = 'vm-host1' kwargs = { 'context': self.adminContext, @@ -1135,17 +1157,22 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase): 'get_service_plugins', return_value={'L3_ROUTER_NAT': l3plugin}),\ mock.patch.object(l3plugin, 'get_dvr_routers_to_remove', - return_value=[{'agent_id': 'foo_agent', - 'router_id': 'foo_id', - 'host': source_host}]): + return_value=routers_to_remove),\ + mock.patch.object(l3plugin, '_get_floatingip_on_port', + return_value=fip): l3_dvrscheduler_db._notify_l3_agent_port_update( 'port', 'after_update', mock.ANY, **kwargs) - (l3plugin.l3_rpc_notifier.router_removed_from_agent. - assert_called_once_with(mock.ANY, 'foo_id', source_host)) + if routers_to_remove: + (l3plugin.l3_rpc_notifier.router_removed_from_agent. + assert_called_once_with(mock.ANY, 'foo_id', source_host)) + self.assertEqual( + 1, + l3plugin.delete_arp_entry_for_dvr_service_port.call_count) + if fip and not routers_to_remove: + (l3plugin.l3_rpc_notifier.routers_updated_on_host. + assert_called_once_with(mock.ANY, ['router_id'], source_host)) self.assertEqual( 1, l3plugin.update_arp_entry_for_dvr_service_port.call_count) - self.assertEqual( - 1, l3plugin.delete_arp_entry_for_dvr_service_port.call_count) l3plugin.dvr_handle_new_service_port.assert_called_once_with( self.adminContext, kwargs.get('port'), dest_host=None) @@ -1181,7 +1208,9 @@ class L3DvrSchedulerTestCase(testlib_api.SqlTestCase): mock.patch.object(l3plugin, 'get_dvr_routers_to_remove', return_value=[{'agent_id': 'foo_agent', 'router_id': 'foo_id', - 'host': source_host}]): + 'host': source_host}]),\ + mock.patch.object(l3plugin, '_get_floatingip_on_port', + return_value=None): l3_dvrscheduler_db._notify_l3_agent_port_update( 'port', 'after_update', plugin, **kwargs)