#!/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 () { $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 () { @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',"",[\&quit]); $top->bind('all',"",[\&makehidden]); $top->bind('all',"",[\&seenall]); $top->bind('all',"",[\&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("",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 () { @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('' => [\&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('' => [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 () { $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; } }