f037523797
The repo is Python 3 now, so update hacking to version 3.0 which supports Python 3. Fix problems found by updated hacking version. Remove hacking and friends from lower-constraints, they are not needed for co-installing. Change-Id: Ibef3bbaceb61612d678c542bc8c95da24a7e2c87
305 lines
12 KiB
Python
305 lines
12 KiB
Python
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
# Copyright 2017 FUJITSU LIMITED
|
|
#
|
|
# 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 re
|
|
|
|
from django import forms as django_forms
|
|
from django.template.loader import get_template
|
|
from django.utils import html
|
|
from django.utils.translation import ugettext_lazy as _ # noqa
|
|
import six
|
|
|
|
from horizon import exceptions
|
|
from horizon import forms
|
|
from horizon import messages
|
|
|
|
from monitoring.alarms import constants
|
|
from monitoring import api
|
|
|
|
|
|
class ExpressionWidget(forms.Widget):
|
|
def __init__(self, initial, attrs):
|
|
super(ExpressionWidget, self).__init__(attrs)
|
|
self.initial = initial
|
|
|
|
def render(self, name, value, attrs):
|
|
final_attrs = self.build_attrs(attrs, {'name': name})
|
|
if value:
|
|
dim = value
|
|
else:
|
|
if 'all' in self.initial['service']:
|
|
dim = ''
|
|
else:
|
|
dim = next(("%s=%s" % (k, v) for k, v in self.initial.items()), '')
|
|
t = get_template(constants.TEMPLATE_PREFIX + 'expression_field.html')
|
|
local_attrs = {'service': dim}
|
|
local_attrs.update(final_attrs)
|
|
|
|
return t.render(local_attrs)
|
|
|
|
|
|
class SimpleExpressionWidget(django_forms.MultiWidget):
|
|
def __init__(self, initial, attrs=None):
|
|
comparators = [('>', '>'), ('>=', '>='), ('<', '<'), ('<=', '<=')]
|
|
func = [('min', _('min')), ('max', _('max')), ('sum', _('sum')),
|
|
('count', _('count')), ('avg', _('avg'))]
|
|
_widgets = (
|
|
django_forms.widgets.Select(attrs=attrs, choices=func),
|
|
ExpressionWidget(initial, attrs={}),
|
|
django_forms.widgets.Select(attrs=attrs, choices=comparators),
|
|
django_forms.widgets.TextInput(),
|
|
)
|
|
super(SimpleExpressionWidget, self).__init__(_widgets, attrs)
|
|
|
|
def decompress(self, expr):
|
|
if expr:
|
|
return re.search(r'^(\w+)\((.*)\) ([<>=]*) (.*)$', expr).groups()
|
|
else:
|
|
return [None, 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 NotificationField(forms.MultiValueField):
|
|
def __init__(self, *args, **kwargs):
|
|
super(NotificationField, self).__init__(fields=(), *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>' % \
|
|
six.text_type(_("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['id']])
|
|
if options:
|
|
output += options
|
|
output += '</select>'
|
|
output += '<td><a href="" id="remove_notif_button">X</a></td>'
|
|
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><a href="" id="remove_notif_button">X</a></td>'
|
|
output += '</td></tr>'
|
|
output += '</table>'
|
|
label = six.text_type(_("+ Add more"))
|
|
output += '<a href="" id="add_notification_button">%s</a>' % (label)
|
|
return html.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({"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'})
|
|
choiceWidget = forms.Select
|
|
if create:
|
|
expressionWidget = SimpleExpressionWidget(initial)
|
|
notificationWidget = NotificationCreateWidget()
|
|
else:
|
|
expressionWidget = textAreaWidget
|
|
notificationWidget = NotificationCreateWidget()
|
|
|
|
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, ("", six.text_type(_("Select Notification"))))
|
|
else:
|
|
notification_choices.insert(
|
|
0, ("", six.text_type(_("No notifications available."))))
|
|
|
|
self.fields['notifications'].choices = notification_choices
|
|
|
|
def clean_expression(self):
|
|
data = self.cleaned_data['expression']
|
|
value = data.split(' ')[2]
|
|
if not value.isdigit():
|
|
raise forms.ValidationError("Value must be an integer")
|
|
|
|
# Always return the cleaned data, whether you have changed it or
|
|
# not.
|
|
return data
|
|
|
|
|
|
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('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,
|
|
ok_actions=alarm_actions,
|
|
undetermined_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.message)
|
|
return False
|
|
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('id')
|
|
for notification in data['notifications']]
|
|
api.monitor.alarm_update(
|
|
request,
|
|
alarm_id=self.initial['id'],
|
|
state=self.initial['state'],
|
|
severity=data['severity'],
|
|
name=data['name'],
|
|
expression=data['expression'],
|
|
description=data['description'],
|
|
actions_enabled=data['actions_enabled'],
|
|
alarm_actions=alarm_actions,
|
|
ok_actions=alarm_actions,
|
|
undetermined_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
|