Add node count field to the role edit dialog

Change-Id: If5e16b54bd41be404334432647f3192afb982961
This commit is contained in:
Radomir Dopieralski 2015-02-19 16:22:57 +01:00
parent 18e2c8b394
commit 4a2fd4f742
5 changed files with 79 additions and 27 deletions

View File

@ -0,0 +1,11 @@
<noscript><h3>{{ step }}</h3></noscript>
<div class="row">
<div class="col-sm-8">
<div class="form form-horizontal">
{% include "horizon/common/_horizontal_fields.html" %}
</div>
</div>
<div class="col-sm-4">
{{ step.get_help_text }}
</div>
</div>

View File

@ -134,8 +134,11 @@ class RolesTest(test.BaseAdminViewTests):
images = self.glanceclient_images.list()
data = {
'name': 'controller',
'description': 'The controller node role.',
'flavor': self.novaclient_flavors.first().name,
'image': self.glanceclient_images.first().id,
'nodes': '0',
}
with contextlib.nested(

View File

@ -14,12 +14,10 @@
import json
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django import http
from django.utils.translation import ugettext_lazy as _
from django.views.generic import base
from glanceclient import exc as glance_exc
from horizon import exceptions as horizon_exceptions
from horizon import tables as horizon_tables
from horizon import utils
from horizon import workflows
@ -127,20 +125,19 @@ class DetailView(horizon_tables.DataTableView, views.RoleMixin,
return context
class UpdateView(workflows.WorkflowView):
class UpdateView(workflows.WorkflowView, views.StackMixin, views.RoleMixin):
workflow_class = role_workflows.UpdateRole
def get_initial(self):
role_id = self.kwargs['role_id']
plan = self.get_plan()
role = self.get_role()
try:
# Get initial role information
plan = api.tuskar.Plan.get_the_plan(self.request)
role = api.tuskar.Role.get(self.request, role_id)
except Exception:
horizon_exceptions.handle(self.request,
_('Unable to retrieve role details.'),
redirect=reverse_lazy(INDEX_URL))
stack = self.get_stack()
if stack:
resources = stack.resources(role=role, with_joins=True)
role_nodes = len(resources)
else:
role_nodes = 0
role_flavor = role.flavor(plan)
role_flavor = '' if role_flavor is None else role_flavor.name
@ -148,11 +145,18 @@ class UpdateView(workflows.WorkflowView):
role_image = role.image(plan)
role_image = '' if role_image is None else role_image.id
return {'role_id': role.id,
'name': role.name,
'flavor': role_flavor,
'image': role_image,
}
free_nodes = len(api.node.Node.list(self.request, associated=False,
maintenance=False))
available_nodes = role_nodes + free_nodes
return {
'role_id': role.id,
'name': role.name,
'flavor': role_flavor,
'image': role_image,
'nodes': role_nodes,
'available_nodes': available_nodes,
}
class PerformanceView(base.TemplateView, views.RoleMixin, views.StackMixin):

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.core.urlresolvers import reverse_lazy
import django.forms
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
@ -26,25 +27,28 @@ from tuskar_ui.utils import utils as tuskar_utils
class UpdateRoleInfoAction(workflows.Action):
# TODO(rdopiera) Make the name and description editable.
name = forms.CharField(
label=_("Name"),
widget=tuskar_ui.forms.LabelWidget(),
required=False,
widget=tuskar_ui.forms.StaticTextWidget
)
description = forms.CharField(
label=_("Description"),
widget=tuskar_ui.forms.LabelWidget(),
required=False,
widget=tuskar_ui.forms.StaticTextWidget
)
flavor = forms.ChoiceField(
label=_("Flavor"),
)
image = forms.ChoiceField(
label=_("Image"),
)
nodes = forms.IntegerField(
label=_("Number of Nodes"),
required=False,
initial=0,
)
class Meta(object):
name = _("Overall Settings")
@ -54,6 +58,13 @@ class UpdateRoleInfoAction(workflows.Action):
def __init__(self, request, context, *args, **kwargs):
super(UpdateRoleInfoAction, self).__init__(request, context, *args,
**kwargs)
self.available_nodes = context['available_nodes']
self.fields['nodes'].widget = tuskar_ui.forms.NumberInput(attrs={
'min': 0,
'max': self.available_nodes,
})
self.fields['nodes'].help_text = _(
"{0} nodes available").format(self.available_nodes)
if not utils.matching_deployment_mode():
del self.fields['flavor']
@ -70,6 +81,24 @@ class UpdateRoleInfoAction(workflows.Action):
choices = [(i.id, i.name) for i in images]
return [('', _('Unknown'))] + choices
def clean_nodes(self):
new_count = int(self.cleaned_data['nodes'] or 0)
if new_count > self.available_nodes:
raise django.forms.ValidationError(_(
"There are only {0} nodes available "
"for the selected flavor."
).format(self.available_nodes))
return str(new_count)
def handle(self, request, context):
return {
'name': self.cleaned_data['name'],
'description': self.cleaned_data['description'],
'flavor': self.cleaned_data.get('flavor'),
'image': self.cleaned_data['image'],
'nodes': self.cleaned_data['nodes'],
}
class UpdateRoleConfigAction(workflows.Action):
class Meta(object):
@ -92,8 +121,9 @@ class UpdateRoleConfigAction(workflows.Action):
class UpdateRoleInfo(workflows.Step):
action_class = UpdateRoleInfoAction
depends_on = ("role_id",)
contributes = ("name", "flavor", "image",)
depends_on = ("role_id", "available_nodes")
contributes = ("name", "description", "flavor", "image", "nodes")
template_name = 'infrastructure/roles/info.html'
class UpdateRoleConfig(workflows.Step):
@ -141,9 +171,10 @@ class UpdateRole(workflows.Workflow):
parameters = data['parameters']
parameters[role.image_id_parameter_name] = data['image']
parameters[role.node_count_parameter_name] = data['nodes']
if utils.matching_deployment_mode():
parameters[role.flavor_parameter_name] = data['flavor']
plan.patch(request, plan.uuid, parameters)
# success
# TODO(rdopiera) Find out how to update role's name and description.
return True

View File

@ -28,10 +28,13 @@ class ItemCountMixin(object):
class StackMixin(object):
@memoized.memoized
def get_plan(self):
return api.tuskar.Plan.get_the_plan(self.request)
@memoized.memoized
def get_stack(self):
plan = api.tuskar.Plan.get_the_plan(self.request)
return api.heat.Stack.get_by_plan(self.request, plan)
return api.heat.Stack.get_by_plan(self.request, self.get_plan())
class RoleMixin(object):