Hello Dejan,

Thanks for your feedback !

Sure it works : 
Due to some stonith timing errors I made the two
test servers happily stonith'ted each other for 
hours =8:)
It should be emphasized that the netio firmware
has to be (at least ?) V 2.33; I had to upgrade
both of my new netios first. 

It does not make sense to use more than one port 
of a netio device for a single node if you have
redundant power supplies in a box, since this would
remove redundancy. Each port is fed through the
netio's power connector ! To keep redundancy, use
two netios on different phases....

$DBG is a remainder from standalone testing -
feel free to remove it.

For the sake of readability, I didn't ran the 
"make-an-expert-looking-perl-script-from-boring-straight-source"
filter on the code, hence the somewhat explicit names of variables.

Cheers,
Martin 

On Mon, 21 Mar 2011 14:39:57 +0100
Dejan Muhamedagic <[email protected]> wrote:

> Hi,
> 
> On Mon, Mar 21, 2011 at 11:34:42AM +0100, Martin Dziobek wrote:
> > Hello all,
> > 
> > It is time to give back - I would like to submit a stonith plugin written 
> > in perl 
> > for the netio230A IP Switch device for review and possible inclusion to 
> > glue.
> > 
> > See http://www.koukaam.se/showproduct.php?article_id=1504 for info about 
> > the device.
> 
> Many thanks for the contribution. A few comments below.
> 
> > Thanks,
> > Martin
> > 
> > 
> > #!/usr/bin/perl -w
> > #
> > # External STONITH module for netio-230A IP switch devices
> > #
> > # Copyright (c) 2011 Martin Dziobek (dziobek at ihr.uni-stuttgart.de)
> > # 
> > # This program is free software; you can redistribute it and/or modify
> > # it under the terms of version 2 of the GNU General Public License as
> > # published by the Free Software Foundation.
> > #
> > # This program is distributed in the hope that it would be useful, but
> > # WITHOUT ANY WARRANTY; without even the implied warranty of
> > # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> > #
> > # Further, this software is distributed without any warranty that it is
> > # free of the rightful claim of any third person regarding infringement
> > # or the like. Any license provided herein, whether implied or
> > # otherwise, applies only to this software file. Patent licenses, if
> > # any, provided herein do not apply to combinations of this program with
> > # other software, or any other product whatsoever.
> > #
> > # You should have received a copy of the GNU General Public License
> > # along with this program; if not, write the Free Software Foundation,
> > # Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
> > #
> > 
> > # This module talks to netio-230A devices via encrypted telnet interface
> > # Tested with firmware revision V 2.33
> > # Settings : All ports manual, watchdog off, port names set to names of
> > #            the machines to be switched 
> 
> What happens if more than one port is used for a single node
> (i.e. dual power supply)?
> 
> > use IO::Socket;
> > use Digest::MD5 qw(md5 md5_hex md5_base64);
> > 
> > my $EX_OK=0;
> > my $EX_FAIL=1;
> > my $EX_ERR=3;
> > 
> > # set to 1 for debugging, else 0
> > my $DBG=0;
> 
> You don't need this. Just use ha_log.sh for logging and specify
> debug as severity. For instance:
> 
>       ha_log.sh debug "..."
> 
> > # stuff from environment
> > my $deviceip = '127.0.0.1';
> > my $deviceport = 1234;
> > my $devicelogin = 'none';
> > my $devicepass = 'none';
> > 
> > # handle to netio device
> > my $remote;
> > # comm line to netio device
> > my $line='';
> > # ports on netio device
> > my @ports=();
> > 
> > my $target="none";
> > my $command="none";
> > 
> > # get command
> > $command = $ARGV[0] if ( defined $ARGV[0] );
> > 
> > # get host to handle on device
> > $target = $ARGV[1] if ( defined $ARGV[1] );
> > 
> > # get stuff from environment
> > $deviceip = $ENV{'deviceip'} if ( defined $ENV{'deviceip'} );
> > $deviceport = $ENV{'deviceport'} if ( defined $ENV{'deviceport'} );
> > $devicelogin = $ENV{'devicelogin'} if ( defined $ENV{'devicelogin'} );
> > $devicepass = $ENV{'devicepass'} if ( defined $ENV{'devicepass'} );
> 
> Why not name parameters without leading "device"?
> 
> > print STDERR "$command $target $deviceip $deviceport $devicelogin 
> > $devicepass\n" if $DBG;
> > 
> > # handle commands which need no connection to
> > # device first
> > if ( $command =~ /^getconfignames$/ ) {
> >     foreach $i ('deviceip','deviceport','devicelogin','devicepass'){
> >       print "$i\n";
> >     }
> >     exit($EX_OK);
> > } elsif ( $command =~ /^getinfo-devid$/ ) {
> >     print "netio-230A STONITH device\n";
> >     exit($EX_OK);    
> > } elsif ( $command =~ /^getinfo-devname$/ ) {
> >     print "netio-230A device\n";
> >     exit($EX_OK);    
> > } elsif ( $command =~ /^getinfo-devdescr$/ ) {
> >     print "netio-230A IP power switch device\n";
> >     exit($EX_OK);    
> > } elsif ( $command =~ /^getinfo-devurl$/ ) {
> >     print "http://www.koukaam.se/";;
> >     exit($EX_OK);
> > } elsif ( $command =~ /^getinfo-xml$/ ) {
> >     $metadata = <<END;
> > <parameters>
> > <parameter name="deviceip" unique="0" required="0">
> > <content type="string" />
> > <shortdesc lang="en">
> > deviceip
> > </shortdesc>
> > <longdesc lang="en">
> > IP of netio-230A device
> > </longdesc>
> > </parameter>
> > <parameter name="deviceport" unique="0" required="0">
> > <content type="string" />
> > <shortdesc lang="en">
> > deviceport
> > </shortdesc>
> > <longdesc lang="en">
> > Port to use on netio-230A device
> > </longdesc>
> > </parameter>
> > <parameter name="devicelogin" unique="0" required="0">
> > <content type="string" />
> > <shortdesc lang="en">
> > devicelogin 
> > </shortdesc>
> > <longdesc lang="en">
> > Username at the netio-230A device
> > </longdesc>
> > </parameter>
> > <parameter name="devicepass" unique="0" required="0">
> > <content type="string" />
> > <shortdesc lang="en">
> > devicepass
> > </shortdesc>
> > <longdesc lang="en">
> > Password at the netio-230A device
> > </longdesc>
> > </parameter>
> > </parameters>
> > END
> >     print $metadata;
> >     exit($EX_OK);
> > }
> > 
> > # connect to device
> > &connect;
> > 
> > if ( $command =~ /^status$/ ) {
> >     print STDERR "CMD status done\n" if $DBG;
> >     # if we came here without bailing out, device is ok
> >     close $remote;
> >     exit($EX_OK);
> > }    
> > 
> > # log in and get port info
> > &login;
> > 
> > # now handle commands which need a connection to the device
> > 
> > if ( $command =~ /^gethosts$/ ) {
> >     print STDERR "CMD gethosts\n" if $DBG;
> >     foreach $n (1..4){     
> >       print $ports[$n]."\n";
> >      }
> >     &bye;
> > }  
> > 
> > 
> > # switch commands
> > 
> > if ( $command =~ /^on$/ ) {
> >     print  STDERR "CMD $target on\n" if $DBG;;
> >     &switch("ON");
> > } elsif ( $command =~ /^off$/ ) {
> >     print  STDERR "CMD $target off\n" if $DBG;
> >     &switch("OFF");
> > } elsif ( $command =~ /^reset$/ ) {
> >     print  STDERR "CMD $target reset\n" if $DBG;
> >     &switch("RESET");
> > } else {
> >     print  STDERR "Command $command: not supported\n" if $DBG;
> >     $line="Command $command: not supported";
> >     &bailout;
> > }
> > 
> > # we should not end up here
> > close $remote;
> > exit($EX_OK);
> > 
> > # -----------------------------------------
> > sub connect{
> >   $remote = IO::Socket::INET->new( Proto     => "tcp",
> >                                    PeerAddr  => $deviceip,
> >                                PeerPort  => $deviceport,
> >                                  );
> >   unless ($remote) { 
> >       print  STDERR "cannot connect to daemon on $deviceip\n";
> >       exit($EX_ERR); 
> >   }
> > }  
> >   
> > sub login{
> >   
> >   $remote->autoflush(1);
> >   
> >   $line = <$remote>;
> >   my($stat,undef,$key,undef)=split(' ',$line,4);  
> >   &bailout unless ($stat == 100);
> > 
> >   my($digest)=md5_hex($devicelogin.$devicepass.$key);
> >   
> >   print $remote "clogin $devicelogin $digest\n";
> >   $line = <$remote>;
> >   &bailout unless($line=~m/^250 OK/);
> >   
> >   foreach $n (1..4){
> >     print $remote "port setup $n\n";
> >     $line = <$remote>;
> >     print  STDERR "$line" if $DBG;
> >     my($stat,$name,undef,undef,$on)=split(' ',$line,5);
> >     &bailout unless ($stat == 250);
> >     $name=~s/\"//g;
> >     $ports[$n]=$name;
> >   }
> > }
> > 
> > sub gethosts{
> >    foreach $n (1..4){     
> >     print $ports[$n]." ";
> >    }
> > }
> > 
> > sub switch{
> >     my($stat)=shift;
> >     foreach $n (1..4){     
> >        if($target eq $ports[$n]){
> >          if($stat eq 'ON'){
> >        print $remote "port $n 1\n";
> >        $line = <$remote>;
> >        &bailout unless($line=~m/^250 OK/);
> >        &bye;
> >      }elsif($stat eq 'OFF'){
> >        print $remote "port $n 0\n";
> >            $line = <$remote>;
> >        &bailout unless($line=~m/^250 OK/);
> >        &bye;
> >      }elsif($stat eq 'RESET'){
> >        print $remote "port $n 0\n";
> >            $line = <$remote>;
> >        &bailout unless($line=~m/^250 OK/);
> >            sleep 5;
> >        print $remote "port $n 1\n";
> >        $line = <$remote>;
> >        &bailout unless($line=~m/^250 OK/);
> >        &bye;                 
> >      }
> >        }
> >     }
> >     $line = "Invalid target\n";
> >     &bailout; 
> > }
> > 
> > sub bailout{
> >   # exit with error condition
> >   print  STDERR "Bailout on $deviceip Offending line: $line";
> >   close $remote;
> >   exit($EX_ERR);
> > }
> > 
> > sub bye{
> >   # exit gracefully
> >   print $remote "quit\n";
> >   $line = <$remote>;
> >   &bailout unless($line=~m/^110 BYE/);
> >   close $remote;
> >   exit($EX_OK);
> > }
> 
> Looks good. Does it work? ;-)
> 
> Cheers,
> 
> Dejan
> _______________________________________________________
> Linux-HA-Dev: [email protected]
> http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
> Home Page: http://linux-ha.org/
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to