Browse Source

litte bit refactoring

devel
bashmak 8 years ago
parent
commit
b3e621d49d
  1. 514
      agent/mod_mikrotik_old.py
  2. 4
      devapp/base_intr.py
  3. 16
      devapp/dev_types.py
  4. 5
      devapp/migrations/0001_initial.py
  5. 11
      dialing.py
  6. 4
      dialing_app/views.py
  7. 2
      msg_app/migrations/0001_initial.py
  8. 6
      msg_app/models.py
  9. 1
      requirements.txt
  10. 3
      statistics/fields.py
  11. 10
      systemd_units/webdav_backup.py

514
agent/mod_mikrotik_old.py

@ -1,514 +0,0 @@
import re
import socket
import binascii
from abc import ABCMeta
from hashlib import md5
from typing import Iterable, Optional, Tuple
from djing.lib import Singleton
from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff
from . import settings as local_settings
from django.conf import settings
from djing import ping
from agent.core import BaseTransmitter, NasNetworkError, NasFailedResult
DEBUG = getattr(settings, 'DEBUG', False)
LIST_USERS_ALLOWED = 'DjingUsersAllowed'
LIST_DEVICES_ALLOWED = 'DjingDevicesAllowed'
class ApiRos(metaclass=Singleton):
"""Routeros api"""
sk = None
is_login = False
def __init__(self, ip: str, port: int):
if self.sk is None:
sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if port is None:
port = local_settings.NAS_PORT
sk.connect((ip, port or 8728))
self.sk = sk
self.currenttag = 0
def login(self, username, pwd):
if self.is_login:
return
chal = None
for repl, attrs in self.talk_iter(("/login",)):
chal = binascii.unhexlify(attrs['=ret'])
md = md5()
md.update(b'\x00')
md.update(bytes(pwd, 'utf-8'))
md.update(chal)
for _ in self.talk_iter(("/login", "=name=" + username,
"=response=00" + binascii.hexlify(md.digest()).decode('utf-8'))):
pass
self.is_login = True
def talk_iter(self, words: Iterable):
if self.write_sentence(words) == 0:
return
while 1:
i = self.read_sentence()
if len(i) == 0:
continue
reply = i[0]
attrs = {}
for w in i[1:]:
j = w.find('=', 1)
if j == -1:
attrs[w] = ''
else:
attrs[w[:j]] = w[j + 1:]
yield (reply, attrs)
if reply == '!done':
return
def write_sentence(self, words: Iterable):
ret = 0
for w in words:
self.write_word(w)
ret += 1
self.write_word('')
return ret
def read_sentence(self):
r = []
while 1:
w = self.read_word()
if w == '':
return r
r.append(w)
def write_word(self, w):
if DEBUG:
print("<<< " + w)
b = bytes(w, "utf-8")
self.write_len(len(b))
self.write_bytes(b)
def read_word(self):
ret = self.read_bytes(self.read_len()).decode('utf-8')
if DEBUG:
print(">>> " + ret)
return ret
def write_len(self, l):
if l < 0x80:
self.write_bytes(bytes((l,)))
elif l < 0x4000:
l |= 0x8000
self.write_bytes(bytes(((l >> 8) & 0xff, l & 0xff)))
elif l < 0x200000:
l |= 0xC00000
self.write_bytes(bytes(((l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff)))
elif l < 0x10000000:
l |= 0xE0000000
self.write_bytes(bytes(((l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff)))
else:
self.write_bytes(bytes((0xf0, (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, l & 0xff)))
def read_len(self):
c = self.read_bytes(1)[0]
if (c & 0x80) == 0x00:
pass
elif (c & 0xC0) == 0x80:
c &= ~0xC0
c <<= 8
c += self.read_bytes(1)[0]
elif (c & 0xE0) == 0xC0:
c &= ~0xE0
c <<= 8
c += self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
elif (c & 0xF0) == 0xE0:
c &= ~0xF0
c <<= 8
c += self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
elif (c & 0xF8) == 0xF0:
c = self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
c <<= 8
c += self.read_bytes(1)[0]
return c
def write_bytes(self, s):
n = 0
while n < len(s):
r = self.sk.send(s[n:])
if r == 0:
raise NasFailedResult("connection closed by remote end")
n += r
def read_bytes(self, length):
ret = b''
while len(ret) < length:
s = self.sk.recv(length - len(ret))
if len(s) == 0:
raise NasFailedResult("connection closed by remote end")
ret += s
return ret
def __del__(self):
if hasattr(self, 'sk'):
self.sk.close()
class TransmitterManager(BaseTransmitter, metaclass=ABCMeta):
def __init__(self, login=None, password=None, ip=None, port=None):
ip = ip or getattr(local_settings, 'NAS_IP')
if ip is None or ip == '<NAS IP>':
raise NasNetworkError('Ip address of NAS does not specified')
if not ping(ip):
raise NasNetworkError('NAS %(ip_addr)s does not pinged' % {
'ip_addr': ip
})
try:
self.ar = ApiRos(ip, port)
self.ar.login(login or getattr(local_settings, 'NAS_LOGIN'),
password or getattr(local_settings, 'NAS_PASSW'))
except ConnectionRefusedError:
raise NasNetworkError('Connection to %s is Refused' % ip)
def _exec_cmd(self, cmd: Iterable) -> list:
if not isinstance(cmd, (list, tuple)):
raise TypeError
result_iter = self.ar.talk_iter(cmd)
res = []
for rt in result_iter:
if rt[0] == '!trap':
raise NasFailedResult(rt[1]['=message'])
res.append(rt[1])
return res
def _exec_cmd_iter(self, cmd: Iterable) -> Iterable:
if not isinstance(cmd, (list, tuple)):
raise TypeError
result_iter = self.ar.talk_iter(cmd)
for rt in result_iter:
if len(rt) < 2:
continue
if rt[0] == '!trap':
raise NasFailedResult(rt[1]['=message'])
yield rt
# Build object ShapeItem from information from mikrotik
@staticmethod
def _build_shape_obj(info: dict) -> AbonStruct:
# Переводим приставку скорости Mikrotik в Mbit/s
def parse_speed(text_speed):
text_speed_digit = float(text_speed[:-1] or 0.0)
text_append = text_speed[-1:]
if text_append == 'M':
res = text_speed_digit
elif text_append == 'k':
res = text_speed_digit / 1000
# elif text_append == 'G':
# res = text_speed_digit * 0x400
else:
res = float(re.sub(r'[a-zA-Z]', '', text_speed)) / 1000 ** 2
return res
speeds = info['=max-limit'].split('/')
t = TariffStruct(
speed_in=parse_speed(speeds[1]),
speed_out=parse_speed(speeds[0])
)
try:
a = AbonStruct(
uid=int(info['=name'][3:]),
# FIXME: тут в разных микротиках или =target-addresses или =target
ip=info['=target'][:-3],
tariff=t,
is_active=False if info['=disabled'] == 'false' else True
)
a.queue_id = info['=.id']
return a
except ValueError:
pass
class QueueManager(TransmitterManager, metaclass=ABCMeta):
# Find queue by name
def find(self, name: str) -> AbonStruct:
ret = self._exec_cmd(('/queue/simple/print', '?name=%s' % name))
if len(ret) > 1:
return self._build_shape_obj(ret[0])
def add(self, user: AbonStruct):
if not isinstance(user, AbonStruct):
raise TypeError
if user.tariff is None or not isinstance(user.tariff, TariffStruct):
return
return self._exec_cmd(('/queue/simple/add',
'=name=uid%d' % user.uid,
# FIXME: тут в разных микротиках или =target-addresses или =target
'=target=%s' % user.ip,
'=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn),
'=queue=MikroBILL_SFQ/MikroBILL_SFQ',
'=burst-time=1/1'
))
def remove(self, user: AbonStruct):
if not isinstance(user, AbonStruct):
raise TypeError
q = self.find('uid%d' % user.uid)
if q is not None:
return self._exec_cmd(('/queue/simple/remove', '=.id=' + getattr(q, 'queue_id', ''),))
def remove_range(self, q_ids: Iterable[str]):
try:
# q_ids = [q.queue_id for q in q_ids]
return self._exec_cmd(('/queue/simple/remove', '=numbers=' + ','.join(q_ids)))
except TypeError as e:
print(e)
def update(self, user: AbonStruct):
if not isinstance(user, AbonStruct):
raise TypeError
if user.tariff is None or not isinstance(user.tariff, TariffStruct):
return
queue = self.find('uid%d' % user.uid)
if queue is None:
return self.add(user)
else:
mk_id = getattr(queue, 'queue_id', '')
return self._exec_cmd(('/queue/simple/set', '=.id=' + mk_id,
'=name=uid%d' % user.uid,
'=max-limit=%.3fM/%.3fM' % (user.tariff.speedOut, user.tariff.speedIn),
# FIXME: тут в разных микротиках или =target-addresses или =target
'=target=%s' % user.ip,
'=queue=MikroBILL_SFQ/MikroBILL_SFQ',
'=burst-time=1/1'
))
def read_queue_iter(self):
for code, dat in self._exec_cmd_iter(('/queue/simple/print', '=detail')):
if code == '!done':
return
sobj = self._build_shape_obj(dat)
if sobj is not None:
yield sobj
def disable(self, user: AbonStruct):
if not isinstance(user, AbonStruct):
raise TypeError
q = self.find('uid%d' % user.uid)
if q is None:
self.add(user)
return self.disable(user)
else:
return self._exec_cmd(('/queue/simple/disable', '=.id=*' + getattr(q, 'queue_id', '')))
def enable(self, user: AbonStruct):
if not isinstance(user, AbonStruct):
raise TypeError
q = self.find('uid%d' % user.uid)
if q is None:
self.add(user)
self.enable(user)
else:
return self._exec_cmd(('/queue/simple/enable', '=.id=*' + getattr(q, 'queue_id', '')))
class IpAddressListObj(IpStruct):
__slots__ = ('__ip', 'mk_id')
def __init__(self, ip, mk_id):
super(IpAddressListObj, self).__init__(ip)
self.mk_id = str(mk_id).replace('*', '')
class IpAddressListManager(TransmitterManager, metaclass=ABCMeta):
def add(self, list_name: str, ip: IpStruct):
if not isinstance(ip, IpStruct):
raise TypeError
commands = (
'/ip/firewall/address-list/add',
'=list=%s' % list_name,
'=address=%s' % ip
)
return self._exec_cmd(commands)
def remove(self, mk_id):
return self._exec_cmd((
'/ip/firewall/address-list/remove',
'=.id=*' + str(mk_id).replace('*', '')
))
def remove_range(self, items: Iterable[IpAddressListObj]):
ids = tuple(ip.mk_id for ip in items if isinstance(ip, IpAddressListObj))
if len(ids) > 0:
return self._exec_cmd([
'/ip/firewall/address-list/remove',
'=numbers=*%s' % ',*'.join(ids)
])
def find(self, ip: IpStruct, list_name: str):
if not isinstance(ip, IpStruct):
raise TypeError
return self._exec_cmd((
'/ip/firewall/address-list/print', 'where',
'?list=%s' % list_name,
'?address=%s' % ip
))
def read_ips_iter(self, list_name: str):
ips = self._exec_cmd_iter((
'/ip/firewall/address-list/print', 'where',
'?list=%s' % list_name,
'?dynamic=no'
))
for code, dat in ips:
if dat != {}:
yield IpAddressListObj(dat['=address'], dat['=.id'])
def disable(self, user: AbonStruct):
r = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
if len(r) > 1:
mk_id = r[0]['=.id']
return self._exec_cmd((
'/ip/firewall/address-list/disable',
'=.id=' + str(mk_id),
))
def enable(self, user):
r = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
if len(r) > 1:
mk_id = r[0]['=.id']
return self._exec_cmd((
'/ip/firewall/address-list/enable',
'=.id=' + str(mk_id),
))
class MikrotikTransmitter(QueueManager, IpAddressListManager):
def add_user_range(self, user_list: VectorAbon):
for usr in user_list:
self.add_user(usr)
def remove_user_range(self, users: VectorAbon):
if not isinstance(users, (tuple, list, set)):
raise ValueError('*users* is used twice, generator does not fit')
queue_ids = (usr.queue_id for usr in users if usr is not None)
QueueManager.remove_range(self, queue_ids)
for ip in (user.ip for user in users if isinstance(user, AbonStruct)):
ip_list_entity = IpAddressListManager.find(self, ip, LIST_USERS_ALLOWED)
if ip_list_entity is not None and len(ip_list_entity) > 1:
IpAddressListManager.remove(self, ip_list_entity[0]['=.id'])
def add_user(self, user: AbonStruct, *args):
if not isinstance(user.ip, IpStruct):
raise TypeError
if user.tariff is None:
return
if not isinstance(user.tariff, TariffStruct):
raise TypeError
try:
QueueManager.add(self, user)
except (NasNetworkError, NasFailedResult) as e:
print('Error:', e)
try:
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip)
except (NasNetworkError, NasFailedResult) as e:
print('Error:', e)
def remove_user(self, user: AbonStruct):
QueueManager.remove(self, user)
firewall_ip_list_obj = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
if firewall_ip_list_obj is not None and len(firewall_ip_list_obj) > 1:
IpAddressListManager.remove(self, firewall_ip_list_obj[0]['=.id'])
def update_user(self, user: AbonStruct, *args):
if not isinstance(user.ip, IpStruct):
raise TypeError
find_res = IpAddressListManager.find(self, user.ip, LIST_USERS_ALLOWED)
queue = QueueManager.find(self, 'uid%d' % user.uid)
if not user.is_active:
# если не активен - то и обновлять не надо
# но и выключить на всяк случай надо, а то вдруг был включён
if len(find_res) > 1:
# и если найден был - то удалим ip из разрешённых
IpAddressListManager.remove(self, find_res[0]['=.id'])
if queue is not None:
QueueManager.remove(self, user)
return
# если нет услуги то её не должно быть и в nas
if user.tariff is None or not isinstance(user.tariff, TariffStruct):
if queue is not None:
QueueManager.remove(self, user)
return
# если не найден (mikrotik возвращает пустой словарь в списке если ничего нет)
if len(find_res) < 2:
# добавим запись об абоненте
IpAddressListManager.add(self, LIST_USERS_ALLOWED, user.ip)
# Проверяем шейпер
if queue is None:
QueueManager.add(self, user)
return
if queue != user:
QueueManager.update(self, user)
def ping(self, host, count=10) -> Optional[Tuple[int, int]]:
r = self._exec_cmd((
'/ip/arp/print',
'?address=%s' % host
))
if r == [{}]:
return
interface = r[0]['=interface']
r = self._exec_cmd((
'/ping', '=address=%s' % host, '=arp-ping=yes', '=interval=100ms', '=count=%d' % count,
'=interface=%s' % interface
))
received, sent = int(r[-2:][0]['=received']), int(r[-2:][0]['=sent'])
return received, sent
# Тарифы хранить нам не надо, так что методы тарифов ниже не реализуем
def add_tariff_range(self, tariff_list: VectorTariff):
pass
# соответственно и удалять тарифы не надо
def remove_tariff_range(self, tariff_list: VectorTariff):
pass
# и добавлять тоже
def add_tariff(self, tariff: TariffStruct):
pass
# и обновлять
def update_tariff(self, tariff: TariffStruct):
pass
def remove_tariff(self, tid: int):
pass
def read_users(self) -> Iterable[AbonStruct]:
# shapes is ShapeItem
allowed_ips = set(IpAddressListManager.read_ips_iter(self, LIST_USERS_ALLOWED))
queues = tuple(q for q in QueueManager.read_queue_iter(self) if q.ip in allowed_ips)
ips_from_queues = set(q.ip for q in queues)
# delete ip addresses that are in firewall/address-list and there are no corresponding in queues
diff = tuple(allowed_ips - ips_from_queues)
if len(diff) > 0:
IpAddressListManager.remove_range(self, diff)
return queues

4
devapp/base_intr.py

@ -66,8 +66,8 @@ class DevBase(object, metaclass=ABCMeta):
def get_is_use_device_port(cls) -> bool: def get_is_use_device_port(cls) -> bool:
return cls.is_use_device_port return cls.is_use_device_port
@classmethod
def validate_extra_snmp_info(cls, v: str) -> None:
@staticmethod
def validate_extra_snmp_info(v: str) -> None:
""" """
Validate extra snmp field for each device. Validate extra snmp field for each device.
If validation failed then raise en exception from djing.lib.tln.ValidationError If validation failed then raise en exception from djing.lib.tln.ValidationError

16
devapp/dev_types.py

@ -103,14 +103,14 @@ class DLinkDevice(DevBase, SNMPBaseWorker):
def get_template_name(self): def get_template_name(self):
return 'ports.html' return 'ports.html'
@classmethod
def validate_extra_snmp_info(cls, v: str) -> None:
@staticmethod
def validate_extra_snmp_info(v: str) -> None:
# Dlink has no require snmp info # Dlink has no require snmp info
pass pass
def monitoring_template(self, *args, **kwargs) -> Optional[str]: def monitoring_template(self, *args, **kwargs) -> Optional[str]:
device = self.db_instance device = self.db_instance
return plain_ip_device_mon_template(device, *args, **kwargs)
return plain_ip_device_mon_template(device)
def register_device(self, extra_data: Dict): def register_device(self, extra_data: Dict):
pass pass
@ -180,8 +180,8 @@ class OLTDevice(DevBase, SNMPBaseWorker):
def get_template_name(self): def get_template_name(self):
return 'olt.html' return 'olt.html'
@classmethod
def validate_extra_snmp_info(cls, v: str) -> None:
@staticmethod
def validate_extra_snmp_info(v: str) -> None:
# Olt has no require snmp info # Olt has no require snmp info
pass pass
@ -253,7 +253,7 @@ class OnuDevice(DevBase, SNMPBaseWorker):
return {'err': "%s: %s" % (_('ONU not connected'), e)} return {'err': "%s: %s" % (_('ONU not connected'), e)}
@staticmethod @staticmethod
def validate_extra_snmp_info(cls, v: str) -> None:
def validate_extra_snmp_info(v: str) -> None:
# DBCOM Onu have en integer snmp port # DBCOM Onu have en integer snmp port
try: try:
int(v) int(v)
@ -439,8 +439,8 @@ class ZteOnuDevice(OnuDevice):
def get_template_name(self): def get_template_name(self):
return 'onu_for_zte.html' return 'onu_for_zte.html'
@classmethod
def validate_extra_snmp_info(cls, v: str) -> None:
@staticmethod
def validate_extra_snmp_info(v: str) -> None:
# for example 268501760.5 # for example 268501760.5
try: try:
fiber_num, onu_port = v.split('.') fiber_num, onu_port = v.split('.')

5
devapp/migrations/0001_initial.py

@ -20,8 +20,7 @@ class Migration(migrations.Migration):
name='Device', name='Device',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
(
'ip_address', MyGenericIPAddressField(max_length=8, protocol='ipv4', verbose_name='Ip address')),
('ip_address', MyGenericIPAddressField(max_length=8, protocol='ipv4', verbose_name='Ip address')),
('mac_addr', djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True, ('mac_addr', djing.fields.MACAddressField(blank=True, integer=True, null=True, unique=True,
verbose_name='Mac address')), verbose_name='Mac address')),
('comment', models.CharField(max_length=256, verbose_name='Comment')), ('comment', models.CharField(max_length=256, verbose_name='Comment')),
@ -66,6 +65,6 @@ class Migration(migrations.Migration):
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='port', name='port',
unique_together=set([('device', 'num')]),
unique_together={('device', 'num')},
), ),
] ]

