Browse Source

Merge branch 'master' of https://github.com/bashmak/djing

# Conflicts:
#	agent/mod_mikrotik.py
devel
Dmitry 9 years ago
parent
commit
65953dae5c
  1. 88
      agent/mod_mikrotik.py

88
agent/mod_mikrotik.py

@ -4,9 +4,8 @@ import binascii
from hashlib import md5
from .core import BaseTransmitter, NasFailedResult, NasNetworkError
from mydefs import ping
from .structs import TariffStruct, AbonStruct, IpStruct
from .structs import TariffStruct, IpStruct
from . import settings
from djing.settings import DEBUG
class ApiRos:
@ -16,17 +15,18 @@ class ApiRos:
self.currenttag = 0
def login(self, username, pwd):
for repl, attrs in self.talk_iter(["/login"]):
for repl, attrs in self.talk(["/login"]):
chal = binascii.unhexlify(attrs['=ret'])
md = md5()
md.update(b'\x00')
md.update(bytes(pwd, 'utf-8'))
md.update(chal)
for r in self.talk_iter(["/login", "=name=" + username,
"=response=00" + binascii.hexlify(md.digest()).decode('utf-8')]): pass
self.talk(["/login", "=name=" + username,
"=response=00" + binascii.hexlify(md.digest()).decode('utf-8')])
def talk_iter(self, words):
def talk(self, words):
if self.writeSentence(words) == 0: return
r = []
while 1:
i = self.readSentence()
if len(i) == 0: continue
@ -38,8 +38,8 @@ class ApiRos:
attrs[w] = ''
else:
attrs[w[:j]] = w[j+1:]
yield (reply, attrs)
if reply == '!done': return
r.append((reply, attrs))
if reply == '!done': return r
def writeSentence(self, words):
ret = 0
@ -57,16 +57,14 @@ class ApiRos:
r.append(w)
def writeWord(self, w):
if DEBUG:
print("<<< " + w)
print("<<< " + w)
b = bytes(w, "utf-8")
self.writeLen(len(b))
self.writeBytes(b)
def readWord(self):
ret = self.readBytes(self.readLen()).decode('utf-8')
if DEBUG:
print(">>> " + ret)
print(">>> " + ret)
return ret
def writeLen(self, l):
@ -132,6 +130,7 @@ class ApiRos:
return ret
# TODO: Реализовать передачу в шейпер срок действия тарифа
class MikrotikTransmitter(BaseTransmitter):
def __init__(self, login=None, password=None, ip=None, port=None):
ip = ip or settings.NAS_IP
@ -145,36 +144,25 @@ class MikrotikTransmitter(BaseTransmitter):
except ConnectionRefusedError:
raise NasNetworkError('Подключение к %s отклонено (Connection Refused)' % ip)
def _exec_cmd_iter(self, cmd):
assert isinstance(cmd, list)
result_iter = self.ar.talk_iter(cmd)
for rt in result_iter:
if rt[0] == '!trap':
raise NasFailedResult(rt[1]['=message'])
yield rt
def _exec_cmd(self, cmd):
assert isinstance(cmd, list)
result_iter = self.ar.talk_iter(cmd)
res = []
for rt in result_iter:
result = self.ar.talk(cmd)
for rt in result:
if rt[0] == '!trap':
raise NasFailedResult(rt[1]['=message'])
res.append(rt[1])
return res
return result
# ищем правило по имени, и возвращаем всю инфу о найденном правиле
def _find_queue(self, name):
ret = self._exec_cmd(['/queue/simple/print', '?name=%s' % name])
return ret[0]
return ret[0][1]
def add_user_range(self, user_list):
for usr in user_list:
self.add_user(usr)
return list(map(self.add_user, user_list))
def remove_user_range(self, user_ids):
names = ['%d' % usr for usr in user_ids]
return self._exec_cmd(['/queue/simple/remove', *names])
def remove_user_range(self, user_list):
names = ['uid%d' % usr.uid for usr in user_list]
return self._exec_cmd(['/queue/simple/remove', '=.id=%s' % ','.join(names)])
# добавляем правило шейпинга для указанного ip и со скоростью max-limit=Upload/Download
# Мы уверены что user это инстанс класса agent.structs.AbonStruct
@ -190,63 +178,41 @@ class MikrotikTransmitter(BaseTransmitter):
# удаляем правило шейпера по имени правила
def remove_user(self, user):
uid = user if type(user) is int else user.uid
return self._exec_cmd(['/queue/simple/remove', '=name=uid%d' % uid])
self._exec_cmd(['/queue/simple/remove', '=.id=uid%d' % uid])
# обновляем основную инфу абонента
def update_user(self, user):
assert isinstance(user.tariff, TariffStruct)
assert isinstance(user.ip, IpStruct)
return self._exec_cmd(['/queue/simple/set', '=name=uid%d' % user.uid,
self._exec_cmd(['/queue/simple/set', '=.id=uid%d' % user.uid,
'=max-limit=%fM/%fM' % (user.tariff.speedOut, user.tariff.speedIn),
'=target-addresses=%s/32' % user.ip.get_str()
])
# читаем абонентов, возващаем абнента и номер в микротике
def read_users_iter(self):
ret_it = self._exec_cmd_iter(['/queue/simple/print', '=detail'])
for re in ret_it:
if re[0] == '!done': return
speeds = re[1]['=limit-at'].split('/')
speeds = [sp.replace('M','') for sp in speeds]
abon = AbonStruct(
uid=int(re[1]['=name'][3:]),
ip=IpStruct(re[1]['=target-addresses'][:-3]),
tariff=TariffStruct(speedIn=speeds[0], speedOut=speeds[1])
)
yield abon
# то же что и выше, только получаем номера в микротике
def read_users_mikroids_iter(self):
ret_it = self._exec_cmd_iter(['/queue/simple/print', '=detail'])
for re in ret_it:
if re[0] == '!done': return
yield int(re[1]['=.id'].replace('*', ''), base=16)
# приостановливаем обслуживание абонента
# в @user передаём номер в микротике
def pause_user(self, user):
self._exec_cmd(['/queue/simple/disable', user])
self._exec_cmd(['/queue/simple/disable', '=.id=uid%d' % user.uid])
# продолжаем обслуживание абонента
# в @user передаём номер в микротике
def start_user(self, user):
self._exec_cmd(['/queue/simple/enable', user])
self._exec_cmd(['/queue/simple/enable', '=.id=uid%d' % user.uid])
# Тарифы хранить нам не надо, так что методы тарифов ниже не реализуем
def add_tariff_range(self, tariff_list):
pass
# соответственно и удалять тарифы не надо
# todo: реальзовать
def remove_tariff_range(self, tariff_list):
pass
# и добавлять тоже
# todo: реальзовать
def add_tariff(self, tariff):
pass
# и обновлять
# todo: реальзовать
def update_tariff(self, tariff):
pass
# todo: реальзовать
def remove_tariff(self, tid):
pass
Loading…
Cancel
Save