blob: ad392ee674385a0b03569aa81b82d431d753a889 [file] [log] [blame]
#!/usr/local/bin/perl -w
use strict 'refs';
require Net::Ping;
require Term::ReadKey;
#defaults
$mibident=".ERRORNAME";
$miberrflag=".ERRORFLAG";
$miberrmsg=".ERRORMSG";
$mibfix=".ERRORFIX";
$mibheadall=".EXTENSIBLEDOTMIB";
$mibclearcache="$mibheadall.VERSIONMIBNUM.VERCLEARCACHE";
$mibrestartagent="$mibheadall.VERSIONMIBNUM.VERRESTARTAGENT";
$mibupdateconfig="$mibheadall.VERSIONMIBNUM.VERUPDATECONFIG";
%miblist=( '.PROCMIBNUM.1' => 'processes',
'.SHELLMIBNUM.1' => 'scripts',
'.MEMMIBNUM' => 'swap space',
'.DISKMIBNUM.1' => 'disks',
'.LOADAVEMIBNUM.1' => 'load-average',
'.ERRORMIBNUM' => 'snmp-agent-errors');
@fixitlist=('.PROCMIBNUM.1','.SHELLMIBNUM.1');
%mibchecklist = ('.PROCMIBNUM.1' => 1,
'.SHELLMIBNUM.1' => 1,
'.MEMMIBNUM' => 1,
'.DISKMIBNUM.1' => 1,
'.LOADAVEMIBNUM.1' => 1,
'.ERRORMIBNUM' => 1);
$errlog="/net/tyfon/1/OV/log/ece-log";
$default_get_args = "-v 1 %s private";
$default_set_args = "-v 1 %s private";
$andlog=0;
$snmppath="BINDIR";
$eraseline=" \r";
$fixit=0; # this should be 0 not -1, but is necessary till getc(STDIN) works
$rescanWhen = 300;
$display = $ENV{'DISPLAY'};
$hidden = 0;
$pinghost = 0;
$loglevel = 1;
$logwindowatstart = 0;
$numloglevels = 5;
$dontstart = 0;
$raiseonnew = 1;
#
# Mib Package: Each mib has a mib number attached and can check/fix itself;
#
package Mib;
# @ISA = qw( Host );
sub new {
my $tmp = shift;
my $self = {};
$self->{'HostId'} = shift;
$self->{'Host'} = $self->{'HostId'}->{'Name'};
$_ = shift;
$self->{'Mib'} = $_;
print "test: $_\n";
($self->{'MibSuffix'}) = /(\.[0-9]+)$/;
if (!defined($mibchecklist{$self->{'MibSuffix'}})) {
($self->{'MibSuffix'}) = /(\.[0-9]+\.1)$/;
}
print "suff: $self->{'MibSuffix'}\n";
$self->{'MibDesc'} = shift;
$self->{'Frame'} = shift;
bless $self;
}
sub getmibnum {
my $self = shift;
return ($self->{'Mib'});
}
sub snmp_walk {
my $self = shift;
$self->{'Frame'}->toplevel->Busy() if ($::display);
my $mib = shift;
my $cmd = "$::snmppath/snmpwalk " . sprintf($::default_get_args, $self->{'Host'}) . " $mib|";
::addToLog("running: $cmd",5);
open(OUT,"$cmd");
my $outcount = 0;
my @result = [];
while (<OUT>) {
$result[$outcount] = $_;
chop;
::addToLog("snmpwalk: $_",5);
if ($::display) {
$self->{'Frame'}->toplevel->update;
}
$outcount++;
}
close(OUT);
for($i=0; $i <= $#result; $i++) {
$result[$i] =~ s/ Hex:.*$//g;
$result[$i] =~ s/\"//g;
}
$self->{'Frame'}->toplevel->Unbusy() if ($::display);
if ($result[0] =~ /No Response/) {
$self->{'HostId'}->hostdown;
splice(@result,0);
}
return @result;
}
sub check {
my $self = shift;
my $tmp = [];
if ($::mibchecklist{$self->{'MibSuffix'}} != 1) {
return @{$tmp};
}
if (! $::display) {
printf "%sChecking %s: %s\r", $::eraseline,$self->{'Host'},
$self->{'MibDesc'};
}
my @walkout = $self->snmp_walk("$self->{'Mib'}$::miberrflag");
while ($#walkout > -1) {
$_ = shift @walkout;
($result) = /= ([0-9]+)/;
if (defined($result) && $result > 0)
{
($mibloc) = /\.([0-9]+) /;
push(@{$tmp},FixProblem::new("",$self->{'HostId'}, $self->{'Mib'},
$self->{'MibDesc'},
$mibloc,$self->{'Frame'}));
if (! $::display) {
printf("%s%-8.8s %-12.12s %2d -- %-37.37s",$::eraseline,
$self->{'Host'},$tmp->[0]->{'ErrName'},
$result,$tmp->[0]->{'ErrMsg'});
if ($tmp->[0]->canfix() && $::fixit == 0) {
printf(" / Fix? ");
$ans = Term::ReadKey::ReadKey(0);
if ("$ans" eq "y" || "$ans" eq "Y") {
printf("\b\b\b\b\b\b\b\b");
$tmp->[0]->fix($mibloc); # fix now if curses
} else {
print $ans;
printf("\nChecking %s: %s\r",$self->{'Host'},
$self->{'MibDesc'});
}
} elsif ($::fixit > 0) {
$tmp->[0]->fix($mibloc); # fix now if curses
}
shift @{$tmp};
}
}
}
return(@{$tmp});
}
#
# Problem Package: A problem comes into existence when found. It may
# or may not know how to fix itself (Problem/FixProblem).
#
package Problem;
@ISA = qw( Mib );
sub snmp_get {
my $self = shift;
$self->{'Frame'}->toplevel->Busy() if ($::display);
my $mib = shift;
my $args = sprintf($::default_get_args, $self->{'Host'});
$_ = `$::snmppath/snmpget $args $mib`;
my ($result) = /= (.*)$/;
if (!defined($result) || $result =~ /No Response/) {
$self->{'HostId'}->hostdown;
$result = "";
}
$result =~ s/\"//g;
$result =~ s/ Hex:.*$//g;
::addToLog("snmpget: $_",5);
$self->{'Frame'}->toplevel->Unbusy() if ($::display);
return $result;
}
sub snmp_set {
my $self = shift;
$self->{'Frame'}->toplevel->Busy() if ($::display);
my $mib = shift;
my $args = sprint($::default_set_args, $self->{'Host'});
$_ = `$::snmppath/snmpset $args $mib`;
my ($result) = /= (.*)$/;
$result = "" if (!defined($result));
$result =~ s/\"//g;
::addToLog("snmpset: $_",5);
$self->{'Frame'}->toplevel->Unbusy() if ($::display);
return $result;
}
sub new{
my $tmp = shift;
my $hostId = shift;
my $mib = shift;
my $mibname = shift;
my $self = new Mib ($hostId,$mib,$mibname);
$self->{'MibLocation'} = shift;
$tmp = shift;
if ($::display) {
$self->{'Frame'} = $tmp->Frame();
}
bless $self;
$self->{'ErrName'} =
$self->snmp_get("$self->{'Mib'}$::mibident.$self->{'MibLocation'}");
$self->{'ErrMsg'} =
$self->snmp_get("$self->{'Mib'}$::miberrmsg.$self->{'MibLocation'}");
if (exists $self->{'HostId'}->{'Down'}) {
return $self;
}
if ($::display) {
$self->{'Frame'}->pack();
$self->{'Desc'} =
$self->{'Frame'}->Button(-text => sprintf("%-12.12s %-42.42s",
$self->{'ErrName'},
$self->{'ErrMsg'}),
-font => "6x13",
-highlightcolor => "#ffffff",
-borderwidth => 0,
-relief => "flat",
-bd => 0, -padx => 0, -pady => 0,
-activeforeground => 'red',
-activebackground => '#C9C9C9',
-background => '#E0C9C9',
-command => [\&selectme,$self]);
$self->{'Desc'}->pack(-fill => "x",-expand => 1,-side=>"left"); #
if ($::raiseonnew) {
$tmp->toplevel->deiconify();
$tmp->toplevel->raise();
}
::addToLog("problem found: $self->{'Host'}\t$self->{'ErrName'}\t$self->{'ErrMsg'}",2);
}
bless $self;
return $self;
}
sub haveseen {
my $self = shift;
$self->{'Desc'}->configure(-background => '#C9C9C9');
}
sub selectme {
my $self = shift;
if ($main::hidden) {
main::makeappear();
return;
}
if (exists $self->{'Selected'}) {
main::deselectitem($self);
delete $self->{'Selected'};
} else {
main::selectitem($self);
$self->{'Desc'}->configure(-foreground => "red");
$self->{'Selected'} = 1;
}
$self->haveseen();
}
sub deselectme {
my $self = shift;
$self->{'Desc'}->configure(-foreground => "black");
delete $self->{'Selected'};
}
sub check {
my $self = shift;
if ($::display) {
main::setstatus("Checking $self->{'Host'} -- $self->{'ErrName'}");
}
else {
printf("Checking \b\b\b\b\b\b\b\b\b");
}
$result = $self->snmp_get("$self->{'Mib'}$::miberrflag.$self->{'MibLocation'}");
if (exists $self->{'HostId'}->{'Down'}) {
return 0;
}
if ($result == 0) {
$self->deleteme();
}
main::setstatus("idle");
return $result;
}
sub fix {
# Don't fix and/or unable to
my $self = shift;
main::setmsg("Don't know how to fix $self->{'ErrName'}");
}
sub rsh {
my $self = shift;
if ($::display) {
system "xterm -e rsh $self->{'HostId'}->{'Name'} -l root &";
}
}
sub deleteme {
my $self = shift;
my $host = $self->{'HostId'};
$host->deleteProb($self);
}
sub deleteself {
my $self = shift;
if ($::display) {
if ($self->{'Selected'}) {
main::deselectitem($self);
}
$self->{'Desc'}->destroy();
$self->{'Frame'}->destroy();
}
}
sub canfix {
return 0;
}
package FixProblem;
@ISA = qw( Problem );
sub new {
my $tmp = shift;
my $hostId = shift;
my $mib = shift;
my $mibdesc = shift;
my $mibloc = shift;
my $frame = shift;
my $self = new Problem ($hostId,$mib,$mibdesc,$mibloc,$frame);
$_ = $mib;
($mymib) = /(\.[0-9]+)$/;
if (grep(/$mymib/,@::fixitlist) && ($::fixit >= 0)) {
bless $self; # Make it a FixProblem if fixable
}
return $self; # else just return a Problem
}
sub canfix {
return 1;
}
sub fix {
my $self = shift;
my $mibloc = shift;
if ($::display) {
main::setstatus(sprintf("Fixing %s: %s",
$self->{'Host'}, $self->{'ErrName'}));
}
else {
printf(" / Fixing...\b\b\b\b\b\b\b\b\b");
}
$self->snmp_set("$self->{'Mib'}$::mibfix.$self->{'MibLocation'} integer 1");
$self->snmp_set("$::mibclearcache integer 1");
if (exists $self->{'HostId'}->{'Down'}) {
return;
}
if ($::display) {
main::setstatus("Sleeping");
}
else {
printf("Sleeping \b\b\b\b\b\b\b\b\b");
}
sleep(2);
if ($::display) {
main::setstatus("Checking");
}
else {
printf("Checking\b\b\b\b\b\b\b\b");
}
if ($self->check() != 0) {
if (! $::display) {
printf("*failed* \n");
} else {
main::setmsg("Failed to fix $self->{'ErrName'} on $self->{'Host'}");
}
}
else {
if ($::display) {
# $self->{'HostId'}->deleteProb($self);
main::setmsg("Fixed $self->{'ErrName'} on $self->{'Host'}");
}
else {
printf("Fixed \n");
}
}
main::setstatus("Idle");
}
#
# Host Package: Each object is a host which can check itself and display
# the results
#
package Host;
sub mibsort {
$_ = $a;
($av) = /\.([0-9]+)/;
$_ = $b;
($bv) = /\.([0-9]+)/;
return $av <=> $bv;
}
sub new {
my $self = {};
my $tmp = shift;
$self->{'Name'} = shift;
$self->{'Host'} = $self->{'Name'};
$self->{'Mibs'} = [];
$self->{'Problems'} = [];
bless $self;
if ($::display) {
$self->{'MainFrame'} = $::HostFrame->Frame();
if (!$::hidden) {
$self->{'MainFrame'}->configure(-relief =>"sunken",-borderwidth=>2);
}
$self->{'ProbFrame'} = $self->{'MainFrame'}->Frame();
$self->{'hostlabel'} =
$self->{'MainFrame'}->Button(-text => sprintf("%-9.9s",
$self->{'Name'}),
-bd => 0, -padx => 0, -pady => 0,
-command =>[\&selectme,$self],
-activeforeground => 'red',
-activebackground => '#C9C9C9',
-width => 9,
-anchor => "w",
-relief => "flat");
$self->{'hostlabel'}->pack(-side=>"left",-ipadx=>1,
-padx=> 1,-pady =>1);
$self->{'ProbFrame'}->pack(-side=>"left",-ipadx=>1,
-padx=> 1,-pady =>1);
$self->{'MainFrame'}->pack( #-padx => 2,-pady =>2,
-fill => "x", -expand => 1);
}
foreach $mibx ( sort mibsort keys(%::miblist) ) {
push(@{$self->{'Mibs'}},
new Mib ($self,"$::mibheadall$mibx",$::miblist{$mibx},
$self->{'ProbFrame'}));
}
return $self;
}
sub rsh {
my $self = shift;
if ($::display) {
system "xterm -e rsh $self->{'Name'} -l root &";
}
}
sub selectme {
my $self = shift;
if ($main::hidden) {
main::makeappear();
return;
}
if (exists $self->{'Selected'}) {
main::deselectitem($self);
delete $self->{'Selected'};
} else {
main::selectitem($self);
$self->{'hostlabel'}->configure(-foreground => "red");
$self->{'Selected'} = 1;
}
}
sub deselectme {
my $self = shift;
$self->{'hostlabel'}->configure(-foreground => "black");
delete $self->{'Selected'};
}
sub fix {
my $self = shift;
if (! exists $self->{'Down'}) {
foreach $i (@{$self->{'Problems'}}) {
if ($i->canfix() && ref($i) ne Host) {
$i->fix();
}
}
}
}
sub seenall {
my $self = shift;
foreach $i (@{$self->{'Problems'}}) {
if (ref($i) ne Host) {
$i->haveseen();
}
}
}
sub canfix {
return 1;
}
sub hostdown {
my $self = shift;
$self->deleteProbs();
push(@{$self->{'Problems'}},$self);
$self->{'Down'} = 1;
if ($::display) {
if (!exists $self->{'hostlabel'}) {
$self->{'hostlabel'} =
$self->{'MainFrame'}->Button(-text => sprintf("%-9.9s",
$self->{'Name'}),
-bd => 0, -padx => 0, -pady => 0,
-command =>[\&selectme,$self],
-activeforeground => 'red',
-activebackground => '#C9C9C9',
-width => 9,
-anchor => "w",
-relief => "flat");
}
::addToLog("$self->{'Name'} is down",2);
$self->{'hostlabel'}->configure(-text =>
sprintf("%-9.9s down",$self->{'Name'}),
-width => 14);
}
}
sub check {
my $self = shift;
$self->{'noDelete'} = 1;
$self->deleteProbs();
delete $self->{'noDelete'};
if ($::display) {
$self->{'hostlabel'}->configure(-text => $self->{'Name'},-width=>9);
}
delete $self->{'Down'};
main::setstatus("pinging $self->{'Name'}");
if (!($::pinghost) || Net::Ping::pingecho($self->{'Name'},2)) {
foreach $i (@{$self->{'Mibs'}}) {
if (ref($i) ne Mib) {
print "$i is a ref($i) not a Mib\n";
} else {
main::setstatus("Checking $self->{'Name'}: " . $i->{'MibDesc'});
push(@{$self->{'Problems'}},$i->check());
}
if (exists $self->{'Down'}) {
last;
}
}
} else {
$self->hostdown();
}
main::setstatus("Idle");
if ($#{$self->{'Problems'}} == -1) {
$self->deleteme();
}
}
sub deleteme {
my $self = shift;
if ($self->{'Selected'}) {
main::deselectitem($self);
}
$self->deleteProbs();
if ($::display) {
$self->{'hostlabel'}->destroy();
$self->{'ProbFrame'}->destroy();
my $top = $self->{'MainFrame'}->toplevel;
$self->{'MainFrame'}->destroy();
$top->update;
}
main::deletehost($self->{'Name'});
}
sub deleteProbs {
my $self = shift;
foreach $i (@{$self->{'Problems'}}) {
if (ref($i) eq Host) {
delete $self->{'Problems'};
return;
}
if (ref($i) ne Problem && ref($i) ne FixProblem) {
print "i: $i is a ", ref($i), "\n";
next;
}
$self->deleteProb($i);
}
}
sub deleteProb {
my $self = shift;
my $child = shift;
for ($k = 0; $k <= $#{$self->{'Problems'}}; $k++) {
if (ref($self->{'Problems'}->[$k]) eq Problem ||
ref($self->{'Problems'}->[$k]) eq FixProblem ) {
if ($self->{'Problems'}->[$k]->{'Mib'} eq $child->{'Mib'} &&
$self->{'Problems'}->[$k]->{'MibLocation'} eq
$child->{'MibLocation'}) {
splice(@{$self->{'Problems'}},$k,1);
$child->deleteself();
if ($#{$self->{'Problems'}} == -1 &&
!exists $self->{'noDelete'}) {
$self->deleteme();
}
last;
}
} else {
print " not: ",$self->{'Problems'}->[$k],"/",
ref($self->{'Problems'}->[$k]),"\n";
}
}
}
package main;
#
# Read arguments
#
if ($#ARGV != -1) {
while ($#ARGV >= 0 && $ARGV[0] =~ /^-/) {
$_ = shift;
$andlog = 1 if (/^-a/);
$dontstart = 1 if (/^-d/);
$fixit = -1 if (/^-n/);
$fixit = 1 if (/^-y/);
$display = 0 if (/^-x/);
$pinghost = 1 if (/^-p/);
$hidden = 1 if (/^-H/);
$loglevel = shift if (/^-V/);
$logwindowatstart = 1 if (/^-L/);
&display_help() if (/^-h/);
&setmibchecklist(@fixitlist) if (/^-f/);
}
}
#
# If necessary check the ece-log file for problems
#
if (($andlog || $#ARGV == -1) && !$dontstart) {
open(LOG,$errlog);
while (<LOG>) {
@fields = split;
@tmp = grep(/$fields[0]/,@ARGV);
if ($#tmp == -1) { # && $fields[1] ne "down") {
$ARGV[$#ARGV + 1] = $fields[0];
}
}
close(LOG);
}
#
# Check all the found hosts
#
if ($display) {
use Tk;
# $tk_strictMotif = 1;
$top = MainWindow->new();
$top->bind('all',"<Control-q>",[\&quit]);
$top->bind('all',"<Control-h>",[\&makehidden]);
$top->bind('all',"<Control-s>",[\&seenall]);
$top->bind('all',"<Control-f>",[\&fixall]);
$top->option('add','*highlightThickness','0'); #wish this worked
# $top->option('add','*highlightbackground','#C9C9C9');
$top->option('add','*background','#C9C9C9');
$top->option('add','*font','6x13');
$HostFrame = $top->Frame();
$MenuFrame = $top->Frame(-relief => "raised",-borderwidth => 2);
$MenuFrame->pack(-fill => "x",-expand => 1);
$statusBar = $top->Frame(-relief => "raised",-borderwidth => 2);
$status = $statusBar->Label(-text => "initializing",-anchor =>"e");
$statusl = $statusBar->Label(-text => "Status: ", -anchor => "w");
$msgBar = $top->Frame(-relief => "raised",-borderwidth => 2);
$msg = $msgBar->Label(-text => "",-anchor =>"e");
$msgl = $msgBar->Label(-text => "Note: ", -anchor => "w");
$botFrame = $top->Frame();
$butFrame = $top->Frame();
$entryhost = "";
$NewHost = $botFrame->Entry(-textvariable => \$entryhost,-width=>20,
-relief => "sunken");
$NewHost->bind("<Return>",sub {newHost("$entryhost");
$NewHost->delete(0,length($entryhost));});
$BotLabel = $botFrame->Label(-text => "Check New Host: ",
-anchor => "w");
$CmdsMenuBut = $MenuFrame->Menubutton(-text => "Cmds");
$CmdsMenu = $CmdsMenuBut->Menu(-tearoff => 1);
$CmdsMenuBut->configure(-menu => $CmdsMenu);
$CmdsMenuBut->pack(-side => "left");
$CmdsMenuBut->command(-label => "Check Hosts", -command => [\&rescanhosts]);
$CmdsMenuBut->command(-label => "Check Log", -command => [\&scanlog]);
$CmdsMenuBut->command(-label => "Fix All", -command => [\&fixall],
-accelerator => "Ctrl-f");
$CmdsMenuBut->command(-label => "Seen All", -command => [\&seenall],
-accelerator => "Ctrl-s");
$CmdsMenuBut->separator();
$CmdsMenuBut->command(-label => "Hide", -command => [\&makehidden],
-accelerator => "Ctrl-h");
$CmdsMenuBut->command(-label => "Quit", -command => [\&quit],
-accelerator => "Ctrl-q");
$PrefsMenuBut = $MenuFrame->Menubutton(-text => "Prefs");
$PrefsMenu = $PrefsMenuBut->Menu(-tearoff => 1);
$PrefsMenuBut->configure(-menu => $PrefsMenu);
$PrefsMenuBut->pack(-side => "left");
$PrefsMenuBut->cascade(-label => "Rescan");
$RescanPrefsBut = $PrefsMenu->Menu();
$PrefsMenuBut->entryconfigure("Rescan",-menu => $RescanPrefsBut);
$AutoRescan = 1;
if ($AutoRescan) {
$afterId = Tk::after($rescanWhen*1000,[\&autorescan]);
}
$RescanPrefsBut->checkbutton(-label =>"Auto Rescan",
-variable =>\$AutoRescan,
-command => sub {if ($AutoRescan) {
$afterId =
Tk::after($rescanWhen*1000,[\&autorescan])
} else {
Tk::after("cancel",$afterId);
}});
$AutoCheckLog = 1;
$RescanPrefsBut->checkbutton(-label =>"Checks Log",
-variable =>\$AutoCheckLog);
$AutoCheckHosts = 0;
$RescanPrefsBut->checkbutton(-label =>"Checks Hosts",
-variable =>\$AutoCheckHosts);
$RescanWhenHidden = 1;
$RescanPrefsBut->checkbutton(-label =>"Only When Hidden",
-variable =>\$RescanWhenHidden);
$RescanPrefsBut->checkbutton(-label =>"Pop forward with new",
-variable =>\$raiseonnew);
$PrefsMenuBut->cascade(-label => "Log Verbosity");
$LogVerbBut = $PrefsMenu->Menu();
$PrefsMenuBut->entryconfigure("Log Verbosity",
-menu => $LogVerbBut);
for ($i=1; $i <= $numloglevels; $i++) {
$LogVerbBut->radiobutton(-label => "$i", -variable => \$loglevel,
-value => $i);
}
$PrefsMenuBut->cascade(-label => "Check For");
$CheckForBut = $PrefsMenu->Menu();
$PrefsMenuBut->entryconfigure("Check For",
-menu => $CheckForBut);
$CheckForBut->command(-label => "Fixable Problems",
-command => [\&setmibchecklist,@fixitlist]);
$CheckForBut->command(-label => "Everything",
-command => [\&setmibchecklist,keys(%miblist)]);
$CheckForBut->separator();
foreach $i ( sort mibsort keys(%::mibchecklist) ) {
$CheckForBut->checkbutton(-label => $miblist{$i},
-variable => \$mibchecklist{$i});
}
$PrefsMenuBut->checkbutton(-label => "Ping Host First",
-variable => \$pinghost);
# Agent control
$agentMenuBut = $MenuFrame->Menubutton(-text => "Agent-Control");
$agentMenu = $agentMenuBut->Menu(-tearoff => 1);
$agentMenuBut->configure(-menu => $agentMenu);
$agentMenuBut->pack(-side => "left");
$agentMenuBut->command(-label => "Re-read Configuration",
-command => [sub {if ($selected) { $top->Busy();
my $args = sprint($::default_get_args, $selected->{'Host'});
$_ = `$::snmppath/snmpset $args $mibupdateconfig i 1`; $top->Unbusy();}}]);
$agentMenuBut->command(-label => "Clear Exec Cache",
-command => [sub {if ($selected) { $top->Busy();
my $args = sprint($::default_get_args, $selected->{'Host'});
$_ = `$::snmppath/snmpset $args $mibclearcache i 1`; $top->Unbusy();}}]);
$agentMenuBut->separator();
$agentMenuBut->command(-label => "Re-start Agent",
-command => [sub {if ($selected) { $top->Busy();
my $args = sprint($::default_get_args, $selected->{'Host'});
$_ = `$::snmppath/snmpset $args $mibrestartagent i 1`; $top->Unbusy();} }]);
# set up remote commands
$remoteMenuBut = $MenuFrame->Menubutton(-text => "Remote-Info");
$remoteMenu = $remoteMenuBut->Menu(-tearoff => 1);
$remoteMenuBut->configure(-menu => $remoteMenu);
$remoteMenuBut->pack(-side => "left");
$remoteMenuBut->command(-label => "Load-Av", -command => [\&remote_load]);
$remoteMenuBut->separator();
$remoteMenuBut->command(-label => "top", -command => [\&remote_cmd,"top"]);
$remoteMenuBut->command(-label => "mailq", -command => [\&remote_cmd,"mailq"]);
$remoteMenuBut->command(-label => "ps", -command => [\&remote_cmd,"ps"]);
$remoteMenuBut->command(-label => "conf", -command => [\&remote_cmd,"conf"]);
# set up log file menu
$logFileMenuBut = $MenuFrame->Menubutton(-text => "Log");
$logFileMenu = $logFileMenuBut->Menu(-tearoff => 1);
$logFileMenuBut->configure(-menu => $logFileMenu);
$logFileMenuBut->pack(-side => "left");
$logFileMenuBut->command(-label => "show log", -command => [\&displayLog]);
$logFileMenuBut->command(-label => "clear log", -command => [\&clearLog]);
$logFileMenuBut->separator();
$logFileMenuBut->command(-label => "show Tyfon's log", -command => [\&displayTyfon]);
# set up status bar
$statusl->pack(-fill => "x", -expand => 1, -side =>"left");
$status->pack(-fill => "x", -expand => 1, -side =>"left");
$msgl->pack(-fill => "x", -expand => 1, -side => "left");
$msg->pack(-fill => "x", -expand => 1, -side => "left");
$statusBar->pack(-fill => "x", -expand => 1);
$msgBar->pack(-fill => "x", -expand => 1);
$HostFrame->pack(-fill => "x",-expand => 1);
$butFrame->pack(-fill => "x",-expand => 1);
$botFrame->pack(-fill => "x",-expand => 1);
$FixBut = $butFrame->Button(-text => "Fix",-command=>[sub{print "hi\n"}],
-state => "disabled");
$FixBut->pack(-side => "left",-padx => 4,-pady => 2,-ipadx => 2,
-ipady => 2);
$RshBut = $butFrame->Button(-text => "Rsh",-command=>[sub{print "hi\n"}],
-state => "disabled");
$RshBut->pack(-side => "left",-padx => 4,-pady => 2,-ipadx => 2,
-ipady => 2);
$DelBut = $butFrame->Button(-text => "Del",
-state => "disabled");
$DelBut->pack(-side => "left",-padx => 4,-pady => 2,-ipadx => 2,
-ipady => 2);
$ChkBut = $butFrame->Button(-text => "Chk",
-state => "disabled");
$ChkBut->pack(-side => "left",-padx => 4,-pady => 2,-ipadx => 2,
-ipady => 2);
$BotLabel->pack(-fill => "x",-expand => 1,-side=>"left");
$NewHost->pack(-side=>"left");
&makehidden() if ($hidden);
$top->update();
# generate log window, but tell it not to create display
$logwindow = MainWindow->new;
$logwindow->option('add','*highlightThickness','0'); #wish this worked
# $logwindow->option('add','*highlightbackground','#C9C9C9');
$logwindow->option('add','*background','#C9C9C9');
$logwindow->option('add','*font','6x13');
$logbuttons = $logwindow->Frame;
$logbuttons->pack(-side => 'bottom', -expand => 1, -fill => 'x');
$logclose = $logbuttons->Button(-text => 'Close',
-command => ['withdraw',$logwindow]);
$logclose->pack(-side => 'left', -expand => 1);
$logtext = $logwindow->Text(-height => 40, -setgrid => 1);
$logtext->pack(-side => 'left', -fill => 'both', -expand => 1);
$logscroll = $logwindow->Scrollbar(-command => ['yview',$logtext]);
$logscroll->pack(-side => 'right', -fill => 'y');
$logtext->configure(-yscrollcommand => ['set', $logscroll]);
$logwindow->title("snmpcheck Action Log file");
$logwindow->iconname("snmpcheck-log");
$logtext->delete('1.0','end');
$logclear = $logbuttons->Button(-text => 'Clear Log',
-command => [\&deleteLog]);
$logclear->pack(-side => 'right', -expand => 1);
if (! $logwindowatstart) {
$logwindow->withdraw;
}
$status->configure(-text => "Idle");
$selected = 0;
# fill table with hosts
if (!$dontstart) {
loadAllHosts(@ARGV);
}
MainLoop;
}
else {
select(STDOUT);
$| = 1;
if ($::fixit == 0) {
Term::ReadKey::ReadMode(3);
}
loadAllHosts(@ARGV);
printf("$eraseline");
}
sub loadAllHosts {
my @hostlist = @_;
foreach $host ( @hostlist ) {
newHost($host);
}
}
sub newHost {
my $name = shift;
if (!exists $chost{"$name"}) {
$chost{"$name"} = new Host ($name);
if ($::display) { $top->update(); }
$chost{"$name"}->check;
} else {
setmsg("$name all ready exists");
}
}
sub deletehost {
my $name = shift;
delete $chost{"$name"};
}
sub setstatus {
my $arg = shift;
if ($display) {
$status->configure(-text => $arg);
$top->update();
addToLog($arg,4);
}
}
sub setmsg {
my $arg = shift;
if ($display) {
$msg->configure(-text => $arg);
$top->update();
addToLog($arg);
}
}
sub addToLog {
if ($display) {
my $logmsg = shift;
my $logaddlevel = shift;
if (! defined($logaddlevel)) {
$logaddlevel = 1;
}
if ($logaddlevel <= $loglevel) {
$logtext->insert('end'," " x ($logaddlevel-1) . "$logmsg\n");
}
}
}
sub displayTyfon {
remote_cmd_generic("cat /net/tyfon/1/OV/log/ece-log","Tyfon -- ece-log");
}
sub displayLog {
$logwindow->deiconify;
$logwindow->raise;
}
sub deleteLog {
$logtext->delete('1.0','end');
}
sub deselectitem {
$obj = shift;
$obj->deselectme();
$FixBut->configure(-state => "disabled");
$RshBut->configure(-state => "disabled");
$DelBut->configure(-state => "disabled");
$ChkBut->configure(-state => "disabled");
$selected = 0;
}
sub selectitem {
if ($selected) {
$selected->deselectme();
}
$selected = shift;
if (ref($selected) ne Host || !(exists $selected->{'Down'})) {
$RshBut->configure(-state => "normal", -command => ['rsh',$selected]);
} else {
$RshBut->configure(-state => "disabled");
}
$DelBut->configure(-state => "normal", -command => ['deleteme',$selected]);
$ChkBut->configure(-state => "normal", -command => ['check',$selected]);
if ($selected->canfix() && !(exists $selected->{'Down'})) {
$FixBut->configure(-state => "normal",
-command => ['fix',$selected]);
} else {
$FixBut->configure(-state => "disabled");
}
if ($hidden == 1) {
makeappear();
}
}
sub makehidden {
$MenuFrame->pack("forget");
$statusBar->pack("forget");
$msgBar->pack("forget");
$butFrame->pack("forget");
$botFrame->pack("forget");
flatten();
$hidden=1;
}
sub makeappear {
$HostFrame->pack("forget");
$MenuFrame->pack(-expand => 1, -fill => "x");
$statusBar->pack(-expand => 1, -fill => "x");
$msgBar->pack(-expand => 1, -fill => "x");
$HostFrame->pack(-expand => 1, -fill => "x");
$butFrame->pack(-expand => 1, -fill => "x");
$botFrame->pack(-expand => 1, -fill => "x");
reliefen();
$hidden=0;
}
sub quit {
$top->destroy();
exit();
}
sub scanlog {
my (@fields, @tmp);
open(LOG,$::errlog);
while (<LOG>) {
@fields = split;
@tmp = grep(/$fields[0]/,@ARGV);
if ($#tmp == -1 && !exists $::chost->{$fields[0]}) {
newHost($fields[0]);
}
}
close(LOG);
}
sub rescanhosts {
foreach $i (keys(%chost)) {
$chost{$i}->check();
}
}
sub autorescan {
$afterId = Tk::after($rescanWhen*1000,[\&autorescan]);
if ($RescanWhenHidden && !$hidden) {return;}
if ($AutoCheckHosts) {
rescanhosts();
}
if ($AutoCheckLog) {
scanlog();
}
}
sub flatten {
foreach $i (keys(%chost)) {
$chost{$i}->{'MainFrame'}->configure(-relief => "flat",-borderwidth=>0);
}
}
sub reliefen {
foreach $i (keys(%chost)) {
$chost{$i}->{'MainFrame'}->configure(-relief =>"sunken",-borderwidth=>2);
}
}
sub fixall {
foreach $i (keys(%chost)) {
$chost{$i}->fix();
}
}
sub seenall {
foreach $i (keys(%chost)) {
$chost{$i}->seenall();
}
}
sub remote_cmd {
my $type = shift;
if ($selected) {
remote_cmd_generic("$::snmppath/rsnmp -p $type $selected->{'Host'}",
"$selected->{'Host'} -- $type",1);
} else {
setmsg("Error: Nothing selected");
}
}
sub remote_load {
if ($selected) {
remote_cmd_generic("$::snmppath/snmpwalk " . sprintf($::default_get_args,$selected->{'Host'}) . " .EXTENSIBLEDOTMIB.LOADAVEMIBNUM.LOADAVE",
"$selected->{'Host'} -- LoadAve");
} else {
setmsg("Error: Nothing selected");
}
}
sub remote_cmd_generic {
my $cmd = shift;
my $title = shift;
my $insert = shift;
addToLog("running: $cmd ... ");
my $newwin = MainWindow->new;
$newwin->Busy();
$newwin->option('add','*highlightThickness','0'); #wish this worked
# $newwin->option('add','*highlightbackground','#C9C9C9');
$newwin->option('add','*background','#C9C9C9');
$newwin->option('add','*font','6x13');
my $buttons = $newwin->Frame;
$buttons->pack(-side => 'bottom', -expand => 1, -fill => 'x');
my $entries = $newwin->Frame;
$entries->pack(-side => 'bottom', -expand => 1, -fill => 'x');
my $text = $newwin->Text(-height => 40, -setgrid => 1);
$text->pack(-side => 'left', -fill => 'both', -expand => 1);
my $scroll = $newwin->Scrollbar(-command => ['yview',$text]);
$scroll->pack(-side => 'left', -fill => 'y');
$text->configure(-yscrollcommand => ['set', $scroll]);
my $close = $buttons->Button(-text => 'Close',
-command => ['destroy',$newwin]);
$close->pack(-side => 'left', -expand => 1);
my $rerun = $buttons->Button(-text => 'Re-Run',
-command=>[\&fill_text,'',$text,
\$cmd,$insert]);
$rerun->pack(-side => 'left', -expand => 1);
my $cmdlabel = $entries->Label(-text => "Command: ");
my $cmdtexte = $entries->Entry(-textvariable => \$cmd,
-relief => "sunken");
$cmdtexte->bind('<Return>' => [\&fill_text,$text, \$cmd,$insert]);
$cmdlabel->pack(-side => 'left');
$cmdtexte->pack(-side => 'left');
my $searchtext = '';
my $searchlabel = $entries->Label(-text => "Search for: ");
my $searchtexte = $entries->Entry(-textvariable => \$searchtext,
-relief => "sunken");
$searchtexte->pack(-side => 'right');
$searchlabel->pack(-side => 'right');
$searchtexte->bind('<Return>' => [sub { $text->tag('remove','search','0.0','end');
my($current, $length) = ('1.0', 0);
while (1) {
$current = $text->search(-count => \$length, $searchtext, $current, 'end');
last if not $current;
$text->tag('add', 'search', $current, "$current + $length char");
$current = $text->index("$current + $length char");
$text->tag('configure','search',
-background =>
'lightBlue');}}]);
if (defined($title)) {
$newwin->title($title);
$newwin->iconname($title);
}
fill_text('',$text,\$cmd,$insert);
}
sub fill_text {
my $dump = shift;
my $textw = shift;
my $cmd = shift;
my $insert = shift;
$textw->delete('1.0','end');
if (defined($insert) && $insert) {
$textw->insert('end',"running: $$cmd\n\n");
}
$textw->toplevel->update();
$textw->toplevel->Busy();
open(OUT,"$$cmd|");
while (<OUT>) {
$textw->insert('end',$_);
$textw->toplevel->update();
$textw->toplevel->Busy();
}
close(OUT);
if (defined ($insert) && $insert) {
$textw->insert('end',"\ndone.\n");
}
$textw->toplevel->Unbusy();
$textw->Unbusy();
addToLog("done: $$cmd");
}
sub display_help {
print "
Usage: snmpcheck [-x] [-n|y] [-h] [-H] [-V NUM] [-L] [-f] [[-a] HOSTS]
-h\tDisplay this message.
-a\tcheck error log file AND hosts specified on command line.
-p\tDon't try and ping-echo the host first
-f\tOnly check for things I can fix
HOSTS\tcheck these hosts for problems.
X Options:
-x\tforces ascii base if \$DISPLAY set (instead of tk).
-H\tstart in hidden mode. (hides user interface)
-V NUM\tsets the initial verbosity level of the command log (def: 1)
-L\tShow the log window at startup
-d\tDon't start by checking anything. Just bring up the interface.
Ascii Options:
-n\tDon't ever try and fix the problems found. Just list.
-y\tAlways fix problems found.
";
exit(0);
}
sub option_get {
my $resource = shift;
return $top->option('get',$resource);
}
sub option_set {
my $resource = shift;
my $value = shift;
$top->option('add',"*$resource",$value);
}
sub option_save {
}
sub mibsort {
$_ = $a;
($av) = /\.([0-9]+)/;
$_ = $b;
($bv) = /\.([0-9]+)/;
return $av <=> $bv;
}
sub setmibchecklist {
my $i;
foreach $i (keys(%mibchecklist)) {
$mibchecklist{$i} = 0;
}
foreach $i (@_) {
$mibchecklist{$i} = 1;
}
}