#!/usr/bin/perl # # pbadm # # Perlbal administrative helper script. # # Authors: # kareila # # Copyright (c) 2009 by Dreamwidth Studios, LLC. # # This program is free software; you may redistribute it and/or modify it under # the same terms as Perl itself. For a copy of the license, please reference # 'perldoc perlartistic' or 'perldoc perlgpl'. # use warnings; use strict; use Net::Telnet (); use Date::Format ('time2str'); use Term::ANSIColor ('color'); ### USER CHANGEABLE CONSTANTS ### my $summary = 0; if ($ARGV[0] eq '-s') { $summary = 1; shift; } my $refresh = shift() || 10; # polling interval in seconds my $timeout = 5; # max time to connect in seconds # intervals for color levels my $sev0 = 0; my $sev0_color = 'green'; my $sev1 = 100; my $sev1_color = 'yellow'; my $sev2 = 500; my $sev2_color = 'bold yellow'; my $sev3 = 1000; my $sev3_color = 'red'; my $sev4_color = 'bold red'; # anything above sev3 ### READ CONFIG INFO ### require "$ENV{LJHOME}/ext/local/etc/config-private.pl"; my %hostinfo = eval "return %LJ::PERLBAL_SERVERS;"; # to suppress the warning die "\%LJ::PERLBAL_SERVERS not found, please check config" unless %hostinfo; my @servers = sort keys %hostinfo; ### INITIALIZE NETWORK VARIABLES ### my %tcp; my %s1; my %s2; foreach (@servers) { $tcp{$_} = new Net::Telnet (Timeout => $timeout, Telnetmode => 0); my ($host, $port) = split ':', $hostinfo{$_}; $tcp{$_}->host($host); $tcp{$_}->port($port); $tcp{$_}->errmode('return'); # don't die on connfail $tcp{$_}->prompt('/\.$/'); # Perlbal end-of-data marker $tcp{$_}->open(); # should stay open } sub color_for { my $n = $_[0]+0; return color $sev4_color if ($n > $sev3); return color $sev3_color if ($n > $sev2 && $n <= $sev3); return color $sev2_color if ($n > $sev1 && $n <= $sev2); return color $sev1_color if ($n > $sev0 && $n <= $sev1); return color $sev0_color if ($n == $sev0); return color $sev4_color; # Makes no sense. } ### INFINITE POLLING LOOP ### until (0 > 1) { my $timestr = time2str("%a %b %d %T %Y", time); foreach my $server (@servers) { my @states = $tcp{$server}->cmd('states'); unless (@states) { $s1{$server} = 'DWN'; $s2{$server} = 'DOWN'; $tcp{$server}->open(); # try to reopen next; } my $bh_xfer = 0; my $bh_wait = 0; my $backend = 0; foreach (@states) { $bh_xfer = $1 if /Perlbal::BackendHTTP xfer_res (\d+)/; $bh_wait = $1 if /Perlbal::BackendHTTP wait_res (\d+)/; $backend = $1 if /Perlbal::ClientProxy wait_backend (\d+)/; } $s1{$server} = sprintf("%03d", $bh_xfer + $bh_wait); $s2{$server} = sprintf("%04d", $backend); } if ($summary) { my ($ts1, $ts2, $td) = (0, 0, 0); # totals of foreach (@servers) { $ts1 += $s1{$_} || 0; $ts2 += $s2{$_} || 0; $td++ if $s1{$_} eq 'DWN'; } my $cr = color 'reset'; my $cw = color 'white'; my $down = $td ? sprintf(' %s** %d DOWN **%s', color($sev4_color), $td, $cr) : ''; printf '%s%2d%s%s IF %s%d%s%s Q%s%s', color($sev0_color), $ts1, $cr, $cw, color_for($ts2), $ts2, $cr, $cw, $down, $cr; print "\n"; last; # only run once } else { print "$timestr: "; foreach (@servers) { my $n = ($s2{$_} eq 'DOWN') ? $sev3 * 10 : $s2{$_}; print color_for($n) . "[$_ - $s1{$_}, $s2{$_}] "; print color 'reset'; } print "\n"; } sleep $refresh; }