From: kupcevic@sourceware.org <kupcevic@sourceware.org>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] cluster/fence/agents apc/fence_apc_snmp.py apc ...
Date: 17 Apr 2007 05:53:24 -0000 [thread overview]
Message-ID: <20070417055324.11901.qmail@sourceware.org> (raw)
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)
next reply other threads:[~2007-04-17 5:53 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-17 5:53 kupcevic [this message]
-- strict thread matches above, loose matches on Subject: below --
2007-04-16 22:33 [Cluster-devel] cluster/fence/agents apc/fence_apc_snmp.py apc kupcevic
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070417055324.11901.qmail@sourceware.org \
--to=kupcevic@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.