Refactor to make alarms and notifications as panels

This commit is contained in:
Rob Raymond 2014-06-03 15:29:18 -06:00
parent de312c7bb0
commit b576f6c4d7
31 changed files with 931 additions and 25 deletions

View File

331
monitoring/alarms/forms.py Normal file
View File

@ -0,0 +1,331 @@
# 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 import forms as django_forms
from django.utils.html import escape
from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _ # noqa
from horizon import exceptions
from horizon import forms
from horizon import messages
from monitoring import api
from monitoring import constants
def get_expression(meter):
expr = meter['name']
args = None
for name, value in meter['dimensions'].items():
if name != 'detail':
if args:
args += ', '
else:
args = ''
args += "%s=%s" % (name, value)
return "%s{%s}" % (expr, args)
class SimpleExpressionWidget(django_forms.MultiWidget):
def __init__(self, meters=None, attrs=None):
choices = [(get_expression(m), get_expression(m)) for m in meters]
comparators = [('>', '>'), ('>=', '>='), ('<', '<'), ('<=', '<=')]
func = [('min', _('min')), ('max', _('max')), ('sum', _('sum')),
('count', _('count')), ('avg', _('avg'))]
_widgets = (
django_forms.widgets.Select(attrs=attrs, choices=func),
django_forms.widgets.Select(attrs=attrs, choices=choices),
django_forms.widgets.Select(attrs=attrs, choices=comparators),
django_forms.widgets.TextInput(attrs=attrs),
)
super(SimpleExpressionWidget, self).__init__(_widgets, attrs)
def decompress(self, expr):
return [None, None, None]
def format_output(self, rendered_widgets):
return ''.join(rendered_widgets)
def value_from_datadict(self, data, files, name):
values = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)]
try:
expression = '%s(%s)%s%s' % (values[0],
values[1],
values[2],
values[3])
except ValueError:
return ''
else:
return expression
class NotificationTableWidget(forms.Widget):
FIELD_ID_IDX = 0
FIELD_NAME_IDX = 1
def __init__(self, *args, **kwargs):
self.fields = kwargs.pop('fields')
super(NotificationTableWidget, self).__init__(*args, **kwargs)
def render(self, name, value, attrs):
output = '<table class="table table-condensed"><thead><tr>'
for field in self.fields:
output += '<th>%s</th>' % unicode(field[self.FIELD_NAME_IDX])
output += '</tr></thead>'
if value:
for notification in value:
output += "<tr>"
for field in self.fields:
field_value = notification[field[self.FIELD_ID_IDX]]
output += '<td>%s</td>' % escape(field_value)
output += "</tr>"
output += '</table>'
return format_html(output)
class NotificationField(forms.MultiValueField):
def __init__(self, *args, **kwargs):
super(NotificationField, self).__init__(*args, **kwargs)
def _get_choices(self):
return self._choices
def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
self._choices = self.widget.choices = list(value)
choices = property(_get_choices, _set_choices)
def compress(self, data_list):
return data_list
def clean(self, value):
return value
class NotificationCreateWidget(forms.Select):
def __init__(self, *args, **kwargs):
super(NotificationCreateWidget, self).__init__(*args, **kwargs)
def render(self, name, value, attrs=None, choices=()):
output = '<table id="notification_table" ' + \
'class="table table-condensed">'
output += '<thead><tr><th>%s</th></tr></thead>' % \
unicode(_("Name"))
if value:
idx = 1
for notification in value:
output += '<tr><td>'
output += ('<select id="id_notifications_%d" ' +
'name="notifications_%d"> ') % (idx, idx)
options = self.render_options(
choices,
[notification['notification_id']])
if options:
output += options
output += '</select>'
output += '</td></tr>'
idx += 1
else:
output += '<tr><td>'
output += '<select id="id_notifications_1" '
output += 'name="notifications_1"> '
options = self.render_options(choices, [value])
if options:
output += options
output += '</select>'
output += '</td></tr>'
output += '</table>'
label = unicode(_("+ Add more"))
output += '<a href="" id="add_notification_button">%s</a>' % (label)
return format_html(output)
def value_from_datadict(self, data, files, name):
notifications = []
i = 0
while True:
i += 1
notification_id = "%s_%d" % (name, i)
if notification_id in data:
if len(data[notification_id]) > 0:
notifications.append({"notification_id":
data[notification_id]})
else:
break
return notifications
class BaseAlarmForm(forms.SelfHandlingForm):
@classmethod
def _instantiate(cls, request, *args, **kwargs):
return cls(request, *args, **kwargs)
def _init_fields(self, readOnly=False, create=False, initial=None):
required = True
textWidget = None
textAreaWidget = forms.Textarea(attrs={'class': 'large-text-area'})
readOnlyTextInput = forms.TextInput(attrs={'readonly': 'readonly'})
choiceWidget = forms.Select
if readOnly:
required = False
textWidget = readOnlyTextInput
choiceWidget = readOnlyTextInput
textAreaWidget = forms.Textarea(attrs={'readonly': 'readonly',
'class': 'large-text-area'
})
expressionWidget = textAreaWidget
else:
if create:
meters = api.monitor.metrics_list(self.request)
if initial and 'service' in initial and \
initial['service'] != 'all':
service = initial['service']
meters = [m for m in meters
if m.setdefault('dimensions', {}).
setdefault('service', '') == service]
expressionWidget = SimpleExpressionWidget(meters=meters)
else:
expressionWidget = textAreaWidget
if create:
notificationWidget = NotificationCreateWidget()
else:
notificationWidget = NotificationTableWidget(
fields=[('name', _('Name')),
('type', _('Type')),
('address', _('Address')), ])
self.fields['name'] = forms.CharField(label=_("Name"),
required=required,
max_length=250,
widget=textWidget)
self.fields['expression'] = forms.CharField(label=_("Expression"),
required=required,
widget=expressionWidget)
self.fields['description'] = forms.CharField(label=_("Description"),
required=False,
widget=textAreaWidget)
sev_choices = [("LOW", _("Low")),
("MEDIUM", _("Medium")),
("HIGH", _("High")),
("CRITICAL", _("Critical"))]
self.fields['severity'] = forms.ChoiceField(label=_("Severity"),
choices=sev_choices,
widget=choiceWidget,
required=False)
self.fields['state'] = forms.CharField(label=_("State"),
required=False,
widget=textWidget)
self.fields['actions_enabled'] = \
forms.BooleanField(label=_("Notifications Enabled"),
required=False,
initial=True)
self.fields['notifications'] = NotificationField(
label=_("Notifications"),
required=False,
widget=notificationWidget)
def set_notification_choices(self, request):
try:
notifications = api.monitor.notification_list(request)
except Exception as e:
notifications = []
exceptions.handle(request,
_('Unable to retrieve notifications: %s') % e)
notification_choices = [(notification['id'], notification['name'])
for notification in notifications]
if notification_choices:
if len(notification_choices) > 1:
notification_choices.insert(
0, ("", unicode(_("Select Notification"))))
else:
notification_choices.insert(
0, ("", unicode(_("No notifications available."))))
self.fields['notifications'].choices = notification_choices
class CreateAlarmForm(BaseAlarmForm):
def __init__(self, request, *args, **kwargs):
super(CreateAlarmForm, self).__init__(request, *args, **kwargs)
super(CreateAlarmForm, self)._init_fields(readOnly=False, create=True,
initial=kwargs['initial'])
super(CreateAlarmForm, self).set_notification_choices(request)
self.fields.pop('state')
def handle(self, request, data):
try:
alarm_actions = [notification.get('notification_id')
for notification in data['notifications']]
api.monitor.alarm_create(
request,
name=data['name'],
expression=data['expression'],
description=data['description'],
severity=data['severity'],
alarm_actions=alarm_actions)
messages.success(request,
_('Alarm has been created successfully.'))
except Exception as e:
exceptions.handle(request, _('Unable to create the alarm: %s') % e)
return False
return True
class DetailAlarmForm(BaseAlarmForm):
def __init__(self, request, *args, **kwargs):
super(DetailAlarmForm, self).__init__(request, *args, **kwargs)
super(DetailAlarmForm, self)._init_fields(readOnly=True)
def handle(self, request, data):
return True
class EditAlarmForm(BaseAlarmForm):
def __init__(self, request, *args, **kwargs):
super(EditAlarmForm, self).__init__(request, *args, **kwargs)
super(EditAlarmForm, self)._init_fields(readOnly=False)
super(EditAlarmForm, self).set_notification_choices(request)
self.fields.pop('state')
def handle(self, request, data):
try:
alarm_actions = []
if data['notifications']:
alarm_actions = [notification.get('notification_id')
for notification in data['notifications']]
api.monitor.alarm_update(
request,
alarm_id=self.initial['id'],
actions_enabled=self.initial['actions_enabled'],
state=self.initial['state'],
severity=data['severity'],
name=data['name'],
expression=data['expression'],
description=data['description'],
alarm_actions=alarm_actions,
)
messages.success(request,
_('Alarm has been edited successfully.'))
except Exception as e:
exceptions.handle(request, _('Unable to edit the alarm: %s') % e)
return False
return True

