d8c8646863cb7c0074e64747271b77b1f8a5376c
[laas.git] / src / workflow / booking_workflow.py
1 ##############################################################################
2 # Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 from django.contrib import messages
11 from django.utils import timezone
12
13 from datetime import timedelta
14
15 from booking.models import Booking
16 from workflow.models import WorkflowStep, AbstractSelectOrCreate
17 from workflow.forms import ResourceSelectorForm, SWConfigSelectorForm, BookingMetaForm
18 from resource_inventory.models import GenericResourceBundle, ConfigBundle
19
20
21 """
22 subclassing notes:
23     subclasses have to define the following class attributes:
24         self.repo_key: main output of step, where the selected/created single selector
25             result is placed at the end
26         self.confirm_key:
27 """
28
29
30 class Abstract_Resource_Select(AbstractSelectOrCreate):
31     form = ResourceSelectorForm
32     template = 'dashboard/genericselect.html'
33     title = "Select Resource"
34     description = "Select a resource template to use for your deployment"
35     short_title = "pod select"
36
37     def __init__(self, *args, **kwargs):
38         super().__init__(*args, **kwargs)
39         self.select_repo_key = self.repo.SELECTED_GRESOURCE_BUNDLE
40         self.confirm_key = self.workflow_type
41
42     def alert_bundle_missing(self):
43         self.set_invalid("Please select a valid resource bundle")
44
45     def get_form_queryset(self):
46         user = self.repo_get(self.repo.SESSION_USER)
47         qs = GenericResourceBundle.objects.filter(owner=user)
48         return qs
49
50     def get_page_context(self):
51         return {
52             'select_type': 'resource',
53             'select_type_title': 'Resource Bundle',
54             'addable_type_num': 1
55         }
56
57     def put_confirm_info(self, bundle):
58         confirm_dict = self.repo_get(self.repo.CONFIRMATION)
59         if self.confirm_key not in confirm_dict:
60             confirm_dict[self.confirm_key] = {}
61         confirm_dict[self.confirm_key]["Resource Template"] = bundle.name
62         self.repo_put(self.repo.CONFIRMATION, confirm_dict)
63
64
65 class Booking_Resource_Select(Abstract_Resource_Select):
66     workflow_type = "booking"
67
68
69 class SWConfig_Select(AbstractSelectOrCreate):
70     title = "Select Software Configuration"
71     description = "Choose the software and related configurations you want to have used for your deployment"
72     short_title = "pod config"
73     form = SWConfigSelectorForm
74
75     def __init__(self, *args, **kwargs):
76         super().__init__(*args, **kwargs)
77         self.select_repo_key = self.repo.SELECTED_CONFIG_BUNDLE
78         self.confirm_key = "booking"
79
80     def alert_bundle_missing(self):
81         self.set_invalid("Please select a valid pod config")
82
83     def get_form_queryset(self):
84         user = self.repo_get(self.repo.SESSION_USER)
85         grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE)
86         qs = ConfigBundle.objects.filter(owner=user).filter(bundle=grb)
87         return qs
88
89     def put_confirm_info(self, bundle):
90         confirm_dict = self.repo_get(self.repo.CONFIRMATION)
91         if self.confirm_key not in confirm_dict:
92             confirm_dict[self.confirm_key] = {}
93         confirm_dict[self.confirm_key]["Software Configuration"] = bundle.name
94         self.repo_put(self.repo.CONFIRMATION, confirm_dict)
95
96     def get_page_context(self):
97         return {
98             'select_type': 'swconfig',
99             'select_type_title': 'Software Config',
100             'addable_type_num': 2
101         }
102
103
104 class Booking_Meta(WorkflowStep):
105     template = 'booking/steps/booking_meta.html'
106     title = "Extra Info"
107     description = "Tell us how long you want your booking, what it is for, and who else should have access to it"
108     short_title = "booking info"
109
110     def get_context(self):
111         context = super(Booking_Meta, self).get_context()
112         initial = {}
113         default = []
114         try:
115             models = self.repo_get(self.repo.BOOKING_MODELS, {})
116             booking = models.get("booking")
117             if booking:
118                 initial['purpose'] = booking.purpose
119                 initial['project'] = booking.project
120                 initial['length'] = (booking.end - booking.start).days
121             info = self.repo_get(self.repo.BOOKING_INFO_FILE, False)
122             if info:
123                 initial['info_file'] = info
124             users = models.get("collaborators", [])
125             for user in users:
126                 default.append(user.userprofile)
127         except Exception:
128             pass
129
130         owner = self.repo_get(self.repo.SESSION_USER)
131
132         context['form'] = BookingMetaForm(initial=initial, user_initial=default, owner=owner)
133         return context
134
135     def post_render(self, request):
136         form = BookingMetaForm(data=request.POST, owner=request.user)
137
138         forms = self.repo_get(self.repo.BOOKING_FORMS, {})
139
140         forms["meta_form"] = form
141         self.repo_put(self.repo.BOOKING_FORMS, forms)
142
143         if form.is_valid():
144             models = self.repo_get(self.repo.BOOKING_MODELS, {})
145             if "booking" not in models:
146                 models['booking'] = Booking()
147             models['collaborators'] = []
148             confirm = self.repo_get(self.repo.CONFIRMATION)
149             if "booking" not in confirm:
150                 confirm['booking'] = {}
151
152             models['booking'].start = timezone.now()
153             models['booking'].end = timezone.now() + timedelta(days=int(form.cleaned_data['length']))
154             models['booking'].purpose = form.cleaned_data['purpose']
155             models['booking'].project = form.cleaned_data['project']
156             for key in ['length', 'project', 'purpose']:
157                 confirm['booking'][key] = form.cleaned_data[key]
158
159             userprofile_list = form.cleaned_data['users']
160             confirm['booking']['collaborators'] = []
161             for userprofile in userprofile_list:
162                 models['collaborators'].append(userprofile.user)
163                 confirm['booking']['collaborators'].append(userprofile.user.username)
164
165             info_file = form.cleaned_data.get("info_file", False)
166             if info_file:
167                 self.repo_put(self.repo.BOOKING_INFO_FILE, info_file)
168
169             self.repo_put(self.repo.BOOKING_MODELS, models)
170             self.repo_put(self.repo.CONFIRMATION, confirm)
171             messages.add_message(request, messages.SUCCESS, 'Form Validated', fail_silently=True)
172             self.set_valid("Step Completed")
173         else:
174             messages.add_message(request, messages.ERROR, "Form didn't validate", fail_silently=True)
175             self.set_invalid("Please complete the fields highlighted in red to continue")
176         return self.render(request)