[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [Linux-cluster] Dell iDRAC 6 Support for fencing device



Seeing as there is already a separate script for the DRAC 5 cards with beyond 1.20 firmware, perhaps this should be there or as a separate fence_drac moule?

# file /sbin/fence_drac
/sbin/fence_drac: perl script text executable
# file /sbin/fence_drac5
/sbin/fence_drac5: python script text executable
#

I've found that the fence_drac no longer works with ver 1.34 and above firmware, but does work with 1.20 and below firmware.  Any Dell PE 1950, 2950, or R series server with a DRAC5 will have newer than 1.20 firmware though if the server was manufactured in the last year or so.

On Fri, Oct 2, 2009 at 3:10 PM, Nitin Choudhary <Nitin Choudhary palm com> wrote:
Hi!

I have pasted the modified version of fence script for Dell iDRAC6.
Thanks,
Nitin

#!/usr/bin/perl

# The following agent has been tested on:
#
#  Model                DRAC Version    Firmware
#  -------------------  --------------  ----------------------
#  PowerEdge 750        DRAC III/XT     3.20 (Build 10.25)
#  Dell Remote Access Controller - ERA and DRAC III/XT, v.3.20, A00 #
#  PowerEdge 1855       DRAC/MC         1.1  (Build 03.03)
#  PowerEdge 1855       DRAC/MC         1.2  (Build 03.03)
#  PowerEdge 1855       DRAC/MC         1.3  (Build 06.12)
#  PowerEdge 1850       DRAC 4/I        1.35 (Build 09.27)
#  PowerEdge 1850       DRAC 4/I        1.40 (Build 08.24)
#  PowerEdge 1950       DRAC 5          1.0  (Build 06.05.12)
#

use Getopt::Std;
use Net::Telnet ();

# Get the program name from $0 and strip directory names $_=$0; s/.*\///; my $pname = $_;

my $telnet_timeout = 10;      # Seconds to wait for matching telent response
my $power_timeout = 20;      # time to wait in seconds for power state changes
$action = ""          # Default fence action.

my $logged_in = 0;
my $quiet = 0;

my $t = new Net::Telnet;

my $DRAC_VERSION_UNKNOWN        = '__unknown__';
my $DRAC_VERSION_III_XT         = 'DRAC III/XT';
my $DRAC_VERSION_MC                     = 'DRAC/MC';
my $DRAC_VERSION_4I                     = 'DRAC 4/I';
my $DRAC_VERSION_4P                     = 'DRAC 4/P';
my $DRAC_VERSION_5                      = 'DRAC 5';
my $DRAC_VERSION_6                      = 'DRAC 6';

my $PWR_CMD_SUCCESS                     = "/^OK/";
my $PWR_CMD_SUCCESS_DRAC5       = "/^Server power operation successful$/";

# WARNING!! Do not add code bewteen "#BEGIN_VERSION_GENERATION" and # "#END_VERSION_GENERATION"  It is generated by the Makefile

#BEGIN_VERSION_GENERATION
$FENCE_RELEASE_NAME="2.0.115";
$REDHAT_COPYRIGHT=("Copyright (C) Red Hat, Inc.  2004  All rights reserved."); $BUILD_DATE="(built Wed Sep  2 11:45:31 EDT 2009)"; #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 DRAC\n";
       print "  -c <cmd_prompt>  force DRAC command prompt\n";
       print "  -d <dracversion> force DRAC version to use\n";
       print "  -D <debugfile>   debugging output file\n";
       print "  -h               usage\n";
       print "  -l <name>        Login name\n";
       print "  -m <modulename>  DRAC/MC module name\n";
       print "  -o <string>      Action: reboot (default), off or on\n";
       print "  -p <string>      Login password\n";
       print "  -S <path>        Script to run to retrieve password\n";
       print "  -q               quiet mode\n";
       print "  -V               version\n";
       print "\n";
       print "CCS Options:\n";
       print "  action = ""      Action: reboot (default), off or on\n";
       print "  debug  = \"debugfile\"   debugging output file\n";
       print "  ipaddr = \"ip\"          IP address or hostname of DRAC\n";
       print "  login  = \"name\"        Login name\n";
       print "  passwd = \"string\"      Login password\n";
       print "  passwd_script = \"path\" Script to run to retrieve password\n";

       exit 0;
}

