diff --git a/fence/agents/apc/fence_apc.py b/fence/agents/apc/fence_apc.py index d0ed9b65..fa1c3a65 100644 --- a/fence/agents/apc/fence_apc.py +++ b/fence/agents/apc/fence_apc.py @@ -1,236 +1,237 @@ #!/usr/bin/python ##### ## ## The Following Agent Has Been Tested On: ## ## Model Firmware ## +---------------------------------------------+ ## AP7951 AOS v2.7.0, PDU APP v2.7.3 ## AP7941 AOS v3.5.7, PDU APP v3.5.6 ## AP9606 AOS v2.5.4, PDU APP v2.7.3 ## ## @note: ssh is very slow on AP79XX devices protocol (1) and ## cipher (des/blowfish) have to be defined ##### import sys, re, pexpect, exceptions sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New APC Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="March, 2008" #END_VERSION_GENERATION def get_power_status(conn, options): exp_result = 0 outlets = {} try: conn.send_eol("1") conn.log_expect(options, options["-c"], int(options["-Y"])) version = 0 admin = 0 switch = 0 if (None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before)): switch = 1 if (None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before)): if (0 == options.has_key("-s")): fail_usage("Failed: You have to enter physical switch number") else: if (0 == options.has_key("-s")): options["-s"] = "1" if (None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before)): version = 2 else: version = 3 if (None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before)): admin = 0 else: admin = 1 if switch == 0: if version == 2: if admin == 0: conn.send_eol("2") else: conn.send_eol("3") else: conn.send_eol("2") conn.log_expect(options, options["-c"], int(options["-Y"])) conn.send_eol("1") else: conn.send_eol(options["-s"]) while True: exp_result = conn.log_expect(options, [ options["-c"], "Press " ], int(options["-Y"])) lines = conn.before.split("\n") show_re = re.compile('(^|\x0D)\s*(\d+)- (.*?)\s+(ON|OFF)\s*') for x in lines: res = show_re.search(x) if (res != None): outlets[res.group(2)] = (res.group(3), res.group(4)) conn.send_eol("") if exp_result == 0: break conn.send(chr(03)) conn.log_expect(options, "- Logout", int(options["-Y"])) conn.log_expect(options, options["-c"], int(options["-Y"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) if ["list", "monitor"].count(options["-o"]) == 1: return outlets else: try: (_, status) = outlets[options["-n"]] return status.lower().strip() except KeyError: fail(EC_STATUS) def set_power_status(conn, options): action = { 'on' : "1", 'off': "2" }[options["-o"]] try: conn.send_eol("1") conn.log_expect(options, options["-c"], int(options["-Y"])) version = 0 admin2 = 0 admin3 = 0 switch = 0 if (None != re.compile('.* MasterSwitch plus.*', re.IGNORECASE | re.S).match(conn.before)): switch = 1 ## MasterSwitch has different schema for on/off actions action = { 'on' : "1", 'off': "3" }[options["-o"]] if (None != re.compile('.* MasterSwitch plus 2', re.IGNORECASE | re.S).match(conn.before)): if (0 == options.has_key("-s")): fail_usage("Failed: You have to enter physical switch number") else: if (0 == options.has_key("-s")): options["-s"] = 1 if (None == re.compile('.*Outlet Management.*', re.IGNORECASE | re.S).match(conn.before)): version = 2 else: version = 3 if (None == re.compile('.*Outlet Control/Configuration.*', re.IGNORECASE | re.S).match(conn.before)): admin2 = 0 else: admin2 = 1 if switch == 0: if version == 2: if admin2 == 0: conn.send_eol("2") else: conn.send_eol("3") else: conn.send_eol("2") conn.log_expect(options, options["-c"], int(options["-Y"])) if (None == re.compile('.*2- Outlet Restriction.*', re.IGNORECASE | re.S).match(conn.before)): admin3 = 0 else: admin3 = 1 conn.send_eol("1") else: conn.send_eol(options["-s"]) while 1 == conn.log_expect(options, [ options["-c"], "Press " ], int(options["-Y"])): conn.send_eol("") + conn.send_eol(options["-n"]+"") conn.log_expect(options, options["-c"], int(options["-Y"])) if switch == 0: if admin2 == 1: conn.send_eol("1") conn.log_expect(options, options["-c"], int(options["-Y"])) if admin3 == 1: conn.send_eol("1") conn.log_expect(options, options["-c"], int(options["-Y"])) else: conn.send_eol("1") conn.log_expect(options, options["-c"], int(options["-Y"])) conn.send_eol(action) conn.log_expect(options, "Enter 'YES' to continue or to cancel :", int(options["-Y"])) conn.send_eol("YES") conn.log_expect(options, "Press to continue...", int(options["-Y"])) conn.send_eol("") conn.log_expect(options, options["-c"], int(options["-Y"])) conn.send(chr(03)) conn.log_expect(options, "- Logout", int(options["-Y"])) conn.log_expect(options, options["-c"], int(options["-Y"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "cmd_prompt", "secure", "port", "identity_file", "switch", "test", "separator", "inet4_only", "inet6_only", "ipport" ] atexit.register(atexit_handler) all_opt["cmd_prompt"]["default"] = "\n>" options = check_input(device_opt, process_input(device_opt)) options["ssh_options"] = "-1 -c blowfish" docs = { } docs["shortdesc"] = "Fence agent for APC over telnet/ssh" docs["longdesc"] = "fence_apc is an I/O Fencing agent \ which can be used with the APC network power switch. It logs into device \ via telnet/ssh and reboots a specified outlet. Lengthy telnet/ssh connections \ should be avoided while a GFS cluster is running because the connection \ will block any necessary fencing actions." docs["vendorurl"] = "http://www.apc.com" show_docs(options, docs) ## Support for -n [switch]:[plug] notation that was used before if (options.has_key("-n") == 1) and (-1 != options["-n"].find(":")): (switch, plug) = options["-n"].split(":", 1) options["-s"] = switch options["-n"] = plug ## ## Operate the fencing device #### conn = fence_login(options) result = fence_action(conn, options, set_power_status, get_power_status, get_power_status) ## ## Logout from system ## ## In some special unspecified cases it is possible that ## connection will be closed before we run close(). This is not ## a problem because everything is checked before. ###### try: conn.send_eol("4") conn.close() except exceptions.OSError: pass except pexpect.ExceptionPexpect: pass sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/apc_snmp/fence_apc_snmp.py b/fence/agents/apc_snmp/fence_apc_snmp.py index cc624a10..6f95f378 100644 --- a/fence/agents/apc_snmp/fence_apc_snmp.py +++ b/fence/agents/apc_snmp/fence_apc_snmp.py @@ -1,204 +1,198 @@ #!/usr/bin/python # The Following agent has been tested on: # - APC Switched Rack PDU (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3 AN1:apc_hw02_aos_270.bin # AF1:v2.7.3 AN1:apc_hw02_rpdu_273.bin MN:AP7930 HR:B2) - SNMP v1 # - APC Web/SNMP Management Card (MB:v3.8.6 PF:v3.5.8 PN:apc_hw02_aos_358.bin AF1:v3.5.7 AN1:apc_hw02_aos_358.bin # AF1:v3.5.7 AN1:apc_hw02_rpdu_357.bin MN:AP7900 HR:B2) - SNMP v1 and v3 (noAuthNoPrivacy,authNoPrivacy, authPrivacy) # - APC Switched Rack PDU (MB:v3.7.0 PF:v2.7.0 PN:apc_hw02_aos_270.bin AF1:v2.7.3 AN1:apc_hw02_rpdu_273.bin # MN:AP7951 HR:B2) - SNMP v1 import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="APC SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # oid defining fence device OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0' ### GLOBAL VARIABLES ### # Device - see ApcRPDU, ApcMSP, ApcMS device = None # Port ID port_id = None # Switch ID switch_id = None # Classes describing Device params class ApcRPDU: # Rack PDU status_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.4.%d' control_oid = '.1.3.6.1.4.1.318.1.1.12.3.3.1.1.4.%d' outlet_table_oid = '.1.3.6.1.4.1.318.1.1.12.3.5.1.1.2' ident_str = "APC rPDU" state_on = 1 state_off = 2 turn_on = 1 turn_off = 2 has_switches = False class ApcMSP: # Master Switch+ status_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.5.%d.1.%d' control_oid = '.1.3.6.1.4.1.318.1.1.6.5.1.1.5.%d.1.%d' outlet_table_oid = '.1.3.6.1.4.1.318.1.1.6.7.1.1.4' ident_str = "APC Master Switch+" state_on = 1 state_off = 2 turn_on = 1 turn_off = 3 has_switches = True class ApcMS: # Master Switch - seems oldest, but supported on every APC PDU status_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d' control_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.3.%d' outlet_table_oid = '.1.3.6.1.4.1.318.1.1.4.4.2.1.4' ident_str = "APC Master Switch (fallback)" state_on = 1 state_off = 2 turn_on = 1 turn_off = 2 has_switches = False ### FUNCTIONS ### def apc_set_device(conn, options): global device agents_dir = {'.1.3.6.1.4.1.318.1.3.4.5':ApcRPDU, '.1.3.6.1.4.1.318.1.3.4.4':ApcMSP, None:ApcMS} # First resolve type of APC apc_type = conn.walk(OID_SYS_OBJECT_ID) if (not ((len(apc_type)==1) and (agents_dir.has_key(apc_type[0][1])))): apc_type = [[None, None]] device = agents_dir[apc_type[0][1]] conn.log_command("Trying %s"%(device.ident_str)) def apc_resolv_port_id(conn, options): - global port_id, switch_id, device + global port_id, switch_id if (device == None): apc_set_device(conn, options) # 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"]) if (device.has_switches): switch_id = int(options["-s"]) else: table = conn.walk(device.outlet_table_oid, 30) for x in table: if (x[1].strip('"') == options["-n"]): t = x[0].split('.') if (device.has_switches): port_id = int(t[len(t)-1]) switch_id = int(t[len(t)-3]) else: port_id = int(t[len(t)-1]) if (port_id == None): fail_usage("Can't find port with name %s!"%(options["-n"])) def get_power_status(conn, options): - global port_id, switch_id, device - if (port_id == None): apc_resolv_port_id(conn, options) 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") def set_power_status(conn, options): - global port_id, switch_id, device - if (port_id == None): apc_resolv_port_id(conn, options) 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)) def get_outlets_status(conn, options): - global device - result = {} if (device == None): apc_set_device(conn, options) res_ports = conn.walk(device.outlet_table_oid, 30) for x in res_ports: t = x[0].split('.') port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1])) port_name = x[1].strip('"') port_status = "" result[port_num] = (port_name, port_status) return result # Define new options def apc_snmp_define_defaults(): all_opt["snmp_version"]["default"] = "1" all_opt["community"]["default"] = "private" # Main agent method def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () apc_snmp_define_defaults() options = check_input(device_opt, process_input(device_opt)) ## 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())): options["-s"] = switch options["-n"] = plug if (not (options.has_key("-s"))): options["-s"] = "1" docs = { } docs["shortdesc"] = "Fence agent for APC over SNMP" docs["longdesc"] = "fence_apc_snmp is an I/O Fencing agent \ which can be used with the APC network power switch. It logs \ into a device via SNMP and reboots a specified outlet. It supports \ SNMP v1 and v3 with all combinations of authenticity/privacy settings." docs["vendorurl"] = "http://www.apc.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/bladecenter/fence_bladecenter.py b/fence/agents/bladecenter/fence_bladecenter.py index 49a3b5be..2825dbec 100644 --- a/fence/agents/bladecenter/fence_bladecenter.py +++ b/fence/agents/bladecenter/fence_bladecenter.py @@ -1,136 +1,136 @@ #!/usr/bin/python ##### ## ## The Following Agent Has Been Tested On: ## ## Model Firmware ## +--------------------+---------------------------+ ## (1) Main application BRET85K, rev 16 ## Boot ROM BRBR67D, rev 16 ## Remote Control BRRG67D, rev 16 ## ##### import sys, re, pexpect, exceptions sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New Bladecenter Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="March, 2008" #END_VERSION_GENERATION def get_power_status(conn, options): try: node_cmd = "system:blade\[" + options["-n"] + "\]>" conn.send_eol("env -T system:blade[" + options["-n"] + "]") i = conn.log_expect(options, [ node_cmd, "system>" ] , int(options["-Y"])) if i == 1: ## Given blade number does not exist if options.has_key("-M"): return "off" else: fail(EC_STATUS) conn.send_eol("power -state") conn.log_expect(options, node_cmd, int(options["-Y"])) status = conn.before.splitlines()[-1] conn.send_eol("env -T system") conn.log_expect(options, options["-c"], int(options["-Y"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) return status.lower().strip() def set_power_status(conn, options): try: node_cmd = "system:blade\[" + options["-n"] + "\]>" conn.send_eol("env -T system:blade[" + options["-n"] + "]") i = conn.log_expect(options, [ node_cmd, "system>" ] , int(options["-Y"])) if i == 1: ## Given blade number does not exist if options.has_key("-M"): return else: fail(EC_GENERIC_ERROR) conn.send_eol("power -"+options["-o"]) conn.log_expect(options, node_cmd, int(options["-Y"])) conn.send_eol("env -T system") conn.log_expect(options, options["-c"], int(options["-Y"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) def get_blades_list(conn, options): outlets = { } try: node_cmd = "system>" conn.send_eol("env -T system") conn.log_expect(options, node_cmd, int(options["-Y"])) conn.send_eol("list -l 2") conn.log_expect(options, node_cmd, int(options["-Y"])) lines = conn.before.split("\r\n") filter_re = re.compile("^\s*blade\[(\d+)\]\s+(.*?)\s*$") - for x in lines: - res = filter_re.search(x) + for blade_line in lines: + res = filter_re.search(blade_line) if res != None: outlets[res.group(1)] = (res.group(2), "") except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) return outlets def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "cmd_prompt", "secure", "port", "identity_file", "separator", "inet4_only", "inet6_only", "ipport", "missing_as_off" ] atexit.register(atexit_handler) all_opt["power_wait"]["default"] = "10" all_opt["cmd_prompt"]["default"] = "system>" options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for IBM BladeCenter" docs["longdesc"] = "fence_bladecenter is an I/O Fencing agent \ which can be used with IBM Bladecenters with recent enough firmware that \ includes telnet support. It logs into a Brocade chasis via telnet or ssh \ and uses the command line interface to power on and off blades." docs["vendorurl"] = "http://www.ibm.com" show_docs(options, docs) ## ## Operate the fencing device ###### conn = fence_login(options) result = fence_action(conn, options, set_power_status, get_power_status, get_blades_list) ## ## Logout from system ###### try: conn.send_eol("exit") conn.close() except exceptions.OSError: pass except pexpect.ExceptionPexpect: pass sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/cisco_mds/fence_cisco_mds.py b/fence/agents/cisco_mds/fence_cisco_mds.py index 8f3ef9df..8ebce8ac 100644 --- a/fence/agents/cisco_mds/fence_cisco_mds.py +++ b/fence/agents/cisco_mds/fence_cisco_mds.py @@ -1,112 +1,108 @@ #!/usr/bin/python # The Following agent has been tested on: # - Cisco MDS UROS 9134 FC (1 Slot) Chassis ("1/2/4 10 Gbps FC/Supervisor-2") Motorola, e500v2 # with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c) # - Cisco MDS 9124 (1 Slot) Chassis ("1/2/4 Gbps FC/Supervisor-2") Motorola, e500 # with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c) import sys, re sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="Cisco MDS 9xxx SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # Cisco admin status PORT_ADMIN_STATUS_OID = ".1.3.6.1.2.1.75.1.2.2.1.1" # IF-MIB trees for alias, status and port ALIASES_OID = ".1.3.6.1.2.1.31.1.1.1.18" PORTS_OID = ".1.3.6.1.2.1.2.2.1.2" ### GLOBAL VARIABLES ### # OID converted from fc port name (fc(x)/(y)) -port_oid = "" +PORT_OID = "" ### FUNCTIONS ### # Convert cisco port name (fc(x)/(y)) to OID def cisco_port2oid(port): port = port.lower() nums = re.match('^fc(\d+)/(\d+)$', port) if ((nums) and (len(nums.groups()))==2): return "%s.%d.%d"% (PORT_ADMIN_STATUS_OID, int(nums.group(1))+21, int(nums.group(2))-1) else: fail_usage("Mangled port number: %s"%(port)) def get_power_status(conn, options): - global port_oid - - (oid, status) = conn.get(port_oid) + (oid, status) = conn.get(PORT_OID) return (status=="1" and "on" or "off") def set_power_status(conn, options): - global port_oid - - conn.set(port_oid,(options["-o"]=="on" and 1 or 2)) + conn.set(PORT_OID, (options["-o"]=="on" and 1 or 2)) # Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is # in format a.b.c.d...z and returned dict has key only z def array_to_dict(ar): return dict(map(lambda y:[y[0].split('.')[-1], y[1]], ar)) def get_outlets_status(conn, options): result = {} res_fc = conn.walk(PORTS_OID, 30) res_aliases = array_to_dict(conn.walk(ALIASES_OID, 30)) fc_re = re.compile('^"fc\d+/\d+"$') for x in res_fc: if fc_re.match(x[1]): port_num = x[0].split('.')[-1] port_name = x[1].strip('"') port_alias = (res_aliases.has_key(port_num) and res_aliases[port_num].strip('"') or "") port_status = "" result[port_name] = (port_alias, port_status) return result # Main agent method def main(): - global port_oid + global PORT_OID device_opt = [ "fabric_fencing", "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for Cisco MDS" docs["longdesc"] = "fence_cisco_mds is an I/O Fencing agent \ which can be used with any Cisco MDS 9000 series with SNMP enabled device." docs["vendorurl"] = "http://www.cisco.com" show_docs(options, docs) if (not (options["-o"] in ["list","monitor"])): - port_oid = cisco_port2oid(options["-n"]) + PORT_OID = cisco_port2oid(options["-n"]) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/cisco_ucs/fence_cisco_ucs.py b/fence/agents/cisco_ucs/fence_cisco_ucs.py index a34a5805..d1d5f2bd 100644 --- a/fence/agents/cisco_ucs/fence_cisco_ucs.py +++ b/fence/agents/cisco_ucs/fence_cisco_ucs.py @@ -1,145 +1,155 @@ #!/usr/bin/python import sys, re import pycurl, StringIO sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New Cisco UCS Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="March, 2008" #END_VERSION_GENERATION -re_cookie = re.compile("", int(options["-Y"])) + res = send_command(options, \ + "", \ + int(options["-Y"])) except pycurl.error, e: sys.stderr.write(e[1] + "\n") fail(EC_TIMED_OUT) - result = re_status.search(res) + result = RE_STATUS.search(res) if (result == None): fail(EC_STATUS) else: status = result.group(1) if (status == "up"): return "on" else: return "off" def set_power_status(conn, options): action = { 'on' : "up", 'off' : "down" }[options["-o"]] try: - res = send_command(options, "", int(options["-Y"])) + res = send_command(options, \ + "" + \ + "" + \ + "" + \ + "", \ + int(options["-Y"])) except pycurl.error, e: sys.stderr.write(e[1] + "\n") fail(EC_TIMED_OUT) return def get_list(conn, options): outlets = { } try: try: - res = send_command(options, "", int(options["-Y"])) + res = send_command(options, \ + "", \ + int(options["-Y"])) except pycurl.error, e: sys.stderr.write(e[1] + "\n") fail(EC_TIMED_OUT) lines = res.split("= LOG_MODE_VERBOSE: opt["debug_fh"].write(command + "\n") opt["debug_fh"].write(result + "\n") return result def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "ssl", "inet4_only", "inet6_only", "ipport", "port", "web", "separator", "suborg" ] atexit.register(atexit_handler) options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for Cisco UCS" docs["longdesc"] = "fence_cisco_ucs is an I/O Fencing agent which can be \ used with Cisco UCS to fence machines." docs["vendorurl"] = "http://www.cisco.com" show_docs(options, docs) ### Login res = send_command(options, "", int(options["-y"])) - result = re_cookie.search(res) + result = RE_COOKIE.search(res) if (result == None): ## Cookie is absenting in response fail(EC_LOGIN_DENIED) options["cookie"] = result.group(1) ## ## Modify suborg to format /suborg if options["-s"] != "": if options["-s"].startswith("/") == False: options["-s"] = "/" + options["-s"] if options["-s"].endswith("/") == True: options["-s"] = options["-s"][0:-1] ## ## Fence operations #### result = fence_action(None, options, set_power_status, get_power_status, get_list) ### Logout; we do not care about result as we will end in any case send_command(options, "", int(options["-Y"])) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/eaton_snmp/fence_eaton_snmp.py b/fence/agents/eaton_snmp/fence_eaton_snmp.py index 24e29fe2..2c5017b0 100644 --- a/fence/agents/eaton_snmp/fence_eaton_snmp.py +++ b/fence/agents/eaton_snmp/fence_eaton_snmp.py @@ -1,238 +1,236 @@ #!/usr/bin/python # The Following agent has been tested on: # - Eaton ePDU Managed - SNMP v1 # EATON | Powerware ePDU model: Managed ePDU (PW104MA0UB99), firmware: 01.01.01 # - Eaton ePDU Switched - SNMP v1 # EATON | Powerware ePDU model: Switched ePDU (IPV3600), firmware: 2.0.K import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="Eaton SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # oid defining fence device OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0' ### GLOBAL VARIABLES ### # Device - see EatonManagedePDU, EatonSwitchedePDU device = None # Port ID 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' outlet_table_oid = '.1.3.6.1.4.1.534.6.6.6.1.2.2.1.1' ident_str = "Eaton Managed ePDU" state_off = 0 state_on = 1 state_cycling = 2 # FIXME: not usable with fence-agents turn_off = 0 turn_on = 1 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, '.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) if (not ((len(eaton_type)==1) and (agents_dir.has_key(eaton_type[0][1])))): eaton_type = [[None, None]] device = agents_dir[eaton_type[0][1]] conn.log_command("Trying %s"%(device.ident_str)) def eaton_resolv_port_id(conn, options): - global port_id, switch_id, device + global port_id, switch_id 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"]) if (device.has_switches): switch_id = int(options["-s"]) else: table = conn.walk(device.outlet_table_oid, 30) for x in table: if (x[1].strip('"')==options["-n"]): t = x[0].split('.') if (device.has_switches): port_id = int(t[len(t)-1]) switch_id = int(t[len(t)-3]) else: 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, after_set + global port_id, 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)) 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, after_set + global port_id, 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)) def get_outlets_status(conn, options): - global device - outletCount = 0 result = {} if (device==None): eaton_set_device(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 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 # Main agent method def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () all_opt["switch"]["default"] = 1 all_opt["power_wait"]["default"] = 2 all_opt["snmp_version"]["default"] = "1" all_opt["community"]["default"] = "private" options = check_input(device_opt, process_input(device_opt)) # 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) docs = { } docs["shortdesc"] = "Fence agent for Eaton over SNMP" docs["longdesc"] = "fence_eaton_snmp is an I/O Fencing agent \ which can be used with the Eaton network power switch. It logs \ into a device via SNMP and reboots a specified outlet. It supports \ SNMP v1 and v3 with all combinations of authenticity/privacy settings." docs["vendorurl"] = "http://powerquality.eaton.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/hpblade/fence_hpblade.py b/fence/agents/hpblade/fence_hpblade.py index 2953ddc5..c7ceb194 100644 --- a/fence/agents/hpblade/fence_hpblade.py +++ b/fence/agents/hpblade/fence_hpblade.py @@ -1,113 +1,113 @@ #!/usr/bin/python ##### ## ## The Following Agent Has Been Tested On: ## * BladeSystem c7000 Enclosure ##### import sys, re, pexpect, exceptions sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="New Bladecenter Agent - test release on steroids" REDHAT_COPYRIGHT="" BUILD_DATE="March, 2008" #END_VERSION_GENERATION def get_power_status(conn, options): try: conn.send_eol("show server status " + options["-n"]) conn.log_expect(options, options["-c"] , int(options["-Y"])) power_re = re.compile("^\s*Power: (.*?)\s*$") status = "unknown" for line in conn.before.splitlines(): res = power_re.search(line) if res != None: status = res.group(1) if status == "unknown": if options.has_key("-M"): return "off" else: fail(EC_STATUS) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) return status.lower().strip() def set_power_status(conn, options): try: if options["-o"] == "on": conn.send_eol("poweron server " + options["-n"]) elif options["-o"] == "off": conn.send_eol("poweroff server " + options["-n"] + " force") conn.log_expect(options, options["-c"], int(options["-Y"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) def get_blades_list(conn, options): outlets = { } try: conn.send_eol("show server list" ) conn.log_expect(options, options["-c"], int(options["-Y"])) list_re = re.compile("^\s*(.*?)\s+(.*?)\s+(.*?)\s+OK\s+(.*?)\s+(.*?)\s*$") for line in conn.before.splitlines(): - res = list_re.search(line) - if res != None: - outlets[res.group(1)] = (res.group(2), res.group(4).lower()) + res = list_re.search(line) + if res != None: + outlets[res.group(1)] = (res.group(2), res.group(4).lower()) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) return outlets def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "cmd_prompt", "secure", "port", "identity_file", "separator", "inet4_only", "inet6_only", "ipport", "missing_as_off" ] atexit.register(atexit_handler) all_opt["cmd_prompt"]["default"] = "c7000oa>" options = check_input(device_opt, process_input(device_opt)) - docs = { } + docs = { } docs["shortdesc"] = "Fence agent for HP BladeSystem" docs["longdesc"] = "fence_hpblade is an I/O Fencing agent \ which can be used with HP BladeSystem. It logs into an enclosure via telnet or ssh \ and uses the command line interface to power on and off blades." docs["vendorurl"] = "http://www.hp.com" show_docs(options, docs) ## ## Operate the fencing device ###### options["eol"] = "\n" conn = fence_login(options) result = fence_action(conn, options, set_power_status, get_power_status, get_blades_list) ## ## Logout from system ###### try: conn.send_eol("exit") conn.close() except exceptions.OSError: pass except pexpect.ExceptionPexpect: pass sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/ibmblade/fence_ibmblade.py b/fence/agents/ibmblade/fence_ibmblade.py index f9ee9552..ceb747d6 100644 --- a/fence/agents/ibmblade/fence_ibmblade.py +++ b/fence/agents/ibmblade/fence_ibmblade.py @@ -1,80 +1,80 @@ #!/usr/bin/python import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="IBM Blade SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # From fence_ibmblade.pl STATUSES_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.5.1.1.4" # remoteControlBladePowerState CONTROL_OID = ".1.3.6.1.4.1.2.3.51.2.22.1.6.1.1.7" # powerOnOffBlade # Status constants returned as value from SNMP STATUS_DOWN = 0 STATUS_UP = 1 # Status constants to set as value to SNMP STATUS_SET_OFF = 0 STATUS_SET_ON = 1 ### FUNCTIONS ### def get_power_status(conn, options): - (oid,status) = conn.get("%s.%s"%(STATUSES_OID, options["-n"])) - return (status==str(STATUS_UP) and "on" or "off") + (_, status) = conn.get("%s.%s"% (STATUSES_OID, options["-n"])) + return (status == str(STATUS_UP) and "on" or "off") def set_power_status(conn, options): conn.set("%s.%s"%(CONTROL_OID, options["-n"]), (options["-o"]=="on" and STATUS_SET_ON or STATUS_SET_OFF)) -def get_outlets_status(conn, options): +def get_outlets_status(conn, _): result = {} res_blades = conn.walk(STATUSES_OID, 30) - for x in res_blades: - port_num = x[0].split('.')[-1] + for blade_info in res_blades: + port_num = blade_info[0].split('.')[-1] port_alias = "" - port_status = (x[1]==str(STATUS_UP) and "on" or "off") + port_status = (blade_info[1]==str(STATUS_UP) and "on" or "off") result[port_num] = (port_alias, port_status) return result # Main agent method def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults() all_opt["snmp_version"]["default"] = "1" options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for IBM BladeCenter over SNMP" docs["longdesc"] = "fence_ibmblade is an I/O Fencing agent \ which can be used with IBM BladeCenter chassis. It issues SNMP Set \ request to BladeCenter chassis, rebooting, powering up or down \ the specified Blade Server." docs["vendorurl"] = "http://www.ibm.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/ifmib/fence_ifmib.py b/fence/agents/ifmib/fence_ifmib.py index fc96fb3a..170134e8 100644 --- a/fence/agents/ifmib/fence_ifmib.py +++ b/fence/agents/ifmib/fence_ifmib.py @@ -1,131 +1,129 @@ #!/usr/bin/python # The Following agent has been tested on: # - Cisco MDS UROS 9134 FC (1 Slot) Chassis ("1/2/4 10 Gbps FC/Supervisor-2") Motorola, e500v2 # with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c) # - Cisco MDS 9124 (1 Slot) Chassis ("1/2/4 Gbps FC/Supervisor-2") Motorola, e500 # with BIOS 1.0.16, kickstart 4.1(1c), system 4.1(1c) # - Partially with APC PDU (Network Management Card AOS v2.7.0, Rack PDU APP v2.7.3) # Only lance if is visible import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="IF:MIB SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # IF-MIB trees for alias, status and port ALIASES_OID = ".1.3.6.1.2.1.31.1.1.1.18" PORTS_OID = ".1.3.6.1.2.1.2.2.1.2" STATUSES_OID = ".1.3.6.1.2.1.2.2.1.7" # Status constants returned as value from SNMP STATUS_UP = 1 STATUS_DOWN = 2 STATUS_TESTING = 3 ### GLOBAL VARIABLES ### # Port number converted from port name or index port_num = None ### FUNCTIONS ### # Convert port index or name to port index def port2index(conn, port): res = None if (port.isdigit()): res = int(port) else: ports = conn.walk(PORTS_OID, 30) for x in ports: if (x[1].strip('"')==port): res = int(x[0].split('.')[-1]) break if (res==None): fail_usage("Can't find port with name %s!"%(port)) return res def get_power_status(conn, options): global port_num if (port_num==None): port_num = port2index(conn, options["-n"]) (oid, status) = conn.get("%s.%d"%(STATUSES_OID, port_num)) return (status==str(STATUS_UP) and "on" or "off") def set_power_status(conn, options): global port_num if (port_num==None): port_num = port2index(conn, options["-n"]) conn.set("%s.%d"%(STATUSES_OID, port_num), (options["-o"]=="on" and STATUS_UP or STATUS_DOWN)) # Convert array of format [[key1, value1], [key2, value2], ... [keyN, valueN]] to dict, where key is # in format a.b.c.d...z and returned dict has key only z def array_to_dict(ar): return dict(map(lambda y:[y[0].split('.')[-1], y[1]], ar)) def get_outlets_status(conn, options): result = {} res_fc = conn.walk(PORTS_OID, 30) res_aliases = array_to_dict(conn.walk(ALIASES_OID, 30)) for x in res_fc: port_num = x[0].split('.')[-1] port_name = x[1].strip('"') port_alias = (res_aliases.has_key(port_num) and res_aliases[port_num].strip('"') or "") port_status = "" result[port_name] = (port_alias, port_status) return result # Main agent method def main(): - global port_oid - device_opt = [ "fabric_fencing", "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () all_opt["snmp_version"]["default"] = "2c" options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for IF MIB" docs["longdesc"] = "fence_ifmib is an I/O Fencing agent \ which can be used with any SNMP IF-MIB capable device. \ \n.P\n\ It was written with managed ethernet switches in mind, in order to \ fence iSCSI SAN connections. However, there are many devices that \ support the IF-MIB interface. The agent uses IF-MIB::ifAdminStatus \ to control the state of an interface." docs["vendorurl"] = "http://www.ietf.org/wg/concluded/ifmib.html" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/intelmodular/fence_intelmodular.py b/fence/agents/intelmodular/fence_intelmodular.py index 32d8449e..3fd98220 100644 --- a/fence/agents/intelmodular/fence_intelmodular.py +++ b/fence/agents/intelmodular/fence_intelmodular.py @@ -1,97 +1,95 @@ #!/usr/bin/python # Tested with an Intel MFSYS25 using firmware package 2.6 Should work with an # MFSYS35 as well. # # Notes: # # The manual and firmware release notes says SNMP is read only. This is not # true, as per the MIBs that ship with the firmware you can write to # the bladePowerLed oid to control the servers. # # Thanks Matthew Kent for original agent and testing. import sys sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="Intel Modular SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # From INTELCORPORATION-MULTI-FLEX-SERVER-BLADES-MIB.my that ships with # firmware updates STATUSES_OID = ".1.3.6.1.4.1.343.2.19.1.2.10.202.1.1.6" # Status constants returned as value from SNMP STATUS_UP = 2 STATUS_DOWN = 0 # Status constants to set as value to SNMP STATUS_SET_ON = 2 STATUS_SET_OFF = 3 ### FUNCTIONS ### def get_power_status(conn, options): (oid, status) = conn.get("%s.%s"% (STATUSES_OID, options["-n"])) return (status==str(STATUS_UP) and "on" or "off") def set_power_status(conn, options): conn.set("%s.%s"%(STATUSES_OID, options["-n"]), (options["-o"]=="on" and STATUS_SET_ON or STATUS_SET_OFF)) def get_outlets_status(conn, options): result = {} res_blades = conn.walk(STATUSES_OID, 30) for x in res_blades: port_num = x[0].split('.')[-1] port_alias = "" port_status = (x[1]==str(STATUS_UP) and "on" or "off") result[port_num] = (port_alias, port_status) return result # Main agent method def main(): - global port_oid - device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for Intel Modular" docs["longdesc"] = "fence_intelmodular is an I/O Fencing agent \ which can be used with Intel Modular device (tested on Intel MFSYS25, should \ work with MFSYS35 as well). \ \n.P\n\ Note: Since firmware update version 2.7, SNMP v2 write support is \ removed, and replaced by SNMP v3 support. So agent now has default \ SNMP version 3. If you are using older firmware, please supply -d \ for command line and snmp_version option for your cluster.conf." docs["vendorurl"] = "http://www.intel.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/ipdu/fence_ipdu.py b/fence/agents/ipdu/fence_ipdu.py index 354a0370..da7f1920 100644 --- a/fence/agents/ipdu/fence_ipdu.py +++ b/fence/agents/ipdu/fence_ipdu.py @@ -1,164 +1,158 @@ #!/usr/bin/python # The Following agent has been tested on: # IBM iPDU model 46M4002 # Firmware release OPDP_sIBM_v01.2_1 # import sys sys.path.append("/usr/share/fence") from fencing import * from fencing_snmp import * #BEGIN_VERSION_GENERATION RELEASE_VERSION="IBM iPDU SNMP fence agent" REDHAT_COPYRIGHT="" BUILD_DATE="" #END_VERSION_GENERATION ### CONSTANTS ### # oid defining fence device OID_SYS_OBJECT_ID = '.1.3.6.1.2.1.1.2.0' ### GLOBAL VARIABLES ### # Device - see IBM iPDU device = None # Port ID port_id = None # Switch ID switch_id = None # Classes describing Device params class IBMiPDU: # iPDU status_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.11.%d' control_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.11.%d' outlet_table_oid = '.1.3.6.1.4.1.2.6.223.8.2.2.1.2' ident_str = "IBM iPDU" state_on = 1 state_off = 0 turn_on = 1 turn_off = 0 has_switches = False ### FUNCTIONS ### def ipdu_set_device(conn, options): global device agents_dir = {'.1.3.6.1.4.1.2.6.223':IBMiPDU, None:IBMiPDU} # First resolve type of PDU device pdu_type = conn.walk(OID_SYS_OBJECT_ID) if (not ((len(pdu_type)==1) and (agents_dir.has_key(pdu_type[0][1])))): pdu_type = [[None, None]] device = agents_dir[pdu_type[0][1]] conn.log_command("Trying %s"%(device.ident_str)) def ipdu_resolv_port_id(conn, options): - global port_id, switch_id, device + global port_id, switch_id if (device==None): ipdu_set_device(conn, options) # 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"]) if (device.has_switches): switch_id = int(options["-s"]) else: table = conn.walk(device.outlet_table_oid, 30) for x in table: if (x[1].strip('"')==options["-n"]): t = x[0].split('.') if (device.has_switches): port_id = int(t[len(t)-1]) switch_id = int(t[len(t)-3]) else: port_id = int(t[len(t)-1]) if (port_id==None): fail_usage("Can't find port with name %s!"%(options["-n"])) def get_power_status(conn, options): - global port_id, switch_id, device - if (port_id==None): ipdu_resolv_port_id(conn, options) 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") def set_power_status(conn, options): - global port_id, switch_id, device - if (port_id==None): ipdu_resolv_port_id(conn, options) 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)) def get_outlets_status(conn, options): - global device - result = {} - if (device==None): + if (device == None): ipdu_set_device(conn, options) res_ports = conn.walk(device.outlet_table_oid, 30) for x in res_ports: t = x[0].split('.') port_num = ((device.has_switches) and "%s:%s"%(t[len(t)-3], t[len(t)-1]) or "%s"%(t[len(t)-1])) port_name = x[1].strip('"') port_status = "" result[port_num] = (port_name, port_status) return result # Main agent method def main(): device_opt = [ "ipaddr", "login", "passwd", "passwd_script", "test", "port", "separator", "no_login", "no_password", "snmp_version", "community", "snmp_auth_prot", "snmp_sec_level", "snmp_priv_prot", "snmp_priv_passwd", "snmp_priv_passwd_script", "udpport", "inet4_only", "inet6_only" ] atexit.register(atexit_handler) snmp_define_defaults () all_opt["snmp_version"]["default"] = "3" all_opt["community"]["default"] = "private" all_opt["switch"]["default"] = "1" device = IBMiPDU options = check_input(device_opt, process_input(device_opt)) docs = { } docs["shortdesc"] = "Fence agent for iPDU over SNMP" docs["longdesc"] = "fence_ipdu is an I/O Fencing agent \ which can be used with the IBM iPDU network power switch. It logs \ into a device via SNMP and reboots a specified outlet. It supports \ SNMP v3 with all combinations of authenticity/privacy settings." docs["vendorurl"] = "http://www.ibm.com" show_docs(options, docs) # Operate the fencing device result = fence_action(FencingSnmp(options), options, set_power_status, get_power_status, get_outlets_status) sys.exit(result) if __name__ == "__main__": main() diff --git a/fence/agents/lib/fencing.py.py b/fence/agents/lib/fencing.py.py index ea0ca09a..af216962 100644 --- a/fence/agents/lib/fencing.py.py +++ b/fence/agents/lib/fencing.py.py @@ -1,983 +1,977 @@ #!/usr/bin/python import sys, getopt, time, os -import pexpect, re -import telnetlib -import atexit +import pexpect, re, atexit import __main__ ## do not add code here. #BEGIN_VERSION_GENERATION RELEASE_VERSION = "New fence lib agent - test release on steroids" REDHAT_COPYRIGHT = "" BUILD_DATE = "March, 2008" #END_VERSION_GENERATION LOG_MODE_VERBOSE = 100 LOG_MODE_QUIET = 0 EC_GENERIC_ERROR = 1 EC_BAD_ARGS = 2 EC_LOGIN_DENIED = 3 EC_CONNECTION_LOST = 4 EC_TIMED_OUT = 5 EC_WAITING_ON = 6 EC_WAITING_OFF = 7 EC_STATUS = 8 EC_STATUS_HMC = 9 EC_PASSWORD_MISSING = 10 TELNET_PATH = "/usr/bin/telnet" SSH_PATH = "/usr/bin/ssh" SSL_PATH = "@SBINDIR@/fence_nss_wrapper" SUDO_PATH = "/usr/bin/sudo" all_opt = { "help" : { "getopt" : "h", "longopt" : "help", "help" : "-h, --help Display this help and exit", "required" : "0", "shortdesc" : "Display help and exit", "order" : 54 }, "version" : { "getopt" : "V", "longopt" : "version", "help" : "-V, --version Output version information and exit", "required" : "0", "shortdesc" : "Display version information and exit", "order" : 53 }, "quiet" : { "getopt" : "q", "help" : "", "order" : 50 }, "verbose" : { "getopt" : "v", "longopt" : "verbose", "help" : "-v, --verbose Verbose mode", "required" : "0", "shortdesc" : "Verbose mode", "order" : 51 }, "debug" : { "getopt" : "D:", "longopt" : "debug-file", "help" : "-D, --debug-file= Debugging to output file", "required" : "0", "shortdesc" : "Write debug information to given file", "order" : 52 }, "delay" : { "getopt" : "f:", "longopt" : "delay", "help" : "--delay Wait X seconds before fencing is started", "required" : "0", "shortdesc" : "Wait X seconds before fencing is started", "default" : "0", "order" : 200 }, "agent" : { "getopt" : "", "help" : "", "order" : 1 }, "web" : { "getopt" : "", "help" : "", "order" : 1 }, "action" : { "getopt" : "o:", "longopt" : "action", "help" : "-o, --action= Action: status, reboot (default), off or on", "required" : "1", "shortdesc" : "Fencing Action", "default" : "reboot", "order" : 1 }, "fabric_fencing" : { "getopt" : "", "help" : "", "order" : 1 }, "ipaddr" : { "getopt" : "a:", "longopt" : "ip", "help" : "-a, --ip= IP address or hostname of fencing device", "required" : "1", "shortdesc" : "IP Address or Hostname", "order" : 1 }, "ipport" : { "getopt" : "u:", "longopt" : "ipport", "help" : "-u, --ipport= TCP port to use", "required" : "0", "shortdesc" : "TCP port to use for connection with device", "order" : 1 }, "login" : { "getopt" : "l:", "longopt" : "username", "help" : "-l, --username= Login name", "required" : "?", "shortdesc" : "Login Name", "order" : 1 }, "no_login" : { "getopt" : "", "help" : "", "order" : 1 }, "no_password" : { "getopt" : "", "help" : "", "order" : 1 }, "passwd" : { "getopt" : "p:", "longopt" : "password", "help" : "-p, --password= Login password or passphrase", "required" : "0", "shortdesc" : "Login password or passphrase", "order" : 1 }, "passwd_script" : { "getopt" : "S:", "longopt" : "password-script=", "help" : "-S, --password-script=