From 5c5630adc1956e4f8eb92c93edebd27ea91c4a3c Mon Sep 17 00:00:00 2001 From: bashmak Date: Thu, 14 Jun 2018 17:24:48 +0300 Subject: [PATCH 1/7] Fix init device types --- abonapp/views.py | 3 +- agent/commands/dhcp.py | 2 +- devapp/base_intr.py | 6 ++- devapp/dev_types.py | 40 ++++++------------- devapp/models.py | 14 +++---- .../templates/devapp/manage_ports/list.html | 2 +- docs/dev.md | 8 ++-- 7 files changed, 30 insertions(+), 45 deletions(-) diff --git a/abonapp/views.py b/abonapp/views.py index ed1a717..afd4b72 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -602,7 +602,8 @@ def clear_dev(request, gid, uname): abon = models.Abon.objects.get(username=uname) abon.device = None abon.dev_port = None - abon.save(update_fields=('device', 'dev_port')) + abon.is_dynamic_ip = False + abon.save(update_fields=('device', 'dev_port', 'is_dynamic_ip')) messages.success(request, _('Device has successfully unattached')) except models.Abon.DoesNotExist: messages.error(request, _('Abon does not exist')) diff --git a/agent/commands/dhcp.py b/agent/commands/dhcp.py index 92051a8..f73db47 100644 --- a/agent/commands/dhcp.py +++ b/agent/commands/dhcp.py @@ -9,7 +9,7 @@ def dhcp_commit(client_ip: str, client_mac: str, switch_mac: str, switch_port: i dev = Device.objects.get(mac_addr=switch_mac) mngr_class = dev.get_manager_klass() - if mngr_class.is_use_device_port(): + if mngr_class.is_use_device_port: abon = Abon.objects.get(dev_port__device=dev, dev_port__num=switch_port, device=dev) diff --git a/devapp/base_intr.py b/devapp/base_intr.py index 3b63998..0d35450 100644 --- a/devapp/base_intr.py +++ b/devapp/base_intr.py @@ -49,12 +49,14 @@ class DevBase(object, metaclass=ABCMeta): def get_template_name(self) -> AnyStr: """Return path to html template for device""" + @property @abstractmethod def has_attachable_to_subscriber(self) -> bool: """Can connect device to subscriber""" - @abstract_static_method - def is_use_device_port() -> bool: + @property + @abstractmethod + def is_use_device_port(self) -> bool: """True if used device port while opt82 authorization""" # fixme: only that is abstract static diff --git a/devapp/dev_types.py b/devapp/dev_types.py index 7baf5e0..31aeb0b 100644 --- a/devapp/dev_types.py +++ b/devapp/dev_types.py @@ -60,6 +60,9 @@ class DLinkPort(BasePort): class DLinkDevice(DevBase, SNMPBaseWorker): + has_attachable_to_subscriber = True + is_use_device_port = True + def __init__(self, dev_instance): DevBase.__init__(self, dev_instance) SNMPBaseWorker.__init__(self, dev_instance.ip_address, dev_instance.man_passw, 2) @@ -103,13 +106,6 @@ class DLinkDevice(DevBase, SNMPBaseWorker): def get_template_name(self): return 'ports.html' - def has_attachable_to_subscriber(self) -> bool: - return True - - @staticmethod - def is_use_device_port(): - return True - @staticmethod def validate_extra_snmp_info(v: str) -> None: # Dlink has no require snmp info @@ -142,6 +138,9 @@ class ONUdev(BasePort): class OLTDevice(DevBase, SNMPBaseWorker): + has_attachable_to_subscriber = False + is_use_device_port = False + def __init__(self, dev_instance): DevBase.__init__(self, dev_instance) SNMPBaseWorker.__init__(self, dev_instance.ip_address, dev_instance.man_passw, 2) @@ -187,13 +186,6 @@ class OLTDevice(DevBase, SNMPBaseWorker): def get_template_name(self): return 'olt.html' - def has_attachable_to_subscriber(self) -> bool: - return False - - @staticmethod - def is_use_device_port(): - return False - @staticmethod def validate_extra_snmp_info(v: str) -> None: # Olt has no require snmp info @@ -208,6 +200,9 @@ class OLTDevice(DevBase, SNMPBaseWorker): class OnuDevice(DevBase, SNMPBaseWorker): + has_attachable_to_subscriber = True + is_use_device_port = False + def __init__(self, dev_instance): DevBase.__init__(self, dev_instance) dev_ip_addr = None @@ -242,13 +237,6 @@ class OnuDevice(DevBase, SNMPBaseWorker): def get_template_name(self): return "onu.html" - def has_attachable_to_subscriber(self) -> bool: - return True - - @staticmethod - def is_use_device_port(): - return False - def get_details(self): if self.db_instance is None: return @@ -330,6 +318,9 @@ class EltexPort(BasePort): class EltexSwitch(DLinkDevice): + has_attachable_to_subscriber = True + is_use_device_port = False + @staticmethod def description(): return _('Eltex switch') @@ -355,13 +346,6 @@ class EltexSwitch(DLinkDevice): tm = RuTimedelta(timedelta(seconds=uptimestamp / 100)) or RuTimedelta(timedelta()) return tm - def has_attachable_to_subscriber(self) -> bool: - return True - - @staticmethod - def is_use_device_port(): - return False - def monitoring_template(self, *args, **kwargs) -> Optional[str]: device = self.db_instance return plain_ip_device_mon_template(device) diff --git a/devapp/models.py b/devapp/models.py index b0a94ee..5f2dedd 100644 --- a/devapp/models.py +++ b/devapp/models.py @@ -73,11 +73,11 @@ class Device(models.Model): return self.status def get_manager_klass(self): - klasses = tuple(kl for kl in self.DEVICE_TYPES if kl[0] == self.devtype) - if len(klasses) > 0: - res = klasses[0][1] - if issubclass(res, DevBase): - return res + klasses = next(kl for kl in self.DEVICE_TYPES if kl[0] == self.devtype) + if klasses: + code, dev_class = klasses + if issubclass(dev_class, DevBase): + return dev_class raise TypeError('one of types is not subclass of DevBase. ' 'Or implementation of that device type is not found') @@ -89,8 +89,8 @@ class Device(models.Model): # Can attach device to subscriber in subscriber page def has_attachable_to_subscriber(self) -> bool: - mngr = self.get_manager_object() - return mngr.has_attachable_to_subscriber() + mngr = self.get_manager_klass() + return mngr.has_attachable_to_subscriber def __str__(self): return "%s: (%s) %s %s" % (self.comment, self.get_devtype_display(), self.ip_address or '', self.mac_addr or '') diff --git a/devapp/templates/devapp/manage_ports/list.html b/devapp/templates/devapp/manage_ports/list.html index e578479..a8bebe6 100644 --- a/devapp/templates/devapp/manage_ports/list.html +++ b/devapp/templates/devapp/manage_ports/list.html @@ -27,7 +27,7 @@ {% else %} {{ port.num_abons }} {% endif %} - + diff --git a/docs/dev.md b/docs/dev.md index b9f728e..94713bc 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -47,6 +47,7 @@ class EltexPort(BasePort): Теперь реализация для свича: ```python class EltexSwitch(DLinkDevice): + is_use_device_port = False @staticmethod def description(): @@ -80,9 +81,6 @@ class EltexSwitch(DLinkDevice): def has_attachable_to_subscriber(self) -> bool: return False - @staticmethod - def is_use_device_port(): - return False ``` Метод **@description** Просто отображает человекопонятное название вашего устройства в биллинге. Заметьте что строка на английском и заключена в процедуру **_** (это ugettext_lazy, см. в импорте вверху файла), @@ -102,9 +100,9 @@ class EltexSwitch(DLinkDevice): Например у Dlink стоит True потому что Dlink стоит во многих местах на доступе, и его порты принадлежат абонентам при авторизации. -Статический метод **@is_use_device_port** используется в DHCP чтоб понять что мы используем для привязки к абоненту всё устройство или +Статическое свойство **@is_use_device_port** используется в DHCP чтоб понять что мы используем для привязки к абоненту всё устройство или только порт устройства. Например, если у устройства только 1 порт абонента (PON ONU), и мы привязываем этого абонента ко всему устройству -а не к порту, то нужно вернуть False, На обычных свичах где мы авторизуем абонента на порту возвращаем True. +а не к порту, то нужно указать False, На обычных свичах где мы авторизуем абонента на порту возвращаем True. Реализация SNMPBaseWorker по сути не нужна, класс абстрактных методов не имеет. Потому когда наследуем наследуемся от *DevBase* то в базовые классы добавим и SNMPBaseWorker, как это сделано в *DLinkDevice*: From 22b1b8e8308dc35fbde07af7d011d69e10904ad6 Mon Sep 17 00:00:00 2001 From: bashmak Date: Sat, 16 Jun 2018 14:19:25 +0300 Subject: [PATCH 2/7] fix generate_random_chars function --- abonapp/forms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abonapp/forms.py b/abonapp/forms.py index e0ebc59..b9cecda 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -16,7 +16,7 @@ def generate_random_chars(length=6, chars=digits, split=2, delimiter=''): try: models.Abon.objects.get(username=username) - return generate_random_username(length=length, chars=chars, split=split, delimiter=delimiter) + return generate_random_chars(length=length, chars=chars, split=split, delimiter=delimiter) except models.Abon.DoesNotExist: return username From 1b736e23ab446e754b0aaadee6faf01db46a9a2a Mon Sep 17 00:00:00 2001 From: bashmak Date: Fri, 22 Jun 2018 11:17:27 +0300 Subject: [PATCH 3/7] Fix bugs --- abonapp/views.py | 9 ++++++- .../templates/clientsideapp/ext.html | 24 +++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/abonapp/views.py b/abonapp/views.py index afd4b72..4dc5db4 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -1,6 +1,6 @@ from typing import Dict, Optional from django.contrib.gis.shortcuts import render_to_text -from django.core.exceptions import PermissionDenied +from django.core.exceptions import PermissionDenied, ValidationError from django.db import IntegrityError, ProgrammingError, transaction from django.db.models import Count, Q from django.shortcuts import render, redirect, get_object_or_404, resolve_url @@ -1097,6 +1097,13 @@ class EditSibscriberMarkers(UpdateView): obj = models.Abon.objects.get(username=self.kwargs.get('uname')) return obj + def dispatch(self, request, *args, **kwargs): + try: + return super(EditSibscriberMarkers, self).dispatch(request, *args, **kwargs) + except ValidationError as e: + messages.error(request, e) + return self.render_to_response(self.get_context_data()) + def get_success_url(self): return resolve_url('abonapp:abon_home', self.kwargs.get('gid'), self.kwargs.get('uname')) diff --git a/clientsideapp/templates/clientsideapp/ext.html b/clientsideapp/templates/clientsideapp/ext.html index 4105265..305d090 100644 --- a/clientsideapp/templates/clientsideapp/ext.html +++ b/clientsideapp/templates/clientsideapp/ext.html @@ -51,18 +51,18 @@ {% trans 'Services' %} - +{# #}