Browse Source

fix bugs

devel
Dmitry 10 years ago
parent
commit
3ddca3f8b5
  1. 1
      .gitignore
  2. 5
      abonapp/apps.py
  3. 2
      abonapp/forms.py
  4. 26
      abonapp/models.py
  5. 54
      abonapp/views.py
  6. 2
      agent.py
  7. 20
      agent/db.py
  8. 5
      agent/firewall.py
  9. 19
      agent/main.py
  10. 8
      agent/models.py
  11. 18
      agent/sslTransmitter.py
  12. 1
      agent/tariff.py
  13. 4
      devapp/models.py
  14. 3
      djing/settings.py
  15. 3
      djing/settings_example.py
  16. 1
      djing/urls.py
  17. 15
      tariff_app/base_intr.py
  18. 2
      tariff_app/custom_tariffs.py
  19. 2
      taskapp/apps.py
  20. 4
      templates/abonapp/peoples.html
  21. 16
      templates/base.html
  22. 2
      templates/taskapp/add_edit_task.html

1
.gitignore

@ -5,3 +5,4 @@ media/min/*
~*/migrations/000*.py
.idea/
djing/settings.py
*/migrations/000*.py

5
abonapp/apps.py

@ -0,0 +1,5 @@
from django.apps import AppConfig
class AbonappConfig(AppConfig):
name = 'abonapp'

2
abonapp/forms.py

@ -36,7 +36,7 @@ class AbonForm(forms.Form):
)
is_active = forms.BooleanField(
required=False,
widget=forms.Select(attrs={'class': 'form-control', 'id': 'isactive'})
widget=forms.NullBooleanSelect(attrs={'class': 'form-control', 'id': 'isactive'})
)
group = forms.ModelChoiceField(

26
abonapp/models.py

@ -15,12 +15,17 @@ from accounts_app.models import UserProfile
class LogicError(Exception):
def __init__(self, value):
self.value = value
def __init__(self, value, err_id=None):
self.value = value
if err_id:
self.err_id = err_id
def __unicode__(self):
return repr(self.value)
def __str__(self):
return repr(self.value)
class AbonGroup(models.Model):
title = models.CharField(max_length=127)
@ -49,7 +54,8 @@ class AbonLog(models.Model):
class AbonTariffManager(models.Manager):
def update_priorities(self, abonent):
@staticmethod
def update_priorities(abonent):
abon_tariff_list = AbonTariff.objects.filter(abon=abonent).order_by('tariff_priority')
# Обновляем приоритеты, чтоб по порядку были
@ -134,7 +140,7 @@ class AbonTariff(models.Model):
next_tarifs = AbonTariff.objects.filter(tariff_priority__gt = self.tariff_priority, abon=self.abon)[:1]
if next_tarifs.count() < 1:
raise LogicError(u'У абонента нет следующих назначенных услуг')
raise LogicError('У абонента нет следующих назначенных услуг')
# 0й элемент это следующая подключаемая услуга
next_tarifs[0].time_start = timezone.now()
@ -177,6 +183,7 @@ class Abon(UserProfile):
_act_tar_cache = None
# возвращает текущий тариф для абонента
def active_tariff(self):
if self._act_tar_cache:
return self._act_tar_cache
@ -317,6 +324,17 @@ class Abon(UserProfile):
comment = u'Завершение услуги по истечению срока действия'
)
# есть-ли доступ у абонента к услуге, смотрим в tariff_app.custom_tariffs.<TariffBase>.manage_access()
def is_access(self):
trf = self.active_tariff()
if not trf: return False
ct = trf.get_calc_type()
if ct.manage_access(self):
return True
else:
return False
class InvoiceForPayment(models.Model):
abon = models.ForeignKey(Abon)

54
abonapp/views.py

@ -213,6 +213,8 @@ def abonhome(request, gid, uid):
try:
if request.method == 'POST':
# подключение к NAS'у в начале для того чтоб если исключение то ничего не сохранялось и сразу показать ошибку
tc = get_TransmitterClientKlass()()
frm = forms.AbonForm(request.POST)
if frm.is_valid():
cd = frm.cleaned_data
@ -229,19 +231,22 @@ def abonhome(request, gid, uid):
abon.is_active = 1 if cd['is_active'] else 0
abon.save()
# Если включили то шлём событие от этом
# Если включили абонента то шлём событие от этом
if cd['is_active'] and not abisactive:
tc = get_TransmitterClientKlass()()
tc.signal_abon_enable(abon)
# смотрим есть-ли доступ у абонента к услуге
is_acc = abon.is_access()
if is_acc:
tc.signal_abon_refresh_info(abon)
else:
tc.signal_abon_close_inet(abon)
# Если выключили
# Если выключили абонента
elif not cd['is_active'] and abisactive:
tc = get_TransmitterClientKlass()()
tc.signal_abon_disable(abon)
# Если изменили инфу, важную для NAS то говорим NAS'у перечитать инфу об абоненте
if abon.ip_address != ip_address:
tc = get_TransmitterClientKlass()()
tc.signal_abon_refresh_info(abon)
#return redirect('abonhome_link', gid, uid)
@ -326,7 +331,7 @@ def buy_tariff(request, gid, uid):
cd = frm.cleaned_data
abon.buy_tariff(cd['tariff'], request.user)
abon.save()
return redirect('abonhome_link', uid=abon.id)
return redirect('abonhome_link', gid=gid, uid=abon.id)
else:
warntext = u'Что-то не так при покупке услуги, проверьте и попробуйте ещё'
else:
@ -363,25 +368,37 @@ def chpriority(request, gid, uid):
@login_required
def complete_service(request, gid, uid, srvid):
abtar = get_object_or_404(models.AbonTariff, id=srvid)
abon_group = get_object_or_404(models.AbonGroup, id=gid)
if abtar.abon.id != int(uid):
return HttpResponse('<h1>uid not equal uid from service</h1>')
try:
if request.method == 'POST':
tc = get_TransmitterClientKlass()()
abon = abtar.abon
# досрочно завершаем услугу
try:
# пробуем активировать следующую услугу
abtar.finish_and_activate_next_tariff(request.user)
# завершаем текущую услугу.
abtar.delete()
except models.LogicError:
# Значит у абонента нет следующих услуг. Сигналим о закрытии инета в NAS
tc = get_TransmitterClientKlass()()
tc.signal_abon_close_inet(abtar.abon)
# Значит у абонента нет следующих услуг. Игнорим, далее в tariff.manage_access() всё разрулится
pass
# завершаем текущую услугу.
abtar.delete()
# Переупорядочиваем приоритеты
models.AbonTariff.objects.update_priorities(abtar.abon)
models.AbonTariff.objects.update_priorities(abon)
# проверяем, может-ли абонент пользоваться новым тарифным планом
if abon.is_access():
# обновляем инфу об абоненте, чтоб применился новый тариф
tc.signal_abon_refresh_info(abon)
else:
# если доступа нет - закрываем инет
tc.signal_abon_close_inet(abon)
return redirect('abonhome_link', gid, uid)
@ -401,12 +418,11 @@ def complete_service(request, gid, uid, srvid):
'minutes': time_use.seconds / 60 % 60
}
return render(request, 'abonapp/complete_service.html', {
'csrf_token': csrf(request)['csrf_token'],
'abtar': abtar,
'abon': get_object_or_404(models.Abon, id=uid),
'abon': abtar.abon,
'next_tariff': next_tariff[0] if next_tariff.count() > 0 else None,
'time_use': time_use,
'abon_group': get_object_or_404(models.AbonGroup, id=gid)
'abon_group': abon_group
})
except models.LogicError as e:
@ -416,10 +432,10 @@ def complete_service(request, gid, uid, srvid):
warntext = e.value
return render(request, 'abonapp/complete_service.html', {
'csrf_token': csrf(request)['csrf_token'],
'abtar': abtar,
'uid': uid,
'warntext': warntext
'abon': abtar.abon,
'warntext': warntext,
'abon_group': abon_group
})

2
agent.py

@ -1,4 +1,4 @@
#!/bin/env python
#!/bin/env python2
import os
from agent import main

20
agent/db.py

@ -1,19 +1,20 @@
# -*- coding:utf-8 -*-
import requests
from json import loads
from requests.exceptions import ConnectionError
from models import deserialize_tariffs, deserialize_abonents
import settings
def load_from_db():
r = requests.get('%s://%s:%d/abons/api/abons' % (
'https' if settings.IS_USE_SSL else 'http',
settings.SERVER_IP,
settings.SERVER_PORT
), verify=False)
try:
r = requests.get('%s://%s:%d/abons/api/abons' % (
'https' if settings.IS_USE_SSL else 'http',
settings.SERVER_IP,
settings.SERVER_PORT
), verify=False)
user_data = loads(r.text)
del r
# Получаем тарифы
tariffs = deserialize_tariffs(user_data)
@ -23,5 +24,8 @@ def load_from_db():
return abons, tariffs
except ValueError as e:
print 'Error:', e, r.text
return
print('Error:', e, r.text)
except ConnectionError:
print("Can not connect to server %s:%d..." % (settings.SERVER_IP, settings.SERVER_PORT))
exit(0)

5
agent/firewall.py

@ -1,4 +1,5 @@
# -*- coding:utf-8 -*-
from agent.models import Abonent, Tariff
class FirewallManager(object):
@ -16,6 +17,7 @@ class FirewallManager(object):
# Открывает доступ в интернет
def open_inet_door(self, user):
assert isinstance(user, Abonent)
if not user.tariff:
print u'WARNING: User does not have a tariff'
return
@ -27,6 +29,7 @@ class FirewallManager(object):
# Закрывает доступ в интернет
def close_inet_door(self, user):
assert isinstance(user, Abonent)
cmd = r"%s table 12 del %s/32 && %s table 13 del %s/32" % (
self.f, user.ip_str(),
self.f, user.ip_str()
@ -35,11 +38,13 @@ class FirewallManager(object):
# Создаёт тариф (пайпы, режущие скорость
def make_tariff(self, tariff):
assert isinstance(tariff, Tariff)
cmd = r"make ipfw tariff :)"
self.exec_cmd(cmd)
# Убирает тариф из фаервола
def destroy_tariff(self, tariff):
assert isinstance(tariff, Tariff)
cmd = r"destroy ipfw tariff :)"
self.exec_cmd(cmd)

19
agent/main.py

@ -4,12 +4,14 @@ from db import load_from_db
from firewall import FirewallManager
from time import sleep
from sslTransmitter import TransmitServer
from agent.models import Abonent, Tariff
def filter_user_by_id(users, uid):
usrs = filter(lambda usr: usr.uid == uid, users)
if len(usrs) > 0:
return usrs[0]
users = filter(lambda usr: isinstance(usr, Abonent), users)
users = filter(lambda usr: usr.uid == uid, users)
if len(users) > 0:
return users[0]
else:
return
@ -21,7 +23,7 @@ def main(debug=False):
# Инициализация абонентов
if debug:
print u'Инициализация...'
print("Инициализация...")
# Открываем доступ в инет тем кто активен и у кого подключён тариф
for usr in filter(lambda usr: usr.is_active, users):
@ -30,13 +32,14 @@ def main(debug=False):
if usr.tariff:
# Открываем доступ в инет
frw.open_inet_door(usr)
if debug: print "Разрешён доступ в инет для:", usr.ip_str()
# Слушем в отдельном процессе сеть на предмет событий
ts = TransmitServer('127.0.0.1', 2134)
ts.start()
if debug:
print u"Загружено %d абонентов" % len(users)
print("Загружено %d абонентов" % len(users))
while True:
@ -44,9 +47,7 @@ def main(debug=False):
events = ts.get_data()
# Проходим по появившимся событиям
for event in events:
#event.toa
#event.id
#event.dt
#event.toa, event.id, event.dt
# Смотрим тип события
toa = int(event.toa)
@ -108,7 +109,7 @@ def main(debug=False):
frw.destroy_tariff(tariff)
frw.make_tariff(tariff)
else:
print 'WARNING: не найден тариф для которого сигнал на изменение данных, пробуем перезагрузиться'
print('WARNING: не найден тариф для которого возбуждён сигнал на изменение данных, пробуем перезагрузиться')
return
# Очищаем очередь событий

8
agent/models.py

@ -81,12 +81,14 @@ class Abonent(Serializer):
is_active = True
def __init__(self, uid=None, ip=None, tariff=None):
# none потому что может инициализироваться пустым, чтоб быть распакованным через deserialize()
if tariff:
assert isinstance(tariff, Tariff)
self.ip = ip
self.uid = uid
self.tariff = tariff
def ip_str(self):
# int2ip, Example out '127.0.0.1'
return socket.inet_ntoa(struct.pack("!I", self.ip))
def _serializable_obj(self):
@ -98,6 +100,10 @@ class Abonent(Serializer):
}
def deserialize(self, dump, tariffs):
# фильтруем только элементы нужного типа
tariffs = filter(lambda trf: isinstance(trf, Tariff), tariffs)
assert len(tariffs) > 0
inf = loads(dump) if type(dump) == str else dump
self.uid = int(inf['id'])
self.is_active = bool(inf['is_active'])

