Browse Source

Multiple changes:

1) Makes mixin for API views.
2) Makes device monitoring notification.
And little bit fixes
devel
bashmak 8 years ago
parent
commit
ffc5a6d5ac
  1. 68
      agent/monitoring_agent.py
  2. 7
      chatbot/telebot.py
  3. 2
      devapp/forms.py
  4. 44
      devapp/locale/ru/LC_MESSAGES/django.po
  5. 34
      devapp/migrations/0006_auto_20180129_1625.py
  6. 17
      devapp/models.py
  7. 6
      devapp/templates/devapp/add_dev.html
  8. 2
      devapp/templates/devapp/dev.html
  9. 20
      devapp/templates/devapp/devices.html
  10. 6
      devapp/urls.py
  11. 112
      devapp/views.py
  12. 57
      djing/global_base_views.py
  13. 6
      djing/settings.py
  14. 4
      djing/views.py
  15. 1
      requirements.txt
  16. 6
      taskapp/handle.py

68
agent/monitoring_agent.py

@ -0,0 +1,68 @@
#!/usr/bin/env python3
import sys
import re
from hashlib import sha256
import requests
API_AUTH_SECRET = 'asihdfaoisydoiayosidyaoisydoiasydaisydasd'
SERVER_DOMAIN = 'http://localhost:8000'
IP_REGEXP = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
def calc_hash(data):
if type(data) is str:
result_data = data.encode('utf-8')
else:
result_data = bytes(data)
return sha256(result_data).hexdigest()
def check_sign(get_list, sign):
hashed = '_'.join(get_list)
my_sign = calc_hash(hashed)
return sign == my_sign
def validate(regexp, string):
if not bool(re.match(regexp, string)):
raise ValueError
return string
def validate_status(text):
if not text in ('UP', 'DOWN', 'UNREACHABLE'):
raise ValueError
return text
def send_request(ip, status, sign):
r = requests.get(
"%(domain)s/dev/on_device_down/" % {'domain': SERVER_DOMAIN},
params={
'ip': ip,
'status': status,
'sign': sign
})
if r.status_code == 200:
print(r.json())
else:
print('Status:', r.status_code, r.text)
if __name__ == '__main__':
if len(sys.argv) < 3:
print('You forget parameters, example of usage:\n'
'$ python3 ./monitoring_agent.py 192.168.0.100 DOWN|UP|UNREACHABLE')
exit(0)
dev_ip = validate(IP_REGEXP, sys.argv[1])
status = validate_status(sys.argv[2])
sign = calc_hash('_'.join((dev_ip, status, API_AUTH_SECRET)))
send_request(dev_ip, status, sign)

7
chatbot/telebot.py

@ -115,7 +115,6 @@ class DjingTelebot(helper.ChatHandler):
self._dialog_fn = None self._dialog_fn = None
self._chat_id = 0 self._chat_id = 0
# пингуем адрес
def ping(self, ip=None): def ping(self, ip=None):
if ip is None: if ip is None:
self._question(_("Let's ping, write ip. It will be necessary to wait 10 seconds"), self.ping) self._question(_("Let's ping, write ip. It will be necessary to wait 10 seconds"), self.ping)
@ -131,7 +130,7 @@ class DjingTelebot(helper.ChatHandler):
self._sent_reply(_("You're '%s', right?") % self._current_user.get_full_name()) self._sent_reply(_("You're '%s', right?") % self._current_user.get_full_name())
# Просто отправляем текст оповещения указанной учётке
# Just sending text to specified account
def send_notify(msg_text, account, tag='none'): def send_notify(msg_text, account, tag='none'):
try: try:
MessageQueue.objects.push(msg=msg_text, user=account, tag=tag) MessageQueue.objects.push(msg=msg_text, user=account, tag=tag)
@ -143,6 +142,6 @@ def send_notify(msg_text, account, tag='none'):
except TelegramBot.DoesNotExist: except TelegramBot.DoesNotExist:
raise ChatException(_("Recipient '%s' does not subscribed on notifications") % account.get_full_name()) raise ChatException(_("Recipient '%s' does not subscribed on notifications") % account.get_full_name())
except ProtocolError as e: except ProtocolError as e:
raise ChatException(e)
raise ChatException('ProtocolError: %s' % e)
except TelegramError as e: except TelegramError as e:
raise ChatException("%s - %s" % (e, tb.user.get_full_name()))
raise ChatException('Telegram error: %s' % e)

