LDIRECTORD: Add external checktype

J.Libak at sh.cvut.cz J.Libak at sh.cvut.cz
Tue Apr 24 17:39:42 BST 2007


I wrote this patch a while ago, but don't use it at the moment.

Roberto Nibali wrote:
>> Cc: Roberto Nibali <ratz at drugphish.ch>
>> Signed-off-by: Simon Horman <horms at verge.net.au>
>>
>> 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

Search lvs-users Archives
Limit search to: Subject & Body Subject Author
Sort by: Reverse Sort

More information about the lvs-users mailing list