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 ##############################################################################
11 from django.http import JsonResponse
12 from django.http.request import QueryDict
13 from django.urls import reverse
15 from booking.models import Booking
16 from workflow.workflow_factory import WorkflowFactory
17 from workflow.models import Repository
18 from resource_inventory.models import (
20 ResourceConfiguration,
23 from workflow.forms import ManagerForm
26 logger = logging.getLogger(__name__)
29 class SessionManager():
30 def active_workflow(self):
31 return self.workflows[-1]
33 def __init__(self, request=None):
35 self.owner = request.user
36 self.factory = WorkflowFactory()
39 def set_step_statuses(self, superclass_type, desired_enabled=True):
40 workflow = self.active_workflow()
41 steps = workflow.steps
43 if isinstance(step, superclass_type):
49 def add_workflow(self, workflow_type=None, **kwargs):
51 if (len(self.workflows) >= 1):
52 defaults = self.workflows[-1].repository.get_child_defaults()
53 repo.set_defaults(defaults)
54 repo.el[repo.HAS_RESULT] = False
55 repo.el[repo.SESSION_USER] = self.owner
56 repo.el[repo.SESSION_MANAGER] = self
57 self.workflows.append(
58 self.factory.create_workflow(
59 workflow_type=workflow_type,
64 def get_redirect(self):
65 if isinstance(self.result, Booking):
66 return reverse('booking:booking_detail', kwargs={'booking_id': self.result.id})
69 def pop_workflow(self, discard=False):
70 multiple_wfs = len(self.workflows) > 1
72 if self.workflows[-1].repository.el[Repository.RESULT]: # move result
73 key = self.workflows[-1].repository.el[Repository.RESULT_KEY]
74 result = self.workflows[-1].repository.el[Repository.RESULT]
75 self.workflows[-2].repository.el[key] = result
76 prev_workflow = self.workflows.pop()
78 current_repo = self.workflows[-1].repository
80 current_repo = prev_workflow.repository
81 self.result = current_repo.el[current_repo.RESULT]
84 return multiple_wfs, self.result
86 def status(self, request):
88 "steps": [step.to_json() for step in self.active_workflow().steps],
89 "active": self.active_workflow().repository.el['active_step'],
90 "workflow_count": len(self.workflows)
93 def handle_post(self, request):
94 form = ManagerForm(request.POST)
96 self.get_active_step().post(
97 QueryDict(form.cleaned_data['step_form']),
101 if form.cleaned_data['step'] == 'prev':
103 if form.cleaned_data['step'] == 'next':
108 def handle_request(self, request):
109 if request.method == 'POST':
110 self.handle_post(request)
111 return self.render(request)
113 def render(self, request, **kwargs):
115 return JsonResponse({
116 "meta": self.status(request),
117 "content": self.get_active_step().render_to_string(request),
120 return JsonResponse({
121 "redirect": self.get_redirect()
124 def post_render(self, request):
125 return self.active_workflow().steps[self.active_workflow().active_index].post_render(request)
127 def get_active_step(self):
128 return self.active_workflow().steps[self.active_workflow().active_index]
130 def go_next(self, **kwargs):
131 # need to verify current step is valid to allow this
132 if self.get_active_step().valid < 200:
134 next_step = self.active_workflow().active_index + 1
135 if next_step >= len(self.active_workflow().steps):
136 raise Exception("Out of bounds request for step")
137 while not self.active_workflow().steps[next_step].enabled:
139 self.active_workflow().repository.el['active_step'] = next_step
140 self.active_workflow().active_index = next_step
142 def go_prev(self, **kwargs):
143 prev_step = self.active_workflow().active_index - 1
145 raise Exception("Out of bounds request for step")
146 while not self.active_workflow().steps[prev_step].enabled:
148 self.active_workflow().repository.el['active_step'] = prev_step
149 self.active_workflow().active_index = prev_step
151 def prefill_repo(self, target_id, workflow_type):
152 self.repository.el[self.repository.EDIT] = True
154 if workflow_type == 0:
155 edit_object = Booking.objects.get(pk=target_id)
156 self.prefill_booking(edit_object)
157 elif workflow_type == 1:
158 edit_object = ResourceTemplate.objects.get(pk=target_id)
159 self.prefill_resource(edit_object)
160 elif workflow_type == 2:
161 edit_object = ResourceTemplate.objects.get(pk=target_id)
162 self.prefill_config(edit_object)
164 def prefill_booking(self, booking):
165 models = self.make_booking_models(booking)
166 confirmation = self.make_booking_confirm(booking)
167 self.active_workflow().repository.el[self.active_workflow().repository.BOOKING_MODELS] = models
168 self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirmation
169 self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = self.make_grb_models(booking.resource.template)
170 self.active_workflow().repository.el[self.active_workflow().repository.SELECTED_RESOURCE_TEMPLATE] = self.make_grb_models(booking.resource.template)['bundle']
171 self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = self.make_config_models(booking.config_bundle)
173 def prefill_resource(self, resource):
174 models = self.make_grb_models(resource)
175 confirm = self.make_grb_confirm(resource)
176 self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = models
177 self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
179 def prefill_config(self, config):
180 models = self.make_config_models(config)
181 confirm = self.make_config_confirm(config)
182 self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = models
183 self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
184 grb_models = self.make_grb_models(config.bundle)
185 self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = grb_models
187 def make_grb_models(self, resource):
188 models = self.active_workflow().repository.el.get(self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS, {})
190 models['bundle'] = resource
191 models['interfaces'] = {}
193 for host in resource.getResources():
194 models['hosts'].append(host)
195 models['interfaces'][host.resource.name] = []
196 models['vlans'][host.resource.name] = {}
197 for interface in host.generic_interfaces.all():
198 models['interfaces'][host.resource.name].append(interface)
199 models['vlans'][host.resource.name][interface.profile.name] = []
200 for vlan in interface.vlans.all():
201 models['vlans'][host.resource.name][interface.profile.name].append(vlan)
204 def make_grb_confirm(self, resource):
205 confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
206 confirm['resource'] = {}
207 confirm['resource']['hosts'] = []
208 confirm['resource']['lab'] = resource.lab.lab_user.username
209 for host in resource.getResources():
210 confirm['resource']['hosts'].append({"name": host.resource.name, "profile": host.profile.name})
213 def make_config_models(self, config):
214 models = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIG_MODELS, {})
215 models['bundle'] = config
216 models['host_configs'] = []
217 for host_conf in ResourceConfiguration.objects.filter(bundle=config):
218 models['host_configs'].append(host_conf)
219 models['opnfv'] = OPNFVConfig.objects.filter(bundle=config).last()
222 def make_config_confirm(self, config):
223 confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
224 confirm['configuration'] = {}
225 confirm['configuration']['hosts'] = []
226 confirm['configuration']['name'] = config.name
227 confirm['configuration']['description'] = config.description
228 opnfv = OPNFVConfig.objects.filter(bundle=config).last()
229 confirm['configuration']['installer'] = opnfv.installer.name
230 confirm['configuration']['scenario'] = opnfv.scenario.name
231 for host_conf in ResourceConfiguration.objects.filter(bundle=config):
232 h = {"name": host_conf.host.resource.name, "image": host_conf.image.name, "role": host_conf.opnfvRole.name}
233 confirm['configuration']['hosts'].append(h)
236 def make_booking_models(self, booking):
237 models = self.active_workflow().repository.el.get(self.active_workflow().repository.BOOKING_MODELS, {})
238 models['booking'] = booking
239 models['collaborators'] = []
240 for user in booking.collaborators.all():
241 models['collaborators'].append(user)
244 def make_booking_confirm(self, booking):
245 confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
246 confirm['booking'] = {}
247 confirm['booking']['length'] = (booking.end - booking.start).days
248 confirm['booking']['project'] = booking.project
249 confirm['booking']['purpose'] = booking.purpose
250 confirm['booking']['resource name'] = booking.resource.template.name
251 confirm['booking']['configuration name'] = booking.config_bundle.name
252 confirm['booking']['collaborators'] = []
253 for user in booking.collaborators.all():
254 confirm['booking']['collaborators'].append(user.username)
258 class ManagerTracker():
268 if ManagerTracker.instance is None:
269 ManagerTracker.instance = ManagerTracker()
270 return ManagerTracker.instance