2
devapp/forms.py

@ -19,7 +19,7 @@ class DeviceForm(forms.ModelForm):
class Meta: class Meta:
model = models.Device model = models.Device
exclude = ['map_dot']
exclude = ['map_dot', 'status']
widgets = { widgets = {
'ip_address': forms.TextInput(attrs={ 'ip_address': forms.TextInput(attrs={
'pattern': ip_addr_regex, 'pattern': ip_addr_regex,

44
devapp/locale/ru/LC_MESSAGES/django.po

@ -221,7 +221,7 @@ msgstr "Прикрепленный абонент"
#: templates/devapp/custom_dev_page/onu.html:47 #: templates/devapp/custom_dev_page/onu.html:47
msgid "ONU Status" msgid "ONU Status"
msgstr ""
msgstr "Состояние ONU"
#: templates/devapp/custom_dev_page/onu.html:57 #: templates/devapp/custom_dev_page/onu.html:57
msgid "ONU error" msgid "ONU error"
@ -229,7 +229,7 @@ msgstr "ONU ошибка"
#: templates/devapp/custom_dev_page/onu.html:71 #: templates/devapp/custom_dev_page/onu.html:71
msgid "Name on OLT" msgid "Name on OLT"
msgstr ""
msgstr "Имя на OLT"
#: templates/devapp/custom_dev_page/onu.html:72 #: templates/devapp/custom_dev_page/onu.html:72
msgid "Distance(m)" msgid "Distance(m)"
@ -238,11 +238,11 @@ msgstr "Расстояние (м)"
#: templates/devapp/custom_dev_page/onu.html:77 #: templates/devapp/custom_dev_page/onu.html:77
#: templates/devapp/custom_dev_page/onu.html:85 #: templates/devapp/custom_dev_page/onu.html:85
msgid "Mac on OLT" msgid "Mac on OLT"
msgstr ""
msgstr "MAC адрес на OLT"
#: templates/devapp/custom_dev_page/onu.html:78 #: templates/devapp/custom_dev_page/onu.html:78
msgid "Mac-addresses does not match" msgid "Mac-addresses does not match"
msgstr ""
msgstr "MAC адреса не совпадают"
#: templates/devapp/custom_dev_page/onu.html:79 #: templates/devapp/custom_dev_page/onu.html:79
#: templates/devapp/custom_dev_page/onu.html:81 #: templates/devapp/custom_dev_page/onu.html:81
@ -312,7 +312,7 @@ msgstr "Устройства без группы"
#: templates/devapp/fix_dev_group.html:17 #: templates/devapp/fix_dev_group.html:17
msgid "Fix device group" msgid "Fix device group"
msgstr ""
msgstr "Поправить группу устройства"
#: templates/devapp/group_list.html:18 #: templates/devapp/group_list.html:18
msgid "Group title" msgid "Group title"
@ -408,11 +408,11 @@ msgstr "Инфа о точке сохранена"
#: views.py:110 #: views.py:110
msgid "You have redirected to existing device" msgid "You have redirected to existing device"
msgstr ""
msgstr "Вы были переадресованы на существующее устройство"
#: views.py:113 views.py:329 views.py:419 #: views.py:113 views.py:329 views.py:419
msgid "Please attach user group for device" msgid "Please attach user group for device"
msgstr ""
msgstr "Пожалуйста назначте устройству группу в настройках"
#: views.py:117 views.py:275 views.py:304 views.py:421 #: views.py:117 views.py:275 views.py:304 views.py:421
msgid "Form is invalid, check fields and try again" msgid "Form is invalid, check fields and try again"
@ -473,11 +473,29 @@ msgstr "Исправлено, обновите страницу"
msgid "Parent device not found" msgid "Parent device not found"
msgstr "Вышестоящее устройство не найдено" msgstr "Вышестоящее устройство не найдено"
#~ msgid "Map point"
#~ msgstr "Точка топологии"
msgid "Send notify when monitoring state changed"
msgstr "Отправлять уведомления при событиях мониторинга"
msgid "Device %(device_name)s is up"
msgstr "%(device_name)s в сети"
msgid "Device %(device_name)s is down"
msgstr "%(device_name)s не в сети"
msgid "Device %(device_name)s is unreachable"
msgstr "%(device_name)s недостижим"
msgid "Device %(device_name)s getting undefined status code"
msgstr "Устройство %(device_name)s получило не определённый код состояния"
msgid "Undefined"
msgstr "Не определено"
msgid "Up"
msgstr "В сети"
#~ msgid "Find the subscriber"
#~ msgstr "Найти абонента"
msgid "Unreachable"
msgstr "Не доступно"
#~ msgid "View the device"
#~ msgstr "Посмотреть устройство"
msgid "Down"
msgstr "Не в сети"

34
devapp/migrations/0006_auto_20180129_1625.py

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-01-29 16:25
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('devapp', '0005_device_snmp_item_num'),
]
operations = [
migrations.AlterModelOptions(
name='device',
options={'ordering': ['comment'], 'permissions': (('can_view_device', 'Can view device'),), 'verbose_name': 'Device', 'verbose_name_plural': 'Devices'},
),
migrations.AddField(
model_name='device',
name='is_noticeable',
field=models.BooleanField(default=False, verbose_name='Send notify when monitoring state changed'),
),
migrations.AddField(
model_name='device',
name='status',
field=models.CharField(choices=[('und', 'Undefined'), ('up', 'Up'), ('unr', 'Unreachable'), ('dwn', 'Down')], default='und', max_length=3, verbose_name='Status'),
),
migrations.AlterField(
model_name='device',
name='snmp_item_num',
field=models.PositiveSmallIntegerField(blank=True, default=0, verbose_name='SNMP Number'),
),
]

17
devapp/models.py

@ -54,7 +54,17 @@ class Device(models.Model):
user_group = models.ForeignKey('abonapp.AbonGroup', verbose_name=_('User group'), on_delete=models.SET_NULL, null=True, blank=True) user_group = models.ForeignKey('abonapp.AbonGroup', verbose_name=_('User group'), on_delete=models.SET_NULL, null=True, blank=True)
parent_dev = models.ForeignKey('self', verbose_name=_('Parent device'), blank=True, null=True, on_delete=models.SET_NULL) parent_dev = models.ForeignKey('self', verbose_name=_('Parent device'), blank=True, null=True, on_delete=models.SET_NULL)
snmp_item_num = models.PositiveSmallIntegerField(_('SNMP Number'), default=0)
snmp_item_num = models.PositiveSmallIntegerField(_('SNMP Number'), default=0, blank=True)
NETWORK_STATES = (
('und', _('Undefined')),
('up', _('Up')),
('unr', _('Unreachable')),
('dwn', _('Down'))
)
status = models.CharField(_('Status'), max_length=3, choices=NETWORK_STATES, default='und')
is_noticeable = models.BooleanField(_('Send notify when monitoring state changed'), default=False)
objects = DeviceManager() objects = DeviceManager()
@ -65,14 +75,13 @@ class Device(models.Model):
) )
verbose_name = _('Device') verbose_name = _('Device')
verbose_name_plural = _('Devices') verbose_name_plural = _('Devices')
ordering = ['comment']
def get_abons(self): def get_abons(self):
pass pass
def get_status(self): def get_status(self):
url = getattr(settings, 'NAGIOS_URL')
if url:
return requests.get('%s/host/status?addr=%s' % (url, self.ip_address))
return self.status
def get_manager_klass(self): def get_manager_klass(self):
klasses = [kl for kl in DEVICE_TYPES if kl[0] == self.devtype] klasses = [kl for kl in DEVICE_TYPES if kl[0] == self.devtype]

6
devapp/templates/devapp/add_dev.html

@ -54,8 +54,10 @@
</div> </div>
</div> </div>
{% bootstrap_icon 'list-alt' as ic %}
{% bootstrap_field form.snmp_item_num addon_before=ic %}
{% bootstrap_icon 'list-alt' as ic %}
{% bootstrap_field form.snmp_item_num addon_before=ic %}
{% bootstrap_field form.is_noticeable %}
<div class="btn-group btn-group-sm"> <div class="btn-group btn-group-sm">
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">

2
devapp/templates/devapp/dev.html

@ -54,6 +54,8 @@
{% bootstrap_icon 'list-alt' as ic %} {% bootstrap_icon 'list-alt' as ic %}
{% bootstrap_field form.snmp_item_num addon_before=ic %} {% bootstrap_field form.snmp_item_num addon_before=ic %}
{% bootstrap_field form.is_noticeable %}
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary"> <button type="submit" class="btn btn-sm btn-primary">
<span class="glyphicon glyphicon-save"></span> {% trans 'Save' %} <span class="glyphicon glyphicon-save"></span> {% trans 'Save' %}

20
devapp/templates/devapp/devices.html

@ -29,7 +29,7 @@
{% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %} {% if order_by == 'comment' %}<span class="glyphicon glyphicon-filter"></span>{% endif %}
</th> </th>
<th class="col-md-3">{% trans 'Mac address' %}</th> <th class="col-md-3">{% trans 'Mac address' %}</th>
<th class="col-md-3 hidden-xs hidden-sm">{% trans 'Plugin output' %}</th>
{# <th class="col-md-3 hidden-xs hidden-sm">{% trans 'Plugin output' %}</th> #}
<th class="col-md-1"> <th class="col-md-1">
<a href="{% url 'devapp:devs' group.pk %}?order_by=devtype&dir={{ dir|default:"down" }}"> <a href="{% url 'devapp:devs' group.pk %}?order_by=devtype&dir={{ dir|default:"down" }}">
{% trans 'Device type' %} {% trans 'Device type' %}
@ -43,20 +43,24 @@
<tbody> <tbody>
{% with can_del_dev=perms.devapp.delete_device can_ch_dev=perms.devapp.change_device %} {% with can_del_dev=perms.devapp.delete_device can_ch_dev=perms.devapp.change_device %}
{% for dev in devices %} {% for dev in devices %}
<tr> <tr>
<td> <td>
{% if dev.mon %}
{% if dev.mon.current_state == '0' %}
{% if dev.status == 'und' %}&ndash;
{% else %}
{% if dev.status == 'unr' or dev.status == 'dwn' %}
<span class="glyphicon glyphicon-exclamation-sign text-danger"></span>
{% elif dev.status == 'up' %}
<span class="glyphicon glyphicon-ok-circle text-success"></span> <span class="glyphicon glyphicon-ok-circle text-success"></span>
{% else %} {% else %}
<span class="glyphicon glyphicon-exclamation-sign text-danger"></span>
<span class="glyphicon glyphicon-question-sign text-warning"></span>
{% endif %} {% endif %}
{% else %}&ndash;{% endif %}
{% endif %}
</td> </td>
<td><a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.ip_address }}</a></td> <td><a href="{% url 'devapp:view' dev.user_group.pk dev.pk %}">{{ dev.ip_address }}</a></td>
<td>{{ dev.comment }}</td> <td>{{ dev.comment }}</td>
<td>{{ dev.mac_addr|default:_('Not assigned') }}</td> <td>{{ dev.mac_addr|default:_('Not assigned') }}</td>
<td class="hidden-xs hidden-sm">{{ dev.mon.plugin_output|default:'&ndash;' }}</td>
{# <td class="hidden-xs hidden-sm">{{ dev.mon.plugin_output|default:'&ndash;' }}</td> #}
<td>{{ dev.get_devtype_display }}</td> <td>{{ dev.get_devtype_display }}</td>
<td class="btn-group btn-group-xs btn-group-justified"> <td class="btn-group btn-group-xs btn-group-justified">
{% if can_del_dev %} {% if can_del_dev %}
@ -73,7 +77,7 @@
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>
<td colspan="7">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' group.pk %}">{% trans 'Create' %}</a></td>
<td colspan="6">{% trans 'Devices does not found' %}. <a href="{% url 'devapp:add' group.pk %}">{% trans 'Create' %}</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
@ -81,7 +85,7 @@
<tfoot> <tfoot>
<tr> <tr>
<td colspan="7">
<td colspan="6">
<a href="{% url 'devapp:add' group.pk %}" class="btn btn-success btn-sm"> <a href="{% url 'devapp:add' group.pk %}" class="btn btn-success btn-sm">
<span class="glyphicon glyphicon-plus"></span> {% trans 'Create' %} <span class="glyphicon glyphicon-plus"></span> {% trans 'Create' %}
</a> </a>

6
devapp/urls.py

@ -1,5 +1,4 @@
from django.conf.urls import url from django.conf.urls import url
from . import views from . import views
@ -23,5 +22,8 @@ urlpatterns = [
url(r'^(?P<group_id>\d+)/(?P<device_id>\d+)/(?P<portid>\d+)/del$', views.delete_single_port, name='del_port'), url(r'^(?P<group_id>\d+)/(?P<device_id>\d+)/(?P<portid>\d+)/del$', views.delete_single_port, name='del_port'),
url(r'^(?P<group_id>\d+)/(?P<device_id>\d+)/(?P<port_id>\d+)/edit$', views.edit_single_port, name='edit_port'), url(r'^(?P<group_id>\d+)/(?P<device_id>\d+)/(?P<port_id>\d+)/edit$', views.edit_single_port, name='edit_port'),
url(r'^fix_device_group/(?P<device_id>\d+)$', views.fix_device_group, name='fix_device_group'), url(r'^fix_device_group/(?P<device_id>\d+)$', views.fix_device_group, name='fix_device_group'),
url(r'^search_dev$', views.search_dev)
url(r'^search_dev$', views.search_dev),
# Monitoring api
url(r'^on_device_down/$', views.OnDevDown.as_view())
] ]

112
devapp/views.py

@ -1,23 +1,28 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.gis.shortcuts import render_to_text from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import IntegrityError from django.db import IntegrityError
from django.db.models import Q, Count from django.db.models import Q, Count
from django.http import HttpResponse
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect, get_object_or_404, resolve_url from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib import messages from django.contrib import messages
from django.utils.translation import gettext_lazy as _
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _, gettext
from easysnmp import EasySNMPTimeoutError, EasySNMPError from easysnmp import EasySNMPTimeoutError, EasySNMPError
from json import dumps
from .models import Device, Port, DeviceDBException, DeviceMonitoringException
from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper
from .forms import DeviceForm, PortForm
from mydefs import pag_mn, res_success, res_error, only_admins, ping, order_helper, ip_addr_regex
from abonapp.models import AbonGroup, Abon from abonapp.models import AbonGroup, Abon
from django.conf import settings from django.conf import settings
from guardian.decorators import permission_required_or_403 as permission_required from guardian.decorators import permission_required_or_403 as permission_required
from guardian.shortcuts import get_objects_for_user from guardian.shortcuts import get_objects_for_user
from chatbot.telebot import send_notify
from chatbot.models import ChatException
from jsonview.decorators import json_view
from djing.global_base_views import HashAuthView, AllowedSubnetMixin
from .models import Device, Port, DeviceDBException, DeviceMonitoringException
from .forms import DeviceForm, PortForm
@login_required @login_required
@ -27,15 +32,16 @@ def devices(request, group_id):
if not request.user.has_perm('abonapp.can_view_abongroup', group): if not request.user.has_perm('abonapp.can_view_abongroup', group):
raise PermissionDenied raise PermissionDenied
try: try:
devs = Device.objects.filter(user_group=group).select_related('user_group').only('comment', 'mac_addr', 'devtype', 'user_group', 'pk', 'ip_address')
devs = Device.objects.filter(user_group=group) \
.select_related('user_group') \
.only('comment', 'mac_addr', 'devtype', 'user_group', 'pk', 'ip_address')
# фильтр
dr, field = order_helper(request) dr, field = order_helper(request)
if field: if field:
devs = devs.order_by(field) devs = devs.order_by(field)
devs = pag_mn(request, devs) devs = pag_mn(request, devs)
devs = Device.objects.wrap_monitoring_info(devs)
#devs = Device.objects.wrap_monitoring_info(devs)
except (DeviceDBException, DeviceMonitoringException) as e: except (DeviceDBException, DeviceMonitoringException) as e:
messages.error(request, e) messages.error(request, e)
@ -52,7 +58,7 @@ def devices(request, group_id):
@only_admins @only_admins
def devices_null_group(request): def devices_null_group(request):
devs = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address') devs = Device.objects.filter(user_group=None).only('comment', 'devtype', 'user_group', 'pk', 'ip_address')
# фильтр
dr, field = order_helper(request) dr, field = order_helper(request)
if field: if field:
devs = devs.order_by(field) devs = devs.order_by(field)
@ -99,11 +105,8 @@ def dev(request, group_id, device_id=0):
try: try:
frm = DeviceForm(request.POST, instance=devinst) frm = DeviceForm(request.POST, instance=devinst)
if frm.is_valid(): if frm.is_valid():
ndev = frm.save()
ndev.update_dhcp()
messages.success(request, _('Device info has been saved'))
return redirect('devapp:edit', ndev.user_group.pk, ndev.pk)
else:
# check if that device is exist
try: try:
already_dev = Device.objects.get(mac_addr=request.POST.get('mac_addr')) already_dev = Device.objects.get(mac_addr=request.POST.get('mac_addr'))
if already_dev.user_group: if already_dev.user_group:
@ -114,6 +117,14 @@ def dev(request, group_id, device_id=0):
return redirect('devapp:fix_device_group', already_dev.pk) return redirect('devapp:fix_device_group', already_dev.pk)
except Device.DoesNotExist: except Device.DoesNotExist:
pass pass
# else update device info
ndev = frm.save()
# change device info in dhcpd.conf
ndev.update_dhcp()
messages.success(request, _('Device info has been saved'))
return redirect('devapp:edit', ndev.user_group.pk, ndev.pk)
else:
messages.error(request, _('Form is invalid, check fields and try again')) messages.error(request, _('Form is invalid, check fields and try again'))
except IntegrityError as e: except IntegrityError as e:
if 'unique constraint' in e.message: if 'unique constraint' in e.message:
@ -129,7 +140,7 @@ def dev(request, group_id, device_id=0):
'comment': request.GET.get('c'), 'comment': request.GET.get('c'),
'ip_address': request.GET.get('ip'), 'ip_address': request.GET.get('ip'),
'man_passw': getattr(settings, 'DEFAULT_SNMP_PASSWORD', ''), 'man_passw': getattr(settings, 'DEFAULT_SNMP_PASSWORD', ''),
'snmp_item_num': request.GET.get('n')
'snmp_item_num': request.GET.get('n') or 0
}) })
else: else:
frm = DeviceForm(instance=devinst) frm = DeviceForm(instance=devinst)
@ -401,7 +412,7 @@ def search_dev(request):
Q(comment__icontains=word) | Q(ip_address=word) Q(comment__icontains=word) | Q(ip_address=word)
).only('pk', 'ip_address', 'comment')[:16] ).only('pk', 'ip_address', 'comment')[:16]
results = [{'id': dev.pk, 'text': "%s: %s" % (dev.ip_address, dev.comment)} for dev in results] results = [{'id': dev.pk, 'text': "%s: %s" % (dev.ip_address, dev.comment)} for dev in results]
return HttpResponse(dumps(results, ensure_ascii=False))
return JsonResponse(results, json_dumps_params={'ensure_ascii': False})
@login_required @login_required
@ -453,10 +464,10 @@ def fix_onu(request):
text = text + ' %s' % _('Parent device not found') text = text + ' %s' % _('Parent device not found')
except Device.DoesNotExist: except Device.DoesNotExist:
pass pass
return HttpResponse(dumps({
return JsonResponse({
'status': status, 'status': status,
'dat': text 'dat': text
}))
})
@login_required @login_required
@ -471,3 +482,66 @@ def fix_port_confict(request, group_id, device_id, port_id):
'device': device, 'device': device,
'port': port 'port': port
}) })
class OnDevDown(AllowedSubnetMixin, HashAuthView):
#
# Api view for monitoring devices
#
http_method_names = ['get']
@method_decorator(json_view)
def get(self, request):
try:
dev_ip = request.GET.get('ip')
dev_status = request.GET.get('status')
if dev_ip is None or dev_ip == '':
return {'text': 'ip does not passed'}
if not bool(re.match(ip_addr_regex, dev_ip)):
return {'text': 'ip address is not valid'}
possible_devices = Device.objects.filter(ip_address=dev_ip)
if possible_devices.count() < 1:
return {
'text': 'Devices with ip %s does not exist' % dev_ip
}
else:
device_down = possible_devices[0]
recipients = device_down.user_group.profiles.all()
names = list()
if dev_status == 'UP':
device_down.status = 'up'
notify_text = 'Device %(device_name)s is up'
elif dev_status == 'DOWN':
device_down.status = 'dwn'
notify_text = 'Device %(device_name)s is down'
elif dev_status == 'UNREACHABLE':
device_down.status = 'unr'
notify_text = 'Device %(device_name)s is unreachable'
else:
device_down.status = 'und'
notify_text = 'Device %(device_name)s getting undefined status code'
device_down.save(update_fields=['status'])
for recipient in recipients:
send_notify(
msg_text=gettext(notify_text) % {
'device_name': "%s %s" % (device_down.ip_address, device_down.comment)
},
account=recipient,
tag='devmon'
)
names.append(recipient.username)
return {
'text': 'notification successfully sent',
'recipients': names
}
except ChatException as e:
return {
'text': str(e)
}

