This commit is contained in:
ponas committed 2014-12-03 20:44:55 +01:00
1 parent 11f3b23c67
commit 9717c93faa
1 file changed
+96 -57
+96 -57
View File
@@ -8,7 +8,6 @@ import ipaddr
import datetime
import re
# Create your models here.
class Nameserver(models.Model):
hostname = models.CharField(max_length=256)
@@ -16,6 +15,7 @@ class Nameserver(models.Model):
def __unicode__(self):
return self.hostname
class MailExchange(models.Model):
priority = models.IntegerField()
hostname = models.CharField(max_length=256)
@@ -23,6 +23,7 @@ class MailExchange(models.Model):
def __unicode__(self):
return "(" + str(self.priority) + ") " + self.hostname
class Domain(models.Model):
domain_name = models.CharField(max_length=256)
domain_soa = models.CharField(max_length=256)
@@ -55,7 +56,8 @@ class Domain(models.Model):
num_records.short_description = "Num Records"
def __eq__(self, other):
if not other: return False
if not other:
return False
return self.domain_name == other.domain_name
def zone_file_contents(self):
@@ -64,7 +66,9 @@ class Domain(models.Model):
content += "; %s\n" % datetime.datetime.now()
content += "; filename: %s\n" % self.domain_filename
content += "$TTL %s\n" % self.domain_ttl
content += "@ IN SOA %s. %s. (\n" % (self.domain_soa, self.domain_admin.replace("@", "."))
content += "@ IN SOA %s. %s. (\n" % (
self.domain_soa,
self.domain_admin.replace("@", "."))
content += "\t%d\t; serial\n" % self.domain_serial
content += "\t%d\t; refresh\n" % self.domain_refresh
content += "\t%d\t; retry\n" % self.domain_retry
@@ -106,12 +110,17 @@ class Domain(models.Model):
for interface in self.interface_set.all():
host = interface.host
if interface.ip4address:
content += "%-20s\tIN\tA\t%s\n" % (host.hostname, interface.ip4address.address)
content += "%-20s\tIN\tA\t%s\n" % (
host.hostname,
interface.ip4address.address)
for ipv6addr in interface.ip6address_set.all():
content += "%-20s\tIN\tAAAA\t%s\n" % (host.hostname, ipv6addr.full_address())
content += "%-20s\tIN\tAAAA\t%s\n" % (
host.hostname,
ipv6addr.full_address())
return content
class DomainSrvRecord(models.Model):
srvce = models.CharField(max_length=64)
prot = models.CharField(max_length=64)
@@ -128,6 +137,7 @@ class DomainSrvRecord(models.Model):
+ str(self.priority) + " " + str(self.weight) + " " + \
str(self.port) + " " + self.target + "."
class DomainTxtRecord(models.Model):
name = models.CharField(max_length=256)
target = models.CharField(max_length=256)
@@ -137,6 +147,7 @@ class DomainTxtRecord(models.Model):
def __unicode__(self):
return self.name + " TXT " + self.target
class DomainCnameRecord(models.Model):
name = models.CharField(max_length=256)
target = models.CharField(max_length=256)
@@ -146,6 +157,7 @@ class DomainCnameRecord(models.Model):
def __unicode__(self):
return self.name + " IN CNAME " + self.target
class DomainARecord(models.Model):
name = models.CharField(max_length=256)
target = models.CharField(max_length=256)
@@ -175,11 +187,12 @@ class DhcpConfig(models.Model):
content += "log-facility %s;\n" % self.log_facility
content += "ddns-update-style %s;\n" % self.ddns_update_style
# time to write the subnet definitions
for subnet in self.ip4subnet_set.all():
content += "\n# %s\n" % subnet.name
content += "subnet %s netmask %s {\n" % (subnet.network, subnet.netmask)
content += "subnet %s netmask %s {\n" % (
subnet.network,
subnet.netmask)
for option in subnet.dhcpoption_set.all():
content += "\toption %s %s;\n" % (option.key, option.value)
@@ -217,6 +230,7 @@ class DhcpConfig(models.Model):
class Meta:
verbose_name = 'DHCP config'
class Ip6Subnet(models.Model):
name = models.CharField(max_length=255)
network = models.CharField(max_length=255)
@@ -238,13 +252,14 @@ class Ip6Subnet(models.Model):
def __unicode__(self):
return self.network + " (" + self.name + ")"
def zone_file_contents(self, generate_unassigned = False):
def zone_file_contents(self, generate_unassigned=False):
content = ""
content += "; zone file for %s\n" % self.domain_name
content += "; %s\n" % datetime.datetime.now()
content += "; filename: %s\n" % self.domain_filename
content += "$TTL %s\n" % self.domain_ttl
content += "@ IN SOA %s. %s. (\n" % (self.domain_soa, \
content += "@ IN SOA %s. %s. (\n" % (
self.domain_soa,
self.domain_admin.replace("@", "."))
content += "\t%d\t; serial\n" % self.domain_serial
content += "\t%d\t; refresh\n" % self.domain_refresh
@@ -260,31 +275,32 @@ class Ip6Subnet(models.Model):
content += ";\n"
# find the network
# network = ipaddr.IPv6Address("%s::" % self.network)
# content += "$ORIGIN " + ".".join(network.exploded.replace(":","")[:16])[::-1] + ".ip6.arpa.\n"
# network = ipaddr.IPv6Address("%s::" % self.network)
# content += "$ORIGIN " + ".".join(network.exploded.replace(":","")[:16])[::-1] + ".ip6.arpa.\n"
for addr in self.ip6address_set.all():
# if addr.interface_set.count() == 0: continue
#if addr.interface_set.count() == 0: continue
if addr.interface.domain == None:
if addr.interface.domain is None:
continue
hostname = "%s.%s" % (addr.interface.host.hostname, addr.interface.domain.domain_name)
hostname = "%s.%s" % (
addr.interface.host.hostname,
addr.interface.domain.domain_name)
ip = ipaddr.IPv6Address(self.network + addr.address)
ip = ".".join(ip.exploded.replace(":","")[16:])[::-1]
ip = ".".join(ip.exploded.replace(":", "")[16:])[::-1]
content += "%s\tPTR\t%s.\n" % (ip, hostname)
# addr = ipaddr.IPv6Address("%s%s" % (interface.
# content += "%20s\tIN\tPTR\t%s.\n" % (addr.address.split(".")[3], hostname)
# addr = ipaddr.IPv6Address("%s%s" % (interface.
# content += "%20s\tIN\tPTR\t%s.\n" % (addr.address.split(".")[3], hostname)
return content
class Meta:
verbose_name = 'IPv6 subnet'
class Ip4Subnet(models.Model):
class Ip4Subnet(models.Model):
name = models.CharField(max_length=256)
netmask = models.IPAddressField()
network = models.IPAddressField()
@@ -334,13 +350,14 @@ class Ip4Subnet(models.Model):
first_address.short_description = 'first address'
last_address.short_description = 'last address'
def zone_file_contents(self, generate_unassigned = False):
def zone_file_contents(self, generate_unassigned=False):
content = ""
content += "; zone file for %s\n" % self.domain_name
content += "; %s\n" % datetime.datetime.now()
content += "; filename: %s\n" % self.domain_filename
content += "$TTL %s\n" % self.domain_ttl
content += "@ IN SOA %s. %s. (\n" % (self.domain_soa, \
content += "@ IN SOA %s. %s. (\n" % (
self.domain_soa,
self.domain_admin.replace("@", "."))
content += "\t%d\t; serial\n" % self.domain_serial
content += "\t%d\t; refresh\n" % self.domain_refresh
@@ -357,21 +374,22 @@ class Ip4Subnet(models.Model):
for addr in self.ip4address_set.all():
if addr.interface_set.count() == 0 and generate_unassigned:
content += "%s\tIN\tPTR\t%s.%s\n" % \
(addr.address, addr.address.split(".")[3], \
content += "%s\tIN\tPTR\t%s.%s\n" % (
addr.address,
addr.address.split(".")[3],
"dhcp.neuf.no.")
continue
for interface in addr.interface_set.all():
if interface.domain == None and generate_unassigned:
content += "%s\tIN\tPTR\t%s.%s.\n" % \
(addr.address, \
addr.address.split(".")[3], \
if interface.domain is None and generate_unassigned:
content += "%s\tIN\tPTR\t%s.%s.\n" % (
addr.address,
addr.address.split(".")[3],
"dhcp.neuf.no")
else:
hostname = "%s.%s" % \
(interface.host.hostname, \
hostname = "%s.%s" % (
interface.host.hostname,
interface.domain.domain_name)
content += "%-20s\tIN\tPTR\t%s.\n" % \
(addr.address.split(".")[3], hostname)
@@ -381,6 +399,7 @@ class Ip4Subnet(models.Model):
class Meta:
verbose_name = 'IPv4 subnet'
class DhcpOption(models.Model):
key = models.CharField(max_length=255)
value = models.CharField(max_length=255)
@@ -392,6 +411,7 @@ class DhcpOption(models.Model):
class Meta:
verbose_name = 'DHCP option'
class DhcpCustomField(models.Model):
value = models.CharField(max_length=255)
ip4subnet = models.ForeignKey(Ip4Subnet)
@@ -399,6 +419,7 @@ class DhcpCustomField(models.Model):
class meta:
verbose_name = 'DHCP custom field'
class Ip4Address(models.Model):
subnet = models.ForeignKey(Ip4Subnet)
address = models.IPAddressField()
@@ -409,7 +430,9 @@ class Ip4Address(models.Model):
if self.interface_set.count() == 0:
return self.address
else:
return "%s (%s)" % (self.address, self.interface_set.get().host.hostname )
return "%s (%s)" % (
self.address,
self.interface_set.get().host.hostname)
def assigned_to_host(self):
self.interface_set.get().host
@@ -420,6 +443,7 @@ class Ip4Address(models.Model):
verbose_name = 'IPv4 address'
verbose_name_plural = 'IPv4 addresses'
class HostType(models.Model):
host_type = models.CharField(max_length=64)
description = models.CharField(max_length=1024)
@@ -433,6 +457,7 @@ class HostType(models.Model):
class Meta:
ordering = ("host_type",)
class OsArchitecture(models.Model):
architecture = models.CharField(max_length=64)
@@ -442,6 +467,7 @@ class OsArchitecture(models.Model):
class Meta:
verbose_name = 'OS architecture'
class OperatingSystem(models.Model):
name = models.CharField(max_length=256)
version = models.CharField(max_length=64)
@@ -453,6 +479,7 @@ class OperatingSystem(models.Model):
class Meta:
ordering = ("name", "version")
class Host(models.Model):
location = models.CharField(max_length=1024)
brand = models.CharField(max_length=1024)
@@ -489,34 +516,38 @@ class Host(models.Model):
return True
return False
ipv6_enabled.boolean = True
# ipv6_enabled.boolean = True
def mac_addresses(self):
addresses = []
for interface in self.interface_set.all():
if interface.macaddr == None: continue
addresses.append( interface.macaddr)
if interface.macaddr is None:
continue
addresses.append(interface.macaddr)
return ",".join(addresses)
def ip_addresses(self):
addresses = []
for interface in self.interface_set.all():
if interface.ip4address == None: continue
addresses.append( interface.ip4address.address )
if interface.ip4address is None:
continue
addresses.append(interface.ip4address.address)
return ",".join(addresses)
def get_ip_addresses(self):
addresses = []
for interface in self.interface_set.all():
if interface.ip4address == None: continue
addresses.append( interface.ip4address.address )
if interface.ip4address is None:
continue
addresses.append(interface.ip4address.address)
return addresses
def get_ip_addresses_for_domain(self, domain):
addresses = []
for interface in self.interface_set.all():
if interface.ip4address == None: continue
addresses.append( interface.ip4address.address )
if interface.ip4address is None:
continue
addresses.append(interface.ip4address.address)
return addresses
class Interface(models.Model):
@@ -533,7 +564,7 @@ class Interface(models.Model):
return "%s (%s on %s)" % (self.macaddr, self.name, self.host.hostname)
def ipv6_enabled(self):
return self.ip6address_set.count() > 0;
return self.ip6address_set.count() > 0
class Ip6Address(models.Model):
subnet = models.ForeignKey(Ip6Subnet)
@@ -544,16 +575,20 @@ class Ip6Address(models.Model):
return self.subnet.network + self.address
def __unicode__(self):
return "%s (%s on %s)" % (self.full_address(), self.interface.name, self.interface.host.hostname)
return "%s (%s on %s)" % (
self.full_address(),
self.interface.name,
self.interface.host.hostname)
class Meta:
verbose_name = 'IPv6 address'
verbose_name_plural = 'IPv6 addresses'
def format_domain_serial_and_add_one(serial):
today = datetime.datetime.now()
res = re.findall("^%4d%02d%02d(\d\d)$" %
(today.year, today.month, today.day), str(serial), re.DOTALL)
res = re.findall("^%4d%02d%02d(\d\d)$" % (
today.year, today.month, today.day), str(serial), re.DOTALL)
if len(res) == 0:
""" This probably means that the serial is malformed
@@ -574,13 +609,12 @@ def format_domain_serial_and_add_one(serial):
else:
number += 1
return "%4d%02d%02d%02d" % \
(today.year, today.month, today.day, number )
return "%4d%02d%02d%02d" % (
today.year, today.month, today.day, number)
else:
""" Just return the first serial for today. """
return "%4d%02d%02d%02d" % \
(today.year, today.month, today.day, 1 )
(today.year, today.month, today.day, 1)
@receiver(post_save, sender=Ip4Subnet)
@@ -591,15 +625,16 @@ def create_ips_for_subnet(sender, instance, created, **kwargs):
subnet = ipaddr.IPv4Network(instance.network + "/" + instance.netmask)
for addr in subnet.iterhosts():
address = Ip4Address(address = str(addr), subnet=instance)
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
@@ -609,7 +644,7 @@ def set_domain_name_for_subnet(sender, instance, **kwargs):
instance.domain_name = "%s.in-addr.arpa" % rev
# update it's own serial
if instance.domain_serial != None:
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
@@ -619,48 +654,52 @@ def set_domain_name_for_subnet(sender, instance, **kwargs):
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 = ipaddr.IPv6Address("%s::" % instance.network)
instance.domain_name = ".".join(network.exploded.replace(":","")[:16])[::-1] + ".ip6.arpa"
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 != None:
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 != None:
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 != None:
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 != None:
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(pre_delete, sender=Interface)
def update_domain_serial_when_interface_deleted(sender, instance, **kwargs):
if instance.domain != None:
if instance.domain is not None:
domain = instance.domain
domain.domain_serial = domain.domain_serial + 1
domain.save()
if instance.ip4address != None:
if instance.ip4address is not None:
subnet = instance.ip4address.subnet
subnet.domain_serial = subnet.domain_serial + 1
subnet.save()