From b1523c64850269bf2ac5327581497382c1ce578b Mon Sep 17 00:00:00 2001 From: Noam Bloom Date: Sun, 16 Oct 2016 07:31:57 +0000 Subject: [PATCH] Added templates list view to vitrage dashboard Change-Id: Iae2a4b09f20d1e26d664b0bd76197a3c302798cd --- MANIFEST.in | 5 +- setup.cfg | 1 + vitrageclient/api/rest/vitrage.py | 20 +++++++ vitrageclient/api/vitrage.py | 4 ++ .../_93_project_template_vitrage_panel.py | 27 +++++++++ .../openstack-service-api/vitrage.service.js | 10 +++- .../services/vitrage_topology.service.js | 17 +++++- .../templateList/templateList.controller.js | 55 +++++++++++++++++++ .../project/templateList/templateList.html | 34 ++++++++++++ .../project/templateList/templateList.scss | 10 ++++ .../static/dashboard/project/vitrage.scss | 3 +- vitragetemplates/__init__.py | 19 +++++++ vitragetemplates/panel.py | 22 ++++++++ .../templates/templates/index.html | 16 ++++++ vitragetemplates/urls.py | 22 ++++++++ vitragetemplates/version.py | 15 +++++ vitragetemplates/views.py | 32 +++++++++++ 17 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 vitragedashboard/enabled/_93_project_template_vitrage_panel.py create mode 100644 vitragedashboard/static/dashboard/project/templateList/templateList.controller.js create mode 100644 vitragedashboard/static/dashboard/project/templateList/templateList.html create mode 100644 vitragedashboard/static/dashboard/project/templateList/templateList.scss create mode 100644 vitragetemplates/__init__.py create mode 100644 vitragetemplates/panel.py create mode 100644 vitragetemplates/templates/templates/index.html create mode 100644 vitragetemplates/urls.py create mode 100644 vitragetemplates/version.py create mode 100644 vitragetemplates/views.py diff --git a/MANIFEST.in b/MANIFEST.in index 6bd6c0d..d26bac7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -15,4 +15,7 @@ recursive-include vitragealarms/static * recursive-include vitragealarms/templates * recursive-include vitrageentities/static * -recursive-include vitrageentities/templates * \ No newline at end of file +recursive-include vitrageentities/templates * + +recursive-include vitragetemplates/static * +recursive-include vitragetemplates/templates * \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 297dc9d..9ac1185 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,6 +23,7 @@ classifier = packages = vitrageentities vitragealarms + vitragetemplates vitragedashboard diff --git a/vitrageclient/api/rest/vitrage.py b/vitrageclient/api/rest/vitrage.py index 1aa0975..43c271b 100644 --- a/vitrageclient/api/rest/vitrage.py +++ b/vitrageclient/api/rest/vitrage.py @@ -97,3 +97,23 @@ class Rca(generic.View): """ return api.vitrage.rca(request, alarm_id) + + +@urls.register +class Templates(generic.View): + """API for vitrage templates.""" + + url_regex = r'vitrage/template/' + + @rest_utils.ajax() + def get(self, request): + """Get a single template with the vitrage id. + + The following get template may be passed in the GET + + :param template_id the id of the vitrage template + + The result is a template object. + """ + + return api.vitrage.templates(request) diff --git a/vitrageclient/api/vitrage.py b/vitrageclient/api/vitrage.py index becf2d9..6deb0e7 100644 --- a/vitrageclient/api/vitrage.py +++ b/vitrageclient/api/vitrage.py @@ -41,3 +41,7 @@ def alarms(request, vitrage_id='all'): def rca(request, alarm_id): return vitrageclient(request).rca.get(alarm_id=alarm_id) + + +def templates(request): + return vitrageclient(request).template.list() diff --git a/vitragedashboard/enabled/_93_project_template_vitrage_panel.py b/vitragedashboard/enabled/_93_project_template_vitrage_panel.py new file mode 100644 index 0000000..bd86762 --- /dev/null +++ b/vitragedashboard/enabled/_93_project_template_vitrage_panel.py @@ -0,0 +1,27 @@ +# 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. + +# The name of the panel to be added to HORIZON_CONFIG. Required. +PANEL = 'templates_vitrage_panel' +# The name of the dashboard the PANEL associated with. Required. +PANEL_DASHBOARD = 'project' +# The name of the panel group the PANEL is associated with. +PANEL_GROUP = 'vitrage_panel_group' + +# Python panel class of the PANEL to be added. +ADD_PANEL = 'vitragetemplates.panel.TemplatesVitrage' + +ADD_INSTALLED_APPS = ['vitragetemplates'] + +ADD_ANGULAR_MODULES = ['horizon.dashboard.project.vitrage'] + +AUTO_DISCOVER_STATIC_FILES = True diff --git a/vitragedashboard/static/app/core/openstack-service-api/vitrage.service.js b/vitragedashboard/static/app/core/openstack-service-api/vitrage.service.js index 6dd8393..aeb8c86 100644 --- a/vitragedashboard/static/app/core/openstack-service-api/vitrage.service.js +++ b/vitragedashboard/static/app/core/openstack-service-api/vitrage.service.js @@ -16,7 +16,8 @@ var service = { getTopology: getTopology, getAlarms: getAlarms, - getRca: getRca + getRca: getRca, + getTemplates: getTemplates }; return service; @@ -55,6 +56,13 @@ }); } + function getTemplates() { + return apiService.get('/api/vitrage/template/') + .error(function () { + toastService.add('error', gettext('Unable to fetch the Vitrage Templates service.')); + }); + } + } }()); diff --git a/vitragedashboard/static/dashboard/project/services/vitrage_topology.service.js b/vitragedashboard/static/dashboard/project/services/vitrage_topology.service.js index e74c2d9..f7944e2 100644 --- a/vitragedashboard/static/dashboard/project/services/vitrage_topology.service.js +++ b/vitragedashboard/static/dashboard/project/services/vitrage_topology.service.js @@ -42,6 +42,20 @@ } } + function getTemplates() { + + if (vitrageAPI) { + return vitrageAPI.getTemplates() + .success(function(data) { + return data; + }) + .error(function(err) { + console.error(err); + } + ) + } + } + function getRootCauseAnalysis(alarm_id) { if (vitrageAPI) { @@ -59,7 +73,8 @@ return { getTopology: getTopology, getAlarms: getAlarms, - getRootCauseAnalysis: getRootCauseAnalysis + getRootCauseAnalysis: getRootCauseAnalysis, + getTemplates: getTemplates } } })(); diff --git a/vitragedashboard/static/dashboard/project/templateList/templateList.controller.js b/vitragedashboard/static/dashboard/project/templateList/templateList.controller.js new file mode 100644 index 0000000..668d1a1 --- /dev/null +++ b/vitragedashboard/static/dashboard/project/templateList/templateList.controller.js @@ -0,0 +1,55 @@ +(function () { + 'use strict'; + + angular + .module('horizon.dashboard.project.vitrage') + .controller('TemplateListController', TemplateListController); + + TemplateListController.$inject = ['$scope', '$modal', 'vitrageTopologySrv','$interval']; + + function TemplateListController($scope, $modal, vitrageTopologySrv,$interval) { + var templateList = this; + templateList.templates = []; + templateList.itemplates = []; + templateList.$interval = $interval; + templateList.checkboxAutoRefresh = true; + $scope.STATIC_URL = STATIC_URL; + templateList.templates = []; + templateList.templateInterval; + + getData(); + startCollectData(); + + function startCollectData() { + if (angular.isDefined(templateList.templateInterval)) return; + templateList.templateInterval = templateList.$interval(getData,10000); + } + + function stopCollectData() { + if (angular.isDefined(templateList.templateInterval)) { + templateList.$interval.cancel(templateList.templateInterval); + templateList.templateInterval = undefined; + } + } + $scope.$on('$destroy',function(){ + templateList.stopCollectData(); + }) + + templateList.autoRefreshChanged = function(){ + if (templateList.checkboxAutoRefresh){ + getData(); + startCollectData(); + }else{ + stopCollectData(); + } + } + + function getData() { + vitrageTopologySrv.getTemplates().then(function(result){ + templateList.templates = result.data; + }); + } + } + +})(); + diff --git a/vitragedashboard/static/dashboard/project/templateList/templateList.html b/vitragedashboard/static/dashboard/project/templateList/templateList.html new file mode 100644 index 0000000..c90a75d --- /dev/null +++ b/vitragedashboard/static/dashboard/project/templateList/templateList.html @@ -0,0 +1,34 @@ +
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + +
{$ 'Name' | translate $}{$ 'Status' | translate $}{$ 'Details' | translate $}{$ 'Timestamp' | translate $}
+ + +
{$template.name$}{$template.status$}{$template["status details"]$} {$template.date | date:"yyyy-MM-dd hh:mm:ss"$}
+
+
diff --git a/vitragedashboard/static/dashboard/project/templateList/templateList.scss b/vitragedashboard/static/dashboard/project/templateList/templateList.scss new file mode 100644 index 0000000..7b201d3 --- /dev/null +++ b/vitragedashboard/static/dashboard/project/templateList/templateList.scss @@ -0,0 +1,10 @@ +.template-list { + .refreshBtn{ + text-align: right; + } + + .first-column { + padding-left: 20px; + } + +} diff --git a/vitragedashboard/static/dashboard/project/vitrage.scss b/vitragedashboard/static/dashboard/project/vitrage.scss index b2b1a27..f4c2557 100644 --- a/vitragedashboard/static/dashboard/project/vitrage.scss +++ b/vitragedashboard/static/dashboard/project/vitrage.scss @@ -1,5 +1,5 @@ @import 'layout/main/compute/compute'; -@import "alarmList/alarmList.scss"; +@import 'alarmList/alarmList.scss'; @import 'components/sunburst/sunburst'; @import 'components/alarms/alarms.scss'; @import 'components/rca/rootCauseAnalysisGraph.scss'; @@ -12,6 +12,7 @@ @import 'entities/info/entities-info.scss'; @import 'entities/toolbox/entities-toolbox.scss'; @import 'entities/entities.scss'; +@import 'templateList/templateList.scss'; .red { color: #FA3C3C; diff --git a/vitragetemplates/__init__.py b/vitragetemplates/__init__.py new file mode 100644 index 0000000..4883a95 --- /dev/null +++ b/vitragetemplates/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +# 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 pbr.version + + +__version__ = pbr.version.VersionInfo( + 'vitrage-dashboard').version_string() diff --git a/vitragetemplates/panel.py b/vitragetemplates/panel.py new file mode 100644 index 0000000..7cd7dbb --- /dev/null +++ b/vitragetemplates/panel.py @@ -0,0 +1,22 @@ +# Copyright 2015 IBM Corp. +# +# 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 + + +class TemplatesVitrage(horizon.Panel): + name = _("Templates") + slug = "vitragetemplates" diff --git a/vitragetemplates/templates/templates/index.html b/vitragetemplates/templates/templates/index.html new file mode 100644 index 0000000..c7ca3cb --- /dev/null +++ b/vitragetemplates/templates/templates/index.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}{% trans "Templates List" %}{% endblock %} + +{% block page_header %} +{% include "horizon/common/_page_header.html" with title=_("Templates List") %} +{% endblock page_header %} + +{% block main %} + +
+ +
+ +{% endblock %} + diff --git a/vitragetemplates/urls.py b/vitragetemplates/urls.py new file mode 100644 index 0000000..a401b89 --- /dev/null +++ b/vitragetemplates/urls.py @@ -0,0 +1,22 @@ +# Copyright 2015 IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from django.conf import urls + +from vitragetemplates import views + +urlpatterns = urls.patterns( + '', + urls.url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/vitragetemplates/version.py b/vitragetemplates/version.py new file mode 100644 index 0000000..cbca802 --- /dev/null +++ b/vitragetemplates/version.py @@ -0,0 +1,15 @@ +# 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 pbr.version + +version_info = pbr.version.VersionInfo('vitrage_templates_ui') diff --git a/vitragetemplates/views.py b/vitragetemplates/views.py new file mode 100644 index 0000000..cbedc00 --- /dev/null +++ b/vitragetemplates/views.py @@ -0,0 +1,32 @@ +# Copyright 2012 Alcatel-Lucent, Inc. +# +# 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 views + +import json + + +class IndexView(views.APIView): + # A very simple class-based view... + template_name = 'templates/index.html' + + def get_data(self, request, context, *args, **kwargs): + topology_settings = { + 'VITRAGE_VERSION': { + 'VER': 1, + 'REL': 1 + } + } + context['TOPOLOGY_VITRAGE_SETTINGS'] = json.dumps(topology_settings) + return context