On Sun, 2010-11-14 at 22:23 +0300, Dmitry Monakhov wrote: > expect scripts are not very reliable, let's add an alternative snmp > method.
Looks good to me, Dimitry. Applied: http://autotest.kernel.org/changeset/4948 > Signed-off-by: Dmitry Monakhov <[email protected]> > --- > conmux/drivers/fence_apc_snmp.py | 370 > ++++++++++++++++++++++++++++++++++++++ > conmux/drivers/module.mk | 2 +- > conmux/examples/apc_snmp.cf | 4 + > 3 files changed, 375 insertions(+), 1 deletions(-) > create mode 100755 conmux/drivers/fence_apc_snmp.py > create mode 100644 conmux/examples/apc_snmp.cf > > diff --git a/conmux/drivers/fence_apc_snmp.py > b/conmux/drivers/fence_apc_snmp.py > new file mode 100755 > index 0000000..18c7303 > --- /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() > diff --git a/conmux/drivers/module.mk b/conmux/drivers/module.mk > index 0cc24f9..4d17ca6 100644 > --- a/conmux/drivers/module.mk > +++ b/conmux/drivers/module.mk > @@ -5,7 +5,7 @@ > > DRIVERS:=blade hmc reboot-netfinity reboot-newisys reboot-numaq \ > reboot-rsa reboot-rsa2 zseries-console x3270_glue.expect \ > - reboot-acs48 reboot-apc reboot-laurel > + reboot-acs48 reboot-apc reboot-laurel fence_apc_snmp.py > > install:: > @[ -d $(BASE)/lib/drivers ] || mkdir $(BASE)/lib/drivers > diff --git a/conmux/examples/apc_snmp.cf b/conmux/examples/apc_snmp.cf > new file mode 100644 > index 0000000..d0a4add > --- /dev/null > +++ b/conmux/examples/apc_snmp.cf > @@ -0,0 +1,4 @@ > +listener localhost/ts63 > +socket console 'console' 'localhost:13467' > +command 'config' 'Show conmux configuration' 'cat > /usr/local/conmux/etc/apc_snmp.cf' > +command 'hardreset' 'initiated a hard reset' 'fence_apc_snmp.py -a > pdu.xx.com -n 11 -l root' _______________________________________________ Autotest mailing list [email protected] http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
