import logging
import logging.config
import textwrap
+import socket
# Third party modules
# from ldap3 import ObjectDef, AttrDef, Reader, Writer
from .ldap_app import PpLdapAppError, PpLdapApplication
-__version__ = '0.1.1'
+__version__ = '0.2.1'
LOG = logging.getLogger(__name__)
default_admin_group = "cn=Administratoren Pixelpark Berlin,ou=Groups,o=Pixelpark,o=isp"
+ # DB data
+ default_db_host = 'master.pp-dns.com'
+ default_db_port = 5432
+ default_db_db = 'dnsui'
+ default_db_user = 'pdnsadm'
+
# -------------------------------------------------------------------------
def __init__(self, appname=None, version=__version__):
self.admin_users = []
self.admin_group = self.default_admin_group
+ self.db_host = self.default_db_host
+ self.db_port = self.default_db_port
+ self.db_db = self.default_db_db
+ self.db_user = self.default_db_user
+ self.db_pass = None
+
+ self.db_connection = None
+
self._show_simulate_opt = True
description = textwrap.dedent('''\
self.initialized = True
+ # -------------------------------------------------------------------------
+ def perform_config(self):
+ """
+ Execute some actions after reading the configuration.
+
+ This method should be explicitely called by all perform_config()
+ methods in descendant classes.
+ """
+
+ super(DnsuiUsersApp, self).perform_config()
+
+ for section_name in self.cfg.keys():
+
+ if self.verbose > 2:
+ LOG.debug("Checking config section {!r} ...".format(section_name))
+ section = self.cfg[section_name]
+
+ if section_name.lower() in ('db', 'database'):
+ self.do_db_cfg(section_name, section)
+
+ # -------------------------------------------------------------------------
+ def do_db_cfg(self, section_name, section):
+
+ if self.verbose > 2:
+ LOG.debug("Evaluating config section {n!r}:\n{s}".format(
+ n=section_name, s=pp(section)))
+
+ if 'host' in section:
+ host = section['host'].lower().strip()
+ if not host:
+ LOG.error('Invalid hostname {!r} in configuration section {!r} found.'.format(
+ section['host'], section_name))
+ else:
+ try:
+ _ = socket.getaddrinfo(host, 5432, proto=socket.IPPROTO_TCP)
+ except socket.gaierror as e:
+ msg = 'Invalid hostname {!r} in configuration section {!r}: {}'.format(
+ section['host'], section_name, e)
+ LOG.error(msg)
+ self.config_has_errors = True
+ else:
+ self.db_host = host
+
+ if 'port' in section:
+ try:
+ port = int(section['port'])
+ if port <= 0:
+ raise ValueError("port number may not be negative.")
+ elif port >= (2 ** 16):
+ raise ValueError("port number must be less than {}".format((2 ** 16)))
+ except (ValueError, TypeError) as e:
+ msg = 'Invalid port number {!r} in configuration section {!r}: {}'.format(
+ section['port'],section_name, e)
+ LOG.error(msg)
+ self.config_has_errors = True
+ else:
+ self.db_port = port
+
+ if 'db' in section:
+ db = section['db'].lower().strip()
+ if not db:
+ LOG.error('Invalid database name {!r} in configuration section {!r} found.'.format(
+ section['db'], section_name))
+ else:
+ self.db_db = db
+
+ if 'user' in section:
+ user = section['user'].lower().strip()
+ if not user:
+ LOG.error('Invalid database user {!r} in configuration section {!r} found.'.format(
+ section['user'], section_name))
+ self.config_has_errors = True
+ else:
+ self.db_user = user
+
+ if 'password' in section:
+ self.db_pass = section['password']
+
+ # -------------------------------------------------------------------------
+ def pre_run(self):
+
+ self.connect_db()
+
+ # -------------------------------------------------------------------------
+ def connect_db(self):
+
+ result = None
+
+ LOG.debug("Connecting to PostgreSQL database on {}@{}:{}/{} ...".format(
+ self.db_user, self.db_host, self.db_port, self.db_db))
+ try:
+ self.db_connection = psycopg2.connect(
+ host=self.db_host,
+ port=self.db_port,
+ dbname=self.db_db,
+ user=self.db_user,
+ password=self.db_pass,
+ )
+
+ sql = 'SHOW server_version'
+ if self.verbose > 1:
+ LOG.debug("SQL: {}".format(sql))
+ with self.db_connection.cursor() as cursor:
+ cursor.execute(sql)
+ result = cursor.fetchone()
+ if self.verbose > 2:
+ LOG.debug("Got version info:\n{}".format(pp(result)))
+ LOG.info("Database is PostgreSQL version {!r}.".format(result[0]))
+
+ except psycopg2.OperationalError as e:
+ LOG.error("Could not connect to database ({}): {}".format(
+ e.__class__.__name__, e))
+ self.exit(7)
+
+ # -------------------------------------------------------------------------
+ def _run(self):
+
+ try:
+
+ LOG.info("Starting user checks ...")
+
+ finally:
+ self._close_db()
+
+ # -------------------------------------------------------------------------
+ def _close_db(self):
+
+ if self.db_connection:
+ LOG.debug("Closing database connection.")
+ try:
+ self.db_connection.close()
+ except Exception as e:
+ LOG.error("Could not close database connection ({}): {}".format(
+ e.__class__.__name__, e))
+ traceback.print_exc()
+ self.db_connection = None
+
+ # -------------------------------------------------------------------------
+ def post_run(self):
+ if self.verbose > 1:
+ LOG.info("executing post_run() ...")
+ self._close_db()
# =============================================================================