summaryrefslogtreecommitdiffstats
path: root/agents/wti
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:50:17 +0000
commit86ed03f8adee56c050c73018537371c230a664a6 (patch)
treeeae3d04cdf1c49848e5a671327ab38297f4acb0d /agents/wti
parentInitial commit. (diff)
downloadfence-agents-86ed03f8adee56c050c73018537371c230a664a6.tar.xz
fence-agents-86ed03f8adee56c050c73018537371c230a664a6.zip
Adding upstream version 4.12.1.upstream/4.12.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'agents/wti')
-rw-r--r--agents/wti/fence_wti.py240
1 files changed, 240 insertions, 0 deletions
diff --git a/agents/wti/fence_wti.py b/agents/wti/fence_wti.py
new file mode 100644
index 0000000..97cc66d
--- /dev/null
+++ b/agents/wti/fence_wti.py
@@ -0,0 +1,240 @@
+#!@PYTHON@ -tt
+
+#####
+##
+## The Following Agent Has Been Tested On:
+##
+## Version Firmware
+## +-----------------+---------------------------+
+## WTI RSM-8R4 ?? unable to find out ??
+## WTI MPC-??? ?? unable to find out ??
+## WTI IPS-800-CE v1.40h (no username) ('list' tested)
+#####
+
+import sys, re, pexpect
+import atexit
+import time
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fspawn, fail, fail_usage, EC_LOGIN_DENIED
+
+def get_listing(conn, options, listing_command):
+ listing = ""
+
+ conn.send_eol(listing_command)
+
+ if isinstance(options["--command-prompt"], list):
+ re_all = list(options["--command-prompt"])
+ else:
+ re_all = [options["--command-prompt"]]
+ re_next = re.compile("Enter: ", re.IGNORECASE)
+ re_all.append(re_next)
+
+ result = conn.log_expect(re_all, int(options["--shell-timeout"]))
+ listing = conn.before
+ if result == (len(re_all) - 1):
+ conn.send_eol("")
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ listing += conn.before
+
+ return listing
+
+def get_plug_status(conn, options):
+ listing = get_listing(conn, options, "/S")
+
+ plug_section = 0
+ plug_index = -1
+ name_index = -1
+ status_index = -1
+ plug_header = list()
+ outlets = {}
+
+ for line in listing.splitlines():
+ if (plug_section == 2) and line.find("|") >= 0 and line.startswith("PLUG") == False:
+ plug_line = [x.strip().lower() for x in line.split("|")]
+ if len(plug_line) < len(plug_header):
+ plug_section = -1
+ if ["list", "monitor"].count(options["--action"]) == 0 and \
+ options["--plug"].lower() == plug_line[plug_index]:
+ return plug_line[status_index]
+ else:
+ ## We already believe that first column contains plug number
+ if len(plug_line[0]) != 0:
+ outlets[plug_line[0]] = (plug_line[name_index], plug_line[status_index])
+ elif plug_section == 1:
+ plug_section = 2
+ elif line.upper().startswith("PLUG"):
+ plug_section = 1
+ plug_header = [x.strip().lower() for x in line.split("|")]
+ plug_index = plug_header.index("plug")
+ name_index = plug_header.index("name")
+ status_index = plug_header.index("status")
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ return outlets
+ else:
+ return "PROBLEM"
+
+def get_plug_group_status_from_list(status_list):
+ for status in status_list:
+ if status == "on":
+ return status
+ return "off"
+
+def get_plug_group_status(conn, options):
+ listing = get_listing(conn, options, "/SG")
+
+ outlets = {}
+ line_index = 0
+ status_index = -1
+ plug_index = -1
+ name_index = -1
+
+ lines = listing.splitlines()
+ while line_index < len(lines) and line_index >= 0:
+ line = lines[line_index]
+ if line.find("|") >= 0 and line.lstrip().startswith("GROUP NAME") == False:
+ plug_line = [x.strip().lower() for x in line.split("|")]
+ if ["list", "monitor"].count(options["--action"]) == 0 and \
+ options["--plug"].lower() == plug_line[name_index]:
+ plug_status = []
+ while line_index < len(lines) and line_index >= 0:
+ plug_line = [x.strip().lower() for x in lines[line_index].split("|")]
+ if len(plug_line) >= max(name_index, status_index) and \
+ len(plug_line[plug_index]) > 0 and \
+ (len(plug_line[name_index]) == 0 or options["--plug"].lower() == plug_line[name_index]):
+ ## Firmware 1.43 does not have a valid value of plug on first line as only name is defined on that line
+ if not "---" in plug_line[status_index]:
+ plug_status.append(plug_line[status_index])
+ line_index += 1
+ else:
+ line_index = -1
+
+ return get_plug_group_status_from_list(plug_status)
+
+ else:
+ ## We already believe that first column contains plug number
+ if len(plug_line[0]) != 0:
+ group_name = plug_line[0]
+ plug_line_index = line_index + 1
+ plug_status = []
+ while plug_line_index < len(lines) and plug_line_index >= 0:
+ plug_line = [x.strip().lower() for x in lines[plug_line_index].split("|")]
+ if len(plug_line[name_index]) > 0:
+ plug_line_index = -1
+ break
+ if len(plug_line[plug_index]) > 0:
+ plug_status.append(plug_line[status_index])
+ plug_line_index += 1
+ else:
+ plug_line_index = -1
+ outlets[group_name] = (group_name, get_plug_group_status_from_list(plug_status))
+ line_index += 1
+
+ elif line.upper().lstrip().startswith("GROUP NAME"):
+ plug_header = [x.strip().lower() for x in line.split("|")]
+ name_index = plug_header.index("group name")
+ plug_index = plug_header.index("plug")
+ status_index = plug_header.index("status")
+ line_index += 2
+ else:
+ line_index += 1
+
+
+ if ["list", "monitor"].count(options["--action"]) == 1:
+ results = {}
+ for group, status in list(outlets.items()):
+ results[group] = (group, status[0])
+
+ return results
+ else:
+ return "PROBLEM"
+
+def get_power_status(conn, options):
+ if ["list"].count(options["--action"]) == 0:
+ ret = get_plug_status(conn, options)
+
+ if ret == "PROBLEM":
+ ret = get_plug_group_status(conn, options)
+ else:
+ ret = dict(list(get_plug_status(conn, options).items()) + \
+ list(get_plug_group_status(conn, options).items()))
+
+ return ret
+
+def set_power_status(conn, options):
+ action = {
+ 'on' : "/on",
+ 'off': "/off"
+ }[options["--action"]]
+
+ conn.send_eol(action + " " + options["--plug"] + ",y")
+ conn.log_expect(options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+ device_opt = ["ipaddr", "login", "passwd", "no_login", "no_password", \
+ "cmd_prompt", "secure", "port", "telnet"]
+
+ atexit.register(atexit_handler)
+
+ all_opt["cmd_prompt"]["default"] = ["RSM>", "MPC>", "IPS>", "TPS>", "NBB>", "NPS>", "VMR>"]
+ all_opt["login_timeout"]["default"] = "10"
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for WTI"
+ docs["longdesc"] = "fence_wti is an I/O Fencing agent \
+which can be used with the WTI Network Power Switch (NPS). It logs \
+into an NPS via telnet or ssh and boots a specified plug. \
+Lengthy telnet connections to the NPS should be avoided while a GFS cluster \
+is running because the connection will block any necessary fencing actions."
+ docs["vendorurl"] = "http://www.wti.com"
+ show_docs(options, docs)
+
+ ##
+ ## Operate the fencing device
+ ##
+ ## @note: if it possible that this device does not need either login, password or both of them
+ #####
+ if "--ssh" not in options:
+ try:
+ if options["--action"] in ["off", "reboot"]:
+ time.sleep(int(options["--delay"]))
+
+ options["eol"] = "\r\n"
+
+ conn = fspawn(options, options["--telnet-path"])
+ conn.send("set binary\n")
+ conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"]))
+
+ re_login = re.compile("(login: )|(Login Name: )|(username: )|(User Name :)", re.IGNORECASE)
+ re_prompt = re.compile("|".join(["(" + x + ")" for x in options["--command-prompt"]]), re.IGNORECASE)
+
+ result = conn.log_expect([re_login, "Password: ", re_prompt], int(options["--shell-timeout"]))
+ if result == 0:
+ if "--username" in options:
+ conn.send_eol(options["--username"])
+ result = conn.log_expect([re_login, "Password: ", re_prompt], int(options["--shell-timeout"]))
+ else:
+ fail_usage("Failed: You have to set login name")
+
+ if result == 1:
+ if "--password" in options:
+ conn.send_eol(options["--password"])
+ conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"]))
+ else:
+ fail_usage("Failed: You have to enter password or password script")
+ except pexpect.EOF:
+ fail(EC_LOGIN_DENIED)
+ except pexpect.TIMEOUT:
+ fail(EC_LOGIN_DENIED)
+ else:
+ conn = fence_login(options)
+
+ result = fence_action(conn, options, set_power_status, get_power_status, get_power_status)
+ fence_logout(conn, "/X")
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()