blob: 3595071f94c9d6aa0f482f41b05b964f290c332f [file] [log] [blame]
#!/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()