]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Refactoring lib/pp_admintools/dns_deploy_zones_app.py
authorFrank Brehm <frank@brehm-online.com>
Thu, 31 Mar 2022 09:35:31 +0000 (11:35 +0200)
committerFrank Brehm <frank@brehm-online.com>
Thu, 31 Mar 2022 09:35:31 +0000 (11:35 +0200)
lib/pp_admintools/dns_deploy_zones_app.py

index 634bb0db60badb023675ea6e528db2308a638688..da2c7e4fb4d3131090cec68e31ccd9a8923b16e7 100644 (file)
@@ -14,9 +14,7 @@ import logging.config
 import textwrap
 import re
 import shlex
-import copy
 import datetime
-import socket
 import tempfile
 import time
 import shutil
@@ -24,22 +22,28 @@ import pipes
 
 from subprocess import Popen, TimeoutExpired, PIPE
 
+from pathlib import Path
+
 # Third party modules
 import six
 from pytz import timezone, UnknownTimeZoneError
 
 # Own modules
-from fb_tools.common import pp, to_str, to_bool
+from fb_tools.common import pp, to_str
 
 from fb_tools.app import BaseApplication
 
+from . import __version__ as GLOBAL_VERSION
+
 from .pdns_app import PpPDNSAppError, PpPDNSApplication
 
+from .dns_deploy_zones_config import DnsDeployZonesConfig
+
 from .pidfile import PidFileError, PidFile
 
 from .xlate import XLATOR
 
-__version__ = '0.7.4'
+__version__ = '0.8.0'
 LOG = logging.getLogger(__name__)
 
 _ = XLATOR.gettext
