diff options
Diffstat (limited to 'dashboard/src/booking/views.py')
-rw-r--r-- | dashboard/src/booking/views.py | 283 |
1 files changed, 138 insertions, 145 deletions
diff --git a/dashboard/src/booking/views.py b/dashboard/src/booking/views.py index 7e35af2..bad7dc9 100644 --- a/dashboard/src/booking/views.py +++ b/dashboard/src/booking/views.py @@ -1,5 +1,6 @@ ############################################################################## # 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 @@ -7,164 +8,74 @@ # http://www.apache.org/licenses/LICENSE-2.0 ############################################################################## -from django.conf import settings from django.contrib import messages -from django.contrib.auth.mixins import LoginRequiredMixin -from django.http import JsonResponse from django.shortcuts import get_object_or_404 -from django.urls import reverse +from django.http import JsonResponse, HttpResponse from django.utils import timezone from django.views import View -from django.views.generic import FormView from django.views.generic import TemplateView -from jira import JIRAError -from django.shortcuts import redirect +from django.shortcuts import redirect, render +from django.db.models import Q +from django.urls import reverse -from account.jira_util import get_jira -from booking.forms import BookingForm, BookingEditForm +from resource_inventory.models import ResourceBundle, HostProfile, Image, Host +from resource_inventory.resource_manager import ResourceManager +from account.models import Lab from booking.models import Booking -from dashboard.models import Resource - -def create_jira_ticket(user, booking): - jira = get_jira(user) - issue_dict = { - 'project': 'PHAROS', - 'summary': str(booking.resource) + ': Access Request', - 'description': booking.purpose, - 'issuetype': {'name': 'Task'}, - 'components': [{'name': 'POD Access Request'}], - 'assignee': {'name': booking.resource.owner.username} - } - issue = jira.create_issue(fields=issue_dict) - jira.add_attachment(issue, user.userprofile.pgp_public_key) - jira.add_attachment(issue, user.userprofile.ssh_public_key) - booking.jira_issue_id = issue.id - booking.save() +from booking.stats import StatisticsManager +from booking.forms import HostReImageForm +from api.models import JobFactory +from workflow.views import login +from booking.forms import QuickBookingForm +from booking.quick_deployer import create_from_form, drop_filter -class BookingFormView(FormView): - template_name = "booking/booking_calendar.html" - form_class = BookingForm +def quick_create_clear_fields(request): + request.session['quick_create_forminfo'] = None - def dispatch(self, request, *args, **kwargs): - self.resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - return super(BookingFormView, self).dispatch(request, *args, **kwargs) - def get_context_data(self, **kwargs): - title = 'Booking: ' + self.resource.name - context = super(BookingFormView, self).get_context_data(**kwargs) - context.update({'title': title, 'resource': self.resource}) - #raise PermissionDenied('check') - return context +def quick_create(request): + if not request.user.is_authenticated: + return login(request) - def get_success_url(self): - return reverse('booking:create', kwargs=self.kwargs) - - def form_valid(self, form): - if not self.request.user.is_authenticated: - messages.add_message(self.request, messages.ERROR, - 'You need to be logged in to book a Pod.') - return super(BookingFormView, self).form_invalid(form) - - user = self.request.user - booking = Booking(start=form.cleaned_data['start'], - end=form.cleaned_data['end'], - purpose=form.cleaned_data['purpose'], - opsys=form.cleaned_data['opsys'], - installer=form.cleaned_data['installer'], - scenario=form.cleaned_data['scenario'], - resource=self.resource, user=user) - try: - booking.save() - except ValueError as err: - messages.add_message(self.request, messages.ERROR, err) - return super(BookingFormView, self).form_invalid(form) - try: - if settings.CREATE_JIRA_TICKET: - create_jira_ticket(user, booking) - except JIRAError: - messages.add_message(self.request, messages.ERROR, 'Failed to create Jira Ticket. ' - 'Please check your Jira ' - 'permissions.') - booking.delete() - return super(BookingFormView, self).form_invalid(form) - messages.add_message(self.request, messages.SUCCESS, 'Booking saved') - return super(BookingFormView, self).form_valid(form) - - -class BookingEditFormView(FormView): - template_name = "booking/booking_calendar.html" - form_class = BookingEditForm - - def is_valid(self): - return True - - def dispatch(self, request, *args, **kwargs): - self.resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - self.original_booking = get_object_or_404(Booking, id=self.kwargs['booking_id']) - return super(BookingEditFormView, self).dispatch(request, *args, **kwargs) + if request.method == 'GET': + context = {} - def get_context_data(self, **kwargs): - title = 'Editing Booking on: ' + self.resource.name - context = super(BookingEditFormView, self).get_context_data(**kwargs) - context.update({'title': title, 'resource': self.resource}) - return context + r_manager = ResourceManager.getInstance() + profiles = {} + for lab in Lab.objects.all(): + profiles[str(lab)] = r_manager.getAvailableHostTypes(lab) + + context['lab_profile_map'] = profiles + + context['form'] = QuickBookingForm(default_user=request.user.username, user=request.user) + + context.update(drop_filter(request.user)) + + return render(request, 'booking/quick_deploy.html', context) + if request.method == 'POST': + form = QuickBookingForm(request.POST, user=request.user) + context = {} + context['lab_profile_map'] = {} + context['form'] = form + + if form.is_valid(): + try: + booking = create_from_form(form, request) + messages.success(request, "We've processed your request. " + "Check Account->My Bookings for the status of your new booking") + return redirect(reverse('booking:booking_detail', kwargs={'booking_id': booking.id})) + except Exception as e: + messages.error(request, "Whoops, an error occurred: " + str(e)) + return render(request, 'booking/quick_deploy.html', context) + else: + messages.error(request, "Looks like the form didn't validate. Check that you entered everything correctly") + return render(request, 'booking/quick_deploy.html', context) - def get_form_kwargs(self): - kwargs = super(BookingEditFormView, self).get_form_kwargs() - kwargs['purpose'] = self.original_booking.purpose - kwargs['start'] = self.original_booking.start - kwargs['end'] = self.original_booking.end - try: - kwargs['installer'] = self.original_booking.installer - except AttributeError: - pass - try: - kwargs['scenario'] = self.original_booking.scenario - except AttributeError: - pass - return kwargs - - def get_success_url(self): - return reverse('booking:create', args=(self.resource.id,)) - - def form_valid(self, form): - - if not self.request.user.is_authenticated: - messages.add_message(self.request, messages.ERROR, - 'You need to be logged in to book a Pod.') - return super(BookingEditFormView, self).form_invalid(form) - - if not self.request.user == self.original_booking.user: - messages.add_message(self.request, messages.ERROR, - 'You are not the owner of this booking.') - return super(BookingEditFormView, self).form_invalid(form) - - #Do Conflict Checks - if self.original_booking.start != form.cleaned_data['start']: - if timezone.now() > form.cleaned_data['start']: - messages.add_message(self.request, messages.ERROR, - 'Cannot change start date after it has occurred.') - return super(BookingEditFormView, self).form_invalid(form) - self.original_booking.start = form.cleaned_data['start'] - self.original_booking.end = form.cleaned_data['end'] - self.original_booking.purpose = form.cleaned_data['purpose'] - self.original_booking.installer = form.cleaned_data['installer'] - self.original_booking.scenario = form.cleaned_data['scenario'] - self.original_booking.reset = form.cleaned_data['reset'] - try: - self.original_booking.save() - except ValueError as err: - messages.add_message(self.request, messages.ERROR, err) - return super(BookingEditFormView, self).form_invalid(form) - - user = self.request.user - return super(BookingEditFormView, self).form_valid(form) class BookingView(TemplateView): template_name = "booking/booking_detail.html" - def get_context_data(self, **kwargs): booking = get_object_or_404(Booking, id=self.kwargs['booking_id']) title = 'Booking Details' @@ -172,6 +83,7 @@ class BookingView(TemplateView): context.update({'title': title, 'booking': booking}) return context + class BookingDeleteView(TemplateView): template_name = "booking/booking_delete.html" @@ -182,12 +94,14 @@ class BookingDeleteView(TemplateView): context.update({'title': title, 'booking': booking}) return context + def bookingDelete(request, booking_id): booking = get_object_or_404(Booking, id=booking_id) booking.delete() messages.add_message(request, messages.SUCCESS, 'Booking deleted') return redirect('../../../../') + class BookingListView(TemplateView): template_name = "booking/booking_list.html" @@ -201,8 +115,87 @@ class BookingListView(TemplateView): class ResourceBookingsJSON(View): def get(self, request, *args, **kwargs): - resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) - bookings = resource.booking_set.get_queryset().values('id', 'start', 'end', 'purpose', - 'jira_issue_status', 'opsys__name', - 'installer__name', 'scenario__name') - return JsonResponse({'bookings': list(bookings)})
\ No newline at end of file + resource = get_object_or_404(ResourceBundle, id=self.kwargs['resource_id']) + bookings = resource.booking_set.get_queryset().values( + 'id', + 'start', + 'end', + 'purpose', + 'jira_issue_status', + 'config_bundle__name' + ) + return JsonResponse({'bookings': list(bookings)}) + + +def build_image_mapping(lab, user): + mapping = {} + for profile in HostProfile.objects.filter(labs=lab): + images = Image.objects.filter( + from_lab=lab, + host_type=profile + ).filter( + Q(public=True) | Q(owner=user) + ) + mapping[profile.name] = [{"name": image.name, "value": image.id} for image in images] + return mapping + + +def booking_detail_view(request, booking_id): + user = None + if request.user.is_authenticated: + user = request.user + else: + return render(request, "dashboard/login.html", {'title': 'Authentication Required'}) + + booking = get_object_or_404(Booking, id=booking_id) + allowed_users = set(list(booking.collaborators.all())) + allowed_users.add(booking.owner) + if user not in allowed_users: + return render(request, "dashboard/login.html", {'title': 'This page is private'}) + + context = { + 'title': 'Booking Details', + 'booking': booking, + 'pdf': booking.pdf, + 'user_id': user.id, + 'image_mapping': build_image_mapping(booking.lab, user) + } + + return render( + request, + "booking/booking_detail.html", + context + ) + + +def booking_modify_image(request, booking_id): + form = HostReImageForm(request.POST) + if form.is_valid(): + booking = Booking.objects.get(id=booking_id) + if request.user != booking.owner: + return HttpResponse("unauthorized") + if timezone.now() > booking.end: + return HttpResponse("unauthorized") + new_image = Image.objects.get(id=form.cleaned_data['image_id']) + host = Host.objects.get(id=form.cleaned_data['host_id']) + host.config.image = new_image + host.config.save() + JobFactory.reimageHost(new_image, booking, host) + return HttpResponse(new_image.name) + return HttpResponse("error") + + +def booking_stats_view(request): + return render( + request, + "booking/stats.html", + context={"data": StatisticsManager.getContinuousBookingTimeSeries(), "title": "Booking Statistics"} + ) + + +def booking_stats_json(request): + try: + span = int(request.GET.get("days", 14)) + except Exception: + span = 14 + return JsonResponse(StatisticsManager.getContinuousBookingTimeSeries(span), safe=False) |