déplacement des scripts python pour les rendre partagés par tous les admins (j'en ai besoin pour d'autres applis que clustercontroller)
This commit is contained in:
commit
1ae5ffd762
|
@ -0,0 +1,42 @@
|
||||||
|
import Sensor
|
||||||
|
|
||||||
|
class ClusterNodeSensorsReadings:
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
POWERSTATE_UNKNOWN=0
|
||||||
|
POWERSTATE_OFF=1
|
||||||
|
POWERSTATE_ON=2
|
||||||
|
POWERSTATE_SLEEP=3
|
||||||
|
"""
|
||||||
|
def __init__(self, clusterNodeName):
|
||||||
|
self.m_clusterNodeName = clusterNodeName
|
||||||
|
self.m_sensors = {}
|
||||||
|
#self.m_powerState = ClusterNodeStatus.POWERSTATE_UNKNOWN
|
||||||
|
return
|
||||||
|
def addSensor(self, sensor):
|
||||||
|
self.m_sensors[sensor.m_name] = sensor
|
||||||
|
def dump(self):
|
||||||
|
for key,sensor in self.m_sensors.iteritems():
|
||||||
|
sensor.dump()
|
||||||
|
return
|
||||||
|
#def getPowerState(self):
|
||||||
|
# return self.m_powerState
|
||||||
|
def getLowestTemperature( self ):
|
||||||
|
#log('ClusterNodeSensorsReadings::getLowestTemperature : start')
|
||||||
|
lowestTemperature = 0.0
|
||||||
|
lowestTemperatureIsDefined = False
|
||||||
|
for key,sensor in self.m_sensors.iteritems():
|
||||||
|
#log('ClusterNodeSensorsReadings::getLowestTemperature : start')
|
||||||
|
if sensor.typeName() == 'Temperature':
|
||||||
|
sensor.m_temperature
|
||||||
|
if lowestTemperatureIsDefined:
|
||||||
|
if sensor.m_temperature < lowestTemperature:
|
||||||
|
lowestTemperature = sensor.m_temperature
|
||||||
|
else:
|
||||||
|
lowestTemperature = sensor.m_temperature
|
||||||
|
lowestTemperatureIsDefined = True
|
||||||
|
assert( lowestTemperatureIsDefined )
|
||||||
|
#log('ClusterNodeSensorsReadings::getLowestTemperature : end')
|
||||||
|
return lowestTemperature
|
|
@ -0,0 +1,81 @@
|
||||||
|
import StringIO
|
||||||
|
import re
|
||||||
|
from Sensor import FanSensor, TemperatureSensor
|
||||||
|
from ClusterNodeSensorsReadings import ClusterNodeSensorsReadings
|
||||||
|
|
||||||
|
class IpmiTool202Parser:
|
||||||
|
def parseSensorOutput( self, strOutput, clusterNodeName ):
|
||||||
|
sensorReadings=ClusterNodeSensorsReadings(clusterNodeName)
|
||||||
|
f = StringIO.StringIO(strOutput)
|
||||||
|
line = f.readline()
|
||||||
|
while( len(line) > 0 ):
|
||||||
|
#print line,
|
||||||
|
matchObj = re.match( '^Sensor ID[ ]*\: \'(?P<sensorName>[a-zA-Z 0-9]+)\'', line )
|
||||||
|
if matchObj:
|
||||||
|
sensorName = matchObj.group('sensorName')
|
||||||
|
# print sensorName
|
||||||
|
# read the entity id
|
||||||
|
line = f.readline()
|
||||||
|
matchObj = re.match( '^ Entity ID[ ]*\: (?P<entityId>[0-9\.]+)', line )
|
||||||
|
assert(matchObj)
|
||||||
|
entityId = matchObj.group('entityId')
|
||||||
|
# print entityId
|
||||||
|
# read the sensor type
|
||||||
|
line = f.readline()
|
||||||
|
matchObj = re.match( '^ Sensor Type[\(\)a-zA-Z ]*\: (?P<sensorType>[a-zA-Z \(\)]+)', line )
|
||||||
|
assert(matchObj)
|
||||||
|
sensorType = matchObj.group('sensorType')
|
||||||
|
#print sensorType
|
||||||
|
if sensorType == 'Fan':
|
||||||
|
rpms = self.parseFanSensorOutput(f)
|
||||||
|
if temperature != None:
|
||||||
|
sensor = FanSensor(sensorName)
|
||||||
|
sensor.m_rpms = rpms
|
||||||
|
elif sensorType == 'Temperature':
|
||||||
|
temperature = self.parseTemperatureSensorOutput(f)
|
||||||
|
if temperature != None:
|
||||||
|
sensor = TemperatureSensor(sensorName)
|
||||||
|
sensor.m_temperature = temperature
|
||||||
|
else:
|
||||||
|
#ignoring other sensors
|
||||||
|
sensor = None
|
||||||
|
if sensor:
|
||||||
|
sensorReadings.addSensor( sensor )
|
||||||
|
else:
|
||||||
|
None
|
||||||
|
#assert(False)
|
||||||
|
line = f.readline()
|
||||||
|
f.close()
|
||||||
|
def parseFanSensorOutput(self, file):
|
||||||
|
"""
|
||||||
|
reads the fan specific ipdmitool output
|
||||||
|
"""
|
||||||
|
line = file.readline()
|
||||||
|
#print line
|
||||||
|
matchObj = re.match( '^ Sensor Reading[ ]*\: (?P<numRpms>[0-9]+) \(\+/\- (?P<rpmsPrecision>[0-9]+)\) RPM', line )
|
||||||
|
if(matchObj):
|
||||||
|
numRpms = matchObj.group('numRpms')
|
||||||
|
#print numRpms
|
||||||
|
rpms = float( numRpms )
|
||||||
|
return rpms
|
||||||
|
else:
|
||||||
|
matchObj = re.match( '^ Sensor Reading[ ]*\: Not Present', line )
|
||||||
|
assert(matchObj)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parseTemperatureSensorOutput(self, file):
|
||||||
|
"""
|
||||||
|
reads the temperature specific ipdmitool output
|
||||||
|
"""
|
||||||
|
# Sensor Reading : 36 (+/- 0) degrees C
|
||||||
|
line = file.readline()
|
||||||
|
#print line
|
||||||
|
matchObj = re.match( '^ Sensor Reading[ ]*\: (?P<temperature>[0-9]+) \(\+/\- (?P<precision>[0-9]+)\) degrees C', line )
|
||||||
|
if(matchObj):
|
||||||
|
temperature = matchObj.group('temperature')
|
||||||
|
temperature = float( temperature )
|
||||||
|
return temperature
|
||||||
|
else:
|
||||||
|
matchObj = re.match( '^ Sensor Reading[ ]*\: Not Present', line )
|
||||||
|
assert(matchObj)
|
||||||
|
return None
|
|
@ -0,0 +1,39 @@
|
||||||
|
import StringIO
|
||||||
|
import re
|
||||||
|
from Sensor import FanSensor, TemperatureSensor
|
||||||
|
from ClusterNodeSensorsReadings import ClusterNodeSensorsReadings
|
||||||
|
|
||||||
|
class IpmiTool218Parser:
|
||||||
|
def parseSensorOutput( self, strOutput, clusterNodeName ):
|
||||||
|
sensorReadings=ClusterNodeSensorsReadings(clusterNodeName)
|
||||||
|
f = StringIO.StringIO(strOutput)
|
||||||
|
line = f.readline()
|
||||||
|
while( len(line) > 0 ):
|
||||||
|
#print line,
|
||||||
|
matchObj = re.match( '^(?P<sensorName>[a-zA-Z 0-9]+[a-zA-Z 0-9]*[a-zA-Z0-9])[ ]*\| (?P<sensorValue>[\.0-9]+)[ ]*\| (?P<sensorUnit>[a-zA-Z0-9][a-zA-Z 0-9]*[a-zA-Z0-9])[?]*', line )
|
||||||
|
if matchObj:
|
||||||
|
#log('readClusterNodeSensorsIpmiTool2_1_8 : sensorName = '+matchObj.group('sensorName'))
|
||||||
|
#log('readClusterNodeSensorsIpmiTool2_1_8 : sensorValue = '+matchObj.group('sensorValue'))
|
||||||
|
#log('readClusterNodeSensorsIpmiTool2_1_8 : sensorUnit = "'+matchObj.group('sensorUnit')+'"')
|
||||||
|
sensorName = matchObj.group('sensorName')
|
||||||
|
sensorValue = matchObj.group('sensorValue')
|
||||||
|
sensorUnit = matchObj.group('sensorUnit')
|
||||||
|
sensor = None
|
||||||
|
if sensorUnit == 'degrees C':
|
||||||
|
sensor = TemperatureSensor(sensorName)
|
||||||
|
sensor.m_temperature = float( sensorValue )
|
||||||
|
elif sensorUnit == 'RPM':
|
||||||
|
sensor = FanSensor(sensorName)
|
||||||
|
sensor.m_rpms = float( sensorValue )
|
||||||
|
else:
|
||||||
|
None
|
||||||
|
if sensor:
|
||||||
|
#log('readClusterNodeSensorsIpmiTool2_1_8 : adding sensor')
|
||||||
|
sensorReadings.addSensor( sensor )
|
||||||
|
else:
|
||||||
|
None
|
||||||
|
#assert(False)
|
||||||
|
line = f.readline()
|
||||||
|
f.close()
|
||||||
|
return sensorReadings
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
class Sensor:
|
||||||
|
def __init__(self, sensorName):
|
||||||
|
self.m_name = sensorName
|
||||||
|
self.m_isValid = True # false if this sensor is not actually present on the target machine
|
||||||
|
return
|
||||||
|
def dump(self):
|
||||||
|
print self.m_name
|
||||||
|
|
||||||
|
class FanSensor(Sensor):
|
||||||
|
def __init__(self, sensorName):
|
||||||
|
Sensor.__init__(self, sensorName)
|
||||||
|
def dump(self):
|
||||||
|
print 'Fan \'', self.m_name, '\' rpm=',self.m_rpms
|
||||||
|
def typeName(self):
|
||||||
|
return 'Fan'
|
||||||
|
|
||||||
|
class TemperatureSensor(Sensor):
|
||||||
|
def __init__(self, sensorName):
|
||||||
|
Sensor.__init__(self, sensorName)
|
||||||
|
def dump(self):
|
||||||
|
print 'Temperature \'', self.m_name, '\' temperature=',self.m_temperature
|
||||||
|
def typeName(self):
|
||||||
|
return 'Temperature'
|
|
@ -0,0 +1 @@
|
||||||
|
# this file is here just so that the containing directory is treated as a python package
|
|
@ -0,0 +1,139 @@
|
||||||
|
import MySQLdb
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import StringIO
|
||||||
|
import re
|
||||||
|
from wol import *
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
from Util import *
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def machineNameToMacAddress( machineName ):
|
||||||
|
conn = MySQLdb.connect('simpatix10', 'root', '', '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 ):
|
||||||
|
"""
|
||||||
|
the light out management ip of servers allows to talk to the server even when it's asleep
|
||||||
|
"""
|
||||||
|
conn = MySQLdb.connect('simpatix10', 'root', '', '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():
|
||||||
|
clusterMachinesNames = []
|
||||||
|
conn = MySQLdb.connect('simpatix10', 'root', '', 'simpadb')
|
||||||
|
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')
|
|
@ -0,0 +1,69 @@
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import StringIO
|
||||||
|
import re
|
||||||
|
from wol import *
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
|
import smtplib
|
||||||
|
from email.MIMEText import MIMEText
|
||||||
|
|
||||||
|
def sendTextMail(strFrom, to, strSubject, text ):
|
||||||
|
#from = "SimpaCluster <guillaume.raffy@univ-rennes1.fr>"
|
||||||
|
mail = MIMEText(text)
|
||||||
|
mail['From'] = strFrom
|
||||||
|
mail['Subject'] = strSubject
|
||||||
|
mail['To'] = to
|
||||||
|
smtp = smtplib.SMTP('smtp.univ-rennes1.fr', 25)
|
||||||
|
#smtp.connect()
|
||||||
|
#smtp.login('guillaume.raffy@univ-rennes1.fr', 'password')
|
||||||
|
smtp.sendmail(strFrom, [to], mail.as_string())
|
||||||
|
smtp.close()
|
||||||
|
|
||||||
|
def log( message ):
|
||||||
|
print time.asctime(time.localtime())+' : '+ message
|
||||||
|
|
||||||
|
def executeProgram( astrArguments ):
|
||||||
|
|
||||||
|
#log('executeProgram : program [%s]' % (','.join(astrArguments)))
|
||||||
|
popen = subprocess.Popen( astrArguments, bufsize=1, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # bufsize=1 seems to prevent deadlocks that happen 50% the time
|
||||||
|
stdout, stderr = popen.communicate()
|
||||||
|
#popen.wait()
|
||||||
|
result = (popen.returncode, stdout, stderr)
|
||||||
|
#log('executeProgram : command %s popen.pid = %d' % (astrArguments[0], popen.pid))
|
||||||
|
#os.kill(popen.pid, signal.SIGTERM)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def executeCommand( command ):
|
||||||
|
"""
|
||||||
|
executes the shell command such as 'set x=1; myprog $x'
|
||||||
|
"""
|
||||||
|
popen = subprocess.Popen( [ command ], bufsize=1, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # bufsize=1 seems to prevent deadlocks that happen 50% the time
|
||||||
|
stdout, stderr = popen.communicate()
|
||||||
|
#popen.wait()
|
||||||
|
result = (popen.returncode, stdout, stderr)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def getUpsStatus():
|
||||||
|
try:
|
||||||
|
url = 'http://Net Vision:public@129.20.27.119/PageMonComprehensive.html'
|
||||||
|
f = urllib.urlopen(url)
|
||||||
|
res = f.read()
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
print "bad read"
|
||||||
|
return
|
||||||
|
h = MyHTMLParser()
|
||||||
|
h.feed(res)
|
||||||
|
tokensList = h.GetTokenList()
|
||||||
|
|
||||||
|
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')
|
|
@ -0,0 +1 @@
|
||||||
|
# this file is here just so that the containing directory is treated as a python package
|
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# wol.py
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
|
def wake_on_lan(macaddress):
|
||||||
|
""" Switches on remote computers using WOL. """
|
||||||
|
|
||||||
|
# Check macaddress format and try to compensate.
|
||||||
|
if len(macaddress) == 12:
|
||||||
|
pass
|
||||||
|
elif len(macaddress) == 12 + 5:
|
||||||
|
sep = macaddress[2]
|
||||||
|
macaddress = macaddress.replace(sep, '')
|
||||||
|
else:
|
||||||
|
raise ValueError('Incorrect MAC address format')
|
||||||
|
|
||||||
|
# Pad the synchronization stream.
|
||||||
|
data = ''.join(['FFFFFFFFFFFF', macaddress * 20])
|
||||||
|
send_data = ''
|
||||||
|
|
||||||
|
# Split up the hex values and pack.
|
||||||
|
for i in range(0, len(data), 2):
|
||||||
|
send_data = ''.join([send_data,
|
||||||
|
struct.pack('B', int(data[i: i + 2], 16))])
|
||||||
|
|
||||||
|
# Broadcast it to the LAN.
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
|
sock.sendto(send_data, ('<broadcast>', 7))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
# Use macaddresses with any seperators.
|
||||||
|
wake_on_lan('00:1E:52:F3:61:60') # simpatix28
|
||||||
|
#wake_on_lan('00:24:36:F2:D0:FA') # simpatix33
|
||||||
|
#wake_on_lan('0F:0F:DF:0F:BF:EF')
|
||||||
|
#wake_on_lan('0F-0F-DF-0F-BF-EF')
|
||||||
|
# or without any seperators.
|
||||||
|
#wake_on_lan('0F0FDF0FBFEF')
|
Loading…
Reference in New Issue