]> Frank Brehm's Git Trees - pixelpark/create-terraform.git/commitdiff
Moving some methods into mixin module lib/cr_tf/handler/dns.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Fri, 13 Oct 2023 13:58:31 +0000 (15:58 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Fri, 13 Oct 2023 13:58:31 +0000 (15:58 +0200)
lib/cr_tf/handler/__init__.py
lib/cr_tf/handler/dns.py [new file with mode: 0644]

index 7d270982f1e17873f2145894d6168dbf637d1486..5f177cbec194fcb256633723da395c6f43c69006 100644 (file)
@@ -12,8 +12,6 @@ from __future__ import absolute_import, print_function
 import os
 import logging
 import re
-import socket
-import ipaddress
 import shutil
 import stat
 import textwrap
@@ -32,7 +30,7 @@ from operator import attrgetter
 import pytz
 import six
 
-from fb_tools.common import pp, to_bool, to_str, RE_DOT_AT_END
+from fb_tools.common import pp, to_bool, to_str
 from fb_tools.errors import HandlerError, ExpectedHandlerError
 from fb_tools.handling_obj import HandlingObject, CalledProcessError
 from fb_tools.handler import BaseHandler
@@ -42,6 +40,7 @@ from fb_vmware.config import VSPhereConfigInfo
 from fb_vmware.connect import VsphereConnection
 
 # Own modules
+from .dns import CrTfHandlerDnsMixin
 from .first import CrTfHandlerFirstMixin
 from .read import CrTfHandlerReadMixin
 
@@ -54,7 +53,7 @@ from ..errors import AbortExecution
 
 from ..xlate import XLATOR
 
-__version__ = '3.9.3'
+__version__ = '3.9.4'
 LOG = logging.getLogger(__name__)
 
 _ = XLATOR.gettext
@@ -62,7 +61,8 @@ ngettext = XLATOR.ngettext
 
 
 # =============================================================================
-class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerReadMixin):
+class CreateTerraformHandler(
+        BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerReadMixin, CrTfHandlerDnsMixin):
     """
     A handler class for creating the terraform environment
     """
@@ -473,30 +473,6 @@ class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerRead
         if self.stop_at_step == 'collect-folders':
             raise AbortExecution('collect-folders')
 
-    # -------------------------------------------------------------------------·
-    def exec_pdns_zones(self):
-
-        if self.config.no_pdns:
-            return
-
-        if self.stop_at_step == 'pdns-zones':
-            self.incr_verbosity()
-
-        print()
-        LOG.info(_("Retrieving informations from PowerDNS ..."))
-
-        self.pdns.get_api_zones()
-        if self.eval_errors:
-            msg = ngettext(
-                "Found one error in exploring PowerDNS zones.",
-                "Found {n} errors in exploring PowerDNS zones.",
-                self.eval_errors).format(n=self.eval_errors)
-            raise ExpectedHandlerError(msg)
-
-        LOG.info(_("Finished step {!r}.").format('pdns-zones'))
-        if self.stop_at_step == 'pdns-zones':
-            raise AbortExecution('pdns-zones')
-
     # -------------------------------------------------------------------------·
     def init_vspheres(self, yaml_file):
 
@@ -812,36 +788,6 @@ class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerRead
         if self.stop_at_step == 'validate-iface':
             raise AbortExecution('validate-iface')
 
-    # -------------------------------------------------------------------------·
-    def exec_validate_dns(self):
-
-        if self.stop_at_step == 'validate-dns':
-            self.incr_verbosity()
-
-        self.validate_dns_mappings()
-        if self.eval_errors:
-            msg = ngettext(
-                "Found one error in validating DNS mappings.",
-                "Found {n} errors in validating DNS mappings.",
-                self.eval_errors).format(n=self.eval_errors)
-            raise ExpectedHandlerError(msg)
-
-        LOG.info(_("Finished step {!r}.").format('validate-dns'))
-        if self.stop_at_step == 'validate-dns':
-            raise AbortExecution('validate-dns')
-
-    # -------------------------------------------------------------------------·
-    def exec_perform_dns(self):
-
-        if self.stop_at_step == 'perform-dns':
-            self.incr_verbosity()
-
-        self.perform_dns()
-
-        LOG.info(_("Finished step {!r}.").format('perform-dns'))
-        if self.stop_at_step == 'perform-dns':
-            raise AbortExecution('perform-dns')
-
     # -------------------------------------------------------------------------·
     def exec_project_dir(self):
 