sub msg
{
       ($msg)= _;
       print $msg."\n" unless $quiet;
}

sub fail
{
       ($msg)= _;
       print $msg."\n" unless $quiet;

       if (defined $t)
       {
               # make sure we don't get stuck in a loop due to errors
               $t->errmode('return');

               logout() if $logged_in;
               $t->close
       }
       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 $FENCE_RELEASE_NAME $BUILD_DATE\n";
       print "$REDHAT_COPYRIGHT\n" if ( $REDHAT_COPYRIGHT );
       exit 0;
}


sub login
{
       $t->open($address) or
               fail "failed: telnet open failed: ". $t->errmsg."\n";

       # Expect 'Login: '
       ($_) = $t->waitfor(Match => "/[Ll]ogin: /", Timeout=>15) or
               fail "failed: telnet failed: ". $t->errmsg."\n" ;

       # Determine DRAC version
 if (/Dell Embedded Remote Access Controller \(ERA\)\nFirmware Version/m)
 {
   $drac_version = $DRAC_VERSION_III_XT;
 } else {
       if (/.*\((DRAC[^)]*)\)/m)
       {
               print "detected drac version '$1'\n" if $verbose;
               $drac_version = $1 unless defined $drac_version;

               print "WARNING: detected drac version '$1' but using "
                       . "user defined version '$drac_version'\n"
                       if ($drac_version ne $1);
       }
       else
       {
               $drac_version = $DRAC_VERSION_UNKNOWN;
       }
 }

       # Setup prompt
       if ($drac_version =~ /$DRAC_VERSION_III_XT/)
       {
               $cmd_prompt = "/\\[$login\\]# /"
                       unless defined $cmd_prompt;
       }
       elsif ($drac_version =~ /$DRAC_VERSION_MC/)
       {
               $cmd_prompt = "/DRAC\\/MC:/"
                       unless defined $cmd_prompt;
       }
       elsif ($drac_version =~ /$DRAC_VERSION_4I/)
       {
               $cmd_prompt = "/\\[$login\\]# /"
                       unless defined $cmd_prompt;
       }
 elsif ($drac_version =~ /$DRAC_VERSION_4P/)
 {
       $cmd_prompt = "/\\[$login\\]# /"
         unless defined $cmd_prompt;
 }
       else
       {
               $drac_version = $DRAC_VERSION_UNKNOWN;
       }

       # Take a guess as to what the prompt might be if not already defined
       $cmd_prompt="/(\\[$login\\]# |DRAC\\/MC:|\\\$ )/" unless defined $cmd_prompt;


       # Send login
       $t->print($login);

       # Expect 'Password: '
       $t->waitfor("/Password: /") or
               fail "failed: timeout waiting for password";

       # Send password
       $t->print($passwd);

       # DRAC5 prints version controller version info
       # only after you've logged in.
       if ($drac_version eq $DRAC_VERSION_UNKNOWN) {
               if ($t->waitfor(Match => "/.*\($DRAC_VERSION_5\)/m")) {
                       $drac_version = $DRAC_VERSION_5;
                       $cmd_prompt = "/\\\$ /";
                       $PWR_CMD_SUCCESS = $PWR_CMD_SUCCESS_DRAC5;
              } elsif ($t->waitfor(Match => "/.*\(admin\)/m")) {
                       $drac_version = $DRAC_VERSION_5;
                       $cmd_prompt = '/> $/';
                       $PWR_CMD_SUCCESS = $PWR_CMD_SUCCESS_DRAC5;
               } else {
                       print "WARNING: unable to detect DRAC version '$_'\n";
               }
       }

       $t->waitfor($cmd_prompt) or
               fail "failed: invalid username or password";

       if ($drac_version eq $DRAC_VERSION_UNKNOWN) {
               print "WARNING: unsupported DRAC version '$drac_version'\n";
       }

       $logged_in = 1;
}

