diff options
Diffstat (limited to '')
-rw-r--r-- | agents/cdu/fence_cdu.py | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/agents/cdu/fence_cdu.py b/agents/cdu/fence_cdu.py new file mode 100644 index 0000000..483ac51 --- /dev/null +++ b/agents/cdu/fence_cdu.py @@ -0,0 +1,176 @@ +#!@PYTHON@ -tt +# fence_cdu - fence agent for a Sentry Switch CDU. +# +# Copyright (C) 2012 Canonical Ltd. +# Copyright (C) 2021 SUSE Linux GmbH <trenn@suse.de> +# +# Authors: Andres Rodriguez <andres.rodriguez@canonical.com> +# Thomas Renninger <trenn@suse.de> +# +# 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 <http://www.gnu.org/licenses/>. + +##### +## +## The Following Agent Has Been Tested On: +## +## Model Firmware +## +---------------------------------------------+ +## Sentry Switched CDU 6a +## Sentry Switched CDU 7.1c <trenn@suse.de> +## Sentry Switched CDU 7.1f <trenn@suse.de> +## Sentry Switched PDU 8.0i <trenn@suse.de> +## +## +##### + +import sys, re, pexpect, atexit, logging +sys.path.append("@FENCEAGENTSLIBDIR@") +from fencing import * +from fencing import fail, EC_TIMED_OUT, run_command, frun, EC_STATUS + +def get_power_status(conn, options): + exp_result = 0 + outlets = {} + try: + 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") + 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: + 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('(\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" ] + + atexit.register(atexit_handler) + + options = check_input(device_opt, process_input(device_opt)) + + ## + ## Fence agent specific defaults + ##### + 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) + (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() |