L3 RPC loop could delete a router on concurrent update
routers_updated does not acquire any lock just updates a set for future rpc loop processing. The self.updated_routers can be changed by concurrent update notification. If this change happens at the time around the self.plugin_rpc.get_routers call, the additional routers - by mistake - is considered as admin_state_up=false routers, which are safe to delete. Creating a local copy of the updated_routers and preserve the fresh updated_routers entries for the next _rpc_loop operations. Change-Id: Icc7377f9c29e248c3b34562465e859b15ecc2ec3 Closes-Bug: #1315467 Partial-Bug: #1253896
This commit is contained in:
parent
3bbfaf94f1
commit
1e176b563e
@ -793,18 +793,24 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
|
|||||||
# _rpc_loop and _sync_routers_task will not be
|
# _rpc_loop and _sync_routers_task will not be
|
||||||
# executed in the same time because of lock.
|
# executed in the same time because of lock.
|
||||||
# so we can clear the value of updated_routers
|
# so we can clear the value of updated_routers
|
||||||
# and removed_routers
|
# and removed_routers, but they can be updated by
|
||||||
|
# updated_routers and removed_routers rpc call
|
||||||
try:
|
try:
|
||||||
LOG.debug(_("Starting RPC loop for %d updated routers"),
|
LOG.debug(_("Starting RPC loop for %d updated routers"),
|
||||||
len(self.updated_routers))
|
len(self.updated_routers))
|
||||||
if self.updated_routers:
|
if self.updated_routers:
|
||||||
router_ids = list(self.updated_routers)
|
# We're capturing and clearing the list, and will
|
||||||
|
# process the "captured" updates in this loop,
|
||||||
|
# and any updates that happen due to a context switch
|
||||||
|
# will be picked up on the next pass.
|
||||||
|
updated_routers = set(self.updated_routers)
|
||||||
|
self.updated_routers.clear()
|
||||||
|
router_ids = list(updated_routers)
|
||||||
routers = self.plugin_rpc.get_routers(
|
routers = self.plugin_rpc.get_routers(
|
||||||
self.context, router_ids)
|
self.context, router_ids)
|
||||||
|
# routers with admin_state_up=false will not be in the fetched
|
||||||
fetched = set([r['id'] for r in routers])
|
fetched = set([r['id'] for r in routers])
|
||||||
self.removed_routers.update(self.updated_routers - fetched)
|
self.removed_routers.update(updated_routers - fetched)
|
||||||
self.updated_routers.clear()
|
|
||||||
|
|
||||||
self._process_routers(routers)
|
self._process_routers(routers)
|
||||||
self._process_router_delete()
|
self._process_router_delete()
|
||||||
|
Loading…
Reference in New Issue
Block a user