From 1c170c3a12d5b13cd7542fc7624105de0e644463 Mon Sep 17 00:00:00 2001 From: Peter Braun Date: Fri, 13 Sep 2024 09:35:45 +0200 Subject: [PATCH] fix: avoid race conditions when removing multiple instance (#15495) * fix: avoid race conditions when removing multiple instance groups at once * remove unused imports --- awx/api/views/mixin.py | 16 ++++++++++++++++ awx/api/views/organization.py | 4 ++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/awx/api/views/mixin.py b/awx/api/views/mixin.py index 2ddc464464..eda90edbfa 100644 --- a/awx/api/views/mixin.py +++ b/awx/api/views/mixin.py @@ -15,6 +15,7 @@ from rest_framework.response import Response from rest_framework import status from awx.main.constants import ACTIVE_STATES +from awx.main.models import Organization from awx.main.utils import get_object_or_400 from awx.main.models.ha import Instance, InstanceGroup, schedule_policy_task from awx.main.models.organization import Team @@ -60,6 +61,21 @@ class UnifiedJobDeletionMixin(object): return Response(status=status.HTTP_204_NO_CONTENT) +class OrganizationInstanceGroupMembershipMixin(object): + """ + This mixin overloads attach/detach so that it calls Organization.save(), + to ensure instance group updates are persisted + """ + + def unattach(self, request, *args, **kwargs): + with transaction.atomic(): + organization_queryset = Organization.objects.select_for_update() + organization = organization_queryset.get(pk=self.get_parent_object().id) + response = super(OrganizationInstanceGroupMembershipMixin, self).unattach(request, *args, **kwargs) + organization.save() + return response + + class InstanceGroupMembershipMixin(object): """ This mixin overloads attach/detach so that it calls InstanceGroup.save(), diff --git a/awx/api/views/organization.py b/awx/api/views/organization.py index 9b93ac8406..338a35678b 100644 --- a/awx/api/views/organization.py +++ b/awx/api/views/organization.py @@ -52,7 +52,7 @@ from awx.api.serializers import ( WorkflowJobTemplateSerializer, CredentialSerializer, ) -from awx.api.views.mixin import RelatedJobsPreventDeleteMixin, OrganizationCountsMixin +from awx.api.views.mixin import RelatedJobsPreventDeleteMixin, OrganizationCountsMixin, OrganizationInstanceGroupMembershipMixin from awx.api.views import immutablesharedfields logger = logging.getLogger('awx.api.views.organization') @@ -202,7 +202,7 @@ class OrganizationNotificationTemplatesApprovalList(OrganizationNotificationTemp relationship = 'notification_templates_approvals' -class OrganizationInstanceGroupsList(SubListAttachDetachAPIView): +class OrganizationInstanceGroupsList(OrganizationInstanceGroupMembershipMixin, SubListAttachDetachAPIView): model = InstanceGroup serializer_class = InstanceGroupSerializer parent_model = Organization