From 231398ca5fee7b825646eeed84523dbfcb414438 Mon Sep 17 00:00:00 2001 From: Gregory Thiemonge Date: Fri, 15 Sep 2023 03:42:26 -0400 Subject: [PATCH] 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 8a47577b7668e6dc82e048d937d1344c667e5124) (cherry picked from commit 8a5bed4cebd70c1c721a3916dc79f2b19343e445) (cherry picked from commit 64d9bdb97556652aa05a34276778260b541ad9c6) (cherry picked from commit 4c97b585ce6e519a5ff090c2cd97fab0e801be0c) --- octavia/api/v2/controllers/member.py | 6 +++++- ...ace-condition-member-batch-update-1aed0e06004c5dad.yaml | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-race-condition-member-batch-update-1aed0e06004c5dad.yaml diff --git a/octavia/api/v2/controllers/member.py b/octavia/api/v2/controllers/member.py index 696591b806..5b946c660b 100644 --- a/octavia/api/v2/controllers/member.py +++ b/octavia/api/v2/controllers/member.py @@ -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 = [ diff --git a/releasenotes/notes/fix-race-condition-member-batch-update-1aed0e06004c5dad.yaml b/releasenotes/notes/fix-race-condition-member-batch-update-1aed0e06004c5dad.yaml new file mode 100644 index 0000000000..b2c5403e08 --- /dev/null +++ b/releasenotes/notes/fix-race-condition-member-batch-update-1aed0e06004c5dad.yaml @@ -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.