I wrote this patch a while ago, but don't use it at the moment.
Roberto Nibali wrote:
>> Cc: Roberto Nibali <ratz@xxxxxxxxxxxx>
>> Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx>
>>
>> Index: heartbeat/ldirectord/ldirectord.in
>> ===================================================================
>> --- heartbeat.orig/ldirectord/ldirectord.in 2007-04-24 18:17:05.000000000
>> +0900
>> +++ heartbeat/ldirectord/ldirectord.in 2007-04-24 18:17:16.000000000
>> +0900
>> @@ -286,7 +286,7 @@ checktimeout, negotiatetimeout, checkcou
>> emailalertfreq and quiescent options listed above may also appear inside a
>> virtual section, in which case the global setting is overridden.
>>
>> -B<checktype => B<connect>|B<negotiate>|B<off>|B<on>|B<ping>|I<N>
>> +B<checktype => B<connect>|B<external>|B<negotiate>|B<off>|B<on>|B<ping>|I<N>
>>
>> Type of check to perform. Negotiate sends a request and matches a receive
>> string. Connect only attemts to make a TCP/IP connection, thus the
>> @@ -351,6 +351,14 @@ Number of port to monitor. Sometimes che
>>
>> Default: port specified for each real server
>>
>> +B<externalpath = ">I<path to script>B<">
>> +
>> +This setting is taken into account if checktype is external - by external
>> +script. Enter path of the script into double quotes. Script should return
>> +0 if everything is ok, or something else if it isn't. 4 parameters are
>> passed
>> +to the script - virtual server ip/firewall mark, virtual server port,
>> +real server ip, real server port.
>> +
>
> Do we need a warning here, that all the calling of external scripts can
> be dangerous security-wise and hazardous runtime-wise? I've just been
> burnt a couple of times when I provided such functionality to former
> customers, who then at free will started creating script monstrosities.
>
Add a warning to description that it should be used only as the last option.
>> B<request = ">I<uri to requested object>B<">
>>
>> This object will be requested each checkinterval seconds on each real
>> @@ -1021,6 +1029,7 @@ sub read_config
>> }
>> $vsrv{real} = \@rsrv;
>> $vsrv{scheduler} = "wrr";
>> + $vsrv{externalpath} = "/bin/true";
>> $vsrv{request} = "/";
>> $vsrv{receive} = "";
>> $vsrv{login} = "";
>> @@ -1062,11 +1071,19 @@ sub read_config
>> if ($1 =~ /(\d+)/ && $1>=0) {
>> $vsrv{num_connects} = $1;
>> $vsrv{checktype} = "combined";
>> - } elsif ( $1 =~ /(\w+)/ && ($1 eq
>> "connect" || $1 eq "negotiate" || $1 eq "ping" || $1 eq "off" || $1 eq "on")
>> ) {
>> + } elsif ( $1 =~ /(\w+)/ &&
>> + ($1 eq "connect" ||
>> + $1 eq "negotiate" ||
>> + $1 eq "ping" ||
>> + $1 eq "off" ||
>> + $1 eq "on" ||
>> + $1 eq "external") ) {
>> $vsrv{checktype} = $1;
>> } else {
>> &config_error($line, "checktype
>> must be connect, negotiate, ping, off, on or a positive number");
>> - }
>> + } elsif ($rcmd =~
>> /^externalpath\s*=\s*(.*)/){
>> + $1 =~ /(.+)/ or &config_error($line,
>> "invalid external script");
>> + $vsrv{externalpath} = $1;
>> } elsif ($rcmd =~ /^checktimeout\s*=\s*(.*)/){
>> $1 =~ /(\d+)/ && $1 or
>> &config_error($line, "invalid check timeout");
>> $vsrv{checktimeout} = $1;
>> @@ -2102,6 +2119,9 @@ sub ld_main
>> } elsif ($$v{checktype} eq "ping") {
>> &ld_debug(2, "Checking ping: real
>> server=$real_id (virtual=$virtual_id)");
>> check_ping($v, $r);
>> + } elsif ($$v{checktype} eq "external") {
>> + &ld_debug(2, "Checking
>> external: real server=$real_id (virtual=$virtual_id)");
>> + check_external($v, $r);
>> } elsif ($$v{checktype} eq "off") {
>> &ld_debug(2, "Checking off: No real or
>> fallback servers to be added\n");
>> } elsif ($$v{checktype} eq "on") {
>> @@ -2570,6 +2590,40 @@ sub check_connect
>> }
>>
>>
>> +sub check_external {
>> + my ($v, $r) = @_;
>> + my $result;
>> + my $v_server;
>> +
>> + eval {
>> + local $SIG{'__DIE__'} = "DEFAULT";
>> + local $SIG{'ALRM'} = sub { die "Timeout Alarm" };
>> + &ld_debug(4, "Timeout is $$v{checktimeout}");
>> + alarm $$v{checktimeout};
>> + if (defined $$v{server}) {
>> + $v_server = $$v{server};
>> + } else {
>> + $v_server = $$v{fwm};
>> + }
>> + $result = system("$$v{externalpath} $v_server " .
>> + "$$v{port} $$r{server} $$r{port}");
>> + alarm 0;
>> + $result >>= 8;
>> + };
>> + if ($@ or $result != 0) {
>> + &service_set($v, $r, "down");
>> + &ld_debug(3, "Deactivated service $$r{server}:$$r{port}: "
>> + "$@ after calling $$v{externalpath} with result "
>> + "$result");
>> + return 0;
>> + } else {
>> + &service_set($v, $r, "up");
>> + &ld_debug(3, "Activated service $$r{server}:$$r{port}");
>> + return 1;
>> + }
>> +}
>> +
>> +
>> sub check_sip
>> {
>> my ($v, $r) = @_;
>>
>
> I seem to be confused a bit at times: so in this checktype the return
> value of the function is 1 for non-failed health check and activated
> service and 0 otherwise? How about introducing enums {SERVICE_UP,
> SERVICE_DOWN} for legibility?
>
Return value of the function is irrelevant, as we only call
check_external($v, $r); and don't do anything with the return value.
Service is activated/deactivated by the &service_set($v, $r, "up"); call.
Jaro
|