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/sw_bundle_workflow.py | 238 +++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 dashboard/src/workflow/sw_bundle_workflow.py (limited to 'dashboard/src/workflow/sw_bundle_workflow.py') diff --git a/dashboard/src/workflow/sw_bundle_workflow.py b/dashboard/src/workflow/sw_bundle_workflow.py new file mode 100644 index 0000000..0e9be95 --- /dev/null +++ b/dashboard/src/workflow/sw_bundle_workflow.py @@ -0,0 +1,238 @@ +############################################################################## +# 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.forms import formset_factory, modelformset_factory + +from workflow.models import WorkflowStep +from workflow.forms import SoftwareConfigurationForm, HostSoftwareDefinitionForm +from workflow.booking_workflow import Resource_Select +from resource_inventory.models import * + + +#resource selection step is reused from Booking workflow + +#TODO: change this: too hacky, just for presentation + +class SWConf_Resource_Select(Resource_Select): + def __init__(self, *args, **kwargs): + super(SWConf_Resource_Select, self).__init__(*args, **kwargs) + self.repo_key = self.repo.SWCONF_SELECTED_GRB + self.confirm_key = "configuration" + + def get_default_entry(self): + booking_grb = self.repo_get(self.repo.BOOKING_SELECTED_GRB) + if booking_grb: + return booking_grb + created_grb = self.repo_get(self.repo.GRESOURCE_BUNDLE_MODELS, {}).get("bundle", None) + return created_grb + + def post_render(self, request): + response = super(SWConf_Resource_Select, self).post_render(request) + models = self.repo_get(self.repo.CONFIG_MODELS, {}) + bundle = models.get("bundle", ConfigBundle(owner=self.repo_get(self.repo.SESSION_USER))) + bundle.bundle = self.repo_get(self.repo_key) # super put grb here + models['bundle'] = bundle + self.repo_put(self.repo.CONFIG_MODELS, models) + return response + +class Define_Software(WorkflowStep): + template = 'config_bundle/steps/define_software.html' + title = "Pick Software" + description = "Choose the opnfv and image of your machines" + short_title = "host config" + + def create_hostformset(self, hostlist): + hosts_initial = [] + host_configs = self.repo_get(self.repo.CONFIG_MODELS, {}).get("host_configs", False) + if host_configs: + for config in host_configs: + host_initial = {'host_id': config.host.id, 'host_name': config.host.resource.name} + host_initial['role'] = config.opnfvRole + host_initial['image'] = config.image + hosts_initial.append(host_initial) + + else: + for host in hostlist: + host_initial = {'host_id': host.id, 'host_name': host.resource.name} + + hosts_initial.append(host_initial) + + HostFormset = formset_factory(HostSoftwareDefinitionForm, extra=0) + host_formset = HostFormset(initial=hosts_initial) + + filter_data = {} + user = self.repo_get(self.repo.SESSION_USER) + i=0; + for host_data in hosts_initial: + host = GenericHost.objects.get(pk=host_data['host_id']) + excluded_images = Image.objects.exclude(owner=user).exclude(public=True) + excluded_images = excluded_images | Image.objects.exclude(host_type=host.profile) + lab = self.repo_get(self.repo.SWCONF_SELECTED_GRB).lab + excluded_images = excluded_images | Image.objects.exclude(from_lab=lab) + filter_data["id_form-" + str(i) + "-image"] = [] + for image in excluded_images: + filter_data["id_form-" + str(i) + "-image"].append(image.name) + i += 1 + + return host_formset, filter_data + + def get_host_list(self, grb=None): + if grb is None: + grb = self.repo_get(self.repo.SWCONF_SELECTED_GRB, False) + if not grb: + return [] + if grb.id: + return GenericHost.objects.filter(resource__bundle=grb) + generic_hosts = self.repo_get(self.repo.GRESOURCE_BUNDLE_MODELS, {}).get("hosts", []) + return generic_hosts + + def get_context(self): + context = super(Define_Software, self).get_context() + + grb = self.repo_get(self.repo.SWCONF_SELECTED_GRB, False) + + if grb: + context["grb"] = grb + formset, filter_data = self.create_hostformset(self.get_host_list(grb)) + context["formset"] = formset + context["filter_data"] = filter_data + else: + context["error"] = "Please select a resource first" + self.metastep.set_invalid("Step requires information that is not yet provided by previous step") + + return context + + def post_render(self, request): + models = self.repo_get(self.repo.CONFIG_MODELS, {}) + if "bundle" not in models: + models['bundle'] = ConfigBundle(owner=self.repo_get(self.repo.SESSION_USER)) + + confirm = self.repo_get(self.repo.CONFIRMATION, {}) + + HostFormset = formset_factory(HostSoftwareDefinitionForm, extra=0) + formset = HostFormset(request.POST) + hosts = self.get_host_list() + if formset.is_valid(): + models['host_configs'] = [] + i = 0 + confirm_hosts = [] + for form in formset: + host = hosts[i] + i += 1 + image = form.cleaned_data['image'] + # checks image compatability + grb = self.repo_get(self.repo.SWCONF_SELECTED_GRB) + lab = None + if grb: + lab = grb.lab + try: + owner = self.repo_get(self.repo.SESSION_USER) + q = Image.objects.filter(owner=owner) | Image.objects.filter(public=True) + q.filter(host_type=host.profile) + q.filter(from_lab=lab) + q.get(id=image.id) # will throw exception if image is not in q + except: + self.metastep.set_invalid("Image " + image.name + " is not compatible with host " + host.resource.name) + role = form.cleaned_data['role'] + bundle = models['bundle'] + hostConfig = HostConfiguration( + host=host, + image=image, + bundle=bundle, + opnfvRole=role + ) + models['host_configs'].append(hostConfig) + confirm_host = {"name": host.resource.name, "image": image.name, "role": role.name} + confirm_hosts.append(confirm_host) + + self.repo_put(self.repo.CONFIG_MODELS, models) + if "configuration" not in confirm: + confirm['configuration'] = {} + confirm['configuration']['hosts'] = confirm_hosts + self.repo_put(self.repo.CONFIRMATION, confirm) + self.metastep.set_valid("Completed") + else: + self.metastep.set_invalid("Please complete all fields") + + return self.render(request) + +class Config_Software(WorkflowStep): + template = 'config_bundle/steps/config_software.html' + form = SoftwareConfigurationForm + context = {'workspace_form':form} + title = "Other Info" + description = "Give your software config a name, description, and other stuff" + short_title = "config info" + + def get_context(self): + context = super(Config_Software, self).get_context() + + initial = {} + models = self.repo_get(self.repo.CONFIG_MODELS, {}) + bundle = models.get("bundle", False) + if bundle: + initial['name'] = bundle.name + initial['description'] = bundle.description + opnfv = models.get("opnfv", False) + if opnfv: + initial['installer'] = opnfv.installer + initial['scenario'] = opnfv.scenario + else: + initial['opnfv'] = False + supported = {} + for installer in Installer.objects.all(): + supported[str(installer)] = [] + for scenario in installer.sup_scenarios.all(): + supported[str(installer)].append(str(scenario)) + + context["form"] = SoftwareConfigurationForm(initial=initial) + context['supported'] = supported + + return context + + def post_render(self, request): + try: + models = self.repo_get(self.repo.CONFIG_MODELS, {}) + if "bundle" not in models: + models['bundle'] = ConfigBundle(owner=self.repo_get(self.repo.SESSION_USER)) + + + confirm = self.repo_get(self.repo.CONFIRMATION, {}) + if "configuration" not in confirm: + confirm['configuration'] = {} + + form = self.form(request.POST) + if form.is_valid(): + models['bundle'].name = form.cleaned_data['name'] + models['bundle'].description = form.cleaned_data['description'] + if form.cleaned_data['opnfv']: + installer = form.cleaned_data['installer'] + scenario = form.cleaned_data['scenario'] + opnfv = OPNFVConfig( + bundle=models['bundle'], + installer=installer, + scenario=scenario + ) + models['opnfv'] = opnfv + confirm['configuration']['installer'] = form.cleaned_data['installer'].name + confirm['configuration']['scenario'] = form.cleaned_data['scenario'].name + + confirm['configuration']['name'] = form.cleaned_data['name'] + confirm['configuration']['description'] = form.cleaned_data['description'] + self.metastep.set_valid("Complete") + else: + self.metastep.set_invalid("Please correct the errors shown below") + + self.repo_put(self.repo.CONFIG_MODELS, models) + self.repo_put(self.repo.CONFIRMATION, confirm) + + except Exception as e: + pass + return self.render(request) -- cgit 1.2.3-korg