#
# Set the power status of the node
#
sub set_power_status
{
       my ($state,$dummy) = @_;
       my $cmd,$svr_action;

       if   ( $state =~ /^on$/)  { $svr_action = "powerup"   }
       elsif( $state =~ /^off$/) { $svr_action = "powerdown" }

       if ($drac_version eq $DRAC_VERSION_MC)
       {
               $cmd = "serveraction -m $modulename  -d 0 $svr_action";
       }
       elsif ($drac_version eq $DRAC_VERSION_5) {
               $cmd = "racadm serveraction $svr_action";
       } else
       {
               $cmd = "serveraction -d 0 $svr_action";
       }

       $t->print($cmd);

       # Expect /$cmd_prompt/
       ($_) = $t->waitfor($cmd_prompt) or
               fail "failed: unexpected serveraction response";

       my @cmd_out = split /\n/;

       # discard command sent to DRAC
       $_ = shift @cmd_out;
       s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g; #strip ansi chars
       s/^.*\x0D//;

       fail "failed: unkown dialog exception: '$_'" unless (/^$cmd$/);

       # Additional lines of output probably means an error.
       # Aborting to be safe.  Note: additional user debugging will be
       # necessary,  run with -D and -v flags
       my $err;
       while (@cmd_out)
       {
               $_ = shift @cmd_out;
               #firmware vers 1.2 on DRAC/MC sends ansi chars - evil
               s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g;
               s/^.*\x0D//;

               next if (/^\s*$/); # skip empty lines
               if (defined $err)
               {
                       $err = $err."\n$_";
               }
               else
               {
                       next if ($PWR_CMD_SUCCESS);
                       $err = $_;
               }
       }
       fail "failed: unexpected response: '$err'" if defined $err; }


#
# get the power status of the node and return it in $status and $_ # sub get_power_status {
       my $status;
       my $modname = $modulename;
       my $cmd;

       if ($drac_version eq $DRAC_VERSION_5) {
               $cmd = "racadm serveraction powerstatus";
       } else {
               $cmd = "getmodinfo";
       }

       $t->print($cmd);

       ($_) = $t->waitfor($cmd_prompt);

       my $found_header = 0;
       my $found_module = 0;

       my @cmd_out = split /\n/;

       # discard command sent to DRAC
       $_ = shift @cmd_out;
       #strip ansi control chars
       s/\e\[(([0-9]+;)*[0-9]+)*[ABCDfHJKmsu]//g;
       s/^.*\x0D//;

       fail "failed: unkown dialog exception: '$_'" unless (/^$cmd$/);

       if ($drac_version ne $DRAC_VERSION_5) {
               #Expect:
               #  #<group>     <module>    <presence>  <pwrState>  <health>  <svcTag>
               #   1  ---->     chassis    Present         ON      Normal    CQXYV61
               #
               #  Note: DRAC/MC has many entries in the table whereas DRAC III has only
               #  a single table entry.

               while (1)
               {
                       $_ = shift @cmd_out;
                       if (/^#<group>\s*<module>\s*<presence>\s*<pwrState>\s*<health>\s*<svcTag>/)
                       {
                               $found_header = 1;
                               last;
                       }
               }
               fail "failed: invalid 'getmodinfo' header: '$_'" unless $found_header;
       }

       foreach (@cmd_out)
       {
               s/^\s+//g; #strip leading space
               s/\s+$//g; #strip training space

               if ($drac_version eq $DRAC_VERSION_5) {
                       if(m/^Server power status: (\w+)/) {
                               $status = lc($1);
                       }
               } else {
                       my ($group,$arrow,$module,$presence,$pwrstate,$health,
                               $svctag,$junk) = split /\s+/;

                       if ($drac_version eq  $DRAC_VERSION_III_XT || $drac_version eq $DRAC_VERSION_4I || $drac_version eq $DRAC_VERSION_4P)
                       {
                               fail "failed: extraneous output detected from 'getmodinfo'" if $found_module;
                               $found_module = 1;
                               $modname = $module;
                       }

                       if ($modname eq $module)
                       {
                               fail "failed: duplicate module names detected" if $status;
                               $found_module = 1;

                               fail "failed: module not reported present" unless ($presence =~ /Present/);
                               $status = $pwrstate;
                       }

               }
       }

       if ($drac_version eq $DRAC_VERSION_MC)
       {
               fail "failed: module '$modulename' not detected" unless $found_module;
       }

       $_=$status;
       if(/^(on|off)$/i)
       {
               # valid power states
       }
       elsif ($status)
       {
               fail "failed: unknown power state '$status'";
       }
       else
       {
               fail "failed: unable to determine power state";
       }
}


# Wait upto $power_timeout seconds for node power state to change to # $state before erroring out.
#
# return 1 on success
# return 0 on failure
#
sub wait_power_status
{
       my ($state,$dummy) = @_;
       my $status;

       $state = lc $state;

       for (my $i=0; $i<$power_timeout ; $i++)
       {
               get_power_status;
               $status = $_;
               my $check = lc $status;

               if ($state eq $check ) { return 1 }
               sleep 1;
       }
       $_ = "timed out waiting to power $state";
       return 0;
}

#
# logout of the telnet session
#
sub logout
{
       $t->print("");
       $t->print("exit");
}

#
# error routine for Net::Telnet instance # sub telnet_error {
       fail "failed: telnet returned: ".$t->errmsg."\n"; }

