Match the output of `ipvsadm -L -n` against a given ldirectord
configuration file to produce a verbose status sub-command output, to
see which virtual and which real servers are up or down, plus some
additional information.

---

The output mimics format of NetScaler "show" commands.

Comments?

Best,
Hannes

diff -r 15160b7b2a93 ldirectord/ldirectord.in
--- a/ldirectord/ldirectord.in  Tue May 26 13:55:29 2009 +0200
+++ b/ldirectord/ldirectord.in  Tue May 26 15:57:00 2009 +0200
@@ -999,6 +999,8 @@
                        print STDERR "ldirectord for $CONFIG is running with 
pid: $oldpid\n";
                        ld_cmd_children("status", %LD_INSTANCE);
                        ld_log("ldirectord for $CONFIG is running with pid: 
$oldpid");
+                       ld_setup();
+                       ld_show_status();
                        ld_log("Exiting from ldirectord $CMD");
                        ld_exit(0, "Exiting from ldirectord $CMD");
                }
@@ -1019,6 +1021,8 @@
                                $status = 3;
                        }
                        print "ldirectord is stopped for $CONFIG\n";
+                       ld_setup();
+                       ld_show_status();
                        ld_exit($status, "Exiting from ldirectord $CMD");
                } else {
                        ld_log("ldirectord is stopped for $CONFIG");
@@ -4966,3 +4970,138 @@
 {
        return ld_find_cmd_path($_[0], $ENV{'PATH'}, $_[1]);
 }
+
+# mode_disp_str
+# helper for ld_show_status
+sub mode_disp_str
+{
+       my ($mode) = (@_);
+       my %map = (
+               gate    => "DSR",
+               masq    => "NAT",
+               ipip    => "TUN"
+       );
+       return exists($map{$mode}) ? "$map{$mode} ($mode)" : "? ($mode)";
+}
+
+# scheduler_disp_str
+# helper for ld_show_status
+sub scheduler_disp_str
+{
+       my ($scheduler) = (@_);
+
+       # stolen from the ipvsadm-1.2.0 manpage
+       my %scheduler_disp_strs = (
+               rr      => "Robin Robin",
+               wrr     => "Weighted Round Robin",
+               lc      => "Least-Connection",
+               wlc     => "Weighted Least-Connection",
+               lblc    => "Locality-Based Least-Connection",
+               lblcr   => "Locality-Based Least-Connection with Replication",
+               dh      => "Destination Hashing",
+               sh      => "Source Hashing",
+               sed     => "Shortest Expected Delay",
+               nq      => "Never Queue"
+       );
+
+       my $scheduler_name = $scheduler_disp_strs{$scheduler};
+       $scheduler_name = "?" if (!defined($scheduler_name));
+       $scheduler_name =~ tr/ -//d;
+       return uc($scheduler_name) . " ($scheduler)";
+}
+
+# ld_show_status
+# Write a verbose status to STDOUT.  It does so by matching the output of
+# ipvsadm against the given config file.  No IPC to the running ldirectord
+# daemon is performed.
+#
+# pre: read_config() and ld_setup() have been called.
+# return: none
+sub ld_show_status
+{
+       # read and parse `ipvsadm -L -n`
+       my $ipvs = &ld_read_ipvsadm();
+
+       print "\n";
+
+       foreach my $cv (@VIRTUAL) {
+               my $real_service = &get_virtual($cv) . " " . $cv->{protocol};
+               my $crs = $cv->{real};
+               my $irs = $ipvs->{$real_service}->{real};
+               my $fb = fallback_find($cv);
+               my $real_str;
+               my $r;
+
+               my $state = exists($ipvs->{$real_service}) ? "UP" : "DOWN";
+               print "\t", get_virtual($cv), " - ", uc($$cv{protocol}), "\n";
+               print "\tState: ", $state, "\n";
+
+               my $eff_state = "DOWN";
+               for $r (values %$irs) {
+                       if ($$r{weight} > 0) {
+                               $eff_state = "UP";
+                               last;
+                       }
+               }
+
+               if ($eff_state eq "DOWN" and defined($fb)) {
+                       $real_str = "$$fb{server}:$$fb{port}";
+                       if (defined($$irs{$real_str})
+                           and $$irs{$real_str}->{weight} > 0) {
+                               $eff_state = "FALLBACK";
+                       }
+               }
+
+               print "\tEffective State: ", $eff_state, "\n";
+               print "\tMethod: ", scheduler_disp_str($$cv{scheduler}), "\n";
+               print "\tConfig Options:\n";
+               for my $key (sort keys %$cv) {
+                       next if ($key =~ 
m/^(server|port|protocol|real|flags|proto|fallback|scheduler)$/m);
+                       my $value = $$cv{$key};
+                       next if (!defined($value) or $value eq "");
+                       print "\t\t$key: $value\n";
+               }
+               print "\n";
+
+               my $r_nr = 1;
+
+               # list fallback
+               if (defined($fb)) {
+                       $state = "FALLBACK";
+                       print $r_nr, ")\t", $$fb{server}, ":", $$fb{port},
+                               " - ", uc($$cv{protocol}),
+                               " Mode: ", mode_disp_str($$fb{forward}),
+                               " State: ", $state,
+                               "\tWeight: ", $$fb{weight}, "\n";
+                       $r_nr++;
+                       delete($$irs{"$$fb{server}:$$fb{port}"});
+               }
+
+               # list real servers which are in the config (up or down)
+               for $r (@$crs) {
+                       $real_str = "$$r{server}:$$r{port}";
+                       $state = (!defined($$irs{$real_str})
+                                 or $$irs{$real_str}->{weight} == 0) ? "DOWN" 
: "UP";
+                       print $r_nr, ")\t", $$r{server}, ":" , $$r{port},
+                               " - ", uc($$cv{protocol}),
+                               " Mode: ", mode_disp_str($$r{forward}),
+                               " State: ", $state,
+                               "\tWeight: ", $$r{weight}, "\n";
+                       $r_nr++;
+                       delete($$irs{$real_str});
+               }
+
+               # list real servers which are up but NOT in the config
+               $state = "UP (NOT IN CFG)";
+               while (($real_str, $r) = each %$irs) {
+                       print $r_nr, ")\t", $real_str,
+                               " - ", uc($$cv{protocol}),
+                               " Mode: ", mode_disp_str($$r{forward}),
+                               " State: ", $state,
+                               "\tWeight: ", $$r{weight}, "\n";
+                       $r_nr++;
+               }
+
+               print "\n";
+       }
+}
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/

Reply via email to