1a8661286c0862430b640ee7ad18ddffbea06900
[freeside.git] / FS / FS / part_export / broadband_snmp_get.pm
1 package FS::part_export::broadband_snmp_get;
2
3 use strict;
4 use vars qw(%info $DEBUG);
5 use base 'FS::part_export';
6 use SNMP;
7 use Tie::IxHash;
8
9 tie my %snmp_version, 'Tie::IxHash',
10   v1  => '1',
11   v2c => '2c'
12   # v3 unimplemented
13 ;
14
15 tie my %options, 'Tie::IxHash',
16   'snmp_version' => {
17     label=>'SNMP version', 
18     type => 'select',
19     options => [ keys %snmp_version ],
20    },
21   'snmp_community' => { 'label'=>'Community', 'default'=>'public' },
22   'snmp_timeout' => { label=>'Timeout (seconds)', 'default'=>1 },
23   'snmp_oid' => { label=>'Object ID', multiple=>1 },
24 ;
25
26 %info = (
27   'svc'     => 'svc_broadband',
28   'desc'    => 'Enable interface display of realtime SNMP get requests to service IP address',
29   'config_element' => '/edit/elements/part_export/broadband_snmp_get.html',
30   'options' => \%options,
31   'no_machine' => 1,
32   'notes'   => <<'END',
33 Display broadband service status information via SNMP.  Timeout is
34 per object, and should be small enough for realtime use.  This export takes no action 
35 during provisioning itself;  it is expected that snmp will be separately
36 configured on the service machine.
37 END
38 );
39
40 sub export_insert { ''; }
41 sub export_replace { ''; }
42 sub export_delete { ''; }
43 sub export_suspend { ''; }
44 sub export_unsuspend { ''; }
45
46 =pod
47
48 =head1 NAME
49
50 FS::part_export::broadband_snmp_get
51
52 =head1 SYNOPSIS
53
54 Configuration for realtime snmp requests to svc_broadband IP address
55
56 =head1 METHODS
57
58 =cut
59
60 =over 4
61
62 =item snmp_results SVC
63
64 Request statistics from SVC ip address.  Returns an array of hashrefs with keys 
65
66 error - error message
67
68 objectID - dotted decimal fully qualified OID
69
70 label - leaf textual identifier (e.g., 'sysDescr')
71
72 values - arrayref of arrayrefs describing values, [<obj>, <iid>, <val>, <type>]
73
74 =cut
75
76 sub snmp_results {
77   my ($self, $svc) = @_;
78   my $host = $svc->ip_addr;
79   my $comm = $self->option('snmp_community');
80   my $vers = $self->option('snmp_version');
81   my $time = ($self->option('snmp_timeout') || 1) * 1000000;
82   my @oids = split("\n", $self->option('snmp_oid'));
83   my %connect = (
84     'DestHost'  => $host,
85     'Community' => $comm,
86     'Version'   => $vers,
87     'Timeout'   => $time,
88   );
89   my $snmp = new SNMP::Session(%connect);
90   return { 'error' => 'Error creating SNMP session' } unless $snmp;
91   return { 'error' => $snmp->{'ErrorStr'} } if $snmp->{'ErrorStr'};
92   my @out;
93   foreach my $oid (@oids) {
94     $oid = $SNMP::MIB{$oid}->{'objectID'} if $SNMP::MIB{$oid};
95     my @values;
96     if ($vers eq '1') {
97       my $varbind = new SNMP::Varbind [$oid];
98       my $max = 1000; #sanity check
99       while ($max > 0 and defined($snmp->getnext($varbind))) {
100         last if $snmp->{'ErrorStr'};
101         last unless $SNMP::MIB{$varbind->[0]}; # does this happen?
102         my $nextoid = $SNMP::MIB{$varbind->[0]}->{'objectID'};
103         last unless $nextoid =~ /^$oid/;
104         $max--;
105         push @values, [ @$varbind ];
106       }
107     } else {
108       # not clear on what max-repeaters (25) does, plucked value from example code
109       # but based on testing, it isn't capping number of returned values
110       my ($values) = $snmp->bulkwalk(0,25,$oid);
111       @values = @$values if $values;
112     }
113     if ($snmp->{'ErrorStr'} || !@values) {
114       push @out, { 'error' => $snmp->{'ErrorStr'} || 'No values retrieved' };
115       next;
116     }
117     my %result = map { $_ => $SNMP::MIB{$oid}{$_} } qw( objectID label );
118     # unbless @values, for ease of JSON encoding
119     $result{'values'} = [];
120     foreach my $value (@values) {
121       push @{$result{'values'}}, [ map { $_ } @$value ];
122     }
123     push @out, \%result;
124   }
125   return @out;      
126 }
127
128 =back
129
130 =cut
131
132 1;
133