#
# execute the action.  Valid actions are 'on' 'off' 'reboot' and 'status'.
# TODO: add 'configure' that uses racadm rpm to enable telnet on the drac # sub do_action {
       get_power_status;
       my $status = $_;

       if ($action =~ /^on$/i)
       {
               if ($status =~ /^on$/i)
               {
                       msg "success: already on";
                       return;
               }

               set_power_status on;
               fail "failed: $_" unless wait_power_status on;

               msg "success: powered on";
       }
       elsif ($action =~ /^off$/i)
       {
               if ($status =~ /^off$/i)
               {
                       msg "success: already off";
                       return;
               }

               set_power_status off;
               fail "failed: $_" unless wait_power_status off;

               msg "success: powered off";
       }
       elsif ($action =~ /^reboot$/i)
       {
               if ( !($status =~ /^off$/i) )
               {
                       set_power_status off;
               }
               fail "failed: $_" unless wait_power_status off;

               set_power_status on;
               fail "failed: $_" unless wait_power_status on;

               msg "success: rebooted";
       }
       elsif ($action =~ /^status$/i)
       {
               msg "status: $status";
               return;
       }
       else
       {
               fail "failed: unrecognised action: '$action'";
       }
}

#
# Decipher STDIN parameters
#
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" )
               {
               }
               elsif ($name eq "ipaddr" )
               {
                       $address = $val;
               }
               elsif ($name eq "login" )
               {
                       $login = $val;
               }
               elsif ($name eq "action" )
               {
                       $action = "">                }
               elsif ($name eq "passwd" )
               {
                       $passwd = $val;
               }
               elsif ($name eq "passwd_script" )
               {
                       $passwd_script = $val;
               }
               elsif ($name eq "debug" )
               {
                       $debug = $val;
               }
               elsif ($name eq "modulename" )
               {
                       $modulename = $val;
               }
               elsif ($name eq "drac_version" )
               {
                       $drac_version = $val;
               }
               elsif ($name eq "cmd_prompt" )
               {
                       $cmd_prompt = $val;
               }
               # Excess name/vals will fail
               else
               {
                       fail "parse error: unknown option \"$opt\"";
               }
       }
}


### MAIN #######################################################

