Merge remote-tracking branch 'upstream/master'
[torrus-plus.git] / src / lib / Torrus / DevDiscover / F5BigIp.pm
blobb686cf791f4dde415c29d85a5ef0d3f6377b4e99
1 # Copyright (C) 2003 Shawn Ferry
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
17 # $Id$
18 # Shawn Ferry <sferry at sevenspace dot com> <lalartu at obscure dot org>
20 # F5 BigIp Load Balancer
22 package Torrus::DevDiscover::F5BigIp;
24 use strict;
25 use warnings;
27 use Torrus::Log;
29 our $VERSION = 1.0;
31 $Torrus::DevDiscover::registry{'F5BigIp'} = {
32 'sequence' => 500,
33 'checkdevtype' => \&checkdevtype,
34 'discover' => \&discover,
35 'buildConfig' => \&buildConfig
38 our %oiddef =
40 # F5
41 'f5' => '1.3.6.1.4.1.3375',
43 '4.x_globalStatUptime' => '1.3.6.1.4.1.3375.1.1.1.2.1.0',
44 '3.x_uptime' => '1.3.6.1.4.1.3375.1.1.50.0',
46 '4.x_globalAttrProductCode' => '1.3.6.1.4.1.3375.1.1.1.1.5.0',
48 '4.x_virtualServer' => '1.3.6.1.4.1.3375.1.1.3',
49 '4.x_virtualServerNumber' => '1.3.6.1.4.1.3375.1.1.3.1.0',
50 '4.x_virtualServerTable' => '1.3.6.1.4.1.3375.1.1.3.2',
51 '4.x_virtualServerIp' => '1.3.6.1.4.1.3375.1.1.3.2.1.1',
52 '4.x_virtualServerPort' => '1.3.6.1.4.1.3375.1.1.3.2.1.2',
53 '4.x_virtualServerPool' => '1.3.6.1.4.1.3375.1.1.3.2.1.30',
55 '4.x_poolTable' => '1.3.6.1.4.1.3375.1.1.7.2',
56 '4.x_poolName' => '1.3.6.1.4.1.3375.1.1.7.2.1.1',
58 '4.x_poolMemberTable' => '1.3.6.1.4.1.3375.1.1.8.2',
59 '4.x_poolMemberPoolName' => '1.3.6.1.4.1.3375.1.1.8.2.1.1',
60 '4.x_poolMemberIpAddress' => '1.3.6.1.4.1.3375.1.1.8.2.1.2',
61 '4.x_poolMemberPort' => '1.3.6.1.4.1.3375.1.1.8.2.1.3',
63 '4.x_sslProxyTable' => '1.3.6.1.4.1.3375.1.1.9.2.1',
64 '4.x_sslProxyOrigIpAddress' => '1.3.6.1.4.1.3375.1.1.9.2.1.1',
65 '4.x_sslProxyOrigPort' => '1.3.6.1.4.1.3375.1.1.9.2.1.2',
66 '4.x_sslProxyDestIpAddress' => '1.3.6.1.4.1.3375.1.1.9.2.1.3',
67 '4.x_sslProxyDestPort' => '1.3.6.1.4.1.3375.1.1.9.2.1.4',
68 '4.x_sslProxyConnLimit' => '1.3.6.1.4.1.3375.1.1.9.2.1.23',
72 # from https://secure.f5.com/validate/help.jsp
73 #HA (BIG-IP high availability software)
74 #3DNS (3-DNS software)
75 #LC (BIG-IP Link Controller software)
76 #LB (BIG-IP Load Balancer 520)
77 #FLB (BIG-IP FireGuard 520)
78 #CLB (BIG-IP Cache Load Balancer 520)
79 #SSL (BIG-IP eCommerce Load Balancer 520)
80 #XLB (BIG-IP user-defined special purpose product for 520 platforms)
81 #ISMAN (iControl Services Manager)
83 our %f5_product = (
84 '1' => { 'product' => 'indeterminate', 'supported' => 0, },
85 '2' => { 'product' => 'ha', 'supported' => 1, },
86 '3' => { 'product' => 'lb', 'supported' => 1, },
87 '4' => { 'product' => 'threedns', 'supported' => 0, },
88 '5' => { 'product' => 'flb', 'supported' => 0, },
89 '6' => { 'product' => 'clb', 'supported' => 0, },
90 '7' => { 'product' => 'xlb', 'supported' => 0, },
91 '8' => { 'product' => 'ssl', 'supported' => 1, },
92 '10' => { 'product' => 'test', 'supported' => 0, },
93 '99' => { 'product' => 'unsupported', 'supported' => 0, },
96 our %f5_sslGatewayLevel = (
97 '1' => 'none',
98 '3' => 'tps200',
99 '4' => 'tps400',
100 '5' => 'tps600',
101 '6' => 'tps800',
102 '7' => 'tps1000',
103 '9' => 'tps500',
104 '10' => 'tps1500',
105 '11' => 'tps2000',
106 '99' => 'unsupported',
112 sub checkdevtype
114 my $dd = shift;
115 my $devdetails = shift;
116 my $data = $devdetails->data();
118 # You would think globalAttrProductCode would work well
119 # I need more examples to see if ha(2) is specific to
120 # BipIP HA or any ha f5 product
122 if( not $dd->checkSnmpTable( 'f5' ) )
124 return 0;
127 return 1;
131 sub discover
133 my $dd = shift;
134 my $devdetails = shift;
136 my $session = $dd->session();
137 my $data = $devdetails->data();
139 # SNMP on F5 boxes will become unresponsive over time with large
140 # enough oids-per-pdu values. 10 appears to work for everything however
141 # no exhaustive testing has been done to determine if a higer number
142 # could be used.
143 if( not defined( $data->{'param'}{'snmp-oids-per-pdu'} ) )
145 my $oidsPerPDU = $devdetails->param('F5BigIp::snmp-oids-per-pdu');
146 if( not defined($oidsPerPDU) or $oidsPerPDU == 0 )
148 $oidsPerPDU = 10;
150 $data->{'param'}{'snmp-oids-per-pdu'} = $oidsPerPDU;
153 # this is rather basic, per-capability checking
154 # may be required in the future
156 if( $dd->checkSnmpOID('4.x_globalStatUptime') )
158 $devdetails->setCap('BigIp_4.x');
160 elsif( $dd->checkSnmpOID('3.x_uptime') )
162 # for v3.x we are not supporting detailed stats, so don't check
163 # anything else
164 $devdetails->setCap('BigIp_3.x');
165 return 1;
168 my $product_name;
169 my $result = $dd->retrieveSnmpOIDs( '4.x_globalAttrProductCode' );
170 my $product_code = $result->{'4.x_globalAttrProductCode'};
172 $product_name = $f5_product{$product_code}->{'product'};
173 if( $f5_product{$product_code}->{'supported'} )
175 $devdetails->setCap( 'BigIp_' . $product_name );
177 else
179 if( defined($product_name) )
181 Debug("Found an unsupported F5 product '$product_name'");
183 else
185 Debug("Found an unknown F5 product");
187 return 0;
190 my $poolTable = $session->get_table( -baseoid =>
191 $dd->oiddef('4.x_poolTable') );
193 if( defined( $poolTable ) )
195 $devdetails->storeSnmpVars( $poolTable );
196 $devdetails->setCap('BigIp_4.x_PoolTable');
198 my $ref = {};
199 $ref->{'indices'} = [];
200 $data->{'poolTable'} = $ref;
202 for my $INDEX ( $devdetails->
203 getSnmpIndices( $dd->oiddef('4.x_poolName') ) )
205 push( @{$ref->{'indices'}}, $INDEX );
206 my $pool = $devdetails->snmpVar($dd->oiddef('4.x_poolName') .
207 '.' . $INDEX );
209 my $nick = $pool;
210 $nick =~ s/\W/_/g;
211 $nick =~ s/_+/_/g;
213 my $param = {};
214 $ref->{$INDEX}->{'param'} = $param;
215 $param->{'nick'} = $nick;
216 $param->{'pool'} = $pool;
217 $param->{'descr'} = "Stats for Pool $pool";
218 $param->{'INDEX'} = $INDEX;
223 my $poolMemberTable =
224 $session->get_table( -baseoid =>
225 $dd->oiddef('4.x_poolMemberTable') );
227 if( defined( $poolMemberTable ) )
229 $devdetails->storeSnmpVars( $poolMemberTable );
230 $devdetails->setCap('BigIp_4.x_PoolMemberTable');
232 my $ref = {};
233 $data->{'poolMemberTable'} = $ref;
235 for my $INDEX
236 ( $devdetails->
237 getSnmpIndices( $dd->oiddef('4.x_poolMemberPoolName') ) )
239 push( @{ $ref->{'indices'} }, $INDEX );
240 my $pool =
241 $devdetails->snmpVar($dd->oiddef('4.x_poolMemberPoolName') .
242 '.' . $INDEX );
243 my $ip =
244 $devdetails->snmpVar($dd->oiddef('4.x_poolMemberIpAddress') .
245 '.' . $INDEX );
246 my $port =
247 $devdetails->snmpVar($dd->oiddef('4.x_poolMemberPort') .
248 '.' . $INDEX );
250 my $nick = "MEMBER_${pool}_${ip}_${port}";
251 $nick =~ s/\W/_/g;
252 $nick =~ s/_+/_/g;
254 my $param = {};
255 $ref->{$INDEX}->{'param'} = $param;
256 $param->{'nick'} = $nick;
257 $param->{'pool'} = $pool;
258 $param->{'descr'} = "Member of Pool $pool IP: $ip Port: $port";
259 $param->{'INDEX'} = $INDEX;
264 my $virtServerNumber = $dd->retrieveSnmpOIDs( '4.x_virtualServerNumber' );
265 if( $virtServerNumber->{'4.x_virtualServerNumber'} > 0 )
267 my $virtServer = $session->get_table( -baseoid =>
268 $dd->oiddef('4.x_virtualServer') );
269 if( defined( $virtServer ) )
271 $devdetails->storeSnmpVars( $virtServer );
272 $devdetails->setCap('BigIp_4.x_VirtualServer');
274 my $ref = {};
275 $data->{'virtualServer'} = $ref;
277 for my $INDEX
278 ( $devdetails->
279 getSnmpIndices( $dd->oiddef('4.x_virtualServerIp') ) )
281 push( @{ $ref->{'indices'} }, $INDEX);
282 my $pool = $devdetails->snmpVar(
283 $dd->oiddef('4.x_virtualServerPool') .
284 '.' . $INDEX );
285 my $ip = $devdetails->snmpVar(
286 $dd->oiddef('4.x_virtualServerIp') .
287 '.' . $INDEX );
288 my $port = $devdetails->snmpVar(
289 $dd->oiddef('4.x_virtualServerPort') .
290 '.' . $INDEX );
292 my $param = {};
293 $ref->{$INDEX}->{'param'} = $param;
295 my $descr = "Virtual Server Pool: $pool IP: $ip Port: $port";
296 my $nick = "VIP_${pool}_${ip}_${port}";
297 $nick =~ s/\W/_/g;
298 $nick =~ s/_+/_/g;
300 $param->{'INDEX'} = $INDEX;
301 $param->{'descr'} = $descr;
302 $param->{'nick'} = $nick;
303 $param->{'pool'} = $pool;
306 else
308 Debug("Virtual Servers Defined but not able to be configured");
312 my $sslProxyTable = $session->get_table( -baseoid =>
313 $dd->oiddef('4.x_sslProxyTable') );
315 if( defined( $sslProxyTable ) )
317 $devdetails->storeSnmpVars( $sslProxyTable );
318 $devdetails->setCap('BigIp_4.x_sslProxyTable');
320 my $ref = {};
321 $ref->{'indices'} = [];
322 $data->{'sslProxyTable'} = $ref;
324 for my $INDEX ( $devdetails->
325 getSnmpIndices( $dd->oiddef('4.x_sslProxyOrigIpAddress') ) )
327 push( @{$ref->{'indices'}}, $INDEX );
329 my $origIp = $devdetails->snmpVar(
330 $dd->oiddef('4.x_sslProxyOrigIpAddress')
331 . '.' . $INDEX );
333 my $origPort = $devdetails->snmpVar(
334 $dd->oiddef('4.x_sslProxyOrigPort')
335 . '.' . $INDEX );
337 my $destIp = $devdetails->snmpVar(
338 $dd->oiddef('4.x_sslProxyDestIpAddress')
339 . '.' . $INDEX );
341 my $destPort = $devdetails->snmpVar(
342 $dd->oiddef('4.x_sslProxyDestPort')
343 . '.' . $INDEX );
345 my $connLimit = $devdetails->snmpVar(
346 $dd->oiddef('4.x_sslProxyConnLimit')
347 . '.' . $INDEX );
351 my $nick = $origIp . '_' . $origPort . '_' . $destIp .
352 '_' . $destPort;
354 my $param = {};
355 $ref->{$INDEX}->{'param'} = $param;
356 $param->{'nick'} = $nick;
357 $param->{'descr'} = "Stats for SSL Proxy Address: " .
358 "${origIp}:${origPort} -> ${destIp}:${destPort}";
359 $param->{'INDEX'} = $INDEX;
360 $param->{'connLimit'} = $connLimit;
367 return 1;
371 sub buildConfig
373 my $devdetails = shift;
374 my $cb = shift;
375 my $devNode = shift;
376 my $data = $devdetails->data();
379 my $bigIpName = 'BigIp_Global_Stats';
381 my $bigIpParam = {
382 'precedence' => '-100',
383 'comment' => 'BigIp Global Stats',
384 'rrd-create-dstype' => 'GAUGE', };
386 if( $devdetails->hasCap('BigIp_4.x') )
388 my $bigIpStatsNode = $cb->addSubtree( $devNode, $bigIpName,
389 $bigIpParam, [ 'F5BigIp::BigIp_4.x' ]);
391 if( $devdetails->hasCap('BigIp_ssl') )
393 $cb->addTemplateApplication
394 ( $bigIpStatsNode , 'F5BigIp::BigIp_4.x_sslProxy_Global' );
397 elsif( $devdetails->hasCap('BigIp_3.x') )
399 $cb->addSubtree( $devNode, $bigIpName, $bigIpParam,
400 [ 'F5BigIp::BigIp_3.x' ]);
403 my $virtName = 'BigIp_VirtualServers';
405 my $virtParam = {
406 'precedence' => '-200',
407 'comment' => 'Virtual Server(VIP) Stats',
410 my $virtTree;
412 if( $devdetails->hasCap('BigIp_4.x_VirtualServer') )
414 my @templates =
415 ( 'F5BigIp::BigIp_4.x_virtualServer-actvconn-overview' );
416 # 'F5BigIp::BigIp_4.x_virtualServer-connrate-overview');
418 $virtTree =
419 $cb->addSubtree( $devNode, $virtName, $virtParam, \@templates );
421 my $ref = $data->{'virtualServer'};
423 for my $INDEX ( @{ $ref->{'indices'} } )
425 my $server = $ref->{$INDEX}->{'param'};
427 $server->{'precedence'} = '-100';
429 $cb->addSubtree( $virtTree, $server->{'nick'}, $server,
430 [ 'F5BigIp::BigIp_4.x_virtualServer' ] );
434 my $poolName = 'BigIp_Pools';
435 my $poolParam = {
436 'precedence' => '-300',
437 'comment' => 'Pool Stats',
440 my $poolTree;
442 if( $devdetails->hasCap('BigIp_4.x_PoolTable') )
444 $poolTree =
445 $cb->addSubtree( $devNode, $poolName, $poolParam,
446 ['F5BigIp::BigIp_4.x_pool-actvconn-overview']);
447 my $ref = $data->{'poolTable'};
449 for my $INDEX ( @{ $ref->{'indices'} } )
451 my $pool = $ref->{$INDEX}->{'param'};
453 $pool->{'precedence'} = '-100';
455 $cb->addSubtree( $poolTree, $pool->{'pool'}, $pool,
456 [ 'F5BigIp::BigIp_4.x_pool' ] );
461 my $poolMemberName = 'BigIp_Pool_Members';
463 my $poolMemberParam = {
464 'precedence' => '-400',
465 'comment' => 'Pool Member Stats',
468 my $poolMemberTree;
470 if( $devdetails->hasCap('BigIp_4.x_PoolMemberTable') )
472 $poolMemberTree =
473 $cb->addSubtree( $devNode, $poolMemberName, $poolMemberParam );
474 my $ref = $data->{'poolMemberTable'};
476 for my $INDEX ( @{ $ref->{'indices'} } )
478 my $poolMemberPoolTree;
479 my $lastPoolTree;
480 my $server = $ref->{$INDEX}->{'param'};
482 my $poolMemberPoolName = $server->{'pool'};
483 my $poolMemberPoolParam = {
484 'precidence' => '-100',
485 'comment' => "Members of the $server->{'pool'} Pool",
489 if( not defined( $lastPoolTree ) or
490 $poolMemberPoolName !~ /\b$lastPoolTree\b/ )
492 my @templates =
493 ( 'F5BigIp::BigIp_4.x_poolMember-actvconn-overview' );
494 $poolMemberPoolTree =
495 $cb->addSubtree( $poolMemberTree, $poolMemberPoolName,
496 $poolMemberPoolParam, \@templates );
498 $lastPoolTree = $poolMemberPoolName;
500 $server->{'precedence'} = '-100';
502 $cb->addSubtree( $poolMemberPoolTree, $server->{'nick'},
503 $server,
504 [ 'F5BigIp::BigIp_4.x_poolMember' ] );
510 # BigIP SSL Product Support
511 if( $devdetails->hasCap('BigIp_4.x_sslProxyTable') )
514 my $bigIpSSLProxies = 'BigIp_SSL_Proxies';
516 my $bigIpSSLParam = {
517 'comment' => 'BigIp SSL Proxies',
518 'rrd-create-dstype' => 'COUNTER', };
520 my $sslProxyTree = $cb->addSubtree(
521 $devNode, $bigIpSSLProxies, $bigIpSSLParam,
522 [ 'F5BigIp::BigIp_4.x_sslProxy-currconn-overview' ]);
524 my $ref = $data->{'sslProxyTable'};
526 for my $INDEX ( @{ $ref->{'indices'} } )
528 my $proxy = $ref->{$INDEX}->{'param'};
530 $cb->addSubtree( $sslProxyTree, $proxy->{'nick'}, $proxy,
531 [ 'F5BigIp::BigIp_4.x_sslProxy' ] );
536 return;
543 # Local Variables:
544 # mode: perl
545 # indent-tabs-mode: nil
546 # perl-indent-level: 4
547 # End: