|
#!/usr/local/bin/python
# encoding: utf-8
"""
*Class to setup database object for the breaker*
:Author:
David Young
:Date Created:
October 29, 2015
"""
################# GLOBAL IMPORTS ####################
import sys
import os
os.environ['TERM'] = 'vt100'
import readline
import glob
import pickle
import time
import pymysql as ms
from docopt import docopt
from fundamentals import tools, times
class database():
"""
*The worker class for the database module*
**Key Arguments:**
- ``log`` -- logger
- ``settings`` -- the settings dictionary
"""
# INITIALISATION
def __init__(
self,
log,
settings=False,
):
self.log = log
log.debug("instansiating a new '_database' object")
self.settings = settings
return None
def close(self):
del self
return None
# METHOD ATTRIBUTES
def get(self):
"""
*get the database object*
**Return:**
- ``self.transientsDbConn, self.ps1gwDbConn, self.cataloguesDbConn`` -- three database connections
"""
self.log.debug('starting the ``get`` method')
self._setup_database_connections()
self.log.debug('completed the ``get`` method')
return self.ligo_virgo_wavesDbConn, self.ps1gwDbConn, self.cataloguesDbConn, self.atlasDbConn, self.ps13piDbConn
def _setup_database_connections(
self):
"""
*setup database connections for transient and catalogue databases*
"""
self.log.debug('starting the ``_setup_database_connections`` method')
from subprocess import Popen, PIPE, STDOUT
tunnelDatabases = {}
for db in self.settings["database settings"]:
port = self.settings["database settings"][db]["port"]
if "tunnel" in str(port):
if port not in tunnelDatabases.keys():
tunnelDatabases[port] = []
tunnelDatabases[port].append(
db)
# SETUP TUNNEL IF REQUIRED
if "ssh tunnels" in self.settings:
tunnels = self.settings["ssh tunnels"]
for tunnelName in tunnels:
tunnel = self.settings["ssh tunnels"][tunnelName]
# TEST TUNNEL DOES NOT ALREADY EXIST
sshPort = tunnel["port"]
for db in tunnelDatabases[tunnelName]:
connected = self._checkServer(
self.settings["database settings"][db]["host"], sshPort)
if connected:
break
if connected:
self.log.debug('ssh tunnel already exists - moving on')
else:
# GRAB TUNNEL SETTINGS FROM SETTINGS FILE
ru = tunnel["remote user"]
rip = tunnel["remote ip"]
rh = tunnel["remote datbase host"]
cmd = "ssh -fnN %(ru)s@%(rip)s -L %(sshPort)s:%(rh)s:3306" % locals()
p = Popen(cmd, shell=True, close_fds=True)
output = p.communicate()[0]
self.log.debug('output: %(output)s' % locals())
# TEST CONNECTION - QUIT AFTER SO MANY TRIES
connected = False
count = 0
while not connected:
for db in tunnelDatabases[tunnelName]:
connected = self._checkServer(
self.settings["database settings"][db]["host"], sshPort)
if connected:
break
time.sleep(1)
count += 1
if count == 5:
self.log.error(
'cound not setup tunnel to remote datbase' % locals())
sys.exit(0)
# SETUP A DATABASE CONNECTION FOR THE ps1gw
host = self.settings["database settings"][
"ps1gw"]["host"]
user = self.settings["database settings"][
"ps1gw"]["user"]
passwd = self.settings["database settings"][
"ps1gw"]["password"]
dbName = self.settings["database settings"][
"ps1gw"]["db"]
port = self.settings["database settings"][
"ps1gw"]["port"]
if "tunnel" in str(port):
port = self.settings["ssh tunnels"][port]["port"]
thisConn = ms.connect(
host=host,
user=user,
passwd=passwd,
db=dbName,
port=port,
use_unicode=True,
charset='utf8'
)
thisConn.autocommit(True)
self.log.debug('ps1gwDbConn: %s' % (thisConn,))
self.ps1gwDbConn = thisConn
# SETUP A DATABASE CONNECTION FOR THE ps13pi
host = self.settings["database settings"][
"ps13pi"]["host"]
user = self.settings["database settings"][
"ps13pi"]["user"]
passwd = self.settings["database settings"][
"ps13pi"]["password"]
dbName = self.settings["database settings"][
"ps13pi"]["db"]
port = self.settings["database settings"][
"ps13pi"]["port"]
if "tunnel" in str(port):
port = self.settings["ssh tunnels"][port]["port"]
thisConn = ms.connect(
host=host,
user=user,
passwd=passwd,
db=dbName,
port=port,
use_unicode=True,
charset='utf8'
)
thisConn.autocommit(True)
self.log.debug('ps13piDbConn: %s' % (thisConn,))
self.ps13piDbConn = thisConn
# SETUP A DATABASE CONNECTION FOR THE altas DATABASE
host = self.settings["database settings"][
"atlas"]["host"]
user = self.settings["database settings"][
"atlas"]["user"]
passwd = self.settings["database settings"][
"atlas"]["password"]
dbName = self.settings["database settings"][
"atlas"]["db"]
port = self.settings["database settings"][
"atlas"]["port"]
if "tunnel" in str(port):
port = self.settings["ssh tunnels"][port]["port"]
thisConn = ms.connect(
host=host,
user=user,
passwd=passwd,
db=dbName,
port=port,
use_unicode=True,
charset='utf8'
)
thisConn.autocommit(True)
self.log.debug('altasDbConn: %s' % (thisConn,))
self.atlasDbConn = thisConn
# SETUP DATABASE CONNECTION FOR WAVE DATABASE
host = self.settings["database settings"][
"ligo_virgo_waves"]["host"]
user = self.settings["database settings"][
"ligo_virgo_waves"]["user"]
passwd = self.settings["database settings"][
"ligo_virgo_waves"]["password"]
dbName = self.settings["database settings"][
"ligo_virgo_waves"]["db"]
port = self.settings["database settings"][
"ligo_virgo_waves"]["port"]
if "tunnel" in str(port):
port = self.settings["ssh tunnels"][port]["port"]
thisConn = ms.connect(
host=host,
user=user,
passwd=passwd,
db=dbName,
port=port,
use_unicode=True,
charset='utf8'
)
thisConn.autocommit(True)
self.log.debug('ligo_virgo_wavesDbConn: %s' % (thisConn,))
self.ligo_virgo_wavesDbConn = thisConn
# SETUP DATABASE CONNECTION FOR CATALOGUE DATABASE
host = self.settings["database settings"][
"catalogues"]["host"]
user = self.settings["database settings"][
"catalogues"]["user"]
passwd = self.settings["database settings"][
"catalogues"]["password"]
dbName = self.settings["database settings"][
"catalogues"]["db"]
port = self.settings["database settings"][
"catalogues"]["port"]
if "tunnel" in str(port):
port = self.settings["ssh tunnels"][port]["port"]
thisConn = ms.connect(
host=host,
user=user,
passwd=passwd,
db=dbName,
port=port,
use_unicode=True,
charset='utf8'
)
thisConn.autocommit(True)
self.log.debug('catalogues database connection: %s' % (thisConn,))
self.cataloguesDbConn = thisConn
self.log.debug('completed the ``_setup_database_connections`` method')
return None
def _checkServer(self, address, port):
"""
*Check that the TCP Port we've decided to use for tunnelling is available*
"""
self.log.debug('starting the ``_checkServer`` method')
# CREATE A TCP SOCKET
import socket
s = socket.socket()
self.log.debug(
"""Attempting to connect to `%(address)s` on port `%(port)s`""" % locals())
try:
s.connect((address, port))
self.log.debug(
"""Connected to `%(address)s` on port `%(port)s`""" % locals())
return True
except socket.error, e:
self.log.info(
"""Connection to `%(address)s` on port `%(port)s` failed - try again: %(e)s""" % locals())
return False
return None
# xt-class-method
if __name__ == '__main__':
main()
|