Merge "[Sahara] Move node processes selection to own tab"

This commit is contained in:
Jenkins 2015-09-03 11:38:40 +00:00 committed by Gerrit Code Review
commit 8956fbcd32
3 changed files with 146 additions and 49 deletions

View File

@ -21,6 +21,8 @@ from openstack_dashboard import api as dash_api
from openstack_dashboard.contrib.sahara import api
from openstack_dashboard.contrib.sahara.content.data_processing.utils \
import workflow_helpers
from openstack_dashboard.contrib.sahara.content.data_processing.\
nodegroup_templates.workflows import create as create_workflow
from openstack_dashboard.test import helpers as test
@ -35,6 +37,37 @@ CREATE_URL = reverse(
class DataProcessingNodeGroupTests(test.TestCase):
def _setup_copy_test(self):
ngt = self.nodegroup_templates.first()
configs = self.plugins_configs.first()
dash_api.cinder.extension_supported(IsA(http.HttpRequest),
'AvailabilityZones') \
.AndReturn(True)
dash_api.cinder.availability_zone_list(IsA(http.HttpRequest))\
.AndReturn(self.availability_zones.list())
dash_api.cinder.volume_type_list(IsA(http.HttpRequest))\
.AndReturn([])
api.sahara.nodegroup_template_get(IsA(http.HttpRequest),
ngt.id) \
.AndReturn(ngt)
api.sahara.plugin_get_version_details(IsA(http.HttpRequest),
ngt.plugin_name,
ngt.hadoop_version) \
.MultipleTimes().AndReturn(configs)
dash_api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
.AndReturn([])
dash_api.network.security_group_list(IsA(http.HttpRequest)) \
.AndReturn([])
self.mox.ReplayAll()
url = reverse(
'horizon:project:data_processing.nodegroup_templates:copy',
args=[ngt.id])
res = self.client.get(url)
return ngt, configs, res
@test.create_stubs({api.sahara: ('nodegroup_template_list',)})
def test_index(self):
api.sahara.nodegroup_template_list(IsA(http.HttpRequest), {}) \
@ -90,33 +123,7 @@ class DataProcessingNodeGroupTests(test.TestCase):
'availability_zone_list',
'volume_type_list')})
def test_copy(self):
ngt = self.nodegroup_templates.first()
configs = self.plugins_configs.first()
dash_api.cinder.extension_supported(IsA(http.HttpRequest),
'AvailabilityZones') \
.AndReturn(True)
dash_api.cinder.availability_zone_list(IsA(http.HttpRequest))\
.AndReturn(self.availability_zones.list())
dash_api.cinder.volume_type_list(IsA(http.HttpRequest))\
.AndReturn([])
api.sahara.nodegroup_template_get(IsA(http.HttpRequest),
ngt.id) \
.AndReturn(ngt)
api.sahara.plugin_get_version_details(IsA(http.HttpRequest),
ngt.plugin_name,
ngt.hadoop_version) \
.MultipleTimes().AndReturn(configs)
dash_api.network.floating_ip_pools_list(IsA(http.HttpRequest)) \
.AndReturn([])
dash_api.network.security_group_list(IsA(http.HttpRequest)) \
.AndReturn([])
self.mox.ReplayAll()
url = reverse(
'horizon:project:data_processing.nodegroup_templates:copy',
args=[ngt.id])
res = self.client.get(url)
ngt, configs, res = self._setup_copy_test()
workflow = res.context['workflow']
step = workflow.get_step("generalconfigaction")
self.assertEqual(step.action['nodegroup_name'].field.initial,
@ -295,3 +302,23 @@ class DataProcessingNodeGroupTests(test.TestCase):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
self.assertMessageCount(success=1)
@test.create_stubs({api.sahara: ('nodegroup_template_get',
'plugin_get_version_details'),
dash_api.network: ('floating_ip_pools_list',
'security_group_list'),
dash_api.cinder: ('extension_supported',
'availability_zone_list',
'volume_type_list')})
def test_workflow_steps(self):
# since the copy workflow is the child of create workflow
# it's better to test create workflow through copy workflow
ngt, configs, res = self._setup_copy_test()
workflow = res.context['workflow']
expected_instances = [
create_workflow.GeneralConfig,
create_workflow.SelectNodeProcesses,
create_workflow.SecurityConfig
]
for expected, observed in zip(expected_instances, workflow.steps):
self.assertIsInstance(observed, expected)

View File

@ -46,12 +46,15 @@ class CopyNodegroupTemplate(create_flow.ConfigureNodegroupTemplate):
**kwargs)
g_fields = None
snp_fields = None
s_fields = None
for step in self.steps:
if isinstance(step, create_flow.GeneralConfig):
g_fields = step.action.fields
if isinstance(step, create_flow.SecurityConfig):
s_fields = step.action.fields
if isinstance(step, create_flow.SelectNodeProcesses):
snp_fields = step.action.fields
g_fields["nodegroup_name"].initial = self.template.name + "-copy"
g_fields["description"].initial = self.template.description
@ -109,4 +112,4 @@ class CopyNodegroupTemplate(create_flow.ConfigureNodegroupTemplate):
_service = service
break
processes_dict["%s:%s" % (_service, process)] = process
g_fields["processes"].initial = processes_dict
snp_fields["processes"].initial = processes_dict

