diff --git a/agents/cdu/fence_cdu.py b/agents/cdu/fence_cdu.py index 2eec3649..483ac512 100644 --- a/agents/cdu/fence_cdu.py +++ b/agents/cdu/fence_cdu.py @@ -1,135 +1,176 @@ #!@PYTHON@ -tt # fence_cdu - fence agent for a Sentry Switch CDU. # # Copyright (C) 2012 Canonical Ltd. # Copyright (C) 2021 SUSE Linux GmbH # # Authors: Andres Rodriguez # Thomas Renninger # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ##### ## ## The Following Agent Has Been Tested On: ## ## Model Firmware ## +---------------------------------------------+ ## Sentry Switched CDU 6a ## Sentry Switched CDU 7.1c +## Sentry Switched CDU 7.1f +## Sentry Switched PDU 8.0i ## ## ##### -import sys, re, pexpect, atexit +import sys, re, pexpect, atexit, logging sys.path.append("@FENCEAGENTSLIBDIR@") from fencing import * -from fencing import fail, EC_TIMED_OUT, run_command, frun +from fencing import fail, EC_TIMED_OUT, run_command, frun, EC_STATUS def get_power_status(conn, options): exp_result = 0 outlets = {} try: - conn.send("STATUS\r\n") + if options["api-version"] == "8": + conn.send("STATUS ALL\r\n") + else: + conn.send("STATUS\r\n") conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) lines = conn.before.split("\n") - # .A12 TowerA_Outlet12 On Idle On - # .A12 test-01 On Idle On - show_re = re.compile('(\.\w+)\s+(\w+|\w+\W\w+)\s+(On|Off)\s+(On|Idle On|Off|Wake On)') + if options["api-version"] == "8": + # AA13 Arm-Console3 Wake On On Normal + # AA14 Master_Outlet_14 Wake On On Normal + show_re = re.compile('(\w+)\s+(\S+)\s+(On|Idle On|Off|Wake On)\s+(On|Off)') + else: + # .A12 TowerA_Outlet12 On Idle On + # .A12 test-01 On Idle On + show_re = re.compile('(\.\w+)\s+(\w+|\w+\W\w+)\s+(On|Off)\s+(On|Idle On|Off|Wake On)') for line in lines: res = show_re.search(line) if res != None: - outlets[res.group(2)] = (res.group(1), res.group(3)) + plug_id = res.group(1) + plug_name = res.group(2) + print(plug_name) + plug_state = res.group(3) + if options["api-version"] == "8": + plug_state = res.group(4) + outlets[plug_name] = (plug_id, plug_state) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) try: (_, status) = outlets[options["--plug"]] return status.lower().strip() except KeyError: fail(EC_STATUS) def set_power_status(conn, options): outlets = {} action = { 'on' : "on", 'off': "off" }[options["--action"]] try: conn.send("LIST OUTLETS\r\n") conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) lines = conn.before.split("\n") + # if options["api-version"] == "8": + # AA13 Arm-Console3 + # AA14 Master_Outlet_14 + # else: # .A12 TowerA_Outlet12 # .A12 test-01 - show_re = re.compile('(\.\w+)\s+(\w+|\w+\W\w+)\s+') + show_re = re.compile('(\S+)\s+(\w+|\w+\W\w+)\s+') for line in lines: res = show_re.search(line) if res != None: outlets[res.group(2)] = (res.group(1)) conn.send(action + " " + outlets[options["--plug"]] + "\r\n") conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) except pexpect.EOF: fail(EC_CONNECTION_LOST) except pexpect.TIMEOUT: fail(EC_TIMED_OUT) def disconnect(conn): conn.sendline("LOGOUT") conn.close() +def get_version(conn, options): + api_ver = "6" + sub = "a" + minor = "" + conn.send("VERSION\r\n") + conn.log_expect(options["--command-prompt"], int(options["--shell-timeout"])) + lines = conn.before.split("\n") + show_re = re.compile('Sentry Switched [PC]DU Version (\d)(.\d|)(\w)\r') + for line in lines: + res = show_re.search(line) + if res != None: + api_ver = res.group(1) + if res.group(2): + sub = res.group(2).lstrip(".") + minor = res.group(3) + return (api_ver, sub, minor) + def main(): - device_opt = [ "ipaddr", "login", "port", "switch", "passwd", "telnet" ] + device_opt = [ "ipaddr", "login", "port", "switch", "passwd", "telnet" ] atexit.register(atexit_handler) options = check_input(device_opt, process_input(device_opt)) ## ## Fence agent specific defaults ##### - options["--command-prompt"] = "Switched CDU:" + options["--command-prompt"] = "Switched [PC]DU: " docs = { } docs["shortdesc"] = "Fence agent for a Sentry Switch CDU over telnet" docs["longdesc"] = "fence_cdu is an I/O Fencing agent \ which can be used with the Sentry Switch CDU. It logs into the device \ via telnet and power's on/off an outlet." docs["vendorurl"] = "http://www.servertech.com" show_docs(options, docs) ## Support for --plug [switch]:[plug] notation that was used before opt_n = options.get("--plug") if opt_n and (-1 != opt_n.find(":")): (switch, plug) = opt_n.split(":", 1) options["--switch"] = switch; options["--plug"] = plug; ## ## Operate the fencing device #### conn = fence_login(options) - # disable output paging - conn.sendline("set option more disabled") - conn.log_expect(options["--command-prompt"], int(options["--login-timeout"])) + (api_ver, sub, minor) = get_version(conn, options) + options["api-version"] = api_ver + logging.debug("Using API version: %s" % api_ver) + if api_ver == "7": + # disable output paging + conn.sendline("set option more disabled") + conn.log_expect(options["--command-prompt"], int(options["--login-timeout"])) 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. ###### atexit.register(disconnect, conn) sys.exit(result) if __name__ == "__main__": main()