diff options
Diffstat (limited to 'clients/snmpfetch.pl')
-rwxr-xr-x | clients/snmpfetch.pl | 256 |
1 files changed, 0 insertions, 256 deletions
diff --git a/clients/snmpfetch.pl b/clients/snmpfetch.pl deleted file mode 100755 index a13ef3f..0000000 --- a/clients/snmpfetch.pl +++ /dev/null @@ -1,256 +0,0 @@ -#! /usr/bin/perl -use DBI; -use POSIX; -use Time::HiRes; -use Net::Telnet; -use strict; -use warnings; - -use lib '../include'; -use nms; -use threads; - -our $running = 0; - -our $dbh = nms::db_connect(); -$dbh->{AutoCommit} = 0; -$dbh->{RaiseError} = 1; - -# normal mode: fetch switches from the database -# instant mode: poll the switches specified on the command line -my $instant = defined($ARGV[0]); - -my $qualification; -if ($instant) { - $qualification = "sysname LIKE ?"; -} else { - $qualification = <<"EOF"; -(last_updated IS NULL OR now() - last_updated > poll_frequency) -AND (locked='f' OR now() - last_updated > '5 minutes'::interval) -AND ip is not null -EOF -} - -our $qswitch = $dbh->prepare(<<"EOF") -SELECT - *, - DATE_TRUNC('second', now() - last_updated - poll_frequency) AS overdue -FROM - switches - NATURAL LEFT JOIN switchtypes -WHERE $qualification -ORDER BY - priority DESC, - overdue DESC -LIMIT 1 -FOR UPDATE OF switches -EOF - or die "Couldn't prepare qswitch"; -our $qlock = $dbh->prepare("UPDATE switches SET locked='t', last_updated=now() WHERE switch=?") - or die "Couldn't prepare qlock"; -our $qunlock = $dbh->prepare("UPDATE switches SET locked='f', last_updated=now() WHERE switch=?") - or die "Couldn't prepare qunlock"; -our $qpoll = $dbh->prepare("INSERT INTO polls (time, switch, port, bytes_in, bytes_out, errors_in, errors_out, official_port,operstatus,ifdescr) VALUES (timeofday()::timestamp,?,?,?,?,?,?,true,?,?)") - or die "Couldn't prepare qpoll"; - -poll_loop(@ARGV); -while ($running > 0) { - SNMP::MainLoop(0.1); -} - -sub poll_loop { - my @switches = @_; - my $instant = (scalar @switches > 0); - my $timeout = 15; - - while (1) { - my $sysname; - if ($instant) { - $sysname = shift @ARGV; - return if (!defined($sysname)); - $qswitch->execute('%'.$sysname.'%') - or die "Couldn't get switch"; - } else { - # Find a switch to grab - $qswitch->execute() - or die "Couldn't get switch"; - } - my $switch = $qswitch->fetchrow_hashref(); - - if (!defined($switch)) { - $dbh->commit; - - if ($instant) { - mylog("No such switch $sysname available, quitting."); - return; - } else { - mylog("No available switches in pool, sleeping."); - SNMP::MainLoop(1.0); - next; - } - } - - $qlock->execute($switch->{'switch'}) - or die "Couldn't lock switch"; - $dbh->commit; - - if ($switch->{'locked'}) { - mylog("WARNING: Lock timed out on $switch->{'ip'}, breaking lock"); - } - - my $msg; - if (defined($switch->{'overdue'})) { - $msg = sprintf "Polling ports %s on %s (%s), %s overdue.", - $switch->{'ports'}, $switch->{'ip'}, $switch->{'sysname'}, $switch->{'overdue'}; - } else { - $msg = sprintf "Polling ports %s on %s (%s), never polled before.", - $switch->{'ports'}, $switch->{'ip'}, $switch->{'sysname'}; - } - mylog($msg); - - my $ip = $switch->{'ip'}; - if ($ip eq '127.0.0.1') { - mylog("Polling disabled for this switch, skipping."); - $qunlock->execute($switch->{'switch'}) - or die "Couldn't unlock switch"; - $dbh->commit; - next; - } - - my $community = $switch->{'community'}; - my $start = [Time::HiRes::gettimeofday]; - my $session; - eval { - $session = nms::snmp_open_session($ip, $community, 1); - }; - if ($@) { - warn "Couldn't open session (even an async one!) to $ip: $!"; - $qunlock->execute($switch->{'switch'}) - or die "Couldn't unlock switch"; - $dbh->commit; - next; - }; - my @ports = expand_ports($switch->{'ports'}); - - my $switch_status = { - session => $session, - ip => $switch->{'ip'}, - sysname => $switch->{'sysname'}, - switch => $switch->{'switch'}, - num_ports => scalar @ports, - num_done => 0, - start => $start, - }; - - for my $port (@ports) { - my @vars = (); - push @vars, ["ifInOctets", $port]; - push @vars, ["ifOutOctets", $port]; - push @vars, ["ifInErrors", $port]; - push @vars, ["ifDescr", $port]; - push @vars, ["ifOutErrors", $port]; - push @vars, ["ifOperStatus", $port]; - my $varlist = SNMP::VarList->new(@vars); - $session->get($varlist, [ \&callback, $switch_status, $port ]); - } - $running++; - - $dbh->rollback; - } -} - -sub expand_ports { - my $in = shift; - my @ranges = split /,/, $in; - my @ret = (); - - for my $range (@ranges) { - if ($range =~ /^\d+$/) { - push @ret, $range; - } elsif ($range =~ /^(\d+)-(\d+)$/) { - for my $i ($1..$2) { - push @ret, $i; - } - } else { - die "Couldn't understand '$range' in ports"; - } - } - - return (sort { $a <=> $b } @ret); -} - -sub mylog { - my $msg = shift; - my $time = POSIX::ctime(time); - $time =~ s/\n.*$//; - printf STDERR "[%s] %s\n", $time, $msg; -} - -sub callback { - my ($switch, $port, $vars) = @_; - - my ($in, $out, $ine, $oute) = (undef, undef, undef, undef); - my $operstatus = 2; - my $ifdescr = undef; - - for my $var (@$vars) { - if ($port != $var->[1]) { - die "Response for unknown OID $var->[0].$var->[1] (expected port $port)"; - } - if ($var->[0] eq 'ifInOctets') { - $in = $var->[2]; - } elsif ($var->[0] eq 'ifOutOctets') { - $out = $var->[2]; - } elsif ($var->[0] eq 'ifInErrors') { - $ine = $var->[2]; - } elsif ($var->[0] eq 'ifOutErrors') { - $oute = $var->[2]; - } elsif ($var->[0] eq 'ifOperStatus') { - $operstatus = $var->[2]; - } elsif ($var->[0] eq 'ifDescr') { - $ifdescr = $var->[2]; - } else { - die "Response for unknown OID $var->[0].$var->[1]"; - } - } - - my $ok = 1; - if (!defined($in) || $in !~ /^\d+$/) { - if (defined($ine)) { - warn $switch->{'sysname'}.":$port: failed reading in ($ine)" . (defined($in) ? ": $in" : ""); - } - $ok = 0; - } - if (!defined($out) || $out !~ /^\d+$/) { - if (defined($oute)) { - warn $switch->{'sysname'}.":$port: failed reading out ($oute)" . (defined($out) ? ": $out" : ""); - } - $ok = 0; - } - if (!defined($ifdescr)) { - warn $switch->{'sysname'}.":$port: failed reading ifdescr"; - $ok = 0; - } elsif ($ifdescr =~ m/\./) { - # Skip virtual ports - $ok = 0; - } - - if ($ok) { - $qpoll->execute($switch->{'switch'}, $port, $in, $out, $ine, $oute,$operstatus,$ifdescr) || die "%s:%s: %s\n", $switch->{'switch'}, $port, $in; - $dbh->commit; - } else { - warn $switch->{'sysname'} . " failed to OK."; - } - - if (++$switch->{'num_done'} == $switch->{'num_ports'}) { - --$running; - - my $elapsed = Time::HiRes::tv_interval($switch->{'start'}); - my $msg = sprintf "Polled $switch->{'ip'} in %5.3f seconds.", $elapsed; - mylog($msg); - - $qunlock->execute($switch->{'switch'}) - or warn "Couldn't unlock switch"; - $dbh->commit; - } -} |