summaryrefslogtreecommitdiffstats
path: root/agents/ipmilan/fence_ipmilan.py
diff options
context:
space:
mode:
Diffstat (limited to 'agents/ipmilan/fence_ipmilan.py')
-rw-r--r--agents/ipmilan/fence_ipmilan.py233
1 files changed, 233 insertions, 0 deletions
diff --git a/agents/ipmilan/fence_ipmilan.py b/agents/ipmilan/fence_ipmilan.py
new file mode 100644
index 0000000..f751de6
--- /dev/null
+++ b/agents/ipmilan/fence_ipmilan.py
@@ -0,0 +1,233 @@
+#!@PYTHON@ -tt
+
+import sys, re, os
+import atexit
+from pipes import quote
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail_usage, is_executable, run_command, run_delay
+
+def get_power_status(_, options):
+ output = _run_command(options, "status")
+ match = re.search('[Cc]hassis [Pp]ower is [\\s]*([a-zA-Z]{2,3})', str(output))
+ status = match.group(1) if match else None
+ return status
+
+def set_power_status(_, options):
+ _run_command(options, options["--action"])
+ return
+
+def reboot_cycle(_, options):
+ output = _run_command(options, "cycle")
+ return bool(re.search('chassis power control: cycle', str(output).lower()))
+
+def reboot_diag(_, options):
+ output = _run_command(options, "diag")
+ return bool(re.search('chassis power control: diag', str(output).lower()))
+
+def _run_command(options, action):
+ cmd, log_cmd = create_command(options, action)
+ return run_command(options, cmd, log_command=log_cmd)
+
+def create_command(options, action):
+ class Cmd:
+ cmd = ""
+ log = ""
+
+ @classmethod
+ def append(cls, cmd, log=None):
+ cls.cmd += cmd
+ cls.log += (cmd if log is None else log)
+
+ # --use-sudo / -d
+ if "--use-sudo" in options:
+ Cmd.append(options["--sudo-path"] + " ")
+
+ Cmd.append(options["--ipmitool-path"])
+
+ # --lanplus / -L
+ if "--lanplus" in options and options["--lanplus"] in ["", "1"]:
+ Cmd.append(" -I lanplus")
+ else:
+ Cmd.append(" -I lan")
+
+ # --ip / -a
+ Cmd.append(" -H " + options["--ip"])
+
+ # --port / -n
+ if "--ipport" in options:
+ Cmd.append(" -p " + options["--ipport"])
+
+ # --target
+ if "--target" in options:
+ Cmd.append(" -t " + options["--target"])
+
+ # --username / -l
+ if "--username" in options and len(options["--username"]) != 0:
+ Cmd.append(" -U " + quote(options["--username"]))
+
+ # --auth / -A
+ if "--auth" in options:
+ Cmd.append(" -A " + options["--auth"])
+
+ # --password / -p
+ if "--password" in options:
+ Cmd.append(" -P " + quote(options["--password"]), " -P [set]")
+ else:
+ Cmd.append(" -P ''", " -P [set]")
+
+ # --cipher / -C
+ if "--cipher" in options:
+ Cmd.append(" -C " + options["--cipher"])
+
+ if "--privlvl" in options:
+ Cmd.append(" -L " + options["--privlvl"])
+
+ if "--hexadecimal-kg" in options:
+ Cmd.append(" -y " + options["--hexadecimal-kg"])
+
+ if "--ipmitool-timeout" in options:
+ Cmd.append(" -N " + options["--ipmitool-timeout"])
+
+ # --action / -o
+ Cmd.append(" chassis power " + action)
+
+ # --verbose-level
+ if options["--verbose-level"] > 1:
+ Cmd.append(" -" + "v" * (options["--verbose-level"] - 1))
+
+ return (Cmd.cmd, Cmd.log)
+
+def define_new_opts():
+ all_opt["lanplus"] = {
+ "getopt" : "P",
+ "longopt" : "lanplus",
+ "help" : "-P, --lanplus Use Lanplus to improve security of connection",
+ "required" : "0",
+ "default" : "0",
+ "shortdesc" : "Use Lanplus to improve security of connection",
+ "order": 1
+ }
+ all_opt["auth"] = {
+ "getopt" : "A:",
+ "longopt" : "auth",
+ "help" : "-A, --auth=[auth] IPMI Lan Auth type (md5|password|none)",
+ "required" : "0",
+ "shortdesc" : "IPMI Lan Auth type.",
+ "choices" : ["md5", "password", "none"],
+ "order": 1
+ }
+ all_opt["cipher"] = {
+ "getopt" : "C:",
+ "longopt" : "cipher",
+ "help" : "-C, --cipher=[cipher] Ciphersuite to use (same as ipmitool -C parameter)",
+ "required" : "0",
+ "shortdesc" : "Ciphersuite to use (same as ipmitool -C parameter)",
+ "order": 1
+ }
+ all_opt["privlvl"] = {
+ "getopt" : "L:",
+ "longopt" : "privlvl",
+ "help" : "-L, --privlvl=[level] "
+ "Privilege level on IPMI device (callback|user|operator|administrator)",
+ "required" : "0",
+ "shortdesc" : "Privilege level on IPMI device",
+ "default" : "administrator",
+ "choices" : ["callback", "user", "operator", "administrator"],
+ "order": 1
+ }
+ all_opt["ipmitool_path"] = {
+ "getopt" : ":",
+ "longopt" : "ipmitool-path",
+ "help" : "--ipmitool-path=[path] Path to ipmitool binary",
+ "required" : "0",
+ "shortdesc" : "Path to ipmitool binary",
+ "default" : "@IPMITOOL_PATH@",
+ "order": 200
+ }
+ all_opt["ipmitool_timeout"] = {
+ "getopt" : ":",
+ "longopt" : "ipmitool-timeout",
+ "help" : "--ipmitool-timeout=[timeout] Timeout (sec) for IPMI operation",
+ "required" : "0",
+ "shortdesc" : "Timeout (sec) for IPMI operation",
+ "default" : "2",
+ "order": 201
+ }
+ all_opt["target"] = {
+ "getopt" : ":",
+ "longopt" : "target",
+ "help" : "--target=[targetaddress] Bridge IPMI requests to the remote target address",
+ "required" : "0",
+ "shortdesc" : "Bridge IPMI requests to the remote target address",
+ "order": 1
+ }
+ all_opt["hexadecimal_kg"] = {
+ "getopt" : ":",
+ "longopt" : "hexadecimal-kg",
+ "help" : "--hexadecimal-kg=[key] Hexadecimal-encoded Kg key for IPMIv2 authentication",
+ "required" : "0",
+ "shortdesc" : "Hexadecimal-encoded Kg key for IPMIv2 authentication",
+ "order": 1
+ }
+
+def main():
+ atexit.register(atexit_handler)
+
+ device_opt = ["ipaddr", "login", "no_login", "no_password", "passwd",
+ "diag", "lanplus", "auth", "cipher", "privlvl", "sudo",
+ "ipmitool_path", "ipmitool_timeout", "method", "target", "hexadecimal_kg"]
+ define_new_opts()
+
+ all_opt["power_wait"]["default"] = 2
+ if os.path.basename(sys.argv[0]) == "fence_ilo3":
+ all_opt["power_wait"]["default"] = "4"
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ilo4":
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ilo5":
+ all_opt["lanplus"]["default"] = "1"
+ elif os.path.basename(sys.argv[0]) == "fence_ipmilanplus":
+ all_opt["lanplus"]["default"] = "1"
+
+ all_opt["ipport"]["default"] = "623"
+ all_opt["method"]["help"] = "-m, --method=[method] Method to fence (onoff|cycle) (Default: onoff)\n" \
+ "WARNING! This fence agent might report success before the node is powered off. " \
+ "You should use -m/method onoff if your fence device works correctly with that option."
+
+ options = check_input(device_opt, process_input(device_opt))
+
+ docs = {}
+ docs["shortdesc"] = "Fence agent for IPMI"
+ docs["longdesc"] = "fence_ipmilan is an I/O Fencing agent\
+which can be used with machines controlled by IPMI.\
+This agent calls support software ipmitool (http://ipmitool.sf.net/). \
+WARNING! This fence agent might report success before the node is powered off. \
+You should use -m/method onoff if your fence device works correctly with that option."
+ docs["vendorurl"] = ""
+ docs["symlink"] = [("fence_ilo3", "Fence agent for HP iLO3"),
+ ("fence_ilo4", "Fence agent for HP iLO4"),
+ ("fence_ilo5", "Fence agent for HP iLO5"),
+ ("fence_ipmilanplus", "Fence agent for IPMIv2 lanplus"),
+ ("fence_imm", "Fence agent for IBM Integrated Management Module"),
+ ("fence_idrac", "Fence agent for Dell iDRAC")]
+ show_docs(options, docs)
+
+ run_delay(options)
+
+ if not is_executable(options["--ipmitool-path"]):
+ fail_usage("Ipmitool not found or not accessible")
+
+ reboot_fn = reboot_cycle
+ if options["--action"] == "diag":
+ # Diag is a special action that can't be verified so we will reuse reboot functionality
+ # to minimize impact on generic library
+ options["--action"] = "reboot"
+ options["--method"] = "cycle"
+ reboot_fn = reboot_diag
+
+ result = fence_action(None, options, set_power_status, get_power_status, None, reboot_fn)
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()