fence-agents: master - fence_brocade: Port fencing agent to fencing library

Marek GrĂ¡c marx at fedoraproject.org
Thu Aug 29 14:23:03 UTC 2013


Gitweb:        http://git.fedorahosted.org/git/?p=fence-agents.git;a=commitdiff;h=d1baa1ba63f92a00f78ae3c344886dfbc08ca1d5
Commit:        d1baa1ba63f92a00f78ae3c344886dfbc08ca1d5
Parent:        5fa456d4075033384ea67ea3dfb257a48d981f4a
Author:        Marek 'marx' Grac <mgrac at redhat.com>
AuthorDate:    Thu Aug 29 16:22:15 2013 +0200
Committer:     Marek 'marx' Grac <mgrac at redhat.com>
CommitterDate: Thu Aug 29 16:22:15 2013 +0200

fence_brocade: Port fencing agent to fencing library

Resolves: rhbz#641632 rhbz#642232 rhbz#841556
---
 fence/agents/brocade/Makefile.am      |    4 +-
 fence/agents/brocade/fence_brocade.pl |  322 ---------------------------------
 fence/agents/brocade/fence_brocade.py |   86 +++++++++
 3 files changed, 88 insertions(+), 324 deletions(-)

diff --git a/fence/agents/brocade/Makefile.am b/fence/agents/brocade/Makefile.am
index 3338804..171425f 100644
--- a/fence/agents/brocade/Makefile.am
+++ b/fence/agents/brocade/Makefile.am
@@ -2,7 +2,7 @@ MAINTAINERCLEANFILES	= Makefile.in
 
 TARGET			= fence_brocade
 
-SRC			= $(TARGET).pl
+SRC			= $(TARGET).py
 
 EXTRA_DIST		= $(SRC)
 
@@ -11,7 +11,7 @@ sbin_SCRIPTS		= $(TARGET)
 man_MANS		= $(TARGET).8
 
 include $(top_srcdir)/make/fencebuild.mk
-include $(top_srcdir)/make/fencemanperl.mk
+include $(top_srcdir)/make/fenceman.mk
 
 clean-local: clean-man
 	rm -f $(TARGET)
