From ac4058a8732f3f4d4d2011471f4e5aadd5da910f Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Thu, 24 Mar 2022 18:43:05 +0100 Subject: [PATCH] Adding lib/pp_admintools/pdns_config.py for class PdnsConfiguration --- lib/pp_admintools/pdns_config.py | 343 +++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 lib/pp_admintools/pdns_config.py diff --git a/lib/pp_admintools/pdns_config.py b/lib/pp_admintools/pdns_config.py new file mode 100644 index 0000000..2bc150d --- /dev/null +++ b/lib/pp_admintools/pdns_config.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +@author: Frank Brehm +@contact: frank.brehm@pixelpark.com +@copyright: © 2022 by Frank Brehm, Berlin +@summary: A module for providing a configuration for applications, + which are Working with PowerDNS. + It's based on class MailConfigError. +""" +from __future__ import absolute_import + +# Standard module +import logging +import pwd +import re +import copy + +from numbers import Number + +# Third party modules + +# Own modules + +from fb_tools.common import is_sequence + +# from .config import ConfigError, BaseConfiguration +from fb_tools.multi_config import MultiConfigError +from fb_tools.multi_config import DEFAULT_ENCODING + +from .mail_config import MailConfigError, MailConfiguration +from .mail_config import DEFAULT_CONFIG_DIR, MAX_PORT_NUMBER + +from .xlate import XLATOR + +MAX_PDNS_API_TIMEOUT = 3600 + +__version__ = '0.1.0' +LOG = logging.getLogger(__name__) + +_ = XLATOR.gettext + + +# ============================================================================= +class PdnsConfigError(MailConfigError): + """Base error class for all exceptions happened during + execution this configured application""" + + pass + + +# ============================================================================= +class PdnsConfiguration(MailConfiguration): + """ + A class for providing a configuration for an arbitrary PowerDNS Application + and methods to read it from configuration files. + """ + + default_pdns_api_instances = { + 'global': { + 'host': "dnsmaster.pp-dns.com", + }, + 'public': { + 'host': "dnsmaster-public.pixelpark.com", + }, + 'local': { + 'host': "dnsmaster-local.pixelpark.com", + }, + } + + default_pdns_api_port = 8081 + default_pdns_api_servername = "localhost" + default_pdns_timeout = 20 + + default_pdns_instance = 'global' + + # ------------------------------------------------------------------------- + def __init__( + self, appname=None, verbose=0, version=__version__, base_dir=None, + append_appname_to_stems=True, additional_stems=None, config_dir=DEFAULT_CONFIG_DIR, + additional_config_file=None, additional_cfgdirs=None, encoding=DEFAULT_ENCODING, + ensure_privacy=True, use_chardet=True, initialized=False): + + self.pdns_api_instances = {} + for inst_name in self.default_pdns_api_instances.keys(): + + def_inst = self.default_pdns_api_instances[inst_name] + + inst = {} + inst['host'] = def_inst['host'] + inst['port'] = self.default_pdns_api_port + inst['key'] = None + inst['servername'] = self.default_pdns_api_servername + + self.pdns_api_instances[inst_name] = inst + + self.pdns_timeout = self.default_pdns_timeout + + add_stems = [] + if additional_stems: + if is_sequence(additional_stems): + for stem in additional_stems: + add_stems.append(stem) + else: + add_stems.append(additional_stems) + + if 'pdns' not in add_stems: + add_stems.append('pdns') + + if 'powerdns' not in add_stems: + add_stems.append('powerdns') + + super(PdnsConfiguration, self).__init__( + appname=appname, verbose=verbose, version=version, base_dir=base_dir, + append_appname_to_stems=append_appname_to_stems, config_dir=config_dir, + additional_stems=add_stems, additional_config_file=additional_config_file, + additional_cfgdirs=additional_cfgdirs, encoding=encoding, use_chardet=use_chardet, + ensure_privacy=ensure_privacy, initialized=False, + ) + + if initialized: + self.initialized = True + + # ------------------------------------------------------------------------- + def as_dict(self, short=True): + """ + Transforms the elements of the object into a dict + + @param short: don't include local properties in resulting dict. + @type short: bool + + @return: structure as dict + @rtype: dict + """ + + res = super(PdnsConfiguration, self).as_dict(short=short) + + res['default_pdns_api_instances'] = self.default_pdns_api_instances + res['default_pdns_api_port'] = self.default_pdns_api_port + res['default_pdns_api_servername'] = self.default_pdns_api_servername + res['default_pdns_timeout'] = self.default_pdns_timeout + res['default_pdns_instance'] = self.default_pdns_instance + + return res + + # ------------------------------------------------------------------------- + def eval_section(self, section_name): + + super(PdnsConfiguration, self).eval_section(section_name) + sn = section_name.lower() + + if sn == 'pdns' or sn == 'powerdns': + section = self.cfg[section_name] + return self._eval_pdns(section_name, section) + + # ------------------------------------------------------------------------- + def _eval_pdns(self, section_name, section): + + if self.verbose > 2: + msg = _("Evaluating config section {!r}:").format(section_name) + LOG.debug(msg + '\n' + pp(section)) + + self._eval_pdns_timeout(section_name, section) + self._eval_pdns_instances(section_name, section) + + # ------------------------------------------------------------------------- + def _eval_pdns_timeout(self, section_name, section): + + re_timeout = re.compile(r'^\s*timeout\s*$', re.IGNORECASE) + + for key in section.keys(): + if not re_timeout.search(key): + continue + + val = section[key] + try: + timeout = int(val) + except (ValueError, TypeError) as e: + msg = _("Value {!r} for PowerDNS API timeout is invalid:").format(val) + LOG.error(msg) + continue + if timeout <= 0 or port > MAX_PDNS_API_TIMEOUT: + msg = _("Value {!r} for PowerDNS API timeout is invalid:").format(timeout) + LOG.error(msg) + continue + + self.pdns_timeout = timeout + + # ------------------------------------------------------------------------- + def _eval_pdns_instances(self, section_name, section): + + re_inst = re.compile(r'^\s*instances?\s*$', re.IGNORECASE) + + for key in section.keys(): + if not re_inst.search(key): + continue + + for instance_name in section[key].keys(): + self._eval_pdns_instance(self, instance_name, section[key][instance_name]) + + # ------------------------------------------------------------------------- + def _eval_pdns_instance(self, instance_name, section): + + iname = instance_name.lower() + + if self.verbose > 2: + msg = _("Evaluating PowerDNS instance {!r}:").format(iname) + LOG.debug(msg + '\n' + pp(section)) + + self._eval_pdns_inst_host(iname, section) + self._eval_pdns_inst_port(iname, section) + self._eval_pdns_inst_servername(iname, section) + self._eval_pdns_inst_key(iname, section) + + # ------------------------------------------------------------------------- + def _eval_pdns_inst_host(self, iname, section): + + pass + + # ------------------------------------------------------------------------- + def _eval_pdns_inst_port(self, iname, section): + + pass + + # ------------------------------------------------------------------------- + def _eval_pdns_inst_servername(self, iname, section): + + pass + + # ------------------------------------------------------------------------- + def _eval_pdns_inst_key(self, iname, section): + + pass + +# re_cc = re.compile(r'^\s*(mail[_-]?)?cc\s*$', re.IGNORECASE) +# +# for key in section.keys(): +# +# self._mail_cc_configured = True +# if not re_cc.search(key): +# continue +# +# val = section[key] +# if not val: +# continue +# if is_sequence(val): +# for v in val: +# result = self._split_mailaddress_tokens(v, _("cc mail address")) +# if result: +# self.mail_cc.expand(result) +# else: +# result = self._split_mailaddress_tokens(val, _("cc mail address")) +# if result: +# self.mail_cc.expand(result) +# +# # ------------------------------------------------------------------------- +# def _eval_mail_reply_to(self, section_name, section): +# +# re_reply = re.compile(r'^\s*(mail[_-]?)?reply([-_]?to)?\s*$', re.IGNORECASE) +# +# for key in section.keys(): +# if not re_reply.search(key): +# continue +# +# val = section[key] +# +# if is_sequence(val): +# if not len(val): +# continue +# val = val[0] +# +# if MailAddress.valid_address(val): +# self.reply_to = val +# else: +# msg = _("Found invalid {what} {addr!r} in configuration.") +# LOG.error(msg.format(what=_("reply to address"), addr=val)) +# +# # ------------------------------------------------------------------------- +# def _eval_mail_method(self, section_name, section): +# +# re_method = re.compile(r'^\s*(mail[_-]?)?method\s*$', re.IGNORECASE) +# +# for key in section.keys(): +# if not re_reply.search(key): +# continue +# +# val = section[key].strip().lower() +# if not val: +# continue +# +# if val not in self.valid_mail_methods: +# msg = _("Found invalid mail method {!r} in configuration.") +# LOG.error(msg.format(section[key])) +# continue +# +# self.mail_method = val +# +# # ------------------------------------------------------------------------- +# def _eval_mail_server(self, section_name, section): +# +# re_server = re.compile(r'^\s*(mail[_-]?)?server\s*$', re.IGNORECASE) +# +# for key in section.keys(): +# if not re_server.search(key): +# continue +# +# val = section[key].strip().lower() +# if not val: +# continue +# +# self.mail_server = val +# +# # ------------------------------------------------------------------------- +# def _eval_smtp_port(self, section_name, section): +# +# re_server = re.compile(r'^\s*(smtp[_-]?)?port\s*$', re.IGNORECASE) +# +# for key in section.keys(): +# if not re_server.search(key): +# continue +# +# val = section[key] +# try: +# port = int(val) +# except (ValueError, TypeError) as e: +# msg = _("Value {!r} for SMTP port is invalid:").format(val) +# LOG.error(msg) +# continue +# if port <= 0 or port > MAX_PORT_NUMBER: +# msg = _("Found invalid SMTP port number {} in configuration.").format(port) +# LOG.error(msg) +# continue +# +# self.smtp_port = port + +# ============================================================================= +if __name__ == "__main__": + + pass + +# ============================================================================= + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list -- 2.39.5