Notification serializers, views, and tasks

* Implement concrete Notification model for notification runs
* Implement NotificationTemplate and Notification serializers and views
* Implement ancillary views
* Implement NotificationTemplate trigger m2m fields on all job templates
  via a fields mixin
* Link NotificationTemplates with an org
* Link notifications with the activity stream
* Implement Notification celery tasks
* Extend Backend field parameters to identify sender and receiver as
  parameters needed by the message and not the backend itself
* Updates to backends to better fit the django email backend model as it
  relates to Messages
* Implement success job chain task + notifications
* Implement notifications in error job chain task
This commit is contained in:
Matthew Jones
2016-02-09 23:12:55 -05:00
parent 319deffc18
commit 8db2f60405
18 changed files with 502 additions and 20 deletions

View File

@@ -5,7 +5,9 @@ import logging
from django.db import models
from django.core.urlresolvers import reverse
from django.core.mail.message import EmailMessage
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_str
from awx.main.models.base import * # noqa
from awx.main.notifications.email_backend import CustomEmailBackend
@@ -17,7 +19,7 @@ from jsonfield import JSONField
logger = logging.getLogger('awx.main.models.notifications')
__all__ = ['NotificationTemplate']
__all__ = ['NotificationTemplate', 'Notification']
class NotificationTemplate(CommonModel):
@@ -30,6 +32,14 @@ class NotificationTemplate(CommonModel):
class Meta:
app_label = 'main'
organization = models.ForeignKey(
'Organization',
blank=False,
null=True,
on_delete=models.SET_NULL,
related_name='notification_templates',
)
notification_type = models.CharField(
max_length = 32,
choices=NOTIFICATION_TYPE_CHOICES,
@@ -42,4 +52,83 @@ class NotificationTemplate(CommonModel):
@property
def notification_class(self):
return CLASS_FOR_NOTIFICATION_TYPE[self.notification_type]
return self.CLASS_FOR_NOTIFICATION_TYPE[self.notification_type]
@property
def recipients(self):
return self.notification_configuration[self.notification_class.recipient_parameter]
def generate_notification(self, subject, message):
notification = Notification(notifier=self,
notification_type=self.notification_type,
recipients=smart_str(self.recipients),
subject=subject,
body=message)
notification.save()
return notification
def send(self, subject, body):
recipients = self.notification_configuration.pop(self.notification_class.recipient_parameter)
sender = self.notification_configuration.pop(self.notification_class.sender_parameter, None)
backend_obj = self.notification_class(**self.notification_configuration)
notification_obj = EmailMessage(subject, body, sender, recipients)
return backend_obj.send_messages([notification_obj])
class Notification(CreatedModifiedModel):
'''
A notification event emitted when a Notifier is run
'''
NOTIFICATION_STATE_CHOICES = [
('pending', _('Pending')),
('successful', _('Successful')),
('failed', _('Failed')),
]
class Meta:
app_label = 'main'
ordering = ('pk',)
notifier = models.ForeignKey(
'NotificationTemplate',
related_name='notifications',
on_delete=models.CASCADE,
editable=False
)
status = models.CharField(
max_length=20,
choices=NOTIFICATION_STATE_CHOICES,
default='pending',
editable=False,
)
error = models.TextField(
blank=True,
default='',
editable=False,
)
notifications_sent = models.IntegerField(
default=0,
editable=False,
)
notification_type = models.CharField(
max_length = 32,
choices=NotificationTemplate.NOTIFICATION_TYPE_CHOICES,
)
recipients = models.TextField(
blank=True,
default='',
editable=False,
)
subject = models.TextField(
blank=True,
default='',
editable=False,
)
body = models.TextField(
blank=True,
default='',
editable=False,
)
def get_absolute_url(self):
return reverse('api:notification_detail', args=(self.pk,))