Fix race condition in members batch update API call

Fix a potential race condition, the member batch update API call
computes a delta between the current state of the members in the DB and
the members in the requests. But it fetches the members from the DB
before locking the load balancer, it means that another Octavia service
may still update the list of members, then the computation of the
changes may be incorrect.

The list of members is now queried in the locked section.

Closes-Bug: #2036156
Change-Id: I453ff385620f488a3e43d4fda01634cdce3be5d4
(cherry picked from commit 8a47577b76)
(cherry picked from commit 8a5bed4ceb)
(cherry picked from commit 64d9bdb975)
(cherry picked from commit 4c97b585ce)
This commit is contained in:
Gregory Thiemonge 2023-09-15 03:42:26 -04:00
parent 5bf40c896a
commit 231398ca5f
2 changed files with 12 additions and 1 deletions

View File

@ -325,7 +325,6 @@ class MembersController(MemberController):
context = pecan_request.context.get('octavia_context')
db_pool = self._get_db_pool(context.session, self.pool_id)
old_members = db_pool.members
project_id, provider = self._get_lb_project_id_provider(
context.session, db_pool.load_balancer_id)
@ -343,6 +342,11 @@ class MembersController(MemberController):
with db_api.get_lock_session() as lock_session:
self._test_lb_and_listener_and_pool_statuses(lock_session)
# Reload the pool, the members may have been updated between the
# first query in this function and the lock of the loadbalancer
db_pool = self._get_db_pool(context.session, self.pool_id)
old_members = db_pool.members
old_member_uniques = {
(m.ip_address, m.protocol_port): m.id for m in old_members}
new_member_uniques = [

View File

@ -0,0 +1,7 @@
---
fixes:
- |
Fixed a race condition in the members batch update API call, the data
passed to the Octavia worker service may have been incorrect when quickly
sending successive API calls. Then the load balancer was stuck in
PENDING_UPDATE provisioning_status.