ef89804460b37b3f96a7dfff8b8884ebc9ed8472
[laas.git] / src / workflow / booking_workflow.py
1 ##############################################################################
2 # Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
3 # Copyright (c) 2020 Sawyer Bergeron, Sean Smith, 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.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, BookingMetaForm, OPNFVSelectForm
18 from resource_inventory.models import OPNFVConfig, ResourceTemplate
19 from django.db.models import Q
20
21
22 """
23 subclassing notes:
24     subclasses have to define the following class attributes:
25         self.repo_key: main output of step, where the selected/created single selector
26             result is placed at the end
27         self.confirm_key:
28 """
29
30
31 class Abstract_Resource_Select(AbstractSelectOrCreate):
32     form = ResourceSelectorForm
33     template = 'dashboard/genericselect.html'
34     title = "Select Resource"
35     description = "Select a resource template to use for your deployment"
36     short_title = "pod select"
37
38     def __init__(self, *args, **kwargs):
39         super().__init__(*args, **kwargs)
40         self.select_repo_key = self.repo.SELECTED_RESOURCE_TEMPLATE
41         self.confirm_key = self.workflow_type
42
43     def alert_bundle_missing(self):
44         self.set_invalid("Please select a valid resource template")
45
46     def get_form_queryset(self):
47         user = self.repo_get(self.repo.SESSION_USER)
48         return ResourceTemplate.objects.filter((Q(owner=user) | Q(public=True)))
49
50     def get_page_context(self):
51         return {
52             'select_type': 'resource',
53             'select_type_title': 'Resource template',
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 OPNFV_EnablePicker(object):
70     pass
71
72
73 class OPNFV_Select(AbstractSelectOrCreate, OPNFV_EnablePicker):
74     title = "Choose an OPNFV Config"
75     description = "Choose or create a description of how you want to deploy OPNFV"
76     short_title = "opnfv config"
77     form = OPNFVSelectForm
78     enabled = False
79
80     def __init__(self, *args, **kwargs):
81         super().__init__(*args, **kwargs)
82         self.select_repo_key = self.repo.SELECTED_OPNFV_CONFIG
83         self.confirm_key = "booking"
84
85     def alert_bundle_missing(self):
86         self.set_invalid("Please select a valid OPNFV config")
87
88     def get_form_queryset(self):
89         cb = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
90         qs = OPNFVConfig.objects.filter(bundle=cb)
91         return qs
92
93     def put_confirm_info(self, config):
94         confirm_dict = self.repo_get(self.repo.CONFIRMATION)
95         if self.confirm_key not in confirm_dict:
96             confirm_dict[self.confirm_key] = {}
97         confirm_dict[self.confirm_key]["OPNFV Configuration"] = config.name
98         self.repo_put(self.repo.CONFIRMATION, confirm_dict)
99
100     def get_page_context(self):
101         return {
102             'select_type': 'opnfv',
103             'select_type_title': 'OPNFV Config',
104             'addable_type_num': 4
105         }
106
107
108 class Booking_Meta(WorkflowStep):
109     template = 'booking/steps/booking_meta.html'
110     title = "Extra Info"
111     description = "Tell us how long you want your booking, what it is for, and who else should have access to it"
112     short_title = "booking info"
113
114     def get_context(self):
115         context = super(Booking_Meta, self).get_context()
116         initial = {}
117         default = []
118         try:
119             models = self.repo_get(self.repo.BOOKING_MODELS, {})
120             booking = models.get("booking")
121             if booking:
122                 initial['purpose'] = booking.purpose
123                 initial['project'] = booking.project
124                 initial['length'] = (booking.end - booking.start).days
125             info = self.repo_get(self.repo.BOOKING_INFO_FILE, False)
126             if info:
127                 initial['info_file'] = info
128             users = models.get("collaborators", [])
129             for user in users:
130                 default.append(user.userprofile)
131         except Exception:
132             pass
133
134         owner = self.repo_get(self.repo.SESSION_USER)
135
136         context['form'] = BookingMetaForm(initial=initial, user_initial=default, owner=owner)
137         return context
138
139     def post(self, post_data, user):
140         form = BookingMetaForm(data=post_data, owner=user)
141
142         forms = self.repo_get(self.repo.BOOKING_FORMS, {})
143
144         forms["meta_form"] = form
145         self.repo_put(self.repo.BOOKING_FORMS, forms)
146
147         if form.is_valid():
148             models = self.repo_get(self.repo.BOOKING_MODELS, {})
149             if "booking" not in models:
150                 models['booking'] = Booking()
151             models['collaborators'] = []
152             confirm = self.repo_get(self.repo.CONFIRMATION)
153             if "booking" not in confirm:
154                 confirm['booking'] = {}
155
156             models['booking'].start = timezone.now()
157             models['booking'].end = timezone.now() + timedelta(days=int(form.cleaned_data['length']))
158             models['booking'].purpose = form.cleaned_data['purpose']
159             models['booking'].project = form.cleaned_data['project']
160             for key in ['length', 'project', 'purpose']:
161                 confirm['booking'][key] = form.cleaned_data[key]
162
163             if form.cleaned_data["deploy_opnfv"]:
164                 self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=True)
165             else:
166                 self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=False)
167
168             userprofile_list = form.cleaned_data['users']
169             confirm['booking']['collaborators'] = []
170             for userprofile in userprofile_list:
171                 models['collaborators'].append(userprofile.user)
172                 confirm['booking']['collaborators'].append(userprofile.user.username)
173
174             info_file = form.cleaned_data.get("info_file", False)
175             if info_file:
176                 self.repo_put(self.repo.BOOKING_INFO_FILE, info_file)
177
178             self.repo_put(self.repo.BOOKING_MODELS, models)
179             self.repo_put(self.repo.CONFIRMATION, confirm)
180             self.set_valid("Step Completed")
181         else:
182             self.set_invalid("Please complete the fields highlighted in red to continue")