178
monitoring/alarms/tables.py Normal file
View File

@ -0,0 +1,178 @@
# 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
from django import template
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tables
from . import constants
from monitoring import api
LOG = logging.getLogger(__name__)
STATUS = ["OK", "WARNING", "CRITICAL", "UNKNOWN"]
def get_status(index):
if index < len(STATUS):
return STATUS[index]
else:
return "UNKNOWN: %d" % index
def show_status(data):
status = data
img_tag = '<img src="%s" title="%s"/>'
if status == 'CRITICAL':
return img_tag % (constants.CRITICAL_ICON, status)
if status in ('LOW', 'MEDIUM', 'HIGH'):
return img_tag % (constants.WARNING_ICON, status)
if status == 'OK':
return img_tag % (constants.OK_ICON, status)
if status == 'UNKNOWN' or status == 'UNDETERMINED':
return img_tag % (constants.UNKNOWN_ICON, status)
return status
def show_severity(data):
severity = data['severity']
state = data['state']
if state == 'ALARM':
return severity
else:
return state
def show_service(data):
if any(data['expression_data']['dimensions']):
dimensions = data['expression_data']['dimensions']
if 'service' in dimensions:
return str(data['expression_data']['dimensions']['service'])
return ""
def show_host(data):
if any(data['expression_data']['dimensions']):
dimensions = data['expression_data']['dimensions']
if 'hostname' in dimensions:
return str(data['expression_data']['dimensions']['hostname'])
return ""
class ShowAlarmHistory(tables.LinkAction):
name = 'history'
verbose_name = _('Show History')
url = constants.URL_PREFIX + 'history'
classes = ('btn-edit',)
class ShowAlarmMeters(tables.LinkAction):
name = 'meters'
verbose_name = _('Show Meters')
url = constants.URL_PREFIX + 'meters'
classes = ('btn-edit',)
class CreateAlarm(tables.LinkAction):
name = "create_alarm"
verbose_name = _("Create Alarm")
classes = ("ajax-modal", "btn-create")
def get_link_url(self):
return reverse(constants.URL_PREFIX + 'alarm_create',
args=(self.table.kwargs['service'],))
def allowed(self, request, datum=None):
return True
class EditAlarm(tables.LinkAction):
name = "edit_alarm"
verbose_name = _("Edit Alarm")
classes = ("ajax-modal", "btn-create")
def get_link_url(self, datum):
return reverse(constants.URL_PREFIX + 'alarm_edit',
args=(self.table.kwargs['service'], datum['id'], ))
def allowed(self, request, datum=None):
return True
class DeleteAlarm(tables.DeleteAction):
name = "delete_alarm"
verbose_name = _("Delete Alarm")
data_type_singular = _("Alarm")
data_type_plural = _("Alarms")
def allowed(self, request, datum=None):
return True
def delete(self, request, obj_id):
api.monitor.alarm_delete(request, obj_id)
class AlarmsTable(tables.DataTable):
status = tables.Column(transform=show_severity, verbose_name=_('Status'),
status_choices={(show_status('OK'), True)},
filters=[show_status, template.defaultfilters.safe])
target = tables.Column('name', verbose_name=_('Name'),
link=constants.URL_PREFIX + 'alarm_detail',
link_classes=('ajax-modal',))
host = tables.Column(transform=show_host, verbose_name=_('Host'))
service = tables.Column(transform=show_service, verbose_name=_('Service'))
state = tables.Column('state', verbose_name=_('State'))
expression = tables.Column('expression', verbose_name=_('Expression'))
enabled = tables.Column('actions_enabled',
verbose_name=_('Notifications Enabled'))
def get_object_id(self, obj):
return obj['id']
class Meta:
name = "alarms"
verbose_name = _("Alarms")
row_actions = (ShowAlarmHistory,
ShowAlarmMeters,
EditAlarm,
DeleteAlarm,
)
table_actions = (CreateAlarm, )
class AlarmHistoryTable(tables.DataTable):
status = tables.Column('Status', verbose_name=_('Status'),
status_choices={(show_status('OK'), True)},
filters=[show_status, template.defaultfilters.safe])
target = tables.Column('Host', verbose_name=_('Host'))
name = tables.Column('Service', verbose_name=_('Service'))
lastCheck = tables.Column('Last_Check', verbose_name=_('Last Check'))
time = tables.Column('Duration', verbose_name=_('Duration'))
detail = tables.Column('Status_Information',
verbose_name=_('Status_Information'))
def get_object_id(self, obj):
return obj['Last_Check'] + obj['Service']
class Meta:
name = "users"
verbose_name = _("Alarm History")
row_actions = (ShowAlarmMeters,)