@@ -57,27 +61,6 @@ class PpDeployZonesApp(PpPDNSApplication):
     of the BIND named daemon.
     """
 
-    default_pidfile = '/run/dns-deploy-zones.pid'
-
-    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',
-    ]
-
-    zone_masters_public = [
-        '217.66.53.97',
-    ]
-
-    default_cmd_checkconf = '/usr/sbin/named-checkconf'
-    default_cmd_reload = '/usr/sbin/rndc reload'
-    default_cmd_status = '/usr/bin/systemctl status named.service'
-    default_cmd_start = '/usr/bin/systemctl start named.service'
-    default_cmd_restart = '/usr/bin/systemctl restart named.service'
-
     re_ipv4_zone = re.compile(r'^((?:\d+\.)+)in-addr\.arpa\.$')
     re_ipv6_zone = re.compile(r'^((?:[\da-f]\.)+)ip6\.arpa\.$')
 
@@ -90,6 +73,8 @@ class PpDeployZonesApp(PpPDNSApplication):
     re_rev = re.compile(r'^rev\.', re.IGNORECASE)
     re_trail_dot = re.compile(r'\.+$')
 
+    default_local_tz_name = 'Europe/Berlin'
+
     open_args = {}
     if six.PY3:
         open_args = {
@@ -98,43 +83,32 @@ class PpDeployZonesApp(PpPDNSApplication):
         }
 
     # -------------------------------------------------------------------------
-    def __init__(self, appname=None, base_dir=None, version=__version__):
+    def __init__(
+        self, appname=None, base_dir=None, version=GLOBAL_VERSION,
+            cfg_class=DnsDeployZonesConfig):
 
         self.zones = {}
         self.pidfile = None
 
         self._show_simulate_opt = True
-
-        self.is_internal = False
-        self.named_listen_on_v6 = False
-        self.pidfile_name = self.default_pidfile
+        self.cfg = None
 
         # 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
 
         self.tempdir = None
         self.temp_zones_cfg_file = None
         self.keep_tempdir = False
         self.keep_backup = False
 
+        self.local_tz = None
+        self.local_tz_name = self.default_local_tz_name
+
         self.backup_suffix = (
             '.' + datetime.datetime.utcnow().strftime('%Y-%m-%d_%H-%M-%S') + '.bak')
 
         self.reload_necessary = False
         self.restart_necessary = False
 
-        self.cmd_checkconf = self.default_cmd_checkconf
-        self.cmd_reload = self.default_cmd_reload
-        self.cmd_status = self.default_cmd_status
-        self.cmd_start = self.default_cmd_start
-        self.cmd_restart = self.default_cmd_restart
-
         self.named_keys = {}
         self.servers = {}
 
@@ -146,29 +120,130 @@ class PpDeployZonesApp(PpPDNSApplication):
         description = _('Generation of the BIND9 configuration file for slave zones.')
 
         super(PpDeployZonesApp, self).__init__(
-            appname=appname, version=version, description=description,
-            base_dir=base_dir, cfg_stems='dns-deploy-zones', environment="public",
+            appname=appname, version=version, description=description, base_dir=base_dir,
+            cfg_class=cfg_class, initialized=False, instance="public",
         )
 
         self.post_init()
 
+    # -------------------------------------------
+    @property
+    def cmd_named_checkconf(self):
+        """The OS command for named-checkconf."""
+
+        checkconf = DnsDeployZonesConfig.default_named_checkconf
+        if self.cfg:
+            checkconf = self.cfg.named_checkconf
+        return str(checkconf)
+
+    # -------------------------------------------
+    @property
+    def cmd_named_reload(self):
+        """The OS command to reload the BIND nameserver."""
+
+        rndc = DnsDeployZonesConfig.default_rndc
+        if self.cfg:
+            rndc = self.cfg.rndc
+
+        return "{} reload".format(rndc)
+
+    # -------------------------------------------
+    @property
+    def cmd_named_status(self):
+        """The OS command to show the status of the BIND nameserver service."""
+
+        systemctl = DnsDeployZonesConfig.default_systemctl
+        if self.cfg:
+            systemctl = self.cfg.systemctl
+
+        return "{} status".format(systemctl)
+
+    # -------------------------------------------
+    @property
+    def cmd_named_start(self):
+        """The OS command to start the BIND nameserver service."""
+
+        systemctl = DnsDeployZonesConfig.default_systemctl
+        if self.cfg:
+            systemctl = self.cfg.systemctl
+
+        return "{} start".format(systemctl)
+
+    # -------------------------------------------
+    @property
+    def cmd_named_restart(self):
+        """The OS command to restart the BIND nameserver service."""
+
+        systemctl = DnsDeployZonesConfig.default_systemctl
+        if self.cfg:
+            systemctl = self.cfg.systemctl
+
+        return "{} restart".format(systemctl)
+
     # -------------------------------------------
     @property
     def named_zones_cfg_file(self):
         """The file for configuration of all own zones."""
-        return os.path.join(self.named_conf_dir, self._named_zones_cfg_file)
+
+        conf_dir = DnsDeployZonesConfig.default_named_conf_dir
+        zones_cfg_file = DnsDeployZonesConfig.default_named_zones_cfg_file
+        if self.cfg:
+            conf_dir = self.cfg.named_conf_dir
+            zones_cfg_file = self.cfg.named_zones_cfg_file
+
+        return (conf_dir / zones_cfg_file).resolve()
 
     # -------------------------------------------
     @property
     def named_slavedir_rel(self):
         """The directory for zone files of slave zones."""
-        return self._named_slavedir
+
+        if self.cfg:
+            return self.cfg.named_slavedir
+        return DnsDeployZonesConfig.default_named_slavedir
+
+    # -------------------------------------------
+    @property
+    def named_basedir(self):
+        """The base directory of named, where all volatile data are stored."""
+
+        if self.cfg:
+            return self.cfg.named_basedir
+        return DnsDeployZonesConfig.default_named_basedir
 
     # -------------------------------------------
     @property
     def named_slavedir_abs(self):
         """The directory for zone files of slave zones."""
-        return os.path.join(self.named_basedir, self._named_slavedir)
+
+        return (self.named_basedir / self.named_slavedir_rel).resolve()
+
+    # -------------------------------------------------------------------------
+    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(DnsDeployZonesConfig, self).as_dict(short=short)
+
+        res['named_slavedir_abs'] = self.named_slavedir_abs
+        res['cmd_named_checkconf'] = self.cmd_named_checkconf
+        res['cmd_named_reload'] = self.cmd_named_reload
+        res['cmd_named_status'] = self.cmd_named_status
+        res['cmd_named_start'] = self.cmd_named_start
+        res['cmd_named_restart'] = self.cmd_named_restart
+        res['named_zones_cfg_file'] = self.named_zones_cfg_file
+        res['named_basedir'] = self.named_basedir
+        res['named_slavedir_rel'] = self.named_slavedir_rel
+        res['named_slavedir_abs'] = self.named_slavedir_abs
+
+        return res
 
     # -------------------------------------------------------------------------
     def init_arg_parser(self):
@@ -202,140 +277,42 @@ class PpDeployZonesApp(PpPDNSApplication):
         if self.args.keep_backup:
             self.keep_backup = True
 
-    # -------------------------------------------------------------------------
-    def perform_config(self):
-
-        super(PpDeployZonesApp, 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() == 'app':
-                self._check_path_config(section, section_name, 'pidfile', 'pidfile_name', True)
-                if 'keep-backup' in section:
-                    self.keep_backup = to_bool(section['keep-backup'])
-                if 'keep_backup' in section:
-                    self.keep_backup = to_bool(section['keep_backup'])
-
-            if section_name.lower() == 'named':
-                self.set_named_options(section, section_name)
-
-        if not self.masters_configured:
-            if self.environment == 'local':
-                self.zone_masters = copy.copy(self.zone_masters_local)
-            else:
-                self.zone_masters = copy.copy(self.zone_masters_public)
-
-    # -------------------------------------------------------------------------
-    def set_named_options(self, section, section_name):
-
-        if self.verbose > 2:
-            LOG.debug(
-                _("Evaluating config section {!r}:").format(section_name) + '\n' + pp(section))
-
-        # Configuration files and directories
-        self._check_path_config(
-            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 'listen_on_v6' in section and section['listen_on_v6'] is not None:
-            self.named_listen_on_v6 = to_bool(section['listen_on_v6'])
-
-        if 'masters' in section:
-            self._get_masters_from_cfg(section['masters'], section_name)
-
-        for item in (
-                'cmd_checkconf', 'cmd_reload', 'cmd_status', 'cmd_start',
-                'cmd_restart', 'zone_tsig_key'):
-            if item in section and section[item].strip():
-                setattr(self, item, section[item].strip())
-
-    # -------------------------------------------------------------------------
-    def _get_masters_from_cfg(self, value, section_name):
-
-        value = value.strip()
-        if not value:
-            msg = _("No masters given in [{}]/masters.").format(section_name)
-            LOG.error(msg)
-            self.config_has_errors = True
-            return
-
-        masters = []
-
-        for m in self.re_split_addresses.split(value):
-            if m:
-                m = m.strip().lower()
-                LOG.debug(_("Checking given master address {!r} ...").format(m))
-                try:
-                    addr_infos = socket.getaddrinfo(
-                        m, 53, proto=socket.IPPROTO_TCP)
-                    for addr_info in addr_infos:
-                        addr = addr_info[4][0]
-                        if not self.named_listen_on_v6 and addr_info[0] == socket.AF_INET6:
-                            msg = _(
-                                "Not using {!r} as a master IP address, because "
-                                "we are not using IPv6.").format(addr)
-                            LOG.debug(msg)
-                            continue
-                        if addr in masters:
-                            LOG.debug(_("Address {!r} are already in masters yet.").format(addr))
-                        else:
-                            LOG.debug(_("Address {!r} are not in masters yet.").format(addr))
-                            masters.append(addr)
-
-                except socket.gaierror as e:
-                    msg = _(
-                        "Invalid hostname or address {a!r} found in [{s}]/masters: {e}").format(
-                            a=m, s=section_name, e=e)
-                    LOG.error(msg)
-                    self.config_has_errors = True
-                    m = None
-        if masters:
-            if self.verbose > 2:
-                LOG.debug(_("Using configured masters: {}").format(pp(masters)))
-            self.zone_masters = masters
-            self.masters_configured = True
-        else:
-            LOG.warn(_("No valid masters found in configuration."))
-
     # -------------------------------------------------------------------------
     def post_init(self):
 
-        super(PpDeployZonesApp, self).post_init()
-        self.initialized = False
-
         if not self.quiet:
             print('')
 
         LOG.debug(_("Post init phase."))
 
-        LOG.debug(_("Checking for masters, which are local addresses ..."))
-        ext_masters = []
-        for addr in self.zone_masters:
-            if addr in self.local_addresses:
-                LOG.debug(
-                    _("Address {!r} is in list of local addresses.").format(addr))
-            else:
-                LOG.debug(
-                    _("Address {!r} is not in list of local addresses.").format(addr))
-                ext_masters.append(addr)
-        self.zone_masters = ext_masters
-        LOG.info(_("Using masters for slave zones: {}").format(
-            ', '.join(map(lambda x: '{!r}'.format(x), self.zone_masters))))
+        super(PpDeployZonesApp, self).post_init()
+
+        cmd_namedcheckconf = self.get_command('named-checkconf', resolve=True)
+        if not cmd_namedcheckconf:
+            self.exit(1)
+        self.cfg.named_checkconf = cmd_namedcheckconf
 
         self.pidfile = PidFile(
-            filename=self.pidfile_name, appname=self.appname, verbose=self.verbose,
+            filename=self.cfg.pidfile, appname=self.appname, verbose=self.verbose,
             base_dir=self.base_dir, simulate=self.simulate)
 
+        if 'TZ' in os.environ and os.environ['TZ']:
+            self.local_tz_name = os.environ['TZ']
+        try:
+            self.local_tz = timezone(self.local_tz_name)
+        except UnknownTimeZoneError:
+            LOG.error(_("Unknown time zone: {!r}.").format(self.local_tz_name))
+            self.exit(6)
+
         self.initialized = True
 
+    # -------------------------------------------------------------------------
+    def current_timestamp(self):
+
+        if self.local_tz:
+            return datetime.datetime.now(self.local_tz).strftime('%Y-%m-%d %H:%M:%S %Z')
+        return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+
     # -------------------------------------------------------------------------
     def pre_run(self):
         """
