8211a0c70525750a29690bc9b6c0e5fc33521f57
[pharos-tools.git] / dashboard / src / booking / views.py
1 ##############################################################################
2 # Copyright (c) 2016 Max Breitenfeldt and others.
3 # Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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
11 from django.contrib import messages
12 from django.shortcuts import get_object_or_404
13 from django.http import JsonResponse, HttpResponse
14 from django.utils import timezone
15 from django.views import View
16 from django.views.generic import TemplateView
17 from django.shortcuts import redirect, render
18 from django.db.models import Q
19
20 from resource_inventory.models import ResourceBundle, HostProfile, Image, Host
21 from resource_inventory.resource_manager import ResourceManager
22 from account.models import Lab
23 from booking.models import Booking
24 from booking.stats import StatisticsManager
25 from booking.forms import HostReImageForm
26 from api.models import JobFactory
27 from workflow.views import login
28 from booking.forms import QuickBookingForm
29 from booking.quick_deployer import create_from_form, drop_filter
30
31
32 def quick_create_clear_fields(request):
33     request.session['quick_create_forminfo'] = None
34
35
36 def quick_create(request):
37     if not request.user.is_authenticated:
38         return login(request)
39
40     if request.method == 'GET':
41         context = {}
42
43         r_manager = ResourceManager.getInstance()
44         profiles = {}
45         for lab in Lab.objects.all():
46             profiles[str(lab)] = r_manager.getAvailableHostTypes(lab)
47
48         context['lab_profile_map'] = profiles
49
50         context['form'] = QuickBookingForm(initial={}, chosen_users=[], default_user=request.user.username, user=request.user)
51
52         context.update(drop_filter(request.user))
53
54         return render(request, 'booking/quick_deploy.html', context)
55     if request.method == 'POST':
56         form = QuickBookingForm(request.POST, user=request.user)
57         context = {}
58         context['lab_profile_map'] = {}
59         context['form'] = form
60
61         if form.is_valid():
62             try:
63                 create_from_form(form, request)
64             except Exception as e:
65                 messages.error(request, "Whoops, an error occurred: " + str(e))
66                 return render(request, 'workflow/exit_redirect.html', context)
67
68             messages.success(request, "We've processed your request. "
69                                       "Check Account->My Bookings for the status of your new booking")
70             return render(request, 'workflow/exit_redirect.html', context)
71         else:
72             messages.error(request, "Looks like the form didn't validate. Check that you entered everything correctly")
73             return render(request, 'booking/quick_deploy.html', context)
74
75
76 class BookingView(TemplateView):
77     template_name = "booking/booking_detail.html"
78
79     def get_context_data(self, **kwargs):
80         booking = get_object_or_404(Booking, id=self.kwargs['booking_id'])
81         title = 'Booking Details'
82         context = super(BookingView, self).get_context_data(**kwargs)
83         context.update({'title': title, 'booking': booking})
84         return context
85
86
87 class BookingDeleteView(TemplateView):
88     template_name = "booking/booking_delete.html"
89
90     def get_context_data(self, **kwargs):
91         booking = get_object_or_404(Booking, id=self.kwargs['booking_id'])
92         title = 'Delete Booking'
93         context = super(BookingDeleteView, self).get_context_data(**kwargs)
94         context.update({'title': title, 'booking': booking})
95         return context
96
97
98 def bookingDelete(request, booking_id):
99     booking = get_object_or_404(Booking, id=booking_id)
100     booking.delete()
101     messages.add_message(request, messages.SUCCESS, 'Booking deleted')
102     return redirect('../../../../')
103
104
105 class BookingListView(TemplateView):
106     template_name = "booking/booking_list.html"
107
108     def get_context_data(self, **kwargs):
109         bookings = Booking.objects.filter(end__gte=timezone.now())
110         title = 'Search Booking'
111         context = super(BookingListView, self).get_context_data(**kwargs)
112         context.update({'title': title, 'bookings': bookings})
113         return context
114
115
116 class ResourceBookingsJSON(View):
117     def get(self, request, *args, **kwargs):
118         resource = get_object_or_404(ResourceBundle, id=self.kwargs['resource_id'])
119         bookings = resource.booking_set.get_queryset().values(
120             'id',
121             'start',
122             'end',
123             'purpose',
124             'jira_issue_status',
125             'config_bundle__name'
126         )
127         return JsonResponse({'bookings': list(bookings)})
128
129
130 def build_image_mapping(lab, user):
131     mapping = {}
132     for profile in HostProfile.objects.filter(labs=lab):
133         images = Image.objects.filter(
134             from_lab=lab,
135             host_type=profile
136         ).filter(
137             Q(public=True) | Q(owner=user)
138         )
139         mapping[profile.name] = [{"name": image.name, "value": image.id} for image in images]
140     return mapping
141
142
143 def booking_detail_view(request, booking_id):
144     user = None
145     if request.user.is_authenticated:
146         user = request.user
147     else:
148         return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
149
150     booking = get_object_or_404(Booking, id=booking_id)
151     allowed_users = set(list(booking.collaborators.all()))
152     allowed_users.add(booking.owner)
153     if user not in allowed_users:
154         return render(request, "dashboard/login.html", {'title': 'This page is private'})
155
156     context = {
157         'title': 'Booking Details',
158         'booking': booking,
159         'pdf': booking.pdf,
160         'user_id': user.id,
161         'image_mapping': build_image_mapping(booking.lab, user)
162     }
163
164     return render(
165         request,
166         "booking/booking_detail.html",
167         context
168     )
169
170
171 def booking_modify_image(request, booking_id):
172     form = HostReImageForm(request.POST)
173     if form.is_valid():
174         booking = Booking.objects.get(id=booking_id)
175         if request.user != booking.owner:
176             return HttpResponse("unauthorized")
177         if timezone.now() > booking.end:
178             return HttpResponse("unauthorized")
179         new_image = Image.objects.get(id=form.cleaned_data['image_id'])
180         host = Host.objects.get(id=form.cleaned_data['host_id'])
181         host.config.image = new_image
182         host.config.save()
183         JobFactory.reimageHost(new_image, booking, host)
184         return HttpResponse(new_image.name)
185     return HttpResponse("error")
186
187
188 def booking_stats_view(request):
189     return render(
190         request,
191         "booking/stats.html",
192         context={"data": StatisticsManager.getContinuousBookingTimeSeries(), "title": "Booking Statistics"}
193     )
194
195
196 def booking_stats_json(request):
197     try:
198         span = int(request.GET.get("days", 14))
199     except Exception:
200         span = 14
201     return JsonResponse(StatisticsManager.getContinuousBookingTimeSeries(span), safe=False)