reformatted code to pep8 convention
This commit is contained in:
parent
c750804914
commit
197e94d320
431
SimpaDbUtil.py
431
SimpaDbUtil.py
|
@ -1,251 +1,258 @@
|
||||||
import MySQLdb
|
import MySQLdb
|
||||||
import time
|
import time
|
||||||
import subprocess
|
|
||||||
import StringIO
|
import StringIO
|
||||||
import re
|
import re
|
||||||
from wol import *
|
from wol import *
|
||||||
import os
|
import os
|
||||||
import signal
|
|
||||||
from Util import *
|
from Util import *
|
||||||
import abc
|
import abc
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from mysql2sqlite import mysql_to_sqlite
|
from mysql2sqlite import mysql_to_sqlite
|
||||||
|
|
||||||
|
|
||||||
def isMachineResponding(machineName):
|
def isMachineResponding(machineName):
|
||||||
(returnCode, stdout, stderr) = executeProgram( [ 'ping', '-o', '-t', '1', machineName ] )
|
(returnCode, stdout, stderr) = executeProgram(['ping', '-o', '-t', '1', machineName])
|
||||||
#log( 'isMachineResponding : result of command %s : %d' % (command, returnCode) )
|
# log( 'isMachineResponding : result of command %s : %d' % (command, returnCode) )
|
||||||
|
|
||||||
if returnCode == 0:
|
if returnCode == 0:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
bMachineNameIsNotKnown = (returnCode == 68)
|
bMachineNameIsNotKnown = (returnCode == 68)
|
||||||
bMachineIsNotResponding = (returnCode == 2)
|
bMachineIsNotResponding = (returnCode == 2)
|
||||||
if bMachineIsNotResponding == False:
|
if bMachineIsNotResponding is False:
|
||||||
bBUG_00000004_IS_STILL_ALIVE = True
|
bBUG_00000004_IS_STILL_ALIVE = True
|
||||||
if bBUG_00000004_IS_STILL_ALIVE == True and returnCode == 142:
|
if bBUG_00000004_IS_STILL_ALIVE is True and returnCode == 142:
|
||||||
log('isMachineResponding : bug00000004 Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName) )
|
log('isMachineResponding : bug00000004 Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName))
|
||||||
# don't stop the program until we understand bug00000004
|
# don't stop the program until we understand bug00000004
|
||||||
elif bBUG_00000004_IS_STILL_ALIVE == True and returnCode == -14: # I had this error code on 07/09/2009 20:38 but I don't know yet what that means
|
elif bBUG_00000004_IS_STILL_ALIVE is True and returnCode == -14: # I had this error code on 07/09/2009 20:38 but I don't know yet what that means
|
||||||
log('isMachineResponding : bug00000004 Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName) )
|
log('isMachineResponding : bug00000004 Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName))
|
||||||
# don't stop the program until we understand bug00000004
|
# don't stop the program until we understand bug00000004
|
||||||
else:
|
else:
|
||||||
log('isMachineResponding : Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName) )
|
log('isMachineResponding : Unexpected return code : returnCode=%d, stdout="%s", stderr="%s" , machineName = %s' % (returnCode, stdout, stderr, machineName))
|
||||||
assert(False)
|
assert(False)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class ISqlDatabaseBackend(object):
|
class ISqlDatabaseBackend(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def query(self, sql_query):
|
||||||
|
"""
|
||||||
|
:param str sql_query: the sql query to perform
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def query(self, sql_query):
|
|
||||||
"""
|
|
||||||
:param str sql_query: the sql query to perform
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
class RemoteMysqlDb(ISqlDatabaseBackend):
|
class RemoteMysqlDb(ISqlDatabaseBackend):
|
||||||
def __init__(self, db_server_fqdn, db_user, db_name):
|
def __init__(self, db_server_fqdn, db_user, db_name):
|
||||||
"""
|
"""
|
||||||
:param str db_server_fqdn: the fully qualified domain name of the server hosting the database, eg simpatix10.univ-rennes1.fr
|
:param str db_server_fqdn: the fully qualified domain name of the server hosting the database, eg simpatix10.univ-rennes1.fr
|
||||||
:param str db_user: the user for accessing the inventory database, eg simpadb_reader
|
:param str db_user: the user for accessing the inventory database, eg simpadb_reader
|
||||||
:param str db_name: the name of the inventory database, eg simpadb
|
:param str db_name: the name of the inventory database, eg simpadb
|
||||||
"""
|
"""
|
||||||
self._db_server_fqdn = db_server_fqdn
|
self._db_server_fqdn = db_server_fqdn
|
||||||
self._db_user = db_user
|
self._db_user = db_user
|
||||||
self._db_name = db_name
|
self._db_name = db_name
|
||||||
self._connect()
|
self._connect()
|
||||||
|
|
||||||
def _connect(self):
|
def _connect(self):
|
||||||
self._conn = MySQLdb.connect(self._db_server_fqdn, self._db_user, '', self._db_name)
|
self._conn = MySQLdb.connect(self._db_server_fqdn, self._db_user, '', self._db_name)
|
||||||
assert(self._conn)
|
assert(self._conn)
|
||||||
|
|
||||||
def query(self, sql_query):
|
def query(self, sql_query):
|
||||||
"""
|
"""
|
||||||
:param str sql_query: the sql query to perform
|
:param str sql_query: the sql query to perform
|
||||||
"""
|
"""
|
||||||
self._conn.query( sql_query )
|
self._conn.query(sql_query)
|
||||||
rows = conn.store_result()
|
rows = conn.store_result()
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
class SqlFile(ISqlDatabaseBackend):
|
class SqlFile(ISqlDatabaseBackend):
|
||||||
def __init__(self, sql_file_path, truncate_hex_strings = False):
|
def __init__(self, sql_file_path, truncate_hex_strings=False):
|
||||||
"""
|
"""
|
||||||
:param str sql_file_path: the path of the sql file containing the inventory database
|
:param str sql_file_path: the path of the sql file containing the inventory database
|
||||||
"""
|
"""
|
||||||
self._sql_file_path = sql_file_path
|
self._sql_file_path = sql_file_path
|
||||||
self._cur = None # sqlite cursor
|
self._cur = None # sqlite cursor
|
||||||
|
|
||||||
sqlite_db_path=':memory:' # sqlite-specific special name for a file stored in memory. We could use something like '/tmp/simpadb.sqlite' here but this would make parsing really slow (1 minute instead of 1s), unless either :
|
sqlite_db_path = ':memory:' # sqlite-specific special name for a file stored in memory. We could use something like '/tmp/simpadb.sqlite' here but this would make parsing really slow (1 minute instead of 1s), unless either :
|
||||||
# - proper fix : group of INSERT statements are surrounded by BEGIN and COMMIT (see http://stackoverflow.com/questions/4719836/python-and-sqlite3-adding-thousands-of-rows)
|
# - proper fix : group of INSERT statements are surrounded by BEGIN and COMMIT (see http://stackoverflow.com/questions/4719836/python-and-sqlite3-adding-thousands-of-rows)
|
||||||
# - the file is stored on a solid state disk
|
# - the file is stored on a solid state disk
|
||||||
try:
|
try:
|
||||||
os.remove(sqlite_db_path)
|
os.remove(sqlite_db_path)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
check_same_thread = False
|
check_same_thread = False
|
||||||
# this is to prevent the following error when run from apache/django : SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 139672342353664 and this is thread id 139672333960960
|
# this is to prevent the following error when run from apache/django : SQLite objects created in a thread can only be used in that same thread.The object was created in thread id 139672342353664 and this is thread id 139672333960960
|
||||||
# accordig to https://stackoverflow.com/questions/48218065/programmingerror-sqlite-objects-created-in-a-thread-can-only-be-used-in-that-sa this is ok, as long as there are no concurrent writes
|
# accordig to https://stackoverflow.com/questions/48218065/programmingerror-sqlite-objects-created-in-a-thread-can-only-be-used-in-that-sa this is ok, as long as there are no concurrent writes
|
||||||
# If set False, the returned connection may be shared across multiple threads. When using multiple threads with the same connection writing operations should be serialized by the user to avoid data corruption
|
# If set False, the returned connection may be shared across multiple threads. When using multiple threads with the same connection writing operations should be serialized by the user to avoid data corruption
|
||||||
# I hope it's safe here but I'm not 100% sure though. Anyway, if the database gets corrupt, it not a big deal since this memory resident database gets reconstructed from the sql file...
|
# I hope it's safe here but I'm not 100% sure though. Anyway, if the database gets corrupt, it not a big deal since this memory resident database gets reconstructed from the sql file...
|
||||||
self._con = sqlite3.connect(sqlite_db_path, check_same_thread=check_same_thread)
|
self._con = sqlite3.connect(sqlite_db_path, check_same_thread=check_same_thread)
|
||||||
f = open(self._sql_file_path, 'r')
|
f = open(self._sql_file_path, 'r')
|
||||||
sql = f.read() # watch out for built-in `str`
|
sql = f.read() # watch out for built-in `str`
|
||||||
#print(sql)
|
# print(sql)
|
||||||
self._cur = self._con.cursor()
|
self._cur = self._con.cursor()
|
||||||
#print(mysql_to_sqlite(sql))
|
# print(mysql_to_sqlite(sql))
|
||||||
sqlite_sql = mysql_to_sqlite(sql, truncate_hex_strings)
|
sqlite_sql = mysql_to_sqlite(sql, truncate_hex_strings)
|
||||||
#with open('/tmp/toto.sqlite.sql', 'w') as f:
|
# with open('/tmp/toto.sqlite.sql', 'w') as f:
|
||||||
# f.write(sqlite_sql)
|
# f.write(sqlite_sql)
|
||||||
#with open('/tmp/toto.sqlite.sql', 'r') as f:
|
# with open('/tmp/toto.sqlite.sql', 'r') as f:
|
||||||
# sqlite_sql = f.read()
|
# sqlite_sql = f.read()
|
||||||
self._cur.executescript(sqlite_sql)
|
self._cur.executescript(sqlite_sql)
|
||||||
|
|
||||||
def query(self, sql_query):
|
def query(self, sql_query):
|
||||||
"""
|
"""
|
||||||
:param str sql_query: the sql query to perform
|
:param str sql_query: the sql query to perform
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
self._cur.execute( sql_query )
|
self._cur.execute(sql_query)
|
||||||
rows = self._cur.fetchall()
|
rows = self._cur.fetchall()
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
class SqlDatabaseReader(object):
|
class SqlDatabaseReader(object):
|
||||||
|
|
||||||
def __init__(self, inv_provider):
|
def __init__(self, inv_provider):
|
||||||
"""
|
"""
|
||||||
:param ISqlDatabaseBackend inv_provider: the input that provides the inventory data
|
:param ISqlDatabaseBackend inv_provider: the input that provides the inventory data
|
||||||
"""
|
"""
|
||||||
self._inv_provider = inv_provider
|
self._inv_provider = inv_provider
|
||||||
|
|
||||||
def query(self, sql_query):
|
def query(self, sql_query):
|
||||||
"""
|
"""
|
||||||
performs a query on the sql database
|
performs a query on the sql database
|
||||||
|
|
||||||
:param str sql_query: the sql query to perform
|
:param str sql_query: the sql query to perform
|
||||||
"""
|
"""
|
||||||
return self._inv_provider.query(sql_query)
|
return self._inv_provider.query(sql_query)
|
||||||
|
|
||||||
def get_table_attr(self, table, key_name, key_value, attr_name ):
|
def get_table_attr(self, table, key_name, key_value, attr_name):
|
||||||
"""
|
"""
|
||||||
reads the value of the fiven attribute of the given item in the given table
|
reads the value of the fiven attribute of the given item in the given table
|
||||||
|
|
||||||
:param str table: the name of the table to read
|
:param str table: the name of the table to read
|
||||||
:param str key_name: the name of the column that stores the id of the item to read
|
:param str key_name: the name of the column that stores the id of the item to read
|
||||||
:param str key_value: the id of the item to read
|
:param str key_value: the id of the item to read
|
||||||
:param str attr_name: the name of the attribute to read from the item
|
:param str attr_name: the name of the attribute to read from the item
|
||||||
"""
|
"""
|
||||||
attr_value = None
|
attr_value = None
|
||||||
rows = self.query("SELECT "+attr_name+" FROM "+table+" WHERE "+key_name+"='"+key_value+"'")
|
rows = self.query("SELECT " + attr_name + " FROM " + table + " WHERE " + key_name + "='" + key_value + "'")
|
||||||
if len(rows) > 0:
|
if len(rows) > 0:
|
||||||
attr_value = rows[0][0]
|
attr_value = rows[0][0]
|
||||||
return attr_value
|
return attr_value
|
||||||
|
|
||||||
def machineNameToMacAddress( machineName ):
|
|
||||||
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
|
||||||
assert(conn)
|
|
||||||
sqlQuery = """SELECT mac_address FROM ethernet_cards WHERE machine_name='"""+machineName+"""' AND type='normal'"""
|
|
||||||
#print sqlQuery
|
|
||||||
conn.query( sqlQuery )
|
|
||||||
r=conn.store_result()
|
|
||||||
row = r.fetch_row(0)
|
|
||||||
assert( len(row) == 1 )
|
|
||||||
#print 'row =', row
|
|
||||||
macAddress = row[0][0]
|
|
||||||
#print macAddress
|
|
||||||
conn.close()
|
|
||||||
return macAddress
|
|
||||||
|
|
||||||
def getLightOutManagementIpAddress( machineName ):
|
def machineNameToMacAddress(machineName):
|
||||||
"""
|
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
||||||
the light out management ip of servers allows to talk to the server even when it's asleep
|
assert(conn)
|
||||||
"""
|
sqlQuery = """SELECT mac_address FROM ethernet_cards WHERE machine_name='""" + machineName + """' AND type='normal'"""
|
||||||
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
# print sqlQuery
|
||||||
assert(conn)
|
conn.query(sqlQuery)
|
||||||
sqlQuery = """SELECT ip_address_1,ip_address_2,ip_address_3,ip_address_4 FROM ethernet_cards WHERE machine_name='"""+machineName+"""' AND type='light_out_management'"""
|
r = conn.store_result()
|
||||||
#print sqlQuery
|
row = r.fetch_row(0)
|
||||||
conn.query( sqlQuery )
|
assert( len(row) == 1)
|
||||||
r=conn.store_result()
|
# print 'row =', row
|
||||||
row = r.fetch_row(0)
|
macAddress = row[0][0]
|
||||||
assert( len(row) == 1 )
|
# print macAddress
|
||||||
#print 'row =', row
|
conn.close()
|
||||||
ipAddress = ('%s.%s.%s.%s') % (row[0][0], row[0][1], row[0][2], row[0][3])
|
return macAddress
|
||||||
#print macAddress
|
|
||||||
conn.close()
|
|
||||||
return ipAddress
|
def getLightOutManagementIpAddress(machineName):
|
||||||
|
"""
|
||||||
|
the light out management ip of servers allows to talk to the server even when it's asleep
|
||||||
|
"""
|
||||||
|
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
||||||
|
assert(conn)
|
||||||
|
sqlQuery = """SELECT ip_address_1,ip_address_2,ip_address_3,ip_address_4 FROM ethernet_cards WHERE machine_name='""" + machineName + """' AND type='light_out_management'"""
|
||||||
|
# print sqlQuery
|
||||||
|
conn.query(sqlQuery)
|
||||||
|
r = conn.store_result()
|
||||||
|
row = r.fetch_row(0)
|
||||||
|
assert(len(row) == 1)
|
||||||
|
# print 'row =', row
|
||||||
|
ipAddress = ('%s.%s.%s.%s') % (row[0][0], row[0][1], row[0][2], row[0][3])
|
||||||
|
# print macAddress
|
||||||
|
conn.close()
|
||||||
|
return ipAddress
|
||||||
|
|
||||||
|
|
||||||
def getClusterMachinesNames():
|
def getClusterMachinesNames():
|
||||||
clusterMachinesNames = []
|
clusterMachinesNames = []
|
||||||
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
conn = MySQLdb.connect('simpatix10', 'simpadb_reader', '', 'simpadb')
|
||||||
assert(conn)
|
assert(conn)
|
||||||
sqlQuery = """SELECT name FROM machines WHERE affectation='cluster'"""
|
sqlQuery = """SELECT name FROM machines WHERE affectation='cluster'"""
|
||||||
#print sqlQuery
|
# print sqlQuery
|
||||||
conn.query( sqlQuery )
|
conn.query(sqlQuery)
|
||||||
r=conn.store_result()
|
r = conn.store_result()
|
||||||
rows = r.fetch_row(0)
|
rows = r.fetch_row(0)
|
||||||
for row in rows:
|
for row in rows:
|
||||||
#print row
|
# print row
|
||||||
clusterMachinesNames.append( row[0] )
|
clusterMachinesNames.append(row[0])
|
||||||
conn.close()
|
conn.close()
|
||||||
return clusterMachinesNames
|
return clusterMachinesNames
|
||||||
|
|
||||||
def machineSupportsIpmi( machineName ):
|
|
||||||
if (machineName == 'simpatix') or (machineName == 'simpatix01' or (machineName == 'simpa-mac2')):
|
|
||||||
# the command ipmitool sensor on simpatix doesn't work :
|
|
||||||
# Unabled to establish a session with the BMC.
|
|
||||||
# Command failed due to Unknown (0xFFFEF921) (0xFFFEF921)
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def putToSleep( machineName ):
|
def machineSupportsIpmi(machineName):
|
||||||
# note : pmset must be executed as root
|
if (machineName == 'simpatix') or (machineName == 'simpatix01' or (machineName == 'simpa-mac2')):
|
||||||
(returnCode, stdout, stderr) = executeCommand([ 'ssh', machineName, 'pmset sleepnow' ])
|
# the command ipmitool sensor on simpatix doesn't work :
|
||||||
"""
|
# Unabled to establish a session with the BMC.
|
||||||
print returnCode
|
# Command failed due to Unknown (0xFFFEF921) (0xFFFEF921)
|
||||||
print 'stdout :'
|
return False
|
||||||
print stdout
|
return True
|
||||||
print 'stderr :'
|
|
||||||
print stderr
|
|
||||||
"""
|
def putToSleep(machineName):
|
||||||
assert( returnCode == 0 )
|
# note : pmset must be executed as root
|
||||||
# check if the command succeeded by looking at the output (that's the only way I found)
|
(returnCode, stdout, stderr) = executeCommand(['ssh', machineName, 'pmset sleepnow'])
|
||||||
f = StringIO.StringIO(stdout)
|
"""
|
||||||
line = f.readline()
|
print returnCode
|
||||||
f.close()
|
print 'stdout :'
|
||||||
matchObj = re.match('^Sleeping now...', line)
|
print stdout
|
||||||
if matchObj:
|
print 'stderr :'
|
||||||
return True
|
print stderr
|
||||||
else:
|
"""
|
||||||
return False
|
assert(returnCode == 0)
|
||||||
|
# check if the command succeeded by looking at the output (that's the only way I found)
|
||||||
|
f = StringIO.StringIO(stdout)
|
||||||
|
line = f.readline()
|
||||||
|
f.close()
|
||||||
|
matchObj = re.match('^Sleeping now...', line)
|
||||||
|
if matchObj:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def wakeUp(machineName):
|
def wakeUp(machineName):
|
||||||
macAddress = machineNameToMacAddress( machineName )
|
macAddress = machineNameToMacAddress(machineName)
|
||||||
wake_on_lan(macAddress)
|
wake_on_lan(macAddress)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def isNonRespondingMachineSleeping(machineName):
|
def isNonRespondingMachineSleeping(machineName):
|
||||||
"""
|
"""
|
||||||
note : crappy method to detect if the machine is sleeping (if other methods are available, I would be very interested)
|
note : crappy method to detect if the machine is sleeping (if other methods are available, I would be very interested)
|
||||||
"""
|
"""
|
||||||
wakeUp(machineName)
|
wakeUp(machineName)
|
||||||
time.sleep(120)
|
time.sleep(120)
|
||||||
if isMachineResponding( machineName ):
|
if isMachineResponding(machineName):
|
||||||
putToSleep( machineName )
|
putToSleep(machineName)
|
||||||
time.sleep(30) # allow a little time to make sure the machine is ready to receive other wake on lan messages
|
time.sleep(30) # allow a little time to make sure the machine is ready to receive other wake on lan messages
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
"""
|
"""
|
||||||
for i in range(30):
|
for i in range(30):
|
||||||
machineName = 'simpatix%d' % (i+10)
|
machineName = 'simpatix%d' % (i+10)
|
||||||
print 'lom ip of %s is %s' % (machineName, getLightOutManagementIpAddress(machineName))
|
print 'lom ip of %s is %s' % (machineName, getLightOutManagementIpAddress(machineName))
|
||||||
"""
|
"""
|
||||||
wakeUp('simpatix21')
|
wakeUp('simpatix21')
|
||||||
#print putToSleep('simpatix13')
|
# print putToSleep('simpatix13')
|
||||||
#print isNonRespondingMachineSleeping('simpatix13')
|
# print isNonRespondingMachineSleeping('simpatix13')
|
||||||
|
|
Loading…
Reference in New Issue