11
dialing.py

@ -147,15 +147,16 @@ def handle_shutdown(event, mngr):
def signal_handler(signum, frame): def signal_handler(signum, frame):
if signum != 10: return
if signum != 10:
return
global outbox_messages global outbox_messages
outbox_messages = True outbox_messages = True
def handle_inbox_long_sms_message(event, manager):
def handle_inbox_long_sms_message(event, mngr):
if event.has_header('Message'): if event.has_header('Message'):
pdu = event.get_header('Message') pdu = event.get_header('Message')
pdu = re.sub(r'^\+CMGR\:\s\d\,\,\d{1,3}\\r\\n', '', pdu)
pdu = re.sub(r'^\+CMGR:\s\d,,\d{1,3}\\r\\n', '', pdu)
sd = SmsDeliver(pdu) sd = SmsDeliver(pdu)
data = sd.data data = sd.data
chunks_count = data.get('cnt') chunks_count = data.get('cnt')
@ -166,10 +167,10 @@ def handle_inbox_long_sms_message(event, manager):
) )
if chunks_count is not None: if chunks_count is not None:
# more than 1 message # more than 1 message
manager.push_text(sms=sms, ref=data.get('ref'), cnt=chunks_count)
mngr.push_text(sms=sms, ref=data.get('ref'), cnt=chunks_count)
else: else:
# one message # one message
manager.save_sms(sms)
mngr.save_sms(sms)
@pidfile(pidname='dialing.py.pid', piddir='/run') @pidfile(pidname='dialing.py.pid', piddir='/run')

