add nick
[laas.git] / src / workflow / opnfv_workflow.py
1 ##############################################################################
2 # Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, 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
11 from django.forms import formset_factory
12
13 from workflow.models import WorkflowStep, AbstractSelectOrCreate
14 from resource_inventory.models import ResourceTemplate, OPNFV_SETTINGS
15 from workflow.forms import OPNFVSelectionForm, OPNFVNetworkRoleForm, OPNFVHostRoleForm, SWConfigSelectorForm, BasicMetaForm
16
17
18 class OPNFV_Resource_Select(AbstractSelectOrCreate):
19     title = "Select Software Configuration"
20     description = "Choose the software bundle you wish to use as a base for your OPNFV configuration"
21     short_title = "software config"
22     form = SWConfigSelectorForm
23
24     def __init__(self, *args, **kwargs):
25         super().__init__(*args, **kwargs)
26         self.select_repo_key = self.repo.SELECTED_CONFIG_BUNDLE
27
28     def get_form_queryset(self):
29         user = self.repo_get(self.repo.SESSION_USER)
30         qs = ResourceTemplate.objects.filter(owner=user)
31         return qs
32
33     def put_confirm_info(self, bundle):
34         confirm_dict = self.repo_get(self.repo.CONFIRMATION)
35         confirm_dict['software bundle'] = bundle.name
36         confirm_dict['hardware POD'] = bundle.bundle.name
37         self.repo_put(self.repo.CONFIRMATION, confirm_dict)
38
39     def get_page_context(self):
40         return {
41             'select_type': 'swconfig',
42             'select_type_title': 'Software Config',
43             'addable_type_num': 2
44         }
45
46
47 class Pick_Installer(WorkflowStep):
48     template = 'config_bundle/steps/pick_installer.html'
49     title = 'Pick OPNFV Installer'
50     description = 'Choose which OPNFV installer to use'
51     short_title = "opnfv installer"
52     modified_key = "installer_step"
53
54     def update_confirmation(self):
55         confirm = self.repo_get(self.repo.CONFIRMATION, {})
56         models = self.repo_get(self.repo.OPNFV_MODELS, {})
57         installer = models.get("installer_chosen")
58         scenario = models.get("scenario_chosen")
59         if not (installer and scenario):
60             return
61         confirm['installer'] = installer.name
62         confirm['scenario'] = scenario.name
63         self.repo_put(self.repo.CONFIRMATION, confirm)
64
65     def get_context(self):
66         context = super(Pick_Installer, self).get_context()
67
68         models = self.repo_get(self.repo.OPNFV_MODELS, {})
69         initial = {
70             "installer": models.get("installer_chosen"),
71             "scenario": models.get("scenario_chosen")
72         }
73
74         context["form"] = OPNFVSelectionForm(initial=initial)
75         return context
76
77     def post(self, post_data, user):
78         form = OPNFVSelectionForm(post_data)
79         if form.is_valid():
80             installer = form.cleaned_data['installer']
81             scenario = form.cleaned_data['scenario']
82             models = self.repo_get(self.repo.OPNFV_MODELS, {})
83             models['installer_chosen'] = installer
84             models['scenario_chosen'] = scenario
85             self.repo_put(self.repo.OPNFV_MODELS, models)
86             self.update_confirmation()
87             self.set_valid("Step Completed")
88         else:
89             self.set_invalid("Please select an Installer and Scenario")
90
91
92 class Assign_Network_Roles(WorkflowStep):
93     template = 'config_bundle/steps/assign_network_roles.html'
94     title = 'Pick Network Roles'
95     description = 'Choose what role each network should get'
96     short_title = "network roles"
97     modified_key = "net_roles_step"
98
99     """
100     to do initial filling, repo should have a "network_roles" array with the following structure for each element:
101     {
102         "role": <NetworkRole object ref>,
103         "network": <Network object ref>
104     }
105     """
106     def create_netformset(self, roles, config_bundle, data=None):
107         roles_initial = []
108         set_roles = self.repo_get(self.repo.OPNFV_MODELS, {}).get("network_roles")
109         if set_roles:
110             roles_initial = set_roles
111         else:
112             for role in OPNFV_SETTINGS.NETWORK_ROLES:
113                 roles_initial.append({"role": role})
114
115         Formset = formset_factory(OPNFVNetworkRoleForm, extra=0)
116         kwargs = {
117             "initial": roles_initial,
118             "form_kwargs": {"config_bundle": config_bundle}
119         }
120         formset = None
121         if data:
122             formset = Formset(data, **kwargs)
123         else:
124             formset = Formset(**kwargs)
125         return formset
126
127     def get_context(self):
128         context = super(Assign_Network_Roles, self).get_context()
129         config_bundle = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
130         if config_bundle is None:
131             context["unavailable"] = True
132             return context
133
134         roles = OPNFV_SETTINGS.NETWORK_ROLES
135         formset = self.create_netformset(roles, config_bundle)
136         context['formset'] = formset
137
138         return context
139
140     def update_confirmation(self):
141         confirm = self.repo_get(self.repo.CONFIRMATION, {})
142         models = self.repo_get(self.repo.OPNFV_MODELS, {})
143         roles = models.get("network_roles")
144         if not roles:
145             return
146         confirm['network roles'] = {}
147         for role in roles:
148             confirm['network roles'][role['role']] = role['network'].name
149         self.repo_put(self.repo.CONFIRMATION, confirm)
150
151     def post(self, post_data, user):
152         models = self.repo_get(self.repo.OPNFV_MODELS, {})
153         config_bundle = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
154         roles = OPNFV_SETTINGS.NETWORK_ROLES
155         net_role_formset = self.create_netformset(roles, config_bundle, data=post_data)
156         if net_role_formset.is_valid():
157             results = []
158             for form in net_role_formset:
159                 results.append({
160                     "role": form.cleaned_data['role'],
161                     "network": form.cleaned_data['network']
162                 })
163             models['network_roles'] = results
164             self.set_valid("Completed")
165             self.repo_put(self.repo.OPNFV_MODELS, models)
166             self.update_confirmation()
167         else:
168             self.set_invalid("Please complete all fields")
169
170
171 class Assign_Host_Roles(WorkflowStep):  # taken verbatim from Define_Software in sw workflow, merge the two?
172     template = 'config_bundle/steps/assign_host_roles.html'
173     title = 'Pick Host Roles'
174     description = "Choose the role each machine will have in your OPNFV pod"
175     short_title = "host roles"
176     modified_key = "host_roles_step"
177
178     def create_host_role_formset(self, hostlist=[], data=None):
179         models = self.repo_get(self.repo.OPNFV_MODELS, {})
180         host_roles = models.get("host_roles", [])
181         if not host_roles:
182             for host in hostlist:
183                 initial = {"host_name": host.resource.name}
184                 host_roles.append(initial)
185         models['host_roles'] = host_roles
186         self.repo_put(self.repo.OPNFV_MODELS, models)
187
188         HostFormset = formset_factory(OPNFVHostRoleForm, extra=0)
189
190         kwargs = {"initial": host_roles}
191         formset = None
192         if data:
193             formset = HostFormset(data, **kwargs)
194         else:
195             formset = HostFormset(**kwargs)
196
197         return formset
198
199     def get_context(self):
200         context = super(Assign_Host_Roles, self).get_context()
201         config = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
202         if config is None:
203             context['error'] = "Please select a Configuration on the first step"
204
205         formset = self.create_host_role_formset(hostlist=config.bundle.getResources())
206         context['formset'] = formset
207
208         return context
209
210     def get_host_role_mapping(self, host_roles, hostname):
211         for obj in host_roles:
212             if hostname == obj['host_name']:
213                 return obj
214         return None
215
216     def update_confirmation(self):
217         confirm = self.repo_get(self.repo.CONFIRMATION, {})
218         models = self.repo_get(self.repo.OPNFV_MODELS, {})
219         roles = models.get("host_roles")
220         if not roles:
221             return
222         confirm['host roles'] = {}
223         for role in roles:
224             confirm['host roles'][role['host_name']] = role['role'].name
225         self.repo_put(self.repo.CONFIRMATION, confirm)
226
227     def post(self, post_data, user):
228         formset = self.create_host_role_formset(data=post_data)
229
230         models = self.repo_get(self.repo.OPNFV_MODELS, {})
231         host_roles = models.get("host_roles", [])
232
233         has_jumphost = False
234         if formset.is_valid():
235             for form in formset:
236                 hostname = form.cleaned_data['host_name']
237                 role = form.cleaned_data['role']
238                 mapping = self.get_host_role_mapping(host_roles, hostname)
239                 mapping['role'] = role
240                 if "jumphost" in role.name.lower():
241                     has_jumphost = True
242
243             models['host_roles'] = host_roles
244             self.repo_put(self.repo.OPNFV_MODELS, models)
245             self.update_confirmation()
246
247             if not has_jumphost:
248                 self.set_invalid('Must have at least one "Jumphost" per POD')
249             else:
250                 self.set_valid("Completed")
251         else:
252             self.set_invalid("Please complete all fields")
253
254
255 class MetaInfo(WorkflowStep):
256     template = 'config_bundle/steps/config_software.html'
257     title = "Other Info"
258     description = "Give your software config a name, description, and other stuff"
259     short_title = "config info"
260
261     def get_context(self):
262         context = super(MetaInfo, self).get_context()
263
264         initial = self.repo_get(self.repo.OPNFV_MODELS, {}).get("meta", {})
265         context["form"] = BasicMetaForm(initial=initial)
266         return context
267
268     def update_confirmation(self):
269         confirm = self.repo_get(self.repo.CONFIRMATION, {})
270         models = self.repo_get(self.repo.OPNFV_MODELS, {})
271         meta = models.get("meta")
272         if not meta:
273             return
274         confirm['name'] = meta['name']
275         confirm['description'] = meta['description']
276         self.repo_put(self.repo.CONFIRMATION, confirm)
277
278     def post(self, post_data, user):
279         models = self.repo_get(self.repo.OPNFV_MODELS, {})
280         info = models.get("meta", {})
281
282         form = BasicMetaForm(post_data)
283         if form.is_valid():
284             info['name'] = form.cleaned_data['name']
285             info['description'] = form.cleaned_data['description']
286             models['meta'] = info
287             self.repo_put(self.repo.OPNFV_MODELS, models)
288             self.update_confirmation()
289             self.set_valid("Complete")
290         else:
291             self.set_invalid("Please correct the errors shown below")
292         self.repo_put(self.repo.OPNFV_MODELS, models)