View File

@ -11,8 +11,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import itertools
import logging
import uuid
from django.utils import encoding
from django.utils import html
from django.utils import safestring
from django.utils.translation import ugettext_lazy as _
from saharaclient.api import base as api_base
@ -129,17 +134,6 @@ class GeneralConfigAction(workflows.Action):
plugin, hadoop_version = (
workflow_helpers.get_plugin_and_hadoop_version(request))
process_choices = []
try:
version_details = saharaclient.plugin_get_version_details(
request, plugin, hadoop_version)
for service, processes in version_details.node_processes.items():
for process in processes:
process_choices.append(
(str(service) + ":" + str(process), process))
except Exception:
exceptions.handle(request,
_("Unable to generate process choices."))
if not saharaclient.SAHARA_AUTO_IP_ALLOCATION_ENABLED:
pools = network.floating_ip_pools_list(request)
@ -169,12 +163,6 @@ class GeneralConfigAction(workflows.Action):
"access other cluster instances."),
required=False)
self.fields["processes"] = forms.MultipleChoiceField(
label=_("Processes"),
widget=forms.CheckboxSelectMultiple(),
help_text=_("Processes to be launched in node group"),
choices=process_choices)
self.fields["plugin_name"] = forms.CharField(
widget=forms.HiddenInput(),
initial=plugin
@ -271,6 +259,79 @@ class SecurityConfigAction(workflows.Action):
help_text = _("Control access to instances of the node group.")
class CheckboxSelectMultiple(forms.CheckboxSelectMultiple):
def render(self, name, value, attrs=None, choices=()):
if value is None:
value = []
has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name)
output = []
initial_service = uuid.uuid4()
str_values = set([encoding.force_text(v) for v in value])
for i, (option_value, option_label) in enumerate(
itertools.chain(self.choices, choices)):
current_service = option_value.split(':')[0]
if current_service != initial_service:
if i > 0:
output.append("</ul>")
service_description = _("%s processes: ") % current_service
service_description = html.conditional_escape(
encoding.force_text(service_description))
output.append(
"<label>{0}</label>".format(service_description))
initial_service = current_service
output.append(encoding.force_text("<ul>"))
if has_id:
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
label_for = ' for="%s"' % final_attrs['id']
else:
label_for = ''
cb = forms.CheckboxInput(
final_attrs, check_test=lambda value: value in str_values)
option_value = encoding.force_text(option_value)
rendered_cb = cb.render(name, option_value)
option_label = html.conditional_escape(
encoding.force_text(option_label))
output.append(
'<li><label{0}>{1} {2}</label></li>'.format(
label_for, rendered_cb, option_label))
output.append('</ul>')
return safestring.mark_safe('\n'.join(output))
class SelectNodeProcessesAction(workflows.Action):
def __init__(self, request, *args, **kwargs):
super(SelectNodeProcessesAction, self).__init__(
request, *args, **kwargs)
plugin, hadoop_version = (
workflow_helpers.get_plugin_and_hadoop_version(request))
node_processes = {}
try:
version_details = saharaclient.plugin_get_version_details(
request, plugin, hadoop_version)
node_processes = version_details.node_processes
except Exception:
exceptions.handle(request,
_("Unable to generate process choices."))
process_choices = []
for service, processes in node_processes.items():
for process in processes:
choice_label = str(service) + ":" + str(process)
process_choices.append((choice_label, process))
self.fields["processes"] = forms.MultipleChoiceField(
label=_("Select Node Group Processes"),
widget=CheckboxSelectMultiple(),
choices=process_choices,
required=True)
class Meta(object):
name = _("Node Processes")
help_text = _("Select node processes for the node group")
class GeneralConfig(workflows.Step):
action_class = GeneralConfigAction
contributes = ("general_nodegroup_name", )
@ -280,9 +341,6 @@ class GeneralConfig(workflows.Step):
if "hidden" in k:
continue
context["general_" + k] = v if v != "None" else None
post = self.workflow.request.POST
context['general_processes'] = post.getlist("processes")
return context
@ -291,6 +349,15 @@ class SecurityConfig(workflows.Step):
contributes = ("security_autogroup", "security_groups")
class SelectNodeProcesses(workflows.Step):
action_class = SelectNodeProcessesAction
def contribute(self, data, context):
post = self.workflow.request.POST
context['general_processes'] = post.getlist('processes')
return context
class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
workflow_helpers.StatusFormatMixin):
slug = "configure_nodegroup_template"
@ -299,7 +366,7 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
success_message = _("Created Node Group Template %s")
name_property = "general_nodegroup_name"
success_url = "horizon:project:data_processing.nodegroup_templates:index"
default_steps = (GeneralConfig, SecurityConfig)
default_steps = (GeneralConfig, SelectNodeProcesses, SecurityConfig)
def __init__(self, request, context_seed, entry_point, *args, **kwargs):
hlps = helpers.Helpers(request)