--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2017 by Frank Brehm, Berlin
+@summary: A module for the application class for configuring named
+"""
+from __future__ import absolute_import
+
+# Standard modules
+import os
+import logging
+import logging.config
+import re
+import pwd
+import glob
+import copy
+import textwrap
+import socket
+
+# Third party modules
+import six
+
+# Own modules
+from .common import pp, to_bool
+
+from .cfg_app import PpCfgAppError, PpConfigApplication
+
+__version__ = '0.1.0'
+LOG = logging.getLogger(__name__)
+
+
+# =============================================================================
+class PpConfigNamedError(PpCfgAppError):
+ pass
+
+
+# =============================================================================
+class PpConfigNamedApp(PpConfigApplication):
+ """
+ Class for a application 'config-named' for configuring the BIND named daemon.
+ """
+
+ default_pdns_api_host = 'systemshare.pixelpark.com'
+ default_pdns_api_port = 8081
+ default_pdns_api_root_path = '/api/v1/servers/localhost'
+
+ default_zone_masters = [
+ '217.66.53.86',
+ ]
+
+ re_split_addresses = re.compile(r'[,;\s]+')
+
+ # -------------------------------------------------------------------------
+ def __init__(self, appname=None, version=__version__):
+
+ self.pdns_api_host = self.default_pdns_api_host
+ self.pdns_api_port = self.default_pdns_api_port
+ self.pdns_api_root_path = self.default_pdns_api_root_path
+ self.pdns_api_key = None
+
+ self.is_internal = False
+ self.zone_masters = copy.copy(self.default_zone_masters)
+ self.query_log = False
+
+ description = textwrap.dedent('''\
+ Generation of configuration of named (the BIND 9 name daemon).
+ ''').strip()
+
+ super(PpConfigNamedApp, self).__init__(
+ appname=appname, version=version, description=description,
+ cfg_stems='dns-deploy-zones',
+ )
+
+ # -------------------------------------------------------------------------
+ def init_arg_parser(self):
+
+ is_internal_group = self.arg_parser.add_mutually_exclusive_group()
+
+ is_internal_group.add_argument(
+ '--internal', '--not-public', dest='internal', action='store_true',
+ help="Creating a named configuration for a internal name server.",
+ )
+
+ is_internal_group.add_argument(
+ '--public', '--not-internal', dest='public', action='store_true',
+ help="Creating a named configuration for a public name server.",
+ )
+
+ query_log_group = self.arg_parser.add_mutually_exclusive_group()
+
+ query_log_group.add_argument(
+ '--querylog', dest='querylog', action='store_true',
+ help="Enabling query logging in the named configuration.",
+ )
+
+ query_log_group.add_argument(
+ '--no-querylog', dest='no_querylog', action='store_true',
+ help="Disabling query logging in the named configuration.",
+ )
+
+ # -------------------------------------------------------------------------
+ def perform_config(self):
+
+ super(PpConfigNamedApp, self).perform_config()
+
+ for section_name in self.cfg.keys():
+
+ if self.verbose > 3:
+ LOG.debug("Checking config section {!r} ...".format(section_name))
+
+ section = self.cfg[section_name]
+
+ if section_name.lower() in (
+ 'powerdns-api', 'powerdns_api', 'powerdnsapi',
+ 'pdns-api', 'pdns_api', 'pdnsapi' ):
+ self.set_api_options(section, section_name)
+
+ if section_name.lower() == 'named':
+ self.set_named_options(section, section_name)
+
+ self._perform_cmdline_opts()
+
+ # -------------------------------------------------------------------------
+ def _perform_cmdline_opts(self):
+
+ if hasattr(self.args, 'internal') and self.args.internal:
+ self.is_internal = True
+ elif hasattr(self.args, 'public') and self.args.public:
+ self.is_internal = False
+
+ if hasattr(self.args, 'querylog') and self.args.querylog:
+ self.query_log = True
+ elif hasattr(self.args, 'no_querylog') and self.args.no_querylog:
+ self.query_log = False
+
+ # -------------------------------------------------------------------------
+ def set_api_options(self, section, section_name):
+
+ if self.verbose > 2:
+ LOG.debug("Evaluating config section {n!r}:\n{s}".format(
+ n=section_name, s=pp(section)))
+
+ if 'host' in section:
+ v = section['host']
+ host = v.lower().strip()
+ if host:
+ self.pdns_api_host = host
+
+ if 'port' in section:
+ try:
+ port = int(section['port'])
+ if port <= 0 or port > 2**16:
+ raise ValueError(
+ "a port must be greater than 0 and less than {}.".format(2**16))
+ except (TypeError, ValueError) as e:
+ LOG.error("Wrong port number {!r} in configuration section {!r}: {}".format(
+ section['port'], section_name, e))
+ else:
+ self.pdns_api_port = port
+
+ if 'root_path' in section:
+ path = section['root_path']
+ if not os.path.isabs(path):
+ msg = (
+ "The root path of the PowerDNS must be an absolute pathname "
+ "(found [{}]/root_path => {!r} in configuration.").format(section_name, path)
+ LOG.error(msg)
+ else:
+ self.pdns_api_root_path = path
+
+ if 'key' in section:
+ key = section['key'].strip()
+ self.pdns_api_key = key
+
+ # -------------------------------------------------------------------------
+ def set_named_options(self, section, section_name):
+
+ if self.verbose > 2:
+ LOG.debug("Evaluating config section {n!r}:\n{s}".format(
+ n=section_name, s=pp(section)))
+
+ if 'is_internal' in section:
+ if section['is_internal'] is None:
+ self.is_internal = False
+ else:
+ self.is_internal = to_bool(section['is_internal'])
+
+ if 'query_log' in section:
+ self.query_log = to_bool(section['query_log'])
+
+ if 'masters' in section:
+ masters = []
+ for m in self.re_split_addresses.split(section['masters']):
+ if m:
+ m = m.strip().lower()
+ try:
+ addr_info = socket.getaddrinfo(
+ m, 53, proto=socket.IPPROTO_TCP, family=socket.AF_INET)
+ except socket.gaierror as e:
+ msg = (
+ "Invalid hostname or address {!r} found in "
+ "[{}]/masters: {}").format(m, section_name, e)
+ LOG.error(msg)
+ m = None
+ if m:
+ masters.append(m)
+ if masters:
+ self.zone_masters = masters
+
+ # -------------------------------------------------------------------------
+ def _run(self):
+
+ if os.geteuid():
+ LOG.error("You must be root to execute this script.")
+ self.exit(1)
+ LOG.info("Jetzt geht's looos")
+
+# =============================================================================
+
+if __name__ == "__main__":
+
+ pass
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list