]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
fix event_send for re-assign floating ip
authorlzklibj <lzklibj@cn.ibm.com>
Tue, 21 Oct 2014 06:55:53 +0000 (23:55 -0700)
committerlzklibj <lzklibj@cn.ibm.com>
Tue, 11 Nov 2014 02:20:10 +0000 (18:20 -0800)
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

neutron/notifiers/nova.py
neutron/tests/unit/notifiers/test_notifiers_nova.py

index 2b2bab63d1bac547bd1803314a7c387d522cf898..e95100597aa9b56cb4f51af9404bdb7fcd2cc338 100644 (file)
@@ -132,6 +132,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)
index 7972ebf55a975cd9839b8ae7beeb5427a3093d34..db9bc79c31d7f97f72844b33666e2d42d156e6a3 100644 (file)
@@ -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)