57
djing/global_base_views.py

@ -0,0 +1,57 @@
from hashlib import sha256
from django.views.generic.base import View
from django.http.response import HttpResponseForbidden
from django.conf import settings
from netaddr import IPNetwork, IPAddress
API_AUTH_SECRET = getattr(settings, 'API_AUTH_SECRET')
API_AUTH_SUBNET = getattr(settings, 'API_AUTH_SUBNET')
class HashAuthView(View):
@staticmethod
def calc_hash(data):
if type(data) is str:
result_data = data.encode('utf-8')
else:
result_data = bytes(data)
return sha256(result_data).hexdigest()
@staticmethod
def check_sign(get_list, sign):
hashed = '_'.join(get_list)
my_sign = HashAuthView.calc_hash(hashed)
return sign == my_sign
def __init__(self, *args, **kwargs):
if API_AUTH_SECRET is None:
raise ImportError('You must specified API_AUTH_SECRET is settings')
else:
super(HashAuthView, self).__init__(*args, **kwargs)
def dispatch(self, request, *args, **kwargs):
sign = request.GET.get('sign')
# Transmittent get list without sign
get_values = request.GET.copy()
del get_values['sign']
if HashAuthView.check_sign(list(get_values.values()) + [API_AUTH_SECRET], sign):
return super(HashAuthView, self).dispatch(request, *args, **kwargs)
else:
return HttpResponseForbidden('Access Denied')
class AllowedSubnetMixin(object):
def dispatch(self, request, *args, **kwargs):
"""
Check if user ip in allowed subnet.
Return 403 denied otherwise.
"""
ip = IPAddress(request.META.get('REMOTE_ADDR'))
if ip in IPNetwork(API_AUTH_SUBNET):
return super(AllowedSubnetMixin, self).dispatch(request, *args, **kwargs)
else:
return HttpResponseForbidden('Access Denied')

