Imre Farkas ff77bcf778 Enable H302 check
H302 check was enabled in Horizon recently which allows importing modules only.
This patch fixes all import statements except for gettext where it makes more
sense to use _. In those cases the warnings are discarded by adding the # noqa
comment to the end of the line.

Fixes: bug #1218882

Change-Id: I745471bd372fac3724aa04cc08c512fb823cfbd0
2013-08-30 15:07:41 +02:00

327 lines
12 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.core import urlresolvers
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import workflows
from tuskar_ui import api as tuskar
import tuskar_ui.workflows
import re
from tuskar_ui.infrastructure.resource_management.resource_classes\
import tables
class ResourceClassInfoAndFlavorsAction(workflows.Action):
name = forms.CharField(max_length=255,
label=_("Class Name"),
help_text="",
required=True)
service_type = forms.ChoiceField(label=_('Class Type'),
required=True,
choices=[('', ''),
('compute',
('Compute')),
('not_compute',
('Non Compute')),
],
widget=forms.Select(
attrs={'class': 'switchable'})
)
image = forms.ChoiceField(label=_('Provisioning Image'),
required=True,
choices=[('compute-img', ('overcloud-compute'))],
widget=forms.Select(
attrs={'class': 'switchable'})
)
def clean(self):
cleaned_data = super(ResourceClassInfoAndFlavorsAction,
self).clean()
name = cleaned_data.get('name')
resource_class_id = self.initial.get('resource_class_id', None)
try:
resource_classes = tuskar.ResourceClass.list(self.request)
except Exception:
resource_classes = []
msg = _('Unable to get resource class list')
exceptions.check_message(["Connection", "refused"], msg)
raise
for resource_class in resource_classes:
if resource_class.name == name and \
resource_class_id != resource_class.id:
raise forms.ValidationError(
_('The name "%s" is already used by'
' another resource class.')
% name
)
return cleaned_data
class Meta:
name = _("Class Settings")
help_text = _("From here you can fill the class "
"settings and add flavors to class.")
class CreateResourceClassInfoAndFlavors(tuskar_ui.workflows.TableStep):
table_classes = (tables.FlavorTemplatesTable,)
action_class = ResourceClassInfoAndFlavorsAction
template_name = 'infrastructure/resource_management/resource_classes/'\
'_resource_class_info_and_flavors_step.html'
contributes = ("name", "service_type", "flavors_object_ids",
'max_vms')
def contribute(self, data, context):
request = self.workflow.request
if data:
context["flavors_object_ids"] =\
request.POST.getlist("flavors_object_ids")
# todo: lsmola django can't parse dictionaruy from POST
# this should be rewritten to django formset
context["max_vms"] = {}
for index, value in request.POST.items():
match = re.match(
'^(flavors_object_ids__max_vms__(.*?))$',
index)
if match:
context["max_vms"][match.groups()[1]] = value
context.update(data)
return context
def get_flavors_data(self):
try:
resource_class_id = self.workflow.context.get("resource_class_id")
if resource_class_id:
resource_class = tuskar.ResourceClass.get(
self.workflow.request,
resource_class_id)
# TODO(lsmola ugly interface, rewrite)
self._tables['flavors'].active_multi_select_values = \
resource_class.flavortemplates_ids
all_flavors = resource_class.all_flavors
else:
all_flavors = tuskar.FlavorTemplate.list(
self.workflow.request)
except Exception:
all_flavors = []
exceptions.handle(self.workflow.request,
_('Unable to retrieve resource flavors list.'))
return all_flavors
class RacksAction(workflows.Action):
class Meta:
name = _("Racks")
class CreateRacks(tuskar_ui.workflows.TableStep):
table_classes = (tables.RacksTable,)
action_class = RacksAction
contributes = ("racks_object_ids")
template_name = 'infrastructure/resource_management/'\
'resource_classes/_racks_step.html'
def contribute(self, data, context):
request = self.workflow.request
context["racks_object_ids"] =\
request.POST.getlist("racks_object_ids")
context.update(data)
return context
def get_racks_data(self):
try:
resource_class_id = self.workflow.context.get("resource_class_id")
if resource_class_id:
resource_class = tuskar.ResourceClass.get(
self.workflow.request,
resource_class_id)
# TODO(lsmola ugly interface, rewrite)
self._tables['racks'].active_multi_select_values = \
resource_class.racks_ids
racks = \
resource_class.all_racks
else:
racks = \
tuskar.Rack.list(self.workflow.request, True)
except Exception:
racks = []
exceptions.handle(self.workflow.request,
_('Unable to retrieve racks list.'))
return racks
class ResourceClassWorkflowMixin:
# FIXME active tabs coflict
# When on page with tabs, the workflow with more steps is used,
# there is a conflict of active tabs and it always shows the
# first tab after an action. So I explicitly specify to what
# tab it should redirect after action, until the coflict will
# be fixed in Horizon.
def get_index_url(self):
"""This url is used both as success and failure url"""
return "%s?tab=resource_management_tabs__resource_classes_tab" %\
urlresolvers.reverse('horizon:infrastructure:resource_management:'
'index')
def get_success_url(self):
return self.get_index_url()
def get_failure_url(self):
return self.get_index_url()
def format_status_message(self, message):
name = self.context.get('name')
return message % name
def _get_flavors(self, request, data):
flavors = []
flavor_ids = data.get('flavors_object_ids') or []
max_vms = data.get('max_vms')
resource_class_name = data['name']
for template_id in flavor_ids:
template = tuskar.FlavorTemplate.get(request, template_id)
capacities = []
for c in template.capacities:
capacities.append({'name': c.name,
'value': str(c.value),
'unit': c.unit})
# FIXME: tuskar uses resource-class-name prefix for flavors,
# e.g. m1.large, we add rc name to the template name:
flavor_name = "%s.%s" % (resource_class_name, template.name)
flavors.append({'name': flavor_name,
'max_vms': max_vms.get(template.id, None),
'capacities': capacities})
return flavors
def _add_racks(self, request, data, resource_class):
ids_to_add = data.get('racks_object_ids') or []
resource_class.set_racks(request, ids_to_add)
class CreateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow):
default_steps = (CreateResourceClassInfoAndFlavors,
CreateRacks)
slug = "create_resource_class"
name = _("Create Class")
finalize_button_name = _("Create Class")
success_message = _('Created class "%s".')
failure_message = _('Unable to create class "%s".')
def _create_resource_class_info(self, request, data):
try:
flavors = self._get_flavors(request, data)
return tuskar.ResourceClass.create(
request,
name=data['name'],
service_type=data['service_type'],
flavors=flavors)
except Exception:
redirect = self.get_failure_url()
exceptions.handle(request,
_('Unable to create resource class.'),
redirect=redirect)
return None
def handle(self, request, data):
resource_class = self._create_resource_class_info(request, data)
self._add_racks(request, data, resource_class)
return True
class UpdateResourceClassInfoAndFlavors(CreateResourceClassInfoAndFlavors):
depends_on = ("resource_class_id",)
class UpdateRacks(CreateRacks):
depends_on = ("resource_class_id",)
class UpdateResourceClass(ResourceClassWorkflowMixin, workflows.Workflow):
default_steps = (UpdateResourceClassInfoAndFlavors,
UpdateRacks)
slug = "update_resource_class"
name = _("Update Class")
finalize_button_name = _("Update Class")
success_message = _('Updated class "%s".')
failure_message = _('Unable to update class "%s".')
def _update_resource_class_info(self, request, data):
try:
flavors = self._get_flavors(request, data)
return tuskar.ResourceClass.update(
request,
data['resource_class_id'],
name=data['name'],
service_type=data['service_type'],
flavors=flavors)
except Exception:
redirect = self.get_failure_url()
exceptions.handle(request,
_('Unable to create resource class.'),
redirect=redirect)
return None
def handle(self, request, data):
resource_class = self._update_resource_class_info(request, data)
self._add_racks(request, data, resource_class)
return True
class DetailUpdateWorkflow(UpdateResourceClass):
def get_index_url(self):
"""This url is used both as success and failure url"""
url = "horizon:infrastructure:resource_management:resource_classes:"\
"detail"
return "%s?tab=resource_class_details__overview" % (
urlresolvers.reverse(url,
args=(self.context["resource_class_id"])))
class UpdateRacksWorkflow(UpdateResourceClass):
def get_index_url(self):
"""This url is used both as success and failure url"""
url = "horizon:infrastructure:resource_management:resource_classes:"\
"detail"
return "%s?tab=resource_class_details__racks" % (
urlresolvers.reverse(url,
args=(self.context["resource_class_id"])))
class UpdateFlavorsWorkflow(UpdateResourceClass):
def get_index_url(self):
"""This url is used both as success and failure url"""
url = "horizon:infrastructure:resource_management:resource_classes:"\
"detail"
return "%s?tab=resource_class_details__flavors" % (
urlresolvers.reverse(url,
args=(self.context["resource_class_id"])))