View File

@ -8,7 +8,7 @@
{% load url from future %}
{% block main %}
<div style="padding: 3px;">
<a href="{% url 'horizon:overcloud:monitoring:alarm' 'all'%}" class="btn btn-small btn-run showspinner">{% trans 'All Alarms' %}</a>
<a href="{% url 'horizon:overcloud:alarms:alarm' 'all'%}" class="btn btn-small btn-run showspinner">{% trans 'All Alarms' %}</a>
</div>
{% include 'overcloud/monitoring/monitor.html' %}
{% include 'overcloud/alarms/monitor.html' %}
{% endblock %}

View File

@ -52,7 +52,7 @@
{{ group.name }}
</div>
{% for service in group.services %}
<a href="{% url 'horizon:overcloud:monitoring:alarm' service.name %}" class="showspinner">
<a href="{% url 'horizon:overcloud:alarms:alarm' service.name %}" class="showspinner">
<div class="base-chicklet {{ service.class }}">
<div>
<div class = "status-icon-holder" >

View File

@ -40,7 +40,4 @@ urlpatterns = patterns(
url(r'^alarm/(?P<service>[^/]+)/(?P<id>[^/]+)/alarm_edit/$',
views.AlarmEditView.as_view(),
name='alarm_edit'),
url(r'^notification_create$',
views.NotificationCreateView.as_view(),
name='notification_create'),
)

