Browse Source

Fix when error while snmp walk

devel
bashmak 8 years ago
parent
commit
7b7e07fa0d
  1. 46
      agent/mod_mikrotik.py
  2. 29
      devapp/base_intr.py
  3. 47
      devapp/dev_types.py
  4. 15
      devapp/views.py

46
agent/mod_mikrotik.py

@ -3,7 +3,7 @@ import socket
import binascii
from abc import ABCMeta
from hashlib import md5
from typing import List, Iterable
from typing import List, Iterable, Optional, Tuple
from .core import BaseTransmitter, NasFailedResult, NasNetworkError
from mydefs import ping, singleton
from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff
@ -336,7 +336,7 @@ class IpAddressListObj(IpStruct):
class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
def add(self, list_name: str, ip: IpStruct, timeout=0):
def add(self, list_name: str, ip: IpStruct):
if not isinstance(ip, IpStruct):
raise TypeError
commands = [
@ -344,18 +344,8 @@ class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
'=list=%s' % list_name,
'=address=%s' % str(ip)
]
if timeout > 0:
commands.append('=timeout=%d' % timeout)
return self._exec_cmd(commands)
def _edit(self, mk_id, timeout=None):
if timeout is not None:
commands = [
'/ip/firewall/address-list/set', '=.id=' + str(mk_id),
'=timeout=%d' % timeout
]
return self._exec_cmd(commands)
def remove(self, mk_id):
return self._exec_cmd([
'/ip/firewall/address-list/remove',
@ -410,12 +400,10 @@ class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
class MikrotikTransmitter(QueueManager, IpAddressListManager):
def add_user_range(self, user_list: VectorAbon):
super(MikrotikTransmitter, self).add_user_range(user_list)
for usr in user_list:
self.add_user(usr)
def remove_user_range(self, users: VectorAbon):
super(MikrotikTransmitter, self).remove_user_range(users)
queue_ids = [usr.queue_id for usr in users if usr is not None]
QueueManager.remove_range(self, queue_ids)
ips = [user.ip for user in users if isinstance(user, AbonStruct)]
@ -424,34 +412,30 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
if ip_list_entity is not None and len(ip_list_entity) > 1:
IpAddressListManager.remove(self, ip_list_entity[0]['=.id'])
def add_user(self, user: AbonStruct, ip_timeout=0):
super(MikrotikTransmitter, self).add_user(user, ip_timeout)
def add_user(self, user: AbonStruct, *args):
if not isinstance(user.ip, IpStruct):
raise TypeError
if user.tariff is None or not isinstance(user.tariff, TariffStruct):
return
QueueManager.add(self, user)
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip, ip_timeout)
# удаляем из списка заблокированных абонентов
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip)
# remove user from denied user list
firewall_ip_list_obj = IpAddressListManager.find(self, user.ip, LIST_USERS_BLOCKED)
if len(firewall_ip_list_obj) > 1:
IpAddressListManager.remove(self, firewall_ip_list_obj[0]['=.id'])
def remove_user(self, user: AbonStruct):
super(MikrotikTransmitter, self).remove_user(user)
QueueManager.remove(self, user)
firewall_ip_list_obj = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
if firewall_ip_list_obj is not None and len(firewall_ip_list_obj) > 1:
IpAddressListManager.remove(self, firewall_ip_list_obj[0]['=.id'])
# обновляем основную инфу абонента
def update_user(self, user: AbonStruct, ip_timeout=0):
super(MikrotikTransmitter, self).update_user(user, ip_timeout)
def update_user(self, user: AbonStruct, *args):
if not isinstance(user.ip, IpStruct):
raise TypeError
# ищем ip абонента в списке ip
find_res = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
queue = QueueManager.find(self, 'uid%d' % user.uid)
if not user.is_active:
# если не активен - то и обновлять не надо
@ -459,11 +443,12 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
if len(find_res) > 1:
# и если найден был - то удалим ip из разрешённых
IpAddressListManager.remove(self, find_res[0]['=.id'])
if queue is not None:
QueueManager.remove(self, user)
return
# если нет услуги то её не должно быть и в nas
if user.tariff is None or not isinstance(user.tariff, TariffStruct):
queue = QueueManager.find(self, 'uid%d' % user.uid)
if queue is not None:
QueueManager.remove(self, user)
return
@ -471,22 +456,17 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
# если не найден (mikrotik возвращает пустой словарь в списке если ничего нет)
if len(find_res) < 2:
# добавим запись об абоненте
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip, ip_timeout)
else:
mk_id = find_res[0]['=.id']
# то обновляем запись в mikrotik
IpAddressListManager._edit(self, mk_id, ip_timeout)
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip)
# Проверяем шейпер
queue = QueueManager.find(self, 'uid%d' % user.uid)
if queue is None:
QueueManager.add(self, user)
return
if queue != user:
QueueManager.update(self, user)
def ping(self, host, count=10):
super(MikrotikTransmitter, self).ping(host)
def ping(self, host, count=10) -> Optional[Tuple[int, int]]:
r = self._exec_cmd([
'/ip/arp/print',
'?address=%s' % host
@ -520,7 +500,7 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
def remove_tariff(self, tid: int):
pass
def read_users(self):
def read_users(self) -> Iterable[AbonStruct]:
# shapes is ShapeItem
allowed_ips = set(IpAddressListManager.read_ips_iter(self, LIST_USERS_ALLOWED))
queues = set(q for q in QueueManager.read_queue_iter(self) if q.ip in allowed_ips)

29
devapp/base_intr.py

@ -1,7 +1,16 @@
from abc import ABCMeta, abstractmethod
from datetime import timedelta
from typing import Union, Iterable, AnyStr, Generator
from easysnmp import Session
ListOrError = Union[
Iterable,
Union[Exception, Iterable]
]
class DeviceImplementationError(Exception):
pass
@ -12,7 +21,7 @@ class DevBase(object, metaclass=ABCMeta):
self.db_instance = dev_instance
@staticmethod
def description():
def description() -> AnyStr:
pass
@abstractmethod
@ -20,29 +29,29 @@ class DevBase(object, metaclass=ABCMeta):
pass
@abstractmethod
def get_ports(self):
def get_ports(self) -> ListOrError:
pass
@abstractmethod
def get_device_name(self):
def get_device_name(self) -> AnyStr:
"""Return device name by snmp"""
@abstractmethod
def uptime(self):
def uptime(self) -> timedelta:
pass
@abstractmethod
def get_template_name(self):
def get_template_name(self) -> AnyStr:
"""Return path to html template for device"""
@staticmethod
@abstractmethod
def has_attachable_to_subscriber():
def has_attachable_to_subscriber() -> bool:
"""Can connect device to subscriber"""
@staticmethod
@abstractmethod
def is_use_device_port():
def is_use_device_port() -> bool:
"""True if used device port while opt82 authorization"""
@ -62,7 +71,7 @@ class BasePort(object, metaclass=ABCMeta):
def enable(self):
pass
def mac(self):
def mac(self) -> str:
return ':'.join(['%x' % ord(i) for i in self._mac])
@ -75,11 +84,11 @@ class SNMPBaseWorker(object, metaclass=ABCMeta):
def set_int_value(self, oid, value):
return self.ses.set(oid, value, 'i')
def get_list(self, oid):
def get_list(self, oid) -> Generator:
for v in self.ses.walk(oid):
yield v.value
def get_list_keyval(self, oid):
def get_list_keyval(self, oid) -> Generator:
for v in self.ses.walk(oid):
snmpnum = v.oid.split('.')[-1:]
yield v.value, snmpnum[0] if len(snmpnum) > 0 else None

47
devapp/dev_types.py

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
from django.utils.translation import gettext_lazy as _
from django.utils.translation import gettext_lazy as _, gettext
from mydefs import RuTimedelta, safe_int
from datetime import timedelta
from easysnmp import EasySNMPTimeoutError
from .base_intr import DevBase, SNMPBaseWorker, BasePort, DeviceImplementationError
from .base_intr import DevBase, SNMPBaseWorker, BasePort, DeviceImplementationError, ListOrError
class DLinkPort(BasePort):
@ -40,7 +40,7 @@ class DLinkDevice(DevBase, SNMPBaseWorker):
def reboot(self):
return self.get_item('.1.3.6.1.4.1.2021.8.1.101.1')
def get_ports(self):
def get_ports(self) -> ListOrError:
interfaces_count = safe_int(self.get_item('.1.3.6.1.2.1.2.1.0'))
nams = list(self.get_list('.1.3.6.1.4.1.171.10.134.2.1.1.100.2.1.3'))
stats = list(self.get_list('.1.3.6.1.2.1.2.2.1.7'))
@ -59,7 +59,7 @@ class DLinkDevice(DevBase, SNMPBaseWorker):
self))
return res
except IndexError:
raise DeviceImplementationError('Dlink port index error')
return DeviceImplementationError('Dlink port index error'), res
def get_device_name(self):
return self.get_item('.1.3.6.1.2.1.1.1.0')
@ -114,23 +114,28 @@ class OLTDevice(DevBase, SNMPBaseWorker):
def reboot(self):
pass
def get_ports(self):
def get_ports(self) -> ListOrError:
nms = self.get_list('.1.3.6.1.4.1.3320.101.10.1.1.79')
res = []
for nm in nms:
n = int(nm)
status = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.26.%d' % n)
signal = self.get_item('.1.3.6.1.4.1.3320.101.10.5.1.5.%d' % n)
onu = ONUdev(
num=n,
name=self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % n),
status=True if status == '3' else False,
mac=self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % n),
speed=0,
signal=int(signal) / 10 if signal != 'NOSUCHINSTANCE' else 0,
snmpWorker=self)
res.append(onu)
try:
for nm in nms:
n = int(nm)
status = self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.26.%d' % n)
signal = self.get_item('.1.3.6.1.4.1.3320.101.10.5.1.5.%d' % n)
onu = ONUdev(
num=n,
name=self.get_item('.1.3.6.1.2.1.2.2.1.2.%d' % n),
status=True if status == '3' else False,
mac=self.get_item('.1.3.6.1.4.1.3320.101.10.1.1.3.%d' % n),
speed=0,
signal=int(signal) / 10 if signal != 'NOSUCHINSTANCE' else 0,
snmpWorker=self)
res.append(onu)
except EasySNMPTimeoutError as e:
return EasySNMPTimeoutError(
"%s (%s)" % (gettext('wait for a reply from the SNMP Timeout'), e)
), res
return res
def get_device_name(self):
@ -166,8 +171,8 @@ class OnuDevice(DevBase, SNMPBaseWorker):
def reboot(self):
pass
def get_ports(self):
pass
def get_ports(self) -> ListOrError:
return []
def get_device_name(self):
pass
@ -239,7 +244,7 @@ class EltexSwitch(DLinkDevice):
def description():
return _('Eltex switch')
def get_ports(self):
def get_ports(self) -> ListOrError:
#nams = self.get_list('.1.3.6.1.4.1.171.10.134.2.1.1.100.2.1.3')
stats = list(self.get_list('.1.3.6.1.2.1.2.2.1.7'))
oper_stats = list(self.get_list('.1.3.6.1.2.1.2.2.1.8'))