diff --git a/fence/agents/brocade/fence_brocade.pl b/fence/agents/brocade/fence_brocade.pl
deleted file mode 100644
index 4be0436..0000000
--- a/fence/agents/brocade/fence_brocade.pl
+++ /dev/null
@@ -1,322 +0,0 @@
-#!/usr/bin/perl
-
-use Getopt::Std;
-use Net::Telnet ();
-
-my $ME = $0;
-
-END {
-  defined fileno STDOUT or return;
-  close STDOUT and return;
-  warn "$ME: failed to close standard output: $!\n";
-  $? ||= 1;
-}
-
-# Get the program name from $0 and strip directory names
-$_=$0;
-s/.*\///;
-my $pname = $_;
-
-$opt_o = 'disable';        # Default fence action
-
-# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and 
-# "#END_VERSION_GENERATION"  It is generated by the Makefile
-
-#BEGIN_VERSION_GENERATION
-$RELEASE_VERSION="";
-$REDHAT_COPYRIGHT="";
-$BUILD_DATE="";
-#END_VERSION_GENERATION
-
-
-sub usage
-{
-    print "Usage:\n";
-    print "\n";
-    print "$pname [options]\n";
-    print "\n";
-    print "Options:\n";
-    print "  -a <ip>          IP address or hostname of switch\n";
-    print "  -h               usage\n";
-    print "  -l <name>        Login name\n";
-    print "  -n <num>         Port number to operate on\n";
-    print "  -o <string>      Action:  disable (default), enable or metadata\n";
-    print "  -p <string>      Password for login\n";
-    print "  -S <path>        Script to run to retrieve password\n";
-    print "  -q               quiet mode\n";
-    print "  -V               version\n";
-
-    exit 0;
-}
-
-sub fail
-{
-  ($msg) = @_;
-  print $msg."\n" unless defined $opt_q;
-  $t->close if defined $t;
-  exit 1;
-}
-
-sub fail_usage
-{
-  ($msg)=@_;
-  print STDERR $msg."\n" if $msg;
-  print STDERR "Please use '-h' for usage.\n";
-  exit 1;
-}
-
-sub version
-{
-  print "$pname $RELEASE_VERSION $BUILD_DATE\n";
-  print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
-
-  exit 0;
-}
-
-sub print_metadata
-{
-print '<?xml version="1.0" ?>
-<resource-agent name="fence_brocade" shortdesc="Fence agent for Brocade over telnet" >
-<longdesc>
-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.
-
-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.
-</longdesc>
-<vendor-url>http://www.brocade.com</vendor-url>
-<parameters>
-        <parameter name="action" unique="0" required="1">
-                <getopt mixed="-o [action]" />
-                <content type="string" default="disable" />
-                <shortdesc lang="en">Fencing Action</shortdesc>
-        </parameter>
-        <parameter name="ipaddr" unique="0" required="1">
-                <getopt mixed="-a [ip]" />
-                <content type="string"  />
-                <shortdesc lang="en">IP Address or Hostname</shortdesc>
-        </parameter>
-        <parameter name="login" unique="0" required="1">
-                <getopt mixed="-l [name]" />
-                <content type="string"  />
-                <shortdesc lang="en">Login Name</shortdesc>
-        </parameter>
-        <parameter name="passwd" unique="0" required="0">
-                <getopt mixed="-p [password]" />
-                <content type="string"  />
-                <shortdesc lang="en">Login password or passphrase</shortdesc>
-        </parameter>
-        <parameter name="passwd_script" unique="0" required="0">
-                <getopt mixed="-S [script]" />
-                <content type="string"  />
-                <shortdesc lang="en">Script to retrieve password</shortdesc>
-        </parameter>
-        <parameter name="port" unique="0" required="1">
-                <getopt mixed="-n [id]" />
-                <content type="string"  />
-                <shortdesc lang="en">Physical plug number or name of virtual machine</shortdesc>
-        </parameter>
-        <parameter name="help" unique="0" required="0">
-                <getopt mixed="-h" />           
-                <content type="string"  />
-                <shortdesc lang="en">Display help and exit</shortdesc>                    
-        </parameter>
-</parameters>
-<actions>
-        <action name="enable" />
-        <action name="disable" />
-        <action name="status" />
-        <action name="metadata" />
-</actions>
-</resource-agent>
-';
-}
-
-
-if (@ARGV > 0) {
-   getopts("a:hl:n:o:p:S:qV") || fail_usage ;
-
-   usage if defined $opt_h;
-   version if defined $opt_V;
-
-   fail_usage "Unknown parameter." if (@ARGV > 0);
-
-   if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
-     print_metadata();
-     exit 0;
-   }
-
-   if (defined $opt_S) {
-     $pwd_script_out = `$opt_S`;
-     chomp($pwd_script_out);
-     if ($pwd_script_out) {
-       $opt_p = $pwd_script_out;
-     }
-   }
-
-   fail_usage "No '-a' flag specified." unless defined $opt_a;
-   fail_usage "No '-n' flag specified." unless defined $opt_n;
-   fail_usage "No '-l' flag specified." unless defined $opt_l;
-   fail_usage "No '-p' or '-S' flag specified." unless defined $opt_p;
-   fail_usage "Unrecognised action '$opt_o' for '-o' flag"
-      unless $opt_o =~ /^(disable|enable)$/i;
-
-} else {
-   get_options_stdin();
-
-   if ((defined $opt_o) && ($opt_o =~ /metadata/i)) {
-     print_metadata();
-     exit 0;
-   }
-
-   fail "failed: no IP address" unless defined $opt_a;
-   fail "failed: no plug number" unless defined $opt_n;
-   fail "failed: no login name" unless defined $opt_l;
-
-   if (defined $opt_S) {
-     $pwd_script_out = `$opt_S`;
-     chomp($pwd_script_out);
-     if ($pwd_script_out) {
-       $opt_p = $pwd_script_out;
-     }
-   }
-
-   fail "failed: no password" unless defined $opt_p;
-   fail "failed: unrecognised action: $opt_o"
-      unless $opt_o =~ /^(disable|enable)$/i;
-}
-
-if ( $opt_o =~ /^(disable|enable)$/i )
-{
-  $opt_o = "port".$1;
-}
-
-
-#
-# Set up and log in
-#
-
-$t = new Net::Telnet;
-
-$t->open($opt_a);
-
-$t->waitfor('/login:/');
-
-$t->print($opt_l);
-
-$t->waitfor('/assword:/');
-
-$t->print($opt_p);
-
-$t->waitfor('/\>/');
-
-
-
-#
-# Do the command
-#
-
-$cmd = "$opt_o $opt_n";
-$t->print($cmd);
-
-
-#
-# Assume here that the word "error" will appear after errors (bad assumption! see next check)
-#
-
-($text, $match) = $t->waitfor('/\>/');
-if ($text =~ /error/)
-{
-  fail "failed: error from switch\n";
-}
-
-
-#
-# Do a portshow on the port and look for the DISABLED string to verify success
-#
-
-$t->print("portshow $opt_n");
-($text, $match) = $t->waitfor('/\>/');
-
-if ( $opt_o eq "portdisable" && !($text =~ /DISABLED/) )
-{
-  fail "failed: portshow $opt_n does not show DISABLED\n";
-}
-elsif ( $opt_o eq "portenable" && ($text =~ /DISABLED/) )
-{
-  fail "failed: portshow $opt_n shows DISABLED\n";
-}
-
-
-print "success: $opt_o $opt_n\n" unless defined $opt_q;
-exit 0;
-
-sub get_options_stdin
-{
-    my $opt;
-    my $line = 0;
-    while( defined($in = <>) )
-    {
-        $_ = $in;
-        chomp;
-
-	# strip leading and trailing whitespace
-        s/^\s*//;
-        s/\s*$//;
-
-	# skip comments
-        next if /^#/;
-
-        $line+=1;
-        $opt=$_;
-        next unless $opt;
-
-        ($name,$val)=split /\s*=\s*/, $opt;
-
-        if ( $name eq "" )
-        {  
-           print STDERR "parse error: illegal name in option $line\n";
-           exit 2;
-	}
-	
-        # DO NOTHING -- this field is used by fenced
-	elsif ($name eq "agent" ) { } 
-
-	# FIXME -- depricated.  use "port" instead.
-        elsif ($name eq "fm" ) 
-	{
-            (my $dummy,$opt_n) = split /\s+/,$val;
-	    print STDERR "Depricated \"fm\" entry detected.  refer to man page.\n";
-	}
-
-        elsif ($name eq "ipaddr" ) 
-	{
-            $opt_a = $val;
-        } 
-	elsif ($name eq "login" ) 
-	{
-            $opt_l = $val;
-        } 
-
-	# FIXME -- depreicated residue of old fencing system
-	elsif ($name eq "name" ) { } 
-
-        elsif (($name eq "option" ) || ($name eq "action"))
-        {
-            $opt_o = $val;
-        }
-	elsif ($name eq "passwd" ) 
-	{
-            $opt_p = $val;
-        } 
-	elsif ($name eq "passwd_script") {
-		$opt_S = $val;
-	}
-	elsif ($name eq "port" ) 
-	{
-            $opt_n = $val;
-        } 
-	# elsif ($name eq "test" ) 
-	# {
-        #    $opt_T = $val;
-        # } 
-    }
-}
diff --git a/fence/agents/brocade/fence_brocade.py b/fence/agents/brocade/fence_brocade.py
new file mode 100644
index 0000000..25581fd
--- /dev/null
+++ b/fence/agents/brocade/fence_brocade.py
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+
+import sys, re, pexpect, exceptions
+sys.path.append("@FENCEAGENTSLIBDIR@")
+from fencing import *
+
+#BEGIN_VERSION_GENERATION
+RELEASE_VERSION="New Brocade Agent - test release on steroids"
+REDHAT_COPYRIGHT=""
+BUILD_DATE="March, 20013"
+#END_VERSION_GENERATION
+
+def get_power_status(conn, options):
+	conn.send_eol("portCfgShow " + options["--plug"])
+
+	exp_result = conn.log_expect(options, options["--command-prompt"], int(options["--shell-timeout"]))
+
+	show_re = re.compile('^\s*Persistent Disable\s*(ON|OFF)\s*$', re.IGNORECASE)
+	lines = conn.before.split("\n")
+
+	for x in lines:
+		res = show_re.search(x)
+		if (res != None):
+			# We queried if it is disabled, so we have to negate answer
+			if res.group(1) == "ON":
+				return "off"
+			else:
+				return "on"
+
+	fail(EC_STATUS)
+def set_power_status(conn, options):
+	action = {
+		'on' : "portCfgPersistentEnable",
+		'off': "portCfgPersistentDisable"
+	}[options["--action"]]
+
+	conn.send_eol(action + " " + options["--plug"])
+	conn.log_expect(options, options["--command-prompt"], int(options["--power-timeout"]))
+
+def main():
+	device_opt = [  "ipaddr", "login", "passwd", "cmd_prompt", "secure", "port", "fabric_fencing" ]
+
+	atexit.register(atexit_handler)
+
+	all_opt["cmd_prompt"]["default"] = [ "> " ]
+
+	options = check_input(device_opt, process_input(device_opt))
+	options["eol"] = "\n"
+
+	docs = { }
+	docs["shortdesc"] = "Fence agent for HP Brocade over telnet/ssh"
+	docs["longdesc"] = "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. \
+\
+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"
+	docs["vendorurl"] = "http://www.brocade.com"
+	show_docs(options, docs)
+
+	##
+	## Operate the fencing device
+	####
+	conn = fence_login(options)
+
+	result = fence_action(conn, options, set_power_status, get_power_status, None)
+
+	##
+	## 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_eol("exit")
+		conn.close()
+	except:
+		pass
+	
+	sys.exit(result)
+
+if __name__ == "__main__":
+	main()


More information about the cluster-commits mailing list