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/