#
# Check parameters
#
if (@ARGV > 0) {
       getopts("a:c:d:D:hl:m:o:p:S:qVv") || fail_usage ;

       usage if defined $opt_h;
       version if defined $opt_V;

       $quiet = 1 if defined $opt_q;
       $debug = $opt_D;

       fail_usage "Unknown parameter." if (@ARGV > 0);

       fail_usage "No '-a' flag specified." unless defined $opt_a;
       $address = $opt_a;

       fail_usage "No '-l' flag specified." unless defined $opt_l;
       $login = $opt_l;

       $modulename = $opt_m if defined $opt_m;

       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 '-p' or '-S' flag specified." unless defined $opt_p;
       $passwd = $opt_p;

       $verbose = $opt_v if defined $opt_v;

       $cmd_prompt = $opt_c if defined $opt_c;
       $drac_version = $opt_d if defined $opt_d;

       if ($opt_o)
       {
               fail_usage "Unrecognised action '$opt_o' for '-o' flag"
               unless $opt_o =~ /^(Off|On|Reboot|status)$/i;
               $action = "">        }

} else {
       get_options_stdin();

       fail "failed: no IP address" unless defined $address;
       fail "failed: no login name" unless defined $login;

       if (defined $passwd_script) {
               $pwd_script_out = `$passwd_script`;
               chomp($pwd_script_out);
               if ($pwd_script_out) {
                       $passwd = $pwd_script_out;
               }
       }

       fail "failed: no password" unless defined $passwd;
       fail "failed: unrecognised action: $action"
               unless $action =~ /^(Off|On|Reboot|status)$/i; }


$t->timeout($telnet_timeout);
$t->input_log($debug) if $debug;
$t->errmode('return');

login;

# Abort on failure beyond here
$t->errmode(\&telnet_error);

if ($drac_version eq $DRAC_VERSION_III_XT) {
       fail "failed: option 'modulename' not compatilble with DRAC version '$drac_version'"
               if defined $modulename;
}
elsif ($drac_version eq $DRAC_VERSION_MC) {
       fail "failed: option 'modulename' required for DRAC version '$drac_version'"
               unless  defined $modulename;
}

do_action;

logout;

exit 0;


-----Original Message-----
From: linux-cluster-bounces redhat com [mailto:linux-cluster-bounces redhat com] On Behalf Of Andrew A. Neuschwander
Sent: Wednesday, September 30, 2009 3:48 PM
To: linux clustering
Subject: Re: [Linux-cluster] Dell iDRAC 6 Support for fencing device

Could you post your modified fence_drac for iDRAC 6?

Thanks,
-A
--
Andrew A. Neuschwander, RHCE
Systems/Software Engineer
College of Forestry and Conservation
The University of Montana
http://www.ntsg.umt.edu
andrew ntsg umt edu - 406.243.6310


Nitin Choudhary wrote:
> Hi!
>
> With small modification to fence_drac script it is working now.
>
> Thanks,
>
> Nitin
>
>
> -----Original Message-----
> From: linux-cluster-bounces redhat com [mailto:linux-cluster-bounces redhat com] On Behalf Of Louis
> Sent: Tuesday, September 29, 2009 6:16 PM
> To: linux clustering
> Subject: Re: [Linux-cluster] Dell iDRAC 6 Support for fencing device
>
> Hi,
>
> I used ipmilan to bypass the iDREC6 fencing.
>
> <fencedevice agent="fence_ipmilan" ipaddr="10.10.10.10" login="xxxxx"
> name="xxxxx" passwd="yyyy">
>
>
> Regards
> Louis
> ----- Original Message -----
> From: "Nitin Choudhary" <Nitin Choudhary palm com>
> To: "linux clustering" <linux-cluster redhat com>
> Sent: Tuesday, September 29, 2009 1:18 PM
> Subject: [Linux-cluster] Dell iDRAC 6 Support for fencing device
>
>
>> Hi!
>>
>> It seems that iDREC6 is not supported as fencing devices.
>>
>> Has anyone setup this before. Is there any workaround for this.
>>
>> Thanks,
>>
>> Nitin
>>
>> --
>> Linux-cluster mailing list
>> Linux-cluster redhat com
>> https://www.redhat.com/mailman/listinfo/linux-cluster
>>
>>
>
>
> --
> Linux-cluster mailing list
> Linux-cluster redhat com
> https://www.redhat.com/mailman/listinfo/linux-cluster
>
> --
> Linux-cluster mailing list
> Linux-cluster redhat com
> https://www.redhat.com/mailman/listinfo/linux-cluster
>

--
Linux-cluster mailing list
Linux-cluster redhat com
https://www.redhat.com/mailman/listinfo/linux-cluster

--
Linux-cluster mailing list
Linux-cluster redhat com
https://www.redhat.com/mailman/listinfo/linux-cluster


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]