[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [PATCH][fence-agents] fence_eaton_snmp: add support for Eaton Switched ePDU



Hi,

you will find attachedĀ  a patch that adds support for Eaton Switched ePDU to fence_eaton_snmp.
please consider applying it.

cheers,
Arnaud
--
Linux / Unix Expert R&D - Eaton - http://powerquality.eaton.com
Network UPS Tools (NUT) Project Leader - http://www.networkupstools.org/
Debian Developer - http://www.debian.org
Free Software Developer - http://arnaud.quette.free.fr/

diff --git a/fence/agents/eaton_snmp/fence_eaton_snmp.py b/fence/agents/eaton_snmp/fence_eaton_snmp.py
index 81d9810..e24cc13 100644
--- a/fence/agents/eaton_snmp/fence_eaton_snmp.py
+++ b/fence/agents/eaton_snmp/fence_eaton_snmp.py
@@ -1,7 +1,8 @@
 #!/usr/bin/python
 
 # The Following agent has been tested on:
-# - Eaton ePDU managed - SNMP v1
+# - Eaton ePDU Managed - SNMP v1
+# - Eaton ePDU Switched - SNMP v1
 
 import sys, re, pexpect
 sys.path.append("@FENCEAGENTSLIBDIR@")
@@ -19,7 +20,7 @@ BUILD_DATE=""
 OID_SYS_OBJECT_ID='.1.3.6.1.2.1.1.2.0'
 
 ### GLOBAL VARIABLES ###
-# Device - see EatonManagedePDU
+# Device - see EatonManagedePDU, EatonSwitchedePDU
 device=None
 
 # Port ID
@@ -27,7 +28,11 @@ port_id=None
 # Switch ID
 switch_id=None
 
+# Did we issue a set before get (to adjust OID with Switched ePDU)
+after_set=False
+
 # Classes describing Device params
+# Managed ePDU
 class EatonManagedePDU:
 	status_oid=      '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
 	control_oid=     '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.3.%d'
@@ -35,18 +40,34 @@ class EatonManagedePDU:
 	ident_str="Eaton Managed ePDU"
 	state_off=0
 	state_on=1
-	state_cycling=2
+	state_cycling=2	# FIXME: not usable with fence-agents
 	turn_off=0
 	turn_on=1
-	turn_cycle=2
-	# FIXME: what's this?
+	turn_cycle=2	# FIXME: not usable with fence-agents
+	has_switches=False
+
+# Switched ePDU (Pulizzi 2)
+# NOTE: sysOID reports "20677.1", while data are actually at "20677.2"
+class EatonSwitchedePDU:
+	status_oid=      '.1.3.6.1.4.1.20677.2.6.3.%d.0'
+	control_oid=     '.1.3.6.1.4.1.20677.2.6.2.%d.0'
+	outlet_table_oid='.1.3.6.1.4.1.20677.2.6.3'
+	ident_str="Eaton Switched ePDU"
+	state_off=2
+	state_on=1
+	state_cycling=0 # Note: this status doesn't exist on this device
+	turn_off=2
+	turn_on=1
+	turn_cycle=3	# FIXME: not usable with fence-agents
 	has_switches=False
 
 ### FUNCTIONS ###
 def eaton_set_device(conn,options):
 	global device
 
-	agents_dir={'.1.3.6.1.4.1.534.6.6.6':EatonManagedePDU}
+	agents_dir={'.1.3.6.1.4.1.534.6.6.6':EatonManagedePDU,
+				'.1.3.6.1.4.1.20677.1':EatonSwitchedePDU,
+				'.1.3.6.1.4.1.20677.2':EatonSwitchedePDU }
 
 	# First resolve type of Eaton
 	eaton_type=conn.walk(OID_SYS_OBJECT_ID)
@@ -64,6 +85,10 @@ def eaton_resolv_port_id(conn,options):
 	if (device==None):
 		eaton_set_device(conn,options)
 
+	# Restore the increment, that was removed in main for ePDU Managed
+	if (device.ident_str == "Eaton Switched ePDU"):
+		options["-n"] = str(int(options["-n"]) + 1)
+
 	# Now we resolv port_id/switch_id
 	if ((options["-n"].isdigit()) and ((not device.has_switches) or (options["-s"].isdigit()))):
 		port_id=int(options["-n"])
@@ -80,28 +105,53 @@ def eaton_resolv_port_id(conn,options):
 					port_id=int(t[len(t)-1])
 					switch_id=int(t[len(t)-3])
 				else:
-					port_id=int(t[len(t)-1])
+					if (device.ident_str == "Eaton Switched ePDU"):
+						port_id=int(t[len(t)-3])
+					else:
+						port_id=int(t[len(t)-1])
 
 	if (port_id==None):
+		# Restore index offset, to provide a valid error output on Managed ePDU
+		if (device.ident_str != "Eaton Switched ePDU"):
+			options["-n"] = str(int(options["-n"]) + 1)
 		fail_usage("Can't find port with name %s!"%(options["-n"]))
 
 def get_power_status(conn,options):
-	global port_id,switch_id,device
+	global port_id,switch_id,device,after_set
 
 	if (port_id==None):
 		eaton_resolv_port_id(conn,options)
 
+	# Ajust OID for Switched ePDU when the get is after a set
+	if ((after_set == True) and (device.ident_str == "Eaton Switched ePDU")):
+		port_id-=1
+		after_set=False
+
 	oid=((device.has_switches) and device.status_oid%(switch_id,port_id) or device.status_oid%(port_id))
 
-	(oid,status)=conn.get(oid)
-	return (status==str(device.state_on) and "on" or "off")
+	try:
+		(oid,status)=conn.get(oid)
+		if (status==str(device.state_on)):
+			return "on"
+		elif (status==str(device.state_off)):
+			return "off"
+		else:
+			return None
+	except:
+		return None
 
 def set_power_status(conn, options):
-	global port_id,switch_id,device
+	global port_id,switch_id,device,after_set
+
+	after_set = True
 
 	if (port_id==None):
 		eaton_resolv_port_id(conn,options)
 
+	# Controls start at #2 on Switched ePDU, since #1 is the global command
+	if (device.ident_str == "Eaton Switched ePDU"):
+		port_id=int(port_id)+1
+
 	oid=((device.has_switches) and device.control_oid%(switch_id,port_id) or device.control_oid%(port_id))
 
 	conn.set(oid,(options["-o"]=="on" and device.turn_on or device.turn_off))
@@ -110,6 +160,7 @@ def set_power_status(conn, options):
 def get_outlets_status(conn, options):
 	global device
 
+	outletCount = 0
 	result={}
 
 	if (device==None):
@@ -118,19 +169,31 @@ def get_outlets_status(conn, options):
 	res_ports=conn.walk(device.outlet_table_oid,30)
 
 	for x in res_ports:
+		outletCount+=1
+		status=x[1]
 		t=x[0].split('.')
 
 		# Plug indexing start from zero, so we substract '1' from the
 		# user's given plug number
-		port_num=str(int(((device.has_switches) and "%s:%s"%(t[len(t)-3],t[len(t)-1]) or "%s"%(t[len(t)-1]))) + 1)
-
-                # Plug indexing start from zero, so we add '1'
-                # for the user's exposed plug number
-                port_name=str(int(x[1].strip('"')) + 1)
-                port_status=""
-                result[port_num]=(port_name,port_status)
-
-        return result
+		if (device.ident_str == "Eaton Managed ePDU"):
+			port_num=str(int(((device.has_switches) and "%s:%s"%(t[len(t)-3],t[len(t)-1]) or "%s"%(t[len(t)-1]))) + 1)
+
+			# Plug indexing start from zero, so we add '1'
+			# for the user's exposed plug number
+			port_name=str(int(x[1].strip('"')) + 1)
+			port_status=""
+			result[port_num]=(port_name,port_status)
+		else:
+			# Switched ePDU do not propose an outletCount OID!
+			# Invalid status (ie value == '0'), retrieved via the walk,
+			# means the outlet is absent
+			port_num=str(outletCount)
+			port_name=str(outletCount)
+			port_status=""
+			if (status != '0'):
+				result[port_num]=(port_name,port_status)
+
+	return result
 
 # Define new options
 def eaton_snmp_define_defaults():
@@ -154,7 +217,7 @@ def main():
 
 	options=check_input(device_opt,process_input(device_opt))
 
-        ## Support for -n [switch]:[plug] notation that was used before
+	## Support for -n [switch]:[plug] notation that was used before
 	if ((options.has_key("-n")) and (-1 != options["-n"].find(":"))):
 		(switch, plug) = options["-n"].split(":", 1)
 		if ((switch.isdigit()) and (plug.isdigit())):
@@ -164,8 +227,9 @@ def main():
 	if (not (options.has_key("-s"))):
 		options["-s"]="1"
 
-	# Plug indexing start from zero, so we substract '1' from the
-	# user's given plug number
+	# Plug indexing start from zero on ePDU Managed, so we substract '1' from
+	# the user's given plug number.
+	# For Switched ePDU, we will add this back again later.
 	if ((options.has_key("-n")) and (options["-n"].isdigit())):
 		options["-n"] = str(int(options["-n"]) - 1)
 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]