1 ##############################################################################
2 # Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
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 ##############################################################################
11 import django.forms as forms
12 from django.forms import widgets
13 from django.contrib.auth.models import User
14 from django.utils.safestring import mark_safe
15 from django.template.loader import render_to_string
16 from django.core import serializers
17 from django.forms.widgets import NumberInput
18 from django.db.models import F
22 from resource_inventory.models import *
23 from account.models import Lab
24 from account.models import UserProfile
27 class SearchableSelectMultipleWidget(widgets.SelectMultiple):
28 template_name = 'dashboard/searchable_select_multiple.html'
30 def __init__(self, attrs=None):
31 self.items = attrs['set']
32 self.show_from_noentry = attrs['show_from_noentry']
33 self.show_x_results = attrs['show_x_results']
34 self.results_scrollable = attrs['scrollable']
35 self.selectable_limit = attrs['selectable_limit']
36 self.placeholder = attrs['placeholder']
37 self.name = attrs['name']
38 self.initial = attrs.get("initial", "")
39 self.default_entry = attrs.get("default_entry", "")
40 self.edit = attrs.get("edit", False)
41 self.wf_type = attrs.get("wf_type")
43 super(SearchableSelectMultipleWidget, self).__init__(attrs)
45 def render(self, name, value, attrs=None, renderer=None):
47 context = self.get_context(attrs)
48 return mark_safe(render_to_string(self.template_name, context))
50 def get_context(self,attrs):
51 return {'items':self.items,
53 'show_from_noentry':self.show_from_noentry,
54 'show_x_results':self.show_x_results,
55 'results_scrollable':self.results_scrollable,
56 'selectable_limit':self.selectable_limit,
57 'placeholder':self.placeholder,
58 'initial':self.initial,
59 'default_entry':self.default_entry,
61 'wf_type': self.wf_type
64 class ResourceSelectorForm(forms.Form):
66 def __init__(self, data=None, **kwargs):
70 if "chosen_resource" in kwargs:
71 chosen_resource = kwargs.pop("chosen_resource")
72 if "bundle" in kwargs:
73 bundle = kwargs.pop("bundle")
75 edit = kwargs.pop("edit")
76 super(ResourceSelectorForm, self).__init__(data=data,**kwargs)
77 queryset = GenericResourceBundle.objects.select_related("owner").all()
78 if data and 'user' in data:
79 queryset = queryset.filter(owner=data['user'])
81 attrs = self.build_search_widget_attrs(chosen_resource, bundle, edit, queryset)
83 self.fields['generic_resource_bundle'] = forms.CharField(
84 widget=SearchableSelectMultipleWidget(attrs=attrs)
87 def build_search_widget_attrs(self, chosen_resource, bundle, edit, queryset):
91 displayable['small_name'] = res.name
93 displayable['expanded_name'] = res.owner.username
95 displayable['expanded_name'] = ""
96 displayable['string'] = res.description
97 displayable['id'] = res.id
98 resources[res.id] = displayable
102 displayable['small_name'] = bundle.name
103 displayable['expanded_name'] = "Current bundle"
104 displayable['string'] = bundle.description
105 displayable['id'] = "repo bundle"
106 resources["repo bundle"] = displayable
109 'show_from_noentry': "true",
110 'show_x_results': -1,
111 'scrollable': "true",
112 'selectable_limit': 1,
113 'name': "generic_resource_bundle",
114 'placeholder': "resource",
115 'initial': chosen_resource,
121 class SWConfigSelectorForm(forms.Form):
123 def __init__(self, *args, **kwargs):
128 if "chosen_software" in kwargs:
129 chosen_software = kwargs.pop("chosen_software")
131 if "bundle" in kwargs:
132 bundle = kwargs.pop("bundle")
134 edit = kwargs.pop("edit")
135 if "resource" in kwargs:
136 resource = kwargs.pop("resource")
137 super(SWConfigSelectorForm, self).__init__(*args,**kwargs)
138 attrs = self.build_search_widget_attrs(chosen_software,bundle, edit, resource)
139 self.fields['software_bundle'] = forms.CharField(
140 widget=SearchableSelectMultipleWidget(attrs=attrs)
143 def build_search_widget_attrs(self, chosen, bundle, edit, resource):
145 queryset = ConfigBundle.objects.select_related('owner').all()
147 queryset = queryset.filter(bundle=resource)
149 for config in queryset:
151 displayable['small_name'] = config.name
152 displayable['expanded_name'] = config.owner.username
153 displayable['string'] = config.description
154 displayable['id'] = config.id
155 configs[config.id] = displayable
159 displayable['small_name'] = bundle.name
160 displayable['expanded_name'] = "Current configuration"
161 displayable['string'] = bundle.description
162 displayable['id'] = "repo bundle"
163 configs['repo bundle'] = displayable
167 'show_from_noentry': "true",
168 'show_x_results': -1,
169 'scrollable': "true",
170 'selectable_limit': 1,
171 'name': "software_bundle",
172 'placeholder': "config",
179 class BookingMetaForm(forms.Form):
181 length = forms.IntegerField(widget=NumberInput(attrs={'type':'range', 'min':"0", "max":"21", "value":"0"}))
182 purpose = forms.CharField(max_length=1000)
183 project = forms.CharField(max_length=400)
184 info_file = forms.CharField(max_length=1000, required=False)
186 def __init__(self, data=None, *args, **kwargs):
188 if "default_user" in kwargs:
189 default_user = kwargs.pop("default_user")
192 self.default_user = default_user
193 if "chosen_users" in kwargs:
194 chosen_users = kwargs.pop("chosen_users")
195 elif data and "users" in data:
196 chosen_users = data.getlist("users")
200 super(BookingMetaForm, self).__init__(data=data, **kwargs)
202 self.fields['users'] = forms.CharField(
203 widget=SearchableSelectMultipleWidget(
204 attrs=self.build_search_widget_attrs(chosen_users, default_user=default_user)
209 def build_user_list(self):
211 returns a mapping of UserProfile ids to displayable objects expected by
212 searchable multiple select widget
216 d_qset = UserProfile.objects.select_related('user').all().exclude(user__username=self.default_user);
217 for userprofile in d_qset:
219 'id':userprofile.user.id,
220 'expanded_name':userprofile.full_name,
221 'small_name':userprofile.user.username,
222 'string':userprofile.email_addr
225 users[userprofile.user.id] = user
228 except Exception as e:
231 def build_search_widget_attrs(self, chosen_users, default_user="you"):
234 'set': self.build_user_list(),
235 'show_from_noentry': "false",
236 'show_x_results': 10,
237 'scrollable': "false",
238 'selectable_limit': -1,
240 'placeholder': "username",
241 'initial': chosen_users,
246 class MultipleSelectFilterWidget(forms.Widget):
247 def __init__(self, attrs=None):
248 super(MultipleSelectFilterWidget, self).__init__(attrs)
250 self.template_name="dashboard/multiple_select_filter_widget.html"
252 def render(self, name, value, attrs=None, renderer=None):
254 self.context = self.get_context(name, value, attrs)
255 html = render_to_string(self.template_name, context=self.context)
256 return mark_safe(html)
258 def get_context(self, name, value, attrs):
261 class MultipleSelectFilterField(forms.Field):
262 def __init__( self, required=True, widget=None, label=None, initial=None,
263 help_text='', error_messages=None, show_hidden_initial=False,
264 validators=(), localize=False, disabled=False, label_suffix=None):
265 """from the documentation:
266 # required -- Boolean that specifies whether the field is required.
268 # widget -- A Widget class, or instance of a Widget class, that should
269 # be used for this Field when displaying it. Each Field has a
270 # default Widget that it'll use if you don't specify this. In
271 # most cases, the default widget is TextInput.
272 # label -- A verbose name for this field, for use in displaying this
273 # field in a form. By default, Django will use a "pretty"
274 # version of the form field name, if the Field is part of a
276 # initial -- A value to use in this Field's initial display. This value
277 # is *not* used as a fallback if data isn't given.
278 # help_text -- An optional string to use as "help text" for this Field.
279 # error_messages -- An optional dictionary to override the default
280 # messages that the field will raise.
281 # show_hidden_initial -- Boolean that specifies if it is needed to render a
282 # hidden widget with initial value after widget.
283 # validators -- List of additional validators to use
284 # localize -- Boolean that specifies if the field should be localized.
285 # disabled -- Boolean that specifies whether the field is disabled, that
286 # is its widget is shown in the form but not editable.
287 # label_suffix -- Suffix to be added to the label. Overrides
288 # form's label_suffix.
290 #this is bad, but django forms are annoying
292 if self.widget is None:
293 self.widget = MultipleSelectFilterWidget()
294 super(MultipleSelectFilterField, self).__init__(
300 error_messages=error_messages,
301 show_hidden_initial=show_hidden_initial,
302 validators=validators,
305 label_suffix=label_suffix
310 This method will raise a django.forms.ValidationError or return clean data
318 Gets all labs and thier host profiles and returns a serialized version the form can understand.
319 Should be rewritten with a related query to make it faster
320 Should be moved outside of global scope
326 for lab in Lab.objects.all():
328 slab['id'] = "lab_" + str(lab.lab_user.id)
329 slab['name'] = lab.name
330 slab['description'] = lab.description
332 slab['selectable'] = 1
335 items[slab['id']] = slab
336 mapping[slab['id']] = []
337 labs[slab['id']] = slab
338 for host in lab.hostprofiles.all():
340 shost['forms'] = [{"name": "host_name", "type": "text", "placeholder": "hostname"}]
341 shost['id'] = "host_" + str(host.id)
342 shost['name'] = host.name
343 shost['description'] = host.description
344 shost['selected'] = 0
345 shost['selectable'] = 1
347 shost['multiple'] = 1
348 items[shost['id']] = shost
349 mapping[slab['id']].append(shost['id'])
350 if shost['id'] not in mapping:
351 mapping[shost['id']] = []
352 mapping[shost['id']].append(slab['id'])
353 hosts[shost['id']] = shost
355 filter_objects = [("labs", labs.values()), ("hosts", hosts.values())]
358 'filter_objects': filter_objects,
364 class HardwareDefinitionForm(forms.Form):
366 def __init__(self, *args, **kwargs):
367 selection_data = kwargs.pop("selection_data", False)
368 super(HardwareDefinitionForm, self).__init__(*args, **kwargs)
369 attrs = FormUtils.getLabData()
370 attrs['selection_data'] = selection_data
371 self.fields['filter_field'] = MultipleSelectFilterField(
372 widget=MultipleSelectFilterWidget(
377 class PodDefinitionForm(forms.Form):
380 xml = forms.CharField()
382 class ResourceMetaForm(forms.Form):
384 bundle_name = forms.CharField(label="POD Name")
385 bundle_description = forms.CharField(label="POD Description", widget=forms.Textarea)
387 class GenericHostMetaForm(forms.Form):
389 host_profile = forms.CharField(label="Host Type", disabled=True, required=False)
390 host_name = forms.CharField(label="Host Name")
392 class NetworkDefinitionForm(forms.Form):
393 def __init__(self, *args, **kwargs):
396 super(NetworkDefinitionForm, self).__init__(**kwargs)
398 class NetworkConfigurationForm(forms.Form):
399 def __init__(self, *args, **kwargs):
402 super(NetworkConfigurationForm).__init__(**kwargs)
404 class HostSoftwareDefinitionForm(forms.Form):
405 fields = ["host_name", "role", "image"]
407 host_name = forms.CharField(max_length=200, disabled=True, required=False)
408 role = forms.ModelChoiceField(queryset=OPNFVRole.objects.all())
409 image = forms.ModelChoiceField(queryset=Image.objects.all())
411 class SoftwareConfigurationForm(forms.Form):
413 name = forms.CharField(max_length=200)
414 description = forms.CharField(widget=forms.Textarea)
415 opnfv = forms.BooleanField(disabled=True, required=False)
416 installer = forms.ModelChoiceField(queryset=Installer.objects.all(), disabled=True, required=False)
417 scenario = forms.ModelChoiceField(queryset=Scenario.objects.all(), disabled=True, required=False)
419 class WorkflowSelectionForm(forms.Form):
420 fields = ['workflow']
422 empty_permitted = False
424 workflow = forms.ChoiceField( choices=(
426 (1, 'Resource Bundle'),
427 (2, 'Software Configuration')
429 label="Choose Workflow",
433 class SnapshotHostSelectForm(forms.Form):
434 host = forms.CharField()
436 class SnapshotMetaForm(forms.Form):
437 name = forms.CharField()
438 description = forms.CharField()
440 class ConfirmationForm(forms.Form):
443 confirm = forms.ChoiceField( choices=(