From 25275685e9a735e51fae8b1a936ba5733f6fb770 Mon Sep 17 00:00:00 2001 From: Parker Berberian Date: Wed, 10 Oct 2018 16:06:47 -0400 Subject: Lab as a Service 2.0 See changes here: https://wiki.opnfv.org/display/INF/Pharos+Laas Change-Id: I59ada5f98e70a28d7f8c14eab3239597e236ca26 Signed-off-by: Sawyer Bergeron Signed-off-by: Parker Berberian --- dashboard/src/workflow/workflow_manager.py | 251 +++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 dashboard/src/workflow/workflow_manager.py (limited to 'dashboard/src/workflow/workflow_manager.py') diff --git a/dashboard/src/workflow/workflow_manager.py b/dashboard/src/workflow/workflow_manager.py new file mode 100644 index 0000000..16fa468 --- /dev/null +++ b/dashboard/src/workflow/workflow_manager.py @@ -0,0 +1,251 @@ +############################################################################## +# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +from django.db import models +from django.contrib.auth.models import User +from django.core import serializers +from django.http import HttpResponse, JsonResponse + +import json +import uuid +import random + +from resource_inventory.models import * +from booking.models import Booking +from workflow.workflow_factory import WorkflowFactory, MetaStep, MetaRelation +from workflow.models import Repository, Confirmation_Step + +import logging +logger = logging.getLogger(__name__) + +class SessionManager(): + + def __init__(self, request=None): + self.repository = Repository() + self.repository.el[self.repository.SESSION_USER] = request.user + self.repository.el['active_step'] = 0 + self.steps = [] + self.factory = WorkflowFactory() + c_step = WorkflowFactory().make_step(Confirmation_Step, self.repository) + self.steps.append(c_step) + metaconfirm = MetaStep() + metaconfirm.index = 0 + metaconfirm.short_title = "confirm" + self.repository.el['steps'] = 1; + self.metaworkflow = None + self.metaworkflows = [] + self.metarelations = [] + self.relationreverselookup = {} + self.initialized = False + self.active_index = 0 + self.step_meta = [metaconfirm] + self.relation_depth = 0 + + def add_workflow(self, workflow_type=None, target_id=None, **kwargs): + if target_id is not None: + self.prefill_repo(target_id, workflow_type) + factory_steps, meta_info = self.factory.conjure(workflow_type=workflow_type, repo=self.repository) + offset = len(meta_info) + for relation in self.metarelations: + if relation.depth > self.relation_depth: + self.relation_depth = relation.depth + if relation.parent >= self.repository.el['active_step']: + relation.parent += offset + for i in range(0, len(relation.children)): + if relation.children[i] >= self.repository.el['active_step']: + relation.children[i] += offset + self.step_meta[self.active_index:self.active_index] = meta_info + self.steps[self.active_index:self.active_index] = factory_steps + + if self.initialized: + relation = MetaRelation() + relation.parent = self.repository.el['active_step'] + offset + relation.depth = self.relationreverselookup[self.step_meta[relation.parent]].depth + 1 + if relation.depth > self.relation_depth: + self.relation_depth = relation.depth + for i in range(self.repository.el['active_step'], offset + self.repository.el['active_step']): + relation.children.append(i) + self.relationreverselookup[self.step_meta[i]] = relation + relation.color = "#%06x" % random.randint(0, 0xFFFFFF) + self.metarelations.append(relation) + else: + relation = MetaRelation() + relation.depth = 0 + relation.parent = 500000000000 + for i in range(0, len(self.step_meta)): + relation.children.append(i) + self.relationreverselookup[self.step_meta[i]] = relation + self.metarelations.append(relation) + self.initialized = True + + + def status(self, request): + try: + workflows = [] + steps = [] + for step in self.step_meta: + steps.append(step.to_json()) + parents = {} + children = {} + responsejson = {} + responsejson["steps"] = steps + responsejson["active"] = self.repository.el['active_step'] + responsejson["relations"] = [] + i = 0 + for relation in self.metarelations: + responsejson["relations"].append(relation.to_json()) + children[relation.parent] = i + for child in relation.children: + parents[child] = i + i += 1 + responsejson['max_depth'] = self.relation_depth + responsejson['parents'] = parents + responsejson['children'] = children + return JsonResponse(responsejson, safe=False) + except Exception as e: + pass + + def render(self, request, **kwargs): + #filter out when a step needs to handle post/form data + # if 'workflow' in post data, this post request was meant for me, not step + if request.method == 'POST' and request.POST.get('workflow', None) is None: + return self.steps[self.active_index].post_render(request) + return self.steps[self.active_index].render(request) + + def post_render(self, request): + return self.steps[self.active_index].post_render(request) + + def goto(self, num, **kwargs): + self.repository.el['active_step'] = int(num) + self.active_index = int(num) + #TODO: change to include some checking + + def prefill_repo(self, target_id, workflow_type): + self.repository.el[self.repository.EDIT] = True + edit_object = None + if workflow_type == 0: + edit_object = Booking.objects.get(pk=target_id) + self.prefill_booking(edit_object) + elif workflow_type == 1: + edit_object = GenericResourceBundle.objects.get(pk=target_id) + self.prefill_resource(edit_object) + elif workflow_type == 2: + edit_object = ConfigBundle.objects.get(pk=target_id) + self.prefill_config(edit_object) + + + def prefill_booking(self, booking): + models = self.make_booking_models(booking) + confirmation = self.make_booking_confirm(booking) + self.repository.el[self.repository.BOOKING_MODELS] = models + self.repository.el[self.repository.CONFIRMATION] = confirmation + self.repository.el[self.repository.GRESOURCE_BUNDLE_MODELS] = self.make_grb_models(booking.resource.template) + self.repository.el[self.repository.BOOKING_SELECTED_GRB] = self.make_grb_models(booking.resource.template)['bundle'] + self.repository.el[self.repository.CONFIG_MODELS] = self.make_config_models(booking.config_bundle) + + def prefill_resource(self, resource): + models = self.make_grb_models(resource) + confirm = self.make_grb_confirm(resource) + self.repository.el[self.repository.GRESOURCE_BUNDLE_MODELS] = models + self.repository.el[self.repository.CONFIRMATION] = confirm + + def prefill_config(self, config): + models = self.make_config_models(config) + confirm = self.make_config_confirm(config) + self.repository.el[self.repository.CONFIG_MODELS] = models + self.repository.el[self.repository.CONFIRMATION] = confirm + grb_models = self.make_grb_models(config.bundle) + self.repository.el[self.repository.GRESOURCE_BUNDLE_MODELS] = grb_models + self.repository.el[self.repository.SWCONF_SELECTED_GRB] = config.bundle + + def make_grb_models(self, resource): + models = self.repository.el.get(self.repository.GRESOURCE_BUNDLE_MODELS, {}) + models['hosts'] = [] + models['bundle'] = resource + models['interfaces'] = {} + models['vlans'] = {} + for host in resource.getHosts(): + models['hosts'].append(host) + models['interfaces'][host.resource.name] = [] + models['vlans'][host.resource.name] = {} + for interface in host.generic_interfaces.all(): + models['interfaces'][host.resource.name].append(interface) + models['vlans'][host.resource.name][interface.profile.name] = [] + for vlan in interface.vlans.all(): + models['vlans'][host.resource.name][interface.profile.name].append(vlan) + return models + + def make_grb_confirm(self, resource): + confirm = self.repository.el.get(self.repository.CONFIRMATION, {}) + confirm['resource'] = {} + confirm['resource']['hosts'] = [] + confirm['resource']['lab'] = resource.lab.lab_user.username + for host in resource.getHosts(): + confirm['resource']['hosts'].append({"name": host.resource.name, "profile": host.profile.name}) + return confirm + + def make_config_models(self, config): + models = self.repository.el.get(self.repository.CONFIG_MODELS, {}) + models['bundle'] = config + models['host_configs'] = [] + for host_conf in HostConfiguration.objects.filter(bundle=config): + models['host_configs'].append(host_conf) + models['opnfv'] = OPNFVConfig.objects.filter(bundle=config).last() + return models + + def make_config_confirm(self, config): + confirm = self.repository.el.get(self.repository.CONFIRMATION, {}) + confirm['configuration'] = {} + confirm['configuration']['hosts'] = [] + confirm['configuration']['name'] = config.name + confirm['configuration']['description'] = config.description + opnfv = OPNFVConfig.objects.filter(bundle=config).last() + confirm['configuration']['installer'] = opnfv.installer.name + confirm['configuration']['scenario'] = opnfv.scenario.name + for host_conf in HostConfiguration.objects.filter(bundle=config): + h = {"name": host_conf.host.resource.name, "image": host_conf.image.name, "role": host_conf.opnfvRole.name} + confirm['configuration']['hosts'].append(h) + return confirm + + def make_booking_models(self, booking): + models = self.repository.el.get(self.repository.BOOKING_MODELS, {}) + models['booking'] = booking + models['collaborators'] = [] + for user in booking.collaborators.all(): + models['collaborators'].append(user) + return models + + def make_booking_confirm(self, booking): + confirm = self.repository.el.get(self.repository.CONFIRMATION, {}) + confirm['booking'] = {} + confirm['booking']['length'] = (booking.end - booking.start).days + confirm['booking']['project'] = booking.project + confirm['booking']['purpose'] = booking.purpose + confirm['booking']['resource name'] = booking.resource.template.name + confirm['booking']['configuration name'] = booking.config_bundle.name + confirm['booking']['collaborators'] = [] + for user in booking.collaborators.all(): + confirm['booking']['collaborators'].append(user.username) + return confirm + + +class ManagerTracker(): + instance = None + + managers = {} + + def __init__(self): + pass + + @staticmethod + def getInstance(): + if ManagerTracker.instance is None: + ManagerTracker.instance = ManagerTracker() + return ManagerTracker.instance -- cgit 1.2.3-korg