Limit total number of active bookings per user
[pharos-tools.git] / dashboard / src / workflow / workflow_manager.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
11 from django.http import JsonResponse
12
13 from booking.models import Booking
14 from workflow.workflow_factory import WorkflowFactory
15 from workflow.models import Repository
16 from resource_inventory.models import (
17     GenericResourceBundle,
18     ConfigBundle,
19     HostConfiguration,
20     OPNFVConfig
21 )
22
23 import logging
24 logger = logging.getLogger(__name__)
25
26
27 class SessionManager():
28     def active_workflow(self):
29         return self.workflows[-1]
30
31     def __init__(self, request=None):
32         self.workflows = []
33
34         self.owner = request.user
35
36         self.factory = WorkflowFactory()
37
38     def add_workflow(self, workflow_type=None, target_id=None, **kwargs):
39         if target_id is not None:
40             self.prefill_repo(target_id, workflow_type)
41
42         repo = Repository()
43         if(len(self.workflows) >= 1):
44             defaults = self.workflows[-1].repository.get_child_defaults()
45             repo.set_defaults(defaults)
46             repo.el[repo.HAS_RESULT] = False
47         repo.el[repo.SESSION_USER] = self.owner
48         self.workflows.append(
49             self.factory.create_workflow(
50                 workflow_type=workflow_type,
51                 repo=repo
52             )
53         )
54
55     def pop_workflow(self):
56         if(len(self.workflows) <= 1):
57             return False
58
59         if self.workflows[-1].repository.el[self.workflows[-1].repository.HAS_RESULT]:
60             key = self.workflows[-1].repository.el[self.workflows[-1].repository.RESULT_KEY]
61             result = self.workflows[-1].repository.el[self.workflows[-1].repository.RESULT]
62             self.workflows[-2].repository.el[key] = result
63         self.workflows.pop()
64         return True
65
66     def status(self, request):
67         try:
68             meta_steps = []
69             for step in self.active_workflow().metasteps:
70                 meta_steps.append(step.to_json())
71             responsejson = {}
72             responsejson["steps"] = meta_steps
73             responsejson["active"] = self.active_workflow().repository.el['active_step']
74             responsejson["workflow_count"] = len(self.workflows)
75             return JsonResponse(responsejson, safe=False)
76         except Exception:
77             pass
78
79     def render(self, request, **kwargs):
80         # filter out when a step needs to handle post/form data
81         # if 'workflow' in post data, this post request was meant for me, not step
82         if request.method == 'POST' and request.POST.get('workflow', None) is None:
83             return self.active_workflow().steps[self.active_workflow().active_index].post_render(request)
84         return self.active_workflow().steps[self.active_workflow().active_index].render(request)
85
86     def post_render(self, request):
87         return self.active_workflow().steps[self.active_workflow().active_index].post_render(request)
88
89     def goto(self, num, **kwargs):
90         self.active_workflow().repository.el['active_step'] = int(num)
91         self.active_workflow().active_index = int(num)
92         # TODO: change to include some checking
93
94     def prefill_repo(self, target_id, workflow_type):
95         self.repository.el[self.repository.EDIT] = True
96         edit_object = None
97         if workflow_type == 0:
98             edit_object = Booking.objects.get(pk=target_id)
99             self.prefill_booking(edit_object)
100         elif workflow_type == 1:
101             edit_object = GenericResourceBundle.objects.get(pk=target_id)
102             self.prefill_resource(edit_object)
103         elif workflow_type == 2:
104             edit_object = ConfigBundle.objects.get(pk=target_id)
105             self.prefill_config(edit_object)
106
107     def prefill_booking(self, booking):
108         models = self.make_booking_models(booking)
109         confirmation = self.make_booking_confirm(booking)
110         self.active_workflow().repository.el[self.active_workflow().repository.BOOKING_MODELS] = models
111         self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirmation
112         self.active_workflow().repository.el[self.active_workflow().repository.GRESOURCE_BUNDLE_MODELS] = self.make_grb_models(booking.resource.template)
113         self.active_workflow().repository.el[self.active_workflow().repository.SELECTED_GRESOURCE_BUNDLE] = self.make_grb_models(booking.resource.template)['bundle']
114         self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = self.make_config_models(booking.config_bundle)
115
116     def prefill_resource(self, resource):
117         models = self.make_grb_models(resource)
118         confirm = self.make_grb_confirm(resource)
119         self.active_workflow().repository.el[self.active_workflow().repository.GRESOURCE_BUNDLE_MODELS] = models
120         self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
121
122     def prefill_config(self, config):
123         models = self.make_config_models(config)
124         confirm = self.make_config_confirm(config)
125         self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = models
126         self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
127         grb_models = self.make_grb_models(config.bundle)
128         self.active_workflow().repository.el[self.active_workflow().repository.GRESOURCE_BUNDLE_MODELS] = grb_models
129
130     def make_grb_models(self, resource):
131         models = self.active_workflow().repository.el.get(self.active_workflow().repository.GRESOURCE_BUNDLE_MODELS, {})
132         models['hosts'] = []
133         models['bundle'] = resource
134         models['interfaces'] = {}
135         models['vlans'] = {}
136         for host in resource.getHosts():
137             models['hosts'].append(host)
138             models['interfaces'][host.resource.name] = []
139             models['vlans'][host.resource.name] = {}
140             for interface in host.generic_interfaces.all():
141                 models['interfaces'][host.resource.name].append(interface)
142                 models['vlans'][host.resource.name][interface.profile.name] = []
143                 for vlan in interface.vlans.all():
144                     models['vlans'][host.resource.name][interface.profile.name].append(vlan)
145         return models
146
147     def make_grb_confirm(self, resource):
148         confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
149         confirm['resource'] = {}
150         confirm['resource']['hosts'] = []
151         confirm['resource']['lab'] = resource.lab.lab_user.username
152         for host in resource.getHosts():
153             confirm['resource']['hosts'].append({"name": host.resource.name, "profile": host.profile.name})
154         return confirm
155
156     def make_config_models(self, config):
157         models = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIG_MODELS, {})
158         models['bundle'] = config
159         models['host_configs'] = []
160         for host_conf in HostConfiguration.objects.filter(bundle=config):
161             models['host_configs'].append(host_conf)
162         models['opnfv'] = OPNFVConfig.objects.filter(bundle=config).last()
163         return models
164
165     def make_config_confirm(self, config):
166         confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
167         confirm['configuration'] = {}
168         confirm['configuration']['hosts'] = []
169         confirm['configuration']['name'] = config.name
170         confirm['configuration']['description'] = config.description
171         opnfv = OPNFVConfig.objects.filter(bundle=config).last()
172         confirm['configuration']['installer'] = opnfv.installer.name
173         confirm['configuration']['scenario'] = opnfv.scenario.name
174         for host_conf in HostConfiguration.objects.filter(bundle=config):
175             h = {"name": host_conf.host.resource.name, "image": host_conf.image.name, "role": host_conf.opnfvRole.name}
176             confirm['configuration']['hosts'].append(h)
177         return confirm
178
179     def make_booking_models(self, booking):
180         models = self.active_workflow().repository.el.get(self.active_workflow().repository.BOOKING_MODELS, {})
181         models['booking'] = booking
182         models['collaborators'] = []
183         for user in booking.collaborators.all():
184             models['collaborators'].append(user)
185         return models
186
187     def make_booking_confirm(self, booking):
188         confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
189         confirm['booking'] = {}
190         confirm['booking']['length'] = (booking.end - booking.start).days
191         confirm['booking']['project'] = booking.project
192         confirm['booking']['purpose'] = booking.purpose
193         confirm['booking']['resource name'] = booking.resource.template.name
194         confirm['booking']['configuration name'] = booking.config_bundle.name
195         confirm['booking']['collaborators'] = []
196         for user in booking.collaborators.all():
197             confirm['booking']['collaborators'].append(user.username)
198         return confirm
199
200
201 class ManagerTracker():
202     instance = None
203
204     managers = {}
205
206     def __init__(self):
207         pass
208
209     @staticmethod
210     def getInstance():
211         if ManagerTracker.instance is None:
212             ManagerTracker.instance = ManagerTracker()
213         return ManagerTracker.instance