monasca-ui/monitoring/alarms/views.py

403 lines
14 KiB
Python

# 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 datetime
import logging
import json
import random
from collections import defaultdict
from django.contrib import messages
from django.core.urlresolvers import reverse_lazy, reverse # noqa
from django.template import defaultfilters as filters
from django.http import HttpResponse # noqa
from django.utils.translation import ugettext as _
from django.views.generic import TemplateView
from horizon import exceptions
from horizon import forms
from horizon import tables
import monclient.exc as exc
from monitoring import api
from .tables import AlarmsTable
from .tables import AlarmHistoryTable
from .tables import show_service
from .tables import show_severity
from . import forms as alarm_forms
from . import constants
LOG = logging.getLogger(__name__)
SAMPLE = [{'name': _('Platform Services'),
'services': [{'name': 'MaaS',
'display': _('MaaS')},
{'name': 'DBaaS',
'display': _('DBaaS')},
{'name': 'LBaaS',
'display': _('LBaaS')},
{'name': 'DNSaaS',
'display': _('DNSaaS')},
{'name': 'MSGaaS',
'display': _('MSGaaS')},
]},
{'name': _('The OverCloud Services'),
'services': [{'name': 'nova',
'display': _('Nova')},
{'name': 'swift',
'display': _('Swift')},
{'name': 'bock',
'display': _('Cinder')},
{'name': 'glance',
'display': _('Glance')},
{'name': 'quantum',
'display': _('Neutron')},
{'name': 'mysql',
'display': _('MySQL')},
{'name': 'rabbitmq',
'display': _('RabbitMQ')},
{'name': 'mini-mon',
'display': _('Monitoring')},
]},
{'name': _('The UnderCloud Services'),
'services': [{'name': 'nova',
'display': _('Nova')},
{'name': 'swift',
'display': _('Cinder')},
{'name': 'glance',
'display': _('Glance')},
{'name': 'horizon',
'display': _('Horizon')},
]},
{'name': _('Network Services'),
'services': [{'name': 'dhcp',
'display': _('DHCP')},
{'name': 'dns',
'display': _('DNS')},
{'name': 'dns-servers',
'display': _('DNS Servers')},
{'name': 'http',
'display': _('http')},
{'name': 'web_proxy',
'display': _('Web Proxy')},
]}
]
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 = 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):
alarms = api.monitor.alarm_list(request)
alarms_by_service = {}
for a in alarms:
service = show_service(a)
service_alarms = alarms_by_service.setdefault(service, [])
service_alarms.append(a)
for row in SAMPLE:
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'])
return SAMPLE
class IndexView(TemplateView):
template_name = constants.TEMPLATE_PREFIX + 'index.html'
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 AlarmServiceView(tables.DataTableView):
table_class = AlarmsTable
template_name = constants.TEMPLATE_PREFIX + 'alarm.html'
def dispatch(self, *args, **kwargs):
self.service = kwargs['service']
del kwargs['service']
return super(AlarmServiceView, self).dispatch(*args, **kwargs)
def get_data(self):
results = []
try:
if self.service == 'all':
results = api.monitor.alarm_list(self.request)
else:
results = api.monitor.alarm_list_by_service(
self.request,
self.service)
except:
messages.error(self.request, _("Could not retrieve alarms"))
return results
def get_context_data(self, **kwargs):
context = super(AlarmServiceView, self).get_context_data(**kwargs)
context["service"] = self.service
return context
class AlarmCreateView(forms.ModalFormView):
form_class = alarm_forms.CreateAlarmForm
template_name = constants.TEMPLATE_PREFIX + 'create.html'
def dispatch(self, *args, **kwargs):
self.service = kwargs['service']
return super(AlarmCreateView, self).dispatch(*args, **kwargs)
def get_initial(self):
return {"service": self.service}
def get_context_data(self, **kwargs):
context = super(AlarmCreateView, self).get_context_data(**kwargs)
context["cancel_url"] = self.get_success_url()
context["action_url"] = reverse(constants.URL_PREFIX + 'alarm_create',
args=(self.service,))
metrics = api.monitor.metrics_list(self.request)
# Filter out metrics for other services
if self.service != 'all':
meters = [m for m in metrics
if m.setdefault('dimensions', {}).
setdefault('service', '') == self.service]
# Aggregate all dimensions for each metric name
d = defaultdict(set)
for metric in metrics:
dim_list = ['%s=%s' % (n, l) for n, l in metric["dimensions"].items()]
d[metric["name"]].update(dim_list)
unique_metrics = [{'name': k, 'dimensions': sorted(list(v))}
for k, v in d.items()]
context["metrics"] = json.dumps(unique_metrics)
return context
def get_success_url(self):
return reverse_lazy(constants.URL_PREFIX + 'alarm',
args=(self.service,))
def transform_alarm_data(obj):
return obj
return {'id': getattr(obj, 'id', None),
'name': getattr(obj, 'name', None),
'expression': getattr(obj, 'expression', None),
'state': filters.title(getattr(obj, 'state', None)),
'severity': filters.title(getattr(obj, 'severity', None)),
'actions_enabled': filters.title(getattr(obj, 'actions_enabled',
None)),
'notifications': getattr(obj, 'alarm_actions', None), }
def transform_alarm_history(results, name):
newlist = []
for item in results:
temp = {}
temp['alarm_id'] = item['alarm_id']
temp['name'] = name
temp['old_state'] = item['old_state']
temp['new_state'] = item['new_state']
temp['timestamp'] = item['timestamp']
temp['reason'] = item['reason']
temp['reason_data'] = item['reason_data']
newlist.append(temp)
return newlist
class AlarmDetailView(forms.ModalFormView):
form_class = alarm_forms.DetailAlarmForm
template_name = constants.TEMPLATE_PREFIX + 'detail.html'
def get_object(self):
id = self.kwargs['id']
try:
if hasattr(self, "_object"):
return self._object
self._object = None
self._object = api.monitor.alarm_get(self.request, id)
notifications = []
# Fetch the notification object for each alarm_actions
for id in self._object["alarm_actions"]:
try:
notification = api.monitor.notification_get(
self.request,
id)
notifications.append(notification)
# except exceptions.NOT_FOUND:
except exc.HTTPException:
msg = _("Notification %s has already been deleted.") % id
notifications.append({"id": id,
"name": unicode(msg),
"type": "",
"address": ""})
self._object["notifications"] = notifications
return self._object
except Exception:
redirect = self.get_success_url()
exceptions.handle(self.request,
_('Unable to retrieve alarm details.'),
redirect=redirect)
return None
def get_initial(self):
self.alarm = self.get_object()
return transform_alarm_data(self.alarm)
def get_context_data(self, **kwargs):
context = super(AlarmDetailView, self).get_context_data(**kwargs)
context["alarm"] = self.alarm
context["cancel_url"] = self.get_success_url()
return context
def get_success_url(self):
return reverse_lazy(constants.URL_PREFIX + 'index')
class AlarmEditView(forms.ModalFormView):
form_class = alarm_forms.EditAlarmForm
template_name = constants.TEMPLATE_PREFIX + 'edit.html'
def dispatch(self, *args, **kwargs):
self.service = kwargs['service']
del kwargs['service']
return super(AlarmEditView, self).dispatch(*args, **kwargs)
def get_object(self):
id = self.kwargs['id']
try:
if hasattr(self, "_object"):
return self._object
self._object = None
self._object = api.monitor.alarm_get(self.request, id)
notifications = []
# Fetch the notification object for each alarm_actions
for id in self._object["alarm_actions"]:
try:
notification = api.monitor.notification_get(
self.request,
id)
notifications.append(notification)
# except exceptions.NOT_FOUND:
except exc.HTTPException:
msg = _("Notification %s has already been deleted.") % id
self._object["notifications"] = notifications
return self._object
except Exception:
redirect = self.get_success_url()
exceptions.handle(self.request,
_('Unable to retrieve alarm details.'),
redirect=redirect)
return None
def get_initial(self):
self.alarm = self.get_object()
return transform_alarm_data(self.alarm)
def get_context_data(self, **kwargs):
context = super(AlarmEditView, self).get_context_data(**kwargs)
id = self.kwargs['id']
context["cancel_url"] = self.get_success_url()
context["action_url"] = reverse(constants.URL_PREFIX + 'alarm_edit',
args=(self.service, id,))
return context
def get_success_url(self):
return reverse_lazy(constants.URL_PREFIX + 'alarm',
args=(self.service,))
class AlarmHistoryView(tables.DataTableView):
table_class = AlarmHistoryTable
template_name = constants.TEMPLATE_PREFIX + 'alarm_history.html'
def dispatch(self, *args, **kwargs):
return super(AlarmHistoryView, self).dispatch(*args, **kwargs)
def get_data(self):
id = self.kwargs['id']
name = self.kwargs['name']
results = []
try:
results = api.monitor.alarm_history(self.request, id)
except:
messages.error(self.request,
_("Could not retrieve alarm history for %s") % id)
return transform_alarm_history(results, name)
def get_context_data(self, **kwargs):
context = super(AlarmHistoryView, self).get_context_data(**kwargs)
return context
class AlarmMeterView(TemplateView):
template_name = constants.TEMPLATE_PREFIX + 'alarm_meter.html'
def get_random_status():
distribution = [
{'prob': .04, 'value': 'chicklet-error'},
{'prob': .04, 'value': 'chicklet-warning'},
{'prob': .04, 'value': 'chicklet-unknown'},
{'prob': .04, 'value': 'chicklet-notfound'},
{'prob': 1.0, 'value': 'chicklet-success'},
]
num = random.random()
for dist in distribution:
if num < dist["prob"]:
return dist["value"]
num = num - dist["prob"]
return distribution[len(distribution) - 1]["value"]