Project

General

Profile

testrtr.pl

NodeLocator router poller - Randy Reitz, 12/14/2011 09:07 AM

 
1
#!/usr/bin/perl  
2
# Runs NL_arplist to extract ARP info from all routers in the
3
# MRTG device list
4
# Darryl Wohlt, Fermilab
5
use lib qw(/usr/lib/mrtg2);
6
use SNMP_Session "0.77";
7
use BER "0.77";
8
use SNMP_util "0.77";
9
use Time::localtime;
10
use Time::Local;
11
use Net::Syslog;
12
use lib qw(/home/netadmin/lib);
13
use NL_misc_subs;
14
use NL_arplist;
15
$testing=0;
16
$email = 1;
17
use Env qw(PATH HOME TERM);
18
$FILEPATH = "/home/netadmin/mrtg";
19
$COMPLAIN = 'darryl@fnal.gov';
20
$COMPLAIN2 = 'vbravov@fnal.gov,darryl@fnal.gov';
21
$JTPATH = "/home/netadmin/jobtime";
22
$comstr = qx(head -1 $FILEPATH/in/cs); 
23
chomp $comstr;
24
$syslog = 0; # send messages to syslogHostIP host below (enable=1, disable=0)
25
$syslogHostIP = "131.225.32.24"; # nsrelay.fnal.gov
26
$syslogPrio = "info";
27
$syslogFacility = "local5";
28
$SNMP_Session::set_retries = 1;
29
$SNMP_Session::suppress_warnings = 2;
30
$SNMP_Session::set_timeout = 1;
31
$RtrARPAge = 240; 
32
# Set poll cycle to the number of minutes (in multiples of 5) that
33
# it takes to poll all the routers.  This value defines how
34
# "fresh" an ARP entry is, which influences whether NodeLocator
35
# will consider a MAC-address/IP-address pair as "active".
36
# The routers.db file contains only these short-time entries, while the
37
# routersarchive.db file maintains an ongoing list of entries,
38
# updating them as needed, without aging them out.
39
#$pollcycle = 5;
40
$pollcycle = 10;
41
$ValidAge = $pollcycle * 60; 
42
$errors = "";
43
%nonpublic=();
44
#$nonpublic{"172.16"}=true;
45
#$nonpublic{"172.17"}=true;
46
$nonpublic{"172"}=true;
47
$nonpublic{"10"}=true;
48

    
49
$jobstart = time();
50
$timestamp = qx(date '+%Y-%m-%d %T');  
51
chomp $timestamp; 
52
# Exit if another testrtr job is already running
53
if (open(LOCK,"$FILEPATH/db/testrtr.lock")) {
54
  open (ERRLOG,">>$FILEPATH/logs/testrtr_error.log");
55
  print ERRLOG "($timestamp) Another testrtr already running.\n";
56
  close(ERRLOG);
57
  $errors = "$timestamp Another testrtr already running.\n\n";
58
#  $errors .= qx(tail -55 $FILEPATH/logs/testrtr.log);
59
  $errors .= <<ENDMSG; 
60
testrtr polls all routers for ARP entries, and updates ~/mrtg/db/routers.db
61
It is called by ~/bin/Every5m.  (see netadmin crontab)
62
testrtr runs independently from nextgen-db, and is not a daemon.
63

    
64
If you receive more than two of these messages consecutively (every 5 minutes), then:
65
1. logon to m-s-nodelocator as netadmin (netvpn required) 
66
2. [netadmin@m-s-nodelocator ~]\$ cd mrtg/db
67
3. [netadmin@m-s-nodelocator db]\$ rm testrtr.lock 
68

    
69
testrtr should start on the next 5-minute interval.
70
ENDMSG
71

    
72
  notify($COMPLAIN2, "!!! testrtr.pl encountered problems", $errors) if ($email);
73
  exit;
74
}
75

    
76
# Continue
77
system("touch $FILEPATH/db/testrtr.lock");
78
$slog=new Net::Syslog(SyslogHost=>$syslogHostIP,Facility=>$syslogFacility,Priority=>$syslogPrio) if ($syslog);
79

    
80
open(LOG,">>$FILEPATH/logs/testrtr.log");
81
print LOG "(testrtr) $timestamp Starting.\n"; 
82
close(LOG);
83

    
84
# Read in the current Routers Archive DB or build a new one
85
open INFILE, "$FILEPATH/db/routersarchive.db"  or goto READINFILE;
86
while($line = <INFILE>) {
87
        @fields = split(' ',$line);
88
        $old_router{$fields[0]} = " $fields[1] $fields[2] $fields[3] $fields[4]\n";
89
      }
90
close INFILE;
91

    
92
READINFILE:
93
# Read in the list of routers to poll
94
$select{"cisco_2950"}=0;
95
$select{"cisco_4006"}=0;
96
$select{"cisco_ios"}=0;
97
$select{"cisco_native"}=1;
98
$select{"cisco_router"}=1;
99
$select{"cisco_switch"}=0;
100
$select{"cisco_wism"}=0;
101
$select{"gen_switch"}=0;
102
$select{"juniper_router"}=0;
103
$select{"snmpv1"}=0;
104
open INFILE, "$FILEPATH/in/infile.in"  or die("Couldnt open file infile.in   $!");
105
while($line = <INFILE>) {
106
  chomp $line;
107
  next if (substr($line,0,1) eq "#");
108
  $line =~ s/\s//g;
109
  @fields = split(';',$line);
110
  next if ($fields[2] eq "nopoll");
111
  if ($select{$fields[3]}) {
112
    push @devices, $fields[0];
113
  }
114
  $comstrs{$fields[0]} = $comstr;
115
  if ($fields[4] =~ m/comstr/) {
116
    $f4 = substr($fields[4],7+index($fields[4],"comstr"));
117
    @subf4 = split("\,",$f4);
118
    $comstrs{$fields[0]} = $subf4[0];
119
  }
120
}
121
close INFILE;
122
%MACtcount = ();
123
# Get fresh data from each device and merge it into the old routers DB
124
foreach $dev (@devices) {
125
  $timestamp = qx(date '+%Y-%m-%d %T'); 
126
  chomp $timestamp;
127
  $shortstamp = qx(date '+%Y\/%m\/%d\/%H:%M');
128
  $starttime = time();
129
  $i=0;
130
  @ARPLIST = "";
131
  %MACcount = ();
132
  @ARPLIST = arplist($dev,$comstrs{$dev});
133
  ($devline,$logtext)='';
134
  foreach $devline (@ARPLIST) {
135
    chomp $devline;
136
    next unless (length($devline)>0);
137
    if ($devline =~ /^[NU]/) { #Not reachable, Unknown name, No response 
138
      $logtext = $devline;
139
      $msgtext = "$dev not responding to requests from testrtr ($devline)\n";
140
      if ($syslog) {
141
	if ($logtext =~ "SNMP") {
142
	  $slog->send($msgtext,Priority=>'notice');
143
	} else { # No ping response or Unknown Name, or other
144
	  $slog->send($msgtext,Priority=>'warning'); 
145
	}
146
      }
147
      $msgtext = "($timestamp) $dev not responding to requests from testrtr ($devline)\n";
148
      open(ERRLOG,">>$FILEPATH/logs/testrtr_error.log");
149
      print ERRLOG "$msgtext\n";
150
      close(ERRLOG);
151
      notify($COMPLAIN, "NodeLocator: error(s) while attempting to collect data", $msgtext) if ($email);
152
    } else { 
153
      @fields = split(" ",$devline); 
154
      #       Apparently sometimes we get truncated lines from arplist 
155
      if ($fields[1] && $fields[2] && $fields[3] && $fields[4]) { 
156
	$old_router{$fields[0]} = " $fields[1] $fields[2] $fields[3] $fields[4]\n"; 
157
	$MACcount{$fields[1]}++;  # Tallying MACs to look for multiple occurrances
158
	$i++; 
159
      } 
160
    } 
161
  }
162

    
163
  $endtime = time(); # endtime is used in other code below
164
  $elapsed = $endtime - $starttime;
165
  $logtext = "$i ARP entries processed in $elapsed seconds." unless ($logtext ne ''); 
166
  $timestamp2=qx(date '+%T');  
167
  chomp $timestamp2; 
168
  open(LOG,">>$FILEPATH/logs/testrtr.log");
169
  print LOG "(testrtr) $timestamp $timestamp2 $dev: $logtext\n"; 
170
  close(LOG);
171
}
172

    
173
# Write out the new routers.db and update the archive db
174
open(RTARCOUT, ">$FILEPATH/db/nroutersarchive.db");
175
open(RTOUT, ">$FILEPATH/db/nrouters.db");
176

    
177
foreach $rtentry (keys %old_router) {
178
  $lk = length($rtentry);
179
  next if ($lk == 0);
180
  $ld = length($old_router{$rtentry});
181
  next if ($ld == 0);
182
  @rflds = split(" ",$old_router{$rtentry}); 
183
  next if ($#rflds != 3); # partial record
184
  @rstamp = split('\/', $rflds[3]); 
185
  $yr = $rstamp[0]-1900; 
186
  $mo = $rstamp[1]-1; 
187
  $da = $rstamp[2]; 
188
  @hhmm = split(":",$rstamp[3]); 
189
  $hh = $hhmm[0]; 
190
  $mi = $hhmm[1]; 
191
  if ($mo < 0) {
192
    $errors .= "Bad record: >$rtentry<\n";
193
    next;
194
  }
195
  $rsecs = timelocal(0,$mi,$hh,$da,$mo,$yr); 
196
  $diff = $endtime - $rsecs;
197
  print RTARCOUT "$rtentry$old_router{$rtentry}";
198
  @ipaddr = split(/\./,$rtentry);
199
#  $ipaddrpfix = "$ipaddr[0]\.$ipaddr[1]";
200
  $ipaddrpfix = $ipaddr[0];
201
# If this entry is still active (and public), write it to routers.db as well
202
  unless ($nonpublic{$ipaddrpfix}) {
203
    print RTOUT "$rtentry$old_router{$rtentry}" if ($diff <= $ValidAge);
204
  }
205
}
206
close(RTARCOUT);
207
close(RTOUT);
208

    
209
# Clean up
210
system("mv $FILEPATH/db/nroutersarchive.db $FILEPATH/db/routersarchive.db");
211
system("mv $FILEPATH/db/nrouters.db $FILEPATH/db/routers.db");
212
unlink("$FILEPATH/db/testrtr.lock");
213
$timestamp = qx(date '+%Y-%m-%d %T');   
214
chomp $timestamp;  
215
$tcount = "\n$timestamp\n";
216
$jobend = time(); 
217
$jobtime = $jobend-$jobstart; 
218
$timestamp = qx(date '+%Y-%m-%d %T');    
219
chomp $timestamp;   
220
open(LOG,">>$FILEPATH/logs/testrtr.log"); 
221
print LOG "(testrtr) $timestamp Ending.\n"; 
222
close(LOG);
223
unless ($testing) {
224
  open(JOBTIME,">$JTPATH/testrtr.dat"); 
225
  print JOBTIME "$jobtime\n300\n"; 
226
  close(JOBTIME); 
227
  open(LOGFILE2,">>$FILEPATH/logs/testrtr_jobtime.log");  
228
  print LOGFILE2 "$timestamp $jobtime\n";  
229
  close(LOGFILE2);  
230
}
231
exit;
232