Blame SOURCES/bz-fence_brocade-Port-fencing-agent-to-fencing-library.patch

d67cb5
From bf77062b93a43a2ef288ca8b6e6b0a889c2993c3 Mon Sep 17 00:00:00 2001
d67cb5
From: Marek 'marx' Grac <mgrac@redhat.com>
d67cb5
Date: Thu, 29 Aug 2013 16:22:15 +0200
d67cb5
Subject: [PATCH 5/6] fence_brocade: Port fencing agent to fencing library
d67cb5
d67cb5
Resolves: rhbz#641632 rhbz#642232 rhbz#841556
d67cb5
---
d67cb5
 fence/agents/brocade/Makefile.am      |    4 +-
d67cb5
 fence/agents/brocade/fence_brocade.pl |  322 ---------------------------------
d67cb5
 fence/agents/brocade/fence_brocade.py |   86 +++++++++
d67cb5
 3 files changed, 88 insertions(+), 324 deletions(-)
d67cb5
 delete mode 100644 fence/agents/brocade/fence_brocade.pl
d67cb5
 create mode 100644 fence/agents/brocade/fence_brocade.py
d67cb5
d67cb5
diff --git a/fence/agents/brocade/Makefile.am b/fence/agents/brocade/Makefile.am
d67cb5
index 3338804..171425f 100644
d67cb5
--- a/fence/agents/brocade/Makefile.am
d67cb5
+++ b/fence/agents/brocade/Makefile.am
d67cb5
@@ -2,7 +2,7 @@ MAINTAINERCLEANFILES	= Makefile.in
d67cb5
 
d67cb5
 TARGET			= fence_brocade
d67cb5
 
d67cb5
-SRC			= $(TARGET).pl
d67cb5
+SRC			= $(TARGET).py
d67cb5
 
d67cb5
 EXTRA_DIST		= $(SRC)
d67cb5
 
d67cb5
@@ -11,7 +11,7 @@ sbin_SCRIPTS		= $(TARGET)
d67cb5
 man_MANS		= $(TARGET).8
d67cb5
 
d67cb5
 include $(top_srcdir)/make/fencebuild.mk
d67cb5
-include $(top_srcdir)/make/fencemanperl.mk
d67cb5
+include $(top_srcdir)/make/fenceman.mk
d67cb5
 
d67cb5
 clean-local: clean-man
d67cb5
 	rm -f $(TARGET)
