diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 4f57087599..7963c06f5a 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1247,6 +1247,7 @@ class OrganizationSerializer(BaseSerializer): activity_stream = self.reverse('api:organization_activity_stream_list', kwargs={'pk': obj.pk}), notification_templates = self.reverse('api:organization_notification_templates_list', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:organization_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:organization_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:organization_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:organization_notification_templates_error_list', kwargs={'pk': obj.pk}), object_roles = self.reverse('api:organization_object_roles_list', kwargs={'pk': obj.pk}), @@ -1353,6 +1354,7 @@ class ProjectSerializer(UnifiedJobTemplateSerializer, ProjectOptionsSerializer): schedules = self.reverse('api:project_schedules_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:project_activity_stream_list', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:project_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:project_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:project_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:project_notification_templates_error_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:project_access_list', kwargs={'pk': obj.pk}), @@ -1971,6 +1973,7 @@ class InventorySourceSerializer(UnifiedJobTemplateSerializer, InventorySourceOpt hosts = self.reverse('api:inventory_source_hosts_list', kwargs={'pk': obj.pk}), groups = self.reverse('api:inventory_source_groups_list', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:inventory_source_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:inventory_source_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:inventory_source_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:inventory_source_notification_templates_error_list', kwargs={'pk': obj.pk}), )) @@ -2793,6 +2796,7 @@ class JobTemplateSerializer(JobTemplateMixin, UnifiedJobTemplateSerializer, JobO activity_stream = self.reverse('api:job_template_activity_stream_list', kwargs={'pk': obj.pk}), launch = self.reverse('api:job_template_launch', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:job_template_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:job_template_access_list', kwargs={'pk': obj.pk}), @@ -3205,6 +3209,7 @@ class SystemJobTemplateSerializer(UnifiedJobTemplateSerializer): schedules = self.reverse('api:system_job_template_schedules_list', kwargs={'pk': obj.pk}), launch = self.reverse('api:system_job_template_launch', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:system_job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:system_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:system_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:system_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), @@ -3272,6 +3277,7 @@ class WorkflowJobTemplateSerializer(JobTemplateMixin, LabelsListMixin, UnifiedJo labels = self.reverse('api:workflow_job_template_label_list', kwargs={'pk': obj.pk}), activity_stream = self.reverse('api:workflow_job_template_activity_stream_list', kwargs={'pk': obj.pk}), notification_templates_any = self.reverse('api:workflow_job_template_notification_templates_any_list', kwargs={'pk': obj.pk}), + notification_templates_started = self.reverse('api:workflow_job_template_notification_templates_started_list', kwargs={'pk': obj.pk}), notification_templates_success = self.reverse('api:workflow_job_template_notification_templates_success_list', kwargs={'pk': obj.pk}), notification_templates_error = self.reverse('api:workflow_job_template_notification_templates_error_list', kwargs={'pk': obj.pk}), access_list = self.reverse('api:workflow_job_template_access_list', kwargs={'pk': obj.pk}), diff --git a/awx/api/urls/inventory_source.py b/awx/api/urls/inventory_source.py index 7a03b91f76..e20362b523 100644 --- a/awx/api/urls/inventory_source.py +++ b/awx/api/urls/inventory_source.py @@ -15,6 +15,7 @@ from awx.api.views import ( InventorySourceHostsList, InventorySourceNotificationTemplatesAnyList, InventorySourceNotificationTemplatesErrorList, + InventorySourceNotificationTemplatesStartedList, InventorySourceNotificationTemplatesSuccessList, ) @@ -31,6 +32,8 @@ urls = [ url(r'^(?P[0-9]+)/hosts/$', InventorySourceHostsList.as_view(), name='inventory_source_hosts_list'), url(r'^(?P[0-9]+)/notification_templates_any/$', InventorySourceNotificationTemplatesAnyList.as_view(), name='inventory_source_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_started/$', InventorySourceNotificationTemplatesStartedList.as_view(), + name='inventory_source_notification_templates_started_list'), url(r'^(?P[0-9]+)/notification_templates_error/$', InventorySourceNotificationTemplatesErrorList.as_view(), name='inventory_source_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', InventorySourceNotificationTemplatesSuccessList.as_view(), diff --git a/awx/api/urls/job_template.py b/awx/api/urls/job_template.py index 0b43575ba4..d9c755e731 100644 --- a/awx/api/urls/job_template.py +++ b/awx/api/urls/job_template.py @@ -15,6 +15,7 @@ from awx.api.views import ( JobTemplateActivityStreamList, JobTemplateNotificationTemplatesAnyList, JobTemplateNotificationTemplatesErrorList, + JobTemplateNotificationTemplatesStartedList, JobTemplateNotificationTemplatesSuccessList, JobTemplateInstanceGroupsList, JobTemplateAccessList, @@ -36,6 +37,8 @@ urls = [ url(r'^(?P[0-9]+)/activity_stream/$', JobTemplateActivityStreamList.as_view(), name='job_template_activity_stream_list'), url(r'^(?P[0-9]+)/notification_templates_any/$', JobTemplateNotificationTemplatesAnyList.as_view(), name='job_template_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_started/$', JobTemplateNotificationTemplatesStartedList.as_view(), + name='job_template_notification_templates_started_list'), url(r'^(?P[0-9]+)/notification_templates_error/$', JobTemplateNotificationTemplatesErrorList.as_view(), name='job_template_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', JobTemplateNotificationTemplatesSuccessList.as_view(), diff --git a/awx/api/urls/organization.py b/awx/api/urls/organization.py index 911143bb86..af04f1fc77 100644 --- a/awx/api/urls/organization.py +++ b/awx/api/urls/organization.py @@ -17,6 +17,7 @@ from awx.api.views import ( OrganizationNotificationTemplatesList, OrganizationNotificationTemplatesAnyList, OrganizationNotificationTemplatesErrorList, + OrganizationNotificationTemplatesStartedList, OrganizationNotificationTemplatesSuccessList, OrganizationInstanceGroupsList, OrganizationObjectRolesList, @@ -25,7 +26,7 @@ from awx.api.views import ( ) -urls = [ +urls = [ url(r'^$', OrganizationList.as_view(), name='organization_list'), url(r'^(?P[0-9]+)/$', OrganizationDetail.as_view(), name='organization_detail'), url(r'^(?P[0-9]+)/users/$', OrganizationUsersList.as_view(), name='organization_users_list'), @@ -39,6 +40,8 @@ urls = [ url(r'^(?P[0-9]+)/notification_templates/$', OrganizationNotificationTemplatesList.as_view(), name='organization_notification_templates_list'), url(r'^(?P[0-9]+)/notification_templates_any/$', OrganizationNotificationTemplatesAnyList.as_view(), name='organization_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_started/$', OrganizationNotificationTemplatesStartedList.as_view(), + name='organization_notification_templates_started_list'), url(r'^(?P[0-9]+)/notification_templates_error/$', OrganizationNotificationTemplatesErrorList.as_view(), name='organization_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', OrganizationNotificationTemplatesSuccessList.as_view(), diff --git a/awx/api/urls/project.py b/awx/api/urls/project.py index 263014e6e2..a37bf0cefb 100644 --- a/awx/api/urls/project.py +++ b/awx/api/urls/project.py @@ -16,6 +16,7 @@ from awx.api.views import ( ProjectSchedulesList, ProjectNotificationTemplatesAnyList, ProjectNotificationTemplatesErrorList, + ProjectNotificationTemplatesStartedList, ProjectNotificationTemplatesSuccessList, ProjectObjectRolesList, ProjectAccessList, @@ -38,6 +39,8 @@ urls = [ url(r'^(?P[0-9]+)/notification_templates_error/$', ProjectNotificationTemplatesErrorList.as_view(), name='project_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', ProjectNotificationTemplatesSuccessList.as_view(), name='project_notification_templates_success_list'), + url(r'^(?P[0-9]+)/notification_templates_started/$', ProjectNotificationTemplatesStartedList.as_view(), + name='project_notification_templates_started_list'), url(r'^(?P[0-9]+)/object_roles/$', ProjectObjectRolesList.as_view(), name='project_object_roles_list'), url(r'^(?P[0-9]+)/access_list/$', ProjectAccessList.as_view(), name='project_access_list'), url(r'^(?P[0-9]+)/copy/$', ProjectCopy.as_view(), name='project_copy'), diff --git a/awx/api/urls/system_job_template.py b/awx/api/urls/system_job_template.py index 637ce05060..294ed863b5 100644 --- a/awx/api/urls/system_job_template.py +++ b/awx/api/urls/system_job_template.py @@ -11,6 +11,7 @@ from awx.api.views import ( SystemJobTemplateSchedulesList, SystemJobTemplateNotificationTemplatesAnyList, SystemJobTemplateNotificationTemplatesErrorList, + SystemJobTemplateNotificationTemplatesStartedList, SystemJobTemplateNotificationTemplatesSuccessList, ) @@ -23,6 +24,8 @@ urls = [ url(r'^(?P[0-9]+)/schedules/$', SystemJobTemplateSchedulesList.as_view(), name='system_job_template_schedules_list'), url(r'^(?P[0-9]+)/notification_templates_any/$', SystemJobTemplateNotificationTemplatesAnyList.as_view(), name='system_job_template_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_any/$', SystemJobTemplateNotificationTemplatesStartedList.as_view(), + name='system_job_template_notification_templates_started_list'), url(r'^(?P[0-9]+)/notification_templates_error/$', SystemJobTemplateNotificationTemplatesErrorList.as_view(), name='system_job_template_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', SystemJobTemplateNotificationTemplatesSuccessList.as_view(), diff --git a/awx/api/urls/workflow_job_template.py b/awx/api/urls/workflow_job_template.py index 2c6f880ce5..67ac690b60 100644 --- a/awx/api/urls/workflow_job_template.py +++ b/awx/api/urls/workflow_job_template.py @@ -15,6 +15,7 @@ from awx.api.views import ( WorkflowJobTemplateActivityStreamList, WorkflowJobTemplateNotificationTemplatesAnyList, WorkflowJobTemplateNotificationTemplatesErrorList, + WorkflowJobTemplateNotificationTemplatesStartedList, WorkflowJobTemplateNotificationTemplatesSuccessList, WorkflowJobTemplateAccessList, WorkflowJobTemplateObjectRolesList, @@ -34,6 +35,8 @@ urls = [ url(r'^(?P[0-9]+)/activity_stream/$', WorkflowJobTemplateActivityStreamList.as_view(), name='workflow_job_template_activity_stream_list'), url(r'^(?P[0-9]+)/notification_templates_any/$', WorkflowJobTemplateNotificationTemplatesAnyList.as_view(), name='workflow_job_template_notification_templates_any_list'), + url(r'^(?P[0-9]+)/notification_templates_started/$', WorkflowJobTemplateNotificationTemplatesStartedList.as_view(), + name='workflow_job_template_notification_templates_started_list'), url(r'^(?P[0-9]+)/notification_templates_error/$', WorkflowJobTemplateNotificationTemplatesErrorList.as_view(), name='workflow_job_template_notification_templates_error_list'), url(r'^(?P[0-9]+)/notification_templates_success/$', WorkflowJobTemplateNotificationTemplatesSuccessList.as_view(), diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 9f85854cdd..92eaa04598 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -116,6 +116,7 @@ from awx.api.views.organization import ( # noqa OrganizationNotificationTemplatesList, OrganizationNotificationTemplatesAnyList, OrganizationNotificationTemplatesErrorList, + OrganizationNotificationTemplatesStartedList, OrganizationNotificationTemplatesSuccessList, OrganizationInstanceGroupsList, OrganizationAccessList, @@ -750,6 +751,14 @@ class ProjectNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): relationship = 'notification_templates_any' +class ProjectNotificationTemplatesStartedList(SubListCreateAttachDetachAPIView): + + model = models.NotificationTemplate + serializer_class = serializers.NotificationTemplateSerializer + parent_model = models.Project + relationship = 'notification_templates_started' + + class ProjectNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): model = models.NotificationTemplate @@ -2113,6 +2122,11 @@ class InventorySourceNotificationTemplatesAnyList(SubListCreateAttachDetachAPIVi return super(InventorySourceNotificationTemplatesAnyList, self).post(request, *args, **kwargs) +class InventorySourceNotificationTemplatesStartedList(InventorySourceNotificationTemplatesAnyList): + + relationship = 'notification_templates_started' + + class InventorySourceNotificationTemplatesErrorList(InventorySourceNotificationTemplatesAnyList): relationship = 'notification_templates_error' @@ -2629,6 +2643,14 @@ class JobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView): relationship = 'notification_templates_any' +class JobTemplateNotificationTemplatesStartedList(SubListCreateAttachDetachAPIView): + + model = models.NotificationTemplate + serializer_class = serializers.NotificationTemplateSerializer + parent_model = models.JobTemplate + relationship = 'notification_templates_started' + + class JobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): model = models.NotificationTemplate @@ -3237,6 +3259,14 @@ class WorkflowJobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachA relationship = 'notification_templates_any' +class WorkflowJobTemplateNotificationTemplatesStartedList(SubListCreateAttachDetachAPIView): + + model = models.NotificationTemplate + serializer_class = serializers.NotificationTemplateSerializer + parent_model = models.WorkflowJobTemplate + relationship = 'notification_templates_started' + + class WorkflowJobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): model = models.NotificationTemplate @@ -3414,6 +3444,14 @@ class SystemJobTemplateNotificationTemplatesAnyList(SubListCreateAttachDetachAPI relationship = 'notification_templates_any' +class SystemJobTemplateNotificationTemplatesStartedList(SubListCreateAttachDetachAPIView): + + model = models.NotificationTemplate + serializer_class = serializers.NotificationTemplateSerializer + parent_model = models.SystemJobTemplate + relationship = 'notification_templates_started' + + class SystemJobTemplateNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): model = models.NotificationTemplate diff --git a/awx/api/views/organization.py b/awx/api/views/organization.py index 37cce7d289..c86306e9cd 100644 --- a/awx/api/views/organization.py +++ b/awx/api/views/organization.py @@ -181,6 +181,14 @@ class OrganizationNotificationTemplatesAnyList(SubListCreateAttachDetachAPIView) relationship = 'notification_templates_any' +class OrganizationNotificationTemplatesStartedList(SubListCreateAttachDetachAPIView): + + model = NotificationTemplate + serializer_class = NotificationTemplateSerializer + parent_model = Organization + relationship = 'notification_templates_started' + + class OrganizationNotificationTemplatesErrorList(SubListCreateAttachDetachAPIView): model = NotificationTemplate diff --git a/awx/main/models/ad_hoc_commands.py b/awx/main/models/ad_hoc_commands.py index 5671bb3383..c843b9f577 100644 --- a/awx/main/models/ad_hoc_commands.py +++ b/awx/main/models/ad_hoc_commands.py @@ -170,11 +170,14 @@ class AdHocCommand(UnifiedJob, JobNotificationMixin): active_templates['error'].add(templ) for templ in base_notification_templates.filter(organization_notification_templates_for_success=org): active_templates['success'].add(templ) + for templ in base_notification_templates.filter(organization_notification_templates_for_started=org): + active_templates['started'].add(templ) for templ in base_notification_templates.filter(organization_notification_templates_for_any=org): active_templates['any'].add(templ) active_templates['error'] = list(active_templates['error']) active_templates['any'] = list(active_templates['any']) active_templates['success'] = list(active_templates['success']) + active_templates['started'] = list(active_templates['started']) return active_templates def get_passwords_needed_to_start(self): diff --git a/awx/main/models/base.py b/awx/main/models/base.py index ba44f9aa98..ec36ec8785 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -386,6 +386,12 @@ class NotificationFieldsModel(BaseModel): related_name='%(class)s_notification_templates_for_success' ) + notification_templates_started = models.ManyToManyField( + "NotificationTemplate", + blank=True, + related_name='%(class)s_notification_templates_for_started' + ) + notification_templates_any = models.ManyToManyField( "NotificationTemplate", blank=True, diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index e7244bac5b..9301c63c1d 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -1619,6 +1619,8 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions, CustomVirtualE base_notification_templates = NotificationTemplate.objects error_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) + started_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_started__in=[self])) success_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) any_notification_templates = list(base_notification_templates @@ -1626,11 +1628,14 @@ class InventorySource(UnifiedJobTemplate, InventorySourceOptions, CustomVirtualE if self.inventory.organization is not None: error_notification_templates = set(error_notification_templates + list(base_notification_templates .filter(organization_notification_templates_for_errors=self.inventory.organization))) + started_notification_templates = set(started_notification_templates + list(base_notification_templates + .filter(organization_notification_templates_for_started=self.inventory.organization))) success_notification_templates = set(success_notification_templates + list(base_notification_templates .filter(organization_notification_templates_for_success=self.inventory.organization))) any_notification_templates = set(any_notification_templates + list(base_notification_templates .filter(organization_notification_templates_for_any=self.inventory.organization))) return dict(error=list(error_notification_templates), + started=list(started_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index b8f2661c97..f20d074ead 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -435,6 +435,8 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour base_notification_templates = NotificationTemplate.objects error_notification_templates = list(base_notification_templates.filter( unifiedjobtemplate_notification_templates_for_errors__in=[self, self.project])) + started_notification_templates = list(base_notification_templates.filter( + unifiedjobtemplate_notification_templates_for_started__in=[self, self.project])) success_notification_templates = list(base_notification_templates.filter( unifiedjobtemplate_notification_templates_for_success__in=[self, self.project])) any_notification_templates = list(base_notification_templates.filter( @@ -443,11 +445,16 @@ class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, Resour if self.project is not None and self.project.organization is not None: error_notification_templates = set(error_notification_templates + list(base_notification_templates.filter( organization_notification_templates_for_errors=self.project.organization))) + started_notification_templates = set(started_notification_templates + list(base_notification_templates.filter( + organization_notification_templates_for_started=self.project.organization))) success_notification_templates = set(success_notification_templates + list(base_notification_templates.filter( organization_notification_templates_for_success=self.project.organization))) any_notification_templates = set(any_notification_templates + list(base_notification_templates.filter( organization_notification_templates_for_any=self.project.organization))) - return dict(error=list(error_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) + return dict(error=list(error_notification_templates), + started=list(started_notification_templates), + success=list(success_notification_templates), + any=list(any_notification_templates)) ''' RelatedJobsMixin @@ -1133,11 +1140,14 @@ class SystemJobTemplate(UnifiedJobTemplate, SystemJobOptions): base_notification_templates = NotificationTemplate.objects.all() error_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) + started_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_started__in=[self])) success_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) any_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_any__in=[self])) return dict(error=list(error_notification_templates), + started=list(started_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) diff --git a/awx/main/models/notifications.py b/awx/main/models/notifications.py index 9fa6e31b17..0b036d3783 100644 --- a/awx/main/models/notifications.py +++ b/awx/main/models/notifications.py @@ -129,7 +129,7 @@ class NotificationTemplate(CommonModelNameNotUnique): if field not in notification_configuration: if 'default' in params: notification_configuration[field] = params['default'] - backend_obj = self.notification_class(**notification_configuration) + backend_obj = self.notification_class(**notification_configuration) notification_obj = EmailMessage(subject, backend_obj.format_body(body), sender, recipients) with set_environ(**settings.AWX_TASK_ENV): return backend_obj.send_messages([notification_obj]) @@ -221,10 +221,13 @@ class JobNotificationMixin(object): def build_notification_failed_message(self): return self._build_notification_message('failed') + def build_notification_running_message(self): + return self._build_notification_message('running') + def send_notification_templates(self, status_str): from awx.main.tasks import send_notifications # avoid circular import - if status_str not in ['succeeded', 'failed']: - raise ValueError(_("status_str must be either succeeded or failed")) + if status_str not in ['succeeded', 'failed', 'running']: + raise ValueError(_("status_str must be either running, succeeded or failed")) try: notification_templates = self.get_notification_templates() except Exception: @@ -233,6 +236,8 @@ class JobNotificationMixin(object): if notification_templates: if status_str == 'succeeded': notification_template_type = 'success' + elif status_str == 'running': + notification_template_type = 'started' else: notification_template_type = 'error' all_notification_templates = set(notification_templates.get(notification_template_type, []) + notification_templates.get('any', [])) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 1759375b51..9da401a909 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -411,6 +411,8 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn base_notification_templates = NotificationTemplate.objects error_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_errors=self)) + started_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_started=self)) success_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_success=self)) any_notification_templates = list(base_notification_templates @@ -420,6 +422,9 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn error_notification_templates = set(error_notification_templates + list(base_notification_templates .filter(organization_notification_templates_for_errors=self.organization))) + started_notification_templates = set(started_notification_templates + + list(base_notification_templates + .filter(organization_notification_templates_for_started=self.organization))) success_notification_templates = set(success_notification_templates + list(base_notification_templates .filter(organization_notification_templates_for_success=self.organization))) @@ -427,6 +432,7 @@ class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEn list(base_notification_templates .filter(organization_notification_templates_for_any=self.organization))) return dict(error=list(error_notification_templates), + started=list(started_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) @@ -567,5 +573,3 @@ class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManage if not selected_groups: return self.global_instance_groups return selected_groups - - diff --git a/awx/main/models/workflow.py b/awx/main/models/workflow.py index 4e4f2a8dbb..3be0938058 100644 --- a/awx/main/models/workflow.py +++ b/awx/main/models/workflow.py @@ -419,11 +419,14 @@ class WorkflowJobTemplate(UnifiedJobTemplate, WorkflowJobOptions, SurveyJobTempl base_notification_templates = NotificationTemplate.objects.all() error_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_errors__in=[self])) + started_notification_templates = list(base_notification_templates + .filter(unifiedjobtemplate_notification_templates_for_started__in=[self])) success_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_success__in=[self])) any_notification_templates = list(base_notification_templates .filter(unifiedjobtemplate_notification_templates_for_any__in=[self])) return dict(error=list(error_notification_templates), + started=list(started_notification_templates), success=list(success_notification_templates), any=list(any_notification_templates)) diff --git a/awx/main/scheduler/task_manager.py b/awx/main/scheduler/task_manager.py index e0d595559f..46181b8b02 100644 --- a/awx/main/scheduler/task_manager.py +++ b/awx/main/scheduler/task_manager.py @@ -587,4 +587,4 @@ class TaskManager(): # Operations whose queries rely on modifications made during the atomic scheduling session for wfj in WorkflowJob.objects.filter(id__in=finished_wfjs): - wfj.send_notification_templates('succeeded' if wfj.status == 'successful' else 'failed') + wfj.send_notification_templates('started' if wfj.status == 'running' else ('succeeded' if wfj.status == 'successful' else 'failed')) diff --git a/awx/main/tasks.py b/awx/main/tasks.py index f899fadb05..7aba377381 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -314,7 +314,7 @@ def send_notifications(notification_list, job_id=None): update_fields = ['status', 'notifications_sent'] try: sent = notification.notification_template.send(notification.subject, notification.body) - notification.status = "successful" + notification.status = "successful" or "running" notification.notifications_sent = sent except Exception as e: logger.error("Send Notification Failed {}".format(e)) @@ -1115,6 +1115,8 @@ class BaseTask(object): self.instance = self.update_model(pk, status='running', start_args='') # blank field to remove encrypted passwords + self.instance.send_notification_templates("running") + self.instance.websocket_emit_status("running") status, rc = 'error', None extra_update_fields = {}