summaryrefslogtreecommitdiffstats
path: root/agents/cisco_ucs
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/cisco_ucs
parentInitial commit. (diff)
downloadfence-agents-upstream/4.12.1.tar.xz
fence-agents-upstream/4.12.1.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/cisco_ucs')
-rw-r--r--agents/cisco_ucs/fence_cisco_ucs.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/agents/cisco_ucs/fence_cisco_ucs.py b/agents/cisco_ucs/fence_cisco_ucs.py
new file mode 100644
index 0000000..b85379a
--- /dev/null
+++ b/agents/cisco_ucs/fence_cisco_ucs.py
@@ -0,0 +1,198 @@
+#!@PYTHON@ -tt
+
+import sys, re
+import pycurl, io
+import logging
+import atexit
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+from fencing import fail, EC_STATUS, EC_LOGIN_DENIED, run_delay
+
+RE_COOKIE = re.compile("<aaaLogin .* outCookie=\"(.*?)\"", re.IGNORECASE)
+RE_STATUS = re.compile("<lsPower .*? state=\"(.*?)\"", re.IGNORECASE)
+RE_GET_DN = re.compile(" dn=\"(.*?)\"", re.IGNORECASE)
+RE_GET_PNDN = re.compile(" pndn=\"(.*?)\"", re.IGNORECASE)
+RE_GET_DESC = re.compile(" descr=\"(.*?)\"", re.IGNORECASE)
+RE_GET_OPERPOWER = re.compile(" operPower=\"(.*?)\"", re.IGNORECASE)
+RE_GET_PRESENCE = re.compile(" presence=\"(.*?)\"", re.IGNORECASE)
+
+options_global = None
+
+def get_power_status(conn, options):
+ del conn
+
+ res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" dn=\"org-root" + options["--suborg"] + "/ls-" +
+ options["--plug"] + "\"/>", int(options["--shell-timeout"]))
+
+ result = RE_GET_PNDN.search(res)
+ if result == None:
+ pndn = ""
+ else:
+ pndn = result.group(1)
+
+ if pndn.strip() == "":
+ if "--missing-as-off" in options:
+ return "off"
+ else:
+ fail(EC_STATUS)
+
+ res = send_command(options, "<configResolveDn cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" dn=\"" + pndn +
+ "\"/>", int(options["--shell-timeout"]))
+
+ result = RE_GET_PRESENCE.search(res)
+ if result == None:
+ fail(EC_STATUS)
+ else:
+ presence_status = result.group(1)
+
+ if presence_status in ["missing", "mismatch"]:
+ return "off"
+ else:
+ result = RE_GET_OPERPOWER.search(res)
+ if result == None:
+ fail(EC_STATUS)
+ else:
+ power_status = result.group(1)
+
+ if power_status == "on":
+ return "on"
+ else:
+ return "off"
+
+def set_power_status(conn, options):
+ del conn
+
+ action = {
+ 'on' : "admin-up",
+ 'off' : "admin-down"
+ }[options["--action"]]
+
+ send_command(options, "<configConfMos cookie=\"" + options["cookie"] + "\" inHierarchical=\"no\">" +
+ "<inConfigs><pair key=\"org-root" + options["--suborg"] + "/ls-" + options["--plug"] +
+ "/power\">" + "<lsPower dn=\"org-root/ls-" + options["--plug"] + "/power\" state=\"" +
+ action + "\" status=\"modified\" />" + "</pair></inConfigs></configConfMos>",
+ int(options["--shell-timeout"]))
+
+ return
+
+def get_list(conn, options):
+ del conn
+ outlets = {}
+
+ try:
+ res = send_command(options, "<configResolveClass cookie=\"" + options["cookie"] +
+ "\" inHierarchical=\"false\" classId=\"lsServer\"/>", int(options["--shell-timeout"]))
+
+ lines = res.split("<lsServer ")
+ for i in range(1, len(lines)):
+ node_name = RE_GET_DN.search(lines[i]).group(1)
+ desc = RE_GET_DESC.search(lines[i]).group(1)
+ outlets[node_name] = (desc, None)
+ except AttributeError:
+ return {}
+ except IndexError:
+ return {}
+
+ return outlets
+
+def send_command(opt, command, timeout):
+ ## setup correct URL
+ if "--ssl-secure" in opt or "--ssl-insecure" in opt:
+ url = "https:"
+ else:
+ url = "http:"
+
+ url += "//" + opt["--ip"] + ":" + str(opt["--ipport"]) + "/nuova"
+
+ ## send command through pycurl
+ conn = pycurl.Curl()
+ web_buffer = io.BytesIO()
+ conn.setopt(pycurl.URL, url.encode("ascii"))
+ conn.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"])
+ conn.setopt(pycurl.POSTFIELDS, command.encode("ascii"))
+ conn.setopt(pycurl.WRITEFUNCTION, web_buffer.write)
+ conn.setopt(pycurl.TIMEOUT, timeout)
+
+ if "--ssl-secure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 1)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 2)
+ elif "--ssl-insecure" in opt:
+ conn.setopt(pycurl.SSL_VERIFYPEER, 0)
+ conn.setopt(pycurl.SSL_VERIFYHOST, 0)
+
+ conn.perform()
+ result = web_buffer.getvalue().decode()
+
+ logging.debug("%s\n", command)
+ logging.debug("%s\n", result)
+
+ return result
+
+def define_new_opts():
+ all_opt["suborg"] = {
+ "getopt" : ":",
+ "longopt" : "suborg",
+ "help" : "--suborg=[path] Additional path needed to access suborganization",
+ "required" : "0",
+ "shortdesc" : "Additional path needed to access suborganization",
+ "default" : "",
+ "order" : 1}
+
+def logout():
+ ### Logout; we do not care about result as we will end in any case
+ try:
+ send_command(options_global, "<aaaLogout inCookie=\"" + options_global["cookie"] + "\" />",
+ int(options_global["--shell-timeout"]))
+ except Exception:
+ pass
+
+def main():
+ global options_global
+ device_opt = ["ipaddr", "login", "passwd", "ssl", "notls", "port", "web", "suborg", "missing_as_off"]
+
+ atexit.register(atexit_handler)
+ atexit.register(logout)
+
+ define_new_opts()
+
+ options_global = 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_global, docs)
+
+ run_delay(options_global)
+ ### Login
+ try:
+ res = send_command(options_global, "<aaaLogin inName=\"" + options_global["--username"] +
+ "\" inPassword=\"" + options_global["--password"] + "\" />", int(options_global["--login-timeout"]))
+ result = RE_COOKIE.search(res)
+ if result == None:
+ ## Cookie is absenting in response
+ fail(EC_LOGIN_DENIED)
+ except Exception as e:
+ logging.error("Failed: {}".format(str(e)))
+ fail(EC_LOGIN_DENIED)
+
+ options_global["cookie"] = result.group(1)
+
+ ##
+ ## Modify suborg to format /suborg
+ if options_global["--suborg"] != "":
+ options_global["--suborg"] = "/" + options_global["--suborg"].lstrip("/").rstrip("/")
+
+ ##
+ ## Fence operations
+ ####
+ result = fence_action(None, options_global, set_power_status, get_power_status, get_list)
+
+ ## Logout is done every time at atexit phase
+ sys.exit(result)
+
+if __name__ == "__main__":
+ main()