diff --git a/LCS/PyCommon/dbcredentials.py b/LCS/PyCommon/dbcredentials.py index 5f3400446e46f2871058b90e649069b2d7b091b0..a2ae916fc079d812669491758a1c1fc9442ed98a 100644 --- a/LCS/PyCommon/dbcredentials.py +++ b/LCS/PyCommon/dbcredentials.py @@ -25,7 +25,7 @@ import pwd from ConfigParser import SafeConfigParser, NoSectionError, DuplicateSectionError from optparse import OptionGroup -__all__ = ["DBCredentials", "options_group", "parse_options"] +__all__ = ["DBCredentials", "options_group", "parse_options", "pg_connect_options"] # obtain the environment, and add USER and HOME if needed (since supervisord does not) environ = os.environ @@ -33,6 +33,7 @@ user_info = pwd.getpwuid(os.getuid()) environ.setdefault("HOME", user_info.pw_dir) environ.setdefault("USER", user_info.pw_name) + def findfiles(pattern): """ Returns a list of files matched by `pattern'. The pattern can include environment variables using the @@ -43,23 +44,44 @@ def findfiles(pattern): except KeyError: return [] -class DBCredentials: - defaults = { + +class Credentials: + def __init__(self): # Flavour of database (postgres, mysql, oracle, sqlite) - "type": "postgres", + self.type = "postgres" # Connection information (port 0 = use default) - "host": "localhost", - "port": 0, + self.host = "localhost" + self.port = 0 # Authentication - "user": "{USER}".format(**environ), - "password": "", + self.user = environ["USER"] + self.password = "" # Database selection - "database": "", - } + self.database = "" + + def __str__(self): + return "type={type} addr={host}:{port} auth={user}:{password} db={database}".format(**self.__dict__) + + def pg_connect_options(self): + """ + Returns a dict of options to provide to PyGreSQL's pg.connect function. Use: + + conn = pg.connect(**dbcreds.pg_connect_options()) + """ + return { + "host": self.host, + "port": self.port or -1, + + "user": self.user, + "passwd": self.password, + + "dbname": self.database, + } + +class DBCredentials: def __init__(self, filepatterns=None): """ Read database credentials from all configuration files matched by any of the patterns @@ -70,7 +92,7 @@ class DBCredentials: "{HOME}/.lofar/dbcredentials/*.ini", ] - self.config = SafeConfigParser(defaults=self.defaults) + self.config = SafeConfigParser() self.files = sum([findfiles(p) for p in filepatterns],[]) self.config.read(self.files) @@ -80,15 +102,25 @@ class DBCredentials: """ Return credentials for a given database. """ + # create default credentials + creds = Credentials() + + # read configuration try: d = dict(self.config.items(self._section(database))) + except NoSectionError: + return creds - # fix types - d["port"] = int(d["port"] or 0) + # parse and convert config information + if "host" in d: creds.host = d["host"] + if "port" in d: creds.port = int(d["port"] or 0) - return d - except NoSectionError: - return self.config.defaults() + if "user" in d: creds.user = d["user"] + if "password" in d: creds.password = d["password"] + + if "database" in d: creds.database = d["database"] + + return creds def set(self, database, credentials): @@ -119,6 +151,7 @@ class DBCredentials: def _section(self, database): return "database:%s" % (database,) + def options_group(parser): """ Return an optparse.OptionGroup containing command-line parameters @@ -156,14 +189,15 @@ def parse_options(options, filepatterns=None): creds = dbc.get(options.dbcredentials) # process supplied overrides - if options.dbName: creds["database"] = options.dbName - if options.dbHost: creds["host"] = options.dbHost - if options.dbPort: creds["port"] = options.dbPort - if options.dbUser: creds["user"] = options.dbUser - if options.dbPassword: creds["password"] = options.dbPassword + if options.dbHost: creds.host = options.dbHost + if options.dbPort: creds.port = options.dbPort + if options.dbUser: creds.user = options.dbUser + if options.dbPassword: creds.password = options.dbPassword + if options.dbName: creds.database = options.dbName return creds + if __name__ == "__main__": import sys from optparse import OptionParser @@ -198,5 +232,5 @@ if __name__ == "__main__": sys.exit(0) """ Print credentials of a specific database. """ - print "\n".join(["%s %s" % (k,v) for k,v in dbc.get(options.database).iteritems()]) + print str(dbc.get(options.database)) diff --git a/SAS/OTDB_Services/TreeService.py b/SAS/OTDB_Services/TreeService.py index 578d94ffefbeb76823bc98b6efc65ea874c2fc99..33cd9ba53ef7b30220171638df8b519d13124094 100755 --- a/SAS/OTDB_Services/TreeService.py +++ b/SAS/OTDB_Services/TreeService.py @@ -224,13 +224,12 @@ class PostgressMessageHandlerInterface(MessageHandlerInterface): self.connected = (self.connection and self.connection.status == 1) while not self.connected: try: - self.connection = pg.connect(user=self.dbcreds["user"], passwd=self.dbcreds["password"], host=self.dbcreds["host"], port=self.dbcreds["port"] or -1, dbname=self.dbcreds["database"]) + self.connection = pg.connect(**self.dbcreds.pg_connect_options()) self.connected = True - logger.info("Connected to database %s on host %s" % (self.dbcreds["database"], self.dbcreds["host"])) + logger.info("Connected to database %s" % (self.dbcreds,)) except (TypeError, SyntaxError, pg.InternalError), e: self.connected = False - logger.error("Not connected to database %s on host %s (anymore), retry in 5 seconds: %s" - % (self.dbcreds["database"], self.dbcreds["host"], e)) + logger.error("Not connected to database %s, retry in 5 seconds: %s" % (self.dbcreds, e)) time.sleep(5) class PostgressTaskSpecificationRequest(PostgressMessageHandlerInterface): diff --git a/SAS/OTDB_Services/TreeStatusEvents.py b/SAS/OTDB_Services/TreeStatusEvents.py index 32220e3b957e5b27fdf16be86da23c085c739390..47e4b19dd20c78be07f72fdd0a987c7a2105a353 100755 --- a/SAS/OTDB_Services/TreeStatusEvents.py +++ b/SAS/OTDB_Services/TreeStatusEvents.py @@ -106,16 +106,17 @@ if __name__ == "__main__": while alive and not connected: # Connect to the database try: - otdb_connection = pg.connect(user=dbcreds["user"], passwd=dbcreds["password"], host=dbcreds["host"], port=dbcreds["port"] or -1, dbname=dbcreds["database"]) + otdb_connection = pg.connect(**dbcreds.pg_connect_options()) connected = True + logger.info("Connected to database %s" % (dbcreds,)) + # Get list of allowed tree states allowed_states = {} for (state_nr, name) in otdb_connection.query("select id,name from treestate").getresult(): allowed_states[state_nr] = name except (TypeError, SyntaxError, pg.InternalError), e: connected = False - logger.error("Not connected to database %s on host %s (anymore), retry in 5 seconds: %s" - % (dbcreds["database"], dbcreds["host"], e)) + logger.error("Not connected to database %s, retry in 5 seconds: %s" % (dbcreds, e)) time.sleep(5) # When we are connected we can poll the database