aboutsummaryrefslogtreecommitdiffstats
path: root/clients/snmpfetchng.pl
blob: 2f5e7855485c9ac9536d02fbb994754cff6169c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use POSIX;
#use Time::HiRes qw(time);
use SNMP;
use Data::Dumper;
use lib '../include';
use nms;

SNMP::initMib();
SNMP::addMibDirs("/srv/tgmanage/mibs/StandardMibs");
SNMP::addMibDirs("/srv/tgmanage/mibs/JuniperMibs");
SNMP::addMibDirs("/srv/tgmanage/mibs");
SNMP::loadModules('ALL');

our $dbh = nms::db_connect();
$dbh->{AutoCommit} = 0;
$dbh->{RaiseError} = 1;

my $qualification = <<"EOF";
(last_updated IS NULL OR now() - last_updated > poll_frequency)
AND (locked='f' OR now() - last_updated > '15 minutes'::interval)
AND mgmt_v4_addr is not null
EOF

# Borrowed from snmpfetch.pl 
our $qswitch = $dbh->prepare(<<"EOF")
SELECT 
  sysname,switch,host(mgmt_v4_addr) as ip,community,
  DATE_TRUNC('second', now() - last_updated - poll_frequency) AS overdue
FROM
  switches
WHERE
$qualification
ORDER BY
  overdue DESC
LIMIT ?
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";
my @switches = ();

my $sth = $dbh->prepare("INSERT INTO snmp (switch,data) VALUES((select switch from switches where sysname=?), ?)");

sub mylog
{
	my $msg = shift;
	my $time = POSIX::ctime(time);
	$time =~ s/\n.*$//;
	printf STDERR "[%s] %s\n", $time, $msg;
}

sub populate_switches
{
	@switches = ();
	my $limit = $nms::config::snmp_max;
	$qswitch->execute($limit)
		or die "Couldn't get switch";
	$dbh->commit;
	while (my $ref = $qswitch->fetchrow_hashref()) {
		push @switches, {
			'sysname' => $ref->{'sysname'},
			'id' => $ref->{'switch'},
			'mgtip' => $ref->{'ip'},
			'community' => $ref->{'community'}
		};
	}
}

sub inner_loop
{
	populate_switches();
	my $poll_todo = "";
	for my $refswitch (@switches) {
		my %switch = %{$refswitch};
		$poll_todo .= "$switch{'sysname'} ";

		$switch{'start'} = time;
		$qlock->execute($switch{'id'})
			or die "Couldn't lock switch";
		$dbh->commit;
		my $s = SNMP::Session->new(DestHost => $switch{'mgtip'},
					  Community => $switch{'community'},
					  UseEnums => 1,
					  Version => '2');
		my $ret = $s->bulkwalk(0, 10, @nms::config::snmp_objects, sub{ callback(\%switch, @_); });
		if (!defined($ret)) {
			mylog("Fudge: ".  $s->{'ErrorStr'});
		}
	}
	mylog( "Polling " . @switches . " switches: $poll_todo");
	SNMP::MainLoop(10);
}

sub callback{
	my @top = $_[1];
	my %switch = %{$_[0]};
	my %tree;
	my %ttop;
	my %nics;
	my @nicids;

	for my $ret (@top) {
		for my $var (@{$ret}) {
			for my $inner (@{$var}) {
				my ($tag,$type,$name,$iid, $val) = ( $inner->tag ,$inner->type , $inner->name, $inner->iid, $inner->val);
				if ($tag eq "ifPhysAddress") {
					next;
				}
				$tree{$iid}{$tag} = $val;
				if ($tag eq "ifIndex") {
					push @nicids, $iid;
				}
			}
		}
	}

	my %tree2;
	for my $nic (@nicids) {
		$tree2{'ports'}{$tree{$nic}{'ifName'}} = $tree{$nic};
		delete $tree{$nic};
	}
	for my $iid (keys %tree) {
		for my $key (keys %{$tree{$iid}}) {
			$tree2{'misc'}{$key}{$iid} = $tree{$iid}{$key};
		}
	}
	$sth->execute($switch{'sysname'}, JSON::XS::encode_json(\%tree2));
	$qunlock->execute($switch{'id'})
		or die "Couldn't unlock switch";
	$dbh->commit;
	mylog( "Polled $switch{'sysname'} in " . (time - $switch{'start'}) . "s.");
}
while (1) {
	inner_loop();
}