On Mon, Oct 10, 2005 at 10:21:05AM +0100, Struan Bartlett wrote: > Hi - > > I'm new to this list but I hope you'll forgive me getting right to the > point. > > Our organisation is testing a new version of ldirectord - version 1.77.2.6 > from Debian package 1.2.3-9sarge3 - and have encountered a serious problem > that shows different behaviour to the previous version we used (1.26) and, > unlike that previous version, seems to prevent it from working properly. > > Here is our ldirectord.cf: > > checktimeout=60 > checkinterval=15 > fallback=127.0.0.1 > > virtual=217.204.41.132:80 > scheduler=wlc > real=192.168.2.32:80 masq 1024 > real=192.168.2.52:80 masq 1024 > real=192.168.2.62:80 masq 1024 > real=192.168.2.72:80 masq 1024 > service=http > request="/cgi/NewsNow/Status/" > receive="ldirectord-ok-string" > protocol=tcp > > Now observe the results on startup: > > # /etc/init.d/ldirectord start > Starting ldirectord > > # ipvsadm -Ln > IP Virtual Server version 1.0.10 (size=4096) > Prot LocalAddress:Port Scheduler Flags > -> RemoteAddress:Port Forward Weight ActiveConn InActConn > TCP 217.204.41.132:80 wlc > -> 192.168.2.62:80 Masq 1024 0 0 > -> 192.168.2.72:80 Masq 1024 0 0 > -> 192.168.2.52:80 Masq 1024 0 0 > -> 192.168.2.32:80 Masq 1024 0 0 > -> 127.0.0.1:80 Local 1 0 0 > > As I hope you see, the failover server weight has not been switched to > zero, which appears to continue to allow some traffic to reach the > failover servers. I understand this is incorrect. > > Please could you advise: is this a known bug, an unknown bug, or an error > in our configuration of ldirectord? > > Kind regards, > > Struan Bartlett > > P.S. For your information, the situation is not the same after a reload: > > # /etc/init.d/ldirectord reload > > # ipvsadm -Ln > IP Virtual Server version 1.0.10 (size=4096) > Prot LocalAddress:Port Scheduler Flags > -> RemoteAddress:Port Forward Weight ActiveConn InActConn > TCP 217.204.41.132:80 wlc > -> 192.168.2.62:80 Masq 1024 0 0 > -> 192.168.2.72:80 Masq 1024 0 0 > -> 192.168.2.52:80 Masq 1024 0 0 > -> 192.168.2.32:80 Masq 1024 0 0
Hi Struan, Sorry for letting your bug report fester in my inbox for such a long time. I've been doing a bit of a blitz on ldirectord bugs over the past few days, and I found that inadvertantly I had a fix for this problem - which is still present in the latest version of ldirectord. I'm not sure if the patch below applied against 1.77.2.6, and it is rather long. But here is is, just for the record. -- Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/ Subject: [LDIRECTORD] Tidy up fallback * Use the same parsing sequence for per-virtual and global fallback * Cope with the fallback not having a port specified by using the port of the virtual service * Split the server feild up into server (ip) and port, and also add a weight feild so that when its passed to get_real_id_str() it has the relevant feilds that would be in a real server, otherwise get_real_id_str() tries to access non-existent values. This patch solves a bug discovered by Struan Bartlett whereby the failack server will not be removed as expected if it doesn't have a port specified. Thanks also to Tuomo Soini for pointing me in this direction Signed-off-by: Simon Horman <[EMAIL PROTECTED]> Index: heartbeat/ldirectord/ldirectord.in =================================================================== --- heartbeat.orig/ldirectord/ldirectord.in 2007-07-05 14:21:42.000000000 +0900 +++ heartbeat/ldirectord/ldirectord.in 2007-07-05 14:21:42.000000000 +0900 @@ -1173,7 +1173,9 @@ sub read_config $vsrv{virtualhost} = $1; } elsif ($rcmd =~ /^fallback\s*=\s*(.*)/) { # Allow specification of a virtual-specific fallback host $fallback_line=$line; - $vsrv{fallback}=parse_fallback($line, $1); + $vsrv{fallback} = + parse_fallback($line, $1, + \%vsrv); } elsif ($rcmd =~ /^quiescent\s*=\s*(.*)/) { ($1 eq "yes" || $1 eq "no") or &config_error($line, "quiescent must be 'yes' or 'no'"); @@ -1240,21 +1242,11 @@ sub read_config "invalid check count value"); $CHECKCOUNT = $1; } elsif ($linedata =~ /^fallback\s*=\s*(.*)/) { - my $tcp = &ld_gethostservbyname($1, "tcp"); - my $udp = &ld_gethostservbyname($1, "udp"); - my $tcp_fb; - my $udp_fb; - if(!defined($tcp) and !defined($udp)){ - &config_error($line, - "invalid address for fallback server"); - } - if(defined($tcp)) { - $tcp_fb=&parse_fallback($line, $tcp); - } - if(defined($udp)) { - $udp_fb=&parse_fallback($line, $udp); - } - $FALLBACK = { "tcp" => $tcp_fb, "udp" => $udp_fb }; + my $tcp = parse_fallback($line, $1, undef); + my $udp = parse_fallback($line, $1, undef); + &_ld_read_config_fallback_resolve($line, "tcp", $tcp); + &_ld_read_config_fallback_resolve($line, "udp", $udp); + $FALLBACK = { "tcp" => $tcp, "udp" => $udp }; } elsif ($linedata =~ /^autoreload\s*=\s*(.*)/) { ($1 eq "yes" || $1 eq "no") or &config_error($line, @@ -1477,16 +1469,20 @@ sub _ld_read_config_fallback_resolve { my($line, $protocol, $fallback)=(@_); - my $ip_port; - unless($fallback) { return; } - $fallback->{server}=&ld_gethostservbyname( - $fallback->{server}, $protocol) - or &config_error($line, - "invalid address for fallback server"); + $fallback->{server} = &ld_gethostbyname($fallback->{server}) or + &config_error($line, "invalid address for fallback server: " . + $fallback->{server}); + + unless($fallback->{"port"}) { + return; + } + + $fallback->{port} = &ld_getservbyname($fallback->{port}, $protocol) or + &config_error($line, "invalid port for fallback server"); } @@ -1696,17 +1692,22 @@ sub add_real_server sub parse_fallback { - my ($line, $fallback) = (@_); + my ($line, $fallback, $vsrv) = (@_); - my $ip_port; + my $server; + my $port; my $fwd; - $fallback =~ /^\s*(\S+)(\s+(\S+))?\s*/ or + $fallback =~ /^\s*([^: ]+)(:(\S+))?(\s+(\S+))?\s*/ or &config_error($line, "invalid fallback server: $fallback"); - $ip_port=$1; - $fwd=$3; + $server=$1; + $port=$3; + $fwd=$5; + if (not defined($port) and defined($vsrv)) { + $port = $vsrv->{"port"}; + } if($fwd) { ($fwd eq "gate" || $fwd eq "masq" || $fwd eq "ipip") @@ -1717,7 +1718,8 @@ sub parse_fallback $fwd="gate" } - return({"server"=>$ip_port, "forward"=>$fwd}); + return({"server"=>$server, "port"=>$port, "forward"=>$fwd, + "weight"=>1}); } @@ -1999,7 +2001,7 @@ sub ld_start my $fallback = fallback_find($nv); if (defined($fallback)) { - delete($or->{$fallback->{server}}); + delete($or->{"$fallback->{server}:$fallback->{port}"}); } for $nr (@$nreal) { @@ -3251,7 +3253,7 @@ sub fallback_on return; } - &_restore_service($v, $fallback->{server}, + &_restore_service($v, $fallback->{server} . ":" . $fallback->{port}, get_forward_flag($fallback->{forward}), "1", "fallback"); } @@ -3274,7 +3276,7 @@ sub fallback_off return; } - &_remove_service($v, $fallback->{server}, + &_remove_service($v, $fallback->{server} . ":" . $fallback->{port}, get_forward_flag($fallback->{forward}), "fallback"); } @@ -3294,11 +3296,20 @@ sub fallback_find if( defined $virtual->{"fallback"} ) { return($virtual->{"fallback"}); - } elsif ( defined($FALLBACK) ) { - return($FALLBACK->{$virtual->{"protocol"}}); + } elsif ( not defined($FALLBACK) ) { + return undef; } - return undef; + # If the global fallback has a port, it can be used as is + if (defined($FALLBACK->{$virtual->{"protocol"}}->{"port"})) { + return $FALLBACK->{$virtual->{"protocol"}}; + } + + # Else create an anonymous fallback + my %anon_fallback = %{$FALLBACK->{$virtual->{"protocol"}}}; + $anon_fallback{"port"} = $virtual->{"port"}; + + return \%anon_fallback; } _______________________________________________ LinuxVirtualServer.org mailing list - lvs-users@LinuxVirtualServer.org Send requests to [EMAIL PROTECTED] or go to http://lists.graemef.net/mailman/listinfo/lvs-users