import torrus 1.0.9
[freeside.git] / torrus / perllib / Torrus / DevDiscover / CiscoSCE.pm
1 #
2 #  Discovery module for Cisco Service Control Engine (formely PCube)
3 #
4 #  Copyright (C) 2007 Jon Nistor
5 #  Copyright (C) 2007 Stanislav Sinyagin
6 #
7 #  This program is free software; you can redistribute it and/or modify
8 #  it under the terms of the GNU General Public License as published by
9 #  the Free Software Foundation; either version 2 of the License, or
10 #  (at your option) any later version.
11 #
12 #  This program is distributed in the hope that it will be useful,
13 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #  GNU General Public License for more details.
16 #
17 #  You should have received a copy of the GNU General Public License
18 #  along with this program; if not, write to the Free Software
19 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21 # $Id: CiscoSCE.pm,v 1.1 2010-12-27 00:03:56 ivan Exp $
22 # Jon Nistor <nistor at snickers dot org>
23 #
24 # NOTE: Options for this module
25 #       CiscoSCE::disable-disk
26 #       CiscoSCE::disable-gc
27 #       CiscoSCE::disable-qos
28 #       CiscoSCE::disable-rdr
29 #       CiscoSCE::disable-subs
30 #       CiscoSCE::disable-tp
31 #
32
33 # Cisco SCE devices discovery
34 package Torrus::DevDiscover::CiscoSCE;
35
36 use strict;
37 use Torrus::Log;
38
39
40 $Torrus::DevDiscover::registry{'CiscoSCE'} = {
41     'sequence'     => 500,
42     'checkdevtype' => \&checkdevtype,
43     'discover'     => \&discover,
44     'buildConfig'  => \&buildConfig
45 };
46
47 # pmodule-dependend OIDs are presented for module #1 only.
48 # currently devices with more than one module do not exist
49
50 our %oiddef =
51     (
52      # PCUBE-SE-MIB
53      'pcubeProducts'        => '1.3.6.1.4.1.5655.1',
54      'pchassisSysType'      => '1.3.6.1.4.1.5655.4.1.2.1.0',
55      'pchassisNumSlots'     => '1.3.6.1.4.1.5655.4.1.2.6.0',
56      'pmoduleType'          => '1.3.6.1.4.1.5655.4.1.3.1.1.2.1',
57      'pmoduleNumLinks'      => '1.3.6.1.4.1.5655.4.1.3.1.1.7.1',
58      'pmoduleSerialNumber'  => '1.3.6.1.4.1.5655.4.1.3.1.1.9.1',
59      'pmoduleNumTrafficProcessors'   => '1.3.6.1.4.1.5655.4.1.3.1.1.3.1',
60      'rdrFormatterEnable'            => '1.3.6.1.4.1.5655.4.1.6.1.0',
61      'rdrFormatterCategoryName'      => '1.3.6.1.4.1.5655.4.1.6.11.1.2',
62      'subscribersNumIpAddrMappings'  => '1.3.6.1.4.1.5655.4.1.8.1.1.3.1',
63      'subscribersNumIpRangeMappings' => '1.3.6.1.4.1.5655.4.1.8.1.1.5.1',
64      'subscribersNumVlanMappings'    => '1.3.6.1.4.1.5655.4.1.8.1.1.7.1',
65      'subscribersNumAnonymous'       => '1.3.6.1.4.1.5655.4.1.8.1.1.16.1',
66      'pportNumTxQueues'     => '1.3.6.1.4.1.5655.4.1.10.1.1.4.1',
67      'pportIfIndex'         => '1.3.6.1.4.1.5655.4.1.10.1.1.5.1',
68      'txQueuesDescription'  => '1.3.6.1.4.1.5655.4.1.11.1.1.4.1',
69
70      # CISCO-SCAS-BB-MIB (PCUBE-ENGAGE-MIB)
71      'globalScopeServiceCounterName' => '1.3.6.1.4.1.5655.4.2.5.1.1.3.1',
72      
73     );
74
75 our %sceChassisNames =
76     (
77      '1'    => 'unknown',
78      '2'    => 'SE 1000',
79      '3'    => 'SE 100',
80      '4'    => 'SE 2000',
81     );
82
83 our %sceModuleDesc =
84     (
85      '1'    => 'unknown',
86      '2'    => '2xGBE + 1xFE Mgmt',
87      '3'    => '2xFE + 1xFE Mgmt',
88      '4'    => '4xGBE + 1 or 2 FastE Mgmt',
89      '5'    => '4xFE + 1xFE Mgmt',
90      '6'    => '4xOC-12 + 1 or 2 FastE Mgmt',
91      '7'    => '16xFE + 2xGBE, 2 FastE Mgmt',
92     );
93
94 sub checkdevtype
95 {
96     my $dd = shift;
97     my $devdetails = shift;
98
99     if( not $dd->oidBaseMatch
100         ( 'pcubeProducts',
101           $devdetails->snmpVar( $dd->oiddef('sysObjectID') ) ) )
102     {
103         return 0;
104     }
105     
106     my $result = $dd->retrieveSnmpOIDs('pchassisNumSlots');
107     if( $result->{'pchassisNumSlots'} > 1 )
108     {
109         Error('This SCE device has more than one module on the chassis.' .
110               'The current version of DevDiscover does not support such ' .
111               'devices');
112         return 0;
113     }
114     
115     $devdetails->setCap('interfaceIndexingPersistent');
116
117     return 1;
118 }
119
120 sub discover
121 {
122     my $dd = shift;
123     my $devdetails = shift;
124
125     my $session = $dd->session();
126     my $data = $devdetails->data();
127
128     # Get the system info and display it in the comment
129     my $sceInfo = $dd->retrieveSnmpOIDs
130         ( 'pchassisSysType', 'pmoduleType', 'pmoduleNumLinks',
131           'pmoduleSerialNumber', 'pmoduleNumTrafficProcessors',
132           'rdrFormatterEnable',
133           'subscribersNumIpAddrMappings', 'subscribersNumIpRangeMappings',
134           'subscribersNumVlanMappings', 'subscribersNumAnonymous' );
135
136     $data->{'sceInfo'} = $sceInfo;
137     
138     $data->{'param'}{'comment'} =
139         $sceChassisNames{$sceInfo->{'pchassisSysType'}} .
140         " chassis, " . $sceModuleDesc{$sceInfo->{'pmoduleType'}} .
141         ", Hw Serial#: " . $sceInfo->{'pmoduleSerialNumber'};
142     
143     # TP: Traffic Processor
144     if( $devdetails->param('CiscoSCE::disable-tp') ne 'yes' )
145     { 
146         $devdetails->setCap('sceTP');
147
148         $data->{'sceTrafficProcessors'} =
149             $sceInfo->{'pmoduleNumTrafficProcessors'};
150     }
151
152     # HDD: Disk Usage
153     if( $devdetails->param('CiscoSCE::disable-disk') ne 'yes' )
154     {
155         $devdetails->setCap('sceDisk');
156     }
157
158     # SUBS: subscriber aware configuration
159     if( $devdetails->param('CiscoSCE::disable-subs') ne 'yes' )
160     {
161         if( $sceInfo->{'subscribersNumIpAddrMappings'}  > 0 or
162             $sceInfo->{'subscribersNumIpRangeMappings'} > 0 or
163             $sceInfo->{'subscribersNumVlanMappings'}    > 0 or
164             $sceInfo->{'subscribersNumAnonymous'}       > 0 )
165         {
166             $devdetails->setCap('sceSubscribers');
167         }
168     }
169     
170     
171     # QOS: TX Queues Names
172     if( $devdetails->param('CiscoSCE::disable-qos') ne 'yes' )
173     { 
174         $devdetails->setCap('sceQos');
175
176         # Get the names of TX queues
177         my $txQueueNum = $session->get_table
178             ( -baseoid => $dd->oiddef('pportNumTxQueues') );
179         $devdetails->storeSnmpVars( $txQueueNum );
180         
181         my $ifIndexTable = $session->get_table
182             ( -baseoid => $dd->oiddef('pportIfIndex') );
183
184         my $txQueueDesc = $session->get_table
185             ( -baseoid => $dd->oiddef('txQueuesDescription') );
186         
187         $devdetails->storeSnmpVars( $txQueueDesc );
188         
189         foreach my $pIndex
190             ( $devdetails->getSnmpIndices( $dd->oiddef('pportNumTxQueues') ) )
191         {
192             # We take ports with more than one queue and add queueing
193             # statistics to interface counters
194             if( $txQueueNum->{$dd->oiddef('pportNumTxQueues') .
195                                   '.' . $pIndex} > 1 )
196             {
197                 # We need the ifIndex to retrieve the interface name
198                 
199                 my $ifIndex =
200                     $ifIndexTable->{$dd->oiddef('pportIfIndex') . '.'
201                                         . $pIndex};
202
203                 $data->{'scePortIfIndex'}{$pIndex} = $ifIndex;
204                 
205                 foreach my $qIndex
206                     ( $devdetails->getSnmpIndices
207                       ( $dd->oiddef('txQueuesDescription') . '.' . $pIndex ) )
208                 {
209                     my $oid = $dd->oiddef('txQueuesDescription') . '.' .
210                         $pIndex . '.' . $qIndex;
211                     
212                     $data->{'sceQueues'}{$pIndex}{$qIndex} =
213                         $txQueueDesc->{$oid};
214                 }
215             }
216         }
217     }
218
219
220     # GC: Global Service Counters
221     if( $devdetails->param('CiscoSCE::disable-gc') ne 'yes' )
222     {
223         # Set the Capability for the Global Counters
224         $devdetails->setCap('sceGlobalCounters');
225
226         my $counterNames = $session->get_table
227             ( -baseoid => $dd->oiddef('globalScopeServiceCounterName') );
228         
229         $devdetails->storeSnmpVars( $counterNames );
230         
231         foreach my $gcIndex
232             ( $devdetails->getSnmpIndices
233               ( $dd->oiddef('globalScopeServiceCounterName') ) )
234         {
235             my $oid =
236                 $dd->oiddef('globalScopeServiceCounterName') . '.' . $gcIndex;
237             if( length( $counterNames->{$oid} ) > 0 )
238             {
239                 $data->{'sceGlobalCounters'}{$gcIndex} = $counterNames->{$oid};
240             }
241         }
242     }
243
244
245     # RDR: Raw Data Record
246     if( $devdetails->param('CiscoSCE::disable-rdr') ne 'yes' )
247     {   
248         if( $sceInfo->{'rdrFormatterEnable'} > 0 )
249         {
250             # Set Capability for the RDR section of XML
251             $devdetails->setCap('sceRDR');
252             
253             # Get the names of the RDR Category
254             my $categoryNames = $session->get_table
255                 ( -baseoid => $dd->oiddef('rdrFormatterCategoryName') );
256             
257             $devdetails->storeSnmpVars( $categoryNames );
258             
259             foreach my $categoryIndex
260                 ( $devdetails->getSnmpIndices
261                   ( $dd->oiddef('rdrFormatterCategoryName') ) )
262             {
263                 my $oid = $dd->oiddef('rdrFormatterCategoryName') . '.'
264                     . $categoryIndex;
265                 $data->{'sceRDR'}{$categoryIndex} = $categoryNames->{$oid};
266             }
267         }
268     }
269     
270     return 1;
271 }
272
273
274 sub buildConfig
275 {
276     my $devdetails = shift;
277     my $cb = shift;
278     my $devNode = shift;
279     my $data = $devdetails->data();
280
281     # Disk Usage information
282     if( $devdetails->hasCap('sceDisk') )
283     {
284         $cb->addTemplateApplication($devNode, 'CiscoSCE::cisco-sce-disk');
285     }
286
287     if( $devdetails->hasCap('sceSubscribers') )
288     {
289         $cb->addTemplateApplication($devNode,
290                                     'CiscoSCE::cisco-sce-subscribers');
291     }
292
293     # Traffic processors subtree
294     if( $devdetails->hasCap('sceTP') )
295     {   
296         my $tpNode = $cb->addSubtree( $devNode, 'SCE_TrafficProcessors',
297                                       { 'comment' => 'TP usage statistics' },
298                                       [ 'CiscoSCE::cisco-sce-tp-subtree']);
299
300         foreach my $tp ( 1 .. $data->{'sceTrafficProcessors'} )
301         {
302             $cb->addSubtree( $tpNode, sprintf('TP_%d', $tp),
303                              { 'sce-tp-index' => $tp },
304                              ['CiscoSCE::cisco-sce-tp'] );
305         }
306     }
307
308
309     # QoS queues
310     if( $devdetails->hasCap('sceQos') )
311     { 
312         # Queues subtree
313         my $qNode =
314             $cb->addSubtree( $devNode, 'SCE_Queues',
315                              { 'comment' => 'TX queues usage statistics' },
316                              [ 'CiscoSCE::cisco-sce-queues-subtree']);
317         
318         foreach my $pIndex ( sort {$a <=> $b}
319                              keys %{$data->{'scePortIfIndex'}} )
320         {
321             my $ifIndex = $data->{'scePortIfIndex'}{$pIndex};
322             my $interface = $data->{'interfaces'}{$ifIndex};
323
324             my $portNode =
325                 $cb->addSubtree
326                 ( $qNode,
327                   $interface->{$data->{'nameref'}{'ifSubtreeName'}},
328                   { 'sce-port-index' => $pIndex,
329                     'precedence' => 1000 - $pIndex });
330             
331             foreach my $qIndex ( sort {$a <=> $b} keys 
332                                  %{$data->{'sceQueues'}{$pIndex}} )
333             {
334                 my $qName = $data->{'sceQueues'}{$pIndex}{$qIndex};
335                 my $subtreeName = 'Q' . $qIndex;
336                 
337                 $cb->addLeaf( $portNode, $subtreeName,
338                               { 'sce-queue-index' => $qIndex,
339                                 'comment' => $qName,
340                                 'precedence' => 1000 - $qIndex });
341             }
342         }
343     } # hasCap sceQos
344
345
346     # Global counters
347     if( $devdetails->hasCap('sceGlobalCounters') )
348     {
349         foreach my $linkIndex ( 1 .. $data->{'sceInfo'}{'pmoduleNumLinks'} )
350         {
351             my $gcNode =
352                 $cb->addSubtree( $devNode,
353                                  'SCE_Global_Counters_L' . $linkIndex,
354                                  { 'comment' =>
355                                        'Global service counters for link #'
356                                        . $linkIndex
357                                  },
358                                  [ 'CiscoSCE::cisco-sce-gc-subtree']);
359             
360             foreach my $gcIndex
361                 ( sort {$a <=> $b} keys %{$data->{'sceGlobalCounters'}} )
362             {
363                 my $srvName = $data->{'sceGlobalCounters'}{$gcIndex};
364                 my $subtreeName = $srvName;
365                 $subtreeName =~ s/\W/_/g;
366                 
367                 $cb->addSubtree( $gcNode, $subtreeName,
368                                  { 'sce-link-index'   => $linkIndex,
369                                    'sce-gc-index'     => $gcIndex,
370                                    'comment'          => $srvName,
371                                    'sce-service-name' => $srvName,
372                                    'precedence'       => 1000 - $gcIndex,
373                                    'searchable'       => 'yes'},
374                                  [ 'CiscoSCE::cisco-sce-gcounter' ]);
375             }
376         }
377     } # END hasCap sceGlobalCounters
378
379
380     # RDR Formatter reports
381     if( $devdetails->hasCap('sceRDR') )
382     {
383         $cb->addTemplateApplication($devNode, 'CiscoSCE::cisco-sce-rdr');
384
385         # Add a Subtree for "SCE_RDR_Categories"
386         my $rdrNode =
387             $cb->addSubtree( $devNode, 'SCE_RDR_Categories',
388                              { 'comment' => 'Raw Data Records per Category' },
389                              [ 'CiscoSCE::cisco-sce-rdr-category-subtree' ]);
390         
391         foreach my $cIndex ( sort {$a <=> $b} keys %{$data->{'sceRDR'}} )
392         {
393             my $categoryName;
394             if ( $data->{'sceRDR'}{$cIndex} )
395             {
396                 $categoryName = $data->{'sceRDR'}{$cIndex};
397             }
398             else
399             {
400                 $categoryName = 'Category_' . $cIndex;
401             }
402             
403             $cb->addSubtree( $rdrNode, 'Category_' . $cIndex,
404                              { 'precedence'      => 1000 - $cIndex,
405                                'sce-rdr-index'   => $cIndex,
406                                'sce-rdr-comment' => $categoryName },
407                              ['CiscoSCE::cisco-sce-rdr-category'] );
408         }
409     } # END hasCap sceRDR    
410 }
411
412 1;
413
414 # Local Variables:
415 # mode: perl
416 # indent-tabs-mode: nil
417 # perl-indent-level: 4
418 # End: