mirror of
https://github.com/ansible/awx.git
synced 2026-02-22 05:30:18 -03:30
Supress exception with concurrent deletion
Relates https://github.com/ansible/ansible-tower/issues/7768 This issue, as well as https://github.com/ansible/ansible-tower/issues/7622, both rooted in a concurrency issue of Django ORM: https://github.com/ansible/ansible-tower/issues/762://code.djangoproject.com/ticket/28806 The solution related deals specifically with the related issue, but is not a general solution. A general workaround can be found in https://github.com/ansible/tower/pull/500. Signed-off-by: Aaron Tan <jangsutsr@gmail.com>
This commit is contained in:
@@ -1106,8 +1106,13 @@ class ProjectUpdateSerializer(UnifiedJobSerializer, ProjectOptionsSerializer):
|
|||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(ProjectUpdateSerializer, self).get_related(obj)
|
res = super(ProjectUpdateSerializer, self).get_related(obj)
|
||||||
|
try:
|
||||||
|
res.update(dict(
|
||||||
|
project = self.reverse('api:project_detail', kwargs={'pk': obj.project.pk}),
|
||||||
|
))
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
res.update(dict(
|
res.update(dict(
|
||||||
project = self.reverse('api:project_detail', kwargs={'pk': obj.project.pk}),
|
|
||||||
cancel = self.reverse('api:project_update_cancel', kwargs={'pk': obj.pk}),
|
cancel = self.reverse('api:project_update_cancel', kwargs={'pk': obj.pk}),
|
||||||
scm_inventory_updates = self.reverse('api:project_update_scm_inventory_updates', kwargs={'pk': obj.pk}),
|
scm_inventory_updates = self.reverse('api:project_update_scm_inventory_updates', kwargs={'pk': obj.pk}),
|
||||||
notifications = self.reverse('api:project_update_notifications_list', kwargs={'pk': obj.pk}),
|
notifications = self.reverse('api:project_update_notifications_list', kwargs={'pk': obj.pk}),
|
||||||
@@ -1728,8 +1733,15 @@ class InventoryUpdateSerializer(UnifiedJobSerializer, InventorySourceOptionsSeri
|
|||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(InventoryUpdateSerializer, self).get_related(obj)
|
res = super(InventoryUpdateSerializer, self).get_related(obj)
|
||||||
|
try:
|
||||||
|
res.update(dict(
|
||||||
|
inventory_source = self.reverse(
|
||||||
|
'api:inventory_source_detail', kwargs={'pk': obj.inventory_source.pk}
|
||||||
|
),
|
||||||
|
))
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
res.update(dict(
|
res.update(dict(
|
||||||
inventory_source = self.reverse('api:inventory_source_detail', kwargs={'pk': obj.inventory_source.pk}),
|
|
||||||
cancel = self.reverse('api:inventory_update_cancel', kwargs={'pk': obj.pk}),
|
cancel = self.reverse('api:inventory_update_cancel', kwargs={'pk': obj.pk}),
|
||||||
notifications = self.reverse('api:inventory_update_notifications_list', kwargs={'pk': obj.pk}),
|
notifications = self.reverse('api:inventory_update_notifications_list', kwargs={'pk': obj.pk}),
|
||||||
))
|
))
|
||||||
@@ -2339,14 +2351,30 @@ class JobOptionsSerializer(LabelsListMixin, BaseSerializer):
|
|||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(JobOptionsSerializer, self).get_related(obj)
|
res = super(JobOptionsSerializer, self).get_related(obj)
|
||||||
res['labels'] = self.reverse('api:job_template_label_list', kwargs={'pk': obj.pk})
|
res['labels'] = self.reverse('api:job_template_label_list', kwargs={'pk': obj.pk})
|
||||||
if obj.inventory:
|
try:
|
||||||
res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk})
|
if obj.inventory:
|
||||||
if obj.project:
|
res['inventory'] = self.reverse('api:inventory_detail', kwargs={'pk': obj.inventory.pk})
|
||||||
res['project'] = self.reverse('api:project_detail', kwargs={'pk': obj.project.pk})
|
except ObjectDoesNotExist:
|
||||||
if obj.credential:
|
setattr(obj, 'inventory', None)
|
||||||
res['credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.credential.pk})
|
try:
|
||||||
if obj.vault_credential:
|
if obj.project:
|
||||||
res['vault_credential'] = self.reverse('api:credential_detail', kwargs={'pk': obj.vault_credential.pk})
|
res['project'] = self.reverse('api:project_detail', kwargs={'pk': obj.project.pk})
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
setattr(obj, 'project', None)
|
||||||
|
try:
|
||||||
|
if obj.credential:
|
||||||
|
res['credential'] = self.reverse(
|
||||||
|
'api:credential_detail', kwargs={'pk': obj.credential.pk}
|
||||||
|
)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
setattr(obj, 'credential', None)
|
||||||
|
try:
|
||||||
|
if obj.vault_credential:
|
||||||
|
res['vault_credential'] = self.reverse(
|
||||||
|
'api:credential_detail', kwargs={'pk': obj.vault_credential.pk}
|
||||||
|
)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
setattr(obj, 'vault_credential', None)
|
||||||
if self.version > 1:
|
if self.version > 1:
|
||||||
if isinstance(obj, UnifiedJobTemplate):
|
if isinstance(obj, UnifiedJobTemplate):
|
||||||
res['extra_credentials'] = self.reverse(
|
res['extra_credentials'] = self.reverse(
|
||||||
@@ -2584,15 +2612,23 @@ class JobSerializer(UnifiedJobSerializer, JobOptionsSerializer):
|
|||||||
notifications = self.reverse('api:job_notifications_list', kwargs={'pk': obj.pk}),
|
notifications = self.reverse('api:job_notifications_list', kwargs={'pk': obj.pk}),
|
||||||
labels = self.reverse('api:job_label_list', kwargs={'pk': obj.pk}),
|
labels = self.reverse('api:job_label_list', kwargs={'pk': obj.pk}),
|
||||||
))
|
))
|
||||||
if obj.job_template:
|
try:
|
||||||
res['job_template'] = self.reverse('api:job_template_detail',
|
if obj.job_template:
|
||||||
kwargs={'pk': obj.job_template.pk})
|
res['job_template'] = self.reverse('api:job_template_detail',
|
||||||
|
kwargs={'pk': obj.job_template.pk})
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
setattr(obj, 'job_template', None)
|
||||||
if (obj.can_start or True) and self.version == 1: # TODO: remove in 3.3
|
if (obj.can_start or True) and self.version == 1: # TODO: remove in 3.3
|
||||||
res['start'] = self.reverse('api:job_start', kwargs={'pk': obj.pk})
|
res['start'] = self.reverse('api:job_start', kwargs={'pk': obj.pk})
|
||||||
if obj.can_cancel or True:
|
if obj.can_cancel or True:
|
||||||
res['cancel'] = self.reverse('api:job_cancel', kwargs={'pk': obj.pk})
|
res['cancel'] = self.reverse('api:job_cancel', kwargs={'pk': obj.pk})
|
||||||
if obj.project_update:
|
try:
|
||||||
res['project_update'] = self.reverse('api:project_update_detail', kwargs={'pk': obj.project_update.pk})
|
if obj.project_update:
|
||||||
|
res['project_update'] = self.reverse(
|
||||||
|
'api:project_update_detail', kwargs={'pk': obj.project_update.pk}
|
||||||
|
)
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
res['relaunch'] = self.reverse('api:job_relaunch', kwargs={'pk': obj.pk})
|
res['relaunch'] = self.reverse('api:job_relaunch', kwargs={'pk': obj.pk})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from django.db.models import Q, Prefetch
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
# Django REST Framework
|
# Django REST Framework
|
||||||
from rest_framework.exceptions import ParseError, PermissionDenied, ValidationError
|
from rest_framework.exceptions import ParseError, PermissionDenied, ValidationError
|
||||||
@@ -1134,8 +1135,11 @@ class ProjectUpdateAccess(BaseAccess):
|
|||||||
|
|
||||||
def can_start(self, obj, validate_license=True):
|
def can_start(self, obj, validate_license=True):
|
||||||
# for relaunching
|
# for relaunching
|
||||||
if obj and obj.project:
|
try:
|
||||||
return self.user in obj.project.update_role
|
if obj and obj.project:
|
||||||
|
return self.user in obj.project.update_role
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@check_superuser
|
@check_superuser
|
||||||
|
|||||||
Reference in New Issue
Block a user