Radomir Dopieralski d491e06d9a Create/edit flavors directly in the resource class form.
The formset in the resource class create/edit form now starts empty,
and allows the user to create or edit the flavors of that class
directly. Flavor templates are no longer used.

The formset starts with a single empty row at the end, for adding a new
flavor, and a "Delete" column with checkboxes for deleting existing
flavors.

If javascript is available, there is a link for adding more empty rows
and the empty line from the end is removed, and the checkboxes are
replaced with a cross icon, for deleting the rows instantly.

All traces of flavor templates have been removed from tuskar-ui.

The Max VMs field has been temporarily removed -- it will be added in
further iterations.

Change-Id: I1ff4c9f90657c62e7c5f45a4b7874524b9df204c
Implements: blueprint remove-flavor-templates
2013-09-17 15:36:55 +02:00

80 lines
3.0 KiB
Python

# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.forms import formsets
from django.utils import datastructures
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import forms
from tuskar_ui import forms as tuskar_forms
CAPACITIES = datastructures.SortedDict([
# (name, (label, unit, required)),
('cpu', (_('VCPU'), '', True)),
('memory', (_('RAM (MB)'), 'MB', True)),
('storage', (_('Root Disk (GB)'), 'GB', True)),
('ephemeral_disk', (_('Ephemeral Disk (GB)'), 'GB', False)),
('swap_disk', (_('Swap Disk (GB)'), 'GB', False)),
])
class FlavorForm(forms.Form):
id = forms.IntegerField(widget=forms.HiddenInput(), required=False)
name = forms.RegexField(label=_("Name"),
max_length=25,
regex=r'^[\w\.\- ]+$',
error_messages={'invalid': _('Name may only '
'contain letters, numbers, underscores, '
'periods and hyphens.')},
widget=forms.TextInput(attrs={
'class': 'input input-small',
}))
def __init__(self, *args, **kwargs):
super(FlavorForm, self).__init__(*args, **kwargs)
for name, (label, unit, required) in CAPACITIES.items():
self.fields[name] = forms.IntegerField(
label=label,
min_value=0,
required=required,
widget=tuskar_forms.NumberInput(attrs={
'class': 'input number_input_slim',
}))
class BaseFlavorFormSet(formsets.BaseFormSet):
def clean(self):
if any(self.errors):
# Don't bother validating the formset unless each form is valid
# on its own
return
names = {}
for form in self.forms:
name = form.cleaned_data.get('name')
if not name:
continue
if name in names:
message = _("This value repeats, but it should be unique.")
other_form = names[name]
form._errors['name'] = form.error_class([message])
other_form._errors['name'] = other_form.error_class([message])
names[name] = form
FlavorFormset = formsets.formset_factory(FlavorForm, extra=1, can_delete=True,
formset=BaseFlavorFormSet)