]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix race condition in dhcp agent
authorAaron Rosen <arosen@nicira.com>
Thu, 21 Mar 2013 01:19:04 +0000 (18:19 -0700)
committerAaron Rosen <arosen@nicira.com>
Thu, 21 Mar 2013 21:39:04 +0000 (14:39 -0700)
This patch fixes a race condition that can happen in the dhcp agent when
a subnet is created and then a host route is then immediately added to that
subnet following a subnet.update.end notification. The race condition occurs
in refresh_dhcp_helper() where self.enable_dhcp_helper() gets called twice
since the first call had not completed self.cache.put(network). This same race
condition can also occur in the other events so lockutils.synchronized() is
added to synchronize those code segments as well.

Fixes bug 1155748

Change-Id: I2ff52adc3dfebddd6d9c15d5dc79aa65be107179

quantum/agent/dhcp_agent.py

index c5d4a03137056c740d08266c04abec4002e4b30d..3ebcbcaf717d3b1256c3e1e1c0a2c9b70a3b0f15 100644 (file)
@@ -37,6 +37,7 @@ from quantum import manager
 from quantum.openstack.common import importutils
 from quantum.openstack.common import jsonutils
 from quantum.openstack.common import log as logging
+from quantum.openstack.common import lockutils
 from quantum.openstack.common import loopingcall
 from quantum.openstack.common.rpc import proxy
 from quantum.openstack.common import service
@@ -226,11 +227,13 @@ class DhcpAgent(manager.Manager):
         else:
             self.disable_dhcp_helper(network.id)
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def network_create_end(self, context, payload):
         """Handle the network.create.end notification event."""
         network_id = payload['network']['id']
         self.enable_dhcp_helper(network_id)
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def network_update_end(self, context, payload):
         """Handle the network.update.end notification event."""
         network_id = payload['network']['id']
@@ -239,10 +242,12 @@ class DhcpAgent(manager.Manager):
         else:
             self.disable_dhcp_helper(network_id)
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def network_delete_end(self, context, payload):
         """Handle the network.delete.end notification event."""
         self.disable_dhcp_helper(payload['network_id'])
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def subnet_update_end(self, context, payload):
         """Handle the subnet.update.end notification event."""
         network_id = payload['subnet']['network_id']
@@ -251,6 +256,7 @@ class DhcpAgent(manager.Manager):
     # Use the update handler for the subnet create event.
     subnet_create_end = subnet_update_end
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def subnet_delete_end(self, context, payload):
         """Handle the subnet.delete.end notification event."""
         subnet_id = payload['subnet_id']
@@ -258,6 +264,7 @@ class DhcpAgent(manager.Manager):
         if network:
             self.refresh_dhcp_helper(network.id)
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def port_update_end(self, context, payload):
         """Handle the port.update.end notification event."""
         port = DictModel(payload['port'])
@@ -269,6 +276,7 @@ class DhcpAgent(manager.Manager):
     # Use the update handler for the port create event.
     port_create_end = port_update_end
 
+    @lockutils.synchronized('agent', 'dhcp-')
     def port_delete_end(self, context, payload):
         """Handle the port.delete.end notification event."""
         port = self.cache.get_port_by_id(payload['port_id'])