Merge "Fixes a typo"
[pharos-tools.git] / dashboard / 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, OPNFVSelectForm
18 from resource_inventory.models import GenericResourceBundle, ConfigBundle, OPNFVConfig
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 OPNFV_EnablePicker(object):
105     pass
106
107
108 class OPNFV_Select(AbstractSelectOrCreate, OPNFV_EnablePicker):
109     title = "Choose an OPNFV Config"
110     description = "Choose or create a description of how you want to deploy OPNFV"
111     short_title = "opnfv config"
112     form = OPNFVSelectForm
113     enabled = False
114
115     def __init__(self, *args, **kwargs):
116         super().__init__(*args, **kwargs)
117         self.select_repo_key = self.repo.SELECTED_OPNFV_CONFIG
118         self.confirm_key = "booking"
119
120     def alert_bundle_missing(self):
121         self.set_invalid("Please select a valid OPNFV config")
122
123     def get_form_queryset(self):
124         cb = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
125         qs = OPNFVConfig.objects.filter(bundle=cb)
126         return qs
127
128     def put_confirm_info(self, config):
129         confirm_dict = self.repo_get(self.repo.CONFIRMATION)
130         if self.confirm_key not in confirm_dict:
131             confirm_dict[self.confirm_key] = {}
132         confirm_dict[self.confirm_key]["OPNFV Configuration"] = config.name
133         self.repo_put(self.repo.CONFIRMATION, confirm_dict)
134
135     def get_page_context(self):
136         return {
137             'select_type': 'opnfv',
138             'select_type_title': 'OPNFV Config',
139             'addable_type_num': 4
140         }
141
142
143 class Booking_Meta(WorkflowStep):
144     template = 'booking/steps/booking_meta.html'
145     title = "Extra Info"
146     description = "Tell us how long you want your booking, what it is for, and who else should have access to it"
147     short_title = "booking info"
148
149     def get_context(self):
150         context = super(Booking_Meta, self).get_context()
151         initial = {}
152         default = []
153         try:
154             models = self.repo_get(self.repo.BOOKING_MODELS, {})
155             booking = models.get("booking")
156             if booking:
157                 initial['purpose'] = booking.purpose
158                 initial['project'] = booking.project
159                 initial['length'] = (booking.end - booking.start).days
160             info = self.repo_get(self.repo.BOOKING_INFO_FILE, False)
161             if info:
162                 initial['info_file'] = info
163             users = models.get("collaborators", [])
164             for user in users:
165                 default.append(user.userprofile)
166         except Exception:
167             pass
168
169         owner = self.repo_get(self.repo.SESSION_USER)
170
171         context['form'] = BookingMetaForm(initial=initial, user_initial=default, owner=owner)
172         return context
173
174     def post_render(self, request):
175         form = BookingMetaForm(data=request.POST, owner=request.user)
176
177         forms = self.repo_get(self.repo.BOOKING_FORMS, {})
178
179         forms["meta_form"] = form
180         self.repo_put(self.repo.BOOKING_FORMS, forms)
181
182         if form.is_valid():
183             models = self.repo_get(self.repo.BOOKING_MODELS, {})
184             if "booking" not in models:
185                 models['booking'] = Booking()
186             models['collaborators'] = []
187             confirm = self.repo_get(self.repo.CONFIRMATION)
188             if "booking" not in confirm:
189                 confirm['booking'] = {}
190
191             models['booking'].start = timezone.now()
192             models['booking'].end = timezone.now() + timedelta(days=int(form.cleaned_data['length']))
193             models['booking'].purpose = form.cleaned_data['purpose']
194             models['booking'].project = form.cleaned_data['project']
195             for key in ['length', 'project', 'purpose']:
196                 confirm['booking'][key] = form.cleaned_data[key]
197
198             if form.cleaned_data["deploy_opnfv"]:
199                 self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=True)
200             else:
201                 self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=False)
202
203             userprofile_list = form.cleaned_data['users']
204             confirm['booking']['collaborators'] = []
205             for userprofile in userprofile_list:
206                 models['collaborators'].append(userprofile.user)
207                 confirm['booking']['collaborators'].append(userprofile.user.username)
208
209             info_file = form.cleaned_data.get("info_file", False)
210             if info_file:
211                 self.repo_put(self.repo.BOOKING_INFO_FILE, info_file)
212
213             self.repo_put(self.repo.BOOKING_MODELS, models)
214             self.repo_put(self.repo.CONFIRMATION, confirm)
215             messages.add_message(request, messages.SUCCESS, 'Form Validated', fail_silently=True)
216             self.set_valid("Step Completed")
217         else:
218             messages.add_message(request, messages.ERROR, "Form didn't validate", fail_silently=True)
219             self.set_invalid("Please complete the fields highlighted in red to continue")
220         return self.render(request)