1 # Copyright (C) 2008 Roman Hochuli
2 # Copyright (C) 2010 Stanislav Sinyagin
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18 # $Id: Foundry.pm,v 1.1 2010-12-27 00:03:48 ivan Exp $
19 # Roman Hochuli <roman@hochu.li>
21 # Common Foundry MIBs, supported by IronWare-Devices
23 package Torrus::DevDiscover::Foundry;
29 $Torrus::DevDiscover::registry{'Foundry'} = {
31 'checkdevtype' => \&checkdevtype,
32 'discover' => \&discover,
33 'buildConfig' => \&buildConfig
40 'fdry' => '1.3.6.1.4.1.1991',
42 # FOUNDRY-SN-AGENT-MIB
43 'fdrySnChasSerNum' => '1.3.6.1.4.1.1991.1.1.1.1.2.0',
44 'fdrySnChasGen' => '1.3.6.1.4.1.1991.1.1.1.1.13',
45 'fdrySnChasIdNumber' => '1.3.6.1.4.1.1991.1.1.1.1.17.0',
46 'fdrySnChasArchitectureType' => '1.3.6.1.4.1.1991.1.1.1.1.25.0',
47 'fdrySnChasProductType' => '1.3.6.1.4.1.1991.1.1.1.1.26.0',
49 # FOUNDRY-SN-AGENT-MIB
50 'fdrySnChasActualTemperature' => '1.3.6.1.4.1.1991.1.1.1.1.18.0',
51 'fdrySnChasWarningTemperature' => '1.3.6.1.4.1.1991.1.1.1.1.19.0',
52 'fdrySnChasShutdownTemperature' => '1.3.6.1.4.1.1991.1.1.1.1.20.0',
53 'fdrySnAgImgVer' => '1.3.6.1.4.1.1991.1.1.2.1.11',
54 'fdrySnAgentTempTable' => '1.3.6.1.4.1.1991.1.1.2.13.1',
55 'fdrySnAgentTempSensorDescr' => '1.3.6.1.4.1.1991.1.1.2.13.1.1.3',
56 'fdrySnAgentTempValue' => '1.3.6.1.4.1.1991.1.1.2.13.1.1.4',
58 # FOUNDRY-SN-AGENT-MIB
59 'fdrySnAgGblCpuUtilData' => '1.3.6.1.4.1.1991.1.1.2.1.35',
60 'fdrySnAgGblCpuUtil1SecAvg' => '1.3.6.1.4.1.1991.1.1.2.1.50',
61 'fdrySnAgGblCpuUtil5SecAvg' => '1.3.6.1.4.1.1991.1.1.2.1.51',
62 'fdrySnAgGblCpuUtil1MinAvg' => '1.3.6.1.4.1.1991.1.1.2.1.52',
63 'fdrySnAgentCpuUtilValue' => '1.3.6.1.4.1.1991.1.1.2.11.1.1.4',
64 'fdrySnAgentCpuUtil100thPercent' => '1.3.6.1.4.1.1991.1.1.2.11.1.1.6',
66 # FOUNDRY-SN-AGENT-MIB
67 'fdrySnAgentBrdTbl' => '1.3.6.1.4.1.1991.1.1.2.2.1.1',
68 'fdrySnAgentBrdMainBrdDescription' => '1.3.6.1.4.1.1991.1.1.2.2.1.1.2',
69 'fdrySnAgentBrdMainPortTotal' => '1.3.6.1.4.1.1991.1.1.2.2.1.1.4',
70 'fdrySnAgentBrdModuleStatus' => '1.3.6.1.4.1.1991.1.1.2.2.1.1.12',
71 # Not listed in FOUNDRY-SN-AGENT-MIB, but in release notes
72 'fdrySnAgentBrdMemoryTotal' => '1.3.6.1.4.1.1991.1.1.2.2.1.1.24',
73 'fdrySnAgentBrdMemoryAvailable' => '1.3.6.1.4.1.1991.1.1.2.2.1.1.25',
77 # Not all interfaces are normally needed to monitor.
78 # You may override the interface filtering in devdiscover-siteconfig.pl:
79 # redefine $Torrus::DevDiscover::Foundry::interfaceFilter
80 # or define $Torrus::DevDiscover::Foundry::interfaceFilterOverlay
83 our $interfaceFilterOverlay;
84 my %fdryInterfaceFilter;
86 if( not defined( $interfaceFilter ) )
88 $interfaceFilter = \%fdryInterfaceFilter;
91 # Key is some unique symbolic name, does not mean anything
92 # ifType is the number to match the interface type
93 # ifDescr is the regexp to match the interface description
94 %fdryInterfaceFilter =
97 'ifType' => 24, # softwareLoopback
101 'ifType' => 135, # l2vlan
105 'ifType' => 150, # mplsTunnel
111 my %productTypeAttr =
114 'desc' => 'BigIron MG8',
118 'desc' => 'NetIron 40G',
122 'desc' => 'NetIron IMR 640',
126 'desc' => 'NetIron RX 800',
130 'desc' => 'NetIron XMR 16000',
134 'desc' => 'NetIron RX 400',
138 'desc' => 'NetIron XMR 8000',
142 'desc' => 'NetIron RX 200',
146 'desc' => 'NetIron XMR 4000',
150 'desc' => 'NetIron MLX-32',
154 'desc' => 'NetIron XMR 32000',
158 'desc' => 'NetIron RX-32',
162 'desc' => 'FastIron',
174 my $devdetails = shift;
177 if( $dd->oidBaseMatch
178 ( 'fdry', $devdetails->snmpVar( $dd->oiddef('sysObjectID') ) ) )
182 &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
183 ($devdetails, $interfaceFilter);
185 if( defined( $interfaceFilterOverlay ) )
187 &Torrus::DevDiscover::RFC2863_IF_MIB::addInterfaceFilter
188 ($devdetails, $interfaceFilterOverlay);
191 $devdetails->setCap('interfaceIndexingPersistent');
203 my $devdetails = shift;
205 my $session = $dd->session();
206 my $data = $devdetails->data();
208 # NOTE: Comments and Serial number of device
210 my $chassis = $dd->retrieveSnmpOIDs( 'fdrySnChasSerNum',
211 'fdrySnChasIdNumber',
212 'fdrySnChasArchitectureType',
213 'fdrySnChasProductType' );
215 Debug('fdrySnChasSerNum=' . $chassis->{'fdrySnChasSerNum'});
216 Debug('fdrySnChasIdNumber=' . $chassis->{'fdrySnChasIdNumber'});
217 Debug('fdrySnChasArchitectureType=' .
218 $chassis->{'fdrySnChasArchitectureType'});
219 Debug('fdrySnChasProductType=' . $chassis->{'fdrySnChasProductType'});
223 if( defined( $chassis ) and
224 defined( $productTypeAttr{$chassis->{'fdrySnChasProductType'}} ) )
226 $productType = $chassis->{'fdrySnChasProductType'};
229 my $deviceComment = 'Brocade ' . $productTypeAttr{$productType}{'desc'};
231 if( defined( $chassis ) )
233 if( defined( $chassis->{'fdrySnChasSerNum'} ) )
235 $deviceComment .= ', Chassis S/N: ' .
236 $chassis->{'fdrySnChasSerNum'};
239 if( defined( $chassis->{'fdrySnChasIdNumber'} ) and
240 $chassis->{'fdrySnChasIdNumber'} ne '' )
242 $deviceComment .= ', Chassis ID: ' .
243 $chassis->{'fdrySnChasIdNumber'};
247 $data->{'param'}{'comment'} = $deviceComment;
250 my $chasTemp = $dd->retrieveSnmpOIDs( 'fdrySnChasActualTemperature',
251 'fdrySnChasWarningTemperature',
252 'fdrySnChasShutdownTemperature');
254 if( defined($chasTemp) and
255 defined($chasTemp->{'fdrySnChasActualTemperature'}) )
257 $devdetails->setCap('snChasActualTemperature');
259 $data->{'fdryChasTemp'}{'warning'} =
260 $chasTemp->{'fdrySnChasWarningTemperature'};
261 $data->{'fdryChasTemp'}{'shutdown'} =
262 $chasTemp->{'fdrySnChasShutdownTemperature'};
265 if( $dd->checkSnmpTable('fdrySnAgentBrdTbl') )
267 $devdetails->setCap('fdryBoardStats');
268 $data->{'fdryBoard'} = {};
270 # get only the modules with
271 # snAgentBrdModuleStatus = moduleRunning(10)
273 my $base = $dd->oiddef('fdrySnAgentBrdModuleStatus');
274 my $table = $session->get_table( -baseoid => $base );
275 my $prefixLen = length( $base ) + 1;
277 while( my( $oid, $status ) = each %{$table} )
281 my $brdIndex = substr( $oid, $prefixLen );
282 $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} = 1;
287 # get module descriptions
289 my $oid = $dd->oiddef('fdrySnAgentBrdMainBrdDescription');
290 my $table = $session->get_table( -baseoid => $oid );
291 my $prefixLen = length( $oid ) + 1;
293 while( my( $oid, $descr ) = each %{$table} )
295 if( length($descr) > 0 )
297 my $brdIndex = substr( $oid, $prefixLen );
299 if( $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} )
301 $data->{'fdryBoard'}{$brdIndex}{'description'} =
308 # Non-chassis Foundry products set the description to "Invalid Module"
309 if( scalar(keys %{$data->{'fdryBoard'}}) == 1 and
310 $data->{'fdryBoard'}{1}{'moduleRunning'} )
312 $data->{'fdryBoard'}{1}{'description'} = 'Management';
315 # check if memory statistics are available
317 my $base = $dd->oiddef('fdrySnAgentBrdMemoryTotal');
318 my $table = $session->get_table( -baseoid => $base );
319 my $prefixLen = length( $base ) + 1;
321 while( my( $oid, $memory ) = each %{$table} )
325 my $brdIndex = substr( $oid, $prefixLen );
327 if( $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} )
329 $data->{'fdryBoard'}{$brdIndex}{'memory'} = 1;
335 # check if CPU stats are available
336 # FOUNDRY-SN-AGENT-MIB::snAgentCpuUtilValue.1.1.1 = Gauge32: 1
337 # FOUNDRY-SN-AGENT-MIB::snAgentCpuUtilValue.1.1.5 = Gauge32: 1
338 # FOUNDRY-SN-AGENT-MIB::snAgentCpuUtilValue.1.1.60 = Gauge32: 1
339 # FOUNDRY-SN-AGENT-MIB::snAgentCpuUtilValue.1.1.300 = Gauge32: 1
341 my $base = $dd->oiddef('fdrySnAgentCpuUtilValue');
342 my $table = $session->get_table( -baseoid => $base );
343 my $prefixLen = length( $base ) + 1;
345 while( my( $oid, $val ) = each %{$table} )
347 my $brdIndex = substr( $oid, $prefixLen );
348 $brdIndex =~ s/\.(.+)$//o;
350 $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} )
352 $data->{'fdryBoard'}{$brdIndex}{'cpu'} = 1;
357 # snAgentCpuUtil100thPercent: supported on NetIron XMR and NetIron
358 # MLX devices running software release 03.9.00 and later, FGS release
359 # 04.3.01 and later, and FSX 04.3.00 and later.
360 # snAgentCpuUtilValue is deprecated in these releases
362 my $base = $dd->oiddef('fdrySnAgentCpuUtil100thPercent');
363 my $table = $session->get_table( -baseoid => $base );
364 my $prefixLen = length( $base ) + 1;
366 while( my( $oid, $val ) = each %{$table} )
368 my $brdIndex = substr( $oid, $prefixLen );
369 $brdIndex =~ s/\.(.+)$//o;
371 $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} )
373 $data->{'fdryBoard'}{$brdIndex}{'cpu-new'} = 1;
378 # check if temperature stats are available
379 # exclude the sensors which show zero
381 my $base = $dd->oiddef('fdrySnAgentTempSensorDescr');
382 my $table = $session->get_table( -baseoid => $base );
383 my $prefixLen = length( $base ) + 1;
385 my $baseVal = $dd->oiddef('fdrySnAgentTempValue');
386 my $values = $session->get_table( -baseoid => $baseVal );
388 while( my( $oid, $descr ) = each %{$table} )
390 my $index = substr( $oid, $prefixLen );
391 my ($brdIndex, $sensor) = split(/\./, $index);
393 if( $data->{'fdryBoard'}{$brdIndex}{'moduleRunning'} and
394 $values->{$baseVal . '.' . $index} > 0 )
396 $data->{'fdryBoard'}{$brdIndex}{'temperature'}{$sensor} =
398 $devdetails->setCap('fdryBoardTemperature');
410 my $devdetails = shift;
414 my $data = $devdetails->data();
416 # Chassis Temperature Sensors
417 if( $devdetails->hasCap('snChasActualTemperature') and not
418 $devdetails->hasCap('fdryBoardTemperature') )
421 'fdry-chastemp-warning' => $data->{'fdryChasTemp'}{'warning'}/2,
422 'fdry-chastemp-shutdown' => $data->{'fdryChasTemp'}{'shutdown'}/2,
425 my $templates = [ 'Foundry::fdry-chass-temperature' ];
427 $cb->addLeaf( $devNode, 'Chassis_Temperature',
428 $param, $templates );
432 if( $devdetails->hasCap('fdryBoardStats') )
434 my $brdNode = $devNode;
435 if( scalar(keys %{$data->{'fdryBoard'}}) > 1 )
438 'node-display-name' => 'Linecard Statistics',
439 'comment' => 'CPU, Memory, and Temperature information',
443 $cb->addSubtree( $devNode, 'Linecard_Statistics', $param );
446 $cb->addTemplateApplication( $brdNode,
447 'Foundry::fdry-board-overview' );
450 foreach my $brdIndex ( sort {$a <=> $b} keys %{$data->{'fdryBoard'}} )
452 my $descr = $data->{'fdryBoard'}{$brdIndex}{'description'};
455 'fdry-board-index' => $brdIndex,
456 'fdry-board-descr' => $descr,
457 'nodeid' => 'module//%nodeid-device%//' . $brdIndex,
461 $cb->addSubtree( $brdNode, 'Linecard_' . $brdIndex,
463 [ 'Foundry::fdry-board-subtree' ]);
465 if( $data->{'fdryBoard'}{$brdIndex}{'memory'} )
467 $cb->addSubtree( $linecardNode, 'Memory_Statistics', {},
468 [ 'Foundry::fdry-board-memstats' ]);
473 if( $data->{'fdryBoard'}{$brdIndex}{'cpu-new'} )
475 $cpuOid = '$fdrySnAgentCpuUtil100thPercent';
477 elsif( $data->{'fdryBoard'}{$brdIndex}{'cpu'} )
479 $cpuOid = '$fdrySnAgentCpuUtilValue';
482 if( defined( $cpuOid ) )
486 ( $linecardNode, 'CPU_Statistics',
488 'fdry-cpu-base' => $cpuOid,
489 'nodeid' => 'cpu//%nodeid-device%//' . $brdIndex,
491 [ 'Foundry::fdry-board-cpustats' ]);
494 if( defined( $data->{'fdryBoard'}{$brdIndex}{'temperature'} ) )
497 $cb->addSubtree( $linecardNode, 'Temperature_Statistics',
498 {}, ['Foundry::fdry-board-tempstats']);
500 # Build a multi-graph for all sensors
503 ('##one', '##two', '##three', '##four', '##five',
504 '##six', '##seven', '##eight', '##nine', '##ten');
507 'comment' => 'Board temperature sensors combined',
508 'ds-type' => 'rrd-multigraph',
509 'vertical-label' => 'Degrees Celcius',
510 'nodeid' => 'temp//%nodeid-device%//' . $brdIndex,
517 keys %{$data->{'fdryBoard'}{$brdIndex}{'temperature'}} )
519 my $leafName = 'sensor_' . $sensor;
521 my $descr = $data->{'fdryBoard'}{$brdIndex}{
522 'temperature'}{$sensor};
524 my $short = 'Temperature sensor ' . $sensor;
528 'precedence' => 1000 - $sensor,
529 'sensor-index' => $sensor,
530 'sensor-short' => $short,
531 'sensor-description' => $descr,
535 ( $tempNode, $leafName, $param,
536 ['Foundry::fdry-board-temp-sensor-halfcelsius'] );
538 push(@sensors, $leafName);
540 $mgParam->{'ds-expr-' . $leafName} =
541 '{' . $leafName . '}';
542 $mgParam->{'graph-legend-' . $leafName} = $short;
543 $mgParam->{'line-style-' . $leafName} = 'LINE2';
545 my $color = shift @colors;
546 if( not defined( $color ) )
548 Error('Too many sensors on one Foundry board');
551 $mgParam->{'line-color-' . $leafName} = $color;
553 $mgParam->{'line-order-' . $leafName} = $sensor;
556 $mgParam->{'ds-names'} = join(',', @sensors);
558 $cb->addLeaf( $tempNode, 'Temperature_Overview', $mgParam );