On Sun, Jul 16, 2006 at 05:49:44PM -0700, Joseph Mack NA3T wrote:
> On Sun, 16 Jul 2006, Robinson, Eric wrote:
>
> >The root cause is that ipvsadm is misbehaving. Instead of changing the
> >realserver's weight, it is complaining that the destination exists.
>
> There were a few of us who wanted this behaviour changed,
> but at the time we were vetoed, but maybe times have
> changed.
>
> Hey Horms,
>
> I don't suppose the ipvsadm add/edit patch of yours
> could be revisited? It seems the current behaviour is
> causing problems with ldirectord.
Hi Joe,
Eric and I discussed this offline and I have formulated a patch which
seems to be working. It should apply to 1.131 (the version he is
using), 1.141 (the version in CVS right now), and likely quite a few
other versions. Comments inline. Feedback welcome.
--
Horms
H: http://www.vergenet.net/~horms/
W: http://www.valinux.co.jp/en/
--- from-0001/ldirectord
+++ to-work/ldirectord 2006-07-17 22:15:09.000000000 -0400
@@ -1496,6 +1496,44 @@ sub ld_setup
}
}
+# ld_read_ipvsadm
+#
+# Net::FTP seems to set the input record separator ($\) to null
+# putting IO into slurp (whole file at a time, rather than line at a time)
+# mode. Net::FTP does this using local $\, which should mean
+# that the change doesn' effect code here, but it does. It also
+# seems to be imposible to turn it off, by say setting $\ back to '\n'
+# Perhaps there is more to this than meets the eye. Perhaps its a perl bug.
+# In any case, this should fix the problem.
+#
+# This should not affect pid or config file parsing as they are called
+# before Net::FTP and as this appears to be a bit of a work around,
+# I'd rather use it in as few places as possible
+#
+# Observed with perl v5.8.8 (Debian's perl 5.8.8-6)
+# -- Horms, 17th July 2005
+sub ld_readline
+{
+ my ($fd, $buf) = (@_);
+ my $line;
+
+ # Uncomment the following line to turn off this work around
+ # return readline($fd);
+
+ $line = shift @$buf;
+ if (defined $line) {
+ return $line . "\n";
+ }
+
+ push @$buf, split /\n/, readline($fd);
+
+ $line = shift @$buf;
+ if (defined $line) {
+ return $line . "\n";
+ }
+
+ return undef;
+}
# ld_read_ipvsadm
# Parses the output of "ipvsadm -L -n" and puts into a structure of
@@ -1540,28 +1578,35 @@ sub ld_read_ipvsadm
my %oldsrv;
my $real_service;
my $fwd;
+ my $buf = [];
+ my $fh;
+ my $line;
# read status of current ipvsadm -L -n
- unless(open(IPVS, "$IPVSADM -L -n |")){
+ unless(open($fh, "$IPVSADM -L -n 2>&1|")){
&ld_exit(1, "Could not run $IPVSADM -L -n: $!");
}
- $_ = <IPVS>; $_ = <IPVS>; $_ = <IPVS>;
- while (<IPVS>) {
- if ($_ =~
/(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)\s+mask\s+(.*)/)
{
+ # Skip the first three lines
+ $line = ld_readline($fh, $buf);
+ $line = ld_readline($fh, $buf);
+ $line = ld_readline($fh, $buf);
+
+ while ($line = ld_readline($fh, $buf)) {
+ if ($line =~
/(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)\s+mask\s+(.*)/)
{
$real_service = "$2 ".lc($1);
$oldsrv{"$real_service"} = {"real"=>{},
"scheduler"=>$3, "persistent"=>$4, "netmask"=>$5};
- } elsif ($_ =~
/(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)/) {
+ } elsif ($line =~
/(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)\s+persistent\s+(\d+)/) {
$real_service = "$2 ".lc($1);
$oldsrv{"$real_service"} = {"real"=>{},
"scheduler"=>$3, "persistent"=>$4};
- } elsif ($_ =~ /(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)/)
{
+ } elsif ($line =~
/(\w+)\s+(\d+\.\d+\.\d+\.\d+\:\d+|\d+)\s+(\w+)/) {
$real_service = "$2 ".lc($1);
$oldsrv{"$real_service"} = {"real"=>{},
"scheduler"=>$3};
} else {
next;
}
- while(<IPVS>) {
- last unless $_ =~ /
->\s+(\d+\.\d+\.\d+\.\d+\:\d+)\s+(\w+)\s+(\d+)/;
+ while ($line = ld_readline($fh, $buf)) {
+ last unless $line =~ /
->\s+(\d+\.\d+\.\d+\.\d+\:\d+)\s+(\w+)\s+(\d+)/;
if ($2 eq "Route") {
$fwd = "gate";
} elsif ($2 eq "Tunnel") {
@@ -1573,7 +1618,7 @@ sub ld_read_ipvsadm
}
redo;
}
- close(IPVS);
+ close($fh);
return(\%oldsrv);
}
|