Index: conmux/drivers/fence_apc_snmp.py |
diff --git a/conmux/drivers/fence_apc_snmp.py b/conmux/drivers/fence_apc_snmp.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..3595071f94c9d6aa0f482f41b05b964f290c332f |
--- /dev/null |
+++ b/conmux/drivers/fence_apc_snmp.py |
@@ -0,0 +1,370 @@ |
+#!/usr/bin/python |
+ |
+############################################################################# |
+############################################################################# |
+## |
+## Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
+## Copyright (C) 2004-2006 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 |
+## of the GNU General Public License v.2. |
+## |
+############################################################################# |
+## 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/ |
+############################################################################# |
+############################################################################# |
+ |
+ |
+ |
+import getopt, sys |
+import os |
+import time |
+import select |
+import signal |
+from glob import glob |
+ |
+#BEGIN_VERSION_GENERATION |
+FENCE_RELEASE_NAME="" |
+REDHAT_COPYRIGHT="" |
+BUILD_DATE="" |
+#END_VERSION_GENERATION |
+ |
+POWER_ON="outletOn" |
+POWER_OFF="outletOff" |
+POWER_REBOOT="outletReboot" |
+ |
+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 sys.argv |
+ 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 |
+ |
+ 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) |
+ |
+ if len(sys.argv) > 1: |
+ try: |
+ opts, args = getopt.getopt(sys.argv[1:], "a:hl:p:n:o:vV", ["help", "output="]) |
+ except getopt.GetoptError: |
+ #print help info and quit |
+ usage() |
+ sys.exit(2) |
+ |
+ for o, a in opts: |
+ if o == "-v": |
+ verbose = True |
+ if o == "-V": |
+ print "%s\n" % FENCE_RELEASE_NAME |
+ print "%s\n" % REDHAT_COPYRIGHT |
+ print "%s\n" % BUILD_DATE |
+ 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() |
+ if o == "-a": |
+ address = a |
+ |
+ if address == "": |
+ usage() |
+ sys.exit(1) |
+ |
+ if port == "": |
+ usage() |
+ sys.exit(1) |
+ |
+ else: #Get opts from stdin |
+ params = {} |
+ #place params in dict |
+ for line in sys.stdin: |
+ val = line.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) |
+ |
+ |
+ 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() |
+ |
+ 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) |
+ |
+ 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" |
+ |
+ (read, write) = os.pipe() |
+ |
+ childpid = os.fork() |
+ if (not childpid): |
+ if (root and root != '/'): os.chroot (root) |
+ if isinstance(catchfd, tuple): |
+ for fd in catchfd: |
+ os.dup2(write, fd) |
+ else: |
+ os.dup2(write, catchfd) |
+ os.close(write) |
+ os.close(read) |
+ |
+ if closefd != -1: |
+ os.close(closefd) |
+ |
+ if stdin: |
+ os.dup2(stdin, 0) |
+ os.close(stdin) |
+ |
+ if (searchPath): |
+ os.execvp(command, argv) |
+ else: |
+ os.execv(command, argv) |
+ |
+ sys.exit(1) |
+ |
+ os.close(write) |
+ |
+ rc = "" |
+ s = "1" |
+ while (s): |
+ select.select([read], [], []) |
+ s = os.read(read, 1000) |
+ rc = rc + s |
+ |
+ os.close(read) |
+ |
+ pid = -1 |
+ status = -1 |
+ try: |
+ (pid, status) = os.waitpid(childpid, 0) |
+ except OSError, (errno, msg): |
+ print __name__, "waitpid:", msg |
+ |
+ if os.WIFEXITED(status) and (os.WEXITSTATUS(status) == 0): |
+ status = os.WEXITSTATUS(status) |
+ else: |
+ status = -1 |
+ |
+ return (rc, status) |
+ |
+if __name__ == "__main__": |
+ main() |