LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

LDIRECTORD: Add ssh check

To: lvs-users@xxxxxxxxxxxxxxxxxxxxxx
Subject: LDIRECTORD: Add ssh check
Cc: Roberto Nibali <rnibali@xxxxxxxxx>
Cc: J.Libak@xxxxxxxxxx
Cc: Roberto Nibali <ratz@xxxxxxxxxxxx>
From: Simon Horman <horms@xxxxxxxxxxxx>
Date: Tue, 24 Apr 2007 19:02:07 +0900
Cc: Roberto Nibali <ratz@xxxxxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>

*** Needs testing - see coments inline ***

Cc: Roberto Nibali <rnibali@xxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>

*** This needs testing - see comments inline ***

Cc: Roberto Nibali <rnibali@xxxxxxxxx>
Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
Index: heartbeat/ldirectord/ldirectord.in
===================================================================
--- heartbeat.orig/ldirectord/ldirectord.in     2007-04-24 18:21:29.000000000 
+0900
+++ heartbeat/ldirectord/ldirectord.in  2007-04-24 18:33:04.000000000 +0900
@@ -300,7 +300,7 @@ checking will take place and no real or 
 On means no checking will take place and real servers will always be
 activated. Default is I<negotiate>.
 
-B<service => 
B<dns>|B<ftp>|B<http>|B<https>|B<imap>|B<imaps>|B<ldap>|B<mysql>|B<nntp>|B<none>|B<oracle>|B<pgsql>|B<pop>|B<pops>|B<radius>|B<sip>|B<smtp>
+B<service => 
B<dns>|B<ftp>|B<http>|B<https>|B<imap>|B<imaps>|B<ldap>|B<mysql>|B<nntp>|B<none>|B<oracle>|B<pgsql>|B<pop>|B<pops>|B<radius>|B<sftp>|B<sip>|B<smtp>|B<ssh>
 
 The type of service to monitor when using checktype=negotiate. None denotes
 a service that will not be monitored. 
@@ -312,6 +312,8 @@ Default:
 
 =item * Virtual server port is 21: ftp
 
+=item * Virtual server port is 22: ssh
+
 =item * Virtual server port is 25: smtp
 
 =item * Virtual server port is 53: dns
@@ -320,6 +322,8 @@ Default:
 
 =item * Virtual server port is 110: pop
 
+=item * Virtual server port is 115: sftp
+
 =item * Virtual server port is 119: nntp
 
 =item * Virtual server port is 143: imap
@@ -374,6 +378,12 @@ For a MySQL, Oracle and PostgeSQL check,
 The data returned is not checked, only that the
 answer is one or more rows.  This is a required setting.
 
+For a SSH check this is the command to be executed after a successful
+login.
+
+For a SFTP check if this file can be fetched, so enter the full path
+to the filename on your SFTP Server.
+
 B<receive = ">I<regexp to compare>B<">
 
 If the requested result contains this I<regexp to compare>, the real server
@@ -387,6 +397,11 @@ any one of the PTR record's names.
 
 For a MySQL check, the receive setting is not used.
 
+For a SSH check, the receive string denotes the expected output of the
+request command.
+
+For the SFTP check, there is nothing to fill in here.
+
 B<httpmethod = GET>|B<HEAD>
 
 Sets the HTTP method which should be used to fetch the URI specified in
@@ -405,8 +420,8 @@ As a last resort the IP address of the r
 
 B<login = ">I<username>B<">
 
-For FTP, IMAP, LDAP, MySQL, Oracle, POP and PostgreSQL, the username
-used to log in.
+For FTP, IMAP, LDAP, MySQL, Oracle, POP, PostgreSQL, SFTP and SSH,
+the username used to log in.
 
 For Radius the passwd is used for the attribute User-Name.
 
@@ -432,7 +447,7 @@ Default:
 B<passwd = ">I<password>B<">
 
 Password to use to login to FTP, IMAP, LDAP, MySQL, Oracle, POP, PostgreSQL
-and SIP servers.
+SFTP, SIP and SSH servers.
 
 For Radius the passwd is used for the attribute User-Password.
 
@@ -1177,7 +1192,9 @@ sub read_config
                                                          $1 eq "pops"  ||
                                                          $1 eq "radius"||
                                                          $1 eq "pgsql" ||
+                                                         $1 eq "scftp" ||
                                                          $1 eq "sip"   ||
