[Cluster-devel] cluster/fence/agents apc/fence_apc_snmp.py apc ...
kupcevic at sourceware.org
kupcevic at sourceware.org
Tue Apr 17 05:53:24 UTC 2007
CVSROOT: /cvs/cluster
Module name: cluster
Branch: RHEL45
Changes by: kupcevic at sourceware.org 2007-04-17 06:53:23
Modified files:
fence/agents/apc: fence_apc_snmp.py
fence/agents/apc_snmp: fence_apc_snmp.py
Log message:
Fixed bz193064 (fence_apc_snmp doesn't support linked switches)
Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/apc/fence_apc_snmp.py.diff?cvsroot=cluster&only_with_tag=RHEL45&r1=1.1.2.3&r2=1.1.2.3.2.1
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/fence/agents/apc_snmp/fence_apc_snmp.py.diff?cvsroot=cluster&only_with_tag=RHEL45&r1=1.1.2.3&r2=1.1.2.3.2.1
--- cluster/fence/agents/apc/fence_apc_snmp.py 2007/02/14 16:23:21 1.1.2.3
+++ cluster/fence/agents/apc/fence_apc_snmp.py 2007/04/17 05:53:23 1.1.2.3.2.1
@@ -4,7 +4,7 @@
#############################################################################
##
## Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-## Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+## Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
##
## This copyrighted material is made available to anyone wishing to use,
## modify, copy, or redistribute it subject to the terms and conditions
@@ -22,7 +22,7 @@
import getopt, sys
import os
-import time
+import datetime
import select
import signal
from glob import glob
@@ -37,49 +37,251 @@
POWER_OFF="outletOff"
POWER_REBOOT="outletReboot"
+
+# oid defining fence device
+oid_sysObjectID = '.1.3.6.1.2.1.1.2.0'
+
+
+
+class SNMP:
+ def __init__(self, params):
+ self.hostname = params['ipaddr']
+ self.udpport = params['udpport']
+ self.community = params['community']
+
+ def get(self, oid):
+ args = ['/usr/bin/snmpget']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ strr, code = execWithCaptureStatus("/usr/bin/snmpget", args)
+ if code:
+ raise Exception, 'snmpget failed'
+ l = strr.strip().split()
+ return l[0], ' '.join(l[1:])
+
+ def set_int(self, oid, value):
+ args = ['/usr/bin/snmpset']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ args.append('i')
+ args.append(str(value))
+ strr,code = execWithCaptureStatus("/usr/bin/snmpset", args)
+ if code:
+ raise Exception, 'snmpset failed'
+
+ def walk(self, oid):
+ args = ['/usr/bin/snmpwalk']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ strr,code = execWithCaptureStatus("/usr/bin/snmpwalk", args)
+ if code:
+ raise Exception, 'snmpwalk failed'
+ lines = strr.strip().splitlines()
+ ret = []
+ for line in lines:
+ l = line.strip().split()
+ ret.append((l[0], ' '.join(l[1:]).strip('"')))
+ return ret
+
+
+
+class FenceAgent:
+
+ def __init__(self, params):
+ self.snmp = SNMP(params)
+
+ def resolve_outlet(self):
+ raise Exception, 'resolve_outlet() not implemented'
+
+ def status(self):
+ oid = self.status_oid % self.resolve_outlet()
+ dummy, stat = self.snmp.get(oid)
+ if stat == self.state_on:
+ return 'on'
+ elif stat == self.state_off:
+ return 'off'
+ else:
+ raise Exception, 'invalid status ' + stat
+
+ def power_off(self):
+ oid = self.control_oid % self.resolve_outlet()
+ self.snmp.set_int(oid, self.turn_off)
+
+ def power_on(self):
+ oid = self.control_oid % self.resolve_outlet()
+ self.snmp.set_int(oid, self.turn_on)
+
+
+
+
+
+
+
+
+class MasterSwitch(FenceAgent):
+
+ def __init__(self, params):
+ FenceAgent.__init__(self, params)
+
+ self.status_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.%s'
+ self.control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%s'
+ self.outlet_table_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2'
+
+ self.state_on = '1'
+ self.state_off = '2'
+
+ self.turn_on = '1'
+ self.turn_off = '2'
+
+ self.port = params['port']
+
+ def resolve_outlet(self):
+ outlet = None
+ try:
+ outlet = str(int(self.port))
+ except:
+ table = self.snmp.walk(self.outlet_table_oid)
+ for row in table:
+ if row[1] == self.port:
+ t = row[0].strip().split('.')
+ outlet = t[len(t)-1]
+ if outlet == None:
+ raise Exception, 'unable to resolve ' + self.port
+ else:
+ self.port = outlet
+ return outlet
+
+
+class MasterSwitchPlus(FenceAgent):
+ def __init__(self, params):
+ FenceAgent.__init__(self, params)
+
+ self.status_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.5.%s.1.%s'
+ self.control_oid = '.1.3.6.1.4.1.318.1.1.6.5.1.1.5.%s.1.%s'
+ self.outlet_table_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.4'
+
+ self.state_on = '1'
+ self.state_off = '2'
+
+ self.turn_on = '1'
+ self.turn_off = '3'
+
+ try:
+ self.switch = params['switch']
+ except:
+ self.switch = ''
+ self.port = params['port']
+
+ def resolve_outlet(self):
+ switch = None
+ outlet = None
+ try:
+ switch = str(int(self.switch))
+ outlet = str(int(self.port))
+ except:
+ table = self.snmp.walk(self.outlet_table_oid)
+ for row in table:
+ if row[1] == self.port:
+ t = row[0].strip().split('.')
+ outlet = t[len(t)-1]
+ switch = t[len(t)-3]
+ if outlet == None:
+ raise Exception, 'unable to resolve ' + self.port
+ else:
+ self.switch = switch
+ self.port = outlet
+ return (switch, outlet)
+
+
+
+
+
+
def usage():
- print "Usage:";
- print "";
- print "Options:";
- print " -a <ip> IP address or hostname of MasterSwitch";
- print " -h usage";
- print " -l <name> Login name";
- print " -n <num> Outlet number to change";
- print " -o <string> Action: Reboot (default), Off or On";
- print " -p <string> Login password";
- print " -q quiet mode";
- print " -V version";
- print " -v Log to file /tmp/apclog";
+ print "Usage:"
+ print ""
+ print "Options:"
+ print " -h Usage"
+ print " -a <ip> IP address or hostname of fence device"
+ print " -u <udpport> UDP port to use (default 161)"
+ print " -c <community> SNMP community (default 'private')"
+ print " -n <num> Outlet name/number to act on"
+ print " -o <string> Action: Reboot (default), On, Off and Status"
+ print " -v Verbose mode - write to /tmp/apclog"
+ print " -V Version"
- sys.exit(0);
+ sys.exit(0)
-def main():
- apc_base = "enterprises.apc.products.hardware."
- apc_outletctl = "masterswitch.sPDUOutletControl.sPDUOutletControlTable.sPDUOutletControlEntry.sPDUOutletCtl."
- apc_outletstatus = "masterswitch.sPDUOutletStatus.sPDUOutletStatusMSPTable.sPDUOutletStatusMSPEntry.sPDUOutletStatusMSP."
-
- address = ""
- output = ""
- port = ""
- action = "outletReboot"
- status_check = False
- verbose = False
+file_log = None
+def set_logging(verbose):
+ global file_log
+ if verbose:
+ file_log = open('/tmp/apclog', 'a')
+ file_log.write('\n----------- ')
+ file_log.write(datetime.datetime.today().ctime())
+ file_log.write(' -----------\n')
+def log(msg, error=False):
+ global file_log
+ if msg.rfind('\n') != len(msg)-1:
+ msg += '\n'
+ if file_log != None:
+ file_log.write(msg)
+ if error:
+ o = sys.stderr
+ else:
+ o = sys.stdout
+ o.write(msg)
+
- if not glob('/usr/share/snmp/mibs/powernet*.mib'):
- sys.stderr.write('This APC Fence script uses snmp to control the APC power switch. This script requires that net-snmp-utils be installed on all nodes in the cluster, and that the powernet369.mib file be located in /usr/share/snmp/mibs/\n')
- sys.exit(1)
+def main():
+ try:
+ main2()
+ return 0
+ except Exception, e:
+ log(str(e), True)
+ sys.exit(1)
+def main2():
+
+ agents_dir = {'.1.3.6.1.4.1.318.1.3.4.5' : MasterSwitch,
+ '.1.3.6.1.4.1.318.1.3.4.4' : MasterSwitchPlus}
+
+ verbose = False
+ params = {}
+
if len(sys.argv) > 1:
try:
- opts, args = getopt.getopt(sys.argv[1:], "a:hl:p:n:o:vV", ["help", "output="])
+ opts, args = getopt.getopt(sys.argv[1:], "ha:u:c:n:o:vV", ["help", "output="])
except getopt.GetoptError:
- #print help info and quit
usage()
sys.exit(2)
for o, a in opts:
+ o = o.strip()
+ a = a.strip()
if o == "-v":
verbose = True
if o == "-V":
@@ -89,229 +291,122 @@
sys.exit(0)
if o in ("-h", "--help"):
usage()
- sys.exit(0)
- if o == "-n":
- port = a
- if o == "-o":
- lcase = a.lower() #Lower case string
- if lcase == "off":
- action = "outletOff"
- elif lcase == "on":
- action = "outletOn"
- elif lcase == "reboot":
- action = "outletReboot"
- elif lcase == "status":
- #action = "sPDUOutletStatusMSPOutletState"
- action = ""
- status_check = True
- else:
- usage()
- sys.exit()
+ sys.exit(0)
if o == "-a":
- address = a
-
- if address == "":
- usage()
- sys.exit(1)
-
- if port == "":
- usage()
- sys.exit(1)
+ params['ipaddr'] = a
+ if o == "-u":
+ params['udpport'] = a
+ if o == "-c":
+ params['community'] = a
+ if o == "-n":
+ switch = ''
+ port = a
+ if ':' in port:
+ idx = port.find(':')
+ switch = port[:idx]
+ port = port[idx+1:]
+ params['switch'] = switch
+ params['port'] = port
+ if o == "-o":
+ params['option'] = a.lower()
else: #Get opts from stdin
- params = {}
- #place params in dict
for line in sys.stdin:
- val = line.split("=")
+ val = line.strip().split("=")
if len(val) == 2:
- params[val[0].strip()] = val[1].strip()
-
- try:
- address = params["ipaddr"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing ipaddr param for fence_apc...exiting")
- sys.exit(1)
- try:
- login = params["login"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing login param for fence_apc...exiting")
- sys.exit(1)
-
- try:
- passwd = params["passwd"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing passwd param for fence_apc...exiting")
- sys.exit(1)
-
- try:
- port = params["port"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing port param for fence_apc...exiting")
- sys.exit(1)
-
+ o = val[0].strip().lower()
+ a = val[1].strip()
+ if o == 'verbose':
+ if a.lower() == 'on' or a.lower() == 'true' or a == '1':
+ verbose = True
+ else:
+ params[o] = a
+
- try:
- a = params["option"]
- if a == "Off" or a == "OFF" or a == "off":
- action = POWER_OFF
- elif a == "On" or a == "ON" or a == "on":
- action = POWER_ON
- elif a == "Reboot" or a == "REBOOT" or a == "reboot":
- action = POWER_REBOOT
- except KeyError, e:
- action = POWER_REBOOT
-
- ####End of stdin section
-
- apc_command = apc_base + apc_outletctl + port
-
- args_status = list()
- args_off = list()
- args_on = list()
-
- args_status.append("/usr/bin/snmpget")
- args_status.append("-Oqu") #sets printing options
- args_status.append("-v")
- args_status.append("1")
- args_status.append("-c")
- args_status.append("private")
- args_status.append("-m")
- args_status.append("ALL")
- args_status.append(address)
- args_status.append(apc_command)
-
- args_off.append("/usr/bin/snmpset")
- args_off.append("-Oqu") #sets printing options
- args_off.append("-v")
- args_off.append("1")
- args_off.append("-c")
- args_off.append("private")
- args_off.append("-m")
- args_off.append("ALL")
- args_off.append(address)
- args_off.append(apc_command)
- args_off.append("i")
- args_off.append("outletOff")
-
- args_on.append("/usr/bin/snmpset")
- args_on.append("-Oqu") #sets printing options
- args_on.append("-v")
- args_on.append("1")
- args_on.append("-c")
- args_on.append("private")
- args_on.append("-m")
- args_on.append("ALL")
- args_on.append(address)
- args_on.append(apc_command)
- args_on.append("i")
- args_on.append("outletOn")
-
- cmdstr_status = ' '.join(args_status)
- cmdstr_off = ' '.join(args_off)
- cmdstr_on = ' '.join(args_on)
-
-##This section issues the actual commands. Reboot is split into
-##Off, then On to make certain both actions work as planned.
-##
-##The status command just dumps the outlet status to stdout.
-##The status checks that are made when turning an outlet on or off, though,
-##use the execWithCaptureStatus so that the stdout from snmpget can be
-##examined and the desired operation confirmed.
-
- if status_check:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_status)
- strr = os.system(cmdstr_status)
- print strr
- if verbose:
- fd.write("Result: %s\n" % strr)
- fd.close()
-
+ set_logging(verbose)
+
+
+ ### validation ###
+
+ try:
+ if params['ipaddr'] == '':
+ raise Exception, 'missing ipadddr'
+ except:
+ log("FENCE: Missing ipaddr param for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'udpport' not in params:
+ params['udpport'] = '161'
+ try:
+ t = int(params['udpport'])
+ if t >= 65536 or t < 0:
+ raise Exception, 'invalid udpport'
+ except:
+ log("FENCE: Invalid udpport for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'community' not in params:
+ params['community'] = 'private'
+ try:
+ port = params['port']
+ if len(port) == 0:
+ raise Exception, 'missing port'
+ except:
+ log("FENCE: Missing port param for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'switch' not in params:
+ params['switch'] = ''
+ try:
+ act = params['option'].lower()
+ if act in ['on', 'off', 'reboot', 'status']:
+ params['option'] = act
+ else:
+ usage()
+ sys.exit(3)
+ except:
+ params['option'] = 'reboot'
+
+ ### End of validation ###
+
+ if verbose:
+ log('called with ' + str(params))
+
+ agent = None
+ dummy, sys_id = SNMP(params).get(oid_sysObjectID)
+ if sys_id not in agents_dir:
+ log('Fence device with \'oid_sysObjectID=' + sys_id + '\' is not supported', True)
+ sys.exit(1)
+ agent = agents_dir[sys_id](params)
+
+ if params['option'] == 'status':
+ log('Outlet "%s" - %s is %s' % (params['port'],
+ str(agent.resolve_outlet()),
+ agent.status()))
+ elif params['option'] == 'on':
+ agent.power_on()
+ if agent.status() != 'on':
+ raise Exception, 'Error turning outlet on'
+ elif params['option'] == 'off':
+ agent.power_off()
+ if agent.status() != 'off':
+ raise Exception, 'Error turning outlet off'
+ elif params['option'] == 'reboot':
+ agent.power_off()
+ if agent.status() != 'off':
+ raise Exception, 'Error turning outlet off'
+ agent.power_on()
+ if agent.status() != 'on':
+ raise Exception, 'Error turning outlet on'
else:
- if action == POWER_OFF:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_off)
- strr = os.system(cmdstr_off)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- fd.close()
- if strr.find(POWER_OFF) >= 0:
- print "Success. Outlet off"
- sys.exit(0)
- else:
- if verbose:
- fd.write("Unable to power off apc outlet")
- fd.close()
- sys.exit(1)
-
- elif action == POWER_ON:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_on)
- strr = os.system(cmdstr_on)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_ON) >= 0:
- if verbose:
- fd.close()
- print "Success. Outlet On."
- sys.exit(0)
- else:
- print "Unable to power on apc outlet"
- if verbose:
- fd.write("Unable to power on apc outlet")
- fd.close()
- sys.exit(1)
-
- elif action == POWER_REBOOT:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_off)
- strr = os.system(cmdstr_off)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_OFF) < 0:
- print "Unable to power off apc outlet"
- if verbose:
- fd.write("Unable to power off apc outlet")
- fd.close()
- sys.exit(1)
+ print 'nothing to do'
+ sys.exit(1)
+ pass
+
- if verbose:
- fd.write("Attempting the following command: %s\n" % cmdstr_on)
- strr = os.system(cmdstr_on)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_ON) >= 0:
- if verbose:
- fd.close()
- print "Success: Outlet Rebooted."
- sys.exit(0)
- else:
- print "Unable to power on apc outlet"
- if verbose:
- fd.write("Unable to power on apc outlet")
- fd.close()
- sys.exit(1)
-
+
def execWithCaptureStatus(command, argv, searchPath = 0, root = '/', stdin = 0,
catchfd = 1, closefd = -1):
if not os.access (root + command, os.X_OK):
- raise RuntimeError, command + " cannot be run"
+ raise Exception, command + " cannot be run"
(read, write) = os.pipe()
@@ -364,4 +459,5 @@
return (rc, status)
if __name__ == "__main__":
- main()
+ ret = main()
+ sys.exit(ret)
--- cluster/fence/agents/apc_snmp/Attic/fence_apc_snmp.py 2007/03/06 15:27:30 1.1.2.3
+++ cluster/fence/agents/apc_snmp/Attic/fence_apc_snmp.py 2007/04/17 05:53:23 1.1.2.3.2.1
@@ -4,7 +4,7 @@
#############################################################################
##
## Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
-## Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
+## Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
##
## This copyrighted material is made available to anyone wishing to use,
## modify, copy, or redistribute it subject to the terms and conditions
@@ -22,7 +22,7 @@
import getopt, sys
import os
-import time
+import datetime
import select
import signal
from glob import glob
@@ -37,49 +37,251 @@
POWER_OFF="outletOff"
POWER_REBOOT="outletReboot"
+
+# oid defining fence device
+oid_sysObjectID = '.1.3.6.1.2.1.1.2.0'
+
+
+
+class SNMP:
+ def __init__(self, params):
+ self.hostname = params['ipaddr']
+ self.udpport = params['udpport']
+ self.community = params['community']
+
+ def get(self, oid):
+ args = ['/usr/bin/snmpget']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ strr, code = execWithCaptureStatus("/usr/bin/snmpget", args)
+ if code:
+ raise Exception, 'snmpget failed'
+ l = strr.strip().split()
+ return l[0], ' '.join(l[1:])
+
+ def set_int(self, oid, value):
+ args = ['/usr/bin/snmpset']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ args.append('i')
+ args.append(str(value))
+ strr,code = execWithCaptureStatus("/usr/bin/snmpset", args)
+ if code:
+ raise Exception, 'snmpset failed'
+
+ def walk(self, oid):
+ args = ['/usr/bin/snmpwalk']
+ args.append('-Oqn')
+ args.append('-v')
+ args.append('1')
+ args.append('-c')
+ args.append(self.community)
+ args.append('-m')
+ args.append('ALL')
+ args.append(self.hostname + ':' + self.udpport)
+ args.append(oid)
+ strr,code = execWithCaptureStatus("/usr/bin/snmpwalk", args)
+ if code:
+ raise Exception, 'snmpwalk failed'
+ lines = strr.strip().splitlines()
+ ret = []
+ for line in lines:
+ l = line.strip().split()
+ ret.append((l[0], ' '.join(l[1:]).strip('"')))
+ return ret
+
+
+
+class FenceAgent:
+
+ def __init__(self, params):
+ self.snmp = SNMP(params)
+
+ def resolve_outlet(self):
+ raise Exception, 'resolve_outlet() not implemented'
+
+ def status(self):
+ oid = self.status_oid % self.resolve_outlet()
+ dummy, stat = self.snmp.get(oid)
+ if stat == self.state_on:
+ return 'on'
+ elif stat == self.state_off:
+ return 'off'
+ else:
+ raise Exception, 'invalid status ' + stat
+
+ def power_off(self):
+ oid = self.control_oid % self.resolve_outlet()
+ self.snmp.set_int(oid, self.turn_off)
+
+ def power_on(self):
+ oid = self.control_oid % self.resolve_outlet()
+ self.snmp.set_int(oid, self.turn_on)
+
+
+
+
+
+
+
+
+class MasterSwitch(FenceAgent):
+
+ def __init__(self, params):
+ FenceAgent.__init__(self, params)
+
+ self.status_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.%s'
+ self.control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%s'
+ self.outlet_table_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2'
+
+ self.state_on = '1'
+ self.state_off = '2'
+
+ self.turn_on = '1'
+ self.turn_off = '2'
+
+ self.port = params['port']
+
+ def resolve_outlet(self):
+ outlet = None
+ try:
+ outlet = str(int(self.port))
+ except:
+ table = self.snmp.walk(self.outlet_table_oid)
+ for row in table:
+ if row[1] == self.port:
+ t = row[0].strip().split('.')
+ outlet = t[len(t)-1]
+ if outlet == None:
+ raise Exception, 'unable to resolve ' + self.port
+ else:
+ self.port = outlet
+ return outlet
+
+
+class MasterSwitchPlus(FenceAgent):
+ def __init__(self, params):
+ FenceAgent.__init__(self, params)
+
+ self.status_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.5.%s.1.%s'
+ self.control_oid = '.1.3.6.1.4.1.318.1.1.6.5.1.1.5.%s.1.%s'
+ self.outlet_table_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.4'
+
+ self.state_on = '1'
+ self.state_off = '2'
+
+ self.turn_on = '1'
+ self.turn_off = '3'
+
+ try:
+ self.switch = params['switch']
+ except:
+ self.switch = ''
+ self.port = params['port']
+
+ def resolve_outlet(self):
+ switch = None
+ outlet = None
+ try:
+ switch = str(int(self.switch))
+ outlet = str(int(self.port))
+ except:
+ table = self.snmp.walk(self.outlet_table_oid)
+ for row in table:
+ if row[1] == self.port:
+ t = row[0].strip().split('.')
+ outlet = t[len(t)-1]
+ switch = t[len(t)-3]
+ if outlet == None:
+ raise Exception, 'unable to resolve ' + self.port
+ else:
+ self.switch = switch
+ self.port = outlet
+ return (switch, outlet)
+
+
+
+
+
+
def usage():
- print "Usage:";
- print "";
- print "Options:";
- print " -a <ip> IP address or hostname of MasterSwitch";
- print " -h usage";
- print " -l <name> Login name";
- print " -n <num> Outlet number to change";
- print " -o <string> Action: Reboot (default), Off or On";
- print " -p <string> Login password";
- print " -q quiet mode";
- print " -V version";
- print " -v Log to file /tmp/apclog";
+ print "Usage:"
+ print ""
+ print "Options:"
+ print " -h Usage"
+ print " -a <ip> IP address or hostname of fence device"
+ print " -u <udpport> UDP port to use (default 161)"
+ print " -c <community> SNMP community (default 'private')"
+ print " -n <num> Outlet name/number to act on"
+ print " -o <string> Action: Reboot (default), On, Off and Status"
+ print " -v Verbose mode - write to /tmp/apclog"
+ print " -V Version"
- sys.exit(0);
+ sys.exit(0)
-def main():
- apc_base = "enterprises.apc.products.hardware."
- apc_outletctl = "masterswitch.sPDUOutletControl.sPDUOutletControlTable.sPDUOutletControlEntry.sPDUOutletCtl."
- apc_outletstatus = "masterswitch.sPDUOutletStatus.sPDUOutletStatusMSPTable.sPDUOutletStatusMSPEntry.sPDUOutletStatusMSP."
-
- address = ""
- output = ""
- port = ""
- action = "outletReboot"
- status_check = False
- verbose = False
+file_log = None
+def set_logging(verbose):
+ global file_log
+ if verbose:
+ file_log = open('/tmp/apclog', 'a')
+ file_log.write('\n----------- ')
+ file_log.write(datetime.datetime.today().ctime())
+ file_log.write(' -----------\n')
+def log(msg, error=False):
+ global file_log
+ if msg.rfind('\n') != len(msg)-1:
+ msg += '\n'
+ if file_log != None:
+ file_log.write(msg)
+ if error:
+ o = sys.stderr
+ else:
+ o = sys.stdout
+ o.write(msg)
+
- if not glob('/usr/share/snmp/mibs/powernet*.mib'):
- sys.stderr.write('This APC Fence script uses snmp to control the APC power switch. This script requires that net-snmp-utils be installed on all nodes in the cluster, and that the powernet369.mib file be located in /usr/share/snmp/mibs/\n')
- sys.exit(1)
+def main():
+ try:
+ main2()
+ return 0
+ except Exception, e:
+ log(str(e), True)
+ sys.exit(1)
+def main2():
+
+ agents_dir = {'.1.3.6.1.4.1.318.1.3.4.5' : MasterSwitch,
+ '.1.3.6.1.4.1.318.1.3.4.4' : MasterSwitchPlus}
+
+ verbose = False
+ params = {}
+
if len(sys.argv) > 1:
try:
- opts, args = getopt.getopt(sys.argv[1:], "a:hl:p:n:o:vV", ["help", "output="])
+ opts, args = getopt.getopt(sys.argv[1:], "ha:u:c:n:o:vV", ["help", "output="])
except getopt.GetoptError:
- #print help info and quit
usage()
sys.exit(2)
for o, a in opts:
+ o = o.strip()
+ a = a.strip()
if o == "-v":
verbose = True
if o == "-V":
@@ -89,229 +291,122 @@
sys.exit(0)
if o in ("-h", "--help"):
usage()
- sys.exit(0)
- if o == "-n":
- port = a
- if o == "-o":
- lcase = a.lower() #Lower case string
- if lcase == "off":
- action = "outletOff"
- elif lcase == "on":
- action = "outletOn"
- elif lcase == "reboot":
- action = "outletReboot"
- elif lcase == "status":
- #action = "sPDUOutletStatusMSPOutletState"
- action = ""
- status_check = True
- else:
- usage()
- sys.exit()
+ sys.exit(0)
if o == "-a":
- address = a
-
- if address == "":
- usage()
- sys.exit(1)
-
- if port == "":
- usage()
- sys.exit(1)
+ params['ipaddr'] = a
+ if o == "-u":
+ params['udpport'] = a
+ if o == "-c":
+ params['community'] = a
+ if o == "-n":
+ switch = ''
+ port = a
+ if ':' in port:
+ idx = port.find(':')
+ switch = port[:idx]
+ port = port[idx+1:]
+ params['switch'] = switch
+ params['port'] = port
+ if o == "-o":
+ params['option'] = a.lower()
else: #Get opts from stdin
- params = {}
- #place params in dict
for line in sys.stdin:
- val = line.split("=")
+ val = line.strip().split("=")
if len(val) == 2:
- params[val[0].strip()] = val[1].strip()
-
- try:
- address = params["ipaddr"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing ipaddr param for fence_apc...exiting")
- sys.exit(1)
- try:
- login = params["login"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing login param for fence_apc...exiting")
- sys.exit(1)
-
- try:
- passwd = params["passwd"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing passwd param for fence_apc...exiting")
- sys.exit(1)
-
- try:
- port = params["port"]
- except KeyError, e:
- sys.stderr.write("FENCE: Missing port param for fence_apc...exiting")
- sys.exit(1)
-
+ o = val[0].strip().lower()
+ a = val[1].strip()
+ if o == 'verbose':
+ if a.lower() == 'on' or a.lower() == 'true' or a == '1':
+ verbose = True
+ else:
+ params[o] = a
+
- try:
- a = params["option"]
- if a == "Off" or a == "OFF" or a == "off":
- action = POWER_OFF
- elif a == "On" or a == "ON" or a == "on":
- action = POWER_ON
- elif a == "Reboot" or a == "REBOOT" or a == "reboot":
- action = POWER_REBOOT
- except KeyError, e:
- action = POWER_REBOOT
-
- ####End of stdin section
-
- apc_command = apc_base + apc_outletctl + port
-
- args_status = list()
- args_off = list()
- args_on = list()
-
- args_status.append("/usr/bin/snmpget")
- args_status.append("-Oqu") #sets printing options
- args_status.append("-v")
- args_status.append("1")
- args_status.append("-c")
- args_status.append("private")
- args_status.append("-m")
- args_status.append("ALL")
- args_status.append(address)
- args_status.append(apc_command)
-
- args_off.append("/usr/bin/snmpset")
- args_off.append("-Oqu") #sets printing options
- args_off.append("-v")
- args_off.append("1")
- args_off.append("-c")
- args_off.append("private")
- args_off.append("-m")
- args_off.append("ALL")
- args_off.append(address)
- args_off.append(apc_command)
- args_off.append("i")
- args_off.append("outletOff")
-
- args_on.append("/usr/bin/snmpset")
- args_on.append("-Oqu") #sets printing options
- args_on.append("-v")
- args_on.append("1")
- args_on.append("-c")
- args_on.append("private")
- args_on.append("-m")
- args_on.append("ALL")
- args_on.append(address)
- args_on.append(apc_command)
- args_on.append("i")
- args_on.append("outletOn")
-
- cmdstr_status = ' '.join(args_status)
- cmdstr_off = ' '.join(args_off)
- cmdstr_on = ' '.join(args_on)
-
-##This section issues the actual commands. Reboot is split into
-##Off, then On to make certain both actions work as planned.
-##
-##The status command just dumps the outlet status to stdout.
-##The status checks that are made when turning an outlet on or off, though,
-##use the execWithCaptureStatus so that the stdout from snmpget can be
-##examined and the desired operation confirmed.
-
- if status_check:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_status)
- strr = os.system(cmdstr_status)
- print strr
- if verbose:
- fd.write("Result: %s\n" % strr)
- fd.close()
-
+ set_logging(verbose)
+
+
+ ### validation ###
+
+ try:
+ if params['ipaddr'] == '':
+ raise Exception, 'missing ipadddr'
+ except:
+ log("FENCE: Missing ipaddr param for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'udpport' not in params:
+ params['udpport'] = '161'
+ try:
+ t = int(params['udpport'])
+ if t >= 65536 or t < 0:
+ raise Exception, 'invalid udpport'
+ except:
+ log("FENCE: Invalid udpport for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'community' not in params:
+ params['community'] = 'private'
+ try:
+ port = params['port']
+ if len(port) == 0:
+ raise Exception, 'missing port'
+ except:
+ log("FENCE: Missing port param for fence_apc_snmp...exiting", True)
+ sys.exit(1)
+ if 'switch' not in params:
+ params['switch'] = ''
+ try:
+ act = params['option'].lower()
+ if act in ['on', 'off', 'reboot', 'status']:
+ params['option'] = act
+ else:
+ usage()
+ sys.exit(3)
+ except:
+ params['option'] = 'reboot'
+
+ ### End of validation ###
+
+ if verbose:
+ log('called with ' + str(params))
+
+ agent = None
+ dummy, sys_id = SNMP(params).get(oid_sysObjectID)
+ if sys_id not in agents_dir:
+ log('Fence device with \'oid_sysObjectID=' + sys_id + '\' is not supported', True)
+ sys.exit(1)
+ agent = agents_dir[sys_id](params)
+
+ if params['option'] == 'status':
+ log('Outlet "%s" - %s is %s' % (params['port'],
+ str(agent.resolve_outlet()),
+ agent.status()))
+ elif params['option'] == 'on':
+ agent.power_on()
+ if agent.status() != 'on':
+ raise Exception, 'Error turning outlet on'
+ elif params['option'] == 'off':
+ agent.power_off()
+ if agent.status() != 'off':
+ raise Exception, 'Error turning outlet off'
+ elif params['option'] == 'reboot':
+ agent.power_off()
+ if agent.status() != 'off':
+ raise Exception, 'Error turning outlet off'
+ agent.power_on()
+ if agent.status() != 'on':
+ raise Exception, 'Error turning outlet on'
else:
- if action == POWER_OFF:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_off)
- strr = os.system(cmdstr_off)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- fd.close()
- if strr.find(POWER_OFF) >= 0:
- print "Success. Outlet off"
- sys.exit(0)
- else:
- if verbose:
- fd.write("Unable to power off apc outlet")
- fd.close()
- sys.exit(1)
-
- elif action == POWER_ON:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_on)
- strr = os.system(cmdstr_on)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_ON) >= 0:
- if verbose:
- fd.close()
- print "Success. Outlet On."
- sys.exit(0)
- else:
- print "Unable to power on apc outlet"
- if verbose:
- fd.write("Unable to power on apc outlet")
- fd.close()
- sys.exit(1)
-
- elif action == POWER_REBOOT:
- if verbose:
- fd = open("/tmp/apclog", "w")
- fd.write("Attempting the following command: %s\n" % cmdstr_off)
- strr = os.system(cmdstr_off)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_OFF) < 0:
- print "Unable to power off apc outlet"
- if verbose:
- fd.write("Unable to power off apc outlet")
- fd.close()
- sys.exit(1)
+ print 'nothing to do'
+ sys.exit(1)
+ pass
+
- if verbose:
- fd.write("Attempting the following command: %s\n" % cmdstr_on)
- strr = os.system(cmdstr_on)
- time.sleep(1)
- strr,code = execWithCaptureStatus("/usr/bin/snmpget",args_status)
- #strr = os.system(cmdstr_status)
- if verbose:
- fd.write("Result: %s\n" % strr)
- if strr.find(POWER_ON) >= 0:
- if verbose:
- fd.close()
- print "Success: Outlet Rebooted."
- sys.exit(0)
- else:
- print "Unable to power on apc outlet"
- if verbose:
- fd.write("Unable to power on apc outlet")
- fd.close()
- sys.exit(1)
-
+
def execWithCaptureStatus(command, argv, searchPath = 0, root = '/', stdin = 0,
catchfd = 1, closefd = -1):
if not os.access (root + command, os.X_OK):
- raise RuntimeError, command + " cannot be run"
+ raise Exception, command + " cannot be run"
(read, write) = os.pipe()
@@ -364,4 +459,5 @@
return (rc, status)
if __name__ == "__main__":
- main()
+ ret = main()
+ sys.exit(ret)
More information about the Cluster-devel
mailing list