@@ -1390,145 +1336,6 @@ class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerRead
         if network not in self.used_networks[vs_name]:
             self.used_networks[vs_name].append(network)
 
-    # -------------------------------------------------------------------------·
-    def validate_dns_mappings(self):
-
-        LOG.info(_("Validating DNS mappings ..."))
-        self._validate_forward_dns_mappings()
-        self._validate_reverse_dns_mappings()
-
-        lines = []
-        if self.dns_mappings2create['forward']:
-            for pair in self.dns_mappings2create['forward']:
-                line = '  * {n!r} => {a!r}'.format(n=pair[0], a=str(pair[1]))
-                lines.append(line)
-        else:
-            lines.append(self.colored('>>> ' + _('None') + ' <<<', 'AQUA'))
-        LOG.info(_("Forward DNS entries to create:") + "\n" + '\n'.join(lines))
-
-        lines = []
-        if self.dns_mappings2create['reverse']:
-            for pair in self.dns_mappings2create['reverse']:
-                line = '  * {r} ({a!r}) => {n!r}'.format(
-                    r=pair[0].reverse_pointer, n=pair[1], a=str(pair[0]))
-                lines.append(line)
-        else:
-            lines.append(self.colored('>>> ' + _('None') + ' <<<', 'AQUA'))
-        LOG.info(_("Reverse DNS entries to create:") + "\n" + '\n'.join(lines))
-
-    # -------------------------------------------------------------------------·
-    def _validate_forward_dns_mappings(self):
-
-        if not self.dns_mapping['forward']:
-            return
-
-        LOG.debug(_("Validating forward DNS mappings ..."))
-
-        for (fqdn, address) in self.dns_mapping['forward']:
-
-            if self.verbose > 1:
-                LOG.debug(_("Validating {f!r} => {a!r}.").format(f=fqdn, a=str(address)))
-
-            results_v4 = []
-            results_v6 = []
-
-            try:
-                addr_infos = socket.getaddrinfo(fqdn, 80)
-            except socket.gaierror:
-                addr_infos = []
-
-            for addr_info in addr_infos:
-                if addr_info[0] not in (socket.AF_INET, socket.AF_INET6):
-                    continue
-                addr = ipaddress.ip_address(addr_info[4][0])
-                if addr.version == 4:
-                    if addr not in results_v4:
-                        results_v4.append(addr)
-                else:
-                    if addr not in results_v6:
-                        results_v6.append(addr)
-            if self.verbose > 2:
-                if results_v4 or results_v6:
-                    lines = []
-                    for addr in results_v4 + results_v6:
-                        lines.append('  * {}'.format(str(addr)))
-                    out = '\n'.join(lines)
-                    LOG.debug(_("Found existing addresses for {f!r}:").format(f=fqdn) + '\n' + out)
-                else:
-                    LOG.debug(_("Did not found existing addresses for {!r}.").format(fqdn))
-
-            if address.version == 4:
-                if not results_v4:
-                    self.dns_mappings2create['forward'].append((fqdn, address))
-                    continue
-                if address in results_v4:
-                    LOG.debug(_("FQDN {f!r} already points to {a!r}.").format(
-                        f=fqdn, a=str(address)))
-                    continue
-            else:
-                if not results_v6:
-                    self.dns_mappings2create['forward'].append((fqdn, address))
-                    continue
-                if address in results_v6:
-                    LOG.debug(_("FQDN {f!r} already points to {a!r}.").format(
-                        f=fqdn, a=str(address)))
-                    continue
-
-            alist = '\n'.join(map(lambda x: '  * {}'.format(str(x)), results_v4 + results_v6))
-            msg = (_(
-                "FQDN {f!r} has already existing addresses, "
-                "but none of them are {a!r}:").format(f=fqdn, a=str(address)) + "\n" + alist)
-            if self.ignore_existing_dns:
-                LOG.warn(msg)
-                self.dns_mappings2create['forward'].append((fqdn, address))
-            else:
-                LOG.error(msg)
-                self.eval_errors += 1
-
-    # -------------------------------------------------------------------------·
-    def _validate_reverse_dns_mappings(self):
-
-        if not self.dns_mapping['reverse']:
-            return
-
-        LOG.debug(_("Validating reverse DNS mappings ..."))
-
-        for (address, fqdn) in self.dns_mapping['reverse']:
-
-            if self.verbose > 1:
-                LOG.debug(_("Validating {a!r} => {f!r}.").format(f=fqdn, a=str(address)))
-
-            try:
-                info = socket.gethostbyaddr(str(address))
-            except socket.herror:
-                info = []
-            if self.verbose > 2:
-                LOG.debug(_("Got reverse info:") + "\n" + str(info))
-            ptr = None
-            if info:
-                ptr = info[0]
-
-            if not ptr:
-                if self.verbose > 1:
-                    LOG.debug(_("Did not found reverse pointer for {!r}.").format(str(address)))
-                self.dns_mappings2create['reverse'].append((address, fqdn))
-                continue
-
-            ptr = RE_DOT_AT_END.sub('', ptr).lower()
-            fqdn_canon = RE_DOT_AT_END.sub('', fqdn).lower()
-
-            if self.verbose > 1:
-                LOG.debug(_("Found reverse pointer {a!r} => {f!r}.").format(f=ptr, a=str(address)))
-            if fqdn_canon == ptr:
-                if self.verbose > 1:
-                    LOG.debug(_("Reverse pointer for {!r} was already existing.").format(
-                        str(address)))
-                continue
-
-            LOG.error(_("Address {a!r} has already an existing reverse pointer to {p!r}.").format(
-                a=str(address), p=ptr))
-            self.eval_errors += 1
-
     # -------------------------------------------------------------------------·
     def get_tf_name_network(self, net_name, *args):
 
