From: Michael Tremer Date: Sat, 25 Apr 2015 11:18:07 +0000 (+0200) Subject: Perform lazy initialization of the database X-Git-Url: http://git.ipfire.org/?p=people%2Fms%2Fddns.git;a=commitdiff_plain;h=63e16feedea3639ef1f21fecbff9ed2ae256728b Perform lazy initialization of the database The database will only be initialized when it is actually needed. That makes starting up ddns a bit faster and allows us to execute it as non-root for simple commands like "list-providers". If the database path is not writable at all, the database feature is disable and an error message is logged. This will hopefully help us to perform the DNS update even when there is a local misconfiguration. --- diff --git a/src/ddns/database.py b/src/ddns/database.py index 5d4ffc9..42c3433 100644 --- a/src/ddns/database.py +++ b/src/ddns/database.py @@ -20,7 +20,7 @@ ############################################################################### import datetime -import os.path +import os import sqlite3 # Initialize the logger. @@ -31,9 +31,11 @@ logger.propagate = 1 class DDNSDatabase(object): def __init__(self, core, path): self.core = core + self.path = path - # Open the database file - self._db = self._open_database(path) + # We won't open the connection to the database directly + # so that we do not do it unnecessarily. + self._db = None def __del__(self): self._close_database() @@ -46,7 +48,7 @@ class DDNSDatabase(object): conn = sqlite3.connect(path, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES) conn.isolation_level = None - if not exists: + if not exists and self.is_writable(): logger.debug("Initialising database layout") c = conn.cursor() c.executescript(""" @@ -68,12 +70,25 @@ class DDNSDatabase(object): return conn + def is_writable(self): + # Check if the database file exists and is writable. + ret = os.access(self.path, os.W_OK) + if ret: + return True + + # If not, we check if we are able to write to the directory. + # In that case the database file will be created in _open_database(). + return os.access(os.path.dirname(self.path), os.W_OK) + def _close_database(self): if self._db: self._db_close() self._db = None def _execute(self, query, *parameters): + if self._db is None: + self._db = self._open_database(self.path) + c = self._db.cursor() try: c.execute(query, parameters) @@ -81,6 +96,10 @@ class DDNSDatabase(object): c.close() def add_update(self, hostname, status, message=None): + if not self.is_writable(): + logger.warning("Could not log any updates because the database is not writable") + return + self._execute("INSERT INTO updates(hostname, status, message, timestamp) \ VALUES(?, ?, ?, ?)", hostname, status, message, datetime.datetime.utcnow())