15
devapp/views.py

@ -11,7 +11,7 @@ from django.contrib import messages
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _, gettext
from easysnmp import EasySNMPTimeoutError, EasySNMPError
from django.views.generic import ListView, DetailView
from django.views.generic import DetailView
from devapp.base_intr import DeviceImplementationError
from mydefs import res_success, res_error, only_admins, ping, ip_addr_regex
@ -30,13 +30,13 @@ from .forms import DeviceForm, PortForm
from mydefs import safe_int
class BaseDeviceListView(ListView):
class BaseDeviceListView(global_base_views.BaseListWithFiltering):
http_method_names = ['get']
paginate_by = getattr(settings, 'PAGINATION_ITEMS_PER_PAGE', 10)
@method_decorator([login_required, only_admins], name='dispatch')
class DevicesListView(BaseDeviceListView, global_base_views.OrderingMixin):
class DevicesListView(global_base_views.OrderingMixin, BaseDeviceListView):
context_object_name = 'devices'
template_name = 'devapp/devices.html'
@ -63,7 +63,7 @@ class DevicesListView(BaseDeviceListView, global_base_views.OrderingMixin):
@method_decorator([login_required, only_admins], name='dispatch')
class DevicesWithoutGroupsListView(BaseDeviceListView, global_base_views.OrderingMixin):
class DevicesWithoutGroupsListView(global_base_views.OrderingMixin, BaseDeviceListView):
context_object_name = 'devices'
template_name = 'devapp/devices_null_group.html'
queryset = Device.objects.filter(group=None).only('comment', 'devtype', 'pk', 'ip_address')
@ -366,6 +366,9 @@ def devview(request, device_id):
if dev.man_passw:
manager = dev.get_manager_object()
ports = manager.get_ports()
if isinstance(ports[0], Exception):
messages.error(request, ports[0])
ports = ports[1]
template_name = manager.get_template_name()
else:
messages.warning(request, _('Not Set snmp device password'))
@ -377,8 +380,8 @@ def devview(request, device_id):
'dev_accs': Abon.objects.filter(device=dev),
'dev_manager': manager
})
except EasySNMPError:
messages.error(request, _('SNMP error on device'))
except EasySNMPError as e:
messages.error(request, "%s: %s" % (gettext('SNMP error on device'), e))
except (DeviceDBException, DeviceImplementationError) as e:
messages.error(request, e)
return render(request, 'devapp/custom_dev_page/' + template_name, {

Loading…
Cancel
Save