2011-04-18 11:32:19 +02:00
import MySQLdb
import time
import subprocess
import StringIO
import re
from wol import *
import os
import signal
from Util import *
2018-02-06 18:37:15 +01:00
import abc
import sqlite3
from mysql2sqlite import mysql_to_sqlite
2011-04-18 11:32:19 +02:00
def isMachineResponding ( machineName ) :
( returnCode , stdout , stderr ) = executeProgram ( [ ' ping ' , ' -o ' , ' -t ' , ' 1 ' , machineName ] )
#log( 'isMachineResponding : result of command %s : %d' % (command, returnCode) )
if returnCode == 0 :
return True
else :
bMachineNameIsNotKnown = ( returnCode == 68 )
bMachineIsNotResponding = ( returnCode == 2 )
if bMachineIsNotResponding == False :
bBUG_00000004_IS_STILL_ALIVE = True
if bBUG_00000004_IS_STILL_ALIVE == True and returnCode == 142 :
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
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
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
else :
log ( ' isMachineResponding : Unexpected return code : returnCode= %d , stdout= " %s " , stderr= " %s " , machineName = %s ' % ( returnCode , stdout , stderr , machineName ) )
assert ( False )
return False
2018-02-06 18:37:15 +01:00
class ISqlDatabaseBackend ( object ) :
def __init__ ( self ) :
pass
@abc.abstractmethod
def query ( self , sql_query ) :
"""
: param str sql_query : the sql query to perform
"""
pass
class RemoteMysqlDb ( ISqlDatabaseBackend ) :
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_user : the user for accessing the inventory database , eg simpadb_reader
: param str db_name : the name of the inventory database , eg simpadb
"""
self . _db_server_fqdn = db_server_fqdn
self . _db_user = db_user
self . _db_name = db_name
self . _connect ( )
def _connect ( self ) :
self . _conn = MySQLdb . connect ( self . _db_server_fqdn , self . _db_user , ' ' , self . _db_name )
assert ( self . _conn )
def query ( self , sql_query ) :
"""
: param str sql_query : the sql query to perform
"""
self . _conn . query ( sql_query )
rows = conn . store_result ( )
return rows
class SqlFile ( ISqlDatabaseBackend ) :
def __init__ ( self , sql_file_path ) :
"""
: param str sql_file_path : the path of the sql file containing the inventory database
"""
self . _sql_file_path = sql_file_path
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 :
# - 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
try :
os . remove ( sqlite_db_path )
except :
pass
self . _con = sqlite3 . connect ( sqlite_db_path )
f = open ( self . _sql_file_path , ' r ' )
sql = f . read ( ) # watch out for built-in `str`
#print(sql)
self . _cur = self . _con . cursor ( )
#print(mysql_to_sqlite(sql))
self . _cur . executescript ( mysql_to_sqlite ( sql ) )
def query ( self , sql_query ) :
"""
: param str sql_query : the sql query to perform
"""
pass
self . _cur . execute ( sql_query )
rows = self . _cur . fetchall ( )
return rows
class SqlDatabaseReader ( object ) :
def __init__ ( self , inv_provider ) :
"""
: param ISqlDatabaseBackend inv_provider : the input that provides the inventory data
"""
self . _inv_provider = inv_provider
def query ( self , sql_query ) :
"""
performs a query on the sql database
: param str sql_query : the sql query to perform
"""
return self . _inv_provider . query ( sql_query )
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
: 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_value : the id of the item to read
: param str attr_name : the name of the attribute to read from the item
"""
attr_value = None
rows = self . query ( " SELECT " + attr_name + " FROM " + table + " WHERE " + key_name + " = ' " + key_value + " ' " )
if len ( rows ) > 0 :
attr_value = rows [ 0 ] [ 0 ]
return attr_value
2011-04-18 11:32:19 +02:00
def machineNameToMacAddress ( machineName ) :
2011-09-22 10:59:23 +02:00
conn = MySQLdb . connect ( ' simpatix10 ' , ' simpadb_reader ' , ' ' , ' simpadb ' )
2011-04-18 11:32:19 +02:00
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 ) :
"""
the light out management ip of servers allows to talk to the server even when it ' s asleep
"""
2011-09-22 10:59:23 +02:00
conn = MySQLdb . connect ( ' simpatix10 ' , ' simpadb_reader ' , ' ' , ' simpadb ' )
2011-04-18 11:32:19 +02:00
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 ( ) :
clusterMachinesNames = [ ]
2011-09-22 10:59:23 +02:00
conn = MySQLdb . connect ( ' simpatix10 ' , ' simpadb_reader ' , ' ' , ' simpadb ' )
2011-04-18 11:32:19 +02:00
assert ( conn )
sqlQuery = """ SELECT name FROM machines WHERE affectation= ' cluster ' """
#print sqlQuery
conn . query ( sqlQuery )
r = conn . store_result ( )
rows = r . fetch_row ( 0 )
for row in rows :
#print row
clusterMachinesNames . append ( row [ 0 ] )
conn . close ( )
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 ) :
# note : pmset must be executed as root
( returnCode , stdout , stderr ) = executeCommand ( [ ' ssh ' , machineName , ' pmset sleepnow ' ] )
"""
print returnCode
print ' stdout : '
print stdout
print ' stderr : '
print stderr
"""
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 ) :
macAddress = machineNameToMacAddress ( machineName )
wake_on_lan ( macAddress )
return True
def isNonRespondingMachineSleeping ( machineName ) :
"""
note : crappy method to detect if the machine is sleeping ( if other methods are available , I would be very interested )
"""
wakeUp ( machineName )
time . sleep ( 120 )
if isMachineResponding ( machineName ) :
putToSleep ( machineName )
time . sleep ( 30 ) # allow a little time to make sure the machine is ready to receive other wake on lan messages
return True
else :
return False
if __name__ == ' __main__ ' :
"""
for i in range ( 30 ) :
machineName = ' simpatix %d ' % ( i + 10 )
print ' lom ip of %s is %s ' % ( machineName , getLightOutManagementIpAddress ( machineName ) )
"""
wakeUp ( ' simpatix21 ' )
#print putToSleep('simpatix13')
#print isNonRespondingMachineSleeping('simpatix13')