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

Reply via email to