easyzone-1.2.2/000775 000765 000024 00000000000 11566175116 013637 5ustar00chrisstaff000000 000000 easyzone-1.2.2/easyzone/000775 000765 000024 00000000000 11566175116 015474 5ustar00chrisstaff000000 000000 easyzone-1.2.2/easyzone.egg-info/000775 000765 000024 00000000000 11566175116 017166 5ustar00chrisstaff000000 000000 easyzone-1.2.2/PKG-INFO000664 000765 000024 00000007322 11566175116 014740 0ustar00chrisstaff000000 000000 Metadata-Version: 1.0 Name: easyzone Version: 1.2.2 Summary: Easy Zone - DNS Zone abstraction module Home-page: http://www.psychofx.com/easyzone/ Author: Chris Miles Author-email: miles.chris@gmail.com License: MIT Description: easyzone ======== Overview -------- Easyzone is a package to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. http://www.psychofx.com/easyzone/ http://pypi.python.org/pypi/easyzone https://bitbucket.org/chrismiles/easyzone/ Main features: * A high-level abstraction on top of dnspython. * Load a zone file into objects. * Modify/add/delete zone/record objects. * Save back to zone file. * Auto-update serial (if necessary). Requirements ------------ * dnspython - http://www.dnspython.org/ Build/Test/Install ------------------ Build:: $ python setup.py build Test:: $ python setup.py test Install:: $ python setup.py install OR with setuptools:: $ easy_install easyzone Examples -------- easyzone:: >>> from easyzone import easyzone >>> z = easyzone.zone_from_file('example.com', '/var/namedb/example.com') >>> z.domain 'example.com.' >>> z.root.soa.serial 2007012902L >>> z.root.records('NS').items ['ns1.example.com.', 'ns2.example.com.'] >>> z.root.records('MX').items [(10, 'mail.example.com.'), (20, 'mail2.example.com.')] >>> z.names['foo.example.com.'].records('A').items ['10.0.0.1'] >>> ns = z.root.records('NS') >>> ns.add('ns3.example.com.') >>> ns.items ['ns1.example.com.', 'ns2.example.com.', 'ns3.example.com.'] >>> ns.delete('ns2.example.com') >>> ns.items ['ns1.example.com.', 'ns3.example.com.'] >>> z.save(autoserial=True) ZoneCheck:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ZoneReload:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Internet :: Name Service (DNS) Classifier: Topic :: System :: Systems Administration easyzone-1.2.2/._README.txt000664 000765 000024 00000000272 11566174622 015554 0ustar00chrisstaff000000 000000 Mac OS X  2ˆºATTR2c©º˜"˜"com.macromates.caret{ column = 0; line = 23; }easyzone-1.2.2/README.txt000664 000765 000024 00000004770 11566174622 015346 0ustar00chrisstaff000000 000000 easyzone ======== Overview -------- Easyzone is a package to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. Main features: * A high-level abstraction on top of dnspython. * Load a zone file into objects. * Modify/add/delete zone/record objects. * Save back to zone file. * Auto-update serial (if necessary). http://www.psychofx.com/easyzone/ http://pypi.python.org/pypi/easyzone https://bitbucket.org/chrismiles/easyzone/ Requirements ------------ * dnspython - http://www.dnspython.org/ Build/Test/Install ------------------ Build:: $ python setup.py build Test:: $ python setup.py test Install:: $ python setup.py install OR with setuptools:: $ easy_install easyzone Examples -------- easyzone:: >>> from easyzone import easyzone >>> z = easyzone.zone_from_file('example.com', '/var/namedb/example.com') >>> z.domain 'example.com.' >>> z.root.soa.serial 2007012902L >>> z.root.records('NS').items ['ns1.example.com.', 'ns2.example.com.'] >>> z.root.records('MX').items [(10, 'mail.example.com.'), (20, 'mail2.example.com.')] >>> z.names['foo.example.com.'].records('A').items ['10.0.0.1'] >>> ns = z.root.records('NS') >>> ns.add('ns3.example.com.') >>> ns.items ['ns1.example.com.', 'ns2.example.com.', 'ns3.example.com.'] >>> ns.delete('ns2.example.com') >>> ns.items ['ns1.example.com.', 'ns3.example.com.'] >>> z.save(autoserial=True) ZoneCheck:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ZoneReload:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> easyzone-1.2.2/setup.cfg000664 000765 000024 00000000073 11566175116 015460 0ustar00chrisstaff000000 000000 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 easyzone-1.2.2/._setup.py000664 000765 000024 00000000272 11566174607 015573 0ustar00chrisstaff000000 000000 Mac OS X  2ˆºATTR2c¯º˜"˜"com.macromates.caret{ column = 0; line = 94; }easyzone-1.2.2/setup.py000664 000765 000024 00000012544 11566174607 015363 0ustar00chrisstaff000000 000000 # # setup.py for easyzone package # # Created by Chris Miles on 2007-01-29. # Copyright (c) 2007-2011 Chris Miles. All rights reserved. # try: from setuptools import setup, Command use_setuptools = True except ImportError: from distutils.core import setup, Command use_setuptools = False from glob import glob import os import sys from unittest import TextTestRunner, TestLoader from easyzone.easyzone import __version__ class TestCommand(Command): user_options = [] def initialize_options(self): self._dir = os.getcwd() def finalize_options(self): build = self.get_finalized_command('build') self.build_purelib = build.build_purelib self.build_platlib = build.build_platlib def run(self): '''Finds all the tests modules in tests/, and runs them. ''' sys.path.insert(0, self.build_purelib) sys.path.insert(0, self.build_platlib) testfiles = [] for t in glob(os.path.join(self._dir, 'tests', '*.py')): if not t.endswith('__init__.py'): testfiles.append('.'.join( ['tests', os.path.splitext(os.path.basename(t))[0]]) ) tests = TestLoader().loadTestsFromNames(testfiles) t = TextTestRunner(verbosity = 2) t.run(tests) class CleanCommand(Command): user_options = [] def initialize_options(self): self._clean_me = [] for root, dirs, files in os.walk('.'): for f in files: if f.endswith('.pyc'): self._clean_me.append(os.path.join(root, f)) def finalize_options(self): pass def run(self): for clean_me in self._clean_me: try: os.unlink(clean_me) except: pass setup_args = dict( name = 'easyzone', version = __version__, author = 'Chris Miles', author_email = 'miles.chris@gmail.com', description = 'Easy Zone - DNS Zone abstraction module', long_description = '''\ easyzone ======== Overview -------- Easyzone is a package to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. http://www.psychofx.com/easyzone/ http://pypi.python.org/pypi/easyzone https://bitbucket.org/chrismiles/easyzone/ Main features: * A high-level abstraction on top of dnspython. * Load a zone file into objects. * Modify/add/delete zone/record objects. * Save back to zone file. * Auto-update serial (if necessary). Requirements ------------ * dnspython - http://www.dnspython.org/ Build/Test/Install ------------------ Build:: $ python setup.py build Test:: $ python setup.py test Install:: $ python setup.py install OR with setuptools:: $ easy_install easyzone Examples -------- easyzone:: >>> from easyzone import easyzone >>> z = easyzone.zone_from_file('example.com', '/var/namedb/example.com') >>> z.domain 'example.com.' >>> z.root.soa.serial 2007012902L >>> z.root.records('NS').items ['ns1.example.com.', 'ns2.example.com.'] >>> z.root.records('MX').items [(10, 'mail.example.com.'), (20, 'mail2.example.com.')] >>> z.names['foo.example.com.'].records('A').items ['10.0.0.1'] >>> ns = z.root.records('NS') >>> ns.add('ns3.example.com.') >>> ns.items ['ns1.example.com.', 'ns2.example.com.', 'ns3.example.com.'] >>> ns.delete('ns2.example.com') >>> ns.items ['ns1.example.com.', 'ns3.example.com.'] >>> z.save(autoserial=True) ZoneCheck:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ZoneReload:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> ''', url = 'http://www.psychofx.com/easyzone/', packages = ['easyzone'], cmdclass = { 'test': TestCommand, 'clean': CleanCommand }, ) if use_setuptools: setup_args.update(dict( classifiers=[ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Topic :: Internet :: Name Service (DNS)", "Topic :: System :: Systems Administration", ], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers keywords='', license='MIT', include_package_data=True, zip_safe=False, install_requires=[ # -*- Extra requirements: -*- "dnspython", ], entry_points=""" # -*- Entry points: -*- """, )) setup(**setup_args) easyzone-1.2.2/easyzone.egg-info/dependency_links.txt000664 000765 000024 00000000001 11566175116 023234 0ustar00chrisstaff000000 000000 easyzone-1.2.2/easyzone.egg-info/entry_points.txt000664 000765 000024 00000000051 11566175116 022460 0ustar00chrisstaff000000 000000 # -*- Entry points: -*- easyzone-1.2.2/easyzone.egg-info/not-zip-safe000664 000765 000024 00000000001 11566174724 021420 0ustar00chrisstaff000000 000000 easyzone-1.2.2/easyzone.egg-info/PKG-INFO000664 000765 000024 00000007322 11566175116 020267 0ustar00chrisstaff000000 000000 Metadata-Version: 1.0 Name: easyzone Version: 1.2.2 Summary: Easy Zone - DNS Zone abstraction module Home-page: http://www.psychofx.com/easyzone/ Author: Chris Miles Author-email: miles.chris@gmail.com License: MIT Description: easyzone ======== Overview -------- Easyzone is a package to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. http://www.psychofx.com/easyzone/ http://pypi.python.org/pypi/easyzone https://bitbucket.org/chrismiles/easyzone/ Main features: * A high-level abstraction on top of dnspython. * Load a zone file into objects. * Modify/add/delete zone/record objects. * Save back to zone file. * Auto-update serial (if necessary). Requirements ------------ * dnspython - http://www.dnspython.org/ Build/Test/Install ------------------ Build:: $ python setup.py build Test:: $ python setup.py test Install:: $ python setup.py install OR with setuptools:: $ easy_install easyzone Examples -------- easyzone:: >>> from easyzone import easyzone >>> z = easyzone.zone_from_file('example.com', '/var/namedb/example.com') >>> z.domain 'example.com.' >>> z.root.soa.serial 2007012902L >>> z.root.records('NS').items ['ns1.example.com.', 'ns2.example.com.'] >>> z.root.records('MX').items [(10, 'mail.example.com.'), (20, 'mail2.example.com.')] >>> z.names['foo.example.com.'].records('A').items ['10.0.0.1'] >>> ns = z.root.records('NS') >>> ns.add('ns3.example.com.') >>> ns.items ['ns1.example.com.', 'ns2.example.com.', 'ns3.example.com.'] >>> ns.delete('ns2.example.com') >>> ns.items ['ns1.example.com.', 'ns3.example.com.'] >>> z.save(autoserial=True) ZoneCheck:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ZoneReload:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: License :: OSI Approved :: MIT License Classifier: Topic :: Internet :: Name Service (DNS) Classifier: Topic :: System :: Systems Administration easyzone-1.2.2/easyzone.egg-info/requires.txt000664 000765 000024 00000000011 11566175116 021556 0ustar00chrisstaff000000 000000 dnspythoneasyzone-1.2.2/easyzone.egg-info/SOURCES.txt000664 000765 000024 00000000515 11566175116 021053 0ustar00chrisstaff000000 000000 README.txt setup.py easyzone/__init__.py easyzone/easyzone.py easyzone/zone_check.py easyzone/zone_reload.py easyzone.egg-info/PKG-INFO easyzone.egg-info/SOURCES.txt easyzone.egg-info/dependency_links.txt easyzone.egg-info/entry_points.txt easyzone.egg-info/not-zip-safe easyzone.egg-info/requires.txt easyzone.egg-info/top_level.txteasyzone-1.2.2/easyzone.egg-info/top_level.txt000664 000765 000024 00000000011 11566175116 021710 0ustar00chrisstaff000000 000000 easyzone easyzone-1.2.2/easyzone/__init__.py000664 000765 000024 00000003615 11566173537 017617 0ustar00chrisstaff000000 000000 """\ Easyzone is a package to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. Examples ======== easyzone:: >>> from easyzone import easyzone >>> z = easyzone.zone_from_file('example.com', '/var/namedb/example.com') >>> z.domain 'example.com.' >>> z.root.soa.serial 2007012902L >>> z.root.records('NS').items ['ns1.example.com.', 'ns2.example.com.'] >>> z.root.records('MX').items [(10, 'mail.example.com.'), (20, 'mail2.example.com.')] >>> z.names['foo.example.com.'].records('A').items ['10.0.0.1'] >>> ns = z.root.records('NS') >>> ns.add('ns3.example.com.') >>> ns.items ['ns1.example.com.', 'ns2.example.com.', 'ns3.example.com.'] >>> ns.delete('ns2.example.com') >>> ns.items ['ns1.example.com.', 'ns3.example.com.'] >>> z.save(autoserial=True) ZoneCheck:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ZoneReload:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> """easyzone-1.2.2/easyzone/._easyzone.py000664 000765 000024 00000000272 11566174465 020127 0ustar00chrisstaff000000 000000 Mac OS X  2ˆºATTR2c¬º˜"˜"com.macromates.caret{ column = 0; line = 13; }easyzone-1.2.2/easyzone/easyzone.py000664 000765 000024 00000023667 11566174465 017727 0ustar00chrisstaff000000 000000 # encoding: utf-8 '''easyzone A module to manage the common record types of a zone file, including SOA records. This module sits on top of the dnspython package and provides a higher level abstraction for common zone file manipulation use cases. ''' __author__ = 'Chris Miles' __copyright__ = '(c) Chris Miles 2007-2011' __version__ = '1.2.2' # ---- Imports ---- # - Python Modules - from time import localtime, strftime, time import types # - dnspython Modules - http://www.dnspython.org/ try: import dns.zone except ImportError: import sys sys.stderr.write("Requires dns module from http://www.dnspython.org/\n") sys.exit(1) import dns.rdtypes.ANY.CNAME import dns.rdtypes.ANY.NS import dns.rdtypes.ANY.MX import dns.rdtypes.IN.A import dns.rdtypes.ANY.TXT # ---- Exceptions ---- class ZoneError(Exception): '''An error from easyzone.Zone''' class NameError(Exception): '''An error from easyzone.Name''' class RecordsError(Exception): '''An error from easyzone.Records''' # ---- Classes ---- class SOA(object): '''Represents the SOA fields of the root node of a Zone. ''' def __init__(self, soa): self._soa = soa def get_mname(self): return str(self._soa.mname) def set_mname(self, value): name = dns.name.Name( value.split('.') ) self._soa.mname = name mname = property(get_mname, set_mname) def get_rname(self): return str(self._soa.rname) def set_rname(self, value): name = dns.name.Name( value.split('.') ) self._soa.rname = name rname = property(get_rname, set_rname) def get_serial(self): return self._soa.serial def set_serial(self, value): self._soa.serial = value serial = property(get_serial, set_serial) def get_refresh(self): return self._soa.refresh def set_refresh(self, value): self._soa.refresh = value refresh = property(get_refresh, set_refresh) def get_retry(self): return self._soa.retry def set_retry(self, value): self._soa.retry = value retry = property(get_retry, set_retry) def get_expire(self): return self._soa.expire def set_expire(self, value): self._soa.expire = value expire = property(get_expire, set_expire) def get_minttl(self): return self._soa.minimum def set_minttl(self, value): self._soa.minimum = value minttl = property(get_minttl, set_minttl) class Records(object): '''Represents the records associated with a name node. Record items are common DNS types such as 'A', 'MX', 'NS', etc. ''' def __init__(self, rectype, rdataset): self.type = rectype self._rdataset = rdataset def add(self, item): if self.type == 'MX': assert type(item) == types.TupleType assert len(item) == 2 assert type(item[0]) == types.IntType assert type(item[1]) == types.StringType elif self.type == 'TXT': assert type(item) == types.StringType if item.startswith('"') and item.endswith('"'): # strip quotes off both ends; dns module will add them automatically item = item[1:-1] else: assert type(item) == types.StringType rd = _new_rdata(self.type, item) self._rdataset.add(rd) def delete(self, item): rd = _new_rdata(self.type, item) try: self._rdataset.remove(rd) except ValueError: raise RecordsError("No such item in record: %s" %item) def __iter__(self): self._item_iter = iter(self._rdataset.items) return self def next(self): if self.type == 'MX': r = self._item_iter.next() return (r.preference, str(r.exchange)) else: return str(self._item_iter.next()) def get_items(self): return [r for r in self] items = property(get_items) class Name(object): '''Represents a name node within a zone file. This could be the root node (the zone itself) or a hostname or subdomain node. Each node can consist of one or more records of various types, e.g. 'MX', 'A', 'NS', etc. If `node` is a dns.node object then the records associated with that node will be available as the `records` attribute. If the node contains SOA fields (i.e. the root ('@') node) then the `soa` attribute points to an SOA object. ''' def __init__(self, name, node=None, ttl=None): self.name = name self.soa = None self.ttl = ttl self._node = node if node: soa = soa_from_node(node) if soa: self.soa = SOA(soa) def records(self, rectype, create=False, ttl=None): typeval = dns.rdatatype._by_text.get(rectype, None) if typeval is None: raise NameError("Invalid type: %s" %rectype) r = self._node.get_rdataset(dns.rdataclass.IN, typeval, create=create) if r is None: return None if self.ttl and r.ttl == 0: r.update_ttl(self.ttl) rec = Records(rectype, r) return rec def clear_all_records(self, exclude=None): '''Clear all the records for this name node. ''' if exclude is None: self._node.rdatasets = [] else: exclude_type = dns.rdatatype._by_text.get(exclude, None) if exclude_type is None: raise NameError("Invalid exclude: %s" % exclude) for r in self._node.rdatasets: if r.rdtype != exclude_type: self._node.rdatasets.remove(r) class Zone(object): '''Represents a DNS zone. ''' def __init__(self, domain): if not domain or not isinstance(domain, types.StringTypes): raise ZoneError('Invalid domain') if domain[-1] != '.': domain = domain + '.' self.domain = domain self._zone = None def load_from_file(self, filename): '''Load the details of a zone from zone file `filename`. ''' self.filename = filename self._zone = dns.zone.from_file(filename, self.domain, relativize=False) def get_root(self): '''Return the root ("@") name of the zone as a Name object. ''' if not self._zone: return None return Name('@', self._zone[self.domain]) root = property(get_root) def get_names(self): '''Return a dictionary of names, keyed by name as string, with values as corresponding Name objects.''' if not self._zone: return None default_ttl = soa_from_node(self._zone[self.domain]).minimum names = {} for name in self._zone.keys(): name = str(name) nameobj = Name(name, self._zone[name], default_ttl) names[name] = nameobj return names names = property(get_names) def add_name(self, name): '''Add a new name (hostname) to the zone. If a node with the same name already exists it is returned instead. ''' node = self._zone.get_node(name, create=True) if node is None: raise ZoneError("Could not create node named: %s" %name) def delete_name(self, name): '''Remove all nodes associated with a name (hostname) from the zone. If no such nodes exist, nothing happens. ''' self._zone.delete_node(name) def save(self, filename=None, autoserial=False): '''Write the zone back to a file. If `filename` is not specified the zone will be written over the top of the file it was read from. if `autoserial`is True then the serial will be updated to the current date in common YYYYMMDDxx format. The serial is guaranteed to be larger than the previous number. ''' if autoserial: soa = self.root.soa new_serial = int(strftime('%Y%m%d00', localtime(time()))) if new_serial <= soa.serial: new_serial = soa.serial + 1 soa.serial = new_serial if not filename: filename = self.filename self._zone.to_file(filename, relativize=False) # ---- Module Functions ---- def zone_from_file(domain, filename): '''Read a zone file and return the contents as a Zone object. ''' zone = Zone(domain) zone.load_from_file(filename) return zone def _new_rdata(rectype, *args): '''Create a new rdata type of `rectype`. rectype must be one of: 'NS', 'MX', 'A', 'CNAME', 'TXT' Extra arguments are as required by the rectype. ''' if rectype == 'NS': name = dns.name.Name( args[0].split('.') ) rd = dns.rdtypes.ANY.NS.NS(dns.rdataclass.IN, dns.rdatatype.NS, name) elif rectype == 'MX': preference = args[0][0] exchange = dns.name.Name( args[0][1].split('.') ) rd = dns.rdtypes.ANY.MX.MX(dns.rdataclass.IN, dns.rdatatype.MX, preference, exchange) elif rectype == 'A': #name = dns.name.Name( args[0].split('.') ) name = args[0] rd = dns.rdtypes.IN.A.A(dns.rdataclass.IN, dns.rdatatype.A, name) elif rectype == 'CNAME': name = dns.name.Name( args[0].split('.') ) rd = dns.rdtypes.ANY.CNAME.CNAME(dns.rdataclass.IN, dns.rdatatype.CNAME, name) elif rectype == 'TXT': rd = dns.rdtypes.ANY.TXT.TXT(dns.rdataclass.IN, dns.rdatatype.TXT, args[0]) else: raise ValueError("rectype not supported: %s" %rectype) return rd def soa_from_node(node): _soa_rec = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) if _soa_rec: soa = _soa_rec.items[0] else: soa = None return soa easyzone-1.2.2/easyzone/zone_check.py000664 000765 000024 00000003163 11566173537 020166 0ustar00chrisstaff000000 000000 # encoding: utf-8 '''zone_check A wrapper around 'named-checkzone' for checking the validity and syntax of zone files. Example:: >>> from easyzone.zone_check import ZoneCheck >>> c = ZoneCheck() >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> c.isValid('foo.com', '/var/named/zones/example.com') False >>> c.error 'Bad syntax' >>> >>> c = ZoneCheck(checkzone='/usr/sbin/named-checkzone') >>> c.isValid('example.com', '/var/named/zones/example.com') True >>> ''' __author__ = 'Chris Miles' __copyright__ = '(c) Chris Miles 2007' __id__ = '$Id$' __url__ = '$URL$' __version__ = '1.0' # ---- Imports ---- # - Python Modules - import subprocess # ---- Exceptions ---- # ---- Classes ---- class ZoneCheck(object): '''A wrapper around bind's named-checkzone utility, used for checking the syntax of a zone file. `checkzone` : string containing path to named-checkzone binary. Or leave as "named-checkzone" to search with default PATH. ''' def __init__(self, checkzone='checkzone'): self.checkzone = checkzone self.error = None def isValid(self, zonename, filename): '''Ask named to check the syntax of a zone file by calling the named-checkzone commmand. ''' cmd = [ self.checkzone, '-q', zonename, filename ] r = subprocess.call(cmd) if r != 0: self.error = 'Bad syntax' return False else: self.error = None return True easyzone-1.2.2/easyzone/zone_reload.py000664 000765 000024 00000003241 11566173537 020354 0ustar00chrisstaff000000 000000 # encoding: utf-8 '''zone_reload A wrapper around 'rndc' for requesting zone reloads from named. Example:: >>> from easyzone.zone_reload import ZoneReload >>> r = ZoneReload() >>> r.reload('example.com') zone reload up-to-date >>> r.reload('foo.com') rndc: 'reload' failed: not found Traceback (most recent call last): File "", line 1, in File "easyzone/zone_reload.py", line 51, in reload raise ZoneReloadError("rndc failed with return code %d" % r) easyzone.zone_reload.ZoneReloadError: rndc failed with return code 1 >>> >>> r = ZoneReload(rndc='/usr/sbin/rndc') >>> r.reload('example.com') zone reload up-to-date >>> ''' __author__ = 'Chris Miles' __copyright__ = '(c) Chris Miles 2007' __id__ = '$Id$' __url__ = '$URL$' __version__ = '1.0' # ---- Imports ---- # - Python Modules - import subprocess # ---- Exceptions ---- class ZoneReloadError(Exception): '''An error occurred within ZoneReload. ''' # ---- Classes ---- class ZoneReload(object): '''A wrapper around bind's rndc utility, used for reloading a modified DNS zone. `rndc` : string containing path to rndc binary. Or leave as "rndc" to search with default PATH. ''' def __init__(self, rndc='rndc'): self.rndc = rndc def reload(self, zone): '''Ask named to perform a zone reload by calling the rndc commmand. ''' cmd = [ self.rndc, 'reload', zone ] r = subprocess.call(cmd) if r != 0: raise ZoneReloadError("rndc failed with return code %d" % r)