Bump everything (python3 ftw), starts verify api

This commit is contained in:
nikolark committed 2015-10-01 22:54:50 +02:00
1 parent bc6029e289
commit 9ff22d634f
17 files changed
+336 -287

No files matched your search

+2 -2
View File
@@ -2,7 +2,7 @@
*.swp *.swp
temp temp
*.log *.log
settings.py local_settings.py
dns_mdb.db db.sqlite3
/.idea /.idea
/venv /venv
-17
View File
@@ -1,17 +0,0 @@
A Django app for managing computer equipment.
Generates DHCP configs and zone files.
Dependencies:
sudo apt-get install libmysqlclient-dev python-dev libldap2-dev libsasl2-dev bind9utils
Setup environment:
mdb$ virtualenv venv
mdb$ . venv/bin/activate
(venv)mdb$ pip install -r requirements.txt
Create a config file:
mdb$ cp mdb/settings-sample.py mdb/settings.py
# Edit settings.py with your favorite editor
Run the server:
(venv)mdb$ python manage.py runserver
+15
View File
@@ -0,0 +1,15 @@
A Django app for managing computer equipment.
## Installation
sudo apt-get install libmysqlclient-dev python-dev libldap2-dev libsasl2-dev bind9utils
virtualenv venv
. venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py runserver
## Features
* Creates DHCPD configuration files
* Creates DNS zone files for BIND
* TODO: Creates PXE config files (with random secret for use with Puppet autosign)
+3 -4
View File
@@ -1,9 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
import os, sys import os
import sys
if __name__ == "__main__": if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mdb.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mdbsite.settings")
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv) execute_from_command_line(sys.argv)
View File
File renamed without changes.
File renamed without changes.
+6
View File
@@ -0,0 +1,6 @@
from rest_framework.views import APIView
class ValidatePuppetHostSecret(APIView):
# TODO
pass
+9 -5
View File
@@ -6,7 +6,11 @@ from difflib import context_diff
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.core.mail import mail_admins from django.core.mail import mail_admins
from optparse import make_option from optparse import make_option
from commands import getstatusoutput try:
from subprocess import getstatusoutput
except ImportError:
from commands import getstatusoutput
from mdb.models import DhcpConfig from mdb.models import DhcpConfig
@@ -42,13 +46,13 @@ class Command(BaseCommand):
# do we need to do anything? # do we need to do anything?
if config.serial == config.active_serial and not force: if config.serial == config.active_serial and not force:
print "Nothing to do, serial is the same: %s" % config.serial print("Nothing to do, serial is the same: %s" % config.serial)
sys.exit(0) sys.exit(0)
# write to stdout # write to stdout
if output == sys.stdout: if output == sys.stdout:
print config.dhcpd_configuration() print(config.dhcpd_configuration())
print 'Not writing to file, serial not updated' print('Not writing to file, serial not updated')
return return
# read current file contents # read current file contents
@@ -71,7 +75,7 @@ class Command(BaseCommand):
tofile=config.serial, tofile=config.serial,
lineterm='')) lineterm=''))
print diff print(diff)
# update serial # update serial
old_serial = config.active_serial old_serial = config.active_serial
+9 -5
View File
@@ -7,8 +7,12 @@ from difflib import context_diff
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.core.mail import mail_admins from django.core.mail import mail_admins
from optparse import make_option from optparse import make_option
from commands import getstatusoutput try:
from mdb.models import * from subprocess import getstatusoutput
except ImportError:
from commands import getstatusoutput
from mdb.models import Domain, Ip4Subnet, Ip6Subnet
class Command(BaseCommand): class Command(BaseCommand):
@@ -43,7 +47,7 @@ class Command(BaseCommand):
# do the binaries exist? # do the binaries exist?
for f in (self.checkzone_bin, self.bind_bin): for f in (self.checkzone_bin, self.bind_bin):
if not os.path.isfile(f): if not os.path.isfile(f):
print "ERROR: no such file %s, exiting..." % f print("ERROR: no such file %s, exiting..." % f)
if not debug: if not debug:
sys.exit(1) sys.exit(1)
@@ -106,11 +110,11 @@ class Command(BaseCommand):
'diff': None, 'diff': None,
} }
print "updating %s %s [%d -> %d]" % ( print("updating %s %s [%d -> %d]" % (
zonetype, zonetype,
zone.domain_name, zone.domain_name,
zone.domain_active_serial, zone.domain_active_serial,
zone.domain_serial) zone.domain_serial))
# generate zone file contents # generate zone file contents
new = zone.zone_file_contents() new = zone.zone_file_contents()
+85
View File
@@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.core.validators
import re
class Migration(migrations.Migration):
dependencies = [
('mdb', '0005_auto_20150822_2204'),
]
operations = [
migrations.AlterModelOptions(
name='dhcpcustomfield',
options={'verbose_name': 'DHCP custom field'},
),
migrations.AlterField(
model_name='domain',
name='domain_admin',
field=models.EmailField(max_length=254),
),
migrations.AlterField(
model_name='domain',
name='domain_ipaddr',
field=models.GenericIPAddressField(protocol='IPv4'),
),
migrations.AlterField(
model_name='host',
name='hostname',
field=models.CharField(validators=[django.core.validators.RegexValidator(code='invalid', message='Enter a valid hostname', regex=re.compile('^(?!-)[-a-z0-9]+(?<!-)$', 34))], max_length=64),
),
migrations.AlterField(
model_name='interface',
name='ip4address',
field=models.OneToOneField(to='mdb.Ip4Address', null=True, blank=True),
),
migrations.AlterField(
model_name='interface',
name='macaddr',
field=models.CharField(validators=[django.core.validators.RegexValidator(code='invalid', message='Enter a valid MAC address', regex=re.compile('^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$', 34))], max_length=17),
),
migrations.AlterField(
model_name='ip4address',
name='address',
field=models.GenericIPAddressField(protocol='IPv4'),
),
migrations.AlterField(
model_name='ip4subnet',
name='dhcp_dynamic_end',
field=models.GenericIPAddressField(protocol='IPv4', null=True, blank=True),
),
migrations.AlterField(
model_name='ip4subnet',
name='dhcp_dynamic_start',
field=models.GenericIPAddressField(protocol='IPv4', null=True, blank=True),
),
migrations.AlterField(
model_name='ip4subnet',
name='domain_admin',
field=models.EmailField(max_length=254),
),
migrations.AlterField(
model_name='ip4subnet',
name='netmask',
field=models.GenericIPAddressField(protocol='IPv4'),
),
migrations.AlterField(
model_name='ip4subnet',
name='network',
field=models.GenericIPAddressField(protocol='IPv4'),
),
migrations.AlterField(
model_name='ip6subnet',
name='domain_admin',
field=models.EmailField(max_length=254),
),
migrations.AlterField(
model_name='operatingsystem',
name='arch',
field=models.CharField(max_length=255, choices=[('mips', 'MIPS'), ('arm', 'ARM'), ('broadcom', 'Broadcom'), ('rc32300', 'RC32300'), ('powerpc', 'PowerPC'), ('powerpc403ga', 'PowerPC403GA'), ('unknown', 'Unknown'), ('x86_64', 'x86-64'), ('i386', 'x86')], null=True, blank=True),
),
]
+59 -41
View File
@@ -2,31 +2,36 @@ from django.db import models
from django.db.models import Count from django.db.models import Count
from django.db.models.signals import post_save, pre_save, pre_delete from django.db.models.signals import post_save, pre_save, pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.encoding import python_2_unicode_compatible
from django.utils.six import u
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from validators import validate_hostname, validate_macaddr from mdb.validators import validate_hostname, validate_macaddr
import ipaddr import ipaddress
import datetime import datetime
import re import re
@python_2_unicode_compatible
class Nameserver(models.Model): class Nameserver(models.Model):
hostname = models.CharField(max_length=256) hostname = models.CharField(max_length=256)
def __unicode__(self): def __str__(self):
return self.hostname return self.hostname
@python_2_unicode_compatible
class MailExchange(models.Model): class MailExchange(models.Model):
priority = models.IntegerField() priority = models.IntegerField()
hostname = models.CharField(max_length=256) hostname = models.CharField(max_length=256)
def __unicode__(self): def __str__(self):
return "(" + str(self.priority) + ") " + self.hostname return "(" + str(self.priority) + ") " + self.hostname
@python_2_unicode_compatible
class Domain(models.Model): class Domain(models.Model):
domain_name = models.CharField(max_length=256) domain_name = models.CharField(max_length=256)
domain_soa = models.CharField(max_length=256) domain_soa = models.CharField(max_length=256)
@@ -38,14 +43,14 @@ class Domain(models.Model):
domain_expire = models.IntegerField(default=604800) domain_expire = models.IntegerField(default=604800)
domain_minimum_ttl = models.IntegerField(default=86400) domain_minimum_ttl = models.IntegerField(default=86400)
domain_admin = models.EmailField() domain_admin = models.EmailField()
domain_ipaddr = models.IPAddressField() domain_ipaddr = models.GenericIPAddressField(protocol='IPv4')
domain_filename = models.CharField(max_length=256) domain_filename = models.CharField(max_length=256)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
domain_nameservers = models.ManyToManyField(Nameserver) domain_nameservers = models.ManyToManyField(Nameserver)
domain_mailexchanges = models.ManyToManyField(MailExchange) domain_mailexchanges = models.ManyToManyField(MailExchange)
def __unicode__(self): def __str__(self):
return self.domain_name return self.domain_name
def num_records(self): def num_records(self):
@@ -63,6 +68,7 @@ class Domain(models.Model):
def __eq__(self, other): def __eq__(self, other):
if not other or not hasattr(other, 'domain_name'): if not other or not hasattr(other, 'domain_name'):
return False return False
return self.domain_name == other.domain_name return self.domain_name == other.domain_name
def zone_file_contents(self): def zone_file_contents(self):
@@ -93,12 +99,12 @@ class Domain(models.Model):
content += "; SRV records\n" content += "; SRV records\n"
for srv in self.domainsrvrecord_set.all(): for srv in self.domainsrvrecord_set.all():
content += unicode(srv) + "\n" content += u(srv) + "\n"
content += "; A records\n" content += "; A records\n"
for a in self.domainarecord_set.all(): for a in self.domainarecord_set.all():
content += unicode(a) + "\n" content += u(a) + "\n"
content += "; CNAME records \n" content += "; CNAME records \n"
@@ -108,7 +114,7 @@ class Domain(models.Model):
content += "; TXT records \n" content += "; TXT records \n"
for txt in self.domaintxtrecord_set.all(): for txt in self.domaintxtrecord_set.all():
content += unicode(txt) + "\n" content += u(txt) + "\n"
content += "; HOST records\n" content += "; HOST records\n"
@@ -126,6 +132,7 @@ class Domain(models.Model):
return content return content
@python_2_unicode_compatible
class DomainSrvRecord(models.Model): class DomainSrvRecord(models.Model):
srvce = models.CharField(max_length=64) srvce = models.CharField(max_length=64)
prot = models.CharField(max_length=64) prot = models.CharField(max_length=64)
@@ -137,42 +144,46 @@ class DomainSrvRecord(models.Model):
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self): def __str__(self):
return self.srvce + "." + self.prot + "." + self.name + ". IN SRV " \ return self.srvce + "." + self.prot + "." + self.name + ". IN SRV " \
+ str(self.priority) + " " + str(self.weight) + " " + \ + str(self.priority) + " " + str(self.weight) + " " + \
str(self.port) + " " + self.target + "." str(self.port) + " " + self.target + "."
@python_2_unicode_compatible
class DomainTxtRecord(models.Model): class DomainTxtRecord(models.Model):
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
target = models.CharField(max_length=256) target = models.CharField(max_length=256)
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self): def __str__(self):
return self.name + " TXT " + self.target return self.name + " TXT " + self.target
@python_2_unicode_compatible
class DomainCnameRecord(models.Model): class DomainCnameRecord(models.Model):
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
target = models.CharField(max_length=256) target = models.CharField(max_length=256)
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self): def __str__(self):
return self.name + " IN CNAME " + self.target return self.name + " IN CNAME " + self.target
@python_2_unicode_compatible
class DomainARecord(models.Model): class DomainARecord(models.Model):
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
target = models.CharField(max_length=256) target = models.CharField(max_length=256)
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self): def __str__(self):
return self.name + " IN A " + self.target return self.name + " IN A " + self.target
@python_2_unicode_compatible
class DhcpConfig(models.Model): class DhcpConfig(models.Model):
serial = models.IntegerField() serial = models.IntegerField()
active_serial = models.IntegerField() active_serial = models.IntegerField()
@@ -229,13 +240,14 @@ class DhcpConfig(models.Model):
return content return content
def __unicode__(self): def __str__(self):
return self.name return self.name
class Meta: class Meta:
verbose_name = 'DHCP config' verbose_name = 'DHCP config'
@python_2_unicode_compatible
class Ip6Subnet(models.Model): class Ip6Subnet(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
network = models.CharField(max_length=255) network = models.CharField(max_length=255)
@@ -254,7 +266,7 @@ class Ip6Subnet(models.Model):
domain_admin = models.EmailField() domain_admin = models.EmailField()
domain_filename = models.CharField(max_length=256) domain_filename = models.CharField(max_length=256)
def __unicode__(self): def __str__(self):
return self.network + " (" + self.name + ")" return self.network + " (" + self.name + ")"
def zone_file_contents(self, generate_unassigned=False): def zone_file_contents(self, generate_unassigned=False):
@@ -292,7 +304,7 @@ class Ip6Subnet(models.Model):
addr.interface.host.hostname, addr.interface.host.hostname,
addr.interface.domain.domain_name) addr.interface.domain.domain_name)
ip = ipaddr.IPv6Address(self.network + addr.address) ip = ipaddress.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) content += "%s\tPTR\t%s.\n" % (ip, hostname)
@@ -305,10 +317,11 @@ class Ip6Subnet(models.Model):
verbose_name = 'IPv6 subnet' verbose_name = 'IPv6 subnet'
@python_2_unicode_compatible
class Ip4Subnet(models.Model): class Ip4Subnet(models.Model):
name = models.CharField(max_length=256) name = models.CharField(max_length=256)
netmask = models.IPAddressField() netmask = models.GenericIPAddressField(protocol='IPv4')
network = models.IPAddressField() network = models.GenericIPAddressField(protocol='IPv4')
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
domain_name = models.CharField(max_length=255, editable=False) domain_name = models.CharField(max_length=255, editable=False)
domain_nameservers = models.ManyToManyField(Nameserver) domain_nameservers = models.ManyToManyField(Nameserver)
@@ -324,29 +337,29 @@ class Ip4Subnet(models.Model):
domain_filename = models.CharField(max_length=256) domain_filename = models.CharField(max_length=256)
dhcp_dynamic = models.BooleanField(default=False) dhcp_dynamic = models.BooleanField(default=False)
dhcp_dynamic_start = models.IPAddressField(null=True, blank=True) dhcp_dynamic_start = models.GenericIPAddressField(protocol='IPv4', null=True, blank=True)
dhcp_dynamic_end = models.IPAddressField(null=True, blank=True) dhcp_dynamic_end = models.GenericIPAddressField(protocol='IPv4', null=True, blank=True)
dhcp_config = models.ForeignKey(DhcpConfig) dhcp_config = models.ForeignKey(DhcpConfig)
def __unicode__(self): def __str__(self):
return self.network + " (" + self.name + ")" return self.network + " (" + self.name + ")"
def num_addresses(self): def num_addresses(self):
subnet = ipaddr.IPv4Network(self.network + "/" + self.netmask) subnet = ipaddress.IPv4Network(self.network + "/" + self.netmask)
return subnet.numhosts return subnet.numhosts
def broadcast_address(self): def broadcast_address(self):
subnet = ipaddr.IPv4Network(self.network + "/" + self.netmask) subnet = ipaddress.IPv4Network(self.network + "/" + self.netmask)
return subnet.broadcast return subnet.broadcast
def first_address(self): def first_address(self):
subnet = ipaddr.IPv4Network(self.network + "/" + self.netmask) subnet = ipaddress.IPv4Network(self.network + "/" + self.netmask)
return subnet.iterhosts().next() return subnet.iterhosts().next()
def last_address(self): def last_address(self):
subnet = ipaddr.IPv4Network(self.network + "/" + self.netmask) subnet = ipaddress.IPv4Network(self.network + "/" + self.netmask)
for curr in subnet.iterhosts(): for curr in subnet.iterhosts():
pass # horribly ineficcient pass # horribly inefficient
return curr return curr
@@ -405,18 +418,20 @@ class Ip4Subnet(models.Model):
verbose_name = 'IPv4 subnet' verbose_name = 'IPv4 subnet'
@python_2_unicode_compatible
class DhcpOption(models.Model): class DhcpOption(models.Model):
key = models.CharField(max_length=255) key = models.CharField(max_length=255)
value = models.CharField(max_length=255) value = models.CharField(max_length=255)
ip4subnet = models.ForeignKey(Ip4Subnet) ip4subnet = models.ForeignKey(Ip4Subnet)
def __unicode__(self): def __str__(self):
return self.key + " " + self.value return self.key + " " + self.value
class Meta: class Meta:
verbose_name = 'DHCP option' verbose_name = 'DHCP option'
@python_2_unicode_compatible
class DhcpCustomField(models.Model): class DhcpCustomField(models.Model):
value = models.CharField(max_length=255) value = models.CharField(max_length=255)
ip4subnet = models.ForeignKey(Ip4Subnet) ip4subnet = models.ForeignKey(Ip4Subnet)
@@ -425,22 +440,20 @@ class DhcpCustomField(models.Model):
verbose_name = 'DHCP custom field' verbose_name = 'DHCP custom field'
@python_2_unicode_compatible
class Ip4Address(models.Model): class Ip4Address(models.Model):
subnet = models.ForeignKey(Ip4Subnet) subnet = models.ForeignKey(Ip4Subnet)
address = models.IPAddressField() address = models.GenericIPAddressField(protocol='IPv4')
last_contact = models.DateTimeField(null=True, blank=True) last_contact = models.DateTimeField(null=True, blank=True)
ping_avg_rtt = models.FloatField(null=True, blank=True) ping_avg_rtt = models.FloatField(null=True, blank=True)
def __unicode__(self): def __str__(self):
# FIXME: generates 2 SQL queries # FIXME: generates 2 SQL queries
_if = self.interface_set.all() _if = self.interface_set.all()
if not _if: if not _if:
return self.address return self.address
return "{} ({})".format( return "{} ({})".format(self.address, _if.get().host.hostname)
self.address,
_if.get().host.hostname
)
def assigned_to_host(self): def assigned_to_host(self):
return self.interface_set.get().host return self.interface_set.get().host
@@ -452,11 +465,12 @@ class Ip4Address(models.Model):
verbose_name_plural = 'IPv4 addresses' verbose_name_plural = 'IPv4 addresses'
@python_2_unicode_compatible
class HostType(models.Model): class HostType(models.Model):
host_type = models.CharField(max_length=64) host_type = models.CharField(max_length=64)
description = models.CharField(max_length=1024) description = models.CharField(max_length=1024)
def __unicode__(self): def __str__(self):
return self.host_type return self.host_type
def num_members(self): def num_members(self):
@@ -466,6 +480,7 @@ class HostType(models.Model):
ordering = ("host_type",) ordering = ("host_type",)
@python_2_unicode_compatible
class OperatingSystem(models.Model): class OperatingSystem(models.Model):
OS_ARCHITECTURES = ( OS_ARCHITECTURES = (
('mips', _('MIPS')), ('mips', _('MIPS')),
@@ -482,13 +497,14 @@ class OperatingSystem(models.Model):
version = models.CharField(max_length=64) version = models.CharField(max_length=64)
arch = models.CharField(max_length=255, choices=OS_ARCHITECTURES, blank=True, null=True) arch = models.CharField(max_length=255, choices=OS_ARCHITECTURES, blank=True, null=True)
def __unicode__(self): def __str__(self):
return self.name + " " + self.version + " (" + self.arch + ")" return self.name + " " + self.version + " (" + self.arch + ")"
class Meta: class Meta:
ordering = ("name", "version") ordering = ("name", "version")
@python_2_unicode_compatible
class Host(models.Model): class Host(models.Model):
location = models.CharField(max_length=1024) location = models.CharField(max_length=1024)
brand = models.CharField(max_length=1024) brand = models.CharField(max_length=1024)
@@ -507,7 +523,7 @@ class Host(models.Model):
kerberos_principal_name = models.CharField(max_length=256, editable=False) kerberos_principal_name = models.CharField(max_length=256, editable=False)
kerberos_principal_created_date = models.DateTimeField(null=True, blank=True, editable=False) kerberos_principal_created_date = models.DateTimeField(null=True, blank=True, editable=False)
def __unicode__(self): def __str__(self):
return self.hostname return self.hostname
def in_domain(self): def in_domain(self):
@@ -531,23 +547,25 @@ class Host(models.Model):
return ",".join(addresses) return ",".join(addresses)
@python_2_unicode_compatible
class Interface(models.Model): class Interface(models.Model):
name = models.CharField(max_length=128) name = models.CharField(max_length=128)
macaddr = models.CharField(max_length=17, validators=[validate_macaddr]) macaddr = models.CharField(max_length=17, validators=[validate_macaddr])
pxe_filename = models.CharField(max_length=64, blank=True) pxe_filename = models.CharField(max_length=64, blank=True)
dhcp_client = models.BooleanField(default=False) dhcp_client = models.BooleanField(default=False)
host = models.ForeignKey(Host) host = models.ForeignKey(Host)
ip4address = models.ForeignKey(Ip4Address, blank=True, null=True, unique=True) ip4address = models.OneToOneField(Ip4Address, blank=True, null=True)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
domain = models.ForeignKey(Domain) domain = models.ForeignKey(Domain)
def __unicode__(self): def __str__(self):
return "%s (%s on %s)" % (self.macaddr, self.name, self.host.hostname) return "%s (%s on %s)" % (self.macaddr, self.name, self.host.hostname)
def ipv6_enabled(self): def ipv6_enabled(self):
return self.ip6address_set.count() > 0 return self.ip6address_set.count() > 0
@python_2_unicode_compatible
class Ip6Address(models.Model): class Ip6Address(models.Model):
subnet = models.ForeignKey(Ip6Subnet) subnet = models.ForeignKey(Ip6Subnet)
address = models.CharField(max_length=64) address = models.CharField(max_length=64)
@@ -556,7 +574,7 @@ class Ip6Address(models.Model):
def full_address(self): def full_address(self):
return self.subnet.network + self.address return self.subnet.network + self.address
def __unicode__(self): def __str__(self):
return "%s (%s on %s)" % ( return "%s (%s on %s)" % (
self.full_address(), self.full_address(),
self.interface.name, self.interface.name,
@@ -604,7 +622,7 @@ def create_ips_for_subnet(sender, instance, created, **kwargs):
if not created: if not created:
return return
subnet = ipaddr.IPv4Network(instance.network + "/" + instance.netmask) subnet = ipaddress.IPv4Network(instance.network + "/" + instance.netmask)
for addr in subnet.iterhosts(): for addr in subnet.iterhosts():
address = Ip4Address(address=str(addr), subnet=instance) address = Ip4Address(address=str(addr), subnet=instance)
@@ -642,7 +660,7 @@ def set_domain_name_for_ipv6_subnet(sender, instance, **kwargs):
if len(instance.domain_name) > 0: if len(instance.domain_name) > 0:
return return
network = ipaddr.IPv6Address("%s::" % instance.network) network = ipaddress.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"
-191
View File
@@ -1,191 +0,0 @@
# Django settings for dns_mdb project.
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('System Administrator', 'sysadmin@example.com'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'mdb.db', # Or path to database file if using sqlite3.
'USER': 'mdb', # Not used with sqlite3.
'PASSWORD': 'mdb', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '3306', # Set to empty string for default. Not used with sqlite3.
}
}
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'Europe/Oslo'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
USE_L10N = True
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/media/'
# Additional locations of static files
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
# Make this unique, and don't share it with anybody.
SECRET_KEY = '@4ps=ebofcpv8sb#y7gm896=l&l*u0u-pgo7bcdj%+(k+2lqnl'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'urls'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'mdb',
'suit',
'django.contrib.admin',
)
# Defines a test runner
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
EMAIL_SUBJECT_PREFIX = '[MDB] '
EMAIL_HOST = 'smtp.example.com'
EMAIL_PORT = 25
# for django-suit
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
TEMPLATE_CONTEXT_PROCESSORS = TCP + (
'django.core.context_processors.request',
)
# django-suit configuration
SUIT_CONFIG = {
# header
'ADMIN_NAME': 'MDB',
'HEADER_DATE_FORMAT': 'l, Y-m-d',
'HEADER_TIME_FORMAT': 'H:i',
# forms
# 'SHOW_REQUIRED_ASTERISK': True, # Default True
# 'CONFIRM_UNSAVED_CHANGES': True, # Default True
# menu
'SEARCH_URL': '/admin/mdb/host/',
# 'MENU_ICONS': {
# 'sites': 'icon-leaf',
# 'auth': 'icon-lock',
# },
# 'MENU_OPEN_FIRST_CHILD': True, # Default True
# 'MENU_EXCLUDE': ('auth.group',),
'MENU': (
{'app': 'mdb', 'label': 'MDB', 'url': 'mdb.host'},
{
'label': 'Settings',
'icon': 'icon-cog',
'models': ('auth.user', 'auth.group')
},
),
# misc
'LIST_PER_PAGE': 30
}
+10 -14
View File
@@ -1,16 +1,12 @@
""" from django.core.urlresolvers import reverse
This file demonstrates writing tests using the unittest module. These will pass from rest_framework.test import APITestCase
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase): class APITestCases(APITestCase):
def test_basic_addition(self): def test_validate_puppet_host_by_secret(self):
""" data = {
Tests that 1 + 1 always equals 2. 'secret': 'something',
""" 'certname': 'arnold.neuf.no'
self.assertEqual(1 + 1, 2) }
res = self.client.post(reverse('api-validate-host-secret'), data)
self.fail()
+128
View File
@@ -0,0 +1,128 @@
import os
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('System Administrator', 'sysadmin@example.com'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite3',
}
}
TIME_ZONE = 'Europe/Oslo'
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
USE_I18N = True
USE_L10N = True
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
ADMIN_MEDIA_PREFIX = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
)
# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
# Make this unique, and don't share it with anybody.
SECRET_KEY = '@4ps=ebofcpv8sb#y7gm896=l&l*u0u-pgo7bcdj%+(k+2lqnl'
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'mdbsite.urls'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'mdb',
'suit',
'django.contrib.admin',
)
# Defines a test runner
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
EMAIL_SUBJECT_PREFIX = '[MDB] '
TEMPLATE_CONTEXT_PROCESSORS = TCP + (
'django.core.context_processors.request', # for django-suit
)
# django-suit configuration
SUIT_CONFIG = {
# header
'ADMIN_NAME': 'MDB',
'HEADER_DATE_FORMAT': 'l, Y-m-d',
'HEADER_TIME_FORMAT': 'H:i',
# forms
# 'SHOW_REQUIRED_ASTERISK': True, # Default True
# 'CONFIRM_UNSAVED_CHANGES': True, # Default True
# menu
'SEARCH_URL': '/admin/mdb/host/',
# 'MENU_ICONS': {
# 'sites': 'icon-leaf',
# 'auth': 'icon-lock',
# },
# 'MENU_OPEN_FIRST_CHILD': True, # Default True
# 'MENU_EXCLUDE': ('auth.group',),
'MENU': (
{'app': 'mdb', 'label': 'MDB', 'url': 'mdb.host'},
{
'label': 'Settings',
'icon': 'icon-cog',
'models': ('auth.user', 'auth.group')
},
),
# misc
'LIST_PER_PAGE': 30
}
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
'PAGINATE_BY': 10
}
try:
from local_settings import *
except ImportError:
pass
+5 -4
View File
@@ -1,14 +1,15 @@
from django.conf.urls import patterns, include, url from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from mdb.api.views import ValidatePuppetHostSecret
admin.autodiscover() admin.autodiscover()
urlpatterns = patterns( urlpatterns = [
'',
url(r'^$', RedirectView.as_view(url='admin/')), url(r'^$', RedirectView.as_view(url='admin/')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
) url(r'^api/validate-host-secret', ValidatePuppetHostSecret.as_view(), name='api-validate-host-secret')
]
urlpatterns += staticfiles_urlpatterns() urlpatterns += staticfiles_urlpatterns()
View File
File renamed without changes.
+5 -4
View File
@@ -1,5 +1,6 @@
Django>=1.7,<1.8 Django>=1.8,<1.9
MySQL-python==1.2.5
ipaddr==2.1.11
django-auth-ldap django-auth-ldap
django-suit django-suit==0.2.15
djangorestframework==3.2.4
ipaddress==1.0.14
mysqlclient==1.3.6