371
monitoring/alarms/views.py Normal file
View File

@ -0,0 +1,371 @@
# 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 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
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'
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context["date"] = datetime.datetime.utcnow()
context["service_groups"] = generate_status(self.request)
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 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 + 'alarms/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,))
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), }
class AlarmDetailView(forms.ModalFormView):
form_class = alarm_forms.DetailAlarmForm
template_name = constants.TEMPLATE_PREFIX + 'alarms/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:
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 = reverse(constants.URL_PREFIX + 'alarm')
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 "d"
class AlarmEditView(forms.ModalFormView):
form_class = alarm_forms.EditAlarmForm
template_name = constants.TEMPLATE_PREFIX + 'alarms/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:
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 = reverse(constants.URL_PREFIX + 'alarm')
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):
# to be implemented
results = []
return results
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"]

View File

@ -0,0 +1,48 @@
# 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.core import validators
from django.utils.translation import ugettext_lazy as _ # noqa
class NotificationType(object):
SMS = "SMS"
EMAIL = "EMAIL"
CHOICES = [(EMAIL, _("Email")),
(SMS, _("SMS")), ]
@staticmethod
def get_label(key):
for choice in NotificationType.CHOICES:
if choice[0] == key:
return choice[1]
return key
PHONE_VALIDATOR = validators.RegexValidator(
regex=r"^\+[()0-9 ]{5,20}$",
message=_("Address must contain a valid phone number."))
EMAIL_VALIDATOR = validators.EmailValidator(
message=_("Address must contain a valid email address."))
URL_PREFIX = 'horizon:overcloud:alarms:'
TEMPLATE_PREFIX = 'overcloud/alarms/'
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'

View File

@ -21,25 +21,6 @@ from . 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<service>[^/]+)/$',
views.AlarmServiceView.as_view(),
name='alarm'),
url(r'^history/(?P<service>[^/]+)$',
views.AlarmHistoryView.as_view(),
name='history'),
url(r'^meters/(?P<service>[^/]+)$',
views.AlarmMeterView.as_view(),
name='meters'),
url(r'^alarm/(?P<service>[^/]+)/create$',
views.AlarmCreateView.as_view(),
name='alarm_create'),
url(r'^(?P<id>[^/]+)/alarm_detail/$',
views.AlarmDetailView.as_view(),
name='alarm_detail'),
url(r'^alarm/(?P<service>[^/]+)/(?P<id>[^/]+)/alarm_edit/$',
views.AlarmEditView.as_view(),
name='alarm_edit'),
url(r'^notification_create$',
views.NotificationCreateView.as_view(),
name='notification_create'),