@@ -348,6 +325,7 @@ class PpDeployZonesApp(PpPDNSApplication):
         if my_uid:
             msg = _("You must be root to execute this script.")
             if self.simulate:
+                msg += ' ' + _("But in simulation mode we are continuing nevertheless.")
                 LOG.warn(msg)
                 time.sleep(1)
             else:
@@ -356,31 +334,16 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         super(PpDeployZonesApp, self).pre_run()
 
-        if self.environment == 'global':
+        if self.cfg.pdns_instance == 'global':
             LOG.error(_(
                 "Using the global DNS master is not supported, "
                 "please use 'local' or 'public'"))
             self.exit(1)
 
-        cmd_namedcheckconf = self.get_command('named-checkconf')
-        if not cmd_namedcheckconf:
-            self.exit(1)
-        self.cmd_checkconf = cmd_namedcheckconf
-
     # -------------------------------------------------------------------------
     def _run(self):
 
-        local_tz_name = 'Europe/Berlin'
-        if 'TZ' in os.environ and os.environ['TZ']:
-            local_tz_name = os.environ['TZ']
-        try:
-            local_tz = timezone(local_tz_name)
-        except UnknownTimeZoneError:
-            LOG.error(_("Unknown time zone: {!r}.").format(local_tz_name))
-            self.exit(6)
-
-        LOG.info(_("Starting: {}").format(
-            datetime.datetime.now(local_tz).strftime('%Y-%m-%d %H:%M:%S %Z')))
+        LOG.info(_("Starting: {}").format(self.current_timestamp()))
 
         self.get_named_keys()
 
