LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

Re: [lvs-users] ldirectord SimpleTCP service check [PATCH]

To: "LinuxVirtualServer.org users mailing list." <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: Re: [lvs-users] ldirectord SimpleTCP service check [PATCH]
From: Simon Horman <horms@xxxxxxxxxxxx>
Date: Fri, 30 Nov 2007 16:35:53 +0900
On Thu, Nov 29, 2007 at 08:41:27AM -0600, Aaron Linnen wrote:
> I have a service with a custom protocol that I'm load balancing and I 
> didn't find an easy way to get that going with ldirectord. I came up 
> with a quick modification that enabled what I needed, but would 
> appreciate comments or, ideally including similar functionality in 
> future releases.
> 
> It's a new service type called simpletcp, and is configured like so:
> virtual = 192.168.44.3:10301
>         protocol = tcp
>         scheduler = wlc
>         real = 192.168.45.4:10301 gate 100
>         real = 192.168.45.5:10301 gate 100
>         service = simpletcp
>         request = "command\narg\n.\n"
>         receive = "^\+OK"
> 
> The check simply sends the request string down the connection and tests 
> against the receive regex. My perl-foo is weak these days, so I'm sure 
> there are some easy improvements that could be made.

Hi Arron,

thanks for your patch. This idea looks like a good one to me and
I'm quite happy to push it into the next release (or the one after that,
as the next release is close to going out the door).

A few things:

* How well have you tested this? Its unlikely to break anything except
  itself, but its good to get an idea anyway.
* Can you add something to the documentation at the top of ldirectord?
  Perhaps doding this as a second patch would work well.
* Your patch seemed to replace all tabs with spaces so it didn't apply.
  I manually fixed this up and the fixed version is below.
* If at all possible could you provide a sign-off line as described
  in section 5 of http://linux.yyz.us/patch-format.html
  Thats basically to say this is your work and you are ok with
  it going into a GPL project.

-- 
Horms


Date: Thu, 29 Nov 2007 08:41:27 -0600
From: Aaron Linnen <aaron@xxxxxxxxxxxxxx>
To: "LinuxVirtualServer.org users mailing list."
        <lvs-users@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [lvs-users] ldirectord SimpleTCP service check [PATCH]

I have a service with a custom protocol that I'm load balancing and I 
didn't find an easy way to get that going with ldirectord. I came up 
with a quick modification that enabled what I needed, but would 
appreciate comments or, ideally including similar functionality in 
future releases.

It's a new service type called simpletcp, and is configured like so:
virtual = 192.168.44.3:10301
        protocol = tcp
        scheduler = wlc
        real = 192.168.45.4:10301 gate 100
        real = 192.168.45.5:10301 gate 100
        service = simpletcp
        request = "command\narg\n.\n"
        receive = "^\+OK"

The check simply sends the request string down the connection and tests 
against the receive regex. My perl-foo is weak these days, so I'm sure 
there are some easy improvements that could be made.

Aaron


Index: heartbeat/ldirectord/ldirectord.in
===================================================================
--- heartbeat.orig/ldirectord/ldirectord.in     2007-11-30 16:17:41.000000000 
+0900
+++ heartbeat/ldirectord/ldirectord.in  2007-11-30 16:26:34.000000000 +0900
@@ -1225,7 +1225,8 @@ sub read_config
                                                          $1 eq "radius"||
                                                          $1 eq "pgsql" ||
                                                          $1 eq "sip"   ||
-                                                         $1 eq "smtp")
+                                                         $1 eq "smtp"  ||
+                                                         $1 eq "simpletcp")
                                            or &config_error($line,
                                                             "service must " .
                                                             "be dns, ftp, " .
@@ -2223,6 +2224,8 @@ sub ld_main
                                                $$r{num_connects} = 0 if 
(check_pgsql($v, $r) == $SERVICE_UP);
                                        } elsif ($$v{service} eq "oracle") {
                                                $$r{num_connects} = 0 if 
(check_oracle($v, $r) == $SERVICE_UP);
+                                       } elsif ($$v{service} eq "simpletcp") {
+                                               $$r{num_connects} = 0 if 
(check_simpletcp($v, $r) == $SERVICE_UP);
                                        } else {
                                                $$r{num_connects} = 0 if 
(check_none($v, $r) == $SERVICE_UP);
                                        }
@@ -2911,6 +2914,73 @@ sub check_sip
 }
 
 
+sub check_simpletcp
+{
+       my ($v, $r) = @_;
+       my $d_port = ld_checkport($v, $r);
+
+       &ld_debug(2, "Checking simpletcp server=$$r{server} port=$d_port");
+
+       eval {
+              use Socket;
+
+              local $SIG{'__DIE__'} = "DEFAULT";
+              local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
+              &ld_debug(4, "Timeout is $$v{checktimeout}");
+              alarm $$v{negotiatetimeout};
+
+              my $sock = &ld_open_socket($$r{server}, $d_port,
+                                      $$v{protocol});
+              unless ($sock) {
+                      alarm 0;
+                      die("Socket Connect Failed");
+              }
+
+              my $s_sockaddr = getsockname($sock);
+              my ($s_port, $s_addr) = sockaddr_in($s_sockaddr);
+              my $s_addr_str = inet_ntoa($s_addr);
+
+              &ld_debug(3, "Connected from $s_addr_str:$s_port to " .
+                      $$r{server} . ":$d_port");
+
+              select $sock;
+              $|=1;
+              select STDOUT;
+
+              my $request = $$r{request};
+              $request =~ s/\\n/\n/g ;
+
+              &ld_debug(2, "Checking simpletcp server=$$r{server} port=$d_port 
request:\n$request");
+              print $sock $request;
+
+              my $ok;
+              my $reply;
+              while (<$sock>) {
+                      &ld_debug(2, "Checking simpletcp server=$$r{server} 
port=$d_port receive=" . $$r{receive} ." got: $_\n");
+                      if ( $_ =~ /$$r{receive}/ ) {
+                              $ok = 1;
+                              last;
+                      }
+              }
+              alarm 0; # Cancel the alarm
+              close($sock);
+
+              if (!defined $ok) {
+                      die "No OK\n";
+              }
+       };
+
+       if ($@) {
+              &service_set($v, $r, "down");
+              &ld_debug(3, "Deactivated service $$r{server}:$$r{port}: $@");
+              return $SERVICE_DOWN;
+       } else {
+              &service_set($v, $r, "up");
+              &ld_debug(3, "Activated service $$r{server}:$$r{port}");
+              return $SERVICE_UP;
+       }
+}
+
 sub check_ftp
 {
        require Net::FTP;


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