diff options
Diffstat (limited to 'dashboard/src/workflow/sw_bundle_workflow.py')
-rw-r--r-- | dashboard/src/workflow/sw_bundle_workflow.py | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/dashboard/src/workflow/sw_bundle_workflow.py b/dashboard/src/workflow/sw_bundle_workflow.py new file mode 100644 index 0000000..0c558fc --- /dev/null +++ b/dashboard/src/workflow/sw_bundle_workflow.py @@ -0,0 +1,198 @@ +############################################################################## +# 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 + +from workflow.models import WorkflowStep +from workflow.forms import BasicMetaForm, HostSoftwareDefinitionForm +from workflow.booking_workflow import Abstract_Resource_Select +from resource_inventory.models import Image, GenericHost, ConfigBundle, HostConfiguration + + +class SWConf_Resource_Select(Abstract_Resource_Select): + workflow_type = "configuration" + + +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 build_filter_data(self, hosts_data): + """ + returns a 2D array of images to exclude + based on the ordering of the passed + hosts_data + """ + filter_data = [] + user = self.repo_get(self.repo.SESSION_USER) + lab = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE).lab + for i, host_data in enumerate(hosts_data): + host = GenericHost.objects.get(pk=host_data['host_id']) + wrong_owner = Image.objects.exclude(owner=user).exclude(public=True) + wrong_host = Image.objects.exclude(host_type=host.profile) + wrong_lab = Image.objects.exclude(from_lab=lab) + excluded_images = wrong_owner | wrong_host | wrong_lab + filter_data.append([]) + for image in excluded_images: + filter_data[i].append(image.pk) + return filter_data + + def create_hostformset(self, hostlist, data=None): + hosts_initial = [] + host_configs = self.repo_get(self.repo.CONFIG_MODELS, {}).get("host_configs", False) + if host_configs: + for config in host_configs: + hosts_initial.append({ + 'host_id': config.host.id, + 'host_name': config.host.resource.name, + 'headnode': config.is_head_node, + 'image': config.image + }) + else: + for host in hostlist: + hosts_initial.append({ + 'host_id': host.id, + 'host_name': host.resource.name + }) + + HostFormset = formset_factory(HostSoftwareDefinitionForm, extra=0) + filter_data = self.build_filter_data(hosts_initial) + + class SpecialHostFormset(HostFormset): + def get_form_kwargs(self, index): + kwargs = super(SpecialHostFormset, self).get_form_kwargs(index) + if index is not None: + kwargs['imageQS'] = Image.objects.exclude(pk__in=filter_data[index]) + return kwargs + + if data: + return SpecialHostFormset(data, initial=hosts_initial) + return SpecialHostFormset(initial=hosts_initial) + + def get_host_list(self, grb=None): + if grb is None: + grb = self.repo_get(self.repo.SELECTED_GRESOURCE_BUNDLE, 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.SELECTED_GRESOURCE_BUNDLE, False) + + if grb: + context["grb"] = grb + formset = self.create_hostformset(self.get_host_list(grb)) + context["formset"] = formset + context['headnode'] = self.repo_get(self.repo.CONFIG_MODELS, {}).get("headnode_index", 1) + else: + context["error"] = "Please select a resource first" + self.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, {}) + + hosts = self.get_host_list() + models['headnode_index'] = request.POST.get("headnode", 1) + formset = self.create_hostformset(hosts, data=request.POST) + has_headnode = False + if formset.is_valid(): + models['host_configs'] = [] + confirm_hosts = [] + for i, form in enumerate(formset): + host = hosts[i] + image = form.cleaned_data['image'] + headnode = form.cleaned_data['headnode'] + if headnode: + has_headnode = True + bundle = models['bundle'] + hostConfig = HostConfiguration( + host=host, + image=image, + bundle=bundle, + is_head_node=headnode + ) + models['host_configs'].append(hostConfig) + confirm_hosts.append({ + "name": host.resource.name, + "image": image.name, + "headnode": headnode + }) + + if not has_headnode: + self.set_invalid('Must have one "Headnode" per POD') + return self.render(request) + + 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.set_valid("Completed") + else: + self.set_invalid("Please complete all fields") + + return self.render(request) + + +class Config_Software(WorkflowStep): + template = 'config_bundle/steps/config_software.html' + 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 + context["form"] = BasicMetaForm(initial=initial) + 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, {}) + if "configuration" not in confirm: + confirm['configuration'] = {} + + form = BasicMetaForm(request.POST) + if form.is_valid(): + models['bundle'].name = form.cleaned_data['name'] + models['bundle'].description = form.cleaned_data['description'] + + confirm['configuration']['name'] = form.cleaned_data['name'] + confirm['configuration']['description'] = form.cleaned_data['description'] + self.set_valid("Complete") + else: + self.set_invalid("Please correct the errors shown below") + + self.repo_put(self.repo.CONFIG_MODELS, models) + self.repo_put(self.repo.CONFIRMATION, confirm) + + return self.render(request) |