diff options
Diffstat (limited to 'tuskar_ui/infrastructure/roles')
-rw-r--r-- | tuskar_ui/infrastructure/roles/__init__.py | 0 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/panel.py | 26 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/tables.py | 66 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/templates/roles/config.html | 24 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/templates/roles/detail.html | 39 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/templates/roles/index.html | 16 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/templates/roles/info.html | 11 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/tests.py | 166 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/urls.py | 29 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/views.py | 191 | ||||
-rw-r--r-- | tuskar_ui/infrastructure/roles/workflows.py | 180 |
11 files changed, 0 insertions, 748 deletions
diff --git a/tuskar_ui/infrastructure/roles/__init__.py b/tuskar_ui/infrastructure/roles/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/tuskar_ui/infrastructure/roles/__init__.py +++ /dev/null diff --git a/tuskar_ui/infrastructure/roles/panel.py b/tuskar_ui/infrastructure/roles/panel.py deleted file mode 100644 index 3a2041f6..00000000 --- a/tuskar_ui/infrastructure/roles/panel.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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.utils.translation import ugettext_lazy as _ -import horizon - -from tuskar_ui.infrastructure import dashboard - - -class Roles(horizon.Panel): - name = _("Deployment Roles") - slug = "roles" - - -dashboard.Infrastructure.register(Roles) diff --git a/tuskar_ui/infrastructure/roles/tables.py b/tuskar_ui/infrastructure/roles/tables.py deleted file mode 100644 index 8da446ca..00000000 --- a/tuskar_ui/infrastructure/roles/tables.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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.utils.translation import ugettext_lazy as _ -from horizon import tables - -from tuskar_ui import api -from tuskar_ui.infrastructure.nodes import tables as nodes_tables - - -class UpdateRole(tables.LinkAction): - name = "update" - verbose_name = _("Edit Role") - url = "horizon:infrastructure:roles:update" - classes = ("ajax-modal",) - icon = "pencil" - - def allowed(self, request, datum): - plan = api.tuskar.Plan.get_the_plan(request) - - if datum.id in [role.id for role in plan.role_list]: - return True - return False - - -class RolesTable(tables.DataTable): - - name = tables.Column('name', - link="horizon:infrastructure:roles:detail", - verbose_name=_("Role")) - flavor = tables.Column('flavor', - verbose_name=_("Flavor")) - image = tables.Column('image', - verbose_name=_("Image")) - - def get_object_id(self, datum): - return datum.uuid - - class Meta(object): - name = "roles" - verbose_name = _("Deployment Roles") - table_actions = () - row_actions = (UpdateRole,) - template = "horizon/common/_enhanced_data_table.html" - - -class NodeTable(nodes_tables.ProvisionedNodesTable): - - class Meta(object): - name = "nodetable" - verbose_name = _("Nodes") - hidden_title = False - table_actions = () - row_actions = () - template = "horizon/common/_enhanced_data_table.html" diff --git a/tuskar_ui/infrastructure/roles/templates/roles/config.html b/tuskar_ui/infrastructure/roles/templates/roles/config.html deleted file mode 100644 index 854871b4..00000000 --- a/tuskar_ui/infrastructure/roles/templates/roles/config.html +++ /dev/null @@ -1,24 +0,0 @@ -<noscript><h3>{{ step }}</h3></noscript> -<div class="row"> - <div class="col-sm-12"> - <div class="form form-horizontal" id="role-config-form"> - {% include "horizon/common/_horizontal_fields.html" %} - </div> - </div> -</div> -<script type="text/javascript"> - (window.$ || window.addHorizonLoadEvent)(function () { - $(document).tooltip('hide'); // Prevent Horizon from adding tooltip. - $('#role-config-form a.help-icon').click(function () { - return false; - }).popover({ - trigger: 'focus', - placement: 'right', - container: '#role-config-form' - }); - $('#role-config-form a.password-button').popover({ - trigger: 'click', - placement: 'right' - }); - }); -</script> diff --git a/tuskar_ui/infrastructure/roles/templates/roles/detail.html b/tuskar_ui/infrastructure/roles/templates/roles/detail.html deleted file mode 100644 index 0839ca0d..00000000 --- a/tuskar_ui/infrastructure/roles/templates/roles/detail.html +++ /dev/null @@ -1,39 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% load url from future %} -{% block title %}{% trans 'Role' %}: {{ role.name }}{% endblock %} - -{% block page_header %} - {% include 'horizon/common/_domain_page_header.html' with title=_('Deployment Role: ')|add:role.name %} -{% endblock page_header %} - -{% block main %} - -<div class="row"> - <div class="col-md-4"> - <h3>{% trans "Properties" %}</h3> - <h4 class="info">{% blocktrans count counter=nodes|length %}{{ counter }} instance{% plural %}{{ counter }} instances{% endblocktrans %}</h4> - <dl class="dl-horizontal dl-horizontal-left"> - <dt>{% trans 'Flavor' %}</dt> - {% if flavor %} - <dd><em>{{ flavor.name }}</em> {{ flavor.get_keys.cpu_arch }} | {{ flavor.vcpus }} {% trans "CPU" %} | {{ flavor.ram }} {% trans "MB RAM" %} | {{ flavor.disk }} {% trans "GB HDD" %}</dd> - {% else %} - <dd>{% trans 'No flavor associated' %}</dd> - {% endif %} - <dt>{% trans 'Image' %}</dt> - {% if image %} - <dd>{{ image.name }}</dd> - {% else %} - <dd>{% trans 'No image associated' %}</dd> - {% endif %} - </dl> - </div> - <div class="col-md-8"> - <h3>{% trans "Performance & Metrics" %}</h3> - {% url 'horizon:infrastructure:roles:performance' role.uuid as node_perf_url %} - {% include "infrastructure/_performance_chart_box.html" with meter_conf=meter_conf node_perf_url=node_perf_url col_size=4 %} - </div> -</div> - -{{ table.render }} -{% endblock %} diff --git a/tuskar_ui/infrastructure/roles/templates/roles/index.html b/tuskar_ui/infrastructure/roles/templates/roles/index.html deleted file mode 100644 index b17ae230..00000000 --- a/tuskar_ui/infrastructure/roles/templates/roles/index.html +++ /dev/null @@ -1,16 +0,0 @@ -{% extends 'infrastructure/base.html' %} -{% load i18n %} -{% block title %}{% trans 'Deployment Roles' %}{% endblock %} - -{% block page_header %} - {% include 'horizon/common/_items_count_domain_page_header.html' with title=_('Deployment Roles') %} -{% endblock page_header %} - -{% block main %} -<div class="row"> - <div class="col-xs-12"> - {{ table.render }} - </div> -</div> - -{% endblock %} diff --git a/tuskar_ui/infrastructure/roles/templates/roles/info.html b/tuskar_ui/infrastructure/roles/templates/roles/info.html deleted file mode 100644 index 2909bd1c..00000000 --- a/tuskar_ui/infrastructure/roles/templates/roles/info.html +++ /dev/null @@ -1,11 +0,0 @@ -<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> diff --git a/tuskar_ui/infrastructure/roles/tests.py b/tuskar_ui/infrastructure/roles/tests.py deleted file mode 100644 index d9ee2057..00000000 --- a/tuskar_ui/infrastructure/roles/tests.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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. - -import contextlib - -from django.core import urlresolvers -from openstack_dashboard.test.test_data import utils -from mock import patch, call # noqa - -from tuskar_ui import api -from tuskar_ui.test import helpers as test -from tuskar_ui.test.test_data import flavor_data -from tuskar_ui.test.test_data import heat_data -from tuskar_ui.test.test_data import node_data -from tuskar_ui.test.test_data import tuskar_data - - -INDEX_URL = urlresolvers.reverse( - 'horizon:infrastructure:roles:index') -DETAIL_URL = urlresolvers.reverse( - 'horizon:infrastructure:roles:detail', args=('role-1',)) -UPDATE_URL = urlresolvers.reverse( - 'horizon:infrastructure:roles:update', args=('role-1',)) - -TEST_DATA = utils.TestDataContainer() -flavor_data.data(TEST_DATA) -node_data.data(TEST_DATA) -heat_data.data(TEST_DATA) -tuskar_data.data(TEST_DATA) - - -class RolesTest(test.BaseAdminViewTests): - - def test_index_get(self): - roles = [api.tuskar.Role(role) - for role in self.tuskarclient_roles.list()] - plans = [api.tuskar.Plan(plan) - for plan in self.tuskarclient_plans.list()] - flavor = self.novaclient_flavors.first() - images = self.glanceclient_images.list() - - with contextlib.nested( - patch('tuskar_ui.api.tuskar.Plan.list', - return_value=plans), - patch('tuskar_ui.api.tuskar.Role.list', - return_value=roles), - patch('openstack_dashboard.api.glance.image_list_detailed', - return_value=[images]), - patch('tuskar_ui.api.flavor.Flavor.get_by_name', - return_value=flavor)): - res = self.client.get(INDEX_URL) - - self.assertTemplateUsed(res, 'infrastructure/roles/index.html') - - def test_detail_get(self): - roles = [api.tuskar.Role(role) - for role in self.tuskarclient_roles.list()] - plans = [api.tuskar.Plan(plan) - for plan in self.tuskarclient_plans.list()] - flavor = self.novaclient_flavors.first() - images = self.glanceclient_images.list() - stack = api.heat.Stack(TEST_DATA.heatclient_stacks.first()) - - with contextlib.nested( - patch('tuskar_ui.api.tuskar.Role.list', - return_value=roles), - patch('tuskar_ui.api.heat.Stack.get_by_plan', - return_value=stack), - patch('tuskar_ui.api.heat.Stack.events', - return_value=[]), - patch('tuskar_ui.api.heat.Stack.resources', - return_value=[]), - patch('tuskar_ui.api.tuskar.Plan.list', - return_value=plans), - patch('openstack_dashboard.api.glance.image_list_detailed', - return_value=[images]), - patch('tuskar_ui.api.flavor.Flavor.get_by_name', - return_value=flavor)): - res = self.client.get(DETAIL_URL) - - self.assertTemplateUsed( - res, 'infrastructure/roles/detail.html') - - def test_update_get(self): - roles = [api.tuskar.Role(role) - for role in self.tuskarclient_roles.list()] - plans = [api.tuskar.Plan(plan) - for plan in self.tuskarclient_plans.list()] - flavors = self.novaclient_flavors.list() - images = self.glanceclient_images.list() - stack = api.heat.Stack(TEST_DATA.heatclient_stacks.first()) - - with contextlib.nested( - patch('tuskar_ui.api.tuskar.Role.list', - return_value=roles), - patch('tuskar_ui.api.heat.Stack.get_by_plan', - return_value=stack), - patch('tuskar_ui.api.heat.Stack.events', - return_value=[]), - patch('tuskar_ui.api.heat.Stack.resources', - return_value=[]), - patch('tuskar_ui.api.tuskar.Plan.list', - return_value=plans), - patch('openstack_dashboard.api.glance.image_get', - return_value=images[0]), - patch('tuskar_ui.api.flavor.Flavor.list', - return_value=flavors), - patch('openstack_dashboard.api.glance.image_list_detailed', - return_value=[images])): - - res = self.client.get(UPDATE_URL) - - # Check that the expected fields are in the form: - self.assertIn('id="id_flavor" name="flavor"', res.content) - self.assertIn('id="id_image" name="image"', res.content) - self.assertIn('flavor-1', res.content) - self.assertIn('flavor-2', res.content) - - def test_update_post(self): - plan = api.tuskar.Plan(self.tuskarclient_plans.first()) - role = api.tuskar.Role(self.tuskarclient_roles.first()) - flavors = self.novaclient_flavors.list() - images = self.glanceclient_images.list() - - data = { - 'name': 'controller', - 'description': 'The controller node role.', - 'flavor': self.novaclient_flavors.first().name, - 'image': self.glanceclient_images.first().name, - 'nodes': '0', - } - - with contextlib.nested( - patch('tuskar_ui.api.flavor.Flavor.list', - return_value=flavors), - patch('openstack_dashboard.api.glance.image_list_detailed', - return_value=[images]), - patch('openstack_dashboard.api.glance.image_get', - return_value=images[0]), - patch('tuskar_ui.api.tuskar.Role.get', - return_value=role), - patch('tuskar_ui.api.tuskar.Plan.patch', - return_value=plan), - patch('tuskar_ui.api.tuskar.Plan.get_the_plan', - return_value=plan)) as mocks: - - mock_patch = mocks[4] - res = self.client.post(UPDATE_URL, data) - self.assertRedirectsNoFollow(res, INDEX_URL) - - self.assertEqual(len(mock_patch.call_args_list), 1) - args = mock_patch.call_args_list[0][0] - self.assertEqual(args[1], plan.id) - self.assertEqual(args[2]['Controller-1::Flavor'], u'flavor-1') - self.assertEqual(args[2]['Controller-1::Image'], u'overcloud-full') diff --git a/tuskar_ui/infrastructure/roles/urls.py b/tuskar_ui/infrastructure/roles/urls.py deleted file mode 100644 index 9dfdb778..00000000 --- a/tuskar_ui/infrastructure/roles/urls.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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.conf import urls - -from tuskar_ui.infrastructure.roles import views - - -urlpatterns = urls.patterns( - '', - urls.url(r'^$', views.IndexView.as_view(), name='index'), - urls.url(r'^(?P<role_id>[^/]+)/$', views.DetailView.as_view(), - name='detail'), - urls.url(r'^(?P<role_id>[^/]+)/edit$', views.UpdateView.as_view(), - name='update'), - urls.url(r'^(?P<role_id>[^/]+)/performance/$', - views.PerformanceView.as_view(), name='performance'), -) diff --git a/tuskar_ui/infrastructure/roles/views.py b/tuskar_ui/infrastructure/roles/views.py deleted file mode 100644 index b5cb5801..00000000 --- a/tuskar_ui/infrastructure/roles/views.py +++ /dev/null @@ -1,191 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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. -import json - -from django.core.urlresolvers import reverse -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 tables as horizon_tables -from horizon import utils -from horizon import workflows -from openstack_dashboard.api import base as api_base - -from tuskar_ui import api -from tuskar_ui.infrastructure.roles import tables -from tuskar_ui.infrastructure.roles import workflows as role_workflows -from tuskar_ui.infrastructure import views -from tuskar_ui.utils import metering as metering_utils - - -INDEX_URL = 'horizon:infrastructure:roles:index' - - -class IndexView(views.ItemCountMixin, horizon_tables.DataTableView): - table_class = tables.RolesTable - template_name = "infrastructure/roles/index.html" - - @utils.memoized.memoized - def get_data(self): - roles = api.tuskar.Role.list(self.request) - plan = api.tuskar.Plan.get_the_plan(self.request) - for role in roles: - role_flavor = role.flavor(plan) - try: - role_image = role.image(plan) - except glance_exc.HTTPNotFound: - # Glance returns a 404 if the image doesn't exist - role_image = None - if role_flavor: - role.flavor = role_flavor.name - else: - role.flavor = _('Unknown') - if role_image: - role.image = role_image.name - else: - role.image = _('Unknown') - - return roles - - -class DetailView(horizon_tables.DataTableView, views.RoleMixin, - views.StackMixin): - table_class = tables.NodeTable - template_name = 'infrastructure/roles/detail.html' - - @utils.memoized.memoized - def _get_nodes(self, stack, role): - resources = stack.resources(role=role, with_joins=True) - nodes = [r.node for r in resources] - for node in nodes: - try: - resource = api.heat.Resource.get_by_node(self.request, node) - except LookupError: - node.role_name = '-' - else: - node.role_name = resource.role.name - node.role_id = resource.role.id - node.stack_id = resource.stack.id - - return nodes - - def get_data(self): - redirect = reverse(INDEX_URL) - stack = self.get_stack() - if stack: - role = self.get_role(redirect) - return self._get_nodes(stack, role) - return [] - - def get_context_data(self, **kwargs): - context = super(DetailView, self).get_context_data(**kwargs) - redirect = reverse(INDEX_URL) - - plan = api.tuskar.Plan.get_the_plan(self.request) - stack = self.get_stack() - role = self.get_role(redirect) - - context['role'] = role - if stack: - context['nodes'] = self._get_nodes(stack, role) - else: - context['nodes'] = [] - context['flavor'] = role.flavor(plan) - context['image'] = role.image(plan) - - if stack: - if api_base.is_service_enabled(self.request, 'metering'): - # Meter configuration in the following format: - # (meter label, url part, barchart (True/False)) - context['meter_conf'] = ( - (_('System Load'), - metering_utils.url_part('hardware.cpu.load.1min', False), - None), - (_('CPU Utilization'), - metering_utils.url_part('hardware.system_stats.cpu.util', - True), - '100'), - (_('Swap Utilization'), - metering_utils.url_part('hardware.memory.swap.util', - True), - '100'), - ) - return context - - -class UpdateView(workflows.WorkflowView, views.StackMixin, views.RoleMixin): - workflow_class = role_workflows.UpdateRole - - def get_initial(self): - plan = self.get_plan() - role = self.get_role() - - 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 - - role_image = role.image(plan) - role_image = '' if role_image is None else role_image.name - - 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): - def get(self, request, *args, **kwargs): - meter = request.GET.get('meter') - date_options = request.GET.get('date_options') - date_from = request.GET.get('date_from') - date_to = request.GET.get('date_to') - stats_attr = request.GET.get('stats_attr', 'avg') - barchart = bool(request.GET.get('barchart')) - - role = self.get_role() - stack = self.get_stack() - instances = stack.resources(role=role, with_joins=True) - - if instances: - instance_uuids = [i.physical_resource_id for i in instances] - json_output = metering_utils.get_nodes_stats( - request=request, - node_uuid=None, - instance_uuids=instance_uuids, - meter=meter, - date_options=date_options, - date_from=date_from, - date_to=date_to, - stats_attr=stats_attr, - barchart=barchart) - else: - json_output = None - - return http.HttpResponse(json.dumps(json_output), - content_type='application/json') diff --git a/tuskar_ui/infrastructure/roles/workflows.py b/tuskar_ui/infrastructure/roles/workflows.py deleted file mode 100644 index b9786112..00000000 --- a/tuskar_ui/infrastructure/roles/workflows.py +++ /dev/null @@ -1,180 +0,0 @@ -# -*- coding: utf8 -*- -# -# 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.urlresolvers import reverse_lazy -import django.forms -from django.utils.translation import ugettext_lazy as _ -from horizon import exceptions -from horizon import forms -from horizon import workflows -from openstack_dashboard.api import glance - -from tuskar_ui import api -import tuskar_ui.forms -from tuskar_ui.infrastructure.flavors import utils -from tuskar_ui.infrastructure.parameters import forms as parameters_forms -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"), - required=False, - widget=tuskar_ui.forms.StaticTextWidget - ) - description = forms.CharField( - label=_("Description"), - 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") - slug = 'update_role_info' - help_text = _("Edit the role details.") - - 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'] - - def populate_flavor_choices(self, request, context): - flavors = api.flavor.Flavor.list(self.request) - choices = [(f.name, f.name) for f in flavors] - return [('', _('Unknown'))] + choices - - def populate_image_choices(self, request, context): - images = glance.image_list_detailed(self.request)[0] - images = [image for image in images - if tuskar_utils.check_image_type(image, - 'overcloud provisioning')] - choices = [(i.name, 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): - name = _("Service Configuration") - slug = 'update_role_config' - help_text = _("Edit the role's services configuration.") - - def __init__(self, request, context, *args, **kwargs): - super(UpdateRoleConfigAction, self).__init__(request, context, - *args, **kwargs) - self.fields.update( - parameters_forms.parameter_fields( - request, - prefix='%s-1::' % context['name']), - ) - - def handle(self, request, context): - return {'parameters': self.cleaned_data} - - -class UpdateRoleInfo(workflows.Step): - action_class = UpdateRoleInfoAction - depends_on = ("role_id", "available_nodes") - contributes = ("name", "description", "flavor", "image", "nodes") - template_name = 'infrastructure/roles/info.html' - - -class UpdateRoleConfig(workflows.Step): - action_class = UpdateRoleConfigAction - depends_on = ("role_id", "name") - contributes = ("parameters",) - template_name = 'infrastructure/roles/config.html' - - -class UpdateRole(workflows.Workflow): - slug = "update_role" - finalize_button_name = _("Save") - success_message = _('Modified role "%s".') - failure_message = _('Unable to modify role "%s".') - index_url = "horizon:infrastructure:roles:index" - default_steps = ( - UpdateRoleInfo, - UpdateRoleConfig, - ) - success_url = reverse_lazy( - 'horizon:infrastructure:roles:index') - - def name(self): - # Use context_seed here, as context['name'] returns empty - # as it's one of the fields. - return _('Edit Role "%s"') % self.context_seed['name'] - - def format_status_message(self, message): - # Use context_seed here, as context['name'] returns empty - # as it's one of the fields. - return message % self.context_seed['name'] - - def handle(self, request, data): - # save it! - role_id = data['role_id'] - 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: - exceptions.handle( - self.request, - _('Unable to retrieve role details.'), - redirect=reverse_lazy(self.index_url)) - - parameters = data['parameters'] - parameters[role.image_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) - # TODO(rdopiera) Find out how to update role's name and description. - return True |