]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix l3 agent to not create already deleted router
authorOleg Bondarev <obondarev@mirantis.com>
Thu, 11 Jun 2015 10:38:55 +0000 (13:38 +0300)
committerOleg Bondarev <obondarev@mirantis.com>
Fri, 19 Jun 2015 14:38:53 +0000 (17:38 +0300)
In case router is deleted during l3 agent resync,
the "deleted" event is processed with higher priority, then
resync event for the router may be processed which will recreate
already deleted router.
This happens due to timestamp not being properly updated for deleted
router in router processor.
The fix adds timestamp update for deleted router.

Functional test will be updated in a follow-up patch

Logging was improved to make debugging a bit easier.

Closes-Bug: #1455439
Change-Id: I2d060064acccc10591a3d90be9011f116548cfce

neutron/agent/l3/agent.py
neutron/tests/unit/agent/l3/test_agent.py

index 6b25b9310952431da38810b3a350a18cbaf68054..d9e4db8de214517361d517b8d66361c6ffa02aae 100644 (file)
@@ -441,7 +441,8 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
 
     def _process_router_update(self):
         for rp, update in self._queue.each_update_to_next_router():
-            LOG.debug("Starting router update for %s", update.id)
+            LOG.debug("Starting router update for %s, action %s, priority %s",
+                      update.id, update.action, update.priority)
             router = update.router
             if update.action != queue.DELETE_ROUTER and not router:
                 try:
@@ -464,6 +465,12 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback,
                     # one router by sticking the update at the end of the queue
                     # at a lower priority.
                     self.fullsync = True
+                else:
+                    # need to update timestamp of removed router in case
+                    # there are older events for the same router in the
+                    # processing queue (like events from fullsync) in order to
+                    # prevent deleted router re-creation
+                    rp.fetched_and_processed(update.timestamp)
                 continue
 
             try:
index 143c659dd122f7c53bb5315cf567eeeedb0f8804..d10c30d8c628049f5a78be4e50958b3af5a600a3 100644 (file)
@@ -2090,6 +2090,23 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
         agent._process_router_update()
         self.assertTrue(agent.fullsync)
 
+    def test_process_routers_update_router_deleted(self):
+        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+        agent._queue = mock.Mock()
+        update = mock.Mock()
+        update.router = None
+        update.action = 1  # ROUTER_DELETED
+        router_info = mock.MagicMock()
+        agent.router_info[update.id] = router_info
+        router_processor = mock.Mock()
+        agent._queue.each_update_to_next_router.side_effect = [
+            [(router_processor, update)]]
+        agent._process_router_update()
+        router_info.delete.assert_called_once_with(agent)
+        self.assertFalse(agent.router_info)
+        router_processor.fetched_and_processed.assert_called_once_with(
+            update.timestamp)
+
     def test_process_router_if_compatible_with_no_ext_net_in_conf(self):
         agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
         self.plugin_api.get_external_network_id.return_value = 'aaa'