From c7954abb174b7b6dbd0ccff9397e2521876cb312 Mon Sep 17 00:00:00 2001 From: lzklibj Date: Mon, 20 Oct 2014 23:55:53 -0700 Subject: [PATCH] fix event_send for re-assign floating ip Neutron can associate a floating ip to a new port without disassociate from original instance port. This situation will send network changed event only for new instance port, and that event object contains the new instance's id. In this case nova will update new instance's info but not original one's in nova's database table instance_info_caches. For nova can get new instance's id from the above event. So in table instance_info_caches, both original instance and new instance will have the same floating ip in their records. And this make it possible that, in most situation, after your re-assign floating ip, run "nova list" will return incorrect info, multiple instances have a same floating ip, and this may confuse users. Nova will sync data in table instance_info_caches, but it may take dozens of seconds. The new added code will send network changed event for the original instance, and this will make nova update instance_ _info_caches table in a few seconds. Change-Id: If3ee11535f649fc51bf1a52806008c1c5c0e73b6 Closes-Bug: 1381886 (cherry picked from commit add8944d4dba2a69e8f7da47f120d5dc63952f77) --- neutron/notifiers/nova.py | 12 ++++++++++++ .../tests/unit/notifiers/test_notifiers_nova.py | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/neutron/notifiers/nova.py b/neutron/notifiers/nova.py index aa4f1b53e..1db6bc097 100644 --- a/neutron/notifiers/nova.py +++ b/neutron/notifiers/nova.py @@ -128,6 +128,18 @@ class Notifier(object): if not cfg.CONF.notify_nova_on_port_data_changes: return + # When neutron re-assigns floating ip from an original instance + # port to a new instance port without disassociate it first, an + # event should be sent for original instance, that will make nova + # know original instance's info, and update database for it. + if (action == 'update_floatingip' + and returned_obj['floatingip'].get('port_id') + and original_obj.get('port_id')): + disassociate_returned_obj = {'floatingip': {'port_id': None}} + event = self.create_port_changed_event(action, original_obj, + disassociate_returned_obj) + self.queue_event(event) + event = self.create_port_changed_event(action, original_obj, returned_obj) self.queue_event(event) diff --git a/neutron/tests/unit/notifiers/test_notifiers_nova.py b/neutron/tests/unit/notifiers/test_notifiers_nova.py index 7972ebf55..db9bc79c3 100644 --- a/neutron/tests/unit/notifiers/test_notifiers_nova.py +++ b/neutron/tests/unit/notifiers/test_notifiers_nova.py @@ -303,3 +303,20 @@ class TestNovaNotify(base.BaseTestCase): self.nova_notifier.queue_event(mock.Mock()) self.assertFalse(self.nova_notifier._waiting_to_send) send_events.assert_called_once_with() + + def test_reassociate_floatingip_without_disassociate_event(self): + returned_obj = {'floatingip': + {'port_id': 'f5348a16-609a-4971-b0f0-4b8def5235fb'}} + original_obj = {'port_id': '5a39def4-3d3f-473d-9ff4-8e90064b9cc1'} + self.nova_notifier._waiting_to_send = True + self.nova_notifier.send_network_change( + 'update_floatingip', original_obj, returned_obj) + self.assertEqual(2, len(self.nova_notifier.pending_events)) + + returned_obj_non = {'floatingip': {'port_id': None}} + event_dis = self.nova_notifier.create_port_changed_event( + 'update_floatingip', original_obj, returned_obj_non) + event_assoc = self.nova_notifier.create_port_changed_event( + 'update_floatingip', original_obj, returned_obj) + self.assertEqual(self.nova_notifier.pending_events[0], event_dis) + self.assertEqual(self.nova_notifier.pending_events[1], event_assoc) -- 2.45.2