@@ -412,8 +375,7 @@ class PpDeployZonesApp(PpPDNSApplication):
         finally:
             self.cleanup()
             self.pidfile = None
-            LOG.info(_("Ending: {}").format(
-                datetime.datetime.now(local_tz).strftime('%Y-%m-%d %H:%M:%S %Z')))
+            LOG.info(_("Ending: {}").format(self.current_timestamp()))
 
     # -------------------------------------------------------------------------
     def cleanup(self):
@@ -423,51 +385,48 @@ class PpDeployZonesApp(PpPDNSApplication):
         for tgt_file in self.moved_files.keys():
             backup_file = self.moved_files[tgt_file]
             LOG.debug(_("Searching for {!r}.").format(backup_file))
-            if os.path.exists(backup_file):
+            if backup_file.exists():
                 if self.keep_backup:
-                    LOG.info(_("Keep existing backup file {!r}.").format(backup_file))
+                    LOG.info(_("Keep existing backup file {!r}.").format(str(backup_file)))
                 else:
-                    LOG.info(_("Removing {!r} ...").format(backup_file))
+                    LOG.info(_("Removing {!r} ...").format(str(backup_file)))
                     if not self.simulate:
-                        os.remove(backup_file)
+                        backup_file.unlink()
 
         # -----------------------
         def emit_rm_err(function, path, excinfo):
             LOG.error(_("Error removing {p!r} - {c}: {e}").format(
-                p=path, c=excinfo[1].__class__.__name__, e=excinfo[1]))
+                p=str(path), c=excinfo[1].__class__.__name__, e=excinfo[1]))
 
         if self.tempdir:
             if self.keep_tempdir:
                 msg = _(
                     "Temporary directory {!r} will not be removed. "
-                    "It's on yours to remove it manually.").format(self.tempdir)
+                    "It's on yours to remove it manually.").format(str(self.tempdir))
                 LOG.warn(msg)
             else:
-                LOG.debug(_("Destroying temporary directory {!r} ...").format(self.tempdir))
-                shutil.rmtree(self.tempdir, False, emit_rm_err)
+                LOG.debug(_("Destroying temporary directory {!r} ...").format(str(self.tempdir)))
+                shutil.rmtree(str(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.tempdir = Path(tempfile.mkdtemp(prefix=(self.appname + '.'), suffix='.tmp.d'))
+        LOG.debug(_("Temporary directory: {!r}.").format(str(self.tempdir)))
 
-        self.temp_zones_cfg_file = os.path.join(
-            self.tempdir, self.default_named_zones_cfg_file)
+        self.temp_zones_cfg_file = self.tempdir / self.cfg.named_zones_cfg_file
 
         if self.verbose > 1:
-            LOG.debug(_("Temporary zones conf: {!r}").format(self.temp_zones_cfg_file))
+            LOG.debug(_("Temporary zones conf: {!r}").format(str(self.temp_zones_cfg_file)))
 
     # -------------------------------------------------------------------------
     def get_named_keys(self):
 
         LOG.info(_("Trying to get all keys from named.conf ..."))
 
-        cmd = shlex.split(str(self.cmd_checkconf))
+        cmd = shlex.split(self.cmd_named_checkconf)
         cmd.append('-p')
 
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
@@ -525,7 +484,7 @@ class PpDeployZonesApp(PpPDNSApplication):
     # -------------------------------------------------------------------------
     def generate_slave_cfg_file(self):
 
-        LOG.info(_("Generating {} ...").format(self.default_named_zones_cfg_file))
+        LOG.info(_("Generating {} ...").format(self.cfg.named_zones_cfg_file))
 
         cur_date = datetime.datetime.now().isoformat(' ')
 
@@ -533,7 +492,7 @@ class PpDeployZonesApp(PpPDNSApplication):
         lines.append('###############################################################')
         lines.append('')
         lines.append(' Bind9 configuration file for slave sones')
-        lines.append(' {}'.format(self.named_zones_cfg_file))
+        lines.append(' {}'.format(str(self.named_zones_cfg_file)))
         lines.append('')
         lines.append(' Generated at: {}'.format(cur_date))
         lines.append('')
@@ -567,13 +526,13 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         content += '\n// vim: ts=8 filetype=named noet noai\n'
 
-        with open(self.temp_zones_cfg_file, 'w', **self.open_args) as fh:
+        with self.temp_zones_cfg_file.open('w', **self.open_args) as fh:
             fh.write(content)
 
         if self.verbose > 2:
             LOG.debug(
                 _("Generated file {!r}:").format(
-                    self.temp_zones_cfg_file) + '\n' + content.strip())
+                    str(self.temp_zones_cfg_file)) + '\n' + content.strip())
 
     # -------------------------------------------------------------------------
     def generate_zone_config(self, zone_name):
