aboutsummaryrefslogtreecommitdiffstats
path: root/src/workflow/sw_bundle_workflow.py
diff options
context:
space:
mode:
authorParker Berberian <pberberian@iol.unh.edu>2018-10-10 16:06:47 -0400
committerParker Berberian <pberberian@iol.unh.edu>2018-10-15 13:16:11 -0400
commit1f3a770d2547848590f39e9d9b9bdffeb94eec14 (patch)
tree97222e5facd1a242d951c38482315057b5790d51 /src/workflow/sw_bundle_workflow.py
parent6d4019e59eda897384e9c00d1daf8b2ce87d128f (diff)
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 <sbergeron@iol.unh.edu> Signed-off-by: Parker Berberian <pberberian@iol.unh.edu>
Diffstat (limited to 'src/workflow/sw_bundle_workflow.py')
-rw-r--r--src/workflow/sw_bundle_workflow.py238
1 files changed, 238 insertions, 0 deletions
diff --git a/src/workflow/sw_bundle_workflow.py b/src/workflow/sw_bundle_workflow.py
new file mode 100644
index 0000000..0e9be95
--- /dev/null
+++ b/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)