+                                                         $1 eq "ssh"   ||
                                                          $1 eq "smtp")
                                            or &config_error($line,
                                                             "service must " .
@@ -1189,7 +1206,8 @@ sub read_config
                                                             "oracle, "      .
                                                             "pop, pops, "   .
                                                             "radius, "      .
-                                                            "pgsql, sip "   .
+                                                            "pgsql, scftp " .
+                                                            "sip, ssh "     .
                                                             "or smtp");
                                        $vsrv{service} = $1;
                                        if($vsrv{service} eq "ftp" and 
@@ -1401,6 +1419,9 @@ sub _ld_read_config_virtual_resolve
                        elsif ($vsrv->{port} eq "21") {
                                $vsrv->{service} = "ftp";
                        } 
+                       elsif ($vsrv->{port} eq "22") {
+                               $vsrv->{service} = "ssh";
+                       }
                        elsif ($vsrv->{port} eq "25") {
                                $vsrv->{service} = "smtp";
                        } 
@@ -1410,6 +1431,9 @@ sub _ld_read_config_virtual_resolve
                        elsif ($vsrv->{port} eq "995") {
                                 $vsrv->{service} = "pops";
                         }
+                       elsif ($vsrv->{port} eq "115") {
+                               $vsrv->{service} = "sftp";
+                       }
                        elsif ($vsrv->{port} eq "119") {
                                $vsrv->{service} = "nntp";
                        } 
@@ -2098,6 +2122,10 @@ sub ld_main
                                                $$r{num_connects} = 0 if 
(check_smtp($v, $r));
                                        } elsif ($$v{service} eq "ftp") {
                                                $$r{num_connects} = 0 if 
(check_ftp($v, $r));
+                                       elsif ( $$v{service} eq "ssh" ) {
+                                               $$r{num_connects} = 0 if ( 
check_ssh( $v, $r ) );
+                                       } elsif ( $$v{service} eq "sftp" ) {
+                                               $$r{num_connects} = 0 if ( 
check_sftp( $v, $r ) );
                                        } elsif ($$v{service} eq "ldap") {
                                                $$r{num_connects} = 0 if 
(check_ldap($v, $r));
                                        } elsif ($$v{service} eq "nntp") {
@@ -2774,6 +2802,94 @@ sub check_ftp
 }
 
 
+sub check_ssh {
+       require Net::SSH::Perl; # Maybe Net::SSH2 would be preferrable? --ratz
+       my ( $v, $r ) = @_;
+       my $ssh;
+       my $port = ( defined $$v{checkport} ? $$v{checkport} : $$r{port} );
+       my ( $stdout, $stderr, $exit );
+
+       &ld_debug( 2, "Checking ssh server=$$r{server} port=$port" );
+
+       eval {
+               local $SIG{'__DIE__'} = "DEFAULT";
+               local $SIG{'ALRM'} = sub { die "timeout\n"; };
+               alarm( $$v{negotiatetimeout} );
+               unless ( $ssh = Net::SSH::Perl->new( $$r{server},
+                                                    port => $port ) ) {
+                       service_set( $v, $r, "down" );
+                       return 1;
+               }
+               # Why oh why are there never any return values
+               # documented in perl???
+               $ssh->login( $$v{login}, $$v{passwd} );
+               ( $stdout, $stderr, $exit ) = $ssh->cmd( $$r{request} );
+               alarm(0);
+       };
+
+       if ( @$ eq "timeout\n" ) {
+               service_set( $v, $r, "down" );
+               return 1;
+       }
+
+       # Buggy as hell, but hey, I can't even test the damn thing,
+       # because of the broken CPAN:
+       #       a) Not every correct command returns 0
+       #       b) Not every command writes to stdout
+       #
+       if ( $exit = 0 and $stdout =~ $$r{receive} ) {
+               service_set( $v, $r, "up" );
+               return 0;
+       } else {
+               service_set( $v, $r, "down" );
+               return 1;
+       }
+}
+
+sub check_sftp {
+       require Net::SFTP;
+       my ( $v, $r ) = @_;
+       my $sftp;
+       my $port = ( defined $$v{checkport} ? $$v{checkport} : $$r{port} );
+
+       &ld_debug( 2, "Checking sftp server=$$r{server} port=$port" );
+
+       eval {
+               sub get_callback {
+                       my ($sftp, $data, $offset, $size) = $@;
+                       &ld_debug(2, "Read $offset / $size bytes");
+               }
+
+               local $SIG{'__DIE__'} = "DEFAULT";
+               local $SIG{'ALRM'} = sub { die "timeout\n"; };
+               alarm( $$v{negotiatetimeout} );
+               unless ( $sftp = Net::SFTP->new( $$r{server},
+                                                login => $$v{login},
+                                                password => $$v{passwd},
+                                                ssh_args =>
+                                                       [port => $port]) ) {
+                       service_set( $v, $r, "down" );
+                       return 1;
+               }
+               alarm(0);
+       };
+
+       if ( @$ eq "timeout\n" ) {
+               service_set( $v, $r, "down" );
+               return 1;
+       }
+
+       $sftp->get( $$r{request}, \&get_callback );
+       if ( $sftp->status ) {
+               service_set( $v, $r, "up" );
+               return 0;
+       } else {
+               service_set( $v, $r, "down" );
+               return 1;
+       }
+}
+
+
 sub check_dns
 {
        my $res;

-- 

-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/


<Prev in Thread] Current Thread [Next in Thread>