From 6a0916371bfafb79970ae274fe18118df06c080d Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Mon, 13 Mar 2017 12:52:33 -0400 Subject: [PATCH] add job cancel dependency information * Inventory updates that are canceled and are dependencies of jobs result in the dependent job being canceled. This code adds a better description to job_explanation so that a job marked as canceled can be traced back to the inventory update that triggered this case. --- awx/main/models/inventory.py | 16 +++++++++++++--- awx/main/models/jobs.py | 6 +++--- awx/main/models/unified_jobs.py | 5 ++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 387277c5e9..81ba4fd50b 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -1277,10 +1277,20 @@ class InventoryUpdate(UnifiedJob, InventorySourceOptions, JobNotificationMixin): def get_notification_friendly_name(self): return "Inventory Update" - def cancel(self): - res = super(InventoryUpdate, self).cancel() + def _build_job_explanation(self): + if not self.job_explanation: + return 'Previous Task Canceled: {"job_type": "%s", "job_name": "%s", "job_id": "%s"}' % \ + (self.model_to_str(), self.name, self.id) + return None + + def get_dependent_jobs(self): + return Job.objects.filter(dependent_jobs__in=[self.id]) + + def cancel(self, job_explanation=None): + + res = super(InventoryUpdate, self).cancel(job_explanation=job_explanation) if res: - map(lambda x: x.cancel(), Job.objects.filter(dependent_jobs__in=[self.id])) + map(lambda x: x.cancel(job_explanation=self._build_job_explanation()), self.get_dependent_jobs()) return res diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 00a68c69ca..26969ffc32 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -633,10 +633,10 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin): Canceling a job also cancels the implicit project update with launch_type run. ''' - def cancel(self): - res = super(Job, self).cancel() + def cancel(self, job_explanation=None): + res = super(Job, self).cancel(job_explanation=job_explanation) if self.project_update: - self.project_update.cancel() + self.project_update.cancel(job_explanation=job_explanation) return res diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 2ccae7fdaf..880789aafe 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -1025,7 +1025,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique if settings.DEBUG: raise - def cancel(self): + def cancel(self, job_explanation=None): if self.can_cancel: if not self.cancel_flag: self.cancel_flag = True @@ -1033,6 +1033,9 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique if self.status in ('pending', 'waiting', 'new'): self.status = 'canceled' cancel_fields.append('status') + if job_explanation is not None: + self.job_explanation = job_explanation + cancel_fields.append('job_explanation') self.save(update_fields=cancel_fields) self.websocket_emit_status("canceled") if settings.BROKER_URL.startswith('amqp://'):