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/

Reply via email to