From 1375c1e7f9e21de9ea0a1c756d27caa652a7c2f2 Mon Sep 17 00:00:00 2001 From: maxbr Date: Mon, 19 Sep 2016 10:13:26 +0200 Subject: Send notifications for booking start and end JIRA: PHAROS-265 Change-Id: I53a37ac31dda70935752afc6da3315e6dfcbc90f Signed-off-by: maxbr --- tools/pharos-dashboard/dashboard/tasks.py | 13 +++++++++++++ tools/pharos-dashboard/notification/__init__.py | 1 + tools/pharos-dashboard/notification/admin.py | 7 +++++++ tools/pharos-dashboard/notification/apps.py | 8 ++++++++ tools/pharos-dashboard/notification/models.py | 22 ++++++++++++++++++++++ tools/pharos-dashboard/notification/signals.py | 15 +++++++++++++++ tools/pharos-dashboard/notification/tasks.py | 23 +++++++++++++++++++++++ 7 files changed, 89 insertions(+) create mode 100644 tools/pharos-dashboard/dashboard/tasks.py create mode 100644 tools/pharos-dashboard/notification/__init__.py create mode 100644 tools/pharos-dashboard/notification/admin.py create mode 100644 tools/pharos-dashboard/notification/apps.py create mode 100644 tools/pharos-dashboard/notification/models.py create mode 100644 tools/pharos-dashboard/notification/signals.py create mode 100644 tools/pharos-dashboard/notification/tasks.py diff --git a/tools/pharos-dashboard/dashboard/tasks.py b/tools/pharos-dashboard/dashboard/tasks.py new file mode 100644 index 00000000..3df4bfba --- /dev/null +++ b/tools/pharos-dashboard/dashboard/tasks.py @@ -0,0 +1,13 @@ +from celery import shared_task +from datetime import timedelta +from django.utils import timezone + +from jenkins.models import JenkinsStatistic +from notification.models import BookingNotification + + +@shared_task +def database_cleanup(): + now = timezone.now() + JenkinsStatistic.objects.filter(timestamp__lt=now - timedelta(weeks=4)).delete() + BookingNotification.objects.filter(submit_time__lt=now - timedelta(weeks=4)).delete() \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/__init__.py b/tools/pharos-dashboard/notification/__init__.py new file mode 100644 index 00000000..926c6e80 --- /dev/null +++ b/tools/pharos-dashboard/notification/__init__.py @@ -0,0 +1 @@ +default_app_config = 'notification.apps.NotificationConfig' \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/admin.py b/tools/pharos-dashboard/notification/admin.py new file mode 100644 index 00000000..1fb5921f --- /dev/null +++ b/tools/pharos-dashboard/notification/admin.py @@ -0,0 +1,7 @@ +from django.conf import settings +from django.contrib import admin + +from notification.models import BookingNotification + +if settings.DEBUG: + admin.site.register(BookingNotification) \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/apps.py b/tools/pharos-dashboard/notification/apps.py new file mode 100644 index 00000000..6039c7bd --- /dev/null +++ b/tools/pharos-dashboard/notification/apps.py @@ -0,0 +1,8 @@ +from django.apps import AppConfig + + +class NotificationConfig(AppConfig): + name = 'notification' + + def ready(self): + import notification.signals #noqa \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/models.py b/tools/pharos-dashboard/notification/models.py new file mode 100644 index 00000000..80f65df4 --- /dev/null +++ b/tools/pharos-dashboard/notification/models.py @@ -0,0 +1,22 @@ +from django.db import models + +class BookingNotification(models.Model): + id = models.AutoField(primary_key=True) + type = models.CharField(max_length=100) + booking = models.ForeignKey('booking.Booking', on_delete=models.CASCADE) + submit_time = models.DateTimeField() + submitted = models.BooleanField(default=False) + + def get_content(self): + return { + 'start': self.booking.start.isoformat(), + 'end': self.booking.end.isoformat(), + 'user': self.booking.user.username, + 'purpose': self.booking.purpose + } + + def save(self, *args, **kwargs): + notifications = self.booking.bookingnotification_set.filter(type=self.type) + if notifications.count() > 1: + raise ValueError('Doubled Notification') + return super(BookingNotification, self).save(*args, **kwargs) \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/signals.py b/tools/pharos-dashboard/notification/signals.py new file mode 100644 index 00000000..c1f33ac0 --- /dev/null +++ b/tools/pharos-dashboard/notification/signals.py @@ -0,0 +1,15 @@ +from django.db.models.signals import post_save +from django.dispatch import receiver + +from booking.models import Booking +from notification.models import BookingNotification + + +@receiver(post_save, sender=Booking) +def booking_notification_handler(sender, instance, **kwargs): + BookingNotification.objects.update_or_create( + booking=instance, type='booking_start', defaults={'submit_time': instance.start} + ) + BookingNotification.objects.update_or_create( + booking=instance, type='booking_end', defaults={'submit_time': instance.end} + ) \ No newline at end of file diff --git a/tools/pharos-dashboard/notification/tasks.py b/tools/pharos-dashboard/notification/tasks.py new file mode 100644 index 00000000..ab3bddc7 --- /dev/null +++ b/tools/pharos-dashboard/notification/tasks.py @@ -0,0 +1,23 @@ +from celery import shared_task +from datetime import timedelta + +from django.conf import settings +from django.utils import timezone + +from notification.models import BookingNotification +from notification_framework.notification import Notification + + +@shared_task +def send_booking_notifications(): + messaging = Notification(dashboard_url=settings.RABBITMQ_URL) + + now = timezone.now() + notifications = BookingNotification.objects.filter(submitted=False, + submit_time__gt=now, + submit_time__lt=now + timedelta(minutes=5)) + for notification in notifications: + messaging.send(notification.type, notification.booking.resource.name, + notification.get_content()) + notification.submitted = True + notification.save() -- cgit 1.2.3-korg From 3c8baae57206988fbdfc2d858ddc3f134e552f07 Mon Sep 17 00:00:00 2001 From: maxbr Date: Mon, 19 Sep 2016 10:14:19 +0200 Subject: Add a REST API for the dashboard JIRA: PHAROS-265 Change-Id: Ic1b2d20415b0b84473d5915c4f26f3e65bbb1ecf Signed-off-by: maxbr --- tools/pharos-dashboard/api/__init__.py | 0 tools/pharos-dashboard/api/serializers.py | 22 +++++++++++++++++ tools/pharos-dashboard/api/urls.py | 28 ++++++++++++++++++++++ tools/pharos-dashboard/api/views.py | 23 ++++++++++++++++++ tools/pharos-dashboard/booking/models.py | 1 + tools/pharos-dashboard/dashboard/urls.py | 1 - tools/pharos-dashboard/pharos_dashboard/urls.py | 4 ++++ tools/pharos-dashboard/templates/base.html | 5 ++++ .../templates/rest_framework/api.html | 9 +++++++ 9 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tools/pharos-dashboard/api/__init__.py create mode 100644 tools/pharos-dashboard/api/serializers.py create mode 100644 tools/pharos-dashboard/api/urls.py create mode 100644 tools/pharos-dashboard/api/views.py create mode 100644 tools/pharos-dashboard/templates/rest_framework/api.html diff --git a/tools/pharos-dashboard/api/__init__.py b/tools/pharos-dashboard/api/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tools/pharos-dashboard/api/serializers.py b/tools/pharos-dashboard/api/serializers.py new file mode 100644 index 00000000..c3875cca --- /dev/null +++ b/tools/pharos-dashboard/api/serializers.py @@ -0,0 +1,22 @@ +from rest_framework import serializers + +from booking.models import Booking +from dashboard.models import Server, Resource + + +class BookingSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Booking + fields = ('id', 'resource', 'start', 'end', 'purpose') + + +class ServerSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Server + fields = ('id', 'resource', 'name', 'model', 'cpu', 'ram', 'storage') + + +class ResourceSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Resource + fields = ('id', 'name', 'description', 'url', 'server_set') diff --git a/tools/pharos-dashboard/api/urls.py b/tools/pharos-dashboard/api/urls.py new file mode 100644 index 00000000..22f12eb6 --- /dev/null +++ b/tools/pharos-dashboard/api/urls.py @@ -0,0 +1,28 @@ +"""pharos_dashboard URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/1.10/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.conf.urls import url, include + 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) +""" +from django.conf.urls import url, include +from rest_framework import routers + +from api.views import * + +router = routers.DefaultRouter() +router.register(r'resources', ResourceViewSet) +router.register(r'servers', ServerViewSet) +router.register(r'bookings', BookingViewSet) + +urlpatterns = [ + url(r'^', include(router.urls)), +] \ No newline at end of file diff --git a/tools/pharos-dashboard/api/views.py b/tools/pharos-dashboard/api/views.py new file mode 100644 index 00000000..78d7b8a9 --- /dev/null +++ b/tools/pharos-dashboard/api/views.py @@ -0,0 +1,23 @@ +from rest_framework import viewsets + +from api.serializers import ResourceSerializer, ServerSerializer, BookingSerializer +from booking.models import Booking +from dashboard.models import Resource, Server + + +class BookingViewSet(viewsets.ModelViewSet): + queryset = Booking.objects.all() + serializer_class = BookingSerializer + filter_fields = ('resource', 'user') + + +class ServerViewSet(viewsets.ModelViewSet): + queryset = Server.objects.all() + serializer_class = ServerSerializer + filter_fields = ('resource', 'name') + + +class ResourceViewSet(viewsets.ModelViewSet): + queryset = Resource.objects.all() + serializer_class = ResourceSerializer + filter_fields = ('name',) \ No newline at end of file diff --git a/tools/pharos-dashboard/booking/models.py b/tools/pharos-dashboard/booking/models.py index e772fb5b..fed35e3f 100644 --- a/tools/pharos-dashboard/booking/models.py +++ b/tools/pharos-dashboard/booking/models.py @@ -6,6 +6,7 @@ from jira import JIRAError from dashboard.models import Resource from django.conf import settings + class Booking(models.Model): id = models.AutoField(primary_key=True) user = models.ForeignKey(User, models.CASCADE) # delete if user is deleted diff --git a/tools/pharos-dashboard/dashboard/urls.py b/tools/pharos-dashboard/dashboard/urls.py index baa2d633..35c64636 100644 --- a/tools/pharos-dashboard/dashboard/urls.py +++ b/tools/pharos-dashboard/dashboard/urls.py @@ -14,7 +14,6 @@ Including another URLconf 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url - from dashboard.views import * urlpatterns = [ diff --git a/tools/pharos-dashboard/pharos_dashboard/urls.py b/tools/pharos-dashboard/pharos_dashboard/urls.py index d8bf5608..4a9d9149 100644 --- a/tools/pharos-dashboard/pharos_dashboard/urls.py +++ b/tools/pharos-dashboard/pharos_dashboard/urls.py @@ -18,12 +18,16 @@ from django.conf.urls import url, include from django.conf.urls.static import static from django.contrib import admin + urlpatterns = [ url(r'^', include('dashboard.urls', namespace='dashboard')), url(r'^booking/', include('booking.urls', namespace='booking')), url(r'^accounts/', include('account.urls', namespace='account')), url(r'^admin/', admin.site.urls), + url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), + + url(r'^api/', include('api.urls')) ] if settings.DEBUG is True: diff --git a/tools/pharos-dashboard/templates/base.html b/tools/pharos-dashboard/templates/base.html index 42156e3b..c5da483d 100644 --- a/tools/pharos-dashboard/templates/base.html +++ b/tools/pharos-dashboard/templates/base.html @@ -76,6 +76,11 @@ class="fa fa-fw">Users +
  • + API + +
  • diff --git a/tools/pharos-dashboard/templates/rest_framework/api.html b/tools/pharos-dashboard/templates/rest_framework/api.html new file mode 100644 index 00000000..9c6c4f7d --- /dev/null +++ b/tools/pharos-dashboard/templates/rest_framework/api.html @@ -0,0 +1,9 @@ +{% extends "rest_framework/base.html" %} + +{% block title %}Pharos Dashboard API{% endblock %} + +{% block branding %} + + Pharos Dashboard API + +{% endblock %} \ No newline at end of file -- cgit 1.2.3-korg