]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Adding DB connection stuff
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 11 Jan 2018 15:42:12 +0000 (16:42 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 11 Jan 2018 15:42:12 +0000 (16:42 +0100)
bin/check-dnsui-users
etc/check-dnsui-users.ini.default
pp_lib/dnsui_users.py

index fa4ef4e95777689ef91ea8ee1b1ba36c1fb89b2e..0d8c667ecfd0df42e148451a99ab04e06b8afc99 100755 (executable)
@@ -34,7 +34,7 @@ app.initialized = True
 if app.verbose > 2:
     print("{c}-Object:\n{a}".format(c=app.__class__.__name__, a=app))
 
-#app()
+app()
 
 sys.exit(0)
 
index 3f42897afcb2562c02e855255080667a726ec318..c8f965df6d47494421ac89c6fb7f4f5feb05d143 100644 (file)
@@ -34,4 +34,23 @@ bind_dn = uid=Solaris_NSS,ou=Unix NSS,ou=Applications,o=pixelpark,o=isp
 # Timeout in seconds for all LDAP operations
 timeout = 5
 
+
+[database]
+; Connection details to the Postgres database
+
+# Zhe hostname or address of the PostgreSQL instance
+#host = master.pp-dns.com
+
+# The TCP port number of the PostgreSQL instance
+#port = 5432
+
+# The database in the PostgreSQL instance
+#db = dnsui
+
+# The name of the database user
+#user = pdnsadm
+
+# The password of the database user
+#password =
+
 # vim: filetype=dosini
index 2d815365cb665657c68ea0f62901b6e5d2c088ea..c1e8bb291bd3b8a9ef55236ccb051695ec4854a0 100644 (file)
@@ -12,6 +12,7 @@ from __future__ import absolute_import
 import logging
 import logging.config
 import textwrap
+import socket
 
 # Third party modules
 # from ldap3 import ObjectDef, AttrDef, Reader, Writer
@@ -23,7 +24,7 @@ from .common import pp
 
 from .ldap_app import PpLdapAppError, PpLdapApplication
 
-__version__ = '0.1.1'
+__version__ = '0.2.1'
 LOG = logging.getLogger(__name__)
 
 
@@ -41,12 +42,26 @@ class DnsuiUsersApp(PpLdapApplication):
 
     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('''\
@@ -60,7 +75,149 @@ class DnsuiUsersApp(PpLdapApplication):
 
         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()
 
 # =============================================================================