18
agent/sslTransmitter.py

@ -67,10 +67,12 @@ def agent_abon_typer(fn):
if isinstance(abon, Abonent):
fn(self, abon)
else:
act_tar = abon.active_tariff()
agent_tariff = Tariff(act_tar.id, act_tar.speedIn, act_tar.speedOut) if act_tar else None
abn = Abonent(
abon.id,
abon.ip_address.int_ip() if abon.ip_address else 0,
abon.active_tariff()
agent_tariff
)
fn(self, abn)
return wrapped
@ -108,7 +110,10 @@ class SSLTransmitterClient(object):
port or settings.SELF_PORT
))
except socket.error:
raise NetExcept(u'Ошибка подключения к NAS агенту')
raise NetExcept('Ошибка подключения к NAS агенту %s:%d' % (
ip or settings.SELF_IP,
port or settings.SELF_PORT
))
def write(self, d):
self.s.write(d)
@ -162,7 +167,8 @@ class SSLTransmitterClient(object):
)
def __del__(self):
self.s.close()
if self.s:
self.s.close()
class PlainTransmitterClient(SSLTransmitterClient):
@ -176,12 +182,16 @@ class PlainTransmitterClient(SSLTransmitterClient):
))
self.s = s
except socket.error:
raise NetExcept(u'Ошибка подключения к NAS агенту')
raise NetExcept('Ошибка подключения к NAS агенту на %s:%d' % (
ip or settings.SELF_IP,
port or settings.SELF_PORT
))
def write(self, d):
self.s.send(d)
# общалка с NAS'ом
def get_TransmitterClientKlass():
if settings.IS_USE_SSL:
return SSLTransmitterClient

1
agent/tariff.py

@ -1 +0,0 @@
# -*- coding:utf-8 -*-

4
devapp/models.py

@ -18,6 +18,9 @@ class Device(models.Model):
man_passw = models.CharField(max_length=16, null=True, blank=True)
#map_dot = models.ForeignKey()
class Meta:
db_table = 'dev'
def get_abons(self):
pass
@ -44,6 +47,7 @@ class Port(models.Model):
speed = models.CharField(max_length=1, default=PORT_SPEEDS[0][0], choices=PORT_SPEEDS)
class Meta:
db_table = 'dev_port'
unique_together = (('device', 'num'))

