1 ##############################################################################
2 # Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
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 ##############################################################################
10 from django.contrib import messages
11 from django.shortcuts import render
12 from django.contrib.auth.models import User
13 from django.utils import timezone
16 from datetime import timedelta
18 from booking.models import Booking
19 from workflow.models import WorkflowStep
20 from workflow.forms import ResourceSelectorForm, SWConfigSelectorForm, BookingMetaForm
21 from resource_inventory.models import GenericResourceBundle, ResourceBundle, ConfigBundle
24 class Resource_Select(WorkflowStep):
25 template = 'booking/steps/resource_select.html'
26 title = "Select Resource"
27 description = "Select a resource template to use for your deployment"
28 short_title = "pod select"
30 def __init__(self, *args, **kwargs):
31 super(Resource_Select, self).__init__(*args, **kwargs)
32 self.repo_key = self.repo.SELECTED_GRESOURCE_BUNDLE
33 self.repo_check_key = False
34 self.confirm_key = "booking"
36 def get_context(self):
37 context = super(Resource_Select, self).get_context()
40 chosen_bundle = self.repo_get(self.repo_key, False)
42 default.append(chosen_bundle.id)
44 bundle = chosen_bundle
45 edit = self.repo_get(self.repo.EDIT, False)
46 user = self.repo_get(self.repo.SESSION_USER)
47 context['form'] = ResourceSelectorForm(
49 chosen_resource=default,
55 def post_render(self, request):
56 form = ResourceSelectorForm(request.POST)
57 context = self.get_context()
59 data = form.cleaned_data['generic_resource_bundle']
62 self.metastep.set_invalid("Please select a valid bundle")
63 return render(request, self.template, context)
64 selected_bundle = json.loads(data)
65 if len(selected_bundle) < 1:
66 self.metastep.set_invalid("Please select a valid bundle")
67 return render(request, self.template, context)
68 selected_id = selected_bundle[0]['id']
69 gresource_bundle = None
71 selected_id = int(selected_id)
72 gresource_bundle = GenericResourceBundle.objects.get(id=selected_id)
74 # we want the bundle in the repo
75 gresource_bundle = self.repo_get(
76 self.repo.GRESOURCE_BUNDLE_MODELS,
78 ).get("bundle", GenericResourceBundle())
83 confirm = self.repo_get(self.repo.CONFIRMATION)
84 if self.confirm_key not in confirm:
85 confirm[self.confirm_key] = {}
86 confirm[self.confirm_key]["resource name"] = gresource_bundle.name
87 self.repo_put(self.repo.CONFIRMATION, confirm)
88 messages.add_message(request, messages.SUCCESS, 'Form Validated Successfully', fail_silently=True)
89 self.metastep.set_valid("Step Completed")
90 return render(request, self.template, context)
92 messages.add_message(request, messages.ERROR, "Form Didn't Validate", fail_silently=True)
93 self.metastep.set_invalid("Please complete the fields highlighted in red to continue")
94 return render(request, self.template, context)
97 class Booking_Resource_Select(Resource_Select):
99 def __init__(self, *args, **kwargs):
100 super(Booking_Resource_Select, self).__init__(*args, **kwargs)
101 self.repo_key = self.repo.SELECTED_GRESOURCE_BUNDLE
102 self.confirm_key = "booking"
104 def get_context(self):
105 context = super(Booking_Resource_Select, self).get_context()
108 def post_render(self, request):
109 response = super(Booking_Resource_Select, self).post_render(request)
110 models = self.repo_get(self.repo.BOOKING_MODELS, {})
111 if "booking" not in models:
112 models['booking'] = Booking()
113 booking = models['booking']
114 resource = self.repo_get(self.repo_key, False)
117 booking.resource.template = resource
119 booking.resource = ResourceBundle(template=resource)
120 models['booking'] = booking
121 self.repo_put(self.repo.BOOKING_MODELS, models)
125 class SWConfig_Select(WorkflowStep):
126 template = 'booking/steps/swconfig_select.html'
127 title = "Select Software Configuration"
128 description = "Choose the software and related configurations you want to have used for your deployment"
129 short_title = "pod config"
131 def post_render(self, request):
132 form = SWConfigSelectorForm(request.POST)
135 bundle_json = form.cleaned_data['software_bundle']
136 bundle_json = bundle_json[2:-2] # Stupid django string bug
138 self.metastep.set_invalid("Please select a valid config")
139 return self.render(request)
140 bundle_json = json.loads(bundle_json)
141 if len(bundle_json) < 1:
142 self.metastep.set_invalid("Please select a valid config")
143 return self.render(request)
145 id = int(bundle_json[0]['id'])
146 bundle = ConfigBundle.objects.get(id=id)
148 grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE)
150 if grb and bundle.bundle != grb:
151 self.metastep.set_invalid("Incompatible config selected for resource bundle")
152 return self.render(request)
154 self.repo_set(self.repo.SELECTED_GRESOURCE_BUNDLE, bundle.bundle)
156 models = self.repo_get(self.repo.BOOKING_MODELS, {})
157 if "booking" not in models:
158 models['booking'] = Booking()
159 models['booking'].config_bundle = bundle
160 self.repo_put(self.repo.BOOKING_MODELS, models)
161 confirm = self.repo_get(self.repo.CONFIRMATION)
162 if "booking" not in confirm:
163 confirm['booking'] = {}
164 confirm['booking']["configuration name"] = bundle.name
165 self.repo_put(self.repo.CONFIRMATION, confirm)
166 self.metastep.set_valid("Step Completed")
167 messages.add_message(request, messages.SUCCESS, 'Form Validated Successfully', fail_silently=True)
169 self.metastep.set_invalid("Please select or create a valid config")
170 messages.add_message(request, messages.ERROR, "Form Didn't Validate", fail_silently=True)
172 return self.render(request)
174 def get_context(self):
175 context = super(SWConfig_Select, self).get_context()
179 created_bundle = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
180 booking = self.repo_get(self.repo.BOOKING_MODELS, {}).get("booking", False)
182 chosen_bundle = booking.config_bundle
183 default.append(chosen_bundle.id)
184 bundle = chosen_bundle
187 default.append(created_bundle.id)
188 bundle = created_bundle
189 edit = self.repo_get(self.repo.EDIT, False)
190 grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE)
191 context['form'] = SWConfigSelectorForm(chosen_software=default, bundle=bundle, edit=edit, resource=grb)
195 class Booking_Meta(WorkflowStep):
196 template = 'booking/steps/booking_meta.html'
198 description = "Tell us how long you want your booking, what it is for, and who else should have access to it"
199 short_title = "booking info"
201 def get_context(self):
202 context = super(Booking_Meta, self).get_context()
206 models = self.repo_get(self.repo.BOOKING_MODELS, {})
207 booking = models.get("booking")
209 initial['purpose'] = booking.purpose
210 initial['project'] = booking.project
211 initial['length'] = (booking.end - booking.start).days
212 info = self.repo_get(self.repo.BOOKING_INFO_FILE, False)
214 initial['info_file'] = info
215 users = models.get("collaborators", [])
217 default.append(user.id)
221 default_user = self.repo_get(self.repo.SESSION_USER)
222 if default_user is None:
226 default_user = default_user.username
228 context['form'] = BookingMetaForm(initial=initial, chosen_users=default, default_user=default_user)
231 def post_render(self, request):
232 form = BookingMetaForm(data=request.POST)
233 context = self.get_context()
235 forms = self.repo_get(self.repo.BOOKING_FORMS, {})
237 forms["meta_form"] = form
238 self.repo_put(self.repo.BOOKING_FORMS, forms)
241 models = self.repo_get(self.repo.BOOKING_MODELS, {})
242 if "booking" not in models:
243 models['booking'] = Booking()
244 models['collaborators'] = []
245 confirm = self.repo_get(self.repo.CONFIRMATION)
246 if "booking" not in confirm:
247 confirm['booking'] = {}
249 models['booking'].start = timezone.now()
250 models['booking'].end = timezone.now() + timedelta(days=int(form.cleaned_data['length']))
251 models['booking'].purpose = form.cleaned_data['purpose']
252 models['booking'].project = form.cleaned_data['project']
253 for key in ['length', 'project', 'purpose']:
254 confirm['booking'][key] = form.cleaned_data[key]
256 user_data = form.cleaned_data['users']
257 confirm['booking']['collaborators'] = []
258 user_data = user_data[2:-2] # fixes malformed string from querydict
260 form_users = json.loads(user_data)
261 for user_json in form_users:
262 user = User.objects.get(pk=user_json['id'])
263 models['collaborators'].append(user)
264 confirm['booking']['collaborators'].append(user.username)
266 info_file = form.cleaned_data.get("info_file", False)
268 self.repo_put(self.repo.BOOKING_INFO_FILE, info_file)
270 self.repo_put(self.repo.BOOKING_MODELS, models)
271 self.repo_put(self.repo.CONFIRMATION, confirm)
272 messages.add_message(request, messages.SUCCESS, 'Form Validated', fail_silently=True)
273 self.metastep.set_valid("Step Completed")
275 messages.add_message(request, messages.ERROR, "Form didn't validate", fail_silently=True)
276 self.metastep.set_invalid("Please complete the fields highlighted in red to continue")
277 context['form'] = form # TODO: store this form
278 return render(request, self.template, context)