From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marek Grac Date: Mon, 30 Sep 2013 13:18:34 +0200 Subject: [Cluster-devel] [PATCH] fence_netio: new fence-agent for the Koukaam NETIO-230B PDU In-Reply-To: <1380363332-6311-1-git-send-email-ndevos@redhat.com> References: <1380363332-6311-1-git-send-email-ndevos@redhat.com> Message-ID: <52495E0A.9010308@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hi, thanks for patch, I do not have any objections - applied to upstream m, On 09/28/2013 12:15 PM, Niels de Vos wrote: > The Koukaam NETIO-230B is a power distribution unit with four normal > (European) sockets. The device has a webui and a telnet interface. Each > socket can be given a custom name, which is returned with '-o list'. > > Link to the device, its specifications and API: > - http://www.koukaam.se/kkm/showproduct.php?article_id=1502 > > Signed-off-by: Niels de Vos > --- > .gitignore | 1 + > configure.ac | 1 + > fence/agents/netio/Makefile.am | 17 +++++ > fence/agents/netio/fence_netio.py | 119 +++++++++++++++++++++++++++++++++++++ > 4 files changed, 138 insertions(+), 0 deletions(-) > create mode 100644 fence/agents/netio/Makefile.am > create mode 100755 fence/agents/netio/fence_netio.py > > diff --git a/.gitignore b/.gitignore > index 245592f..0c19556 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -59,6 +59,7 @@ fence/agents/lib/fencing_snmp.pyc > fence/agents/lpar/fence_lpar > fence/agents/manual/fence_ack_manual > fence/agents/mcdata/fence_mcdata > +fence/agents/netio/fence_netio > fence/agents/node_assassin/fence_na > fence/agents/node_assassin/fence_na.conf > fence/agents/node_assassin/fence_na.lib > diff --git a/configure.ac b/configure.ac > index 910cab8..6f4baa0 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -276,6 +276,7 @@ AC_CONFIG_FILES([Makefile > fence/agents/lpar/Makefile > fence/agents/manual/Makefile > fence/agents/mcdata/Makefile > + fence/agents/netio/Makefile > fence/agents/nss_wrapper/Makefile > fence/agents/rackswitch/Makefile > fence/agents/ovh/Makefile > diff --git a/fence/agents/netio/Makefile.am b/fence/agents/netio/Makefile.am > new file mode 100644 > index 0000000..3e1a1d9 > --- /dev/null > +++ b/fence/agents/netio/Makefile.am > @@ -0,0 +1,17 @@ > +MAINTAINERCLEANFILES = Makefile.in > + > +TARGET = fence_netio > + > +SRC = $(TARGET).py > + > +EXTRA_DIST = $(SRC) > + > +sbin_SCRIPTS = $(TARGET) > + > +man_MANS = $(TARGET).8 > + > +include $(top_srcdir)/make/fencebuild.mk > +include $(top_srcdir)/make/fenceman.mk > + > +clean-local: clean-man > + rm -f $(TARGET) > diff --git a/fence/agents/netio/fence_netio.py b/fence/agents/netio/fence_netio.py > new file mode 100755 > index 0000000..ffb6e30 > --- /dev/null > +++ b/fence/agents/netio/fence_netio.py > @@ -0,0 +1,119 @@ > +#!/usr/bin/python > + > +import sys, re, pexpect, exceptions > +sys.path.append("@FENCEAGENTSLIBDIR@") > +from fencing import * > + > +#BEGIN_VERSION_GENERATION > +RELEASE_VERSION="" > +REDHAT_COPYRIGHT="" > +BUILD_DATE="" > +#END_VERSION_GENERATION > + > +def get_power_status(conn, options): > + conn.send_eol("port %s" % options["--plug"]) > + re_status = re.compile("250 [01imt]") > + conn.log_expect(options, re_status, int(options["--shell-timeout"])) > + status = { > + "0" : "off", > + "1" : "on", > + "i" : "reboot", > + "m" : "manual", > + "t" : "timer" > + }[conn.after.split()[1]] > + > + return status > + > +def set_power_status(conn, options): > + action = { > + "on" : "1", > + "off" : "0", > + "reboot" : "i" > + }[options["--action"]] > + > + conn.send_eol("port %s %s" % (options["--plug"], action)) > + conn.log_expect(options, "250 OK", int(options["--shell-timeout"])) > + > +def get_outlet_list(conn, options): > + result = {} > + > + try: > + # the NETIO-230B has 4 ports, counting start at 1 > + for plug in ["1", "2", "3", "4"]: > + conn.send_eol("port setup %s" % plug) > + conn.log_expect(options, "250 .+", int(options["--shell-timeout"])) > + # the name is enclosed in "", drop those with [1:-1] > + name = conn.after.split()[1][1:-1] > + result[plug] = (name, "unknown") > + except Exception, exn: > + print str(exn) > + > + return result > + > +def main(): > + device_opt = [ "ipaddr", "login", "passwd", "port" ] > + > + atexit.register(atexit_handler) > + > + opt = process_input(device_opt) > + > + # set default port for telnet only > + if 0 == opt.has_key("--ipport"): > + opt["--ipport"] = "1234" > + > + opt["eol"] = "\r\n" > + options = check_input(device_opt, opt) > + > + docs = { } > + docs["shortdesc"] = "I/O Fencing agent for Koukaam NETIO-230B" > + docs["longdesc"] = "fence_netio is an I/O Fencing agent which can be \ > +used with the Koukaam NETIO-230B Power Distribution Unit. It logs into \ > +device via telnet and reboots a specified outlet. Lengthy telnet connections \ > +should be avoided while a GFS cluster is running because the connection will \ > +block any necessary fencing actions." > + docs["vendorurl"] = "http://www.koukaam.se/" > + show_docs(options, docs) > + > + ## > + ## Operate the fencing device > + ## We can not use fence_login(), username and passwd are sent on one line > + #### > + try: > + try: > + conn = fspawn(options, TELNET_PATH) > + conn.send("set binary\n") > + conn.send("open %s -%s\n"%(options["--ip"], options["--ipport"])) > + except pexpect.ExceptionPexpect, ex: > + sys.stderr.write(str(ex) + "\n") > + sys.stderr.write("Due to limitations, binary dependencies on fence agents " > + "are not in the spec file and must be installed separately." + "\n") > + sys.exit(EC_GENERIC_ERROR) > + > + screen = conn.read_nonblocking(size=100, timeout=int(options["--shell-timeout"])) > + conn.log_expect(options, "100 HELLO .*", int(options["--shell-timeout"])) > + conn.send_eol("login %s %s" % (options["--username"], options["--password"])) > + conn.log_expect(options, "250 OK", int(options["--shell-timeout"])) > + except pexpect.EOF: > + fail(EC_LOGIN_DENIED) > + except pexpect.TIMEOUT: > + fail(EC_LOGIN_DENIED) > + result = fence_action(conn, options, set_power_status, get_power_status, get_outlet_list) > + > + ## > + ## 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. > + ###### > + try: > + conn.send("quit\n") > + conn.log_expect(options, "110 BYE", int(options["--shell-timeout"])) > + conn.close() > + except: > + pass > + > + sys.exit(result) > + > +if __name__ == "__main__": > + main()