Browse Source

Merge branch 'devel' into separate_network

devel
bashmak 8 years ago
parent
commit
ac78a64c8b
  1. 8
      abonapp/forms.py
  2. 4
      abonapp/templates/abonapp/editAbon.html
  3. 10
      abonapp/templates/abonapp/modal_abonamount.html
  4. 21
      abonapp/views.py
  5. 6
      devapp/dev_types.py
  6. 44
      devapp/models.py
  7. 24
      devapp/onu_register.py
  8. 55
      devapp/onu_register.sh
  9. 2
      devapp/views.py
  10. 2
      dialing_app/views.py

8
abonapp/forms.py

@ -165,3 +165,11 @@ class MarkersForm(forms.ModelForm):
def save(self, commit=True):
instance = super(MarkersForm, self).save(commit=False)
return instance.save(update_fields=('markers',))
class AmountMoneyForm(forms.Form):
amount = forms.FloatField(max_value=50000, label=_('Amount of money'))
comment = forms.CharField(max_length=128, label=_('Comment'), required=False)
def save(self):
pass

4
abonapp/templates/abonapp/editAbon.html

@ -40,7 +40,9 @@
{# Ip address field #}
{# {% trans 'Reset ip' as tx %}#}
{# {% url 'abonapp:reset_ip' group.pk abon.username as url %}#}
{# {% bootstrap_button '' button_type='link' icon='refresh' button_class='btn-default btn-cmd' id='iprefreshbtn' href=url size='sm' title=tx as bt %}#}
{# {% if abon.is_dynamic_ip %}#}
{# {% bootstrap_button '' button_type='link' icon='refresh' button_class='btn-default btn-cmd' id='iprefreshbtn' href=url size='sm' title=tx as bt %}#}
{# {% endif %} #}
{# {% bootstrap_field form.ip_address form_group_class='form-group-sm' addon_after_class='input-group-btn' addon_after=bt %}#}

10
abonapp/templates/abonapp/modal_abonamount.html

@ -1,4 +1,5 @@
{% load i18n %}
{% load bootstrap3 %}
<form role="form" action="{% url 'abonapp:abon_amount' group_id abon.username %}" method="post"> {% csrf_token %}
<div class="modal-header primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
@ -6,15 +7,8 @@
</div>
<div class="modal-body">
<div class="form-group-sm">
<label for="amount">{% trans 'Amount of money' %}</label>
<div class="input-group">
<span class="input-group-addon"><span class="glyphicon glyphicon-ruble"></span></span>
<input id="amount" type="text" name="amount" placeholder="0.0" class="form-control" required>
</div>
</div>
<input type="hidden" name="abonuname" value="{{ abon.username }}"><br>
{% bootstrap_form form %}
<div class="btn-group">
<button type="submit" class="btn btn-sm btn-primary">

21
abonapp/views.py

@ -4,6 +4,7 @@ from django.contrib.gis.shortcuts import render_to_text
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import IntegrityError, ProgrammingError, transaction
from django.db.models import Count, Q
from django.http.request import QueryDict
from django.shortcuts import render, redirect, get_object_or_404, resolve_url
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
@ -188,17 +189,23 @@ class DelAbonDeleteView(DeleteView):
@transaction.atomic
def abonamount(request, gid, uname):
abon = get_object_or_404(models.Abon, username=uname)
frm = None
try:
if request.method == 'POST':
abonuname = request.POST.get('abonuname')
if abonuname == uname:
amnt = lib.safe_float(request.POST.get('amount'))
abon.add_ballance(request.user, amnt, comment=_('fill account through admin side'))
frm = forms.AmountMoneyForm(request.POST)
if frm.is_valid():
amnt = frm.cleaned_data.get('amount')
comment = frm.cleaned_data.get('comment')
if not comment:
comment = _('fill account through admin side')
abon.add_ballance(request.user, amnt, comment=comment)
abon.save(update_fields=('ballance',))
messages.success(request, _('Account filled successfully on %.2f') % amnt)
return redirect('abonapp:abon_phistory', gid=gid, uname=uname)
else:
messages.error(request, _('I not know the account id'))
else:
frm = forms.AmountMoneyForm()
except (NasNetworkError, NasFailedResult) as e:
messages.error(request, e)
except lib.MultipleException as errs:
@ -206,7 +213,8 @@ def abonamount(request, gid, uname):
messages.error(request, err)
return render_to_text('abonapp/modal_abonamount.html', {
'abon': abon,
'group_id': gid
'group_id': gid,
'form': frm
}, request=request)
@ -1154,8 +1162,7 @@ def search_abon(request):
if not word:
return None
results = models.Abon.objects.filter(fio__icontains=word)[:8]
results = ({'id': usr.pk, 'text': "%s: %s" % (usr.username, usr.fio)} for usr in results)
return results
return list({'id': usr.pk, 'text': "%s: %s" % (usr.username, usr.fio)} for usr in results)
class DhcpLever(SecureApiView):

6
devapp/dev_types.py

@ -61,6 +61,7 @@ class DLinkPort(BasePort):
class DLinkDevice(DevBase, SNMPBaseWorker):
has_attachable_to_subscriber = True
tech_code = 'dlink_sw'
description = _('DLink switch')
is_use_device_port = True
@ -196,6 +197,7 @@ class OLTDevice(DevBase, SNMPBaseWorker):
class OnuDevice(DevBase, SNMPBaseWorker):
has_attachable_to_subscriber = True
description = _('PON ONU')
tech_code = 'bdcom_onu'
is_use_device_port = False
def __init__(self, dev_instance):
@ -312,6 +314,7 @@ class EltexSwitch(DLinkDevice):
description = _('Eltex switch')
is_use_device_port = False
has_attachable_to_subscriber = True
tech_code = 'eltex_sw'
def get_ports(self) -> ListOrError:
res = []
@ -322,7 +325,7 @@ class EltexSwitch(DLinkDevice):
self.get_item('.1.3.6.1.2.1.31.1.1.1.18.%d' % n),
self.get_item('.1.3.6.1.2.1.2.2.1.8.%d' % n),
self.get_item('.1.3.6.1.2.1.2.2.1.6.%d' % n),
int(speed),
int(speed) if speed != 'NOSUCHINSTANCE' else 0,
))
return res
@ -414,6 +417,7 @@ class Olt_ZTE_C320(OLTDevice):
class ZteOnuDevice(OnuDevice):
description = _('ZTE PON ONU')
tech_code = 'zte_onu'
def get_details(self) -> Optional[Dict]:
if self.db_instance is None:

44
devapp/models.py

@ -1,11 +1,9 @@
import os
from typing import Optional, AnyStr
from subprocess import run
from jsonfield import JSONField
from django.db import models
from django.conf import settings
from django.shortcuts import resolve_url
from django.utils.translation import gettext_lazy as _
from jsonfield import JSONField
from djing.fields import MACAddressField
from djing.lib import MyChoicesAdapter
@ -67,20 +65,12 @@ class Device(models.Model):
verbose_name_plural = _('Devices')
ordering = ('id',)
def get_abons(self):
pass
def get_status(self):
return self.status
def get_manager_klass(self):
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')
try:
return next(klass for code, klass in self.DEVICE_TYPES if code == self.devtype)
except StopIteration:
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:
man_klass = self.get_manager_klass()
@ -96,20 +86,12 @@ class Device(models.Model):
def __str__(self):
return "%s: (%s) %s %s" % (self.comment, self.get_devtype_display(), self.ip_address or '', self.mac_addr or '')
def update_dhcp(self, remove=False):
# FIXME: Remove static list of registrable device types
if self.devtype not in ('On', 'Dl', 'Zo'):
return
if self.group is None:
raise DeviceDBException(_('Device does not have a group, please fix that'))
code = self.group.code
newmac = str(self.mac_addr)
filepath = os.path.join(settings.BASE_DIR, 'devapp', 'onu_register.sh')
if remove:
param = 'del'
else:
param = 'update'
run((filepath, param, newmac, code))
@staticmethod
def update_dhcp():
from .onu_register import onu_register
onu_register(
Device.objects.exclude(group=None).select_related('group').only('mac_addr', 'group__code').iterator()
)
def generate_config_template(self) -> Optional[AnyStr]:
mng = self.get_manager_object()

24
devapp/onu_register.py

@ -0,0 +1,24 @@
#!/usr/bin/env python3
from typing import Iterable
from subprocess import run
def onu_register(devices: Iterable):
with open('/etc/dhcp/macs.conf', 'w') as f:
for dev in devices:
if not dev.has_attachable_to_subscriber() or dev.mac_addr is None:
continue
group_code = dev.group.code
if not group_code:
continue
try:
mn = dev.get_manager_klass()
dev_code = mn.tech_code
f.write('subclass "%(group_code)s.%(dev_code)s" "%(mac)s";\n' % {
'group_code': group_code,
'mac': dev.mac_addr,
'dev_code': dev_code
})
except TypeError:
continue
run(('/usr/bin/sudo', 'systemctl', 'restart', 'isc-dhcp-server.service'))

55
devapp/onu_register.sh

@ -1,55 +0,0 @@
#!/bin/bash
# Action
ACT=$1
if [[ ${ACT} == '' ]]; then
echo 'Need the action type parameter'
exit
fi
# old mac address
if [[ $2 =~ ^([0-9A-Fa-f]{1,2}[:-]){5}([0-9A-Fa-f]{1,2})$ ]]; then
MAC=$2
else
echo "Bad mac $MAC addr"
exit
fi
# part code
if [[ $3 =~ ^[a-zA-Z]+$ ]]; then
PART_CODE=$3
else
echo 'code must contains only letters'
exit
fi
DHCP_MACS='/etc/dhcp/macs.conf'
PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin
# if just remove device
if [[ ${ACT} == 'del' ]]; then
sed -i "/${MAC}/d" ${DHCP_MACS}
exit
fi
# If exist mac with code
if grep "^subclass\ \"${PART_CODE}\" \"${MAC}\";$" "${DHCP_MACS}" > /dev/null; then
# mac is already exists, quit
exit
else
# If mac existing in another group
if grep "${MAC}" ${DHCP_MACS} > /dev/null; then
# remove it
sed -i "/${MAC}/d" ${DHCP_MACS}
fi
# add new mac
echo "subclass \"${PART_CODE}\" \"${MAC}\";" >> ${DHCP_MACS}
sudo systemctl restart isc-dhcp-server.service
fi

2
devapp/views.py

@ -76,7 +76,7 @@ class DeviceDeleteView(DeleteView):
def delete(self, request, *args, **kwargs):
res = super().delete(request, *args, **kwargs)
try:
self.object.update_dhcp(remove=True)
self.object.update_dhcp()
except DeviceDBException as e:
messages.error(request, e)
messages.success(request, _('Device successfully deleted'))

2
dialing_app/views.py

@ -49,7 +49,7 @@ class LastCallsListView(BaseListView):
@login_required
@only_admins
def to_abon(request, tel):
abon = Abon.objects.filter(telephone=tel)
abon = Abon.objects.filter(Q(telephone__icontains=tel) | Q(additional_telephones__telephone__icontains=tel))
abon_count = abon.count()
if abon_count > 1:
messages.warning(request, _('Multiple users with the telephone number'))

Loading…
Cancel
Save