Adding plugins panel for Sahara
The plugins panel is used to show the various hadoop flavors/versions that are supported by the underlying Sahara API. * also added basic panel tests This code was originally from: https://github.com/openstack/sahara-dashboard Change-Id: Ib0c95334a5122529fddbfd9c0cd0d0c06e0c8ad3 Partial-Implements: blueprint merge-sahara-dashboard Co-Authored-By: Nikita Konovalov <nkonovalov@mirantis.com> Co-Authored-By: Dmitry Mescheryakov <dmescheryakov@mirantis.com>
This commit is contained in:
parent
f712ed04cc
commit
7c3897a4bd
@ -63,7 +63,8 @@ class SystemInfoViewTests(test.BaseAdminViewTests):
|
||||
'<Service: ec2>',
|
||||
'<Service: metering>',
|
||||
'<Service: orchestration>',
|
||||
'<Service: database>'])
|
||||
'<Service: database>',
|
||||
'<Service: data_processing>', ])
|
||||
|
||||
network_agents_tab = res.context['tab_group'].get_tab('network_agents')
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -57,6 +57,12 @@ class DatabasePanels(horizon.PanelGroup):
|
||||
'database_backups',)
|
||||
|
||||
|
||||
class DataProcessingPanels(horizon.PanelGroup):
|
||||
name = _("Data Processing")
|
||||
slug = "data_processing"
|
||||
panels = ('data_processing.data_plugins',)
|
||||
|
||||
|
||||
class Project(horizon.Dashboard):
|
||||
name = _("Project")
|
||||
slug = "project"
|
||||
@ -65,7 +71,8 @@ class Project(horizon.Dashboard):
|
||||
NetworkPanels,
|
||||
ObjectStorePanels,
|
||||
OrchestrationPanels,
|
||||
DatabasePanels,)
|
||||
DatabasePanels,
|
||||
DataProcessingPanels,)
|
||||
default_panel = 'overview'
|
||||
supports_tenants = True
|
||||
|
||||
|
@ -0,0 +1,26 @@
|
||||
# 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 PluginsPanel(horizon.Panel):
|
||||
name = _("Plugins")
|
||||
slug = 'data_processing.data_plugins'
|
||||
permissions = ('openstack.services.data_processing',)
|
||||
|
||||
dashboard.Project.register(PluginsPanel)
|
@ -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 import template
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import tables
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def render_versions(plugin):
|
||||
template_name = 'project/data_processing.data_plugins/_versions_list.html'
|
||||
context = {"plugin": plugin}
|
||||
return template.loader.render_to_string(template_name, context)
|
||||
|
||||
|
||||
class PluginsTable(tables.DataTable):
|
||||
title = tables.Column("title",
|
||||
verbose_name=_("Title"),
|
||||
link=("horizon:project:data_processing.data_plugins:details"))
|
||||
|
||||
versions = tables.Column(render_versions,
|
||||
verbose_name=_("Supported Versions"))
|
||||
|
||||
description = tables.Column("description",
|
||||
verbose_name=_("Description"))
|
||||
|
||||
class Meta:
|
||||
name = "plugins"
|
||||
verbose_name = _("Plugins")
|
@ -0,0 +1,46 @@
|
||||
# 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 openstack_dashboard.api import sahara as saharaclient
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DetailsTab(tabs.Tab):
|
||||
name = _("Details")
|
||||
slug = "plugin_details_tab"
|
||||
template_name = ("project/data_processing.data_plugins/_details.html")
|
||||
|
||||
def get_context_data(self, request):
|
||||
plugin_id = self.tab_group.kwargs['plugin_id']
|
||||
plugin = None
|
||||
try:
|
||||
plugin = saharaclient.plugin_get(request, plugin_id)
|
||||
except Exception as e:
|
||||
LOG.error("Unable to get plugin with plugin_id %s (%s)" %
|
||||
(plugin_id, str(e)))
|
||||
exceptions.handle(self.tab_group.request,
|
||||
_('Unable to retrieve plugin.'))
|
||||
return {"plugin": plugin}
|
||||
|
||||
|
||||
class PluginDetailsTabs(tabs.TabGroup):
|
||||
slug = "cluster_details"
|
||||
tabs = (DetailsTab,)
|
||||
sticky = True
|
@ -0,0 +1,25 @@
|
||||
{% load i18n %}
|
||||
|
||||
<h3>{% trans "Data Processing Plugin Overview" %}</h3>
|
||||
|
||||
<div class="status row-fluid detail">
|
||||
<h4>{% trans "Info" %}</h4>
|
||||
<hr class="header_rule">
|
||||
<dl>
|
||||
<dt>{% trans "Name" %}</dt>
|
||||
<dd>{{ plugin.name }}</dd>
|
||||
<dt>{% trans "Title" %}</dt>
|
||||
<dd>{{ plugin.title }}</dd>
|
||||
<dt>{% trans "Description" %}</dt>
|
||||
<dd>{{ plugin.description }}</dd>
|
||||
<dt>{% trans "Supported Versions" %}</dt>
|
||||
<dd>
|
||||
<ul>
|
||||
{% for version in plugin.versions %}
|
||||
<li>{{ version }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</dd>
|
||||
|
||||
</dl>
|
||||
</div>
|
@ -0,0 +1,5 @@
|
||||
<ul>
|
||||
{% for version in plugin.versions %}
|
||||
<li>{{ version }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing Plugin Details" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Data Processing Plugin Details") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
{{ tab_group.render }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Data Processing" %}{% endblock %}
|
||||
|
||||
{% block page_header %}
|
||||
{% include "horizon/common/_page_header.html" with title=_("Data Processing Plugins") %}
|
||||
{% endblock page_header %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<div class="plugins">
|
||||
{{ plugins_table.render }}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,50 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django import http
|
||||
|
||||
from mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
|
||||
INDEX_URL = reverse(
|
||||
'horizon:project:data_processing.data_plugins:index')
|
||||
DETAILS_URL = reverse(
|
||||
'horizon:project:data_processing.data_plugins:details', args=['id'])
|
||||
|
||||
|
||||
class DataProcessingPluginsTests(test.TestCase):
|
||||
@test.create_stubs({api.sahara: ('plugin_list',)})
|
||||
def test_index(self):
|
||||
api.sahara.plugin_list(IsA(http.HttpRequest)) \
|
||||
.AndReturn(self.plugins.list())
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(INDEX_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.data_plugins/plugins.html')
|
||||
self.assertContains(res, 'vanilla')
|
||||
self.assertContains(res, 'plugin')
|
||||
|
||||
@test.create_stubs({api.sahara: ('plugin_get',)})
|
||||
def test_details(self):
|
||||
api.sahara.plugin_get(IsA(http.HttpRequest), IsA(unicode)) \
|
||||
.AndReturn(self.plugins.list()[0])
|
||||
self.mox.ReplayAll()
|
||||
res = self.client.get(DETAILS_URL)
|
||||
self.assertTemplateUsed(res,
|
||||
'project/data_processing.data_plugins/details.html')
|
||||
self.assertContains(res, 'vanilla')
|
||||
self.assertContains(res, 'plugin')
|
||||
self.assertContains(res, 'Plugin Overview')
|
@ -0,0 +1,25 @@
|
||||
# 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 # noqa
|
||||
from django.conf.urls import url # noqa
|
||||
|
||||
from openstack_dashboard.dashboards.project.\
|
||||
data_processing.data_plugins import views
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', views.PluginsView.as_view(), name='index'),
|
||||
url(r'^(?P<plugin_id>[^/]+)$',
|
||||
views.PluginDetailsView.as_view(), name='details'),
|
||||
)
|
@ -0,0 +1,47 @@
|
||||
# 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 tables
|
||||
from horizon import tabs
|
||||
|
||||
from openstack_dashboard.api import sahara as saharaclient
|
||||
import openstack_dashboard.dashboards.project.data_processing. \
|
||||
data_plugins.tables as p_tables
|
||||
import openstack_dashboard.dashboards.project.data_processing. \
|
||||
data_plugins.tabs as p_tabs
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginsView(tables.DataTableView):
|
||||
table_class = p_tables.PluginsTable
|
||||
template_name = 'project/data_processing.data_plugins/plugins.html'
|
||||
|
||||
def get_data(self):
|
||||
try:
|
||||
plugins = saharaclient.plugin_list(self.request)
|
||||
except Exception:
|
||||
plugins = []
|
||||
msg = _('Unable to retrieve data processing plugins.')
|
||||
exceptions.handle(self.request, msg)
|
||||
return plugins
|
||||
|
||||
|
||||
class PluginDetailsView(tabs.TabView):
|
||||
tab_group_class = p_tabs.PluginDetailsTabs
|
||||
template_name = 'project/data_processing.data_plugins/details.html'
|
@ -36,6 +36,7 @@ from heatclient import client as heat_client
|
||||
from keystoneclient.v2_0 import client as keystone_client
|
||||
from neutronclient.v2_0 import client as neutron_client
|
||||
from novaclient.v1_1 import client as nova_client
|
||||
from saharaclient import client as sahara_client
|
||||
from swiftclient import client as swift_client
|
||||
from troveclient import client as trove_client
|
||||
|
||||
@ -262,6 +263,7 @@ class APITestCase(TestCase):
|
||||
self._original_heatclient = api.heat.heatclient
|
||||
self._original_ceilometerclient = api.ceilometer.ceilometerclient
|
||||
self._original_troveclient = api.trove.troveclient
|
||||
self._original_saharaclient = api.sahara.client
|
||||
|
||||
# Replace the clients with our stubs.
|
||||
api.glance.glanceclient = lambda request: self.stub_glanceclient()
|
||||
@ -273,6 +275,7 @@ class APITestCase(TestCase):
|
||||
api.ceilometer.ceilometerclient = lambda request: \
|
||||
self.stub_ceilometerclient()
|
||||
api.trove.troveclient = lambda request: self.stub_troveclient()
|
||||
api.sahara.client = lambda request: self.stub_saharaclient()
|
||||
|
||||
def tearDown(self):
|
||||
super(APITestCase, self).tearDown()
|
||||
@ -284,6 +287,7 @@ class APITestCase(TestCase):
|
||||
api.heat.heatclient = self._original_heatclient
|
||||
api.ceilometer.ceilometerclient = self._original_ceilometerclient
|
||||
api.trove.troveclient = self._original_troveclient
|
||||
api.sahara.client = self._original_saharaclient
|
||||
|
||||
def stub_novaclient(self):
|
||||
if not hasattr(self, "novaclient"):
|
||||
@ -357,6 +361,12 @@ class APITestCase(TestCase):
|
||||
self.troveclient = self.mox.CreateMock(trove_client.Client)
|
||||
return self.troveclient
|
||||
|
||||
def stub_saharaclient(self):
|
||||
if not hasattr(self, "saharaclient"):
|
||||
self.mox.StubOutWithMock(sahara_client, 'Client')
|
||||
self.saharaclient = self.mox.CreateMock(sahara_client.Client)
|
||||
return self.saharaclient
|
||||
|
||||
|
||||
@unittest.skipUnless(os.environ.get('WITH_SELENIUM', False),
|
||||
"The WITH_SELENIUM env variable is not set.")
|
||||
|
@ -122,7 +122,15 @@ SERVICE_CATALOG = [
|
||||
{"region": "RegionOne",
|
||||
"adminURL": "http://admin.trove.example.com:8779/v1.0",
|
||||
"publicURL": "http://public.trove.example.com:8779/v1.0",
|
||||
"internalURL": "http://int.trove.example.com:8779/v1.0"}]}
|
||||
"internalURL": "http://int.trove.example.com:8779/v1.0"}]},
|
||||
{"type": "data_processing",
|
||||
"name": "Sahara",
|
||||
"endpoints_links": [],
|
||||
"endpoints": [
|
||||
{"region": "RegionOne",
|
||||
"adminURL": "http://admin.sahara.example.com:8386/v1.1",
|
||||
"publicURL": "http://public.sahara.example.com:8386/v1.1",
|
||||
"internalURL": "http://int.sahara.example.com:8386/v1.1"}]}
|
||||
]
|
||||
|
||||
|
||||
|
30
openstack_dashboard/test/test_data/sahara_data.py
Normal file
30
openstack_dashboard/test/test_data/sahara_data.py
Normal file
@ -0,0 +1,30 @@
|
||||
# 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 openstack_dashboard.test.test_data import utils
|
||||
|
||||
from saharaclient.api import plugins
|
||||
|
||||
|
||||
def data(TEST):
|
||||
TEST.plugins = utils.TestDataContainer()
|
||||
|
||||
plugin1_dict = {
|
||||
"description": "vanilla plugin",
|
||||
"name": "vanilla",
|
||||
"title": "Vanilla Apache Hadoop",
|
||||
"versions": ["2.3.0", "1.2.1"]
|
||||
}
|
||||
|
||||
plugin1 = plugins.Plugin(plugins.PluginManager(None), plugin1_dict)
|
||||
|
||||
TEST.plugins.add(plugin1)
|
@ -22,6 +22,7 @@ def load_test_data(load_onto=None):
|
||||
from openstack_dashboard.test.test_data import keystone_data
|
||||
from openstack_dashboard.test.test_data import neutron_data
|
||||
from openstack_dashboard.test.test_data import nova_data
|
||||
from openstack_dashboard.test.test_data import sahara_data
|
||||
from openstack_dashboard.test.test_data import swift_data
|
||||
from openstack_dashboard.test.test_data import trove_data
|
||||
|
||||
@ -37,6 +38,7 @@ def load_test_data(load_onto=None):
|
||||
heat_data.data,
|
||||
ceilometer_data.data,
|
||||
trove_data.data,
|
||||
sahara_data.data,
|
||||
)
|
||||
if load_onto:
|
||||
for data_func in loaders:
|
||||
|
Loading…
Reference in New Issue
Block a user