add nick
[laas.git] / src / notifier / manager.py
1 ##############################################################################
2 # Copyright (c) 2018 Parker Berberian, Sawyer Bergeron and others.
3 # Copyright (c) 2020 Sawyer Bergeron, Sean Smith, and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10 import os
11 from notifier.models import Notification, Emailed, Email
12
13 from django.template.loader import render_to_string
14 from django.utils import timezone
15
16
17 class NotificationHandler(object):
18
19     @classmethod
20     def notify_new_booking(cls, booking):
21         template = "notifier/new_booking.html"
22         titles = ["You have a new booking (" + str(booking.id) + ")", "You have been added to a booking (" + str(booking.id) + ")"]
23         cls.booking_notify(booking, template, titles)
24
25     @classmethod
26     def notify_booking_end(cls, booking):
27         template = "notifier/end_booking.html"
28         titles = ["Your booking (" + str(booking.id) + ") has ended", "A booking (" + str(booking.id) + ") that you collaborate on has ended"]
29         cls.booking_notify(booking, template, titles)
30
31     @classmethod
32     def notify_booking_expiring(cls, booking):
33         template = "notifier/expiring_booking.html"
34         titles = ["Your booking (" + str(booking.id) + ") is about to expire", "A booking (" + str(booking.id) + ") that you collaborate on is about to expire"]
35         cls.booking_notify(booking, template, titles)
36         cls.email_booking_expiring(booking)
37
38     @classmethod
39     def booking_notify(cls, booking, template, titles):
40         """
41         Create a notification for a booking owner and collaborators using the template.
42
43         titles is a list - the first is the title for the owner's notification,
44             the last is the title for the collaborators'
45         """
46         owner_notif = Notification.objects.create(
47             title=titles[0],
48             content=render_to_string(
49                 template,
50                 context={
51                     "booking": booking,
52                     "owner": True
53                 }
54             )
55         )
56         owner_notif.recipients.add(booking.owner.userprofile)
57         if not booking.collaborators.all().exists():
58             return  # no collaborators - were done
59
60         collab_notif = Notification.objects.create(
61             title=titles[-1],
62             content=render_to_string(
63                 template,
64                 context={
65                     "booking": booking,
66                     "owner": False
67                 }
68             )
69         )
70         for c in booking.collaborators.all():
71             collab_notif.recipients.add(c.userprofile)
72
73     @classmethod
74     def email_job_fulfilled(cls, job):
75         template_name = "notifier/email_fulfilled.txt"
76         all_tasks = job.get_tasklist()
77         users = list(job.booking.collaborators.all())
78         users.append(job.booking.owner)
79         for user in users:
80             user_tasklist = []
81             # gather up all the relevant messages from the lab
82             for task in all_tasks:
83                 if (not hasattr(task.config, "user")) or task.config.user == user:
84                     user_tasklist.append(
85                         {
86                             "title": task.type_str() + " Message: ",
87                             "content": task.message
88                         }
89                     )
90             # gather up all the other needed info
91             context = {
92                 "owner": user == job.booking.owner,
93                 "user_name": user.userprofile.full_name,
94                 "messages": user_tasklist,
95                 "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(job.booking.id) + "/"
96             }
97
98             # render email template
99             message = render_to_string(template_name, context)
100
101             # finally, queue email for sending
102             Email.objects.create(title="Your Booking is Ready", message=message, recipient=user.userprofile.email_addr)
103
104     @classmethod
105     def email_booking_over(cls, booking):
106         template_name = "notifier/email_ended.txt"
107         hostnames = [host.name for host in booking.resource.get_resources()]
108         users = list(booking.collaborators.all())
109         users.append(booking.owner)
110         for user in users:
111             context = {
112                 "user_name": user.userprofile.full_name,
113                 "booking": booking,
114                 "hosts": hostnames,
115                 "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/"
116             }
117
118             message = render_to_string(template_name, context)
119
120             Email.objects.create(title="Your Booking has Expired", message=message, recipient=user.userprofile.email_addr)
121
122     @classmethod
123     def email_booking_expiring(cls, booking):
124         template_name = "notifier/email_expiring.txt"
125         hostnames = [host.name for host in booking.resource.get_resources()]
126         users = list(booking.collaborators.all())
127         users.append(booking.owner)
128         for user in users:
129             context = {
130                 "user_name": user.userprofile.full_name,
131                 "booking": booking,
132                 "hosts": hostnames,
133                 "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/"
134             }
135
136             message = render_to_string(template_name, context)
137
138             Email.objects.create(title="Your Booking is Expiring", message=message, recipient=user.userprofile.email_addr)
139
140     @classmethod
141     def task_updated(cls, task):
142         """
143         Notification of task changing.
144
145         called every time a lab updated info about a task.
146         sends an email when 'task' changing state means a booking has
147         just been fulfilled (all tasks done, servers ready to use)
148         or is over.
149         """
150         if task.job is None or task.job.booking is None:
151             return
152         if task.job.is_fulfilled():
153             if task.job.booking.end < timezone.now():
154                 if Emailed.objects.filter(end_booking=task.job.booking).exists():
155                     return
156                 Emailed.objects.create(end_booking=task.job.booking)
157                 cls.email_booking_over(task.job.booking)
158             if task.job.booking.end > timezone.now() and task.job.booking.start < timezone.now():
159                 if Emailed.objects.filter(begin_booking=task.job.booking).exists():
160                     return
161                 Emailed.objects.create(begin_booking=task.job.booking)
162                 cls.email_job_fulfilled(task.job)