3
djing/settings.py

@ -35,7 +35,8 @@ INSTALLED_APPS = [
'searchapp',
'devapp',
'mapapp',
'statistics'
'statistics',
'taskapp'
]
MIDDLEWARE_CLASSES = [

3
djing/settings_example.py

@ -35,7 +35,8 @@ INSTALLED_APPS = [
'searchapp',
'devapp',
'mapapp',
'statistics'
'statistics',
'taskapp'
]
MIDDLEWARE_CLASSES = [

1
djing/urls.py

@ -14,6 +14,7 @@ urlpatterns = [
url(r'^dev/', include('devapp.urls')),
url(r'^map/', include('mapapp.urls')),
url(r'^statistic/', include('statistics.urls')),
url(r'^tasks/', include('taskapp.urls')),
url(r'^admin/', admin.site.urls),
]

15
tariff_app/base_intr.py

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
#from abonapp import Abon
class TariffBase(object):
class TariffBase:
__metaclass__ = ABCMeta
# Принимает на вход:
@ -14,3 +15,15 @@ class TariffBase(object):
@staticmethod
def description():
"""Возвращает текстовое описание"""
@staticmethod
def manage_access(abon):
"""Управляет доступом абонента к услуге"""
#assert isinstance(abon, Abon)
# если абонент не активен то выходим
if not abon.is_active: return False
# смотрим на текущую услугу
act_tar = abon.active_tariff()
# если есть услуга
if act_tar:
return True

2
tariff_app/custom_tariffs.py

@ -2,12 +2,14 @@
from django.utils import timezone
from datetime import datetime, timedelta
from base_intr import TariffBase
#from abonapp import AbonTariff
class TariffDefault(TariffBase):
# Базовый функционал считает стоимость пропорционально использованному времени
def calc_amount(self, abon_tariff):
#assert isinstance(abon_tariff, AbonTariff)
# сейчас
nw = datetime.now(tz=timezone.get_current_timezone())

2
taskapp/apps.py

@ -1,5 +1,5 @@
from django.apps import AppConfig
class TicketsappConfig(AppConfig):
class TaskappConfig(AppConfig):
name = 'taskapp'

4
templates/abonapp/peoples.html

@ -46,7 +46,9 @@
</thead>
<tbody>
{% for human in peoples %}
<tr>
{% if human.is_active %}<tr>
{% else %}<tr class="danger">
{% endif %}
<td>{{ human.id }}</td>
<td><a href="{% url 'abonhome_link' human.group.id human.id %}">{{ human.username }}</a></td>
<td>{{ human.ip_address|default:'Не назначен' }}</td>

16
templates/base.html

@ -21,10 +21,10 @@
<div class="modal-header warning">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel"><span class="glyphicon glyphicon-warning-sign"></span>
Ошибка</h4>
Надпись вверху</h4>
</div>
<div class="modal-body">
...
тут содержимое блока
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
@ -151,11 +151,23 @@
<a href="{{ pool_home_link }}">
<span class="glyphicon glyphicon-compressed"></span> ip пул
</a></li>
<li><a href="{% url 'devs_link' %}">
<span class="glyphicon glyphicon-hdd"></span> железки
</a></li>
{% url 'task_home' as task_home %}
{% if task_home in request.path %}
<li class="active">
{% else %}
<li>
{% endif %}
<a href="{{ task_home }}">
<span class="glyphicon glyphicon-tasks"></span> Задачи
</a></li>
</ul>
<ul class="nav nav-sidebar">

2
templates/taskapp/add_edit_task.html

@ -4,7 +4,7 @@
<ol class="breadcrumb">
<li><span class="glyphicon glyphicon-home"></span></li>
<li><a href="{% url 'task_home' %}">Задачи</a></li>
<li class="active">Создать</li>
<li class="active">{% if task.id %}Редактировать{% else %}Создать{% endif %}</li>
</ol>

Loading…
Cancel
Save