diff --git a/monitoring/alarms/tests.py b/monitoring/alarms/tests.py index b6f97297..f018157e 100644 --- a/monitoring/alarms/tests.py +++ b/monitoring/alarms/tests.py @@ -16,13 +16,6 @@ DETAIL_URL = urlresolvers.reverse( class AlarmsTest(helpers.TestCase): - def test_index_get(self): - res = self.client.get(INDEX_URL) - - self.assertTemplateUsed( - res, 'monitoring/alarms/index.html') - self.assertTemplateUsed(res, 'monitoring/alarms/monitor.html') - def test_alarms_get(self): with patch('monitoring.api.monitor', **{ 'spec_set': ['alarm_list_by_service'], diff --git a/monitoring/alarms/urls.py b/monitoring/alarms/urls.py index 4964899d..8bd0039a 100644 --- a/monitoring/alarms/urls.py +++ b/monitoring/alarms/urls.py @@ -21,7 +21,6 @@ from monitoring.alarms import views urlpatterns = patterns( '', url(r'^$', views.IndexView.as_view(), name='index'), - url(r'^status', views.StatusView.as_view(), name='status'), url(r'^alarm/(?P[^/]+)/$', views.AlarmServiceView.as_view(), name='alarm'), diff --git a/monitoring/alarms/views.py b/monitoring/alarms/views.py index c58ac1f0..84c35678 100644 --- a/monitoring/alarms/views.py +++ b/monitoring/alarms/views.py @@ -22,9 +22,10 @@ from django.conf import settings # noqa from django.contrib import messages from django.core.urlresolvers import reverse_lazy, reverse # noqa from django.http import HttpResponse # noqa +from django.shortcuts import redirect from django.template import defaultfilters as filters from django.utils.translation import ugettext as _ # noqa -from django.views.generic import TemplateView # noqa +from django.views.generic import View # noqa from horizon import exceptions from horizon import forms @@ -95,26 +96,9 @@ def generate_status(request): return SERVICES -class IndexView(TemplateView): - template_name = constants.TEMPLATE_PREFIX + 'index.html' - - def get_context_data(self, **kwargs): - context = super(IndexView, self).get_context_data(**kwargs) - context["token"] = self.request.user.token.id - return context - - -class StatusView(TemplateView): - template_name = "" - - def get(self, request, *args, **kwargs): - ret = { - 'series': generate_status(self.request), - 'settings': {} - } - - return HttpResponse(json.dumps(ret), - content_type='application/json') +class IndexView(View): + def dispatch(self, request, *args, **kwargs): + return redirect(constants.URL_PREFIX + 'alarm', service='all') class AlarmServiceView(tables.DataTableView): diff --git a/monitoring/dashboard.py b/monitoring/dashboard.py index 585dcc76..2a5490f6 100644 --- a/monitoring/dashboard.py +++ b/monitoring/dashboard.py @@ -22,8 +22,8 @@ import horizon class Monitoring(horizon.Dashboard): name = _("Monitoring") slug = "monitoring" - panels = ('alarms', 'notifications') - default_panel = 'alarms' + panels = ('overview', 'alarms', 'notifications') + default_panel = 'overview' horizon.register(Monitoring) diff --git a/monitoring/overview/__init__.py b/monitoring/overview/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/monitoring/overview/constants.py b/monitoring/overview/constants.py new file mode 100644 index 00000000..9fe21222 --- /dev/null +++ b/monitoring/overview/constants.py @@ -0,0 +1,25 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# +# 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. + + +URL_PREFIX = 'horizon:monitoring:overview:' +TEMPLATE_PREFIX = 'monitoring/overview/' + +CRITICAL_ICON = '/static/monitoring/img/critical-icon.png' +WARNING_ICON = '/static/monitoring/img/warning-icon.png' +OK_ICON = '/static/monitoring/img/ok-icon.png' +UNKNOWN_ICON = '/static/monitoring/img/unknown-icon.png' +NOTFOUND_ICON = '/static/monitoring/img/notfound-icon.png' diff --git a/monitoring/overview/panel.py b/monitoring/overview/panel.py new file mode 100644 index 00000000..57fb1c12 --- /dev/null +++ b/monitoring/overview/panel.py @@ -0,0 +1,29 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# +# 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 _ # noqa + +import horizon + +from monitoring import dashboard + + +class Overview(horizon.Panel): + name = _("Overview") + slug = 'overview' + + +dashboard.Monitoring.register(Overview) diff --git a/monitoring/alarms/templates/alarms/index.html b/monitoring/overview/templates/overview/index.html similarity index 91% rename from monitoring/alarms/templates/alarms/index.html rename to monitoring/overview/templates/overview/index.html index e223228b..9ba0f5db 100644 --- a/monitoring/alarms/templates/alarms/index.html +++ b/monitoring/overview/templates/overview/index.html @@ -14,5 +14,5 @@ {% trans 'Dashboard' %} - {% include 'monitoring/alarms/monitor.html' %} + {% include 'monitoring/overview/monitor.html' %} {% endblock %} \ No newline at end of file diff --git a/monitoring/alarms/templates/alarms/monitor.html b/monitoring/overview/templates/overview/monitor.html similarity index 96% rename from monitoring/alarms/templates/alarms/monitor.html rename to monitoring/overview/templates/overview/monitor.html index 00e46d41..4edcd9cb 100644 --- a/monitoring/alarms/templates/alarms/monitor.html +++ b/monitoring/overview/templates/overview/monitor.html @@ -55,7 +55,7 @@ {$ group.name $}
- +
diff --git a/monitoring/overview/tests.py b/monitoring/overview/tests.py new file mode 100644 index 00000000..4e6463b9 --- /dev/null +++ b/monitoring/overview/tests.py @@ -0,0 +1,18 @@ +from django.core import urlresolvers +from mock import patch, call # noqa + +from monitoring.test import helpers +from monitoring.overview import constants + + +INDEX_URL = urlresolvers.reverse( + constants.URL_PREFIX + 'index') + + +class OverviewTest(helpers.TestCase): + def test_index_get(self): + res = self.client.get(INDEX_URL) + self.assertTemplateUsed( + res, 'monitoring/overview/index.html') + self.assertTemplateUsed(res, 'monitoring/overview/monitor.html') + diff --git a/monitoring/overview/urls.py b/monitoring/overview/urls.py new file mode 100644 index 00000000..1913a2b0 --- /dev/null +++ b/monitoring/overview/urls.py @@ -0,0 +1,25 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# +# 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 monitoring.overview import views + +urlpatterns = patterns( + '', + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^status', views.StatusView.as_view(), name='status'), +) diff --git a/monitoring/overview/views.py b/monitoring/overview/views.py new file mode 100644 index 00000000..6bcf9210 --- /dev/null +++ b/monitoring/overview/views.py @@ -0,0 +1,106 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# +# 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 + +import json +import logging + +from django.conf import settings # noqa +from django.http import HttpResponse # noqa +from django.views.generic import TemplateView # noqa + +from monitoring.overview import constants +from monitoring.alarms import tables as alarm_tables +from monitoring import api + +LOG = logging.getLogger(__name__) +SERVICES = getattr(settings, 'MONITORING_SERVICES', []) + + +def get_icon(status): + if status == 'chicklet-success': + return constants.OK_ICON + if status == 'chicklet-error': + return constants.CRITICAL_ICON + if status == 'chicklet-warning': + return constants.WARNING_ICON + if status == 'chicklet-unknown': + return constants.UNKNOWN_ICON + if status == 'chicklet-notfound': + return constants.NOTFOUND_ICON + + +priorities = [ + {'status': 'chicklet-success', 'severity': 'OK'}, + {'status': 'chicklet-unknown', 'severity': 'UNDETERMINED'}, + {'status': 'chicklet-warning', 'severity': 'LOW'}, + {'status': 'chicklet-warning', 'severity': 'MEDIUM'}, + {'status': 'chicklet-warning', 'severity': 'HIGH'}, + {'status': 'chicklet-error', 'severity': 'CRITICAL'}, +] +index_by_severity = {d['severity']: i for i, d in enumerate(priorities)} + + +def get_status(alarms): + if not alarms: + return 'chicklet-notfound' + status_index = 0 + for a in alarms: + severity = alarm_tables.show_severity(a) + severity_index = index_by_severity[severity] + status_index = max(status_index, severity_index) + return priorities[status_index]['status'] + + +def generate_status(request): + try: + alarms = api.monitor.alarm_list(request) + except Exception: + alarms = [] + alarms_by_service = {} + for a in alarms: + service = alarm_tables.show_service(a) + service_alarms = alarms_by_service.setdefault(service, []) + service_alarms.append(a) + for row in SERVICES: + row['name'] = unicode(row['name']) + for service in row['services']: + service_alarms = alarms_by_service.get(service['name'], []) + service['class'] = get_status(service_alarms) + service['icon'] = get_icon(service['class']) + service['display'] = unicode(service['display']) + return SERVICES + + +class IndexView(TemplateView): + template_name = constants.TEMPLATE_PREFIX + 'index.html' + + def get_context_data(self, **kwargs): + context = super(IndexView, self).get_context_data(**kwargs) + context["token"] = self.request.user.token.id + return context + + +class StatusView(TemplateView): + template_name = "" + + def get(self, request, *args, **kwargs): + ret = { + 'series': generate_status(self.request), + 'settings': {} + } + + return HttpResponse(json.dumps(ret), + content_type='application/json')