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
|
package FS::part_export::broadband_snmp_get;
use strict;
use vars qw(%info $DEBUG);
use base 'FS::part_export';
use SNMP;
use Tie::IxHash;
tie my %snmp_version, 'Tie::IxHash',
v1 => '1',
v2c => '2c'
# v3 unimplemented
;
tie my %options, 'Tie::IxHash',
'snmp_version' => {
label=>'SNMP version',
type => 'select',
options => [ keys %snmp_version ],
},
'snmp_community' => { 'label'=>'Community', 'default'=>'public' },
'snmp_timeout' => { label=>'Timeout (seconds)', 'default'=>1 },
'snmp_oid' => { label=>'Object ID', multiple=>1 },
'snmp_oid_name' => { label=>'Object Name', multiple=>1 },
;
%info = (
'svc' => 'svc_broadband',
'desc' => 'Enable interface display of realtime SNMP get requests to service IP address',
'config_element' => '/edit/elements/part_export/broadband_snmp_get.html',
'options' => \%options,
'no_machine' => 1,
'notes' => <<'END',
Display broadband service status information via SNMP. Timeout is
per object, and should be small enough for realtime use. This export takes no action
during provisioning itself; it is expected that snmp will be separately
configured on the service machine.
END
);
sub export_insert { ''; }
sub export_replace { ''; }
sub export_delete { ''; }
sub export_suspend { ''; }
sub export_unsuspend { ''; }
=pod
=head1 NAME
FS::part_export::broadband_snmp_get
=head1 SYNOPSIS
Configuration for realtime snmp requests to svc_broadband IP address
=head1 METHODS
=cut
=over 4
=item snmp_results SVC
Request statistics from SVC ip address. Returns an array of hashrefs with keys
error - error message
objectID - dotted decimal fully qualified OID
label - leaf textual identifier (e.g., 'sysDescr')
values - arrayref of arrayrefs describing values, [<obj>, <iid>, <val>, <type>]
=cut
sub snmp_results {
my ($self, $svc) = @_;
my $host = $svc->ip_addr;
my $comm = $self->option('snmp_community');
my $vers = $self->option('snmp_version');
my $time = ($self->option('snmp_timeout') || 1) * 1000000;
my @oids = split("\n", $self->option('snmp_oid'));
my @oidnames = split("\n", $self->option('snmp_oid_name'));
my %connect = (
'DestHost' => $host,
'Community' => $comm,
'Version' => $vers,
'Timeout' => $time,
);
my $snmp = new SNMP::Session(%connect);
return { 'error' => 'Error creating SNMP session' } unless $snmp;
return { 'error' => $snmp->{'ErrorStr'} } if $snmp->{'ErrorStr'};
my @out;
for (my $i=0; $i <= $#oids; $i++) {
my $oid = $oids[$i];
my $oidname = $oidnames[$i];
$oid = $SNMP::MIB{$oid}->{'objectID'} if $SNMP::MIB{$oid};
my @values;
if ($vers eq '1') {
my $varbind = new SNMP::Varbind [$oid];
my $max = 1000; #sanity check
while ($max > 0 and defined($snmp->getnext($varbind))) {
last if $snmp->{'ErrorStr'};
last unless $SNMP::MIB{$varbind->[0]}; # does this happen?
my $nextoid = $SNMP::MIB{$varbind->[0]}->{'objectID'};
last unless $nextoid =~ /^$oid/;
$max--;
push @values, [ @$varbind ];
}
} else {
# not clear on what max-repeaters (25) does, plucked value from example code
# but based on testing, it isn't capping number of returned values
my ($values) = $snmp->bulkwalk(0,25,$oid);
@values = @$values if $values;
}
if ($snmp->{'ErrorStr'} || !@values) {
push @out, { 'error' => $snmp->{'ErrorStr'} || 'No values retrieved' };
next;
}
my %result = map { $_ => $SNMP::MIB{$oid}{$_} } qw( objectID label );
$result{'name'} = $oidname;
# unbless @values, for ease of JSON encoding
$result{'values'} = [];
foreach my $value (@values) {
push @{$result{'values'}}, [ map { $_ } @$value ];
}
push @out, \%result;
}
return @out;
}
=back
=cut
1;
|