4
dialing_app/views.py

@ -164,7 +164,7 @@ class SmsManager(SecureApiView):
http_method_names = ('get',) http_method_names = ('get',)
@staticmethod @staticmethod
def bad_cmd(**kwargs) -> JSONType:
def bad_cmd() -> JSONType:
return {'text': 'Command is not allowed'} return {'text': 'Command is not allowed'}
@method_decorator(json_view) @method_decorator(json_view)
@ -198,7 +198,7 @@ class SmsManager(SecureApiView):
return {'text': 'Bad mid parameter'} return {'text': 'Bad mid parameter'}
@staticmethod @staticmethod
def get_new(**kwargs) -> JSONType:
def get_new() -> JSONType:
msgs = SMSOut.objects.filter(status='nw').defer('status') msgs = SMSOut.objects.filter(status='nw').defer('status')
res = [{ res = [{
'when': round(m.timestamp), 'when': round(m.timestamp),

2
msg_app/migrations/0001_initial.py

@ -109,6 +109,6 @@ class Migration(migrations.Migration):
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='messagestatus', name='messagestatus',
unique_together=set([('msg', 'user', 'state')]),
unique_together={('msg', 'user', 'state')},
), ),
] ]

6
msg_app/models.py

@ -123,7 +123,8 @@ class ConversationManager(models.Manager):
) )
return conversation return conversation
def get_new_messages_count(self, account):
@staticmethod
def get_new_messages_count(account):
if isinstance(account, UserProfile): if isinstance(account, UserProfile):
return MessageStatus.objects.filter(user=account, state='new').count() return MessageStatus.objects.filter(user=account, state='new').count()
else: else:
@ -176,7 +177,8 @@ class Conversation(models.Model):
except ChatException as e: except ChatException as e:
raise MessageError(e) raise MessageError(e)
def remove_message(self, msg):
@staticmethod
def remove_message(msg):
if isinstance(msg, Message): if isinstance(msg, Message):
m = msg m = msg
else: else:

1
requirements.txt

@ -24,6 +24,7 @@ pyst2
django-jsonview django-jsonview
django-bitfield django-bitfield
transliterate transliterate
asterisk
# django-xmlview for pay system allpay # django-xmlview for pay system allpay
-e git://github.com/nerosketch/django-xmlview.git#egg=django-xmlview -e git://github.com/nerosketch/django-xmlview.git#egg=django-xmlview

3
statistics/fields.py

@ -35,7 +35,8 @@ class UnixDateTimeField(models.DateTimeField):
else: else:
return datetime.datetime.fromtimestamp(float(val)) return datetime.datetime.fromtimestamp(float(val))
def _is_string(value, val):
@staticmethod
def _is_string(val):
return isinstance(val, str) return isinstance(val, str)
def get_db_prep_value(self, val, *args, **kwargs): def get_db_prep_value(self, val, *args, **kwargs):

10
systemd_units/webdav_backup.py

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os
from sys import argv from sys import argv
from datetime import datetime, timedelta from datetime import datetime, timedelta
import webdav.client as wc import webdav.client as wc
@ -15,7 +16,7 @@ def remove_old_files(border_time: datetime, client):
for file in client.list('ISBackups'): for file in client.list('ISBackups'):
fdate = datetime.strptime(file, 'djing%Y-%m-%d_%H.%M.%S.sql.gz') fdate = datetime.strptime(file, 'djing%Y-%m-%d_%H.%M.%S.sql.gz')
if fdate < border_time: if fdate < border_time:
del_fname = 'ISBackups/%' % file
del_fname = os.path.join('ISBackups', file)
client.clean(del_fname) client.clean(del_fname)
print("rm %s" % del_fname) print("rm %s" % del_fname)
@ -25,9 +26,12 @@ if __name__ == '__main__':
try: try:
client = wc.Client(options) client = wc.Client(options)
if reqfile == 'rotate': if reqfile == 'rotate':
border_time = datetime.now() - timedelta(month=3)
border_time = datetime.now() - timedelta(weeks=12)
remove_old_files(border_time, client) remove_old_files(border_time, client)
else: else:
client.upload_sync(remote_path="ISBackups/%s" % reqfile, local_path="/var/backups/%s" % reqfile)
client.upload_sync(
remote_path=os.path.join('ISBackups', reqfile),
local_path=os.path.join('var', 'backups', reqfile)
)
except wc.WebDavException as we: except wc.WebDavException as we:
print(we, type(we)) print(we, type(we))
Loading…
Cancel
Save