@@ -1592,109 +1399,6 @@ class CreateTerraformHandler(BaseHandler, CrTfHandlerFirstMixin, CrTfHandlerRead
             return default
         raise KeyError(_("Did not found datastore {!r}.").format(ds_name))
 
-    # --------------------------------------------------------------------------
-    def perform_dns(self):
-
-        if self.config.no_pdns:
-            LOG.debug(_("Power DNS actions are not eceuted."))
-            return
-
-        print()
-        LOG.info(_("Performing DNS actions ..."))
-        print()
-
-        # TODO: Check for simulate and mappings to create
-
-        errors = 0
-
-        for (fqdn, address) in self.dns_mappings2create['forward']:
-            if not self._perform_dns_forward(fqdn, address):
-                errors += 1
-
-        for (address, fqdn) in self.dns_mappings2create['reverse']:
-            if not self._perform_dns_reverse(address, fqdn):
-                errors += 1
-
-        if errors:
-            msg = ngettext(
-                "There was one error in creating DNS mappings.",
-                "There were {n} errors in creating DNS mappings.", errors).format(n=errors)
-            raise ExpectedHandlerError(msg)
-        else:
-            if self.verbose > 1:
-                LOG.debug(_("No errors in creating DNS mappings."))
-
-        print()
-
-        for zone_name in self.updated_zones:
-            self._increase_zone_serial(zone_name)
-
-    # --------------------------------------------------------------------------
-    def _increase_zone_serial(self, zone_name):
-
-        LOG.info(_("Increasing serial of zone {!r}.").format(zone_name))
-
-        zone = self.pdns.zones[zone_name]
-        zone.increase_serial()
-        zone.notify()
-
-    # --------------------------------------------------------------------------
-    def _perform_dns_forward(self, fqdn, address):
-
-        record_type = 'A'
-        addr_obj = ipaddress.ip_address(address)
-        if addr_obj.version == 6:
-            record_type = 'AAAA'
-
-        canon_fqdn = self.pdns.canon_name(fqdn)
-
-        zone_name = self.pdns.get_zone_for_item(canon_fqdn, is_fqdn=True)
-        if zone_name:
-            if self.verbose > 1:
-                LOG.debug(_("Got zone {z!r} for FQDN {f!r}.").format(
-                    z=zone_name, f=canon_fqdn))
-        else:
-            LOG.error(_("Did not found zone to insert {t}-record for {f!r}.").format(
-                t=record_type, f=fqdn))
-            return False
-
-        zone = self.pdns.zones[zone_name]
-        if addr_obj.is_private:
-            zone.add_address_record(
-                fqdn, address, set_ptr=False, comment='local',
-                account=self.config.pdns_comment_account, append_comments=True)
-        else:
-            zone.add_address_record(fqdn, address, set_ptr=False)
-        if zone_name not in self.updated_zones:
-            self.updated_zones.append(zone_name)
-        return True
-
-    # --------------------------------------------------------------------------
-    def _perform_dns_reverse(self, address, fqdn):
-
-        LOG.debug(_("Trying to create PTR-record {a!r} => {f!r}.").format(
-            f=fqdn, a=str(address)))
-
-        pointer = self.pdns.canon_name(address.reverse_pointer)
-        if self.verbose > 1:
-            LOG.debug(_("PTR of {a!r}: {p!r}.").format(a=str(address), p=pointer))
-
-        zone_name = self.pdns.get_zone_for_item(pointer, is_fqdn=True)
-        if zone_name:
-            if self.verbose > 1:
-                LOG.debug(_("Got reverse zone {z!r} for address {a!r}.").format(
-                    z=zone_name, a=str(address)))
-        else:
-            LOG.warn(_("Did not found zone to insert PTR-record {p!r} ({a}).").format(
-                p=pointer, a=str(address)))
-            return True
-
-        zone = self.pdns.zones[zone_name]
-        zone.add_ptr_record(pointer, fqdn)
-        if zone_name not in self.updated_zones:
-            self.updated_zones.append(zone_name)
-        return True
-
     # --------------------------------------------------------------------------
     def ensure_project_dir(self):
 
diff --git a/lib/cr_tf/handler/dns.py b/lib/cr_tf/handler/dns.py
new file mode 100644 (file)
index 0000000..612aa81
--- /dev/null
@@ -0,0 +1,342 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2023 by Frank Brehm, Berlin
+@summary: A mixin module for the handler module for dns related methods.
+"""
+from __future__ import absolute_import, print_function
+
+# Standard module
+import ipaddress
+import logging
+import socket
+
+# Third party modules
+from fb_tools.common import RE_DOT_AT_END
+from fb_tools.errors import ExpectedHandlerError
+
+# Own modules
+
+from ..errors import AbortExecution
+
+from ..xlate import XLATOR
+
+__version__ = '0.1.0'
+LOG = logging.getLogger(__name__)
+
+_ = XLATOR.gettext
+ngettext = XLATOR.ngettext
+
+
+# =============================================================================
+class CrTfHandlerDnsMixin():
+    """A mixin module for the handler module for dns related methods."""
+
+    # -------------------------------------------------------------------------·
+    def exec_pdns_zones(self):
+
+        if self.config.no_pdns:
+            return
+
+        if self.stop_at_step == 'pdns-zones':
+            self.incr_verbosity()
+
+        print()
+        LOG.info(_("Retrieving informations from PowerDNS ..."))
+
+        self.pdns.get_api_zones()
+        if self.eval_errors:
+            msg = ngettext(
+                "Found one error in exploring PowerDNS zones.",
+                "Found {n} errors in exploring PowerDNS zones.",
+                self.eval_errors).format(n=self.eval_errors)
+            raise ExpectedHandlerError(msg)
+
+        LOG.info(_("Finished step {!r}.").format('pdns-zones'))
+        if self.stop_at_step == 'pdns-zones':
+            raise AbortExecution('pdns-zones')
+
+    # -------------------------------------------------------------------------·
+    def exec_validate_dns(self):
+
+        if self.stop_at_step == 'validate-dns':
+            self.incr_verbosity()
+
+        self.validate_dns_mappings()
+        if self.eval_errors:
+            msg = ngettext(
+                "Found one error in validating DNS mappings.",
+                "Found {n} errors in validating DNS mappings.",
+                self.eval_errors).format(n=self.eval_errors)
+            raise ExpectedHandlerError(msg)
+
+        LOG.info(_("Finished step {!r}.").format('validate-dns'))
+        if self.stop_at_step == 'validate-dns':
+            raise AbortExecution('validate-dns')
+
+    # -------------------------------------------------------------------------·
+    def exec_perform_dns(self):
+
+        if self.stop_at_step == 'perform-dns':
+            self.incr_verbosity()
+
+        self.perform_dns()
+
+        LOG.info(_("Finished step {!r}.").format('perform-dns'))
+        if self.stop_at_step == 'perform-dns':
+            raise AbortExecution('perform-dns')
+
+    # --------------------------------------------------------------------------
+    def perform_dns(self):
+
+        if self.config.no_pdns:
+            LOG.debug(_("Power DNS actions are not eceuted."))
+            return
+
+        print()
+        LOG.info(_("Performing DNS actions ..."))
+        print()
+
+        # TODO: Check for simulate and mappings to create
+
+        errors = 0
+
+        for (fqdn, address) in self.dns_mappings2create['forward']:
+            if not self._perform_dns_forward(fqdn, address):
+                errors += 1
+
+        for (address, fqdn) in self.dns_mappings2create['reverse']:
+            if not self._perform_dns_reverse(address, fqdn):
+                errors += 1
+
+        if errors:
+            msg = ngettext(
+                "There was one error in creating DNS mappings.",
+                "There were {n} errors in creating DNS mappings.", errors).format(n=errors)
+            raise ExpectedHandlerError(msg)
+        else:
+            if self.verbose > 1:
+                LOG.debug(_("No errors in creating DNS mappings."))
+
+        print()
+
+        for zone_name in self.updated_zones:
+            self._increase_zone_serial(zone_name)
+
+    # --------------------------------------------------------------------------
+    def _increase_zone_serial(self, zone_name):
+
+        LOG.info(_("Increasing serial of zone {!r}.").format(zone_name))
+
+        zone = self.pdns.zones[zone_name]
+        zone.increase_serial()
+        zone.notify()
+
+    # --------------------------------------------------------------------------
+    def _perform_dns_forward(self, fqdn, address):
+
+        record_type = 'A'
+        addr_obj = ipaddress.ip_address(address)
+        if addr_obj.version == 6:
+            record_type = 'AAAA'
+
+        canon_fqdn = self.pdns.canon_name(fqdn)
+
+        zone_name = self.pdns.get_zone_for_item(canon_fqdn, is_fqdn=True)
+        if zone_name:
+            if self.verbose > 1:
+                LOG.debug(_("Got zone {z!r} for FQDN {f!r}.").format(
+                    z=zone_name, f=canon_fqdn))
+        else:
+            LOG.error(_("Did not found zone to insert {t}-record for {f!r}.").format(
+                t=record_type, f=fqdn))
+            return False
+
+        zone = self.pdns.zones[zone_name]
+        if addr_obj.is_private:
+            zone.add_address_record(
+                fqdn, address, set_ptr=False, comment='local',
+                account=self.config.pdns_comment_account, append_comments=True)
+        else:
+            zone.add_address_record(fqdn, address, set_ptr=False)
+        if zone_name not in self.updated_zones:
+            self.updated_zones.append(zone_name)
+        return True
+
+    # --------------------------------------------------------------------------
+    def _perform_dns_reverse(self, address, fqdn):
+
+        LOG.debug(_("Trying to create PTR-record {a!r} => {f!r}.").format(
+            f=fqdn, a=str(address)))
+
+        pointer = self.pdns.canon_name(address.reverse_pointer)
+        if self.verbose > 1:
+            LOG.debug(_("PTR of {a!r}: {p!r}.").format(a=str(address), p=pointer))
+
+        zone_name = self.pdns.get_zone_for_item(pointer, is_fqdn=True)
+        if zone_name:
+            if self.verbose > 1:
+                LOG.debug(_("Got reverse zone {z!r} for address {a!r}.").format(
+                    z=zone_name, a=str(address)))
+        else:
+            LOG.warn(_("Did not found zone to insert PTR-record {p!r} ({a}).").format(
+                p=pointer, a=str(address)))
+            return True
+
+        zone = self.pdns.zones[zone_name]
+        zone.add_ptr_record(pointer, fqdn)
+        if zone_name not in self.updated_zones:
+            self.updated_zones.append(zone_name)
+        return True
+
+    # -------------------------------------------------------------------------·
+    def validate_dns_mappings(self):
+
+        LOG.info(_("Validating DNS mappings ..."))
+        self._validate_forward_dns_mappings()
+        self._validate_reverse_dns_mappings()
+
+        lines = []
+        if self.dns_mappings2create['forward']:
+            for pair in self.dns_mappings2create['forward']:
+                line = '  * {n!r} => {a!r}'.format(n=pair[0], a=str(pair[1]))
+                lines.append(line)
+        else:
+            lines.append(self.colored('>>> ' + _('None') + ' <<<', 'AQUA'))
+        LOG.info(_("Forward DNS entries to create:") + "\n" + '\n'.join(lines))
+
+        lines = []
+        if self.dns_mappings2create['reverse']:
+            for pair in self.dns_mappings2create['reverse']:
+                line = '  * {r} ({a!r}) => {n!r}'.format(
+                    r=pair[0].reverse_pointer, n=pair[1], a=str(pair[0]))
+                lines.append(line)
+        else:
+            lines.append(self.colored('>>> ' + _('None') + ' <<<', 'AQUA'))
+        LOG.info(_("Reverse DNS entries to create:") + "\n" + '\n'.join(lines))
+
+    # -------------------------------------------------------------------------·
+    def _validate_forward_dns_mappings(self):
+
+        if not self.dns_mapping['forward']:
+            return
+
+        LOG.debug(_("Validating forward DNS mappings ..."))
+
+        for (fqdn, address) in self.dns_mapping['forward']:
+
+            if self.verbose > 1:
+                LOG.debug(_("Validating {f!r} => {a!r}.").format(f=fqdn, a=str(address)))
+
+            results_v4 = []
+            results_v6 = []
+
+            try:
+                addr_infos = socket.getaddrinfo(fqdn, 80)
+            except socket.gaierror:
+                addr_infos = []
+
+            for addr_info in addr_infos:
+                if addr_info[0] not in (socket.AF_INET, socket.AF_INET6):
+                    continue
+                addr = ipaddress.ip_address(addr_info[4][0])
+                if addr.version == 4:
+                    if addr not in results_v4:
+                        results_v4.append(addr)
+                else:
+                    if addr not in results_v6:
+                        results_v6.append(addr)
+            if self.verbose > 2:
+                if results_v4 or results_v6:
+                    lines = []
+                    for addr in results_v4 + results_v6:
+                        lines.append('  * {}'.format(str(addr)))
+                    out = '\n'.join(lines)
+                    LOG.debug(_("Found existing addresses for {f!r}:").format(f=fqdn) + '\n' + out)
+                else:
+                    LOG.debug(_("Did not found existing addresses for {!r}.").format(fqdn))
+
+            if address.version == 4:
+                if not results_v4:
+                    self.dns_mappings2create['forward'].append((fqdn, address))
+                    continue
+                if address in results_v4:
+                    LOG.debug(_("FQDN {f!r} already points to {a!r}.").format(
+                        f=fqdn, a=str(address)))
+                    continue
+            else:
+                if not results_v6:
+                    self.dns_mappings2create['forward'].append((fqdn, address))
+                    continue
+                if address in results_v6:
+                    LOG.debug(_("FQDN {f!r} already points to {a!r}.").format(
+                        f=fqdn, a=str(address)))
+                    continue
+
+            alist = '\n'.join(map(lambda x: '  * {}'.format(str(x)), results_v4 + results_v6))
+            msg = (_(
+                "FQDN {f!r} has already existing addresses, "
+                "but none of them are {a!r}:").format(f=fqdn, a=str(address)) + "\n" + alist)
+            if self.ignore_existing_dns:
+                LOG.warn(msg)
+                self.dns_mappings2create['forward'].append((fqdn, address))
+            else:
+                LOG.error(msg)
+                self.eval_errors += 1
+
+    # -------------------------------------------------------------------------·
+    def _validate_reverse_dns_mappings(self):
+
+        if not self.dns_mapping['reverse']:
+            return
+
+        LOG.debug(_("Validating reverse DNS mappings ..."))
+
+        for (address, fqdn) in self.dns_mapping['reverse']:
+
+            if self.verbose > 1:
+                LOG.debug(_("Validating {a!r} => {f!r}.").format(f=fqdn, a=str(address)))
+
+            try:
+                info = socket.gethostbyaddr(str(address))
+            except socket.herror:
+                info = []
+            if self.verbose > 2:
+                LOG.debug(_("Got reverse info:") + "\n" + str(info))
+            ptr = None
+            if info:
+                ptr = info[0]
+
+            if not ptr:
+                if self.verbose > 1:
+                    LOG.debug(_("Did not found reverse pointer for {!r}.").format(str(address)))
+                self.dns_mappings2create['reverse'].append((address, fqdn))
+                continue
+
+            ptr = RE_DOT_AT_END.sub('', ptr).lower()
+            fqdn_canon = RE_DOT_AT_END.sub('', fqdn).lower()
+
+            if self.verbose > 1:
+                LOG.debug(_("Found reverse pointer {a!r} => {f!r}.").format(f=ptr, a=str(address)))
+            if fqdn_canon == ptr:
+                if self.verbose > 1:
+                    LOG.debug(_("Reverse pointer for {!r} was already existing.").format(
+                        str(address)))
+                continue
+
+            LOG.error(_("Address {a!r} has already an existing reverse pointer to {p!r}.").format(
+                a=str(address), p=ptr))
+            self.eval_errors += 1
+
+
+# =============================================================================
+
+if __name__ == "__main__":
+
+    pass
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list