@@ -700,33 +659,32 @@ class PpDeployZonesApp(PpPDNSApplication):
             raise PpDeployZonesError(_("Target file not defined."))
 
         LOG.debug(_("Comparing {one!r} with {two!r} ...").format(
-            one=file_src, two=file_tgt))
+            one=str(file_src), two=str(file_tgt)))
 
-        if not os.path.exists(file_src):
+        if not file_src.exists():
             msg = _("{what} {f!r} does not exists.").format(
-                what=_("Source file"), f=file_src)
+                what=_("Source file"), f=str(file_src))
             raise PpDeployZonesError(msg)
-        if not os.path.isfile(file_src):
+        if not file_src.is_file():
             msg = _("{what} {f!r} is not a regular file.").format(
-                what=_("Source file"), f=file_src)
+                what=_("Source file"), f=str(file_src))
             raise PpDeployZonesError(msg)
 
-        if not os.path.exists(file_tgt):
+        if not file_tgt.exists():
             msg = _("{what} {f!r} does not exists.").format(
-                what=_("Target file"), f=file_tgt)
+                what=_("Target file"), f=str(file_tgt))
             LOG.debug(msg)
             return False
-        if not os.path.isfile(file_tgt):
+        if not file_tgt.is_file():
             msg = _("{what} {f!r} is not a regular file.").format(
-                what=_("Target file"), f=file_tgt)
+                what=_("Target file"), f=str(file_tgt))
             raise PpDeployZonesError(msg)
 
         # Reading source file
         content_src = ''
         if self.verbose > 2:
-            LOG.debug(_("Reading {!r} ...").format(file_src))
-        with open(file_src, 'r', **self.open_args) as fh:
-            content_src = fh.read()
+            LOG.debug(_("Reading {!r} ...").format(str(file_src)))
+        content_src = file_src.read_text(**self.open_args)
         lines_str_src = self.re_block_comment.sub('', content_src)
         lines_str_src = self.re_line_comment.sub('', lines_str_src)
         lines_src = []
@@ -735,14 +693,15 @@ class PpDeployZonesApp(PpPDNSApplication):
             if line:
                 lines_src.append(line)
         if self.verbose > 3:
-            LOG.debug(_("Cleaned version of {!r}:").format(file_src) + '\n' + '\n'.join(lines_src))
+            msg = _("Cleaned version of {!r}:").format(str(file_src))
+            msg += '\n' + '\n'.join(lines_src)
+            LOG.debug(msg)
 
         # Reading target file
         content_tgt = ''
         if self.verbose > 2:
-            LOG.debug(_("Reading {!r} ...").format(file_tgt))
-        with open(file_tgt, 'r', **self.open_args) as fh:
-            content_tgt = fh.read()
+            LOG.debug(_("Reading {!r} ...").format(str(file_tgt)))
+        content_tgt = file_tgt.read_text(**self.open_args)
         lines_str_tgt = self.re_block_comment.sub('', content_tgt)
         lines_str_tgt = self.re_line_comment.sub('', lines_str_tgt)
         lines_tgt = []
@@ -751,13 +710,15 @@ class PpDeployZonesApp(PpPDNSApplication):
             if line:
                 lines_tgt.append(line)
         if self.verbose > 3:
-            LOG.debug(_("Cleaned version of {!r}:").format(file_tgt) + '\n' + '\n'.join(lines_tgt))
+            msg = _("Cleaned version of {!r}:").format(str(file_tgt))
+            msg += '\n' + '\n'.join(lines_tgt)
+            LOG.debug(msg)
 
         if len(lines_src) != len(lines_tgt):
             LOG.debug(_(
                 "Source file {sf!r} has different number essential lines ({sl}) than "
                 "the target file {tf!r} ({tl} lines).").format(
-                sf=file_src, sl=len(lines_src), tf=file_tgt, tl=len(lines_tgt)))
+                sf=str(file_src), sl=len(lines_src), tf=str(file_tgt), tl=len(lines_tgt)))
             return False
 
         i = 0