d67cb5
diff --git a/fence/agents/brocade/fence_brocade.pl b/fence/agents/brocade/fence_brocade.pl
d67cb5
deleted file mode 100644
d67cb5
index 4be0436..0000000
d67cb5
--- a/fence/agents/brocade/fence_brocade.pl
d67cb5
+++ /dev/null
d67cb5
@@ -1,322 +0,0 @@
d67cb5
-#!/usr/bin/perl
d67cb5
-
d67cb5
-use Getopt::Std;
d67cb5
-use Net::Telnet ();
d67cb5
-
d67cb5
-my $ME = $0;
d67cb5
-
d67cb5
-END {
d67cb5
-  defined fileno STDOUT or return;
d67cb5
-  close STDOUT and return;
d67cb5
-  warn "$ME: failed to close standard output: $!\n";
d67cb5
-  $? ||= 1;
d67cb5
-}
d67cb5
-
d67cb5
-# Get the program name from $0 and strip directory names
d67cb5
-$_=$0;
d67cb5
-s/.*\///;
d67cb5
-my $pname = $_;
d67cb5
-
d67cb5
-$opt_o = 'disable';        # Default fence action
d67cb5
-
d67cb5
-# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and 
d67cb5
-# "#END_VERSION_GENERATION"  It is generated by the Makefile
d67cb5
-
d67cb5
-#BEGIN_VERSION_GENERATION
d67cb5
-$RELEASE_VERSION="";
d67cb5
-$REDHAT_COPYRIGHT="";
d67cb5
-$BUILD_DATE="";
d67cb5
-#END_VERSION_GENERATION
d67cb5
-
d67cb5
-
d67cb5
-sub usage
d67cb5
-{
d67cb5
-    print "Usage:\n";
d67cb5
-    print "\n";
d67cb5
-    print "$pname [options]\n";
d67cb5
-    print "\n";
d67cb5
-    print "Options:\n";
d67cb5
-    print "  -a <ip>          IP address or hostname of switch\n";
d67cb5
-    print "  -h               usage\n";
d67cb5
-    print "  -l <name>        Login name\n";
d67cb5
-    print "  -n <num>         Port number to operate on\n";
d67cb5
-    print "  -o <string>      Action:  disable (default), enable or metadata\n";
d67cb5
-    print "  -p <string>      Password for login\n";
d67cb5
-    print "  -S <path>        Script to run to retrieve password\n";
d67cb5
-    print "  -q               quiet mode\n";
d67cb5
-    print "  -V               version\n";
d67cb5
-
d67cb5
-    exit 0;
d67cb5
-}
d67cb5
-
d67cb5
-sub fail
d67cb5
-{
d67cb5
-  ($msg) = @_;
d67cb5
-  print $msg."\n" unless defined $opt_q;
d67cb5
-  $t->close if defined $t;
d67cb5
-  exit 1;
d67cb5
-}
d67cb5
-
d67cb5
-sub fail_usage
d67cb5
-{
d67cb5
-  ($msg)=@_;
d67cb5
-  print STDERR $msg."\n" if $msg;
d67cb5
-  print STDERR "Please use '-h' for usage.\n";
d67cb5
-  exit 1;
d67cb5
-}
d67cb5
-
d67cb5
-sub version
d67cb5
-{
d67cb5
-  print "$pname $RELEASE_VERSION $BUILD_DATE\n";
d67cb5
-  print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
d67cb5
-
d67cb5
-  exit 0;
d67cb5
-}
d67cb5
-
d67cb5
-sub print_metadata
d67cb5
-{
d67cb5
-print '
d67cb5
-<resource-agent name="fence_brocade" shortdesc="Fence agent for Brocade over telnet" >
d67cb5
-<longdesc>
d67cb5
-fence_brocade is an I/O Fencing agent which can be used with Brocade FC switches. It logs into a Brocade switch via telnet and disables a specified port. Disabling the port which a machine is connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided while a GFS cluster is running because the connection will block any necessary fencing actions.
d67cb5
-
d67cb5
-After  a fence operation has taken place the fenced machine can no longer connect to the Brocade FC switch.  When the fenced machine is ready to be brought back into the GFS cluster (after reboot) the port on the Brocade FC switch needs to be enabled. This can be done by running fence_brocade and specifying the enable action.
d67cb5
-</longdesc>
d67cb5
-<vendor-url>http://www.brocade.com</vendor-url>
d67cb5
-<parameters>
d67cb5
-        <parameter name="action" unique="0" required="1">
d67cb5
-                <getopt mixed="-o [action]" />
d67cb5
-                <content type="string" default="disable" />
d67cb5
-                <shortdesc lang="en">Fencing Action</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="ipaddr" unique="0" required="1">
d67cb5
-                <getopt mixed="-a [ip]" />
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">IP Address or Hostname</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="login" unique="0" required="1">
d67cb5
-                <getopt mixed="-l [name]" />
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">Login Name</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="passwd" unique="0" required="0">
d67cb5
-                <getopt mixed="-p [password]" />
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">Login password or passphrase</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="passwd_script" unique="0" required="0">
d67cb5
-                <getopt mixed="-S [script]" />
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">Script to retrieve password</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="port" unique="0" required="1">
d67cb5
-                <getopt mixed="-n [id]" />
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">Physical plug number or name of virtual machine</shortdesc>
d67cb5
-        </parameter>
d67cb5
-        <parameter name="help" unique="0" required="0">
d67cb5
-                <getopt mixed="-h" />           
d67cb5
-                <content type="string"  />
d67cb5
-                <shortdesc lang="en">Display help and exit</shortdesc>                    
d67cb5
-        </parameter>
d67cb5
-</parameters>
d67cb5
-<actions>
d67cb5
-        <action name="enable" />
d67cb5
-        <action name="disable" />
d67cb5
-        <action name="status" />
d67cb5
-        <action name="metadata" />
d67cb5
-</actions>
d67cb5
-</resource-agent>
d67cb5
-';
d67cb5
-}
d67cb5
-
d67cb5
-
d67cb5
-if (@ARGV > 0) {
d67cb5
-   getopts("a:hl:n:o:p:S:qV") || fail_usage ;
d67cb5
-
d67cb5
-   usage if defined $opt_h;
d67cb5
-   version if defined $opt_V;
d67cb5
-
d67cb5
-   fail_usage "Unknown parameter." if (@ARGV > 0);
d67cb5
-
d67cb5
-   if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
d67cb5
-     print_metadata();
d67cb5
-     exit 0;
d67cb5
-   }
d67cb5
-
d67cb5
-   if (defined $opt_S) {
d67cb5
-     $pwd_script_out = `$opt_S`;
d67cb5
-     chomp($pwd_script_out);
d67cb5
-     if ($pwd_script_out) {
d67cb5
-       $opt_p = $pwd_script_out;
d67cb5
-     }
d67cb5
-   }
d67cb5
-
d67cb5
-   fail_usage "No '-a' flag specified." unless defined $opt_a;
d67cb5
-   fail_usage "No '-n' flag specified." unless defined $opt_n;
d67cb5
-   fail_usage "No '-l' flag specified." unless defined $opt_l;
d67cb5
-   fail_usage "No '-p' or '-S' flag specified." unless defined $opt_p;
d67cb5
-   fail_usage "Unrecognised action '$opt_o' for '-o' flag"
d67cb5
-      unless $opt_o =~ /^(disable|enable)$/i;
d67cb5
-
d67cb5
-} else {
d67cb5
-   get_options_stdin();
d67cb5
-
d67cb5
-   if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
d67cb5
-     print_metadata();
d67cb5
-     exit 0;
d67cb5
-   }
d67cb5
-
d67cb5
-   fail "failed: no IP address" unless defined $opt_a;
d67cb5
-   fail "failed: no plug number" unless defined $opt_n;
d67cb5
-   fail "failed: no login name" unless defined $opt_l;
d67cb5
-
d67cb5
-   if (defined $opt_S) {
d67cb5
-     $pwd_script_out = `$opt_S`;
d67cb5
-     chomp($pwd_script_out);
d67cb5
-     if ($pwd_script_out) {
d67cb5
-       $opt_p = $pwd_script_out;
d67cb5
-     }
d67cb5
-   }
d67cb5
-
d67cb5
-   fail "failed: no password" unless defined $opt_p;
d67cb5
-   fail "failed: unrecognised action: $opt_o"
d67cb5
-      unless $opt_o =~ /^(disable|enable)$/i;
d67cb5
-}
d67cb5
-
d67cb5
-if ( $opt_o =~ /^(disable|enable)$/i )
d67cb5
-{
d67cb5
-  $opt_o = "port".$1;
d67cb5
-}
d67cb5
-
d67cb5
-
d67cb5
-#
d67cb5
-# Set up and log in
d67cb5
-#
d67cb5
-
d67cb5
-$t = new Net::Telnet;
d67cb5
-
d67cb5
-$t->open($opt_a);
d67cb5
-
d67cb5
-$t->waitfor('/login:/');
d67cb5
-
d67cb5
-$t->print($opt_l);
d67cb5
-
d67cb5
-$t->waitfor('/assword:/');
d67cb5
-
d67cb5
-$t->print($opt_p);
d67cb5
-
d67cb5
-$t->waitfor('/\>/');
d67cb5
-
d67cb5
-
d67cb5
-
d67cb5
-#
d67cb5
-# Do the command
d67cb5
-#
d67cb5
-
d67cb5
-$cmd = "$opt_o $opt_n";
d67cb5
-$t->print($cmd);
d67cb5
-
d67cb5
-
d67cb5
-#
d67cb5
-# Assume here that the word "error" will appear after errors (bad assumption! see next check)
d67cb5
-#
d67cb5
-
d67cb5
-($text, $match) = $t->waitfor('/\>/');
d67cb5
-if ($text =~ /error/)
d67cb5
-{
d67cb5
-  fail "failed: error from switch\n";
d67cb5
-}
d67cb5
-
d67cb5
-
d67cb5
-#
d67cb5
-# Do a portshow on the port and look for the DISABLED string to verify success
d67cb5
-#
d67cb5
-
d67cb5
-$t->print("portshow $opt_n");
d67cb5
-($text, $match) = $t->waitfor('/\>/');
d67cb5
-
d67cb5
-if ( $opt_o eq "portdisable" && !($text =~ /DISABLED/) )
d67cb5
-{
d67cb5
-  fail "failed: portshow $opt_n does not show DISABLED\n";
d67cb5
-}
d67cb5
-elsif ( $opt_o eq "portenable" && ($text =~ /DISABLED/) )
d67cb5
-{
d67cb5
-  fail "failed: portshow $opt_n shows DISABLED\n";
d67cb5
-}
d67cb5
-
d67cb5
-
d67cb5
-print "success: $opt_o $opt_n\n" unless defined $opt_q;
d67cb5
-exit 0;
d67cb5
-
d67cb5
-sub get_options_stdin
d67cb5
-{
d67cb5
-    my $opt;
d67cb5
-    my $line = 0;
d67cb5
-    while( defined($in = <>) )
d67cb5
-    {
d67cb5
-        $_ = $in;
d67cb5
-        chomp;
d67cb5
-
d67cb5
-	# strip leading and trailing whitespace
d67cb5
-        s/^\s*//;
d67cb5
-        s/\s*$//;
d67cb5
-
d67cb5
-	# skip comments
d67cb5
-        next if /^#/;
d67cb5
-
d67cb5
-        $line+=1;
d67cb5
-        $opt=$_;
d67cb5
-        next unless $opt;
d67cb5
-
d67cb5
-        ($name,$val)=split /\s*=\s*/, $opt;
d67cb5
-
d67cb5
-        if ( $name eq "" )
d67cb5
-        {  
d67cb5
-           print STDERR "parse error: illegal name in option $line\n";
d67cb5
-           exit 2;
d67cb5
-	}
d67cb5
-	
d67cb5
-        # DO NOTHING -- this field is used by fenced
d67cb5
-	elsif ($name eq "agent" ) { } 
d67cb5
-
d67cb5
-	# FIXME -- depricated.  use "port" instead.
d67cb5
-        elsif ($name eq "fm" ) 
d67cb5
-	{
d67cb5
-            (my $dummy,$opt_n) = split /\s+/,$val;
d67cb5
-	    print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
d67cb5
-	}
d67cb5
-
d67cb5
-        elsif ($name eq "ipaddr" ) 
d67cb5
-	{
d67cb5
-            $opt_a = $val;
d67cb5
-        } 
d67cb5
-	elsif ($name eq "login" ) 
d67cb5
-	{
d67cb5
-            $opt_l = $val;
d67cb5
-        } 
d67cb5
-
d67cb5
-	# FIXME -- depreicated residue of old fencing system
d67cb5
-	elsif ($name eq "name" ) { } 
d67cb5
-
d67cb5
-        elsif (($name eq "option" ) || ($name eq "action"))
d67cb5
-        {
d67cb5
-            $opt_o = $val;
d67cb5
-        }
d67cb5
-	elsif ($name eq "passwd" ) 
d67cb5
-	{
d67cb5
-            $opt_p = $val;
d67cb5
-        } 
d67cb5
-	elsif ($name eq "passwd_script") {
d67cb5
-		$opt_S = $val;
d67cb5
-	}
d67cb5
-	elsif ($name eq "port" ) 
d67cb5
-	{
d67cb5
-            $opt_n = $val;
d67cb5
-        } 
d67cb5
-	# elsif ($name eq "test" ) 
d67cb5
-	# {
d67cb5
-        #    $opt_T = $val;
d67cb5
-        # } 
d67cb5
-    }
d67cb5
-}
d67cb5
diff --git a/fence/agents/brocade/fence_brocade.py b/fence/agents/brocade/fence_brocade.py
d67cb5
new file mode 100644
d67cb5
index 0000000..25581fd
d67cb5
--- /dev/null
d67cb5
+++ b/fence/agents/brocade/fence_brocade.py
d67cb5
@@ -0,0 +1,86 @@
d67cb5
+#!/usr/bin/python
d67cb5
+
d67cb5
+import sys, re, pexpect, exceptions
d67cb5
+sys.path.append("@FENCEAGENTSLIBDIR@")
d67cb5
+from fencing import *
d67cb5
+
d67cb5
+#BEGIN_VERSION_GENERATION
d67cb5
+RELEASE_VERSION="New Brocade Agent - test release on steroids"
d67cb5
+REDHAT_COPYRIGHT=""
d67cb5
+BUILD_DATE="March, 20013"
d67cb5
+#END_VERSION_GENERATION
d67cb5
+
d67cb5
+def get_power_status(conn, options):
d67cb5
+	conn.send_eol("portCfgShow " + options["--plug"])
d67cb5
+
d67cb5
+	exp_result = conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
d67cb5
+
d67cb5
+	show_re = re.compile('^\s*Persistent Disable\s*(ON|OFF)\s*$', re.IGNORECASE)
d67cb5
+	lines = conn.before.split("\n")
d67cb5
+
d67cb5
+	for x in lines:
d67cb5
+		res = show_re.search(x)
d67cb5
+		if (res != None):
d67cb5
+			# We queried if it is disabled, so we have to negate answer
d67cb5
+			if res.group(1) == "ON":
d67cb5
+				return "off"
d67cb5
+			else:
d67cb5
+				return "on"
d67cb5
+
d67cb5
+	fail(EC_STATUS)
d67cb5
+def set_power_status(conn, options):
d67cb5
+	action = {
d67cb5
+		'on' : "portCfgPersistentEnable",
d67cb5
+		'off': "portCfgPersistentDisable"
d67cb5
+	}[options["--action"]]
d67cb5
+
d67cb5
+	conn.send_eol(action + " " + options["--plug"])
d67cb5
+	conn.log_expect(options, options["--command-prompt"], int(options["--power-timeout"]))
d67cb5
+
d67cb5
+def main():
d67cb5
+	device_opt = [  "ipaddr", "login", "passwd", "cmd_prompt", "secure", "port", "fabric_fencing" ]
d67cb5
+
d67cb5
+	atexit.register(atexit_handler)
d67cb5
+
d67cb5
+	all_opt["cmd_prompt"]["default"] = [ "> " ]
d67cb5
+
d67cb5
+	options = check_input(device_opt, process_input(device_opt))
d67cb5
+	options["eol"] = "\n"
d67cb5
+
d67cb5
+	docs = { }
d67cb5
+	docs["shortdesc"] = "Fence agent for HP Brocade over telnet/ssh"
d67cb5
+	docs["longdesc"] = "fence_brocade is an I/O Fencing agent which can be used with Brocade FC switches. \
d67cb5
+It logs into a Brocade switch via telnet and disables a specified port. Disabling the port which a machine is \
d67cb5
+connected to effectively fences that machine. Lengthy telnet connections to the switch should be avoided  while \
d67cb5
+a GFS cluster is running because the connection will block any necessary fencing actions. \
d67cb5
+\
d67cb5
+After  a fence operation has taken place the fenced machine can no longer connect to the Brocade FC switch.  \
d67cb5
+When the fenced machine is ready to be brought back into the GFS cluster (after reboot) the port on the Brocade \
d67cb5
+FC switch needs to be enabled. This can be done by running fence_brocade and specifying the enable action"
d67cb5
+	docs["vendorurl"] = "http://www.brocade.com"
d67cb5
+	show_docs(options, docs)
d67cb5
+
d67cb5
+	##
d67cb5
+	## Operate the fencing device
d67cb5
+	####
d67cb5
+	conn = fence_login(options)
d67cb5
+
d67cb5
+	result = fence_action(conn, options, set_power_status, get_power_status, None)
d67cb5
+
d67cb5
+	##
d67cb5
+	## Logout from system
d67cb5
+	##
d67cb5
+	## In some special unspecified cases it is possible that 
d67cb5
+	## connection will be closed before we run close(). This is not 
d67cb5
+	## a problem because everything is checked before.
d67cb5
+	######
d67cb5
+	try:
d67cb5
+		conn.send_eol("exit")
d67cb5
+		conn.close()
d67cb5
+	except:
d67cb5
+		pass
d67cb5
+	
d67cb5
+	sys.exit(result)
d67cb5
+
d67cb5
+if __name__ == "__main__":
d67cb5
+	main()
d67cb5
-- 
d67cb5
1.7.7.6
d67cb5