From: Frank Brehm Date: Thu, 9 Nov 2017 18:03:38 +0000 (+0100) Subject: Generated temp slave zones config file X-Git-Tag: 0.1.2~88 X-Git-Url: https://git.uhu-banane.net/?a=commitdiff_plain;h=ff41095254c69b0e271f3d24c1ab65858c8f2e26;p=pixelpark%2Fadmin-tools.git Generated temp slave zones config file --- diff --git a/pp_lib/deploy_zones_from_pdns.py b/pp_lib/deploy_zones_from_pdns.py index e8c68c6..3feeb51 100644 --- a/pp_lib/deploy_zones_from_pdns.py +++ b/pp_lib/deploy_zones_from_pdns.py @@ -17,6 +17,9 @@ import shlex, subprocess import copy import datetime import socket +import tempfile +import time +import shutil from subprocess import Popen, TimeoutExpired, PIPE @@ -40,7 +43,7 @@ from .pdns_record import compare_rrsets from .pidfile import PidFileError, InvalidPidFileError, PidFileInUseError, PidFile -__version__ = '0.2.4' +__version__ = '0.3.1' LOG = logging.getLogger(__name__) @@ -60,6 +63,8 @@ class PpDeployZonesApp(PpPDNSApplication): default_named_conf_dir = '/etc' default_named_zones_cfg_file = 'named.zones.conf' + default_named_basedir = '/var/named' + default_named_slavedir = 'slaves' zone_masters_local = [ '217.66.53.87', @@ -105,6 +110,8 @@ class PpDeployZonesApp(PpPDNSApplication): # Configuration files and directories self.named_conf_dir = self.default_named_conf_dir self._named_zones_cfg_file = self.default_named_zones_cfg_file + self.named_basedir = self.default_named_basedir + self._named_slavedir = self.default_named_slavedir self.zone_masters = copy.copy(self.zone_masters_public) self.masters_configured = False @@ -146,6 +153,18 @@ class PpDeployZonesApp(PpPDNSApplication): """The file for configuration of all own zones.""" return os.path.join(self.named_conf_dir, self._named_zones_cfg_file) + # ------------------------------------------- + @property + def named_slavedir_rel(self): + """The directory for zone files of slave zones.""" + return self._named_slavedir + + # ------------------------------------------- + @property + def named_slavedir_abs(self): + """The directory for zone files of slave zones.""" + return os.path.join(self.named_basedir, self._named_slavedir) + # ------------------------------------------------------------------------- def init_arg_parser(self): @@ -206,6 +225,8 @@ class PpDeployZonesApp(PpPDNSApplication): section, section_name, 'config_dir', 'named_conf_dir', True) self._check_path_config( section, section_name, 'zones_cfg_file', '_named_zones_cfg_file', False) + self._check_path_config(section, section_name, 'base_dir', 'named_basedir', True) + self._check_path_config(section, section_name, 'slave_dir', '_named_slavedir', False) if 'masters' in section: self._get_masters_from_cfg(section['masters'], section_name) @@ -306,6 +327,9 @@ class PpDeployZonesApp(PpPDNSApplication): self.zones = self.get_api_zones() self.zones.sort(key=lambda x: cmp_to_key(compare_fqdn)(x.name_unicode)) + self.init_temp_objects() + self.generate_slave_cfg_file() + finally: self.cleanup() self.pidfile = None @@ -339,6 +363,127 @@ class PpDeployZonesApp(PpPDNSApplication): shutil.rmtree(self.tempdir, False, emit_rm_err) self.tempdir = None + # ------------------------------------------------------------------------- + def init_temp_objects(self): + """Init temporary objects and properties.""" + + self.tempdir = tempfile.mkdtemp( + prefix=(self.appname + '.'), suffix='.tmp.d' + ) + LOG.debug("Temporary directory: {!r}.".format(self.tempdir)) + + self.temp_zones_cfg_file = os.path.join( + self.tempdir, self.default_named_zones_cfg_file) + + if self.verbose > 1: + LOG.debug("Temporary zones conf: {!r}".format(self.temp_zones_cfg_file)) + + # ------------------------------------------------------------------------- + def generate_slave_cfg_file(self): + + LOG.info("Generating {} ...".format(self.default_named_zones_cfg_file)) + + cur_date = datetime.datetime.now().isoformat(' ') + re_rev = re.compile(r'^rev\.', re.IGNORECASE) + re_trail_dot = re.compile(r'\.+$') + + lines = [] + lines.append('###############################################################') + lines.append('') + lines.append(' Bind9 configuration file for slave sones') + lines.append(' {}'.format(self.named_zones_cfg_file)) + lines.append('') + lines.append(' Generated at: {}'.format(cur_date)) + lines.append('') + lines.append('###############################################################') + header = textwrap.indent('\n'.join(lines), '//', lambda line: True) + '\n' + + content = header + + for zone in self.zones: + + canonical_name = zone.name_unicode + match = self.re_ipv4_zone.search(zone.name) + if match: + prefix = self._get_ipv4_prefix(match.group(1)) + if prefix: + if prefix == '127.0.0': + LOG.debug("Pure local zone {!r} will not be considered.".format(prefix)) + continue + canonical_name = 'rev.' + prefix + else: + match = self.re_ipv6_zone.search(zone.name) + if match: + prefix = self._get_ipv6_prefix(match.group(1)) + if prefix: + canonical_name = 'rev.' + prefix + + show_name = canonical_name + show_name = re_rev.sub('Reverse ', show_name) + show_name = re_trail_dot.sub('', show_name) + zname = re_trail_dot.sub('', zone.name) + + zfile = os.path.join( + self.named_slavedir_rel, re_trail_dot.sub('', canonical_name) + '.zone') + + lines = [] + lines.append('') + lines.append('// {}'.format(show_name)) + lines.append('zone "{}" in {{'.format(zname)) + lines.append('\tmasters {') + for master in self.zone_masters: + lines.append('\t\t{};'.format(master)) + lines.append('\t};') + lines.append('\ttype slave;') + lines.append('\tfile "{}";'.format(zfile)) + lines.append('};') + + content += '\n'.join(lines) + '\n' + + content += '\n// vim: ts=8 filetype=named noet noai\n' + + with open(self.temp_zones_cfg_file, 'w', **self.open_args) as fh: + fh.write(content) + + if self.verbose > 2: + LOG.debug("Generated {!r}:\n{}".format(self.temp_zones_cfg_file, content.strip())) + + # ------------------------------------------------------------------------- + def _get_ipv4_prefix(self, match): + + tuples = [] + for t in match.split('.'): + if t: + tuples.insert(0, t) + if self.verbose > 2: + LOG.debug("Got IPv4 tuples: {}".format(pp(tuples))) + return '.'.join(tuples) + + # ------------------------------------------------------------------------- + def _get_ipv6_prefix(self, match): + + tuples = [] + for t in match.split('.'): + if t: + tuples.insert(0, t) + + tokens = [] + while len(tuples): + token = ''.join(tuples[0:4]).ljust(4, '0') + if token.startswith('000'): + token = token[3:] + elif token.startswith('00'): + token = token[2:] + elif token.startswith('0'): + token = token[1:] + tokens.append(token) + del tuples[0:4] + + if self.verbose > 2: + LOG.debug("Got IPv6 tokens: {}".format(pp(tokens))) + + return ':'.join(tokens) + # ============================================================================= diff --git a/pp_lib/pdns_app.py b/pp_lib/pdns_app.py index 0d0654d..fd6fe07 100644 --- a/pp_lib/pdns_app.py +++ b/pp_lib/pdns_app.py @@ -26,7 +26,7 @@ from .common import pp, to_bool from .cfg_app import PpCfgAppError, PpConfigApplication from .pdns_zone import PdnsApiZone -__version__ = '0.3.2' +__version__ = '0.3.3' LOG = logging.getLogger(__name__) _LIBRARY_NAME = "pp-pdns-api-client" @@ -546,7 +546,7 @@ class PpPDNSApplication(PpConfigApplication): path = "/servers/{}/zones".format(self.api_servername) json_response = self.perform_request(path) - if self.verbose > 2: + if self.verbose > 3: LOG.debug("Got a response:\n{}".format(pp(json_response))) zone_list = [] @@ -558,6 +558,9 @@ class PpPDNSApplication(PpConfigApplication): if self.verbose > 2: print("{!r}".format(zone)) + if self.verbose > 1: + LOG.debug("Found {} zones.".format(len(zone_list))) + return zone_list # =============================================================================