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