Merge "Add import of node group templates"
This commit is contained in:
commit
bd9df45a36
|
@ -166,7 +166,8 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version,
|
|||
use_autoconfig=None,
|
||||
shares=None,
|
||||
is_public=None,
|
||||
is_protected=None):
|
||||
is_protected=None,
|
||||
volume_mount_prefix=None):
|
||||
return client(request).node_group_templates.create(
|
||||
name=name,
|
||||
plugin_name=plugin_name,
|
||||
|
@ -189,7 +190,8 @@ def nodegroup_template_create(request, name, plugin_name, hadoop_version,
|
|||
use_autoconfig=use_autoconfig,
|
||||
shares=shares,
|
||||
is_public=is_public,
|
||||
is_protected=is_protected)
|
||||
is_protected=is_protected,
|
||||
volume_mount_prefix=volume_mount_prefix)
|
||||
|
||||
|
||||
def nodegroup_template_list(request, search_opts=None,
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
# 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 exceptions
|
||||
from horizon import forms
|
||||
from openstack_dashboard.api import neutron
|
||||
from openstack_dashboard.dashboards.project.instances \
|
||||
import utils as nova_utils
|
||||
from oslo_serialization import jsonutils as json
|
||||
from saharaclient.api import base as api_base
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
BASE_IMAGE_URL = "horizon:project:data_processing.clusters:register"
|
||||
|
||||
|
||||
class ImportNodegroupTemplateFileForm(forms.SelfHandlingForm):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Import Node Group Template")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.next_view = kwargs.pop('next_view')
|
||||
super(ImportNodegroupTemplateFileForm, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
template_upload = forms.FileField(
|
||||
label=_('Template File'),
|
||||
required=True)
|
||||
|
||||
def handle(self, request, data):
|
||||
kwargs = {'template_upload': data['template_upload']}
|
||||
request.method = 'GET'
|
||||
return self.next_view.as_view()(request, **kwargs)
|
||||
|
||||
|
||||
class ImportNodegroupTemplateDetailsForm(forms.SelfHandlingForm):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Import Node Group Template")
|
||||
|
||||
template = forms.CharField(
|
||||
widget=forms.widgets.HiddenInput)
|
||||
|
||||
name = forms.CharField(label=_("Name"),
|
||||
required=False,
|
||||
help_text=_("Name must be provided "
|
||||
"either here or in the template. If "
|
||||
"provided in both places, this one "
|
||||
"will be used."))
|
||||
|
||||
security_groups = forms.MultipleChoiceField(
|
||||
label=_("Security Groups"),
|
||||
widget=forms.CheckboxSelectMultiple(),
|
||||
help_text=_("Launch instances in these security groups. "
|
||||
"Auto security group will be determined by the "
|
||||
"value present in the imported template."),
|
||||
required=False)
|
||||
|
||||
floating_ip_pool = forms.ChoiceField(
|
||||
label=_("Floating IP Pool"),
|
||||
required=False)
|
||||
|
||||
flavor = forms.ChoiceField(label=_("Openstack Flavor"))
|
||||
|
||||
image_id = forms.DynamicChoiceField(label=_("Base Image"),
|
||||
add_item_link=BASE_IMAGE_URL)
|
||||
|
||||
def _populate_image_choices(self, request, plugin, hadoop_version):
|
||||
all_images = saharaclient.image_list(request)
|
||||
details = saharaclient.plugin_get_version_details(request,
|
||||
plugin,
|
||||
hadoop_version)
|
||||
return [(image.id, image.name) for image in all_images
|
||||
if (set(details.required_image_tags).
|
||||
issubset(set(image.tags)))]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
try:
|
||||
request = args[0]
|
||||
template_string = ""
|
||||
|
||||
if "template_upload" in kwargs:
|
||||
template_upload = kwargs.pop('template_upload')
|
||||
super(ImportNodegroupTemplateDetailsForm, self).__init__(
|
||||
*args, **kwargs)
|
||||
|
||||
template_string = template_upload.read()
|
||||
self.fields["template"].initial = template_string
|
||||
|
||||
else:
|
||||
super(ImportNodegroupTemplateDetailsForm, self).__init__(
|
||||
*args, **kwargs)
|
||||
template_string = self.data["template"]
|
||||
|
||||
template_json = json.loads(template_string)
|
||||
template_json = template_json["node_group_template"]
|
||||
|
||||
security_group_list = neutron.security_group_list(request)
|
||||
security_group_choices = \
|
||||
[(sg.id, sg.name) for sg in security_group_list]
|
||||
self.fields["security_groups"].choices = security_group_choices
|
||||
|
||||
pools = neutron.floating_ip_pools_list(request)
|
||||
pool_choices = [(pool.id, pool.name) for pool in pools]
|
||||
pool_choices.insert(0, (None, "Do not assign floating IPs"))
|
||||
self.fields["floating_ip_pool"].choices = pool_choices
|
||||
|
||||
flavors = nova_utils.flavor_list(request)
|
||||
if flavors:
|
||||
self.fields["flavor"].choices = nova_utils.sort_flavor_list(
|
||||
request, flavors)
|
||||
else:
|
||||
self.fields["flavor"].choices = []
|
||||
|
||||
self.fields["image_id"].choices = \
|
||||
self._populate_image_choices(request,
|
||||
template_json["plugin_name"],
|
||||
template_json["hadoop_version"])
|
||||
except (ValueError, KeyError):
|
||||
raise exceptions.BadRequest(_("Could not parse template"))
|
||||
except Exception:
|
||||
exceptions.handle(request)
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
template = data["template"]
|
||||
template = json.loads(template)
|
||||
template = template["node_group_template"]
|
||||
|
||||
if not data["name"] and "name" not in template.keys():
|
||||
return False
|
||||
if data["name"]:
|
||||
template["name"] = data["name"]
|
||||
|
||||
template["security_groups"] = data["security_groups"]
|
||||
template["floating_ip_pool"] = data["floating_ip_pool"]
|
||||
template["flavor_id"] = data["flavor"]
|
||||
template["image_id"] = data["image_id"]
|
||||
|
||||
saharaclient.nodegroup_template_create(request, **template)
|
||||
return True
|
||||
except api_base.APIException as e:
|
||||
self.error_description = str(e)
|
||||
return False
|
||||
except Exception as e:
|
||||
if isinstance(e, TypeError):
|
||||
raise exceptions.BadRequest(
|
||||
_("Template JSON contained invalid key"))
|
||||
else:
|
||||
raise exceptions.BadRequest(_("Could not parse template"))
|
|
@ -43,6 +43,15 @@ class CreateNodegroupTemplate(tables.LinkAction):
|
|||
icon = "plus"
|
||||
|
||||
|
||||
class ImportNodegroupTemplate(tables.LinkAction):
|
||||
name = "import"
|
||||
verbose_name = _("Import Template")
|
||||
url = ("horizon:project:data_processing.clusters:"
|
||||
"import-nodegroup-template-file")
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
|
||||
|
||||
class ConfigureNodegroupTemplate(tables.LinkAction):
|
||||
name = "configure"
|
||||
verbose_name = _("Configure Template")
|
||||
|
@ -149,6 +158,7 @@ class NodegroupTemplatesTable(sahara_table.SaharaPaginateTabbedTable):
|
|||
name = "nodegroup_templates"
|
||||
verbose_name = _("Node Group Templates")
|
||||
table_actions = (CreateNodegroupTemplate,
|
||||
ImportNodegroupTemplate,
|
||||
ConfigureNodegroupTemplate,
|
||||
DeleteTemplate,
|
||||
NodeGroupTemplatesFilterAction,)
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
# limitations under the License.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
from horizon import workflows
|
||||
|
@ -30,6 +32,8 @@ import sahara_dashboard.content.data_processing.clusters. \
|
|||
nodegroup_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.edit as edit_flow
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.forms.import_forms as import_forms
|
||||
|
||||
|
||||
class NodegroupTemplateDetailsView(tabs.TabView):
|
||||
|
@ -49,8 +53,8 @@ class NodegroupTemplateDetailsView(tabs.TabView):
|
|||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(NodegroupTemplateDetailsView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
context = super(
|
||||
NodegroupTemplateDetailsView, self).get_context_data(**kwargs)
|
||||
node_group_template = self.get_object()
|
||||
context['template'] = node_group_template
|
||||
context['url'] = self.get_redirect_url()
|
||||
|
@ -97,8 +101,8 @@ class CopyNodegroupTemplateView(workflows.WorkflowView):
|
|||
template_name = "nodegroup_templates/configure.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CopyNodegroupTemplateView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
context = super(
|
||||
CopyNodegroupTemplateView, self).get_context_data(**kwargs)
|
||||
|
||||
context["template_id"] = kwargs["template_id"]
|
||||
return context
|
||||
|
@ -127,3 +131,38 @@ class EditNodegroupTemplateView(CopyNodegroupTemplateView):
|
|||
success_url = ("horizon:project:"
|
||||
"data_processing.clusters:index")
|
||||
template_name = "nodegroup_templates/configure.html"
|
||||
|
||||
|
||||
class ImportNodegroupTemplateFileView(forms.ModalFormView):
|
||||
template_name = "nodegroup_templates/import.html"
|
||||
form_class = import_forms.ImportNodegroupTemplateFileForm
|
||||
submit_label = _("Next")
|
||||
submit_url = reverse_lazy("horizon:project:data_processing."
|
||||
"clusters:import-nodegroup-template-file")
|
||||
success_url = reverse_lazy("horizon:project:data_processing."
|
||||
"clusters:import-nodegroup-template-details")
|
||||
page_title = _("Import Node Group Template")
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(
|
||||
ImportNodegroupTemplateFileView, self).get_form_kwargs()
|
||||
kwargs['next_view'] = ImportNodegroupTemplateDetailsView
|
||||
return kwargs
|
||||
|
||||
|
||||
class ImportNodegroupTemplateDetailsView(forms.ModalFormView):
|
||||
template_name = "nodegroup_templates/import.html"
|
||||
form_class = import_forms.ImportNodegroupTemplateDetailsForm
|
||||
submit_label = _("Import")
|
||||
submit_url = reverse_lazy("horizon:project:data_processing."
|
||||
"clusters:import-nodegroup-template-details")
|
||||
success_url = reverse_lazy("horizon:project:data_processing."
|
||||
"clusters:index")
|
||||
page_title = _("Import Node Group Template")
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(
|
||||
ImportNodegroupTemplateDetailsView, self).get_form_kwargs()
|
||||
if 'template_upload' in self.kwargs:
|
||||
kwargs['template_upload'] = self.kwargs['template_upload']
|
||||
return kwargs
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{% extends "horizon/common/_modal_form.html" %}
|
||||
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}import-nodegroup-template{% endblock %}
|
||||
{% block form_action %}{{ submit_url }}{% endblock %}
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-header %}{{ page_title }}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" id="upload_file_btn" type="submit" value="{{ submit_label }}"/>
|
||||
<a href="{% url 'horizon:project:data_processing.clusters:index' %}"
|
||||
class="btn btn-default cancel">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
|
@ -0,0 +1,7 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Import Node Group Template" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'nodegroup_templates/_import.html' %}
|
||||
{% endblock %}
|
|
@ -48,6 +48,12 @@ urlpatterns = [url(r'^$', views.IndexView.as_view(), name='index'),
|
|||
url(r'^configure-nodegroup-template$',
|
||||
ngt_views.ConfigureNodegroupTemplateView.as_view(),
|
||||
name='configure-nodegroup-template'),
|
||||
url(r'^import-nodegroup-template-file$',
|
||||
ngt_views.ImportNodegroupTemplateFileView.as_view(),
|
||||
name='import-nodegroup-template-file'),
|
||||
url(r'^import-nodegroup-template-details$',
|
||||
ngt_views.ImportNodegroupTemplateDetailsView.as_view(),
|
||||
name='import-nodegroup-template-details'),
|
||||
url(r'^cluster-template/(?P<template_id>[^/]+)$',
|
||||
ct_views.ClusterTemplateDetailsView.as_view(),
|
||||
name='ct-details'),
|
||||
|
|
Loading…
Reference in New Issue