Browse Source

Make telnet script for ZTE-C320. And maked snmp field validate in dynamic device types

devel
bashmak 8 years ago
parent
commit
d5eeeec38f
  1. 11
      agent/mod_mikrotik.py
  2. 15
      devapp/base_intr.py
  3. 24
      devapp/dev_types.py
  4. 18
      devapp/forms.py
  5. 433
      devapp/locale/ru/LC_MESSAGES/django.po
  6. 9
      devapp/models.py
  7. 2
      devapp/templates/devapp/devices.html
  8. 15
      djing/lib/__init__.py
  9. 4
      djing/lib/tln/__init__.py
  10. 266
      djing/lib/tln/tln.py

11
agent/mod_mikrotik.py

@ -6,7 +6,7 @@ from abc import ABCMeta
from hashlib import md5 from hashlib import md5
from typing import Iterable, Optional, Tuple from typing import Iterable, Optional, Tuple
from .core import BaseTransmitter, NasFailedResult, NasNetworkError from .core import BaseTransmitter, NasFailedResult, NasNetworkError
from djing.lib import singleton
from djing.lib import Singleton
from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff
from . import settings as local_settings from . import settings as local_settings
from django.conf import settings from django.conf import settings
@ -18,8 +18,7 @@ LIST_USERS_ALLOWED = 'DjingUsersAllowed'
LIST_USERS_BLOCKED = 'DjingUsersBlocked' LIST_USERS_BLOCKED = 'DjingUsersBlocked'
@singleton
class ApiRos:
class ApiRos(metaclass=Singleton):
"""Routeros api""" """Routeros api"""
sk = None sk = None
is_login = False is_login = False
@ -223,8 +222,8 @@ class TransmitterManager(BaseTransmitter, metaclass=ABCMeta):
speeds = info['=max-limit'].split('/') speeds = info['=max-limit'].split('/')
t = TariffStruct( t = TariffStruct(
speedIn=parse_speed(speeds[1]),
speedOut=parse_speed(speeds[0])
speed_in=parse_speed(speeds[1]),
speed_out=parse_speed(speeds[0])
) )
try: try:
a = AbonStruct( a = AbonStruct(
@ -480,7 +479,7 @@ class MikrotikTransmitter(QueueManager, IpAddressListManager):
interface = r[0]['=interface'] interface = r[0]['=interface']
r = self._exec_cmd(( r = self._exec_cmd((
'/ping', '=address=%s' % host, '=arp-ping=yes', '=interval=100ms', '=count=%d' % count, '/ping', '=address=%s' % host, '=arp-ping=yes', '=interval=100ms', '=count=%d' % count,
'=interface=%s' % interface
'=interface=%s' % interface
)) ))
received, sent = int(r[-2:][0]['=received']), int(r[-2:][0]['=sent']) received, sent = int(r[-2:][0]['=received']), int(r[-2:][0]['=sent'])
return received, sent return received, sent

15
devapp/base_intr.py

@ -1,10 +1,10 @@
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from datetime import timedelta from datetime import timedelta
from django.utils.translation import gettext
from typing import Union, Iterable, AnyStr, Generator, Optional from typing import Union, Iterable, AnyStr, Generator, Optional
from easysnmp import Session from easysnmp import Session
from django.utils.translation import gettext
ListOrError = Union[ ListOrError = Union[
Iterable, Iterable,
Union[Exception, Iterable] Union[Exception, Iterable]
@ -15,7 +15,7 @@ class DeviceImplementationError(Exception):
pass pass
class DevBase(object, metaclass=ABCMeta):
class DevBase(object):
def __init__(self, dev_instance=None): def __init__(self, dev_instance=None):
self.db_instance = dev_instance self.db_instance = dev_instance
@ -53,6 +53,15 @@ class DevBase(object, metaclass=ABCMeta):
def is_use_device_port() -> bool: def is_use_device_port() -> bool:
"""True if used device port while opt82 authorization""" """True if used device port while opt82 authorization"""
@abstractmethod
def validate_extra_snmp_info(self, v: str) -> None:
"""
Validate extra snmp field for each device.
If validation failed then raise en exception from djing.lib.tln.ValidationError
with description of error.
:param v: String value for validate
"""
class BasePort(object, metaclass=ABCMeta): class BasePort(object, metaclass=ABCMeta):
def __init__(self, num, name, status, mac, speed): def __init__(self, num, name, status, mac, speed):

24
devapp/dev_types.py

@ -4,6 +4,7 @@ from easysnmp import EasySNMPTimeoutError
from django.utils.translation import gettext_lazy as _, gettext from django.utils.translation import gettext_lazy as _, gettext
from djing.lib import RuTimedelta, safe_int from djing.lib import RuTimedelta, safe_int
from djing.lib.tln.tln import ValidationError as TlnValidationError
from .base_intr import DevBase, SNMPBaseWorker, BasePort, DeviceImplementationError, ListOrError from .base_intr import DevBase, SNMPBaseWorker, BasePort, DeviceImplementationError, ListOrError
@ -77,6 +78,10 @@ class DLinkDevice(DevBase, SNMPBaseWorker):
def is_use_device_port(): def is_use_device_port():
return True return True
def validate_extra_snmp_info(self, v: str) -> None:
# Dlink has no require snmp info
pass
class ONUdev(BasePort): class ONUdev(BasePort):
def __init__(self, num, name, status, mac, speed, signal, snmp_worker): def __init__(self, num, name, status, mac, speed, signal, snmp_worker):
@ -150,6 +155,10 @@ class OLTDevice(DevBase, SNMPBaseWorker):
def is_use_device_port(): def is_use_device_port():
return False return False
def validate_extra_snmp_info(self, v: str) -> None:
# Olt has no require snmp info
pass
class OnuDevice(DevBase, SNMPBaseWorker): class OnuDevice(DevBase, SNMPBaseWorker):
def __init__(self, dev_instance): def __init__(self, dev_instance):
@ -216,6 +225,13 @@ class OnuDevice(DevBase, SNMPBaseWorker):
except EasySNMPTimeoutError as e: except EasySNMPTimeoutError as e:
return {'err': "%s: %s" % (_('ONU not connected'), e)} return {'err': "%s: %s" % (_('ONU not connected'), e)}
def validate_extra_snmp_info(self, v: str) -> None:
# DBCOM Onu have en integer snmp port
try:
int(v)
except ValueError:
raise TlnValidationError(_('Onu snmp field must be en integer'))
class EltexPort(BasePort): class EltexPort(BasePort):
def __init__(self, snmp_worker, *args, **kwargs): def __init__(self, snmp_worker, *args, **kwargs):
@ -360,3 +376,11 @@ class ZteOnuDevice(OnuDevice):
def get_template_name(self): def get_template_name(self):
return 'onu_for_zte.html' return 'onu_for_zte.html'
def validate_extra_snmp_info(self, v: str) -> None:
# for example 268501760.5
try:
fiber_num, onu_port = v.split('.')
int(fiber_num), int(onu_port)
except ValueError:
raise TlnValidationError(_('Zte onu snmp field must be two dot separated integers'))

18
devapp/forms.py

@ -1,7 +1,9 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.db import IntegrityError from django.db import IntegrityError
from djing.lib.tln.tln import ValidationError as TlnValidationError
from . import models from . import models
from djing import MAC_ADDR_REGEX, IP_ADDR_REGEX from djing import MAC_ADDR_REGEX, IP_ADDR_REGEX
@ -15,9 +17,23 @@ class DeviceForm(forms.ModelForm):
'unique': _('Device with that mac is already exist') 'unique': _('Device with that mac is already exist')
}) })
def clean_snmp_extra(self):
snmp_extra = self.cleaned_data.get('snmp_extra')
if snmp_extra is None:
return
device = self.instance
manager = device.get_manager_object()
try:
manager.validate_extra_snmp_info(snmp_extra)
except TlnValidationError as e:
raise ValidationError(
e, code='invalid'
)
return snmp_extra
class Meta: class Meta:
model = models.Device model = models.Device
exclude = ['map_dot', 'status']
exclude = ('map_dot', 'status')
widgets = { widgets = {
'ip_address': forms.TextInput(attrs={ 'ip_address': forms.TextInput(attrs={
'pattern': IP_ADDR_REGEX, 'pattern': IP_ADDR_REGEX,

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

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-24 23:27+0300\n"
"POT-Creation-Date: 2018-06-02 16:39+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Dmitry Novikov nerosketch@gmail.com\n" "Last-Translator: Dmitry Novikov nerosketch@gmail.com\n"
"Language: ru\n" "Language: ru\n"
@ -18,377 +18,456 @@ msgstr ""
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" "%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n" "%100>=11 && n%100<=14)? 2 : 3);\n"
#: devapp/base_intr.py:82
#: base_intr.py:92
msgid "Ip address is required" msgid "Ip address is required"
msgstr "Ip адрес необходим" msgstr "Ip адрес необходим"
#: devapp/dev_types.py:35
#: dev_types.py:37
msgid "DLink switch" msgid "DLink switch"
msgstr "Свич D'Link" msgstr "Свич D'Link"
#: devapp/dev_types.py:54
#: dev_types.py:56
msgid "does not fetch the mac" msgid "does not fetch the mac"
msgstr "не нашёл мак" msgstr "не нашёл мак"
#: devapp/dev_types.py:106
#: dev_types.py:112
msgid "PON OLT" msgid "PON OLT"
msgstr "" msgstr ""
#: devapp/dev_types.py:131 devapp/views.py:268 devapp/views.py:413
#: dev_types.py:136 views.py:275 views.py:433
msgid "wait for a reply from the SNMP Timeout" msgid "wait for a reply from the SNMP Timeout"
msgstr "Время ожидания ответа от SNMP истекло" msgstr "Время ожидания ответа от SNMP истекло"
#: devapp/dev_types.py:171
#: dev_types.py:176
msgid "Ip address or parent device with ip address required for ONU device"
msgstr ""
"Необходим ip адрес. Или родительское устройство с назначенным ip адресом "
"необходимо."
#: dev_types.py:182
msgid "PON ONU" msgid "PON ONU"
msgstr "" msgstr ""
#: devapp/dev_types.py:216
#: dev_types.py:227
msgid "ONU not connected" msgid "ONU not connected"
msgstr "ONU не в сети" msgstr "ONU не в сети"
#: devapp/dev_types.py:242
#: dev_types.py:234
msgid "Onu snmp field must be en integer"
msgstr "Поле для snmp информации об ONU должно быть числом"
#: dev_types.py:260
msgid "Eltex switch" msgid "Eltex switch"
msgstr "Элтекс свич" msgstr "Элтекс свич"
#: devapp/forms.py:14
#: dev_types.py:305
msgid "OLT ZTE C320"
msgstr ""
#: dev_types.py:354
msgid "ZTE PON ONU"
msgstr ""
#: dev_types.py:387
msgid "Zte onu snmp field must be two dot separated integers"
msgstr ""
"Поле snmp информации для ZTE ONU должно быть двумя целыми числами, "
"разделенными точкой"
#: forms.py:16
msgid "Mac address is required for fill" msgid "Mac address is required for fill"
msgstr "MAC-адрес необходим для заполнения" msgstr "MAC-адрес необходим для заполнения"
#: devapp/forms.py:15
#: forms.py:17
msgid "Device with that mac is already exist" msgid "Device with that mac is already exist"
msgstr "Устройство с этим мак-адресом уже есть" msgstr "Устройство с этим мак-адресом уже есть"
#: devapp/forms.py:48
#: forms.py:63
msgid "Port number on device must be unique" msgid "Port number on device must be unique"
msgstr "Номер порта на устройстве должен быть уникальным" msgstr "Номер порта на устройстве должен быть уникальным"
#: devapp/models.py:21 devapp/templates/devapp/custom_dev_page/onu.html:18
#: devapp/templates/devapp/devices.html:22
#: devapp/templates/devapp/devices_null_group.html:20
#: models.py:25 templates/devapp/custom_dev_page/onu.html:18
#: templates/devapp/custom_dev_page/onu_for_zte.html:18
#: templates/devapp/devices.html:22 templates/devapp/devices_null_group.html:20
msgid "Ip address" msgid "Ip address"
msgstr "Ip адрес" msgstr "Ip адрес"
#: devapp/models.py:22 devapp/templates/devapp/devices.html:32
#: models.py:26 templates/devapp/devices.html:32
msgid "Mac address" msgid "Mac address"
msgstr "Мак адрес" msgstr "Мак адрес"
#: devapp/models.py:23 devapp/templates/devapp/devices.html:28
#: devapp/templates/devapp/devices_null_group.html:26
#: models.py:27 templates/devapp/devices.html:28
#: templates/devapp/devices_null_group.html:26
msgid "Comment" msgid "Comment"
msgstr "Комментарий" msgstr "Комментарий"
#: devapp/models.py:30 devapp/templates/devapp/devices.html:36
#: devapp/templates/devapp/devices_null_group.html:32
#: models.py:36 templates/devapp/devices.html:36
#: templates/devapp/devices_null_group.html:32
msgid "Device type" msgid "Device type"
msgstr "Тип устройства" msgstr "Тип устройства"
#: devapp/models.py:32
#: models.py:38
msgid "SNMP password" msgid "SNMP password"
msgstr "Пароль SNMP" msgstr "Пароль SNMP"
#: devapp/models.py:33
#: models.py:39
msgid "Device group" msgid "Device group"
msgstr "Группа устройства" msgstr "Группа устройства"
#: devapp/models.py:34 devapp/templates/devapp/add_dev.html:46
#: devapp/templates/devapp/custom_dev_page/onu.html:34
#: devapp/templates/devapp/custom_dev_page/ports.html:59
#: devapp/templates/devapp/dev.html:33
#: devapp/templates/devapp/fix_dev_group.html:42
#: models.py:40 templates/devapp/add_dev.html:46
#: templates/devapp/custom_dev_page/onu.html:34
#: templates/devapp/custom_dev_page/onu_for_zte.html:34
#: templates/devapp/custom_dev_page/ports.html:59 templates/devapp/dev.html:33
#: templates/devapp/fix_dev_group.html:42
msgid "Parent device" msgid "Parent device"
msgstr "Родительское устройство" msgstr "Родительское устройство"
#: devapp/models.py:37
msgid "SNMP Number"
msgstr "SNMP Ном."
#: models.py:43
msgid "SNMP extra info"
msgstr "Доп. инфо для snmp"
#: devapp/models.py:40
#: models.py:46
msgid "Undefined" msgid "Undefined"
msgstr "Не определено" msgstr "Не определено"
#: devapp/models.py:41
#: models.py:47
msgid "Up" msgid "Up"
msgstr "В сети" msgstr "В сети"
#: devapp/models.py:42
#: models.py:48
msgid "Unreachable" msgid "Unreachable"
msgstr "Не доступно" msgstr "Не доступно"
#: devapp/models.py:43
#: models.py:49
msgid "Down" msgid "Down"
msgstr "Не в сети" msgstr "Не в сети"
#: devapp/models.py:45
#: models.py:51
msgid "Status" msgid "Status"
msgstr "Состояние" msgstr "Состояние"
#: devapp/models.py:47
#: models.py:53
msgid "Send notify when monitoring state changed" msgid "Send notify when monitoring state changed"
msgstr "Отправлять уведомления при событиях мониторинга" msgstr "Отправлять уведомления при событиях мониторинга"
#: devapp/models.py:52
#: models.py:58
msgid "Can view device" msgid "Can view device"
msgstr "Может видеть устройство" msgstr "Может видеть устройство"
#: devapp/models.py:54 devapp/models.py:126
#: models.py:60 models.py:108
msgid "Device" msgid "Device"
msgstr "Устройство" msgstr "Устройство"
#: devapp/models.py:55 devapp/templates/devapp/devices.html:14
#: devapp/templates/devapp/devices_null_group.html:8
#: models.py:61 templates/devapp/devices.html:14
#: templates/devapp/devices_null_group.html:8
msgid "Devices" msgid "Devices"
msgstr "Устройства" msgstr "Устройства"
#: devapp/models.py:127 devapp/templates/devapp/manage_ports/list.html:11
#: models.py:96 views.py:175 views.py:237
msgid "Device does not have a group, please fix that"
msgstr "У устройства нет группы, пожалуйста, исправьте это"
#: models.py:109 templates/devapp/manage_ports/list.html:11
msgid "Number" msgid "Number"
msgstr "Номер" msgstr "Номер"
#: devapp/models.py:128 devapp/templates/devapp/custom_dev_page/onu.html:20
#: devapp/templates/devapp/custom_dev_page/ports.html:88
#: devapp/templates/devapp/manage_ports/add_ports.html:33
#: devapp/templates/devapp/manage_ports/list.html:12
#: models.py:110 templates/devapp/custom_dev_page/onu.html:20
#: templates/devapp/custom_dev_page/onu_for_zte.html:20
#: templates/devapp/custom_dev_page/ports.html:88
#: templates/devapp/manage_ports/add_ports.html:33
#: templates/devapp/manage_ports/list.html:12
msgid "Description" msgid "Description"
msgstr "Описание" msgstr "Описание"
#: devapp/models.py:137
#: models.py:119
msgid "Can toggle ports" msgid "Can toggle ports"
msgstr "Может переключать порты" msgstr "Может переключать порты"
#: devapp/models.py:139 devapp/templates/devapp/custom_dev_page/ports.html:110
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:24
#: models.py:121 templates/devapp/custom_dev_page/ports.html:110
#: templates/devapp/manage_ports/fix_abon_device.html:24
msgid "Port" msgid "Port"
msgstr "Порт" msgstr "Порт"
#: devapp/models.py:140
#: models.py:122
msgid "Ports" msgid "Ports"
msgstr "Порты" msgstr "Порты"
#: devapp/templates/devapp/add_dev.html:8
#: devapp/templates/devapp/devices.html:8
#: devapp/templates/devapp/devices_null_group.html:7
#: devapp/templates/devapp/fix_dev_group.html:9
#: devapp/templates/devapp/group_list.html:7
#: devapp/templates/devapp/manage_ports/add_ports.html:7
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:7
#: templates/devapp/add_dev.html:8
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:7
#: templates/devapp/devices.html:8 templates/devapp/devices_null_group.html:7
#: templates/devapp/fix_dev_group.html:9 templates/devapp/group_list.html:7
#: templates/devapp/manage_ports/add_ports.html:7
#: templates/devapp/manage_ports/fix_abon_device.html:7
msgid "Groups" msgid "Groups"
msgstr "Группы" msgstr "Группы"
#: devapp/templates/devapp/add_dev.html:10
#: templates/devapp/add_dev.html:10
msgid "Add new device" msgid "Add new device"
msgstr "Добавить устройство" msgstr "Добавить устройство"
#: devapp/templates/devapp/add_dev.html:16
#: devapp/templates/devapp/custom_dev_page/ports.html:68
#: devapp/templates/devapp/devices.html:63
#: devapp/templates/devapp/manage_ports/add_ports.html:16
#: templates/devapp/add_dev.html:16
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:12
#: templates/devapp/custom_dev_page/ports.html:68
#: templates/devapp/devices.html:63
#: templates/devapp/manage_ports/add_ports.html:16
msgid "Not assigned" msgid "Not assigned"
msgstr "&lt;Не назначено&gt;" msgstr "&lt;Не назначено&gt;"
#: devapp/templates/devapp/add_dev.html:21 devapp/templates/devapp/dev.html:8
#: templates/devapp/add_dev.html:21 templates/devapp/dev.html:8
msgid "Device info" msgid "Device info"
msgstr "Инфа о железке" msgstr "Инфа о железке"
#: devapp/templates/devapp/add_dev.html:60 devapp/templates/devapp/dev.html:43
#: devapp/templates/devapp/dev.html:47
#: devapp/templates/devapp/fix_dev_group.html:51
#: devapp/templates/devapp/fix_dev_group.html:55
#: templates/devapp/add_dev.html:60 templates/devapp/dev.html:43
#: templates/devapp/dev.html:47 templates/devapp/fix_dev_group.html:51
#: templates/devapp/fix_dev_group.html:55
msgid "Find the device" msgid "Find the device"
msgstr "Найти устройство" msgstr "Найти устройство"
#: devapp/templates/devapp/add_dev.html:72 devapp/templates/devapp/dev.html:61
#: devapp/templates/devapp/fix_dev_group.html:64
#: devapp/templates/devapp/manage_ports/add_ports.html:75
#: devapp/templates/devapp/manage_ports/add_ports.html:79
#: devapp/templates/devapp/manage_ports/modal_add_edit_port.html:21
#: templates/devapp/add_dev.html:72 templates/devapp/dev.html:61
#: templates/devapp/fix_dev_group.html:64
#: templates/devapp/manage_ports/add_ports.html:75
#: templates/devapp/manage_ports/add_ports.html:79
#: templates/devapp/manage_ports/modal_add_edit_port.html:21
msgid "Save" msgid "Save"
msgstr "Сохранить" msgstr "Сохранить"
#: devapp/templates/devapp/add_dev.html:75 devapp/templates/devapp/dev.html:73
#: devapp/templates/devapp/fix_dev_group.html:67
#: templates/devapp/add_dev.html:75 templates/devapp/dev.html:73
#: templates/devapp/fix_dev_group.html:67
msgid "Reset" msgid "Reset"
msgstr "Сбросить" msgstr "Сбросить"
#: devapp/templates/devapp/custom_dev_page/olt.html:10
#: devapp/templates/devapp/custom_dev_page/onu.html:12
#: devapp/templates/devapp/custom_dev_page/ports.html:12
#: templates/devapp/custom_dev_page/olt.html:10
#: templates/devapp/custom_dev_page/olt_ztec320.html:11
#: templates/devapp/custom_dev_page/onu.html:12
#: templates/devapp/custom_dev_page/onu_for_zte.html:12
#: templates/devapp/custom_dev_page/ports.html:12
msgid "Uptime" msgid "Uptime"
msgstr "Без перезагрузки" msgstr "Без перезагрузки"
#: devapp/templates/devapp/custom_dev_page/olt.html:17
#: templates/devapp/custom_dev_page/olt.html:17
msgid "SNMP Num" msgid "SNMP Num"
msgstr "SNMP Ном." msgstr "SNMP Ном."
#: devapp/templates/devapp/custom_dev_page/olt.html:18
#: templates/devapp/custom_dev_page/olt.html:18
msgid "Name" msgid "Name"
msgstr "Имя" msgstr "Имя"
#: devapp/templates/devapp/custom_dev_page/olt.html:19
#: devapp/templates/devapp/custom_dev_page/onu.html:19
#: templates/devapp/custom_dev_page/olt.html:19
#: templates/devapp/custom_dev_page/onu.html:19
#: templates/devapp/custom_dev_page/onu_for_zte.html:19
msgid "Mac" msgid "Mac"
msgstr "Мак" msgstr "Мак"
#: devapp/templates/devapp/custom_dev_page/olt.html:20
#: devapp/templates/devapp/custom_dev_page/onu.html:73
#: templates/devapp/custom_dev_page/olt.html:20
#: templates/devapp/custom_dev_page/onu.html:74
#: templates/devapp/custom_dev_page/onu_for_zte.html:77
msgid "Signal" msgid "Signal"
msgstr "Ур. сигнала" msgstr "Ур. сигнала"
#: devapp/templates/devapp/custom_dev_page/olt.html:38
#: templates/devapp/custom_dev_page/olt.html:38
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:45
msgid "Create device" msgid "Create device"
msgstr "Создать устройство" msgstr "Создать устройство"
#: devapp/templates/devapp/custom_dev_page/olt.html:45
#: devapp/templates/devapp/manage_ports/list.html:48
#: templates/devapp/custom_dev_page/olt.html:45
#: templates/devapp/manage_ports/list.html:48
msgid "Ports not found" msgid "Ports not found"
msgstr "Порты не найдены" msgstr "Порты не найдены"
#: devapp/templates/devapp/custom_dev_page/onu.html:10
#: devapp/templates/devapp/custom_dev_page/ports.html:10
#: templates/devapp/custom_dev_page/olt_ztec320.html:31
#: templates/devapp/custom_dev_page/ports.html:54
msgid "We have not received info, please check options :("
msgstr "Инфа не получена, проверьте настройки :("
#: templates/devapp/custom_dev_page/olt_ztec320.html:36
msgid "Long description"
msgstr "Длинное описание"
#: templates/devapp/custom_dev_page/olt_ztec320.html:37
msgid "Hostname"
msgstr "Имя хоста"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:15
msgid "OLT Scan"
msgstr "Скан OLT"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:27
msgid "Onu type"
msgstr "Тип ONU"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:28
msgid "Onu port"
msgstr "Порт ONU"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:29
msgid "Onu signal"
msgstr "Сигнала ONU"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:30
msgid "Serial"
msgstr "Серийный номер"
#: templates/devapp/custom_dev_page/olt_ztec320_ports.html:52
msgid "ONU not found"
msgstr "ONU не найдена"
#: templates/devapp/custom_dev_page/onu.html:10
#: templates/devapp/custom_dev_page/onu_for_zte.html:10
#: templates/devapp/custom_dev_page/ports.html:10
msgid "Title of the type of switch" msgid "Title of the type of switch"
msgstr "Название типа свича" msgstr "Название типа свича"
#: devapp/templates/devapp/custom_dev_page/onu.html:22
#: templates/devapp/custom_dev_page/onu.html:22
#: templates/devapp/custom_dev_page/onu_for_zte.html:22
msgid "Attached user" msgid "Attached user"
msgstr "Прикрепленный абонент" msgstr "Прикрепленный абонент"
#: devapp/templates/devapp/custom_dev_page/onu.html:47
#: templates/devapp/custom_dev_page/onu.html:48
#: templates/devapp/custom_dev_page/onu_for_zte.html:50
msgid "ONU Status" msgid "ONU Status"
msgstr "Состояние ONU" msgstr "Состояние ONU"
#: devapp/templates/devapp/custom_dev_page/onu.html:57
#: templates/devapp/custom_dev_page/onu.html:58
#: templates/devapp/custom_dev_page/onu_for_zte.html:60
msgid "ONU error" msgid "ONU error"
msgstr "ONU ошибка" msgstr "ONU ошибка"
#: devapp/templates/devapp/custom_dev_page/onu.html:71
#: templates/devapp/custom_dev_page/onu.html:72
#: templates/devapp/custom_dev_page/onu_for_zte.html:75
msgid "Name on OLT" msgid "Name on OLT"
msgstr "Имя на OLT" msgstr "Имя на OLT"
#: devapp/templates/devapp/custom_dev_page/onu.html:72
#: templates/devapp/custom_dev_page/onu.html:73
#: templates/devapp/custom_dev_page/onu_for_zte.html:76
msgid "Distance(m)" msgid "Distance(m)"
msgstr "Расстояние (м)" msgstr "Расстояние (м)"
#: devapp/templates/devapp/custom_dev_page/onu.html:77
#: devapp/templates/devapp/custom_dev_page/onu.html:85
#: templates/devapp/custom_dev_page/onu.html:78
#: templates/devapp/custom_dev_page/onu.html:86
msgid "Mac on OLT" msgid "Mac on OLT"
msgstr "MAC адрес на OLT" msgstr "MAC адрес на OLT"
#: devapp/templates/devapp/custom_dev_page/onu.html:78
#: templates/devapp/custom_dev_page/onu.html:79
msgid "Mac-addresses does not match" msgid "Mac-addresses does not match"
msgstr "MAC адреса не совпадают" msgstr "MAC адреса не совпадают"
#: devapp/templates/devapp/custom_dev_page/onu.html:79
#: devapp/templates/devapp/custom_dev_page/onu.html:81
#: templates/devapp/custom_dev_page/onu.html:80
#: templates/devapp/custom_dev_page/onu.html:82
msgid "Fix it" msgid "Fix it"
msgstr "Исправить" msgstr "Исправить"
#: devapp/templates/devapp/custom_dev_page/onu.html:92
#: templates/devapp/custom_dev_page/onu.html:93
#: templates/devapp/custom_dev_page/onu_for_zte.html:83
msgid "Info does not fetch" msgid "Info does not fetch"
msgstr "Информация не получена" msgstr "Информация не получена"
#: devapp/templates/devapp/custom_dev_page/ports.html:44
#: templates/devapp/custom_dev_page/ports.html:44
msgid "Disable port" msgid "Disable port"
msgstr "Выключить порт" msgstr "Выключить порт"
#: devapp/templates/devapp/custom_dev_page/ports.html:48
#: templates/devapp/custom_dev_page/ports.html:48
msgid "Enable port" msgid "Enable port"
msgstr "Включить порт" msgstr "Включить порт"
#: devapp/templates/devapp/custom_dev_page/ports.html:54
msgid "We have not received info, please check options :("
msgstr "Инфа не получена, проверьте настройки :("
#: devapp/templates/devapp/custom_dev_page/ports.html:80
#: templates/devapp/custom_dev_page/ports.html:80
msgid "Device log" msgid "Device log"
msgstr "Лог устройства" msgstr "Лог устройства"
#: devapp/templates/devapp/custom_dev_page/ports.html:87
#: templates/devapp/custom_dev_page/ports.html:87
msgid "Level" msgid "Level"
msgstr "Уровень" msgstr "Уровень"
#: devapp/templates/devapp/custom_dev_page/ports.html:89
#: templates/devapp/custom_dev_page/ports.html:89
msgid "Date" msgid "Date"
msgstr "Дата" msgstr "Дата"
#: devapp/templates/devapp/custom_dev_page/ports.html:104
#: templates/devapp/custom_dev_page/ports.html:104
msgid "Ports comment" msgid "Ports comment"
msgstr "Комментарии портов" msgstr "Комментарии портов"
#: devapp/templates/devapp/custom_dev_page/ports.html:111
#: templates/devapp/custom_dev_page/ports.html:111
msgid "Title" msgid "Title"
msgstr "Название" msgstr "Название"
#: devapp/templates/devapp/custom_dev_page/ports.html:122
#: templates/devapp/custom_dev_page/ports.html:122
msgid "We have not received info for ports" msgid "We have not received info for ports"
msgstr "Инфа о портах не получена" msgstr "Инфа о портах не получена"
#: devapp/templates/devapp/dev.html:65 devapp/templates/devapp/dev.html:69
#: devapp/templates/devapp/manage_ports/add_ports.html:53
#: devapp/templates/devapp/manage_ports/add_ports.html:55
#: devapp/templates/devapp/manage_ports/list.html:35
#: devapp/templates/devapp/manage_ports/modal_del_port.html:14
#: templates/devapp/dev.html:65 templates/devapp/dev.html:69
#: templates/devapp/manage_ports/add_ports.html:53
#: templates/devapp/manage_ports/add_ports.html:55
#: templates/devapp/manage_ports/list.html:35
#: templates/devapp/manage_ports/modal_del_port.html:14
msgid "Delete" msgid "Delete"
msgstr "Удалить" msgstr "Удалить"
#: devapp/templates/devapp/dev.html:68
#: templates/devapp/dev.html:68
msgid "Permission denied" msgid "Permission denied"
msgstr "Доступ запрещён" msgstr "Доступ запрещён"
#: devapp/templates/devapp/devices.html:81
#: devapp/templates/devapp/devices_null_group.html:62
#: templates/devapp/device_confirm_delete.html:9
msgid "Remove device"
msgstr "Удалить устройство"
#: templates/devapp/device_confirm_delete.html:13
msgid "Are you sure you want to delete device?"
msgstr "Вы уверены что хотите удалить устройство?"
#: templates/devapp/devices.html:81 templates/devapp/devices_null_group.html:62
msgid "Devices does not found" msgid "Devices does not found"
msgstr "Нет созданных устройств" msgstr "Нет созданных устройств"
#: devapp/templates/devapp/devices.html:81
#: devapp/templates/devapp/devices.html:91
#: devapp/templates/devapp/devices_null_group.html:62
#: devapp/templates/devapp/devices_null_group.html:72
#: templates/devapp/devices.html:81 templates/devapp/devices.html:91
#: templates/devapp/devices_null_group.html:62
#: templates/devapp/devices_null_group.html:72
msgid "Create" msgid "Create"
msgstr "Cоздать" msgstr "Cоздать"
#: devapp/templates/devapp/devices_null_group.html:13
#: devapp/templates/devapp/group_list.html:32
#: templates/devapp/devices_null_group.html:13
#: templates/devapp/group_list.html:32
msgid "Devices without group" msgid "Devices without group"
msgstr "Устройства без группы" msgstr "Устройства без группы"
#: devapp/templates/devapp/fix_dev_group.html:17
#: templates/devapp/fix_dev_group.html:17
msgid "Fix device group" msgid "Fix device group"
msgstr "Поправить группу устройства" msgstr "Поправить группу устройства"
#: devapp/templates/devapp/group_list.html:14
#: templates/devapp/group_list.html:14
msgid "Group title" msgid "Group title"
msgstr "Название" msgstr "Название"
#: devapp/templates/devapp/group_list.html:24
#: templates/devapp/group_list.html:24
msgid "Groups was not found" msgid "Groups was not found"
msgstr "Эта группа не найдена" msgstr "Эта группа не найдена"
#: devapp/templates/devapp/group_list.html:35
#: templates/devapp/group_list.html:35
msgid "Export to nagios objects" msgid "Export to nagios objects"
msgstr "Экспортировать конфиг для nagios" msgstr "Экспортировать конфиг для nagios"
#: devapp/templates/devapp/manage_ports/add_ports.html:10
#: devapp/templates/devapp/manage_ports/list.html:58
#: templates/devapp/manage_ports/add_ports.html:10
#: templates/devapp/manage_ports/list.html:58
msgid "Add ports" msgid "Add ports"
msgstr "Добавить порты" msgstr "Добавить порты"
#: devapp/templates/devapp/manage_ports/add_ports.html:32
#: templates/devapp/manage_ports/add_ports.html:32
msgid "Mode" msgid "Mode"
msgstr "Режим" msgstr "Режим"
#: devapp/templates/devapp/manage_ports/add_ports.html:60
#: devapp/templates/devapp/manage_ports/list.html:57
#: templates/devapp/manage_ports/add_ports.html:60
#: templates/devapp/manage_ports/list.html:57
msgid "Add" msgid "Add"
msgstr "Добавить" msgstr "Добавить"
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:10
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:16
#: templates/devapp/manage_ports/fix_abon_device.html:10
#: templates/devapp/manage_ports/fix_abon_device.html:16
msgid "Fix subscriber ports conflict" msgid "Fix subscriber ports conflict"
msgstr "Исправить конфликт абонентов на порту" msgstr "Исправить конфликт абонентов на порту"
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:21
#: templates/devapp/manage_ports/fix_abon_device.html:21
msgid "Subscribers list on port" msgid "Subscribers list on port"
msgstr "Список абонентов на порту" msgstr "Список абонентов на порту"
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:25
#: templates/devapp/manage_ports/fix_abon_device.html:25
msgid "" msgid ""
"You may choose the subscriber who correctly attached to device port. When " "You may choose the subscriber who correctly attached to device port. When "
"you have found right subscriber, remove the port from the other person" "you have found right subscriber, remove the port from the other person"
@ -397,15 +476,15 @@ msgstr ""
"найдёте нужного абонента удалите этот порт у другого абонента чтоб исправить " "найдёте нужного абонента удалите этот порт у другого абонента чтоб исправить "
"конфликт" "конфликт"
#: devapp/templates/devapp/manage_ports/fix_abon_device.html:31
#: templates/devapp/manage_ports/fix_abon_device.html:31
msgid "Abons not found" msgid "Abons not found"
msgstr "Абоненты не найдены" msgstr "Абоненты не найдены"
#: devapp/templates/devapp/manage_ports/list.html:13
#: templates/devapp/manage_ports/list.html:13
msgid "Count of subscribers" msgid "Count of subscribers"
msgstr "Сколько абонов" msgstr "Сколько абонов"
#: devapp/templates/devapp/manage_ports/list.html:26
#: templates/devapp/manage_ports/list.html:26
#, python-format #, python-format
msgid "" msgid ""
"Port should not have more than one subscriber, <a href='%(furl)s'>fix that</" "Port should not have more than one subscriber, <a href='%(furl)s'>fix that</"
@ -414,113 +493,105 @@ msgstr ""
"Порт не должен иметь больше одного назначенного абонента, <a " "Порт не должен иметь больше одного назначенного абонента, <a "
"href='%(furl)s'>исправить</a>" "href='%(furl)s'>исправить</a>"
#: devapp/templates/devapp/manage_ports/list.html:31
#: templates/devapp/manage_ports/list.html:31
msgid "Show subscriber on port" msgid "Show subscriber on port"
msgstr "Показать абонента на порту" msgstr "Показать абонента на порту"
#: devapp/templates/devapp/manage_ports/list.html:40
#: devapp/templates/devapp/manage_ports/modal_add_edit_port.html:14
#: templates/devapp/manage_ports/list.html:40
#: templates/devapp/manage_ports/modal_add_edit_port.html:14
msgid "Edit" msgid "Edit"
msgstr "Редактировать" msgstr "Редактировать"
#: devapp/templates/devapp/manage_ports/modal_del_port.html:7
#: templates/devapp/manage_ports/modal_del_port.html:7
msgid "Are you sure?" msgid "Are you sure?"
msgstr "Вы уверены?" msgstr "Вы уверены?"
#: devapp/templates/devapp/manage_ports/modal_del_port.html:11
#: templates/devapp/manage_ports/modal_del_port.html:11
msgid "Are you sure that you want to delete switch port from db?" msgid "Are you sure that you want to delete switch port from db?"
msgstr "Вы уверены что хотите удалить порт свича из бд?" msgstr "Вы уверены что хотите удалить порт свича из бд?"
#: devapp/templates/devapp/manage_ports/modal_show_subscriber_on_port.html:5
#: templates/devapp/manage_ports/modal_show_subscriber_on_port.html:5
msgid "Subscriber on port" msgid "Subscriber on port"
msgstr "Абонент на порту" msgstr "Абонент на порту"
#: devapp/views.py:80
msgid "Delete failed"
msgstr "Неизвестная ошибка при удалении :("
#: views.py:87
msgid "Device successfully deleted"
msgstr "Устройство успешно удалено"
#: devapp/views.py:109
#: views.py:115
msgid "You have redirected to existing device" msgid "You have redirected to existing device"
msgstr "Вы были переадресованы на существующее устройство" msgstr "Вы были переадресованы на существующее устройство"
#: devapp/views.py:112 devapp/views.py:361 devapp/views.py:457
#: views.py:118 views.py:368 views.py:481
msgid "Please attach group for device" msgid "Please attach group for device"
msgstr "Пожалуйста назначте устройству группу в настройках" msgstr "Пожалуйста назначте устройству группу в настройках"
#: devapp/views.py:121
#: views.py:127
msgid "Device info has been saved" msgid "Device info has been saved"
msgstr "Инфа о точке сохранена" msgstr "Инфа о точке сохранена"
#: devapp/views.py:124 devapp/views.py:307 devapp/views.py:336
#: devapp/views.py:459
#: views.py:130 views.py:314 views.py:343 views.py:483
msgid "Form is invalid, check fields and try again" msgid "Form is invalid, check fields and try again"
msgstr "Ошибка в данных, проверте их ещё раз" msgstr "Ошибка в данных, проверте их ещё раз"
#: devapp/views.py:127
#: views.py:133
#, python-format #, python-format
msgid "Duplicate user and port: %s" msgid "Duplicate user and port: %s"
msgstr "Пользователь с таким портом и устройством уже есть: %s" msgstr "Пользователь с таким портом и устройством уже есть: %s"
#: devapp/views.py:168 devapp/views.py:230
msgid "Device does not have a group, please fix that"
msgstr "У устройства нет группы, пожалуйста, исправьте это"
#: devapp/views.py:173 devapp/views.py:263 devapp/views.py:348
#: views.py:180 views.py:270 views.py:355
msgid "Device does not exist" msgid "Device does not exist"
msgstr "Устойство не найдено" msgstr "Устойство не найдено"
#: devapp/views.py:194
#: views.py:201
msgid "Subscribers on port does not exist" msgid "Subscribers on port does not exist"
msgstr "Абоненты на порту не найдены" msgstr "Абоненты на порту не найдены"
#: devapp/views.py:196
#: views.py:203
msgid "More than one subscriber on device port" msgid "More than one subscriber on device port"
msgstr "Больше одного абонента на порту устройства" msgstr "Больше одного абонента на порту устройства"
#: devapp/views.py:282
#: views.py:289
msgid "Port successfully removed" msgid "Port successfully removed"
msgstr "Порт успешно удалён" msgstr "Порт успешно удалён"
#: devapp/views.py:290 devapp/views.py:318
#: views.py:297 views.py:325
msgid "Port does not exist" msgid "Port does not exist"
msgstr "Порт не найден" msgstr "Порт не найден"
#: devapp/views.py:305 devapp/views.py:333
#: views.py:312 views.py:340
msgid "Port successfully saved" msgid "Port successfully saved"
msgstr "Порт успешно сохранён" msgstr "Порт успешно сохранён"
#: devapp/views.py:368 devapp/views.py:411
#: views.py:375 views.py:431
msgid "Dot was not pinged" msgid "Dot was not pinged"
msgstr "Эта точка не пингуется" msgstr "Эта точка не пингуется"
#: devapp/views.py:377 devapp/views.py:409
#: views.py:384 views.py:429
msgid "Not Set snmp device password" msgid "Not Set snmp device password"
msgstr "Не указан snmp пароль для устройства" msgstr "Не указан snmp пароль для устройства"
#: devapp/views.py:385
#: views.py:392
msgid "SNMP error on device" msgid "SNMP error on device"
msgstr "Ошибка SNMP на устройстве" msgstr "Ошибка SNMP на устройстве"
#: devapp/views.py:454
#: views.py:478
msgid "Device fixed" msgid "Device fixed"
msgstr "Устройство исправлено" msgstr "Устройство исправлено"
#: devapp/views.py:483
#: views.py:508
#, python-format #, python-format
msgid "Device with mac address %(mac)s does not exist" msgid "Device with mac address %(mac)s does not exist"
msgstr "Устройство мак адресом %(mac)s не найдено" msgstr "Устройство мак адресом %(mac)s не найдено"
#: devapp/views.py:491
#: views.py:516
msgid "Fixed" msgid "Fixed"
msgstr "Исправлено, обновите страницу" msgstr "Исправлено, обновите страницу"
#: devapp/views.py:494
#: views.py:519
msgid "Parent device not found" msgid "Parent device not found"
msgstr "Вышестоящее устройство не найдено" msgstr "Вышестоящее устройство не найдено"
#~ msgid "Plugin output"
#~ msgstr "Вывод мониторинга"
msgid "Device %(device_name)s is up" msgid "Device %(device_name)s is up"
msgstr "%(device_name)s в сети" msgstr "%(device_name)s в сети"
@ -532,15 +603,3 @@ msgstr "%(device_name)s недостижим"
msgid "Device %(device_name)s getting undefined status code" msgid "Device %(device_name)s getting undefined status code"
msgstr "Устройство %(device_name)s получило не определённый код состояния" msgstr "Устройство %(device_name)s получило не определённый код состояния"
msgid "Ip address or parent device with ip address required for ONU device"
msgstr "Необходим ip адрес. Или родительское устройство с назначенным ip адресом необходимо."
msgid "Are you sure you want to delete device?"
msgstr "Вы уверены что хотите удалить устройство?"
msgid "Remove device"
msgstr "Удалить устройство"
msgid "Device successfully deleted"
msgstr "Устройство успешно удалено"

9
devapp/models.py

@ -20,6 +20,8 @@ class DeviceMonitoringException(Exception):
class Device(models.Model): class Device(models.Model):
_cached_manager = None
ip_address = MyGenericIPAddressField(verbose_name=_('Ip address'), null=True, blank=True) ip_address = MyGenericIPAddressField(verbose_name=_('Ip address'), null=True, blank=True)
mac_addr = MACAddressField(verbose_name=_('Mac address'), null=True, blank=True, unique=True) mac_addr = MACAddressField(verbose_name=_('Mac address'), null=True, blank=True, unique=True)
comment = models.CharField(_('Comment'), max_length=256) comment = models.CharField(_('Comment'), max_length=256)
@ -71,11 +73,14 @@ class Device(models.Model):
res = klasses[0][1] res = klasses[0][1]
if issubclass(res, DevBase): if issubclass(res, DevBase):
return res return res
return
raise TypeError('one of types is not subclass of DevBase. '
'Or implementation of that device type is not found')
def get_manager_object(self) -> DevBase: def get_manager_object(self) -> DevBase:
man_klass = self.get_manager_klass() man_klass = self.get_manager_klass()
return man_klass(self)
if self._cached_manager is None:
self._cached_manager = man_klass(self)
return self._cached_manager
# Can attach device to subscriber in subscriber page # Can attach device to subscriber in subscriber page
def has_attachable_to_subscriber(self): def has_attachable_to_subscriber(self):

2
devapp/templates/devapp/devices.html

@ -30,7 +30,6 @@
{% 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-1"> <th class="col-md-1">
<a href="{% url 'devapp:devs' group.pk %}?{% url_replace request order_by='devtype' dir=dir|default:'down' %}"> <a href="{% url 'devapp:devs' group.pk %}?{% url_replace request order_by='devtype' dir=dir|default:'down' %}">
{% trans 'Device type' %} {% trans 'Device type' %}
@ -61,7 +60,6 @@
<td><a href="{% url 'devapp:view' grpid dev.pk %}">{{ dev.ip_address }}</a></td> <td><a href="{% url 'devapp:view' grpid 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>{{ 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 %}

15
djing/lib/__init__.py

@ -1,5 +1,6 @@
import socket import socket
import struct import struct
from abc import ABCMeta
from datetime import timedelta from datetime import timedelta
from collections import Iterator from collections import Iterator
from django.db import models from django.db import models
@ -125,12 +126,10 @@ class LogicError(Exception):
pass pass
def singleton(class_):
instances = {}
class Singleton(type):
_instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

4
djing/lib/tln/__init__.py

@ -0,0 +1,4 @@
from .tln import *
__all__ = ('TelnetApi', 'ValidationError', 'ZTEFiberNumberNotFound', 'ZTEFiberIsFull',
'OnuZteRegisterError', 'ZteOltConsoleError', 'register_onu_ZTE_F660')

266
djing/lib/tln/tln.py

@ -0,0 +1,266 @@
#!/usr/bin/env python3
import re
import struct
from telnetlib import Telnet
from time import sleep
from typing import Generator, Dict, Optional, Tuple
class ZteOltConsoleError(Exception):
pass
class OnuZteRegisterError(ZteOltConsoleError):
pass
class ZTEFiberIsFull(ZteOltConsoleError):
pass
class ZTEFiberNumberNotFound(ZteOltConsoleError):
pass
class ValidationError(ValueError):
pass
MAC_ADDR_REGEX = b'^([0-9A-Fa-f]{1,2}[:-]){5}([0-9A-Fa-f]{1,2})$'
IP_ADDR_REGEX = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.' \
'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
ONU_SN_REGEX = b'^ZTEG[A-F\d]{8}$'
class TelnetApi(Telnet):
config_level = []
def __init__(self, *args, **kwargs):
timeout = kwargs.get('timeout')
if timeout:
self._timeout = timeout
self._prompt_string = b'ZTE-C320-PKP#'
super().__init__(*args, **kwargs)
def write(self, buffer: bytes) -> None:
buffer = buffer + b'\n'
print('>>', buffer)
super().write(buffer)
def resize_screen(self, width: int, height: int):
naws_cmd = struct.pack('>BBBHHBB',
255, 250, 31, # IAC SB NAWS
width, height,
255, 240 # IAC SE
)
sock = self.get_socket()
sock.send(naws_cmd)
def enter(self, username: bytes, passw: bytes) -> None:
self.read_until(b'Username:')
self.write(username)
self.read_until(b'Password:')
self.write(passw)
def read_lines(self) -> Generator:
while True:
line = self.read_until(b'\r\n', timeout=self._timeout)
line = line.replace(b'\r\n', b'')
if self._prompt_string == line:
break
if line == b'':
continue
yield line
def command_to(self, cmd: bytes) -> Generator:
self.write(cmd)
return self.read_lines()
def set_prompt_string(self, prompt_string: bytes) -> None:
self.config_level.append(prompt_string)
self._prompt_string = prompt_string
def level_exit(self) -> Optional[Tuple]:
if len(self.config_level) < 2:
print('We are in root')
return
self.config_level.pop()
self.set_prompt_string(self.config_level[-1])
return tuple(self.command_to(b'exit'))
def __del__(self):
if self.sock:
self.write(b'exit')
super().__del__()
def parse_onu_name(onu_name: bytes, name_regexp=re.compile(b'[/:_]')) -> Dict[str, bytes]:
gpon_onu, stack_num, rack_num, fiber_num, onu_num = name_regexp.split(onu_name)
return {
'stack_num': stack_num,
'rack_num': rack_num,
'fiber_num': fiber_num,
'onu_num': onu_num
}
class OltZTERegister(TelnetApi):
def __init__(self, screen_size: Tuple[int, int], *args, **kwargs):
super().__init__(*args, **kwargs)
self.resize_screen(*screen_size)
def get_unregistered_onu(self, sn: bytes) -> Optional[Dict]:
lines = tuple(self.command_to(b'show gpon onu uncfg'))
if len(lines) > 3:
# devices available
# find onu by sn
line = tuple(ln for ln in lines if sn.lower() in ln.lower())
if len(line) > 0:
line = line[0]
onu_name, onu_sn, onu_state = line.split()
onu_numbers = parse_onu_name(onu_name)
onu_numbers.update({
'onu_name': onu_name,
'onu_sn': onu_sn,
'onu_state': onu_state
})
return onu_numbers
def get_last_registered_onu_number(self, stack_num: int, rack_num: int, fiber_num: int) -> int:
registered_lines = self.command_to(b'show run int gpon-olt_%d/%d/%d' % (
stack_num,
rack_num,
fiber_num
))
onu_type_regexp = re.compile(b'^\s{2}onu \d{1,3} type [-\w\d]{4,64} sn \w{4,64}$')
last_onu = 0
for rl in registered_lines:
if rl == b' --More--':
self.write(b' ')
if onu_type_regexp.match(rl):
_onu, num, _type, onu_type, _sn, onu_sn = rl.split()
last_onu = int(num)
return last_onu
def enter_to_config_mode(self) -> bool:
prompt = b'ZTE-C320-PKP(config)#'
self.set_prompt_string(prompt)
res = tuple(self.command_to(b'config terminal'))
if res[1].startswith(b'Enter configuration commands'):
# ok, we in the config mode
return True
return False
def go_to_olt_interface(self, stack_num: int, rack_num: int, fiber_num: int) -> Tuple:
self.set_prompt_string(b'ZTE-C320-PKP(config-if)#')
return tuple(self.command_to(b'interface gpon-olt_%d/%d/%d' % (
stack_num,
rack_num,
fiber_num
)))
def go_to_onu_interface(self, stack_num: int, rack_num: int, fiber_num: int, onu_port_num: int) -> Tuple:
self.set_prompt_string(b'ZTE-C320-PKP(config-if)#')
return tuple(self.command_to(b'interface gpon-onu_%d/%d/%d:%d' % (
stack_num,
rack_num,
fiber_num,
onu_port_num
)))
def apply_conf_to_onu(self, mac_addr: bytes, vlan_id: int) -> None:
tmpl = (
b'switchport vlan %d tag vport 1' % vlan_id,
b'port-location format flexible-syntax vport 1',
b'port-location sub-option remote-id enable vport 1',
b'port-location sub-option remote-id name %s vport 1' % mac_addr,
b'dhcp-option82 enable vport 1',
b'dhcp-option82 trust true replace vport 1',
b'ip dhcp snooping enable vport 1'
)
for conf_line in tmpl:
self.write(conf_line)
def register_onu_on_olt_fiber(self, onu_type: bytes, new_onu_num: int, onu_sn: bytes, line_profile: bytes,
remote_profile: bytes) -> Tuple:
# ok, we in interface
tpl = b'onu %d type %s sn %s' % (new_onu_num, onu_type, onu_sn)
r = tuple(self.command_to(tpl))
return tuple(self.command_to(b'onu %d profile line %s remote %s' % (
new_onu_num,
line_profile,
remote_profile
))) + r
def register_onu_ZTE_F660(olt_ip: str, onu_sn: bytes, login_passwd: Tuple[bytes, bytes], onu_mac: bytes):
onu_type = b'ZTE-F660'
line_profile = b'ZTE-F660-LINE'
remote_profile = b'ZTE-F660-ROUTER'
if not re.match(MAC_ADDR_REGEX, onu_mac):
raise ValidationError
if not re.match(IP_ADDR_REGEX, olt_ip):
raise ValidationError
if not re.match(ONU_SN_REGEX, onu_sn):
raise ValidationError
tn = OltZTERegister(host=olt_ip, timeout=2, screen_size=(120, 128))
tn.enter(*login_passwd)
unregistered_onu = tn.get_unregistered_onu(onu_sn)
if unregistered_onu is None:
raise OnuZteRegisterError('unregistered onu not found, sn=%s' % onu_sn.decode('utf-8'))
stack_num = int(unregistered_onu['stack_num'])
rack_num = int(unregistered_onu['rack_num'])
fiber_num = int(unregistered_onu['fiber_num'])
last_onu_number = tn.get_last_registered_onu_number(
stack_num, rack_num, fiber_num
)
if last_onu_number < 1:
raise ZTEFiberNumberNotFound
elif last_onu_number > 126:
raise ZTEFiberIsFull('olt fiber %d is full' % fiber_num)
# enter to config
if not tn.enter_to_config_mode():
raise ZteOltConsoleError('Failed to enter to config mode')
# go to olt interface
if not tn.go_to_olt_interface(stack_num, rack_num, fiber_num):
raise ZteOltConsoleError('Failed to enter in olt fiber port')
# new onu port number
new_onu_port_num = last_onu_number + 1
# register onu on olt interface
r = tn.register_onu_on_olt_fiber(onu_type, new_onu_port_num, onu_sn, line_profile, remote_profile)
print(r)
# exit from olt interface
tn.level_exit()
r = tn.go_to_onu_interface(stack_num, rack_num, fiber_num, new_onu_port_num)
print(r)
tn.apply_conf_to_onu(onu_mac, 145)
sleep(1)
return
if __name__ == '__main__':
ip = '10.40.1.10'
try:
register_onu_ZTE_F660(
olt_ip=ip, onu_sn=b'ZTEGC0458DCE', login_passwd=(b'admin', b'2ekc3'),
onu_mac=b'cc:7b:35:8b:7:0'
)
except ZteOltConsoleError as e:
print(e)
except ConnectionRefusedError:
print('ERROR: connection refused', ip)
Loading…
Cancel
Save