--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pvl/config/bind/model.py Sun Jul 12 02:14:34 2009 +0300
@@ -0,0 +1,188 @@
+"""
+ High-level BIND stuff
+"""
+
+from __future__ import with_statement
+
+from . import zone
+
+import os.path, datetime
+
+DEFAULT_TTL = zone.Interval(3600)
+
+class Settings (object) :
+ """
+ A set of basic settings for a zone, mostly default TTL/refresh/retry/expire/minimum settings
+ """
+
+ def __init__ (self, ttl, hostmaster, refresh, retry, expire, minimum) :
+ self.ttl = ttl
+ self.hostmaster = hostmaster
+ self.refresh = refresh
+ self.retry = retry
+ self.expire = expire
+ self.minimum = minimum
+
+class AutoSerial (object) :
+ """
+ Automatically generate the next serial to use by loading it from a file.
+
+ The generated serials are in YYYYMMDDXX format.
+ """
+
+ def __init__ (self, path) :
+ """
+ Load the current serial
+
+ @param path the path to the serial file
+ """
+
+ # store
+ self.path = path
+
+ # load it
+ # XXX: locking
+ serial = self.read()
+
+ # current date
+ today = datetime.date.today()
+
+ # parse it
+ if serial :
+ date, code = self.parse(serial)
+
+ else :
+ date, code = today, 0
+
+ # increment it
+ date, code = self.next(date, code)
+
+ # format it
+ self._serial = self.build(date, code)
+
+ # write it out
+ self.write(self._serial)
+
+ def parse (self, serial) :
+ """
+ Parse the given serial into a (datetime.date, code) format
+ """
+
+ # build it into a date
+ date = datetime.date(
+ year = int(serial[0:4]),
+ month = int(serial[4:6]),
+ day = int(serial[6:8])
+ )
+
+ code = int(serial[8:])
+
+ return date, code
+
+ def next (self, date, code) :
+ """
+ Return the next valid serial following the given one
+ """
+
+ # current date
+ today = datetime.date.today()
+
+ # now to increment?
+ if date < today :
+ # jump to today's first serial
+ date = today
+ code = 0
+
+ else :
+ # today or overflowed into the future, just increment the code
+ code += 1
+
+ # code overflowed into next day?
+ if code > 99 :
+ date += datetime.timedelta(days=1)
+ code = 0
+
+ # ok
+ return date, code
+
+ def build (self, date, code) :
+ """
+ Build a serial code the given date/code
+ """
+
+ assert 0 <= code <= 99
+
+ return "%s%02d" % (date.strftime("%Y%m%d"), code)
+
+ def read (self) :
+ """
+ Read the current serial, returning it, or None, if not found...
+ """
+
+ # if it doesn't exist, default
+ if not os.path.exists(self.path) :
+ return None
+
+ # read it
+ with open(self.path) as fh :
+ return fh.read().strip()
+
+ def write (self, serial) :
+ """
+ Write a new serial
+ """
+
+ with open(self.path, 'w') as fh :
+ fh.write("%s\n" % (serial, ))
+
+ def serial (self) :
+ """
+ Return a new, unused serial code (before __init__)
+ """
+
+ return self._serial
+
+class Domain (zone.Zone) :
+ """
+ A domain has a skeleton of stuff defined, but the rest is $INCLUDE'd from elsewhere, which is useful for
+ multi-domain setups where the domains are mostly similar
+ """
+
+ def __init__ (self, domain, path, nameservers, mailservers, serial, settings, include=None, objs=None) :
+ """
+ @param domain the domain name
+ @param path the path to the zone file
+ @param nameservers list of nameservers as labels
+ @param mailservers list of (pref, label) tuples for MX records
+ @param serial the serial code to use
+ @param settings the TTL/SOA settings to use
+ @param include the optional zonefile to include
+ @param objs the optional other objects to add to the zonefile
+ """
+
+ super(Domain, self).__init__(domain, path)
+
+ # the default TTL
+ self.add_directive(zone.TTLDirective(settings.ttl))
+
+ # the SOA record
+ self.add_record(zone.SOA(None, nameservers[0],
+ settings.hostmaster, serial, settings.refresh, settings.retry, settings.expire, settings.minimum
+ ))
+
+ # the NS records
+ for label in nameservers :
+ self.add_record(zone.NS(None, label))
+
+ # the MX records
+ for pref, label in mailservers :
+ self.add_record(zone.MX(None, pref, label))
+
+ # include?
+ if include :
+ self.add_directive(zone.IncludeDirective(include))
+
+ if objs :
+ for obj in objs :
+ self.add_obj(obj)
+