216 lines
8.3 KiB
Python
216 lines
8.3 KiB
Python
import logging
|
|
from functools import cached_property
|
|
|
|
from django.db import models
|
|
from django.db.models.signals import post_save, pre_delete, pre_save
|
|
from django.dispatch import receiver
|
|
|
|
from lib.db import TaskAwareModelMixin
|
|
from lib.decorators import skip_signal
|
|
from lib.mikrotik import MikrotikModelMixin, is_local_ip
|
|
|
|
|
|
class DNSStatic(MikrotikModelMixin, TaskAwareModelMixin):
|
|
id = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
name = models.CharField(max_length=150, null=True, blank=True, unique=True, )
|
|
address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
ttl = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
dynamic = models.CharField(max_length=150, null=True, blank=True, default='', editable=False)
|
|
regexp = models.CharField(max_length=150, null=True, blank=True, unique=True, )
|
|
|
|
# lease = models.ForeignKey('IPDHCPLease', on_delete=models.SET_NULL, null=True, blank=True, default=None, related_name='dns_statics', name)
|
|
|
|
@property
|
|
def unique_on_router(self):
|
|
return ['address', ('name', 'regexp')]
|
|
|
|
@property
|
|
def get_self_params(self):
|
|
return {f:getattr(self, f) for f in ['address', 'name', 'regexp', 'comment'] if getattr(self, f, None)}
|
|
|
|
def __str__(self):
|
|
return f'{self.address} - {self.name or self.regexp}'
|
|
|
|
@property
|
|
def no_mikrotik_props(self):
|
|
return super().no_mikrotik_props + ['ttl']
|
|
|
|
@property
|
|
def router_base(self):
|
|
return '/ip/dns/static'
|
|
|
|
@cached_property
|
|
def router_list(self):
|
|
ret = []
|
|
for r in self.router_get_all:
|
|
if is_local_ip(r['address']):
|
|
ret.append(r)
|
|
self.response = ret
|
|
return self.response
|
|
|
|
|
|
class IPAddress(MikrotikModelMixin, TaskAwareModelMixin):
|
|
id = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
network = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
interface = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
actual_interface = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
invalid = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
dynamic = models.CharField(max_length=150, null=True, blank=True, default='', editable=False)
|
|
|
|
@property
|
|
def unique_on_router(self):
|
|
return ['address', 'network', 'interface']
|
|
|
|
def __str__(self):
|
|
return f'{self.address} - {self.comment}'
|
|
|
|
@property
|
|
def router_base(self):
|
|
return '/ip/address'
|
|
|
|
@property
|
|
def no_mikrotik_props(self):
|
|
return super().no_mikrotik_props + [
|
|
'actual_interface',
|
|
'invalid',
|
|
]
|
|
|
|
@property
|
|
def get_next_ip(self):
|
|
# sync_from_mikrotik(IPDHCPLease)
|
|
net = '.'.join(self.network.split('.')[:-1]) + '.'
|
|
used = sorted(IPDHCPLease.objects.filter(address__startswith=net).values_list('address', flat=True),
|
|
reverse=True)
|
|
next32 = 1
|
|
if used:
|
|
next32 += int(used[0].split('.')[-1])
|
|
return f'{net}{next32}'
|
|
|
|
@cached_property
|
|
def router_list(self):
|
|
""" { "id": "*XXX", "address": "X.X.X.X/XX",
|
|
"network": "X.X.X.X", "interface": "<>",
|
|
"actual-interface": "", "invalid": "false",
|
|
"dynamic": "true", "disabled": "false" } """
|
|
ret = []
|
|
for r in self.router_get_all:
|
|
if all([
|
|
r['invalid'] == 'false',
|
|
r['disabled'] == 'false',
|
|
'container' in r.get('comment', '').lower(),
|
|
is_local_ip(r['address']),
|
|
r['address'].endswith('.1/24'),
|
|
]):
|
|
ret.append(r)
|
|
return ret
|
|
|
|
|
|
class IPDHCPLease(MikrotikModelMixin, TaskAwareModelMixin):
|
|
id = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
mac_address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
client_id = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
hostname = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
valid_until = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
dynamic = models.CharField(max_length=150, null=True, blank=True, default='', editable=False)
|
|
blocked = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
active_client_id = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
active_mac_address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
expires_after = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
age = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
active_server = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
active_address = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
host_name = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
radius = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
last_seen = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
dhcp_option = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
status = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
server = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
address_lists = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
always_broadcast = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
lease_time = models.CharField(max_length=150, null=True, blank=True, default='')
|
|
|
|
@property
|
|
def unique_on_router(self):
|
|
return ['address', 'nac_address']
|
|
|
|
|
|
@property
|
|
def mikrotik_send_params(self):
|
|
return {
|
|
'address': self.address,
|
|
'mac-address': self.mac_address,
|
|
'comment': self.comment,
|
|
}
|
|
|
|
def save(self, *args, **kwargs):
|
|
self.mac_address = self.mac_address.upper() if self.mac_address else ''
|
|
super().save(*args, **kwargs)
|
|
|
|
@property
|
|
def network_24(self):
|
|
return '.'.join(self.address.split('.')[:-1]) + '.'
|
|
|
|
def __str__(self):
|
|
return f'{self.address} - {self.mac_address} - {self.status}'
|
|
|
|
@property
|
|
def router_base(self):
|
|
return '/ip/dhcp-server/lease'
|
|
|
|
@cached_property
|
|
def router_list(self):
|
|
return self.router_get_all
|
|
|
|
@property
|
|
def no_mikrotik_props(self):
|
|
return super().no_mikrotik_props + [
|
|
'active_client_id',
|
|
'active_mac_address',
|
|
'expires_after',
|
|
'age',
|
|
'active_server',
|
|
'active_address',
|
|
'hostname',
|
|
'host_name',
|
|
'radius',
|
|
'last_seen',
|
|
'status',
|
|
'lease_time',
|
|
'server',
|
|
]
|
|
|
|
|
|
for cl in [IPAddress, IPDHCPLease, DNSStatic]:
|
|
@receiver(pre_save, sender=cl)
|
|
def send_before_save(sender, instance: MikrotikModelMixin, **kwargs):
|
|
if instance._state.adding:
|
|
logging.info(f'Created {instance} via pre_save event - do nothing')
|
|
return instance
|
|
try:
|
|
response = instance.sync_to_router()
|
|
logging.debug(f'Update {instance} to router with {response}')
|
|
except Exception as e:
|
|
logging.error(f'Error while updating {instance} to router: {e}')
|
|
return instance
|
|
|
|
@receiver(post_save, sender=cl)
|
|
@skip_signal(signaltype='post_save')
|
|
def send_after_save(sender, instance: MikrotikModelMixin, created, **kwargs):
|
|
if created:
|
|
logging.info(f'Created {instance} via post_save event - sync once')
|
|
instance.sync_to_router()
|
|
return instance
|
|
|
|
|
|
# @skip_signal(signaltype='pre_delete')
|
|
@receiver(pre_delete, sender=cl)
|
|
def send_before_delete(sender, instance, **kwargs):
|
|
try:
|
|
response = instance.delete_from_router()
|
|
logging.debug(f'Deleted {instance} from router with {response}')
|
|
except Exception as e:
|
|
logging.error(f'Error while deleting {instance} from router: {e}')
|
|
return instance
|