]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
NSX: Fix KeyError in sync if nsx_router_id not found
authorAaron Rosen <aaronorosen@gmail.com>
Tue, 8 Apr 2014 20:20:49 +0000 (13:20 -0700)
committerAaron Rosen <aaronorosen@gmail.com>
Wed, 9 Apr 2014 01:28:18 +0000 (18:28 -0700)
Previously, a KeyError would occur in the sync code which would
cause the sync thread to stop running. This would occur if there
was a router entry in the database but no nsx_router_mapping and
the router was not found in nsx. Note: this should never happen unless
one did not run the db migration which introduced and migrated the data
for the NeutronNsxRouterMapping table.

(cherry picked from commit d90d71cfdae1d9c9c3b54cc33adfabce683c633c)
Change-Id: I44f3e7de9323f594501db63d3ad33e80e617bfdc
Closes-bug: #1304647

neutron/plugins/vmware/common/sync.py
neutron/tests/unit/vmware/test_nsx_sync.py

index 1b9c4926bd02399e9afe078dc470763369b8e3cd..d032f43fe1d1c14b75cc05f1806f90e6c58ecf5e 100644 (file)
@@ -334,16 +334,16 @@ class NsxSynchronizer():
                 # This query will return the logical router status too
                 nsx_router_id = nsx_utils.get_nsx_router_id(
                     context.session, self._cluster, neutron_router_data['id'])
-                lrouter = routerlib.get_lrouter(
-                    self._cluster, nsx_router_id)
+                if nsx_router_id:
+                    lrouter = routerlib.get_lrouter(
+                        self._cluster, nsx_router_id)
             except exceptions.NotFound:
                 # NOTE(salv-orlando): We should be catching
                 # api_exc.ResourceNotFound here
                 # The logical router was not found
                 LOG.warning(_("Logical router for neutron router %s not "
                               "found on NSX."), neutron_router_data['id'])
-                lrouter = None
-            else:
+            if lrouter:
                 # Update the cache
                 self._nsx_cache.update_lrouter(lrouter)
 
index b9de0a156cc8f4157decced488f5ab6bd72276ea..6fbb5d7da6cc9a5b1754083d14639808baec4bee 100644 (file)
@@ -30,6 +30,7 @@ from neutron.plugins.vmware.api_client import client
 from neutron.plugins.vmware.api_client import exception as api_exc
 from neutron.plugins.vmware.api_client import version
 from neutron.plugins.vmware.common import sync
+from neutron.plugins.vmware.dbexts import db
 from neutron.plugins.vmware import nsx_cluster as cluster
 from neutron.plugins.vmware import nsxlib
 from neutron.plugins.vmware import plugin
@@ -621,6 +622,34 @@ class SyncTestCase(base.BaseTestCase):
                     exp_status = constants.NET_STATUS_ACTIVE
                 self.assertEqual(exp_status, q_rtr['status'])
 
+    def test_synchronize_router_nsx_mapping_not_found(self):
+        ctx = context.get_admin_context()
+        with self._populate_data(ctx):
+            # Put a router down to verify synchronization
+            lr_uuid = self.fc._fake_lrouter_dict.keys()[0]
+            q_rtr_id = self._get_tag_dict(
+                self.fc._fake_lrouter_dict[lr_uuid]['tags'])['q_router_id']
+            self.fc._fake_lrouter_dict[lr_uuid]['status'] = 'false'
+            q_rtr_data = self._plugin._get_router(ctx, q_rtr_id)
+
+            # delete router mapping from db.
+            db.delete_neutron_nsx_router_mapping(ctx.session, q_rtr_id)
+            # pop router from fake nsx client
+            router_data = self.fc._fake_lrouter_dict.pop(lr_uuid)
+
+            self._plugin._synchronizer.synchronize_router(ctx, q_rtr_data)
+            # Reload from db
+            q_routers = self._plugin.get_routers(ctx)
+            for q_rtr in q_routers:
+                if q_rtr['id'] == q_rtr_id:
+                    exp_status = constants.NET_STATUS_ERROR
+                else:
+                    exp_status = constants.NET_STATUS_ACTIVE
+                self.assertEqual(exp_status, q_rtr['status'])
+            # put the router database since we don't handle missing
+            # router data in the fake nsx api_client
+            self.fc._fake_lrouter_dict[lr_uuid] = router_data
+
     def test_synchronize_router_on_get(self):
         cfg.CONF.set_override('always_read_status', True, 'NSX_SYNC')
         ctx = context.get_admin_context()