diff --git a/ldvspec/connection/__init__.py b/ldvspec/connection/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ldvspec/connection/config.py b/ldvspec/connection/config.py new file mode 100644 index 0000000000000000000000000000000000000000..947d8c96042c4254fad4177bf46b4952903fbe7d --- /dev/null +++ b/ldvspec/connection/config.py @@ -0,0 +1,21 @@ +from configparser import ConfigParser + + +def read_config(section, filename='database.cfg'): + parser = ConfigParser() + try: + parser.read(filename) + except FileNotFoundError as exc: + raise FileNotFoundError( + "Configuration file with filename {0} not found".format(filename) + ) from exc + + db_settings = {} + if parser.has_section(section): + params = parser.items(section) + for param in params: + db_settings[param[0]] = param[1] + else: + raise Exception('Section {0} not found in the {1} file'.format(section, filename)) + + return db_settings diff --git a/ldvspec/connection/database.cfg b/ldvspec/connection/database.cfg new file mode 100644 index 0000000000000000000000000000000000000000..05df7ee81622d5db71a04bf57c38b2016bbc0e36 --- /dev/null +++ b/ldvspec/connection/database.cfg @@ -0,0 +1,15 @@ +[postgresql-local] +host=localhost +port=5433 +database=ldv-spec-db +user=postgres +password=secret + +[postgresql-ldv] +tunnelhost=dop821.astron.nl +tunnelusername=sdco +host=sdc-db.astron.nl +port=5432 +database=ldvadmin +user=ldvrbow +password=Wehn5CTYj1RcbstMSGls \ No newline at end of file diff --git a/ldvspec/connection/retrieve_db_connection.py b/ldvspec/connection/retrieve_db_connection.py new file mode 100644 index 0000000000000000000000000000000000000000..af8659de67ab2ac9f68ae86aa2b84a4e5521c789 --- /dev/null +++ b/ldvspec/connection/retrieve_db_connection.py @@ -0,0 +1,95 @@ +import sys + +import psycopg2 +from config import read_config +import logging +import argparse +from sshtunnel import SSHTunnelForwarder +import os + + +def connect_postgresql(section): + """ Connect to the PostgreSQL database server """ + conn = None + tunnel = None + try: + # read connection parameters + configuration = read_config(section=section) + + logging.info('Connecting PostgreSQL database %s', configuration.get('database', 'no database name given')) + + host = configuration.get('host', 'no host given') + if host != 'localhost': + tunnel = open_tunnel(configuration) + conn = psycopg2.connect(host='localhost', + port=tunnel.local_bind_port, + database=configuration.get('database'), + user=configuration.get('user'), + password=configuration.get('password')) + else: + conn = psycopg2.connect(**configuration) + + cur = conn.cursor() + cur.execute('SELECT version()') + db_version = cur.fetchone() + logging.info('Database version: ' + db_version[0]) + + except (Exception, psycopg2.DatabaseError) as error: + logging.error(error) + if tunnel is not None: + tunnel.stop() + + return conn, tunnel + + +def open_tunnel(configuration_params): + tunnel_host = configuration_params.get('tunnelhost', "no tunnel host given") + tunnel_username = configuration_params.get('tunnelusername', "no username for the tunnel given") + host = configuration_params.get('host', "no host given") + port = int(configuration_params.get('port', "no port given")) + + try: + ssh_config_file = os.path.expanduser("~/.ssh/config") + except FileNotFoundError as exc: + raise FileNotFoundError( + "Ssh config file not found on standard path '~/.ssh/config'. This is mandatory for opening the ssh tunnel" + ) from exc + + logging.info("Creating ssh tunnel for %s and port %s with tunnel host %s and username %s", repr(host), port, + repr(tunnel_host), repr(tunnel_username)) + ssh_tunnel = SSHTunnelForwarder( + ssh_address_or_host=tunnel_host, + ssh_username=tunnel_username, + ssh_config_file=ssh_config_file, + remote_bind_address=(host, port) + ) + ssh_tunnel.start() + return ssh_tunnel + + +def main(): + """ + Opens a database connection from configuration file database.cfg + """ + logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.DEBUG) + + # Check the invocation arguments + parser = argparse.ArgumentParser() + parser.add_argument("-s", "--section", help="Add the configuration's section from the database.cfg.") + args = parser.parse_args() + + if not args.section: + logging.critical("Error: no configuration section given. Try --help") + sys.exit(-1) + + return connect_postgresql(args.section) + + +if __name__ == '__main__': + connection, server = main() + if connection is not None: + connection.close() + logging.info('Database connection closed.') + if server is not None: + server.stop() + logging.info('Tunneled server stopped.') diff --git a/ldvspec/connection/test.py b/ldvspec/connection/test.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ldvspec/requirements/base.txt b/ldvspec/requirements/base.txt index 45954f46e55c36134e02bec5a7006d63434827a9..b0d8418bd30fe83d55dec70a510771eeef51bf61 100644 --- a/ldvspec/requirements/base.txt +++ b/ldvspec/requirements/base.txt @@ -10,4 +10,5 @@ whitenoise==5.0.1 six==1.15.0 fontawesome-free==5.15.2 pyyaml==6.0 -uritemplate==4.1.1 \ No newline at end of file +uritemplate==4.1.1 +sshtunnel==0.4.0 \ No newline at end of file