#!/bin/env python3
# -*- coding: utf-8 -*-
-__version__ = '0.4.0'
+__version__ = '0.4.1'
MAX_PORT_NUMBER = (2 ** 16) - 1
MAX_TIMEOUT = 3600
+DEFAULT_CONFIG_DIR = 'pixelpark'
# vim: ts=4 et list
import time
import shutil
import pipes
+import ipaddress
from subprocess import Popen, TimeoutExpired, PIPE
from .xlate import XLATOR
-__version__ = '0.8.0'
+__version__ = '0.8.1'
LOG = logging.getLogger(__name__)
_ = XLATOR.gettext
cfg_class=cfg_class, initialized=False, instance="public",
)
- self.post_init()
+ masters = []
+ for addr in sorted(self.cfg.masters, key=ipaddress.ip_address):
+ if addr not in self.local_addresses:
+ masters.append(addr)
+
+ self.cfg.masters = masters
+
+ self.initialized = True
# -------------------------------------------
@property
if self.cfg:
systemctl = self.cfg.systemctl
- return "{} status".format(systemctl)
+ return "{} status named.service".format(systemctl)
# -------------------------------------------
@property
if self.cfg:
systemctl = self.cfg.systemctl
- return "{} start".format(systemctl)
+ return "{} start named.service".format(systemctl)
# -------------------------------------------
@property
if self.cfg:
systemctl = self.cfg.systemctl
- return "{} restart".format(systemctl)
+ return "{} restart named.service".format(systemctl)
# -------------------------------------------
@property
@rtype: dict
"""
- res = super(DnsDeployZonesConfig, self).as_dict(short=short)
+ res = super(PpDeployZonesApp, self).as_dict(short=short)
res['named_slavedir_abs'] = self.named_slavedir_abs
res['cmd_named_checkconf'] = self.cmd_named_checkconf
super(PpDeployZonesApp, self).post_init()
+ LOG.debug(_("My own post init phase."))
+
cmd_namedcheckconf = self.get_command('named-checkconf', resolve=True)
if not cmd_namedcheckconf:
self.exit(1)
LOG.error(_("Unknown time zone: {!r}.").format(self.local_tz_name))
self.exit(6)
- self.initialized = True
-
# -------------------------------------------------------------------------
def current_timestamp(self):
lines.append('// {}'.format(show_name))
lines.append('zone "{}" in {{'.format(zname))
lines.append('\tmasters {')
- for master in self.zone_masters:
+ for master in self.cfg.masters:
lines.append('\t\t{};'.format(master))
lines.append('\t};')
lines.append('\ttype slave;')
allow_line += ' };'
lines.append(allow_line)
- for master in self.zone_masters:
+ for master in self.cfg.masters:
if master not in self.servers:
self.servers[master] = {}
if 'keys' not in self.servers[master]:
if lines_src[i] != lines_tgt[i]:
LOG.debug(_(
"Source file {sf!r} has a different content than "
- "the target file {tf!r}.").format(sf=str(file_src), tf=str(lines_tgt)))
+ "the target file {tf!r}.").format(sf=str(file_src), tf=str(file_tgt)))
return False
i += 1
from .xlate import XLATOR
-__version__ = '0.1.1'
+__version__ = '0.2.1'
LOG = logging.getLogger(__name__)
_ = XLATOR.gettext
"""
default_pidfile = Path('/run/dns-deploy-zones.pid')
+ default_keep_backup = False
default_named_conf_dir = Path('/etc')
default_named_zones_cfg_file = Path('named.zones.conf')
default_named_basedir = Path('/var/named')
default_named_slavedir = Path('slaves')
- default_zone_masters_local = set('dnsmaster-local.pixelpark.com')
- default_zone_masters_public = set('dnsmaster-public.pixelpark.com')
+ default_zone_masters_local = ['master-local.pp-dns.com']
+ default_zone_masters_public = ['master-public.pp-dns.com']
default_rndc = Path('/usr/sbin/rndc')
default_systemctl = Path('/usr/bin/systemctl')
ensure_privacy=True, use_chardet=True, initialized=False):
self.pidfile = self.default_pidfile
+ self.keep_backup = self.default_keep_backup
+
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
res = super(DnsDeployZonesConfig, self).as_dict(short=short)
res['default_pidfile'] = self.default_pidfile
+ res['default_keep_backup'] = self.default_keep_backup
res['default_named_conf_dir'] = self.default_named_conf_dir
res['default_named_zones_cfg_file'] = self.default_named_zones_cfg_file
res['default_named_basedir'] = self.default_named_basedir
addr_list = set()
+ if self.verbose > 3:
+ msg = _("Trying to evaluate address of host {!r} ...").format(host)
+ LOG.debug(msg)
+
try:
addr_infos = socket.getaddrinfo(host, 53, proto=socket.IPPROTO_TCP)
for addr_info in addr_infos:
else:
LOG.error(msg)
return set()
+ if self.verbose > 3:
+ msg = _("Got addresses {a!r} for host {h!r}.")
+ LOG.debug(msg.format(a=addr_list, h=host))
+
return addr_list
# -------------------------------------------------------------------------
msg = _("Found path to {what}: {path!r}.").format(what=what, path=val)
LOG.debug(msg)
- self.named_config_dir = path
+ self.named_conf_dir = path
# -------------------------------------------------------------------------
def _eval_named_configfile(self, iname, key, section):
if val is None:
return
- self.named_internal = val
+ self.named_internal = to_bool(val)
# -------------------------------------------------------------------------
def _eval_named_listen_v6(self, iname, key, section):
if val is None:
return
- self.named_listen_on_v6 = val
+ self.named_listen_on_v6 = to_bool(val)
+
+ # -------------------------------------------------------------------------
+ def _eval_app(self, section_name, section):
+
+ if self.verbose > 2:
+ msg = _("Evaluating config section {!r}:").format(section_name)
+ LOG.debug(msg + '\n' + pp(section))
+
+ re_pidfile = re.compile(r'^\s*pid[_-]?file$', re.IGNORECASE)
+ re_keep_backup = re.compile(r'^\s*keep[_-]?backup$', re.IGNORECASE)
+
+ for key in section.keys():
+
+ if re_pidfile.search(key):
+ self._eval_pidfile(section_name, key, section)
+ continue
+
+ if re_keep_backup.search(key):
+ self._eval_keep_backup(section_name, key, section)
+ continue
+
+ # -------------------------------------------------------------------------
+ def _eval_pidfile(self, iname, key, section):
+
+ val = section[key].strip()
+ if not val:
+ return
+
+ what = _("the PID file")
+ path = Path(val)
+ if not path.is_absolute():
+ msg = _("The path to {what} must be an absolute path, found {path!r}.")
+ msg = msg.format(what=what, path=val)
+ if self.raise_on_error:
+ raise DnsDeployZonesConfigError(msg)
+ else:
+ LOG.error(msg)
+ return
+
+ if self.verbose > 2:
+ msg = _("Found path to {what}: {path!r}.").format(what=what, path=val)
+ LOG.debug(msg)
+
+ self.pidfile = path
+
+ # -------------------------------------------------------------------------
+ def _eval_keep_backup(self, iname, key, section):
+
+ val = section[key]
+ if val is None:
+ return
+
+ self.keep_backup = to_bool(val)
# -------------------------------------------------------------------------
def eval(self):
if self.masters:
if self.verbose > 2:
- LOG.debug(_("Using configured masters:") + ' ' + pp(self.masters))
+ LOG.debug(_("Using configured masters:") + '\n' + pp(self.masters))
else:
LOG.warn(_("No valid masters found in configuration."))
+ if self.verbose > 2:
+ msg = _("Evaluated configuration:")
+ msg += " " + pp(self.as_dict())
+
# =============================================================================
if __name__ == "__main__":
# Own modules
from . import __version__ as GLOBAL_VERSION
-from . import MAX_PORT_NUMBER
+from . import MAX_PORT_NUMBER, DEFAULT_CONFIG_DIR
from fb_tools.common import pp
from .mailaddress import MailAddress
-__version__ = '0.2.4'
+__version__ = '0.2.5'
LOG = logging.getLogger(__name__)
_ = XLATOR.gettext
def __init__(
self, appname=None, verbose=0, version=GLOBAL_VERSION, base_dir=None,
cfg_class=MailConfiguration, initialized=False, usage=None, description=None,
- argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None):
+ argparse_epilog=None, argparse_prefix_chars='-', env_prefix=None,
+ config_dir=DEFAULT_CONFIG_DIR):
super(BaseMailApplication, self).__init__(
appname=appname, verbose=verbose, version=version, base_dir=base_dir,
description=description, cfg_class=cfg_class, initialized=False,
argparse_epilog=argparse_epilog, argparse_prefix_chars=argparse_prefix_chars,
- env_prefix=env_prefix,
+ env_prefix=env_prefix, config_dir=config_dir
)
# -------------------------------------------------------------------------
from fb_tools.multi_config import DEFAULT_ENCODING
from . import __version__ as GLOBAL_VERSION
-from . import MAX_PORT_NUMBER
+from . import MAX_PORT_NUMBER, DEFAULT_CONFIG_DIR
from .mailaddress import MailAddress
from .xlate import XLATOR
-__version__ = '0.1.6'
+__version__ = '0.1.8'
LOG = logging.getLogger(__name__)
_ = XLATOR.gettext
-DEFAULT_CONFIG_DIR = 'pixelpark'
VALID_MAIL_METHODS = ('smtp', 'sendmail')
self.mail_from = self.default_mail_from_complete
self.mail_cc = copy.copy(self.default_mail_cc)
self.reply_to = self.default_reply_to
- self.mail_method = default_mail_method
+ self.mail_method = self.default_mail_method
self.mail_server = self.default_mail_server
self.smtp_port = self.default_smtp_port
self._mail_cc_configured = False
from .xlate import XLATOR
-__version__ = '0.9.0'
+__version__ = '0.9.1'
LOG = logging.getLogger(__name__)
_ = XLATOR.gettext
# -------------------------------------------------------------------------
def eval_instance(self, inst_name):
+ if self.verbose > 2:
+ msg = _("Evaluating instance {!r} ...").format(inst_name)
+ LOG.debug(msg)
+
if not self.cfg:
msg = _("Configuration not available.")
raise PpPDNSAppError(msg)
msg = _("PDNS instance {!r} is not configured.").format(inst_name)
raise PpPDNSAppError(msg)
- inst = self.cfg.pdns_api_instances[inst_name]
-
self._instance = inst_name
- self.api_host = inst['host']
- self.api_port = inst['port']
- self.api_key = inst['key']
- self.api_servername = inst['servername']
+ if self.cfg.pdns_host:
+ self.api_host = self.cfg.pdns_host
+ if self.cfg.pdns_key:
+ self.api_key = self.cfg.pdns_key
+ if self.cfg.pdns_port:
+ self.api_port = self.cfg.pdns_port
+ if self.cfg.pdns_servername:
+ self.api_servername = self.cfg.pdns_servername
# -------------------------------------------------------------------------
def as_dict(self, short=True):
res = super(PpPDNSApplication, self).as_dict(short=short)
res['api_host'] = self.api_host
- res['api_key'] = self.api_key
res['api_port'] = self.api_port
res['api_servername'] = self.api_servername
res['instance'] = self.instance
res['api_server_version'] = self.api_server_version
+ if self.api_key:
+ if self.verbose > 4:
+ res['api_key'] = self.api_key
+ else:
+ res['api_key'] = '******'
+ else:
+ res['api_key'] = None
+
return res
# -------------------------------------------------------------------------
configuration a.s.o.
This method could be overwritten by descendant classes, these
- methhods should allways include a call to post_init() of the
+ methods should allways include a call to post_init() of the
parent class.
"""
self.pdns = PowerDNSServer(
appname=self.appname, verbose=self.verbose, base_dir=self.base_dir,
- master_server=self.api_host, port=self.api_port,
- key=self.api_key, use_https=False,
+ master_server=self.cfg.pdns_host, port=self.cfg.pdns_port,
+ key=self.cfg.pdns_key, use_https=False,
simulate=self.simulate, force=self.force, initialized=False,
)
self.pdns.initialized = True