6
djing/settings.py

@ -180,3 +180,9 @@ TELEGRAM_BOT_TOKEN = local_settings.TELEGRAM_BOT_TOKEN
TELEPHONE_REGEXP = r'^\+[7,8,9,3]\d{10,11}$' TELEPHONE_REGEXP = r'^\+[7,8,9,3]\d{10,11}$'
ASTERISK_MANAGER_AUTH = local_settings.ASTERISK_MANAGER_AUTH ASTERISK_MANAGER_AUTH = local_settings.ASTERISK_MANAGER_AUTH
# Secret word for auth to api views by hash
API_AUTH_SECRET = local_settings.API_AUTH_SECRET
# Allowed subnet for api
API_AUTH_SUBNET = local_settings.API_AUTH_SUBNET

4
djing/views.py

@ -8,7 +8,3 @@ def home(request):
return redirect('acc_app:profile') return redirect('acc_app:profile')
else: else:
return redirect('client_side:home') return redirect('client_side:home')
def finance_report(request):
pass

1
requirements.txt

@ -20,3 +20,4 @@ django-jsonfield
requests requests
webdavclient webdavclient
pyst2 pyst2
django-jsonview

6
taskapp/handle.py

@ -15,10 +15,10 @@ def handle(task, author, recipients, abon_group):
try: try:
dst_account = recipient dst_account = recipient
text = _('Task') text = _('Task')
# Если сигнал самому себе то молчим
# If signal to myself then quietly
if author == recipient: if author == recipient:
return return
# Если задача завершена или провалена
# If task completed or failed
elif task.state == 'F' or task.state == 'C': elif task.state == 'F' or task.state == 'C':
text = _('Task completed') text = _('Task completed')
if task.abon is not None: if task.abon is not None:
@ -36,7 +36,7 @@ def handle(task, author, recipients, abon_group):
fulltext += task.descr if task.descr else '' fulltext += task.descr if task.descr else ''
if task.state == 'F' or task.state == 'C': if task.state == 'F' or task.state == 'C':
# Если задача завершена или провалена то отправляем одно оповещение автору
# If task completed or failed than send one message to author
try: try:
send_notify(fulltext, author, tag='taskap') send_notify(fulltext, author, tag='taskap')
except ChatException as e: except ChatException as e:

Loading…
Cancel
Save