LVS
lvs-users
Google
 
Web LinuxVirtualServer.org

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

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

===== CUT =====
--- /usr/sbin/ldirectord        2007-08-10 06:15:50.000000000 -0600
+++ ldirectord  2007-09-13 09:30:20.000000000 -0600
@@ -1222,7 +1222,8 @@
                                                          $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, " .
@@ -2220,6 +2221,8 @@
                                                $$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);
                                        }
@@ -2907,6 +2910,73 @@
 }


+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;

===== CUT =====




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