Files
mdb/mdb/signals.py
T

144 lines
5.1 KiB
Python

import logging
import os
import uuid
from django.conf import settings
from django.db.models.signals import pre_delete, post_save, pre_save
from django.dispatch import receiver
import ipaddress
from mdb.models import Interface, Host, Ip6Subnet, Ip4Subnet, Ip4Address
from mdb.utils import format_domain_serial_and_add_one
logger = logging.getLogger(__name__)
@receiver(post_save, sender=Ip4Subnet)
def create_ips_for_subnet(sender, instance, created, **kwargs):
if not created:
return
subnet = ipaddress.IPv4Network(instance.network + "/" + instance.netmask)
for addr in subnet.hosts():
address = Ip4Address(address=str(addr), subnet=instance)
address.save()
@receiver(pre_delete, sender=Ip4Subnet)
def delete_ips_for_subnet(sender, instance, **kwargs):
for addr in instance.ip4address_set.all():
addr.delete()
@receiver(pre_save, sender=Ip4Subnet)
def set_domain_name_for_subnet(sender, instance, **kwargs):
# we assume that the reverse domain_name does not change
if len(instance.domain_name) == 0:
ipspl = instance.network.split(".")
rev = "%s.%s.%s" % (ipspl[2], ipspl[1], ipspl[0])
instance.domain_name = "%s.in-addr.arpa" % rev
# update it's own serial
# if instance.domain_serial is not None:
# instance.domain_serial = format_domain_serial_and_add_one(instance.domain_serial)
# lets update the serial of the dhcp config
# when the subnet is changed
if instance.dhcp_config:
# instance.dhcp_config.serial = instance.dhcp_config.serial + 1
instance.dhcp_config.serial = format_domain_serial_and_add_one(instance.dhcp_config.serial)
instance.dhcp_config.save()
@receiver(pre_save, sender=Ip6Subnet)
def set_domain_name_for_ipv6_subnet(sender, instance, **kwargs):
if len(instance.domain_name) > 0:
return
network = ipaddress.IPv6Address("%s::" % instance.network)
instance.domain_name = ".".join(network.exploded.replace(":", "")[:16])[::-1] + ".ip6.arpa"
@receiver(post_save, sender=Interface)
def update_domain_serial_when_change_to_interface(sender, instance, created, **kwargs):
if instance.domain is not None:
domain = instance.domain
domain.domain_serial = format_domain_serial_and_add_one(domain.domain_serial)
domain.save()
if instance.ip4address is not None:
subnet = instance.ip4address.subnet
subnet.domain_serial = format_domain_serial_and_add_one(subnet.domain_serial)
subnet.save()
@receiver(post_save, sender=Host)
def update_domain_serial_when_change_to_host(sender, instance, created, **kwargs):
for interface in instance.interface_set.all():
if interface.domain is not None:
domain = interface.domain
domain.domain_serial = format_domain_serial_and_add_one(domain.domain_serial)
domain.save()
if interface.ip4address is not None:
subnet = interface.ip4address.subnet
subnet.domain_serial = format_domain_serial_and_add_one(subnet.domain_serial)
subnet.save()
@receiver(post_save, sender=Host)
def create_pxe_key_and_write_pxe_files_when_host_changes(sender, instance, created, **kwargs):
host = instance
if not host.pxe_key:
# generate key (prevent infinite recursion by using update)
pxe_key = uuid.uuid4().hex
Host.objects.filter(pk=host.pk).update(pxe_key=pxe_key)
host.pxe_key = pxe_key
for pxe_file_name, pxe_file in host.as_pxe_files():
path = os.path.join(settings.MDB_PXE_TFTP_ROOT, pxe_file_name)
if host.pxe_installable:
# Write pxeconfig file to disk
with open(path, 'w+') as f:
f.write(pxe_file)
logger.info("Created or updated {}".format(path))
os.chmod(path, 0o644) # Not writeable for all
# Also set necessary fields for pxe installation
interfaces = host.interface_set.exclude(ip4address__isnull=True)
for _if in interfaces:
changed = False
if not _if.pxe_filename:
_if.pxe_filename = 'pxelinux.0' # don't overwrite
changed = True
if not _if.dhcp_client:
_if.dhcp_client = True
changed = True
if changed:
_if.save()
else:
if os.path.exists(path):
# Delete pxeconfig file from disk
os.unlink(path)
logger.info("deleted {}".format(path))
@receiver(pre_delete, sender=Interface)
def update_domain_serial_when_interface_deleted(sender, instance, **kwargs):
if instance.domain is not None:
domain = instance.domain
domain.domain_serial += 1
domain.save()
if instance.ip4address is not None:
subnet = instance.ip4address.subnet
subnet.domain_serial += 1
subnet.save()
# @receiver(pre_save, sender=Domain)
# def update_domain_serial_when_domain_is_saved(sender, instance, **kwargs):
# instance.domain_serial = format_domain_serial_and_add_one(instance.domain_serial)