From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22054 invoked by alias); 22 Jul 2008 05:00:19 -0000 Received: (qmail 22013 invoked by uid 9702); 22 Jul 2008 05:00:13 -0000 Date: Tue, 22 Jul 2008 05:00:00 -0000 Message-ID: <20080722050013.21995.qmail@sourceware.org> From: fabbione@sourceware.org To: cluster-cvs@sources.redhat.com, cluster-devel@redhat.com Subject: Cluster Project branch, master, updated. cluster-2.99.06-40-gb3877bc X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: 4552c160f7daf9b5a4af3db302c64ddc76082601 X-Git-Newrev: b3877bc1cb5e24c72a480f48ef05b008471c6627 Mailing-List: contact cluster-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cluster-cvs-owner@sourceware.org X-SW-Source: 2008-q3/txt/msg00113.txt.bz2 This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Cluster Project". http://sources.redhat.com/git/gitweb.cgi?p=cluster.git;a=commitdiff;h=b3877bc1cb5e24c72a480f48ef05b008471c6627 The branch, master has been updated via b3877bc1cb5e24c72a480f48ef05b008471c6627 (commit) from 4552c160f7daf9b5a4af3db302c64ddc76082601 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b3877bc1cb5e24c72a480f48ef05b008471c6627 Author: Fabio M. Di Nitto Date: Tue Jul 22 06:59:28 2008 +0200 [FENCE] Sync fence_apc_snmp from RHEL47 branch Signed-off-by: Fabio M. Di Nitto ----------------------------------------------------------------------- Summary of changes: fence/agents/apc_snmp/fence_apc_snmp.py | 576 ++++++++++++++++++------------- 1 files changed, 336 insertions(+), 240 deletions(-) diff --git a/fence/agents/apc_snmp/fence_apc_snmp.py b/fence/agents/apc_snmp/fence_apc_snmp.py index da8a4e8..63de054 100644 --- a/fence/agents/apc_snmp/fence_apc_snmp.py +++ b/fence/agents/apc_snmp/fence_apc_snmp.py @@ -9,7 +9,7 @@ import getopt, sys import os -import time +import datetime import select import signal from glob import glob @@ -24,49 +24,251 @@ POWER_ON="outletOn" 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 = ['@SNMPBIN@/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("@SNMPBIN@/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 = ['@SNMPBIN@/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("@SNMPBIN@/snmpset", args) + if code: + raise Exception, 'snmpset failed' + + def walk(self, oid): + args = ['@SNMPBIN@/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("@SNMPBIN@/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 or stat == "outletStatusOn": + return 'on' + elif stat == self.state_off or stat == "outletStatusOff": + 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 address or hostname of MasterSwitch"; - print " -h usage"; - print " -l Login name"; - print " -n Outlet number to change"; - print " -o Action: Reboot (default), Off or On"; - print " -p 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 address or hostname of fence device" + print " -u UDP port to use (default 161)" + print " -c SNMP community (default 'private')" + print " -n Outlet name/number to act on" + print " -o 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." +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) - address = "" - output = "" - port = "" - action = "outletReboot" - status_check = False - verbose = False - if not glob('@MIBDIR@/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 @MIBDIR@\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": @@ -76,229 +278,122 @@ def main(): 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("@SNMPBIN@/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("@SNMPBIN@/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("@SNMPBIN@/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("@SNMPBIN@/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("@SNMPBIN@/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("@SNMPBIN@/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("@SNMPBIN@/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() @@ -351,4 +446,5 @@ def execWithCaptureStatus(command, argv, searchPath = 0, root = '/', stdin = 0, return (rc, status) if __name__ == "__main__": - main() + ret = main() + sys.exit(ret) hooks/post-receive -- Cluster Project