Add node count field to the role edit dialog
Change-Id: If5e16b54bd41be404334432647f3192afb982961
This commit is contained in:
parent
18e2c8b394
commit
4a2fd4f742
11
tuskar_ui/infrastructure/roles/templates/roles/info.html
Normal file
11
tuskar_ui/infrastructure/roles/templates/roles/info.html
Normal 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>
|
@ -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(
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user