@@ -765,7 +726,7 @@ class PpDeployZonesApp(PpPDNSApplication):
             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=file_src, tf=lines_tgt))
+                    "the target file {tf!r}.").format(sf=str(file_src), tf=str(lines_tgt)))
                 return False
             i += 1
 
@@ -782,22 +743,24 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         for tgt_file in self.files2replace.keys():
 
-            backup_file = tgt_file + self.backup_suffix
+            backup_file = Path(str(tgt_file) + self.backup_suffix)
 
-            if os.path.exists(tgt_file):
+            if tgt_file.exists():
                 self.moved_files[tgt_file] = backup_file
-                LOG.info(_("Copying {frm!r} => {to!r} ...").format(frm=tgt_file, to=backup_file))
+                LOG.info(_("Copying {frm!r} => {to!r} ...").format(
+                    frm=str(tgt_file), to=str(backup_file)))
                 if not self.simulate:
-                    shutil.copy2(tgt_file, backup_file)
+                    shutil.copy2(str(tgt_file), str(backup_file))
 
         if self.verbose > 1:
             LOG.debug(_("All backuped config files:") + '\n' + pp(self.moved_files))
 
         for tgt_file in self.files2replace.keys():
             src_file = self.files2replace[tgt_file]
-            LOG.info(_("Copying {frm!r} => {to!r} ...").format(frm=src_file, to=tgt_file))
+            LOG.info(_("Copying {frm!r} => {to!r} ...").format(
+                frm=str(src_file), to=str(tgt_file)))
             if not self.simulate:
-                shutil.copy2(src_file, tgt_file)
+                shutil.copy2(str(src_file), str(tgt_file))
 
     # -------------------------------------------------------------------------
     def restore_configfiles(self):
@@ -806,18 +769,19 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         for tgt_file in self.moved_files.keys():
             backup_file = self.moved_files[tgt_file]
-            LOG.info(_("Moving {frm!r} => {to!r} ...").format(frm=backup_file, to=tgt_file))
+            LOG.info(_("Moving {frm!r} => {to!r} ...").format(
+                frm=str(backup_file), to=str(tgt_file)))
             if not self.simulate:
-                if os.path.exists(backup_file):
-                    os.rename(backup_file, tgt_file)
+                if backup_file.exists():
+                    backup_file.rename(tgt_file)
                 else:
-                    LOG.error(_("Could not find backup file {!r}.").format(backup_file))
+                    LOG.error(_("Could not find backup file {!r}.").format(str(backup_file)))
 
     # -------------------------------------------------------------------------
     def check_namedconf(self):
 
         LOG.info(_("Checking syntax correctness of named.conf ..."))
-        cmd = shlex.split(str(self.cmd_checkconf))
+        cmd = shlex.split(self.cmd_named_checkconf)
         if self.verbose > 2:
             cmd.append('-p')
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
@@ -855,7 +819,7 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         LOG.debug(_("Checking, whether named is running ..."))
 
-        cmd = shlex.split(self.cmd_status)
+        cmd = shlex.split(self.cmd_named_status)
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
         LOG.debug(_("Executing: {}").format(cmd_str))
 
@@ -887,7 +851,7 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         LOG.info(_("Starting {} ...").format('named'))
 
-        cmd = shlex.split(self.cmd_start)
+        cmd = shlex.split(self.cmd_named_start)
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
         LOG.debug(_("Executing: {}").format(cmd_str))
 
@@ -922,7 +886,7 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         LOG.info(_("Restarting {} ...").format('named'))
 
-        cmd = shlex.split(self.cmd_restart)
+        cmd = shlex.split(self.cmd_named_restart)
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
         LOG.debug(_("Executing: {}").format(cmd_str))
 
@@ -957,7 +921,7 @@ class PpDeployZonesApp(PpPDNSApplication):
 
         LOG.info(_("Reloading {} ...").format('named'))
 
-        cmd = shlex.split(self.cmd_reload)
+        cmd = shlex.split(self.cmd_named_reload)
         cmd_str = ' '.join(map(lambda x: pipes.quote(x), cmd))
         LOG.debug(_("Executing: {}").format(cmd_str))