aboutsummaryrefslogtreecommitdiffstats
path: root/src/notifier
diff options
context:
space:
mode:
Diffstat (limited to 'src/notifier')
-rw-r--r--src/notifier/admin.py3
-rw-r--r--src/notifier/manager.py57
-rw-r--r--src/notifier/migrations/0006_emailed.py24
-rw-r--r--src/notifier/models.py27
-rw-r--r--src/notifier/tasks.py35
5 files changed, 139 insertions, 7 deletions
diff --git a/src/notifier/admin.py b/src/notifier/admin.py
index 4a2984c..f6dbfd1 100644
--- a/src/notifier/admin.py
+++ b/src/notifier/admin.py
@@ -9,6 +9,7 @@
from django.contrib import admin
-from notifier.models import Notification
+from notifier.models import Notification, Emailed
admin.site.register(Notification)
+admin.site.register(Emailed)
diff --git a/src/notifier/manager.py b/src/notifier/manager.py
index 9b89ef5..ee849a8 100644
--- a/src/notifier/manager.py
+++ b/src/notifier/manager.py
@@ -7,10 +7,11 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
import os
-from notifier.models import Notification
+from notifier.models import Notification, Emailed
from django.core.mail import send_mail
from django.template.loader import render_to_string
+from django.utils import timezone
class NotificationHandler(object):
@@ -28,6 +29,13 @@ class NotificationHandler(object):
cls.booking_notify(booking, template, titles)
@classmethod
+ def notify_booking_expiring(cls, booking):
+ template = "notifier/expiring_booking.html"
+ titles = ["Your booking (" + str(booking.id) + ") is about to expire", "A booking (" + str(booking.id) + ") that you collaborate on is about to expire"]
+ cls.booking_notify(booking, template, titles)
+ cls.email_booking_expiring(booking)
+
+ @classmethod
def booking_notify(cls, booking, template, titles):
"""
Creates a notification for a booking owner and collaborators
@@ -72,7 +80,7 @@ class NotificationHandler(object):
user_tasklist = []
# gather up all the relevant messages from the lab
for task in all_tasks:
- if (not hasattr(task, "user")) or task.user == user:
+ if (not hasattr(task.config, "user")) or task.config.user == user:
user_tasklist.append(
{
"title": task.type_str() + " Message: ",
@@ -81,6 +89,7 @@ class NotificationHandler(object):
)
# gather up all the other needed info
context = {
+ "owner": user == job.booking.owner,
"user_name": user.userprofile.full_name,
"messages": user_tasklist,
"booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(job.booking.id) + "/"
@@ -118,7 +127,31 @@ class NotificationHandler(object):
"Your Booking has Expired",
message,
os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@laas-dashboard"),
- user.userprofile.email_addr,
+ [user.userprofile.email_addr],
+ fail_silently=False
+ )
+
+ @classmethod
+ def email_booking_expiring(cls, booking):
+ template_name = "notifier/email_expiring.txt"
+ hostnames = [host.template.resource.name for host in booking.resource.hosts.all()]
+ users = list(booking.collaborators.all())
+ users.append(booking.owner)
+ for user in users:
+ context = {
+ "user_name": user.userprofile.full_name,
+ "booking": booking,
+ "hosts": hostnames,
+ "booking_url": os.environ.get("DASHBOARD_URL", "<Dashboard url>") + "/booking/detail/" + str(booking.id) + "/"
+ }
+
+ message = render_to_string(template_name, context)
+
+ send_mail(
+ "Your Booking is Expiring",
+ message,
+ os.environ.get("DEFAULT_FROM_EMAIL", "opnfv@laas-dashboard"),
+ [user.userprofile.email_addr],
fail_silently=False
)
@@ -126,8 +159,20 @@ class NotificationHandler(object):
def task_updated(cls, task):
"""
called every time a lab updated info about a task.
- currently only checks if the job is now done so I can send an email,
- may add more functionality later
+ sends an email when 'task' changing state means a booking has
+ just been fulfilled (all tasks done, servers ready to use)
+ or is over.
"""
+ if task.job is None or task.job.booking is None:
+ return
if task.job.is_fulfilled():
- cls.email_job_fulfilled(task.job)
+ if task.job.booking.end < timezone.now():
+ if Emailed.objects.filter(end_booking=task.job.booking).exists():
+ return
+ Emailed.objects.create(end_booking=task.job.booking)
+ cls.email_booking_over(task.job.booking)
+ if task.job.booking.end > timezone.now() and task.job.booking.start < timezone.now():
+ if Emailed.objects.filter(begin_booking=task.job.booking).exists():
+ return
+ Emailed.objects.create(begin_booking=task.job.booking)
+ cls.email_job_fulfilled(task.job)
diff --git a/src/notifier/migrations/0006_emailed.py b/src/notifier/migrations/0006_emailed.py
new file mode 100644
index 0000000..22ba9c5
--- /dev/null
+++ b/src/notifier/migrations/0006_emailed.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.2 on 2019-11-21 18:55
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('booking', '0006_booking_opnfv_config'),
+ ('notifier', '0005_auto_20190306_1616'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Emailed',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('almost_end_booking', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='warning_mail', to='booking.Booking')),
+ ('begin_booking', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='begin_mail', to='booking.Booking')),
+ ('end_booking', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='over_mail', to='booking.Booking')),
+ ],
+ ),
+ ]
diff --git a/src/notifier/models.py b/src/notifier/models.py
index 49189e8..382d3a9 100644
--- a/src/notifier/models.py
+++ b/src/notifier/models.py
@@ -9,6 +9,7 @@
from django.db import models
from account.models import UserProfile
+from booking.models import Booking
class Notification(models.Model):
@@ -23,3 +24,29 @@ class Notification(models.Model):
def to_preview_html(self):
return "<h3>" + self.title + "</h3>" # TODO - template?
+
+
+class Emailed(models.Model):
+ """
+ A simple record to remember who has already gotten an email
+ to avoid resending
+ """
+ begin_booking = models.OneToOneField(
+ Booking,
+ null=True,
+ on_delete=models.CASCADE,
+ related_name="begin_mail"
+ )
+ almost_end_booking = models.OneToOneField(
+ Booking,
+ null=True,
+ on_delete=models.CASCADE,
+ related_name="warning_mail"
+ )
+ end_booking = models.OneToOneField(
+ Booking,
+ null=True,
+ on_delete=models.CASCADE,
+ related_name="over_mail"
+ )
+
diff --git a/src/notifier/tasks.py b/src/notifier/tasks.py
new file mode 100644
index 0000000..b45ab8e
--- /dev/null
+++ b/src/notifier/tasks.py
@@ -0,0 +1,35 @@
+##############################################################################
+# Copyright (c) 2016 Max Breitenfeldt and others.
+# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+
+from celery import shared_task
+from django.utils import timezone
+from django.conf import settings
+from booking.models import Booking
+from notifier.models import Emailed
+from notifier.manager import NotificationHandler
+
+
+@shared_task
+def notify_expiring():
+ """
+ Notify users if their booking is within 48 hours of expiring.
+ """
+ expire_time = timezone.now() + timezone.timedelta(hours=settings.EXPIRE_HOURS)
+ # Don't email people about bookings that have started recently
+ start_time = timezone.now() - timezone.timedelta(hours=settings.EXPIRE_LIFETIME)
+ bookings = Booking.objects.filter(end__lte=expire_time,
+ end__gte=timezone.now(),
+ start__lte=start_time)
+ for booking in bookings:
+ if Emailed.objects.filter(almost_end_booking=booking).exists():
+ continue
+ NotificationHandler.notify_booking_expiring(booking)
+ Emailed.objects.create(almost_end_booking=booking)