import torrus 1.0.9
[freeside.git] / torrus / perllib / Torrus / DevDiscover / F5BigIp.pm
diff --git a/torrus/perllib/Torrus/DevDiscover/F5BigIp.pm b/torrus/perllib/Torrus/DevDiscover/F5BigIp.pm
new file mode 100644 (file)
index 0000000..e0d0770
--- /dev/null
@@ -0,0 +1,543 @@
+#  Copyright (C) 2003  Shawn Ferry
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software
+#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+# $Id: F5BigIp.pm,v 1.1 2010-12-27 00:03:48 ivan Exp $
+# Shawn Ferry <sferry at sevenspace dot com> <lalartu at obscure dot org>
+
+# F5 BigIp Load Balancer
+
+package Torrus::DevDiscover::F5BigIp;
+
+use strict;
+use Torrus::Log;
+
+
+$Torrus::DevDiscover::registry{'F5BigIp'} = {
+    'sequence'     => 500,
+    'checkdevtype' => \&checkdevtype,
+    'discover'     => \&discover,
+    'buildConfig'  => \&buildConfig
+    };
+
+our %oiddef =
+    (
+     # F5
+     'f5'                           => '1.3.6.1.4.1.3375',
+
+     '4.x_globalStatUptime'         => '1.3.6.1.4.1.3375.1.1.1.2.1.0',
+     '3.x_uptime'                   => '1.3.6.1.4.1.3375.1.1.50.0',
+
+     '4.x_globalAttrProductCode'    => '1.3.6.1.4.1.3375.1.1.1.1.5.0',
+
+     '4.x_virtualServer'            => '1.3.6.1.4.1.3375.1.1.3',
+     '4.x_virtualServerNumber'      => '1.3.6.1.4.1.3375.1.1.3.1.0',
+     '4.x_virtualServerTable'       => '1.3.6.1.4.1.3375.1.1.3.2',
+     '4.x_virtualServerIp'          => '1.3.6.1.4.1.3375.1.1.3.2.1.1',
+     '4.x_virtualServerPort'        => '1.3.6.1.4.1.3375.1.1.3.2.1.2',
+     '4.x_virtualServerPool'        => '1.3.6.1.4.1.3375.1.1.3.2.1.30',
+
+     '4.x_poolTable'                => '1.3.6.1.4.1.3375.1.1.7.2',
+     '4.x_poolName'                 => '1.3.6.1.4.1.3375.1.1.7.2.1.1',
+
+     '4.x_poolMemberTable'          => '1.3.6.1.4.1.3375.1.1.8.2',
+     '4.x_poolMemberPoolName'       => '1.3.6.1.4.1.3375.1.1.8.2.1.1',
+     '4.x_poolMemberIpAddress'      => '1.3.6.1.4.1.3375.1.1.8.2.1.2',
+     '4.x_poolMemberPort'           => '1.3.6.1.4.1.3375.1.1.8.2.1.3',
+
+     '4.x_sslProxyTable'            => '1.3.6.1.4.1.3375.1.1.9.2.1',
+     '4.x_sslProxyOrigIpAddress'    => '1.3.6.1.4.1.3375.1.1.9.2.1.1',
+     '4.x_sslProxyOrigPort'         => '1.3.6.1.4.1.3375.1.1.9.2.1.2',
+     '4.x_sslProxyDestIpAddress'    => '1.3.6.1.4.1.3375.1.1.9.2.1.3',
+     '4.x_sslProxyDestPort'         => '1.3.6.1.4.1.3375.1.1.9.2.1.4',
+     '4.x_sslProxyConnLimit'        => '1.3.6.1.4.1.3375.1.1.9.2.1.23',
+
+     );
+
+# from https://secure.f5.com/validate/help.jsp
+#HA (BIG-IP high availability software)
+#3DNS (3-DNS software)
+#LC (BIG-IP Link Controller software)
+#LB (BIG-IP Load Balancer 520)
+#FLB (BIG-IP FireGuard 520)
+#CLB (BIG-IP Cache Load Balancer 520)
+#SSL (BIG-IP eCommerce Load Balancer 520)
+#XLB (BIG-IP user-defined special purpose product for 520 platforms)
+#ISMAN (iControl Services Manager)
+
+our %f5_product = (
+    '1'     => { 'product' => 'indeterminate',  'supported' => 0, },
+    '2'     => { 'product' => 'ha',             'supported' => 1, },
+    '3'     => { 'product' => 'lb',             'supported' => 1, },
+    '4'     => { 'product' => 'threedns',       'supported' => 0, },
+    '5'     => { 'product' => 'flb',            'supported' => 0, },
+    '6'     => { 'product' => 'clb',            'supported' => 0, },
+    '7'     => { 'product' => 'xlb',            'supported' => 0, },
+    '8'     => { 'product' => 'ssl',            'supported' => 1, },
+    '10'    => { 'product' => 'test',           'supported' => 0, },
+    '99'    => { 'product' => 'unsupported',    'supported' => 0, },
+    );
+
+our %f5_sslGatewayLevel = (
+    '1'     => 'none',
+    '3'     => 'tps200',
+    '4'     => 'tps400',
+    '5'     => 'tps600',
+    '6'     => 'tps800',
+    '7'     => 'tps1000',
+    '9'     => 'tps500',
+    '10'    => 'tps1500',
+    '11'    => 'tps2000',
+    '99'    => 'unsupported',
+    );
+
+
+
+
+sub checkdevtype
+{
+    my $dd = shift;
+    my $devdetails = shift;
+    my $data = $devdetails->data();
+
+    # You would think globalAttrProductCode would work well
+    # I need more examples to see if ha(2) is specific to
+    # BipIP HA or any ha f5 product
+
+    if( not $dd->checkSnmpTable( 'f5' ) )
+    {
+        return 0;
+    }
+
+    return 1;
+}
+
+
+sub discover
+{
+    my $dd = shift;
+    my $devdetails = shift;
+
+    my $session = $dd->session();
+    my $data = $devdetails->data();
+
+    # SNMP on F5 boxes will become unresponsive over time with large
+    # enough oids-per-pdu values.  10 appears to work for everything however
+    # no exhaustive testing has been done to determine if a higer number
+    # could be used.
+    if( not defined( $data->{'param'}{'snmp-oids-per-pdu'} ) )
+    {
+        my $oidsPerPDU = $devdetails->param('F5BigIp::snmp-oids-per-pdu');
+        if( $oidsPerPDU == 0 )
+        {
+            $oidsPerPDU = 10;
+        }
+        $data->{'param'}{'snmp-oids-per-pdu'} = $oidsPerPDU;
+    }
+
+    # this is rather basic, per-capability checking
+    # may be required in the future
+
+    if( $dd->checkSnmpOID('4.x_globalStatUptime') )
+    {
+        $devdetails->setCap('BigIp_4.x');
+    }
+    elsif( $dd->checkSnmpOID('3.x_uptime') )
+    {
+        # for v3.x we are not supporting detailed stats, so don't check
+        # anything else
+        $devdetails->setCap('BigIp_3.x');
+        return 1;
+    }
+
+    my $product_name;
+    my $product_name;
+    my $result = $dd->retrieveSnmpOIDs( '4.x_globalAttrProductCode' );
+    my $product_code = $result->{'4.x_globalAttrProductCode'};
+
+    $product_name = %f5_product->{$product_code}->{'product'};
+    if( %f5_product->{$product_code}->{'supported'} )
+    {
+        $devdetails->setCap( 'BigIp_' . $product_name );
+    }
+    else
+    {
+        if( defined($product_name) )
+        {
+            Debug("Found an unsupported F5 product '$product_name'");
+        }
+        else
+        {
+            Debug("Found an unknown F5 product");
+        }
+        return 0;
+    }
+
+    my $poolTable = $session->get_table( -baseoid =>
+                                 $dd->oiddef('4.x_poolTable') );
+
+    if( defined( $poolTable ) )
+    {
+        $devdetails->storeSnmpVars( $poolTable );
+        $devdetails->setCap('BigIp_4.x_PoolTable');
+
+        my $ref = {};
+        $ref->{'indices'} = [];
+        $data->{'poolTable'} = $ref;
+
+        foreach my $INDEX ( $devdetails->
+                            getSnmpIndices( $dd->oiddef('4.x_poolName') ) )
+        {
+            push( @{$ref->{'indices'}}, $INDEX );
+            my $pool = $devdetails->snmpVar($dd->oiddef('4.x_poolName') .
+                                            '.' . $INDEX );
+
+            my $nick = $pool;
+            $nick =~ s/\W/_/g;
+            $nick =~ s/_+/_/g;
+
+            my $param = {};
+            $ref->{$INDEX}->{'param'} = $param;
+            $param->{'nick'} = $nick;
+            $param->{'pool'} = $pool;
+            $param->{'descr'} = "Stats for Pool $pool";
+            $param->{'INDEX'} = $INDEX;
+        }
+
+    }
+
+    my $poolMemberTable =
+        $session->get_table( -baseoid =>
+                             $dd->oiddef('4.x_poolMemberTable') );
+
+    if( defined( $poolMemberTable ) )
+    {
+        $devdetails->storeSnmpVars( $poolMemberTable );
+        $devdetails->setCap('BigIp_4.x_PoolMemberTable');
+
+        my $ref = {};
+        $data->{'poolMemberTable'} = $ref;
+
+        foreach my $INDEX
+            ( $devdetails->
+              getSnmpIndices( $dd->oiddef('4.x_poolMemberPoolName') ) )
+        {
+            push( @{ $ref->{'indices'} }, $INDEX );
+            my $pool =
+                $devdetails->snmpVar($dd->oiddef('4.x_poolMemberPoolName') .
+                                     '.' . $INDEX );
+            my $ip =
+                $devdetails->snmpVar($dd->oiddef('4.x_poolMemberIpAddress') .
+                                     '.' . $INDEX );
+            my $port =
+                $devdetails->snmpVar($dd->oiddef('4.x_poolMemberPort') .
+                                     '.' . $INDEX );
+
+            my $nick = "MEMBER_${pool}_${ip}_${port}";
+            $nick =~ s/\W/_/g;
+            $nick =~ s/_+/_/g;
+
+            my $param = {};
+            $ref->{$INDEX}->{'param'} = $param;
+            $param->{'nick'} = $nick;
+            $param->{'pool'} = $pool;
+            $param->{'descr'} = "Member of Pool $pool IP: $ip Port: $port";
+            $param->{'INDEX'} = $INDEX;
+        }
+
+    }
+
+    my $virtServerNumber = $dd->retrieveSnmpOIDs( '4.x_virtualServerNumber' );
+    if( $virtServerNumber->{'4.x_virtualServerNumber'} > 0 )
+    {
+        my $virtServer = $session->get_table( -baseoid =>
+                                          $dd->oiddef('4.x_virtualServer') );
+        if( defined( $virtServer ) )
+        {
+            $devdetails->storeSnmpVars( $virtServer );
+            $devdetails->setCap('BigIp_4.x_VirtualServer');
+
+            my $ref = {};
+            $data->{'virtualServer'} = $ref;
+
+            foreach my $INDEX
+                ( $devdetails->
+                  getSnmpIndices( $dd->oiddef('4.x_virtualServerIp') ) )
+            {
+                push( @{ $ref->{'indices'} }, $INDEX);
+                my $pool = $devdetails->snmpVar(
+                                $dd->oiddef('4.x_virtualServerPool') .
+                                '.' . $INDEX );
+                my $ip = $devdetails->snmpVar(
+                                $dd->oiddef('4.x_virtualServerIp') .
+                                '.' . $INDEX );
+                my $port = $devdetails->snmpVar(
+                                $dd->oiddef('4.x_virtualServerPort') .
+                                '.' . $INDEX );
+
+                my $param = {};
+                $ref->{$INDEX}->{'param'} = $param;
+
+                my $descr = "Virtual Server Pool: $pool IP: $ip Port: $port";
+                my $nick = "VIP_${pool}_${ip}_${port}";
+                $nick =~ s/\W/_/g;
+                $nick =~ s/_+/_/g;
+
+                $param->{'INDEX'} = $INDEX;
+                $param->{'descr'} = $descr;
+                $param->{'nick'} = $nick;
+                $param->{'pool'} = $pool;
+            }
+        }
+        else
+        {
+            Debug("Virtual Servers Defined but not able to be configured");
+        }
+    }
+
+    my $sslProxyTable = $session->get_table( -baseoid =>
+                            $dd->oiddef('4.x_sslProxyTable') );
+
+    if( defined( $sslProxyTable ) )
+    {
+        $devdetails->storeSnmpVars( $sslProxyTable );
+        $devdetails->setCap('BigIp_4.x_sslProxyTable');
+
+        my $ref = {};
+        $ref->{'indices'} = [];
+        $data->{'sslProxyTable'} = $ref;
+
+        foreach my $INDEX ( $devdetails->
+            getSnmpIndices( $dd->oiddef('4.x_sslProxyOrigIpAddress') ) )
+        {
+            push( @{$ref->{'indices'}}, $INDEX );
+
+            my $origIp = $devdetails->snmpVar(
+                    $dd->oiddef('4.x_sslProxyOrigIpAddress')
+                    . '.' .  $INDEX );
+
+            my $origPort = $devdetails->snmpVar(
+                    $dd->oiddef('4.x_sslProxyOrigPort')
+                    . '.' .  $INDEX );
+
+            my $destIp = $devdetails->snmpVar(
+                    $dd->oiddef('4.x_sslProxyDestIpAddress')
+                    . '.' .  $INDEX );
+
+            my $destPort = $devdetails->snmpVar(
+                    $dd->oiddef('4.x_sslProxyDestPort')
+                    . '.' .  $INDEX );
+
+            my $connLimit = $devdetails->snmpVar(
+                    $dd->oiddef('4.x_sslProxyConnLimit')
+                    . '.' .  $INDEX );
+
+
+
+            my $nick = $origIp . '_' . $origPort . '_' . $destIp .
+                    '_' . $destPort;
+
+            my $param = {};
+            $ref->{$INDEX}->{'param'} = $param;
+            $param->{'nick'} = $nick;
+            $param->{'descr'} = "Stats for SSL Proxy Address: " .
+                    "${origIp}:${origPort} -> ${destIp}:${destPort}";
+            $param->{'INDEX'} = $INDEX;
+            $param->{'connLimit'} = $connLimit;
+
+        }
+
+
+    }
+
+    return 1;
+}
+
+
+sub buildConfig
+{
+    my $devdetails = shift;
+    my $cb = shift;
+    my $devNode = shift;
+    my $data = $devdetails->data();
+
+
+    my $bigIpName = 'BigIp_Global_Stats';
+
+    my $bigIpParam = {
+        'precedence'         => '-100',
+        'comment'            => 'BigIp Global Stats',
+        'rrd-create-dstype'  => 'GAUGE', };
+
+    if( $devdetails->hasCap('BigIp_4.x') )
+    {
+        my $bigIpStatsNode = $cb->addSubtree( $devNode, $bigIpName,
+                $bigIpParam, [ 'F5BigIp::BigIp_4.x' ]);
+
+        if( $devdetails->hasCap('BigIp_ssl') )
+        {
+            $cb->addTemplateApplication
+                ( $bigIpStatsNode , 'F5BigIp::BigIp_4.x_sslProxy_Global' );
+        }
+    }
+    elsif( $devdetails->hasCap('BigIp_3.x') )
+    {
+        $cb->addSubtree( $devNode, $bigIpName, $bigIpParam,
+                         [ 'F5BigIp::BigIp_3.x' ]);
+    }
+
+    my $virtName = 'BigIp_VirtualServers';
+
+    my $virtParam = {
+        'precedence'        => '-200',
+        'comment'           => 'Virtual Server(VIP) Stats',
+    };
+
+    my $virtTree;
+
+    if( $devdetails->hasCap('BigIp_4.x_VirtualServer') )
+    {
+        my @templates =
+            ( 'F5BigIp::BigIp_4.x_virtualServer-actvconn-overview' );
+        #    'F5BigIp::BigIp_4.x_virtualServer-connrate-overview');
+
+        $virtTree =
+            $cb->addSubtree( $devNode, $virtName, $virtParam, \@templates );
+
+        my $ref = $data->{'virtualServer'};
+
+        foreach my $INDEX ( @{ $ref->{'indices'} } )
+        {
+            my $server = $ref->{$INDEX}->{'param'};
+
+            $server->{'precedence'} = '-100';
+
+            $cb->addSubtree( $virtTree, $server->{'nick'}, $server,
+                          [ 'F5BigIp::BigIp_4.x_virtualServer' ] );
+        }
+    }
+
+    my $poolName = 'BigIp_Pools';
+    my $poolParam = {
+        'precedence'        => '-300',
+        'comment'           => 'Pool Stats',
+    };
+
+    my $poolTree;
+
+    if( $devdetails->hasCap('BigIp_4.x_PoolTable') )
+    {
+        $poolTree =
+            $cb->addSubtree( $devNode, $poolName, $poolParam,
+                             ['F5BigIp::BigIp_4.x_pool-actvconn-overview']);
+        my $ref = $data->{'poolTable'};
+
+        foreach my $INDEX ( @{ $ref->{'indices'} } )
+        {
+            my $pool = $ref->{$INDEX}->{'param'};
+
+            $pool->{'precedence'} = '-100';
+
+            $cb->addSubtree( $poolTree, $pool->{'pool'}, $pool,
+                          [ 'F5BigIp::BigIp_4.x_pool' ] );
+        }
+
+    }
+
+    my $poolMemberName = 'BigIp_Pool_Members';
+
+    my $poolMemberParam = {
+        'precedence'        => '-400',
+        'comment'           => 'Pool Member Stats',
+    };
+
+    my $poolMemberTree;
+
+    if( $devdetails->hasCap('BigIp_4.x_PoolMemberTable') )
+    {
+        $poolMemberTree =
+            $cb->addSubtree( $devNode, $poolMemberName, $poolMemberParam );
+        my $ref = $data->{'poolMemberTable'};
+
+        foreach my $INDEX ( @{ $ref->{'indices'} } )
+        {
+            my $poolMemberPoolTree;
+            my $lastPoolTree;
+            my $server = $ref->{$INDEX}->{'param'};
+
+            my $poolMemberPoolName = $server->{'pool'};
+            my $poolMemberPoolParam = {
+                'precidence'    => '-100',
+                'comment'       => "Members of the $server->{'pool'} Pool",
+            };
+
+
+            if( not defined( $lastPoolTree ) or
+                $poolMemberPoolName !~ /\b$lastPoolTree\b/ )
+            {
+                my @templates =
+                    ( 'F5BigIp::BigIp_4.x_poolMember-actvconn-overview' );
+                $poolMemberPoolTree =
+                    $cb->addSubtree( $poolMemberTree, $poolMemberPoolName,
+                                     $poolMemberPoolParam, \@templates );
+
+                $lastPoolTree = $poolMemberPoolName;
+
+                $server->{'precedence'} = '-100';
+
+                $cb->addSubtree( $poolMemberPoolTree, $server->{'nick'}, $server,
+                              [ 'F5BigIp::BigIp_4.x_poolMember' ] );
+            }
+        }
+    }
+
+
+    # BigIP SSL Product Support
+    if( $devdetails->hasCap('BigIp_4.x_sslProxyTable') )
+    {
+
+        my $bigIpSSLProxies = 'BigIp_SSL_Proxies';
+
+        my $bigIpSSLParam = {
+            'comment'            => 'BigIp SSL Proxies',
+            'rrd-create-dstype'  => 'COUNTER', };
+
+        my $sslProxyTree = $cb->addSubtree(
+                    $devNode, $bigIpSSLProxies, $bigIpSSLParam,
+                    [ 'F5BigIp::BigIp_4.x_sslProxy-currconn-overview' ]);
+
+        my $ref = $data->{'sslProxyTable'};
+
+        foreach my $INDEX ( @{ $ref->{'indices'} } )
+        {
+            my $proxy = $ref->{$INDEX}->{'param'};
+
+            $cb->addSubtree( $sslProxyTree, $proxy->{'nick'}, $proxy,
+                    [ 'F5BigIp::BigIp_4.x_sslProxy' ] );
+        }
+
+    }
+
+}
+
+
+1;
+
+
+# Local Variables:
+# mode: perl
+# indent-tabs-mode: nil
+# perl-indent-level: 4
+# End: