Reorganizing cluster panels into tabs
First patch in reorganizing the sahara UI to be more tab oriented rather than death by a thousand panels. There are other patches that will complete the work, but this patch addresses the cluster-oriented panels by moving them under a single panel named Clusters. Change-Id: Iae4bf4b5127fb29153ec5335070cde7d344e059e Partial-Implements: bp reduce-number-of-panels
This commit is contained in:
parent
ecdd89583a
commit
5aa8b83bc9
@ -1,28 +0,0 @@
|
||||
# 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 openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class ClusterTemplatesPanel(horizon.Panel):
|
||||
name = _("Cluster Templates")
|
||||
slug = 'data_processing.cluster_templates'
|
||||
permissions = (('openstack.services.data-processing',
|
||||
'openstack.services.data_processing'),)
|
||||
|
||||
|
||||
dashboard.Project.register(ClusterTemplatesPanel)
|
@ -1,43 +0,0 @@
|
||||
# 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.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
import sahara_dashboard.content. \
|
||||
data_processing.cluster_templates.views as views
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.ClusterTemplatesView.as_view(),
|
||||
name='index'),
|
||||
url(r'^$', views.ClusterTemplatesView.as_view(),
|
||||
name='cluster-templates'),
|
||||
url(r'^upload_file$',
|
||||
views.UploadFileView.as_view(),
|
||||
name='upload_file'),
|
||||
url(r'^create-cluster-template$',
|
||||
views.CreateClusterTemplateView.as_view(),
|
||||
name='create-cluster-template'),
|
||||
url(r'^configure-cluster-template$',
|
||||
views.ConfigureClusterTemplateView.as_view(),
|
||||
name='configure-cluster-template'),
|
||||
url(r'^(?P<template_id>[^/]+)$',
|
||||
views.ClusterTemplateDetailsView.as_view(),
|
||||
name='details'),
|
||||
url(r'^(?P<template_id>[^/]+)/copy$',
|
||||
views.CopyClusterTemplateView.as_view(),
|
||||
name='copy'),
|
||||
url(r'^(?P<template_id>[^/]+)/edit$',
|
||||
views.EditClusterTemplateView.as_view(),
|
||||
name='edit'))
|
@ -35,7 +35,7 @@ class ClusterTemplatesFilterAction(tables.FilterAction):
|
||||
class UploadFile(tables.LinkAction):
|
||||
name = 'upload_file'
|
||||
verbose_name = _("Upload Template")
|
||||
url = 'horizon:project:data_processing.cluster_templates:upload_file'
|
||||
url = 'horizon:project:data_processing.clusters:upload_file'
|
||||
classes = ("btn-launch", "ajax-modal")
|
||||
icon = "upload"
|
||||
|
||||
@ -59,14 +59,14 @@ class CreateCluster(tables.LinkAction):
|
||||
class CopyTemplate(tables.LinkAction):
|
||||
name = "copy"
|
||||
verbose_name = _("Copy Template")
|
||||
url = "horizon:project:data_processing.cluster_templates:copy"
|
||||
url = "horizon:project:data_processing.clusters:ct-copy"
|
||||
classes = ("ajax-modal", )
|
||||
|
||||
|
||||
class EditTemplate(tables.LinkAction):
|
||||
name = "edit"
|
||||
verbose_name = _("Edit Template")
|
||||
url = "horizon:project:data_processing.cluster_templates:edit"
|
||||
url = "horizon:project:data_processing.clusters:ct-edit"
|
||||
classes = ("ajax-modal", )
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@ class DeleteTemplate(tables.DeleteAction):
|
||||
class CreateClusterTemplate(tables.LinkAction):
|
||||
name = "create"
|
||||
verbose_name = _("Create Template")
|
||||
url = ("horizon:project:data_processing.cluster_templates:"
|
||||
url = ("horizon:project:data_processing.clusters:"
|
||||
"create-cluster-template")
|
||||
classes = ("ajax-modal", "create-clustertemplate-btn")
|
||||
icon = "plus"
|
||||
@ -103,7 +103,7 @@ class CreateClusterTemplate(tables.LinkAction):
|
||||
class ConfigureClusterTemplate(tables.LinkAction):
|
||||
name = "configure"
|
||||
verbose_name = _("Configure Cluster Template")
|
||||
url = ("horizon:project:data_processing.cluster_templates:"
|
||||
url = ("horizon:project:data_processing.clusters:"
|
||||
"configure-cluster-template")
|
||||
classes = ("ajax-modal", "configure-clustertemplate-btn")
|
||||
icon = "plus"
|
||||
@ -152,7 +152,7 @@ class ClusterTemplatesTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link=("horizon:project:data_processing."
|
||||
"cluster_templates:details"))
|
||||
"clusters:ct-details"))
|
||||
plugin_name = tables.Column("plugin_name",
|
||||
verbose_name=_("Plugin"))
|
||||
hadoop_version = tables.Column("hadoop_version",
|
@ -22,16 +22,41 @@ from openstack_dashboard.api import nova
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
from sahara_dashboard.content. \
|
||||
data_processing.utils import workflow_helpers as helpers
|
||||
from sahara_dashboard.content.data_processing.clusters.cluster_templates \
|
||||
import tables as cluster_template_tables
|
||||
from sahara_dashboard.content.data_processing \
|
||||
import tabs as sahara_tabs
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ClusterTemplatesTab(sahara_tabs.SaharaTableTab):
|
||||
table_classes = (cluster_template_tables.ClusterTemplatesTable, )
|
||||
name = _("Cluster Templates")
|
||||
slug = "clusters_templates_tab"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_cluster_templates_data(self):
|
||||
try:
|
||||
table = self._tables['cluster_templates']
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(table.request, table)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
cluster_templates = saharaclient.cluster_template_list(
|
||||
self.request, search_opts)
|
||||
except Exception:
|
||||
cluster_templates = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster template list"))
|
||||
return cluster_templates
|
||||
|
||||
|
||||
class GeneralTab(tabs.Tab):
|
||||
name = _("General Info")
|
||||
slug = "cluster_template_details_tab"
|
||||
template_name = (
|
||||
"project/data_processing.cluster_templates/_details.html")
|
||||
template_name = "cluster_templates/_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
template_id = self.tab_group.kwargs['template_id']
|
||||
@ -47,8 +72,7 @@ class ClusterTemplateConfigsDetails(tabs.Tab):
|
||||
name = _("Configuration Details")
|
||||
slug = "cluster_template_configs_details_tab"
|
||||
template_name = (
|
||||
"project/data_processing.cluster_templates/"
|
||||
"_cluster_template_configs_details.html")
|
||||
"cluster_templates/_cluster_template_configs_details.html")
|
||||
|
||||
def get_context_data(self, request):
|
||||
template_id = self.tab_group.kwargs['template_id']
|
||||
@ -63,8 +87,7 @@ class ClusterTemplateConfigsDetails(tabs.Tab):
|
||||
class NodeGroupsTab(tabs.Tab):
|
||||
name = _("Node Groups")
|
||||
slug = "cluster_template_nodegroups_tab"
|
||||
template_name = (
|
||||
"project/data_processing.cluster_templates/_nodegroups_details.html")
|
||||
template_name = "cluster_templates/_nodegroups_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
template_id = self.tab_group.kwargs['template_id']
|
@ -26,9 +26,10 @@ from sahara_dashboard import api
|
||||
from sahara_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:data_processing.cluster_templates:index')
|
||||
INDEX_URL = reverse('horizon:project:data_processing.clusters:'
|
||||
'cluster-templates-tab')
|
||||
DETAILS_URL = reverse(
|
||||
'horizon:project:data_processing.cluster_templates:details', args=['id'])
|
||||
'horizon:project:data_processing.clusters:ct-details', args=['id'])
|
||||
|
||||
|
||||
class DataProcessingClusterTemplateTests(test.TestCase):
|
||||
@ -38,9 +39,7 @@ class DataProcessingClusterTemplateTests(test.TestCase):
|
||||
.AndReturn(self.cluster_templates.list())
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.cluster_templates/'
|
||||
'cluster_templates.html')
|
||||
self.assertTemplateUsed(res, 'clusters/index.html')
|
||||
self.assertContains(res, 'Cluster Templates')
|
||||
self.assertContains(res, 'Name')
|
||||
|
||||
@ -78,7 +77,7 @@ class DataProcessingClusterTemplateTests(test.TestCase):
|
||||
.MultipleTimes().AndReturn(ngts)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:data_processing.cluster_templates:copy',
|
||||
url = reverse('horizon:project:data_processing.clusters:ct-copy',
|
||||
args=[ct.id])
|
||||
res = self.client.get(url)
|
||||
workflow = res.context['workflow']
|
||||
@ -140,7 +139,7 @@ class DataProcessingClusterTemplateTests(test.TestCase):
|
||||
.AndReturn(new_ct)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:project:data_processing.cluster_templates:edit',
|
||||
url = reverse('horizon:project:data_processing.clusters:ct-edit',
|
||||
args=[ct.id])
|
||||
|
||||
def serialize(obj):
|
@ -23,40 +23,25 @@ from horizon.utils import memoized
|
||||
from horizon import workflows
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
from sahara_dashboard.content.data_processing. \
|
||||
from sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates import forms as cluster_forms
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.tables as ct_tables
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.tabs as _tabs
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.copy as copy_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.edit as edit_flow
|
||||
|
||||
|
||||
class ClusterTemplatesView(tables.DataTableView):
|
||||
table_class = ct_tables.ClusterTemplatesTable
|
||||
template_name = (
|
||||
'project/data_processing.cluster_templates/cluster_templates.html')
|
||||
template_name = 'cluster_templates/cluster_templates.html'
|
||||
page_title = _("Cluster Templates")
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(self.request)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
cluster_templates = saharaclient.cluster_template_list(
|
||||
self.request, search_opts)
|
||||
except Exception:
|
||||
cluster_templates = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster template list"))
|
||||
return cluster_templates
|
||||
|
||||
|
||||
class ClusterTemplateDetailsView(tabs.TabView):
|
||||
tab_group_class = _tabs.ClusterTemplateDetailsTabs
|
||||
@ -72,7 +57,7 @@ class ClusterTemplateDetailsView(tabs.TabView):
|
||||
msg = _('Unable to retrieve details for '
|
||||
'cluster template "%s".') % ct_id
|
||||
redirect = reverse("horizon:project:data_processing."
|
||||
"cluster_templates:cluster-templates")
|
||||
"clusters:cluster-templates-tab")
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -90,33 +75,34 @@ class ClusterTemplateDetailsView(tabs.TabView):
|
||||
|
||||
class UploadFileView(forms.ModalFormView):
|
||||
form_class = cluster_forms.UploadFileForm
|
||||
template_name = (
|
||||
'project/data_processing.cluster_templates/upload_file.html')
|
||||
template_name = 'cluster_templates/upload_file.html'
|
||||
success_url = reverse_lazy(
|
||||
'horizon:project:data_processing.cluster_templates:index')
|
||||
'horizon:project:data_processing.clusters:cluster-templates-tab')
|
||||
page_title = _("Upload Template")
|
||||
|
||||
|
||||
class CreateClusterTemplateView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.CreateClusterTemplate
|
||||
success_url = ("horizon:project:data_processing.cluster_templates"
|
||||
success_url = ("horizon:project:data_processing.clusters"
|
||||
":create-cluster-template")
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "project/data_processing.cluster_templates/create.html"
|
||||
template_name = "cluster_templates/create.html"
|
||||
page_title = _("Create Cluster Template")
|
||||
|
||||
|
||||
class ConfigureClusterTemplateView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.ConfigureClusterTemplate
|
||||
success_url = "horizon:project:data_processing.cluster_templates"
|
||||
template_name = "project/data_processing.cluster_templates/configure.html"
|
||||
success_url = ("horizon:project:data_processing.clusters"
|
||||
":cluster-templates-tab")
|
||||
template_name = "cluster_templates/configure.html"
|
||||
page_title = _("Configure Cluster Template")
|
||||
|
||||
|
||||
class CopyClusterTemplateView(workflows.WorkflowView):
|
||||
workflow_class = copy_flow.CopyClusterTemplate
|
||||
success_url = "horizon:project:data_processing.cluster_templates"
|
||||
template_name = "project/data_processing.cluster_templates/configure.html"
|
||||
success_url = ("horizon:project:data_processing.clusters"
|
||||
":cluster-templates-tab")
|
||||
template_name = "cluster_templates/configure.html"
|
||||
page_title = _("Copy Cluster Template")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -147,5 +133,6 @@ class CopyClusterTemplateView(workflows.WorkflowView):
|
||||
|
||||
class EditClusterTemplateView(CopyClusterTemplateView):
|
||||
workflow_class = edit_flow.EditClusterTemplate
|
||||
success_url = "horizon:project:data_processing.cluster_templates"
|
||||
template_name = "project/data_processing.cluster_templates/configure.html"
|
||||
success_url = ("horizon:project:data_processing.clusters:"
|
||||
"cluster-templates-tab")
|
||||
template_name = "cluster_templates/configure.html"
|
@ -19,7 +19,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing.utils. \
|
||||
workflow_helpers as wf_helpers
|
@ -14,6 +14,7 @@
|
||||
import base64
|
||||
import json
|
||||
|
||||
from django.core import urlresolvers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from saharaclient.api import base as api_base
|
||||
|
||||
@ -67,7 +68,7 @@ class SelectPluginAction(workflows.Action):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Select plugin and hadoop version for cluster template")
|
||||
help_text_template = ("project/data_processing.cluster_templates/"
|
||||
help_text_template = ("cluster_templates/"
|
||||
"_create_general_help.html")
|
||||
|
||||
|
||||
@ -81,8 +82,12 @@ class CreateClusterTemplate(workflows.Workflow):
|
||||
finalize_button_name = _("Next")
|
||||
success_message = _("Created")
|
||||
failure_message = _("Could not create")
|
||||
success_url = "horizon:project:data_processing.cluster_templates:index"
|
||||
default_steps = (SelectPlugin,)
|
||||
success_url = "horizon:project:data_processing.clusters:clusters-tab"
|
||||
default_steps = (SelectPlugin, )
|
||||
|
||||
def get_success_url(self):
|
||||
url = urlresolvers.reverse(self.success_url)
|
||||
return url
|
||||
|
||||
|
||||
class GeneralConfigAction(workflows.Action):
|
||||
@ -149,8 +154,7 @@ class GeneralConfigAction(workflows.Action):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Details")
|
||||
help_text_template = ("project/data_processing.cluster_templates/"
|
||||
"_configure_general_help.html")
|
||||
help_text_template = ("cluster_templates/_configure_general_help.html")
|
||||
|
||||
|
||||
class GeneralConfig(workflows.Step):
|
||||
@ -232,8 +236,7 @@ class ConfigureNodegroupsAction(workflows.Action):
|
||||
class ConfigureNodegroups(workflows.Step):
|
||||
action_class = ConfigureNodegroupsAction
|
||||
contributes = ("hidden_nodegroups_field", )
|
||||
template_name = ("project/data_processing.cluster_templates/"
|
||||
"cluster_node_groups_template.html")
|
||||
template_name = ("cluster_templates/cluster_node_groups_template.html")
|
||||
|
||||
def contribute(self, data, context):
|
||||
for k, v in data.items():
|
||||
@ -302,7 +305,8 @@ class ConfigureClusterTemplate(whelpers.ServiceParametersWorkflow,
|
||||
finalize_button_name = _("Create")
|
||||
success_message = _("Created Cluster Template %s")
|
||||
name_property = "general_cluster_template_name"
|
||||
success_url = "horizon:project:data_processing.cluster_templates:index"
|
||||
success_url = ("horizon:project:data_processing.clusters:"
|
||||
"cluster-templates-tab")
|
||||
default_steps = (GeneralConfig,
|
||||
ConfigureNodegroups)
|
||||
|
@ -20,9 +20,9 @@ from horizon import exceptions
|
||||
from horizon import forms
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.copy as copy_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
utils.workflow_helpers as whelpers
|
@ -134,8 +134,7 @@ def rich_status_filter(status_dict):
|
||||
return status_dict["status"]
|
||||
|
||||
# Error is rendered with a template containing an error description.
|
||||
return render_to_string(
|
||||
"project/data_processing.clusters/_rich_status.html", status_dict)
|
||||
return render_to_string("clusters/_rich_status.html", status_dict)
|
||||
|
||||
|
||||
class ConfigureCluster(tables.LinkAction):
|
||||
@ -172,7 +171,7 @@ class ClustersTable(tables.DataTable):
|
||||
name = tables.Column("name",
|
||||
verbose_name=_("Name"),
|
||||
link=("horizon:project:data_processing."
|
||||
"clusters:details"))
|
||||
"clusters:cluster-details"))
|
||||
|
||||
plugin = tables.Column("plugin_name",
|
||||
verbose_name=_("Plugin"))
|
@ -19,6 +19,10 @@ from horizon import exceptions
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
|
||||
from sahara_dashboard.content.data_processing.clusters.clusters \
|
||||
import tables as cluster_tables
|
||||
from sahara_dashboard.content.data_processing \
|
||||
import tabs as sahara_tabs
|
||||
from sahara_dashboard.content.data_processing.utils \
|
||||
import workflow_helpers as helpers
|
||||
|
||||
@ -32,10 +36,31 @@ from sahara_dashboard.api import sahara as saharaclient
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ClustersTab(sahara_tabs.SaharaTableTab):
|
||||
table_classes = (cluster_tables.ClustersTable, )
|
||||
name = _("Clusters")
|
||||
slug = "clusters_tab"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_clusters_data(self):
|
||||
try:
|
||||
table = self._tables['clusters']
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(table.request, table)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
clusters = saharaclient.cluster_list(self.request, search_opts)
|
||||
except Exception:
|
||||
clusters = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster list"))
|
||||
return clusters
|
||||
|
||||
|
||||
class GeneralTab(tabs.Tab):
|
||||
name = _("General Info")
|
||||
slug = "cluster_details_tab"
|
||||
template_name = "project/data_processing.clusters/_details.html"
|
||||
template_name = "clusters/_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
cluster_id = self.tab_group.kwargs['cluster_id']
|
||||
@ -79,7 +104,7 @@ class ClusterConfigsDetails(tabs.Tab):
|
||||
name = _("Configuration Details")
|
||||
slug = "cluster_configs_details_tab"
|
||||
template_name = (
|
||||
"project/data_processing.clusters/_cluster_configs_details.html")
|
||||
"clusters/_cluster_configs_details.html")
|
||||
|
||||
def get_context_data(self, request):
|
||||
cluster_id = self.tab_group.kwargs['cluster_id']
|
||||
@ -101,8 +126,7 @@ def build_link(url):
|
||||
class NodeGroupsTab(tabs.Tab):
|
||||
name = _("Node Groups")
|
||||
slug = "cluster_nodegroups_tab"
|
||||
template_name = (
|
||||
"project/data_processing.clusters/_nodegroups_details.html")
|
||||
template_name = "clusters/_nodegroups_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
cluster_id = self.tab_group.kwargs['cluster_id']
|
||||
@ -167,7 +191,7 @@ class InstancesTable(tables.DataTable):
|
||||
class InstancesTab(tabs.TableTab):
|
||||
name = _("Instances")
|
||||
slug = "cluster_instances_tab"
|
||||
template_name = "project/data_processing.clusters/_instances_details.html"
|
||||
template_name = "clusters/_instances_details.html"
|
||||
table_classes = (InstancesTable, )
|
||||
|
||||
def get_cluster_instances_data(self):
|
||||
@ -197,7 +221,7 @@ class InstancesTab(tabs.TableTab):
|
||||
class EventLogTab(tabs.Tab):
|
||||
name = _("Cluster Events")
|
||||
slug = "cluster_event_log"
|
||||
template_name = "project/data_processing.clusters/_event_log.html"
|
||||
template_name = "clusters/_event_log.html"
|
||||
|
||||
def get_context_data(self, request, **kwargs):
|
||||
cluster_id = self.tab_group.kwargs['cluster_id']
|
@ -21,7 +21,7 @@ from sahara_dashboard.test import helpers as test
|
||||
from sahara_dashboard import api
|
||||
|
||||
|
||||
INDEX_URL = reverse('horizon:project:data_processing.clusters:index')
|
||||
INDEX_URL = reverse('horizon:project:data_processing.clusters:clusters-tab')
|
||||
DETAILS_URL = reverse(
|
||||
'horizon:project:data_processing.clusters:details', args=['id'])
|
||||
|
||||
@ -33,8 +33,7 @@ class DataProcessingClusterTests(test.TestCase):
|
||||
.AndReturn(self.clusters.list())
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(
|
||||
res, 'project/data_processing.clusters/clusters.html')
|
||||
self.assertTemplateUsed(res, 'clusters/index.html')
|
||||
self.assertContains(res, 'Clusters')
|
||||
self.assertContains(res, 'Name')
|
||||
|
@ -0,0 +1,257 @@
|
||||
# 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 datetime import datetime
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import base as django_base
|
||||
import six
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
from horizon import workflows
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
tables as c_tables
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
tabs as _tabs
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
workflows.scale as scale_flow
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
workflows.update as update_flow
|
||||
from saharaclient.api.base import APIException
|
||||
|
||||
|
||||
class ClustersView(tables.DataTableView):
|
||||
table_class = c_tables.ClustersTable
|
||||
template_name = 'clusters/clusters.html'
|
||||
page_title = _("Clusters")
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(self.request)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
clusters = saharaclient.cluster_list(self.request, search_opts)
|
||||
except Exception:
|
||||
clusters = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster list"))
|
||||
return clusters
|
||||
|
||||
|
||||
class ClusterDetailsView(tabs.TabView):
|
||||
tab_group_class = _tabs.ClusterDetailsTabs
|
||||
template_name = 'horizon/common/_detail.html'
|
||||
page_title = "{{ cluster.name|default:cluster.id }}"
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_object(self):
|
||||
cl_id = self.kwargs["cluster_id"]
|
||||
try:
|
||||
return saharaclient.cluster_get(self.request, cl_id)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for cluster "%s".') % cl_id
|
||||
redirect = reverse(
|
||||
"horizon:project:data_processing.clusters:clusters-tab")
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ClusterDetailsView, self).get_context_data(**kwargs)
|
||||
context['cluster'] = self.get_object()
|
||||
return context
|
||||
|
||||
|
||||
class ClusterEventsView(django_base.View):
|
||||
|
||||
_date_format = "%Y-%m-%dT%H:%M:%S"
|
||||
|
||||
@staticmethod
|
||||
def _created_at_key(obj):
|
||||
return datetime.strptime(obj["created_at"],
|
||||
ClusterEventsView._date_format)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
cluster_id = kwargs.get("cluster_id")
|
||||
|
||||
try:
|
||||
cluster = saharaclient.cluster_get(request, cluster_id,
|
||||
show_progress=True)
|
||||
node_group_mapping = {}
|
||||
for node_group in cluster.node_groups:
|
||||
node_group_mapping[node_group["id"]] = node_group["name"]
|
||||
|
||||
provision_steps = cluster.provision_progress
|
||||
|
||||
# Sort by create time
|
||||
provision_steps = sorted(provision_steps,
|
||||
key=ClusterEventsView._created_at_key,
|
||||
reverse=True)
|
||||
|
||||
for step in provision_steps:
|
||||
# Sort events of the steps also
|
||||
step["events"] = sorted(step["events"],
|
||||
key=ClusterEventsView._created_at_key,
|
||||
reverse=True)
|
||||
|
||||
successful_events_count = 0
|
||||
|
||||
for event in step["events"]:
|
||||
if event["node_group_id"]:
|
||||
event["node_group_name"] = node_group_mapping[
|
||||
event["node_group_id"]]
|
||||
|
||||
event_result = _("Unknown")
|
||||
if event["successful"] is True:
|
||||
successful_events_count += 1
|
||||
event_result = _("Completed Successfully")
|
||||
elif event["successful"] is False:
|
||||
event_result = _("Failed")
|
||||
|
||||
event["result"] = event_result
|
||||
|
||||
if not event["event_info"]:
|
||||
event["event_info"] = _("No info available")
|
||||
|
||||
start_time = datetime.strptime(step["created_at"],
|
||||
self._date_format)
|
||||
end_time = datetime.now()
|
||||
# Clear out microseconds. There is no need for that precision.
|
||||
end_time = end_time.replace(microsecond=0)
|
||||
if step["successful"] is not None:
|
||||
updated_at = step["updated_at"]
|
||||
end_time = datetime.strptime(updated_at,
|
||||
self._date_format)
|
||||
step["duration"] = six.text_type(end_time - start_time)
|
||||
|
||||
result = _("In progress")
|
||||
step["completed"] = successful_events_count
|
||||
|
||||
if step["successful"] is True:
|
||||
step["completed"] = step["total"]
|
||||
result = _("Completed Successfully")
|
||||
elif step["successful"] is False:
|
||||
result = _("Failed")
|
||||
|
||||
step["result"] = result
|
||||
|
||||
status = cluster.status.lower()
|
||||
need_update = status not in ("active", "error")
|
||||
except APIException:
|
||||
# Cluster is not available. Returning empty event log.
|
||||
need_update = False
|
||||
provision_steps = []
|
||||
|
||||
context = {"provision_steps": provision_steps,
|
||||
"need_update": need_update}
|
||||
|
||||
return HttpResponse(json.dumps(context),
|
||||
content_type='application/json')
|
||||
|
||||
|
||||
class CreateClusterView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.CreateCluster
|
||||
success_url = \
|
||||
"horizon:project:data_processing.clusters:create-cluster"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "clusters/create.html"
|
||||
page_title = _("Launch Cluster")
|
||||
|
||||
|
||||
class ConfigureClusterView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.ConfigureCluster
|
||||
success_url = "horizon:project:data_processing.clusters-tab"
|
||||
template_name = "clusters/configure.html"
|
||||
page_title = _("Configure Cluster")
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(ConfigureClusterView, self).get_initial()
|
||||
initial.update(self.kwargs)
|
||||
return initial
|
||||
|
||||
|
||||
class ScaleClusterView(workflows.WorkflowView):
|
||||
workflow_class = scale_flow.ScaleCluster
|
||||
success_url = "horizon:project:data_processing.clusters-tab"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "clusters/scale.html"
|
||||
page_title = _("Scale Cluster")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ScaleClusterView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
|
||||
context["cluster_id"] = kwargs["cluster_id"]
|
||||
return context
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
template_id = self.kwargs['cluster_id']
|
||||
try:
|
||||
template = saharaclient.cluster_template_get(self.request,
|
||||
template_id)
|
||||
except Exception:
|
||||
template = None
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster template."))
|
||||
self._object = template
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(ScaleClusterView, self).get_initial()
|
||||
initial.update({'cluster_id': self.kwargs['cluster_id']})
|
||||
return initial
|
||||
|
||||
|
||||
class UpdateClusterSharesView(workflows.WorkflowView):
|
||||
workflow_class = update_flow.UpdateShares
|
||||
success_url = "horizon:project:data_processing.clusters"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "clusters/update.html"
|
||||
page_title = _("Update Cluster Shares")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateClusterSharesView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
context["cluster_id"] = kwargs["cluster_id"]
|
||||
return context
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
cluster_id = self.kwargs['cluster_id']
|
||||
try:
|
||||
cluster = saharaclient.cluster_get(self.request, cluster_id)
|
||||
except Exception:
|
||||
cluster = None
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster."))
|
||||
self._object = cluster
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(UpdateClusterSharesView, self).get_initial()
|
||||
initial.update({
|
||||
'cluster_id': self.kwargs['cluster_id'],
|
||||
'cluster': self.get_object()})
|
||||
return initial
|
@ -26,23 +26,22 @@ import sahara_dashboard.content.data_processing.utils. \
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as t_flows
|
||||
|
||||
from saharaclient.api import base as api_base
|
||||
|
||||
|
||||
KEYPAIR_IMPORT_URL = "horizon:project:access_and_security:keypairs:import"
|
||||
BASE_IMAGE_URL = "horizon:project:data_processing.data_image_registry:register"
|
||||
BASE_IMAGE_URL = "horizon:project:data_processing.clusters:register"
|
||||
TEMPLATE_UPLOAD_URL = (
|
||||
"horizon:project:data_processing.cluster_templates:upload_file")
|
||||
"horizon:project:data_processing.clusters:upload_file")
|
||||
|
||||
|
||||
class SelectPluginAction(t_flows.SelectPluginAction):
|
||||
class Meta(object):
|
||||
name = _("Select plugin and hadoop version for cluster")
|
||||
help_text_template = (
|
||||
"project/data_processing.clusters/_create_general_help.html")
|
||||
help_text_template = "clusters/_create_general_help.html"
|
||||
|
||||
|
||||
class SelectPlugin(t_flows.SelectPlugin):
|
||||
@ -52,7 +51,7 @@ class SelectPlugin(t_flows.SelectPlugin):
|
||||
class CreateCluster(t_flows.CreateClusterTemplate):
|
||||
slug = "create_cluster"
|
||||
name = _("Launch Cluster")
|
||||
success_url = "horizon:project:data_processing.cluster_templates:index"
|
||||
success_url = "horizon:project:data_processing.clusters:clusters-tab"
|
||||
default_steps = (SelectPlugin,)
|
||||
|
||||
|
||||
@ -206,8 +205,7 @@ class GeneralConfigAction(workflows.Action):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Configure Cluster")
|
||||
help_text_template = \
|
||||
("project/data_processing.clusters/_configure_general_help.html")
|
||||
help_text_template = "clusters/_configure_general_help.html"
|
||||
|
||||
|
||||
class GeneralConfig(workflows.Step):
|
||||
@ -227,7 +225,7 @@ class ConfigureCluster(whelpers.StatusFormatMixin, workflows.Workflow):
|
||||
finalize_button_name = _("Launch")
|
||||
success_message = _("Launched Cluster %s")
|
||||
name_property = "general_cluster_name"
|
||||
success_url = "horizon:project:data_processing.clusters:index"
|
||||
success_url = "horizon:project:data_processing.clusters:clusters-tab"
|
||||
default_steps = (GeneralConfig, )
|
||||
|
||||
def handle(self, request, context):
|
@ -19,9 +19,9 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as clt_create_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
clusters.workflows.create as cl_create_flow
|
||||
from sahara_dashboard.content.data_processing.utils import workflow_helpers
|
||||
|
@ -23,13 +23,12 @@ from sahara_dashboard.api import sahara as saharaclient
|
||||
class EditTagsAction(tables.LinkAction):
|
||||
name = "edit_tags"
|
||||
verbose_name = _("Edit Tags")
|
||||
url = "horizon:project:data_processing.data_image_registry:edit_tags"
|
||||
url = "horizon:project:data_processing.clusters:edit_tags"
|
||||
classes = ("ajax-modal",)
|
||||
|
||||
|
||||
def tags_to_string(image):
|
||||
template_name = (
|
||||
'project/data_processing.data_image_registry/_list_tags.html')
|
||||
template_name = 'data_image_registry/_list_tags.html'
|
||||
context = {"image": image}
|
||||
return template.loader.render_to_string(template_name, context)
|
||||
|
||||
@ -37,7 +36,7 @@ def tags_to_string(image):
|
||||
class RegisterImage(tables.LinkAction):
|
||||
name = "register"
|
||||
verbose_name = _("Register Image")
|
||||
url = "horizon:project:data_processing.data_image_registry:register"
|
||||
url = "horizon:project:data_processing.clusters:register"
|
||||
classes = ("ajax-modal",)
|
||||
icon = "plus"
|
||||
|
@ -0,0 +1,43 @@
|
||||
# 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 logging
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tabs
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
|
||||
from sahara_dashboard.content.data_processing.clusters.data_image_registry \
|
||||
import tables as data_image_registry_tables
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DataImageRegistryTab(tabs.TableTab):
|
||||
table_classes = (data_image_registry_tables.ImageRegistryTable, )
|
||||
name = _("Data Image Registry")
|
||||
slug = "data_image_registry_tab"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_image_registry_data(self):
|
||||
try:
|
||||
images = saharaclient.image_list(self.request)
|
||||
except Exception:
|
||||
images = []
|
||||
msg = _('Unable to retrieve image list')
|
||||
exceptions.handle(self.request, msg)
|
||||
return images
|
@ -21,9 +21,9 @@ from sahara_dashboard.test import helpers as test
|
||||
from sahara_dashboard import api
|
||||
|
||||
INDEX_URL = reverse(
|
||||
'horizon:project:data_processing.data_image_registry:index')
|
||||
'horizon:project:data_processing.clusters:image-registry-tab')
|
||||
REGISTER_URL = reverse(
|
||||
'horizon:project:data_processing.data_image_registry:register')
|
||||
'horizon:project:data_processing.clusters:register')
|
||||
|
||||
|
||||
class DataProcessingImageRegistryTests(test.TestCase):
|
||||
@ -35,9 +35,7 @@ class DataProcessingImageRegistryTests(test.TestCase):
|
||||
|
||||
res = self.client.get(INDEX_URL)
|
||||
|
||||
self.assertTemplateUsed(
|
||||
res,
|
||||
'project/data_processing.data_image_registry/image_registry.html')
|
||||
self.assertTemplateUsed(res, 'clusters/index.html')
|
||||
self.assertContains(res, 'Image Registry')
|
||||
self.assertContains(res, 'Image')
|
||||
self.assertContains(res, 'Tags')
|
||||
@ -117,7 +115,7 @@ class DataProcessingImageRegistryTests(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
edit_tags_url = reverse(
|
||||
'horizon:project:data_processing.data_image_registry:edit_tags',
|
||||
'horizon:project:data_processing.clusters:edit_tags',
|
||||
args=[image.id])
|
||||
res = self.client.post(
|
||||
edit_tags_url,
|
@ -23,17 +23,16 @@ from horizon.utils import memoized
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
from sahara_dashboard.content. \
|
||||
data_processing.data_image_registry.forms import EditTagsForm
|
||||
data_processing.clusters.data_image_registry.forms import EditTagsForm
|
||||
from sahara_dashboard.content. \
|
||||
data_processing.data_image_registry.forms import RegisterImageForm
|
||||
from sahara_dashboard.content. \
|
||||
data_processing.data_image_registry.tables import ImageRegistryTable
|
||||
data_processing.clusters.data_image_registry.forms import RegisterImageForm
|
||||
from sahara_dashboard.content.data_processing. \
|
||||
clusters.data_image_registry.tables import ImageRegistryTable
|
||||
|
||||
|
||||
class ImageRegistryView(tables.DataTableView):
|
||||
table_class = ImageRegistryTable
|
||||
template_name = (
|
||||
'project/data_processing.data_image_registry/image_registry.html')
|
||||
template_name = 'data_image_registry/image_registry.html'
|
||||
page_title = _("Image Registry")
|
||||
|
||||
def get_data(self):
|
||||
@ -74,10 +73,9 @@ def update_context_with_plugin_tags(request, context):
|
||||
|
||||
class EditTagsView(forms.ModalFormView):
|
||||
form_class = EditTagsForm
|
||||
template_name = (
|
||||
'project/data_processing.data_image_registry/edit_tags.html')
|
||||
template_name = 'data_image_registry/edit_tags.html'
|
||||
success_url = reverse_lazy(
|
||||
'horizon:project:data_processing.data_image_registry:index')
|
||||
'horizon:project:data_processing.clusters:image-registry-tab')
|
||||
page_title = _("Edit Image Tags")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -108,10 +106,9 @@ class EditTagsView(forms.ModalFormView):
|
||||
|
||||
class RegisterImageView(forms.ModalFormView):
|
||||
form_class = RegisterImageForm
|
||||
template_name = (
|
||||
'project/data_processing.data_image_registry/register_image.html')
|
||||
template_name = 'data_image_registry/register_image.html'
|
||||
success_url = reverse_lazy(
|
||||
'horizon:project:data_processing.data_image_registry:index')
|
||||
'horizon:project:data_processing.clusters:image-registry-tab')
|
||||
page_title = _("Register Image")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
@ -32,7 +32,7 @@ class NodeGroupTemplatesFilterAction(tables.FilterAction):
|
||||
class CreateNodegroupTemplate(tables.LinkAction):
|
||||
name = "create"
|
||||
verbose_name = _("Create Template")
|
||||
url = ("horizon:project:data_processing.nodegroup_templates:"
|
||||
url = ("horizon:project:data_processing.clusters:"
|
||||
"create-nodegroup-template")
|
||||
classes = ("ajax-modal", "create-nodegrouptemplate-btn")
|
||||
icon = "plus"
|
||||
@ -41,7 +41,7 @@ class CreateNodegroupTemplate(tables.LinkAction):
|
||||
class ConfigureNodegroupTemplate(tables.LinkAction):
|
||||
name = "configure"
|
||||
verbose_name = _("Configure Template")
|
||||
url = ("horizon:project:data_processing.nodegroup_templates:"
|
||||
url = ("horizon:project:data_processing.clusters:"
|
||||
"configure-nodegroup-template")
|
||||
classes = ("ajax-modal", "configure-nodegrouptemplate-btn")
|
||||
icon = "plus"
|
||||
@ -51,14 +51,14 @@ class ConfigureNodegroupTemplate(tables.LinkAction):
|
||||
class CopyTemplate(tables.LinkAction):
|
||||
name = "copy"
|
||||
verbose_name = _("Copy Template")
|
||||
url = "horizon:project:data_processing.nodegroup_templates:copy"
|
||||
url = "horizon:project:data_processing.clusters:copy"
|
||||
classes = ("ajax-modal", )
|
||||
|
||||
|
||||
class EditTemplate(tables.LinkAction):
|
||||
name = "edit"
|
||||
verbose_name = _("Edit Template")
|
||||
url = "horizon:project:data_processing.nodegroup_templates:edit"
|
||||
url = "horizon:project:data_processing.clusters:edit"
|
||||
classes = ("ajax-modal", )
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ class NodegroupTemplatesTable(tables.DataTable):
|
||||
name = tables.Column(
|
||||
"name",
|
||||
verbose_name=_("Name"),
|
||||
link="horizon:project:data_processing.nodegroup_templates:details")
|
||||
link="horizon:project:data_processing.clusters:details")
|
||||
plugin_name = tables.Column("plugin_name",
|
||||
verbose_name=_("Plugin"))
|
||||
hadoop_version = tables.Column("hadoop_version",
|
@ -22,18 +22,42 @@ from openstack_dashboard.api import network
|
||||
from openstack_dashboard.api import nova
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
|
||||
from sahara_dashboard.content.data_processing \
|
||||
import tabs as sahara_tabs
|
||||
from sahara_dashboard.content. \
|
||||
data_processing.utils import workflow_helpers as helpers
|
||||
from sahara_dashboard.content.data_processing.clusters.nodegroup_templates \
|
||||
import tables as node_group_template_tables
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NodeGroupTemplatesTab(sahara_tabs.SaharaTableTab):
|
||||
table_classes = (node_group_template_tables.NodegroupTemplatesTable, )
|
||||
name = _("Node Group Templates")
|
||||
slug = "node_group_templates_tab"
|
||||
template_name = "horizon/common/_detail_table.html"
|
||||
|
||||
def get_nodegroup_templates_data(self):
|
||||
try:
|
||||
table = self._tables['nodegroup_templates']
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(table.request, table)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
node_group_templates = saharaclient.nodegroup_template_list(
|
||||
self.request, search_opts)
|
||||
except Exception:
|
||||
node_group_templates = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch node group template list"))
|
||||
return node_group_templates
|
||||
|
||||
|
||||
class GeneralTab(tabs.Tab):
|
||||
name = _("General Info")
|
||||
slug = "nodegroup_template_details_tab"
|
||||
template_name = (
|
||||
"project/data_processing.nodegroup_templates/_details.html")
|
||||
template_name = "nodegroup_templates/_details.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
template_id = self.tab_group.kwargs['template_id']
|
||||
@ -79,8 +103,7 @@ class GeneralTab(tabs.Tab):
|
||||
class ConfigsTab(tabs.Tab):
|
||||
name = _("Service Configurations")
|
||||
slug = "nodegroup_template_service_configs_tab"
|
||||
template_name = (
|
||||
"project/data_processing.nodegroup_templates/_service_confs.html")
|
||||
template_name = "nodegroup_templates/_service_confs.html"
|
||||
|
||||
def get_context_data(self, request):
|
||||
template_id = self.tab_group.kwargs['template_id']
|
@ -21,18 +21,18 @@ from openstack_dashboard import api as dash_api
|
||||
from sahara_dashboard import api
|
||||
from sahara_dashboard.content.data_processing.utils \
|
||||
import workflow_helpers
|
||||
from sahara_dashboard.content.data_processing.\
|
||||
from sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows import create as create_workflow
|
||||
from sahara_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse(
|
||||
'horizon:project:data_processing.nodegroup_templates:index')
|
||||
'horizon:project:data_processing.clusters:nodegroup-templates-tab')
|
||||
DETAILS_URL = reverse(
|
||||
'horizon:project:data_processing.nodegroup_templates:details',
|
||||
'horizon:project:data_processing.clusters:details',
|
||||
args=['id'])
|
||||
CREATE_URL = reverse(
|
||||
'horizon:project:data_processing.nodegroup_templates:' +
|
||||
'horizon:project:data_processing.clusters:' +
|
||||
'configure-nodegroup-template')
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ class DataProcessingNodeGroupTests(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse(
|
||||
'horizon:project:data_processing.nodegroup_templates:copy',
|
||||
'horizon:project:data_processing.clusters:copy',
|
||||
args=[ngt.id])
|
||||
res = self.client.get(url)
|
||||
|
||||
@ -73,10 +73,9 @@ class DataProcessingNodeGroupTests(test.TestCase):
|
||||
api.sahara.nodegroup_template_list(IsA(http.HttpRequest), {}) \
|
||||
.AndReturn(self.nodegroup_templates.list())
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.nodegroup_templates/'
|
||||
'nodegroup_templates.html')
|
||||
res = self.client.get(INDEX_URL +
|
||||
"?tab=cluster_tabs__node_group_templates_tab")
|
||||
self.assertTemplateUsed(res, 'clusters/index.html')
|
||||
self.assertContains(res, 'Node Group Templates')
|
||||
self.assertContains(res, 'Name')
|
||||
self.assertContains(res, 'Plugin')
|
||||
@ -232,7 +231,7 @@ class DataProcessingNodeGroupTests(test.TestCase):
|
||||
configs = self.plugins_configs.first()
|
||||
new_name = ngt.name + '-updated'
|
||||
UPDATE_URL = reverse(
|
||||
'horizon:project:data_processing.nodegroup_templates:edit',
|
||||
'horizon:project:data_processing.clusters:edit',
|
||||
kwargs={'template_id': ngt.id})
|
||||
self.mox.StubOutWithMock(
|
||||
workflow_helpers, 'parse_configs_from_context')
|
@ -22,22 +22,21 @@ from horizon import workflows
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.tables as _tables
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.tabs as _tabs
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.copy as copy_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.edit as edit_flow
|
||||
|
||||
|
||||
class NodegroupTemplatesView(tables.DataTableView):
|
||||
table_class = _tables.NodegroupTemplatesTable
|
||||
template_name = (
|
||||
'project/data_processing.nodegroup_templates/nodegroup_templates.html')
|
||||
template_name = 'nodegroup_templates/nodegroup_templates.html'
|
||||
page_title = _("Node Group Templates")
|
||||
|
||||
def get_data(self):
|
||||
@ -69,7 +68,7 @@ class NodegroupTemplateDetailsView(tabs.TabView):
|
||||
msg = _('Unable to retrieve details for '
|
||||
'node group template "%s".') % ngt_id
|
||||
redirect = reverse("horizon:project:data_processing."
|
||||
"nodegroup_templates:nodegroup-templates")
|
||||
"clusters:nodegroup-templates")
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
@ -88,18 +87,18 @@ class NodegroupTemplateDetailsView(tabs.TabView):
|
||||
class CreateNodegroupTemplateView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.CreateNodegroupTemplate
|
||||
success_url = (
|
||||
"horizon:project:data_processing.nodegroup_templates:"
|
||||
"horizon:project:data_processing.clusters:"
|
||||
"create-nodegroup-template")
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "project/data_processing.nodegroup_templates/create.html"
|
||||
template_name = "nodegroup_templates/create.html"
|
||||
page_title = _("Create Node Group Template")
|
||||
|
||||
|
||||
class ConfigureNodegroupTemplateView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.ConfigureNodegroupTemplate
|
||||
success_url = "horizon:project:data_processing.nodegroup_templates"
|
||||
template_name = (
|
||||
"project/data_processing.nodegroup_templates/configure.html")
|
||||
success_url = ("horizon:project:"
|
||||
"data_processing.clusters:nodegroup-templates-tab")
|
||||
template_name = "nodegroup_templates/configure.html"
|
||||
page_title = _("Create Node Group Template")
|
||||
|
||||
def get_initial(self):
|
||||
@ -110,9 +109,9 @@ class ConfigureNodegroupTemplateView(workflows.WorkflowView):
|
||||
|
||||
class CopyNodegroupTemplateView(workflows.WorkflowView):
|
||||
workflow_class = copy_flow.CopyNodegroupTemplate
|
||||
success_url = "horizon:project:data_processing.nodegroup_templates"
|
||||
template_name = (
|
||||
"project/data_processing.nodegroup_templates/configure.html")
|
||||
success_url = ("horizon:project:"
|
||||
"data_processing.clusters:nodegroup-templates-tab")
|
||||
template_name = "nodegroup_templates/configure.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CopyNodegroupTemplateView, self)\
|
||||
@ -142,6 +141,6 @@ class CopyNodegroupTemplateView(workflows.WorkflowView):
|
||||
|
||||
class EditNodegroupTemplateView(CopyNodegroupTemplateView):
|
||||
workflow_class = edit_flow.EditNodegroupTemplate
|
||||
success_url = "horizon:project:data_processing.nodegroup_templates"
|
||||
template_name = (
|
||||
"project/data_processing.nodegroup_templates/configure.html")
|
||||
success_url = ("horizon:project:"
|
||||
"data_processing.clusters:nodegroup-templates-tab")
|
||||
template_name = "nodegroup_templates/configure.html"
|
@ -17,7 +17,7 @@ from horizon import exceptions
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.create as create_flow
|
||||
|
||||
|
@ -228,9 +228,7 @@ class GeneralConfigAction(workflows.Action):
|
||||
|
||||
class Meta(object):
|
||||
name = _("Configure Node Group Template")
|
||||
help_text_template = (
|
||||
"project/data_processing.nodegroup_templates"
|
||||
"/_configure_general_help.html")
|
||||
help_text_template = "nodegroup_templates/_configure_general_help.html"
|
||||
|
||||
|
||||
class SecurityConfigAction(workflows.Action):
|
||||
@ -419,7 +417,8 @@ class ConfigureNodegroupTemplate(workflow_helpers.ServiceParametersWorkflow,
|
||||
finalize_button_name = _("Create")
|
||||
success_message = _("Created Node Group Template %s")
|
||||
name_property = "general_nodegroup_name"
|
||||
success_url = "horizon:project:data_processing.nodegroup_templates:index"
|
||||
success_url = ("horizon:project:data_processing.clusters:"
|
||||
"nodegroup-templates-tab")
|
||||
default_steps = (GeneralConfig, SelectNodeProcesses, SecurityConfig, )
|
||||
|
||||
def __init__(self, request, context_seed, entry_point, *args, **kwargs):
|
||||
@ -559,8 +558,7 @@ class SelectPluginAction(workflows.Action,
|
||||
|
||||
class Meta(object):
|
||||
name = _("Select plugin and hadoop version")
|
||||
help_text_template = ("project/data_processing.nodegroup_templates"
|
||||
"/_create_general_help.html")
|
||||
help_text_template = "nodegroup_templates/_create_general_help.html"
|
||||
|
||||
|
||||
class SelectPlugin(workflows.Step):
|
||||
@ -581,5 +579,6 @@ class CreateNodegroupTemplate(workflows.Workflow):
|
||||
finalize_button_name = _("Next")
|
||||
success_message = _("Created")
|
||||
failure_message = _("Could not create")
|
||||
success_url = "horizon:project:data_processing.nodegroup_templates:index"
|
||||
success_url = ("horizon:project:data_processing.clusters:"
|
||||
"nodegroup-templates-tab")
|
||||
default_steps = (SelectPlugin,)
|
@ -19,9 +19,9 @@ from horizon import forms
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
nodegroup_templates.workflows.copy as copy_flow
|
||||
from sahara_dashboard.content.data_processing.utils \
|
||||
import workflow_helpers
|
@ -13,7 +13,7 @@
|
||||
</dl>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Plugin" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.data_plugins:details' template.plugin_name %}">{{ template.plugin_name }}</a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.jobs:details' template.plugin_name %}">{{ template.plugin_name }}</a></dd>
|
||||
<dt>{% trans "Version" %}</dt>
|
||||
<dd>{{ template.hadoop_version }}</dd>
|
||||
<dt>{% trans "Use auto-configuration" %}</dt>
|
@ -12,7 +12,7 @@
|
||||
|
||||
<dt>{% trans "Template" %}</dt>
|
||||
{% if node_group.node_group_template_id %}
|
||||
<dd><a href="{% url 'horizon:project:data_processing.nodegroup_templates:details' node_group.node_group_template_id %}">{{ node_group.node_group_template.name }} </a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.clusters:details' node_group.node_group_template_id %}">{{ node_group.node_group_template.name }} </a></dd>
|
||||
{% else %}
|
||||
<dd>{% trans "Template not specified" %}</dd>
|
||||
{% endif %}
|
@ -4,7 +4,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}upload_file{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.cluster_templates:upload_file' %}{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.clusters:upload_file' %}{% endblock %}
|
||||
{% block form_attrs %}enctype="multipart/form-data"{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Upload Template" %}{% endblock %}
|
||||
@ -19,5 +19,5 @@
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" id="upload_file_btn" type="submit" value="{% trans "Upload" %}"/>
|
||||
<a href="{% url 'horizon:project:data_processing.cluster_templates:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
<a href="{% url 'horizon:project:data_processing.clusters:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -59,5 +59,4 @@
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -3,5 +3,5 @@
|
||||
{% block title %}{% trans "Upload Template" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/data_processing.cluster_templates/_upload_file.html' %}
|
||||
{% include 'cluster_templates/_upload_file.html' %}
|
||||
{% endblock %}
|
@ -29,19 +29,21 @@
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Plugin" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.data_plugins:details' cluster.plugin_name %}">{{ cluster.plugin_name }}</a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.jobs:plugin-details' cluster.plugin_name %}">{{ cluster.plugin_name }}</a></dd>
|
||||
<dt>{% trans "Version" %}</dt>
|
||||
<dd>{{ cluster.hadoop_version }}</dd>
|
||||
</dl>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Template" %}</dt>
|
||||
{% if cluster_template %}
|
||||
<dd><a href="{% url 'horizon:project:data_processing.cluster_templates:details' cluster_template.id %}">{{ cluster_template.name }} </a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.clusters:ct-details' cluster_template.id %}">{{ cluster_template.name }} </a></dd>
|
||||
{% else %}
|
||||
<dd>{% trans "Template not specified" %}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Base Image" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:images:images:detail' base_image.id %}">{{ base_image.name }}</a></dd>
|
||||
{% if base_image.id %}
|
||||
<dt>{% trans "Base Image" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:images:images:detail' base_image.id %}">{{ base_image.name }}</a></dd>
|
||||
{% endif %}
|
||||
{% if network %}
|
||||
<dt>{% trans "Neutron Management Network" %}</dt>
|
||||
<dd>{{ network }}</dd>
|
@ -18,7 +18,7 @@
|
||||
|
||||
<dt>{% trans "Template" %}</dt>
|
||||
{% if node_group.node_group_template_id %}
|
||||
<dd><a href="{% url 'horizon:project:data_processing.nodegroup_templates:details' node_group.node_group_template_id %}">{{ node_group.node_group_template.name }} </a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.clusters:details' node_group.node_group_template_id %}">{{ node_group.node_group_template.name }} </a></dd>
|
||||
{% else %}
|
||||
<dd>{% trans "Template not specified" %}</dd>
|
||||
{% endif %}
|
@ -3,5 +3,5 @@
|
||||
{% block title %}{% trans "Launch Cluster" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'templates/data_processing.clusters/_create_cluster.html' %}
|
||||
{% include 'clusters/_create_cluster.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,155 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Clusters" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
if ($("#id_tags_list").val()) {
|
||||
var tags = JSON.parse($("#id_tags_list").val());
|
||||
$.each(tags, function (i, tag) {
|
||||
var tagspan = '<span class="label label-info" style="float: left;display: block; margin: 2px;">' +
|
||||
tag +
|
||||
'<i class="fa fa-close" onclick="remove_tag(this);"></i></span>';
|
||||
$("#image_tags_list").append(tagspan);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
// ensure that we only do this for the cluster template form
|
||||
if (($(modal).find("#create_cluster_template__selectpluginaction")).length > 0) {
|
||||
var $navbar = $(modal).find(".nav-tabs");
|
||||
if ($navbar.find("li").size() == 1) {
|
||||
// hide tab bar for plugin/version modal wizard
|
||||
$navbar.hide();
|
||||
}
|
||||
var add_ng_btn_label = '{% trans "Add Node Group" %}';
|
||||
$(".hidden_nodegroups_field").after("<input type='button' id='add_nodegroup' value='" + add_ng_btn_label + "'/><br/>");
|
||||
$("#add_nodegroup").click(function() {
|
||||
$(".hidden_nodegroups_field").val("create_nodegroup");
|
||||
$(".hidden_configure_field").val("create_nodegroup");
|
||||
var form = $(".hidden_nodegroups_field").closest("form");
|
||||
form.submit();
|
||||
});
|
||||
|
||||
|
||||
$(".hidden_nodegroups_field").val("");
|
||||
$(".hidden_configure_field").val("");
|
||||
|
||||
if ($(modal).find(".hidden_create_field").length > 0) {
|
||||
var form = $(".hidden_create_field").closest("form");
|
||||
var successful = false;
|
||||
form.submit(function (e) {
|
||||
var oldHref = $(".configure-clustertemplate-btn")[0].href;
|
||||
var plugin = $("#id_plugin_name option:selected").val();
|
||||
var version = $("#id_" + plugin + "_version option:selected").val();
|
||||
form.find(".close").click();
|
||||
$(".configure-clustertemplate-btn")[0].href = oldHref +
|
||||
"?plugin_name=" + encodeURIComponent(plugin) +
|
||||
"&hadoop_version=" + encodeURIComponent(version);
|
||||
$(".configure-clustertemplate-btn").click();
|
||||
$(".configure-clustertemplate-btn")[0].href = oldHref;
|
||||
return false;
|
||||
});
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
}
|
||||
}
|
||||
|
||||
//display version for selected plugin
|
||||
$(document).on('change', '.plugin_name_choice', switch_versions);
|
||||
function switch_versions() {
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
var plugin = $(this);
|
||||
$("." + plugin.val() + "_version_choice").closest(".form-group").show();
|
||||
}
|
||||
$(".plugin_name_choice").change();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
function get_service_tab(service) {
|
||||
return $("a").filter(function (idx, e) {
|
||||
return $(e).attr("data-target") && $(e).attr("data-target").indexOf('_'+service.toLowerCase()+'-') != -1
|
||||
}).closest("li");
|
||||
}
|
||||
|
||||
// replace form submit with ajax POST and trigger next workflow
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
// ensure that we only do this for the nodegroup template form
|
||||
if (($(modal).find("#create_nodegroup_template__selectpluginaction")).length > 0) {
|
||||
var $navbar = $(modal).find(".nav-tabs");
|
||||
if ($navbar.find("li").size() == 1) {
|
||||
// hide tab bar for plugin/version modal wizard
|
||||
$navbar.hide();
|
||||
}
|
||||
|
||||
if ($(modal).find(".hidden_create_field").length > 0) {
|
||||
var form = $(".hidden_create_field").closest("form");
|
||||
var successful = false;
|
||||
form.submit(function (e) {
|
||||
var oldHref = $(".configure-nodegrouptemplate-btn")[0].href;
|
||||
var plugin = $("#id_plugin_name option:selected").val();
|
||||
var version = $("#id_" + plugin + "_version option:selected").val();
|
||||
form.find(".close").click();
|
||||
$(".configure-nodegrouptemplate-btn")[0].href = oldHref +
|
||||
"?plugin_name=" + encodeURIComponent(plugin) +
|
||||
"&hadoop_version=" + encodeURIComponent(version);
|
||||
$(".configure-nodegrouptemplate-btn").click();
|
||||
$(".configure-nodegrouptemplate-btn")[0].href = oldHref;
|
||||
return false;
|
||||
});
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
}
|
||||
}
|
||||
|
||||
//display version for selected plugin
|
||||
$(document).on('change', '.plugin_name_choice', switch_versions);
|
||||
function switch_versions() {
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
var plugin = $(this);
|
||||
$("." + plugin.val() + "_version_choice").closest(".form-group").show();
|
||||
}
|
||||
|
||||
$(".plugin_name_choice").change();
|
||||
|
||||
//handle node processes change
|
||||
$("input").filter(function (idx, e) {
|
||||
return $(e).attr("name") && $(e).attr("name").indexOf("processes") != -1
|
||||
})
|
||||
.change(function () {
|
||||
var process_service = $(this).val();
|
||||
var service = $(this).val().split(":")[0];
|
||||
var enabled = false;
|
||||
$(this).closest("ul").find("input").each(function (idx, el) {
|
||||
if ($(el).val().split(":")[0] != service) {
|
||||
return;
|
||||
}
|
||||
enabled |= $(el).is(':checked');
|
||||
});
|
||||
if (enabled) {
|
||||
get_service_tab(service).show();
|
||||
} else {
|
||||
get_service_tab(service).hide();
|
||||
}
|
||||
}).change();
|
||||
//general tab should be active
|
||||
get_service_tab("generalconfigaction").find("a").click();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -4,7 +4,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}edit_tags_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.data_image_registry:edit_tags' image.id %}{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.clusters:edit_tags' image.id %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Edit Image Tags" %}{% endblock %}
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
{% include 'project/data_processing.data_image_registry/_tag_form.html' %}
|
||||
{% include 'data_image_registry/_tag_form.html' %}
|
||||
</div>
|
||||
<div class="right">
|
||||
{% include 'project/data_processing.data_image_registry/_help.html' %}
|
||||
{% include 'data_image_registry/_help.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" id="edit_image_tags_btn" type="submit" value="{% trans "Done" %}"/>
|
||||
<a href="{% url 'horizon:project:data_processing.data_image_registry:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
<a href="{% url 'horizon:project:data_processing.clusters:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -4,7 +4,7 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}register_image_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.data_image_registry:register' %}{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:project:data_processing.clusters:register' %}{% endblock %}
|
||||
|
||||
{% block modal-header %}{% trans "Register Image" %}{% endblock %}
|
||||
|
||||
@ -12,15 +12,15 @@
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
{% include 'project/data_processing.data_image_registry/_tag_form.html' %}
|
||||
{% include 'data_image_registry/_tag_form.html' %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
{% include 'project/data_processing.data_image_registry/_help.html' %}
|
||||
{% include 'data_image_registry/_help.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block modal-footer %}
|
||||
<input class="btn btn-primary pull-right" id="edit_image_tags_btn" type="submit" value="{% trans "Done" %}"/>
|
||||
<a href="{% url 'horizon:project:data_processing.data_image_registry:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
<a href="{% url 'horizon:project:data_processing.clusters:index' %}" class="btn btn-default secondary cancel close">{% trans "Cancel" %}</a>
|
||||
{% endblock %}
|
@ -3,5 +3,5 @@
|
||||
{% block title %}{% trans "Edit Image Tags" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/data_processing.data_image_registry/_edit_tags.html' %}
|
||||
{% include 'data_image_registry/_edit_tags.html' %}
|
||||
{% endblock %}
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="image_registry">
|
||||
{{ image_registry_table.render }}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -3,5 +3,5 @@
|
||||
{% block title %}{% trans "Register Image" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include 'project/data_processing.data_image_registry/_register_image.html' %}
|
||||
{% include 'data_image_registry/_register_image.html' %}
|
||||
{% endblock %}
|
@ -34,7 +34,7 @@
|
||||
{% endif %}
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Plugin" %}</dt>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.data_plugins:details' template.plugin_name %}">{{ template.plugin_name }}</a></dd>
|
||||
<dd><a href="{% url 'horizon:project:data_processing.jobs:details' template.plugin_name %}">{{ template.plugin_name }}</a></dd>
|
||||
<dt>{% trans "Version" %}</dt>
|
||||
<dd>{{ template.hadoop_version }}</dd>
|
||||
</dl>
|
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="nodegroup_templates">
|
||||
{{ nodegroup_templates_table.render }}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -16,28 +16,85 @@ from django.conf.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
import sahara_dashboard.content.data_processing.clusters.views as views
|
||||
|
||||
|
||||
import sahara_dashboard.content.data_processing.clusters.data_image_registry. \
|
||||
views as image_views
|
||||
import sahara_dashboard.content.data_processing.clusters.nodegroup_templates. \
|
||||
views as ngt_views
|
||||
import sahara_dashboard.content.data_processing.clusters.cluster_templates. \
|
||||
views as ct_views
|
||||
import sahara_dashboard.content.data_processing.clusters.clusters. \
|
||||
views as cluster_views
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.ClustersView.as_view(),
|
||||
url(r'^$', views.IndexView.as_view(),
|
||||
name='index'),
|
||||
url(r'^$', views.ClustersView.as_view(),
|
||||
name='clusters'),
|
||||
url(r'^\?tab=cluster_tabs__data_image_registry_tab$',
|
||||
views.IndexView.as_view(),
|
||||
name='image-registry-tab'),
|
||||
url(r'^\?tab=cluster_tabs__node_group_templates_tab$',
|
||||
views.IndexView.as_view(),
|
||||
name='nodegroup-templates-tab'),
|
||||
url(r'^\?tab=cluster_tabs__clusters_templates_tab$',
|
||||
views.IndexView.as_view(),
|
||||
name='cluster-templates-tab'),
|
||||
url(r'^\?tab=cluster_tabs__clusters_tab$',
|
||||
views.IndexView.as_view(),
|
||||
name='clusters-tab'),
|
||||
url(r'^upload_file$',
|
||||
ct_views.UploadFileView.as_view(),
|
||||
name='upload_file'),
|
||||
url(r'^create-cluster-template$',
|
||||
ct_views.CreateClusterTemplateView.as_view(),
|
||||
name='create-cluster-template'),
|
||||
url(r'^create-nodegroup-template$',
|
||||
ngt_views.CreateNodegroupTemplateView.as_view(),
|
||||
name='create-nodegroup-template'),
|
||||
url(r'^configure-cluster-template$',
|
||||
ct_views.ConfigureClusterTemplateView.as_view(),
|
||||
name='configure-cluster-template'),
|
||||
url(r'^configure-nodegroup-template$',
|
||||
ngt_views.ConfigureNodegroupTemplateView.as_view(),
|
||||
name='configure-nodegroup-template'),
|
||||
url(r'^cluster-template/(?P<template_id>[^/]+)$',
|
||||
ct_views.ClusterTemplateDetailsView.as_view(),
|
||||
name='ct-details'),
|
||||
url(r'^node-group-template/(?P<template_id>[^/]+)$',
|
||||
ngt_views.NodegroupTemplateDetailsView.as_view(),
|
||||
name='details'),
|
||||
url(r'^cluster-template/(?P<template_id>[^/]+)/copy$',
|
||||
ct_views.CopyClusterTemplateView.as_view(),
|
||||
name='ct-copy'),
|
||||
url(r'^cluster-template/(?P<template_id>[^/]+)/edit$',
|
||||
ct_views.EditClusterTemplateView.as_view(),
|
||||
name='ct-edit'),
|
||||
url(r'^node-group-template/'
|
||||
'(?P<template_id>[^/]+)/copy$',
|
||||
ngt_views.CopyNodegroupTemplateView.as_view(),
|
||||
name='copy'),
|
||||
url(r'^node-group-template/'
|
||||
'(?P<template_id>[^/]+)/edit$',
|
||||
ngt_views.EditNodegroupTemplateView.as_view(),
|
||||
name='edit'),
|
||||
url(r'^create-cluster$',
|
||||
views.CreateClusterView.as_view(),
|
||||
cluster_views.CreateClusterView.as_view(),
|
||||
name='create-cluster'),
|
||||
url(r'^configure-cluster$',
|
||||
views.ConfigureClusterView.as_view(),
|
||||
cluster_views.ConfigureClusterView.as_view(),
|
||||
name='configure-cluster'),
|
||||
url(r'^(?P<cluster_id>[^/]+)$',
|
||||
views.ClusterDetailsView.as_view(),
|
||||
name='details'),
|
||||
url(r'^(?P<cluster_id>[^/]+)/events$',
|
||||
views.ClusterEventsView.as_view(),
|
||||
url(r'^cluster/(?P<cluster_id>[^/]+)$',
|
||||
cluster_views.ClusterDetailsView.as_view(),
|
||||
name='cluster-details'),
|
||||
url(r'^cluster/(?P<cluster_id>[^/]+)/events$',
|
||||
cluster_views.ClusterEventsView.as_view(),
|
||||
name='events'),
|
||||
url(r'^(?P<cluster_id>[^/]+)/scale$',
|
||||
views.ScaleClusterView.as_view(),
|
||||
url(r'^cluster/(?P<cluster_id>[^/]+)/scale$',
|
||||
cluster_views.ScaleClusterView.as_view(),
|
||||
name='scale'),
|
||||
url(r'^(?P<cluster_id>[^/]+)/update_shares$',
|
||||
views.UpdateClusterSharesView.as_view(),
|
||||
name='update-shares'))
|
||||
url(r'^cluster/(?P<cluster_id>[^/]+)/update_shares$',
|
||||
cluster_views.UpdateClusterSharesView.as_view(),
|
||||
name='update-shares'),
|
||||
url(r'^edit_tags/(?P<image_id>[^/]+)/$',
|
||||
image_views.EditTagsView.as_view(),
|
||||
name='edit_tags'),
|
||||
url(r'^register/$',
|
||||
image_views.RegisterImageView.as_view(),
|
||||
name='register'))
|
||||
|
@ -11,256 +11,29 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from datetime import datetime
|
||||
import json
|
||||
import logging
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import base as django_base
|
||||
import six
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import tables
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
from horizon import workflows
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
tables as c_tables
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
tabs as _tabs
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
workflows.create as create_flow
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
workflows.scale as scale_flow
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
workflows.update as update_flow
|
||||
from saharaclient.api.base import APIException
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
from sahara_dashboard.content.data_processing.clusters.cluster_templates \
|
||||
import tabs as cluster_templates_tabs
|
||||
from sahara_dashboard.content.data_processing.clusters.clusters \
|
||||
import tabs as clusters_tabs
|
||||
from sahara_dashboard.content.data_processing.clusters.data_image_registry \
|
||||
import tabs as data_image_registry_tabs
|
||||
from sahara_dashboard.content.data_processing.clusters.nodegroup_templates \
|
||||
import tabs as node_group_templates_tabs
|
||||
|
||||
|
||||
class ClustersView(tables.DataTableView):
|
||||
table_class = c_tables.ClustersTable
|
||||
template_name = 'project/data_processing.clusters/clusters.html'
|
||||
class ClusterTabs(tabs.TabGroup):
|
||||
slug = "cluster_tabs"
|
||||
tabs = (clusters_tabs.ClustersTab,
|
||||
cluster_templates_tabs.ClusterTemplatesTab,
|
||||
node_group_templates_tabs.NodeGroupTemplatesTab,
|
||||
data_image_registry_tabs.DataImageRegistryTab,)
|
||||
sticky = True
|
||||
|
||||
|
||||
class IndexView(tabs.TabbedTableView):
|
||||
tab_group_class = ClusterTabs
|
||||
template_name = "clusters/index.html"
|
||||
page_title = _("Clusters")
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
search_opts = {}
|
||||
filter = self.get_server_filter_info(self.request)
|
||||
if filter['value'] and filter['field']:
|
||||
search_opts = {filter['field']: filter['value']}
|
||||
clusters = saharaclient.cluster_list(self.request, search_opts)
|
||||
except Exception:
|
||||
clusters = []
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster list"))
|
||||
return clusters
|
||||
|
||||
|
||||
class ClusterDetailsView(tabs.TabView):
|
||||
tab_group_class = _tabs.ClusterDetailsTabs
|
||||
template_name = 'horizon/common/_detail.html'
|
||||
page_title = "{{ cluster.name|default:cluster.id }}"
|
||||
|
||||
@memoized.memoized_method
|
||||
def get_object(self):
|
||||
cl_id = self.kwargs["cluster_id"]
|
||||
try:
|
||||
return saharaclient.cluster_get(self.request, cl_id)
|
||||
except Exception:
|
||||
msg = _('Unable to retrieve details for cluster "%s".') % cl_id
|
||||
redirect = reverse(
|
||||
"horizon:project:data_processing.clusters:clusters")
|
||||
exceptions.handle(self.request, msg, redirect=redirect)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ClusterDetailsView, self).get_context_data(**kwargs)
|
||||
cluster = self.get_object()
|
||||
context['cluster'] = cluster
|
||||
context['actions'] = self._get_actions(cluster)
|
||||
return context
|
||||
|
||||
def _get_actions(self, cluster):
|
||||
table = c_tables.ClustersTable(self.request)
|
||||
return table.render_row_actions(cluster)
|
||||
|
||||
|
||||
class ClusterEventsView(django_base.View):
|
||||
|
||||
_date_format = "%Y-%m-%dT%H:%M:%S"
|
||||
|
||||
@staticmethod
|
||||
def _created_at_key(obj):
|
||||
return datetime.strptime(obj["created_at"],
|
||||
ClusterEventsView._date_format)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
cluster_id = kwargs.get("cluster_id")
|
||||
|
||||
try:
|
||||
cluster = saharaclient.cluster_get(request, cluster_id,
|
||||
show_progress=True)
|
||||
node_group_mapping = {}
|
||||
for node_group in cluster.node_groups:
|
||||
node_group_mapping[node_group["id"]] = node_group["name"]
|
||||
|
||||
provision_steps = cluster.provision_progress
|
||||
|
||||
# Sort by create time
|
||||
provision_steps = sorted(provision_steps,
|
||||
key=ClusterEventsView._created_at_key,
|
||||
reverse=True)
|
||||
|
||||
for step in provision_steps:
|
||||
# Sort events of the steps also
|
||||
step["events"] = sorted(step["events"],
|
||||
key=ClusterEventsView._created_at_key,
|
||||
reverse=True)
|
||||
|
||||
successful_events_count = 0
|
||||
|
||||
for event in step["events"]:
|
||||
if event["node_group_id"]:
|
||||
event["node_group_name"] = node_group_mapping[
|
||||
event["node_group_id"]]
|
||||
|
||||
event_result = _("Unknown")
|
||||
if event["successful"] is True:
|
||||
successful_events_count += 1
|
||||
event_result = _("Completed Successfully")
|
||||
elif event["successful"] is False:
|
||||
event_result = _("Failed")
|
||||
|
||||
event["result"] = event_result
|
||||
|
||||
if not event["event_info"]:
|
||||
event["event_info"] = _("No info available")
|
||||
|
||||
start_time = datetime.strptime(step["created_at"],
|
||||
self._date_format)
|
||||
end_time = datetime.now()
|
||||
# Clear out microseconds. There is no need for that precision.
|
||||
end_time = end_time.replace(microsecond=0)
|
||||
if step["successful"] is not None:
|
||||
updated_at = step["updated_at"]
|
||||
end_time = datetime.strptime(updated_at,
|
||||
self._date_format)
|
||||
step["duration"] = six.text_type(end_time - start_time)
|
||||
|
||||
result = _("In progress")
|
||||
step["completed"] = successful_events_count
|
||||
|
||||
if step["successful"] is True:
|
||||
step["completed"] = step["total"]
|
||||
result = _("Completed Successfully")
|
||||
elif step["successful"] is False:
|
||||
result = _("Failed")
|
||||
|
||||
step["result"] = result
|
||||
|
||||
status = cluster.status.lower()
|
||||
need_update = status not in ("active", "error")
|
||||
except APIException:
|
||||
# Cluster is not available. Returning empty event log.
|
||||
need_update = False
|
||||
provision_steps = []
|
||||
|
||||
context = {"provision_steps": provision_steps,
|
||||
"need_update": need_update}
|
||||
|
||||
return HttpResponse(json.dumps(context),
|
||||
content_type='application/json')
|
||||
|
||||
|
||||
class CreateClusterView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.CreateCluster
|
||||
success_url = \
|
||||
"horizon:project:data_processing.clusters:create-cluster"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "project/data_processing.clusters/create.html"
|
||||
page_title = _("Launch Cluster")
|
||||
|
||||
|
||||
class ConfigureClusterView(workflows.WorkflowView):
|
||||
workflow_class = create_flow.ConfigureCluster
|
||||
success_url = "horizon:project:data_processing.clusters"
|
||||
template_name = "project/data_processing.clusters/configure.html"
|
||||
page_title = _("Configure Cluster")
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(ConfigureClusterView, self).get_initial()
|
||||
initial.update(self.kwargs)
|
||||
return initial
|
||||
|
||||
|
||||
class ScaleClusterView(workflows.WorkflowView):
|
||||
workflow_class = scale_flow.ScaleCluster
|
||||
success_url = "horizon:project:data_processing.clusters"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "project/data_processing.clusters/scale.html"
|
||||
page_title = _("Scale Cluster")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ScaleClusterView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
|
||||
context["cluster_id"] = kwargs["cluster_id"]
|
||||
return context
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
template_id = self.kwargs['cluster_id']
|
||||
try:
|
||||
template = saharaclient.cluster_template_get(self.request,
|
||||
template_id)
|
||||
except Exception:
|
||||
template = None
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster template."))
|
||||
self._object = template
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(ScaleClusterView, self).get_initial()
|
||||
initial.update({'cluster_id': self.kwargs['cluster_id']})
|
||||
return initial
|
||||
|
||||
|
||||
class UpdateClusterSharesView(workflows.WorkflowView):
|
||||
workflow_class = update_flow.UpdateShares
|
||||
success_url = "horizon:project:data_processing.clusters"
|
||||
classes = ("ajax-modal",)
|
||||
template_name = "project/data_processing.clusters/update.html"
|
||||
page_title = _("Update Cluster Shares")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UpdateClusterSharesView, self)\
|
||||
.get_context_data(**kwargs)
|
||||
context["cluster_id"] = kwargs["cluster_id"]
|
||||
return context
|
||||
|
||||
def get_object(self, *args, **kwargs):
|
||||
if not hasattr(self, "_object"):
|
||||
cluster_id = self.kwargs['cluster_id']
|
||||
try:
|
||||
cluster = saharaclient.cluster_get(self.request, cluster_id)
|
||||
except Exception:
|
||||
cluster = None
|
||||
exceptions.handle(self.request,
|
||||
_("Unable to fetch cluster."))
|
||||
self._object = cluster
|
||||
return self._object
|
||||
|
||||
def get_initial(self):
|
||||
initial = super(UpdateClusterSharesView, self).get_initial()
|
||||
initial.update({
|
||||
'cluster_id': self.kwargs['cluster_id'],
|
||||
'cluster': self.get_object()})
|
||||
return initial
|
||||
|
@ -1,28 +0,0 @@
|
||||
# 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 openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class ImageRegistryPanel(horizon.Panel):
|
||||
name = _("Image Registry")
|
||||
slug = 'data_processing.data_image_registry'
|
||||
permissions = (('openstack.services.data-processing',
|
||||
'openstack.services.data_processing'),)
|
||||
|
||||
|
||||
dashboard.Project.register(ImageRegistryPanel)
|
@ -1,24 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="image_registry">
|
||||
{{ image_registry_table.render }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
var tags = JSON.parse($("#id_tags_list").val());
|
||||
$.each(tags, function(i, tag) {
|
||||
var tagspan = '<span class="label label-info" style="float: left;display: block; margin: 2px;">' +
|
||||
tag +
|
||||
'<i class="fa fa-close" onclick="remove_tag(this);"></i></span>';
|
||||
$("#image_tags_list").append(tagspan);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
@ -1,33 +0,0 @@
|
||||
# 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.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
import sahara_dashboard.content. \
|
||||
data_processing.data_image_registry.views as views
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.ImageRegistryView.as_view(),
|
||||
name='index'),
|
||||
url(r'^$', views.ImageRegistryView.as_view(),
|
||||
name='image_registry'),
|
||||
url(r'^edit_tags/(?P<image_id>[^/]+)/$',
|
||||
views.EditTagsView.as_view(),
|
||||
name='edit_tags'),
|
||||
url(r'^register/$',
|
||||
views.RegisterImageView.as_view(),
|
||||
name='register'),
|
||||
)
|
@ -21,10 +21,10 @@ from horizon import forms
|
||||
from horizon import workflows
|
||||
|
||||
from sahara_dashboard.api import sahara as saharaclient
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
import sahara_dashboard.content.data_processing.clusters. \
|
||||
cluster_templates.workflows.create as t_flows
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
clusters.workflows.create as c_flow
|
||||
clusters.clusters.workflows.create as c_flow
|
||||
from sahara_dashboard.content.data_processing.utils \
|
||||
import acl as acl_utils
|
||||
import sahara_dashboard.content.data_processing. \
|
||||
|
@ -1,28 +0,0 @@
|
||||
# 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 openstack_dashboard.dashboards.project import dashboard
|
||||
|
||||
|
||||
class NodegroupTemplatesPanel(horizon.Panel):
|
||||
name = _("Node Group Templates")
|
||||
slug = 'data_processing.nodegroup_templates'
|
||||
permissions = (('openstack.services.data-processing',
|
||||
'openstack.services.data_processing'),)
|
||||
|
||||
|
||||
dashboard.Project.register(NodegroupTemplatesPanel)
|
@ -1,81 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="nodegroup_templates">
|
||||
{{ nodegroup_templates_table.render }}
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
addHorizonLoadEvent(function () {
|
||||
function get_service_tab(service) {
|
||||
return $("a").filter(function (idx, e) {
|
||||
return $(e).attr("data-target") && $(e).attr("data-target").indexOf('_'+service.toLowerCase()+'-') != -1
|
||||
}).closest("li");
|
||||
}
|
||||
|
||||
// replace form submit with ajax POST and trigger next workflow
|
||||
horizon.modals.addModalInitFunction(function (modal) {
|
||||
var $navbar = $(modal).find(".nav-tabs");
|
||||
if ($navbar.find("li").size() == 1) {
|
||||
// hide tab bar for plugin/version modal wizard
|
||||
$navbar.hide();
|
||||
}
|
||||
|
||||
if ($(modal).find(".hidden_create_field").length > 0) {
|
||||
var form = $(".hidden_create_field").closest("form");
|
||||
var successful = false;
|
||||
form.submit(function (e) {
|
||||
var oldHref = $(".configure-nodegrouptemplate-btn")[0].href;
|
||||
var plugin = $("#id_plugin_name option:selected").val();
|
||||
var version = $("#id_" + plugin + "_version option:selected").val();
|
||||
form.find(".close").click();
|
||||
$(".configure-nodegrouptemplate-btn")[0].href = oldHref +
|
||||
"?plugin_name=" + encodeURIComponent(plugin) +
|
||||
"&hadoop_version=" + encodeURIComponent(version);
|
||||
$(".configure-nodegrouptemplate-btn").click();
|
||||
$(".configure-nodegrouptemplate-btn")[0].href = oldHref;
|
||||
return false;
|
||||
});
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
}
|
||||
|
||||
//display version for selected plugin
|
||||
$(document).on('change', '.plugin_name_choice', switch_versions);
|
||||
function switch_versions() {
|
||||
$(".plugin_version_choice").closest(".form-group").hide();
|
||||
var plugin = $(this);
|
||||
$("." + plugin.val() + "_version_choice").closest(".form-group").show();
|
||||
}
|
||||
|
||||
$(".plugin_name_choice").change();
|
||||
|
||||
//handle node processes change
|
||||
$("input").filter(function (idx, e) {
|
||||
return $(e).attr("name") && $(e).attr("name").indexOf("processes") != -1
|
||||
})
|
||||
.change(function () {
|
||||
var process_service = $(this).val();
|
||||
var service = $(this).val().split(":")[0];
|
||||
var enabled = false;
|
||||
$(this).closest("ul").find("input").each(function (idx, el) {
|
||||
if ($(el).val().split(":")[0] != service) {
|
||||
return;
|
||||
}
|
||||
enabled |= $(el).is(':checked');
|
||||
});
|
||||
if (enabled) {
|
||||
get_service_tab(service).show();
|
||||
} else {
|
||||
get_service_tab(service).hide();
|
||||
}
|
||||
}).change();
|
||||
//general tab should be active
|
||||
get_service_tab("generalconfigaction").find("a").click();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
@ -1,43 +0,0 @@
|
||||
# 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.urls import patterns
|
||||
from django.conf.urls import url
|
||||
|
||||
import sahara_dashboard.content. \
|
||||
data_processing.nodegroup_templates.views as views
|
||||
|
||||
|
||||
urlpatterns = patterns('sahara.nodegroup_templates.views',
|
||||
url(r'^$', views.NodegroupTemplatesView.as_view(),
|
||||
name='index'),
|
||||
url(r'^nodegroup-templates$',
|
||||
views.NodegroupTemplatesView.as_view(),
|
||||
name='nodegroup-templates'),
|
||||
url(r'^create-nodegroup-template$',
|
||||
views.CreateNodegroupTemplateView.as_view(),
|
||||
name='create-nodegroup-template'),
|
||||
url(r'^configure-nodegroup-template$',
|
||||
views.ConfigureNodegroupTemplateView.as_view(),
|
||||
name='configure-nodegroup-template'),
|
||||
url(r'^(?P<template_id>[^/]+)$',
|
||||
views.NodegroupTemplateDetailsView.as_view(),
|
||||
name='details'),
|
||||
url(r'^(?P<template_id>[^/]+)/copy$',
|
||||
views.CopyNodegroupTemplateView.as_view(),
|
||||
name='copy'),
|
||||
url(r'^(?P<template_id>[^/]+)/edit$',
|
||||
views.EditNodegroupTemplateView.as_view(),
|
||||
name='edit')
|
||||
)
|
44
sahara_dashboard/content/data_processing/tabs.py
Normal file
44
sahara_dashboard/content/data_processing/tabs.py
Normal file
@ -0,0 +1,44 @@
|
||||
# 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 horizon import tabs
|
||||
|
||||
|
||||
class SaharaTableTab(tabs.TableTab):
|
||||
def get_server_filter_info(self, request, table):
|
||||
filter_action = table._meta._filter_action
|
||||
if filter_action is None or filter_action.filter_type != 'server':
|
||||
return None
|
||||
param_name = filter_action.get_param_name()
|
||||
filter_string = request.POST.get(param_name)
|
||||
filter_string_session = request.session.get(param_name, "")
|
||||
changed = (filter_string is not None
|
||||
and filter_string != filter_string_session)
|
||||
if filter_string is None:
|
||||
filter_string = filter_string_session
|
||||
filter_field_param = param_name + '_field'
|
||||
filter_field = request.POST.get(filter_field_param)
|
||||
filter_field_session = request.session.get(filter_field_param)
|
||||
if filter_field is None and filter_field_session is not None:
|
||||
filter_field = filter_field_session
|
||||
setattr(table.base_actions["filter"], "filter_string", filter_string)
|
||||
setattr(table.base_actions["filter"], "filter_field", filter_field)
|
||||
filter_info = {
|
||||
'action': filter_action,
|
||||
'value_param': param_name,
|
||||
'value': filter_string,
|
||||
'field_param': filter_field_param,
|
||||
'field': filter_field,
|
||||
'changed': changed
|
||||
}
|
||||
return filter_info
|
@ -89,9 +89,7 @@ def _create_step_action(name, title, parameters, advanced_fields=None,
|
||||
class_fields[ad_field_name] = ad_field_value
|
||||
|
||||
action_meta = type('Meta', (object, ),
|
||||
dict(help_text_template=("project"
|
||||
"/data_processing."
|
||||
"nodegroup_templates/"
|
||||
dict(help_text_template=("nodegroup_templates/"
|
||||
"_fields_help.html")))
|
||||
|
||||
class_fields['Meta'] = action_meta
|
||||
|
@ -128,7 +128,7 @@
|
||||
<div>
|
||||
<a class="btn btn-default btn-small btn-create btn-inline ajax-modal
|
||||
{% if not request.session.worker_name %} disabled{% endif %}"
|
||||
href="{% url 'horizon:project:data_processing.cluster_templates:configure-cluster-template' %}?plugin_name={{ request.session.plugin_name }}&hadoop_version={{ request.session.plugin_version }}&forms_ids=[0,1]&count_0=1&group_name_0={{ request.session.master_name }}&template_id_0={{ request.session.master_id }}&count_1=1&group_name_1={{ request.session.worker_name }}&template_id_1={{ request.session.worker_id }}&serialized_0=null&serialized_1=null">
|
||||
href="{% url 'horizon:project:data_processing.clusters:configure-cluster-template' %}?plugin_name={{ request.session.plugin_name }}&hadoop_version={{ request.session.plugin_version }}&forms_ids=[0,1]&count_0=1&group_name_0={{ request.session.master_name }}&template_id_0={{ request.session.master_id }}&count_1=1&group_name_1={{ request.session.worker_name }}&template_id_1={{ request.session.worker_id }}&serialized_0=null&serialized_1=null">
|
||||
<span class="fa fa-plus"></span> {% trans "Create a Cluster Template" %}</a>
|
||||
</div>
|
||||
<div>{% trans "Current choice:" %}
|
||||
|
@ -25,7 +25,8 @@ ADD_PANEL = \
|
||||
'content.data_processing.clusters.panel.ClustersPanel')
|
||||
|
||||
ADD_INSTALLED_APPS = \
|
||||
["sahara_dashboard.content.data_processing", ]
|
||||
["sahara_dashboard.content.data_processing",
|
||||
"sahara_dashboard.content.data_processing.clusters", ]
|
||||
|
||||
ADD_JS_FILES = [
|
||||
'dashboard/project/data_processing/data_processing.event_log.js'
|
||||
|
@ -1,29 +0,0 @@
|
||||
# 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 sahara_dashboard import exceptions
|
||||
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'data_processing.cluster_templates'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'data_processing'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
('sahara_dashboard.'
|
||||
'content.data_processing.cluster_templates.panel.ClusterTemplatesPanel')
|
||||
|
||||
ADD_EXCEPTIONS = {
|
||||
'recoverable': exceptions.RECOVERABLE
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
# 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 sahara_dashboard import exceptions
|
||||
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'data_processing.nodegroup_templates'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'data_processing'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
('sahara_dashboard.'
|
||||
'content.data_processing.nodegroup_templates.panel.'
|
||||
'NodegroupTemplatesPanel')
|
||||
|
||||
ADD_EXCEPTIONS = {
|
||||
'recoverable': exceptions.RECOVERABLE
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
# 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 sahara_dashboard import exceptions
|
||||
|
||||
# The slug of the panel to be added to HORIZON_CONFIG. Required.
|
||||
PANEL = 'data_processing.data_image_registry'
|
||||
# The slug of the dashboard the PANEL associated with. Required.
|
||||
PANEL_DASHBOARD = 'project'
|
||||
# The slug of the panel group the PANEL is associated with.
|
||||
PANEL_GROUP = 'data_processing'
|
||||
|
||||
# Python panel class of the PANEL to be added.
|
||||
ADD_PANEL = \
|
||||
('sahara_dashboard.'
|
||||
'content.data_processing.data_image_registry.panel.ImageRegistryPanel')
|
||||
|
||||
ADD_EXCEPTIONS = {
|
||||
'recoverable': exceptions.RECOVERABLE
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user