Datapower monitoring

Posted by on Nov 24, 2012 in ITM6 | No Comments

Datapower devices return a number of different metrics for the various parts of the device.  To gather the metrics you can send SNMP get requests to the devices.

The following script takes a argument about which metric you want to gather the information for and then uses a configuration file which holds the server name and community name to gather the metrics from.  It will perform the queries in parallel to help in the processing of a number of Datapower devices as the default time-out for the SNMP query is 15 seconds.

It will do a simple query to all devices first to make sure that they are up then it will perform the query requested.

The following are the list of metrics that can be requested:

  • PING
  • MessageDurations
  • MessageCounts
  • CPUUsage
  • MemoryStatus
  • FilesystemStatus
  • ReceiveKbpsThroughput
  • TransmitKbpsThroughput
  • HTTPConnections
  • SystemUsageLoad
  • Environmental
  • ActiveUsersSessions

If no data is returned for a Datapower device then no result is shown with the exception on the PING request which always returns either up or down for all devices.

Some of the queries will only query against one community name even though you have multiple community names for a Datapower device this is because the metrics returned are for the whole Datapower device and not community specific.  The following metrics are community specific:

  • MessageDurations
  • MessageCounts
#!/usr/bin/perl

################################################################################################
# Function : Script dataprovider for SNMP queries. This allows for mulitple community names for
# : for the one server which the SNMP data provider can not do.
# : This will query the server for the OID specified and all child objects from that
# : OID for the supplied servers and community names in the configuration file
#
# History : Name Date Ver Details
# : James Potter 01/12/2008 1.0 Script created
# : James Potter 04/11/2010 1.2 Updated to only check base CPU, Mem and Users on
# the first datapower server not for each community
# : James Potter 04/11/2010 2.0 Re-writen to work using threading
# : James Potter 20/05/2011 2.1 Updated to include new stats
#
# Input : OID Query Object
# : Configuration file - colon deliminated logfile in custom dir (*snmp_server_list*)
# : server name:community name
#
# Output : Messages to ITM6
#
# Run Loc : ITM6 agent - called from the MDL
# Usage : //SOURCE SCRIPT /usr/bin/perl datapower_query.pl "CPUUsage"
################################################################################################

use threads;
use threads::shared;
my (@threads);

$|=1;

# holds the OIDs for each of the query types
my %queryOIDs = ("PING", "1.3.6.1.4.1.14685.3.1.3",
                 "MessageDurations", "1.3.6.1.4.1.14685.3.1.58.1",
                 "MessageCounts", "1.3.6.1.4.1.14685.3.1.56.1",
                 "CPUUsage", "1.3.6.1.4.1.14685.3.1.14",
                 "MemoryStatus", "1.3.6.1.4.1.14685.3.1.5",
                 "ActiveUsersSessions", "1.3.6.1.4.1.14685.3.1.1.1",
                 "FilesystemStatus", "1.3.6.1.4.1.14685.3.1.29",
                 "ReceiveKbpsThroughput", "1.3.6.1.4.1.14685.3.1.24",
                 "TransmitKbpsThroughput", "1.3.6.1.4.1.14685.3.1.26",
                 "HTTPConnections", "1.3.6.1.4.1.14685.3.1.30",
                 "Environmental", "1.3.6.1.4.1.14685.3.1.55",
                 "SystemUsageLoad", "1.3.6.1.4.1.14685.3.1.52"
                );

# holds whether the query needs to be run on the specific community or once per device
# 1 = only on one device
# 0 = on all communities
my %queryType = ("PING", "1",
                 "MessageDurations", "0",
                 "MessageCounts", "0",
                 "CPUUsage", "1",
                 "MemoryStatus", "1",
                 "FilesystemStatus", "1",
                 "ReceiveKbpsThroughput", "1",
                 "TransmitKbpsThroughput", "1",
                 "HTTPConnections", "1",
                 "SystemUsageLoad", "1",
                 "Environmental", "1",
                 "ActiveUsersSessions", "1"
                );

my %statusDetails = (1, "Responding",
                     0, "Not Responding"
                    );

my %serverStatus;                                 # holds whether ping query responds for each device
my %allServers;                                   # holds the details of the communties for each of the devices

################################################################################################
# should not need to change the following
################################################################################################
my $is_ha = "false";                                       # flag if this is to check for HA
my $tag=$0;                                                # sets the tag to the name of the script
$tag =~s/^(.*\/)*(\w+)\.pl/$2/;                            # strips off leading directory structure and trailing extension
my $monitoring_code="DAP";
my $link_location = "./";            # location for custom monitoring links
################################################################################################

my $runQuery = $ARGV[0];
if ($runQuery eq "") {
  $runQuery = "PING";
}

# Builds a list of all the devices and there communities being run against
if (opendir(D,$link_location)) {
  @files=grep(/snmp_server_list/i,readdir(D));
  foreach $f (@files) {
    open(F,"$link_location/$f");
    while(<F>) {
      s/^\s*|\s*$|\n//g;
      if (/^#/) { next; }
      if ($_ eq "") { next; }
      my ($serverName, $community) = split(/:/);
      $allServers{$serverName} .= $community . ":";
    }
    close F;
  }
  closedir D;
}

# goes though each community and checks the status of each so that we don''t run queries against devices that arn''t responding
# this will check the default community if it is defined otherwise the first community found for the device
foreach my $serverName(keys(%allServers)) {
  if ($allServers{$serverName} =~ /default/) {
    push(@threads, threads->new(\&getDPStatus,$serverName, "default", $queryOIDs{PING}));
  } else {
    $allServers{$serverName} =~ s/:$//g;
    my @serverCommunities = split(/:/,$allServers{$serverName});
    push(@threads, threads->new(\&getDPStatus,$serverName, $serverCommunities[0], $queryOIDs{PING}));
  }
}

# go though each thread and get the results
foreach my $myThread(@threads)
{
    my @returnData = $myThread->join ;
    $serverStatus{$returnData[0]} = $returnData[1];
}

if ($runQuery eq "PING") {
  # goes though the results and outputs the ping results
  foreach my $serverName (keys(%serverStatus)) {
    if ($serverStatus{$serverName}) {
      print "5:$serverName:default:${serverName}_default:Datapower device $serverName is responding\n";
    } else {
      print "2:$serverName:default:${serverName}_default:Datapower device $serverName is NOT responding\n";
    }
  }
  exit;                                                        # we don''t need to check anything else as we just need ping status
}

undef @threads;

# query each of the devices for the specific details
foreach my $serverName (keys(%serverStatus)) {
  if ($serverStatus{$serverName}) {
    $allServers{$serverName} =~ s/:$//g;
    if ($queryType{$runQuery}) {   # if this is only required on individual server not all communities
      if ($allServers{$serverName} =~ /default/) {
        push(@threads, threads->new(\&getDPQuery,$serverName, "default", $queryOIDs{$runQuery}));
      } else {
        my @serverCommunities = split(/:/,$allServers{$serverName});
        push(@threads, threads->new(\&getDPQuery,$serverName, $serverCommunities[0], $queryOIDs{$runQuery}));
      }
    } else {
      my @serverCommunities = split(/:/,$allServers{$serverName});
      foreach my $communityName (@serverCommunities) {
        push(@threads, threads->new(\&getDPQuery,$serverName, $communityName, $queryOIDs{$runQuery}));
      }
    }
  }
}

# go though each thread and get the results
foreach my $myThread(@threads)
{
    my @returnData = $myThread->join ;
    my @detailedData = split(/¬/,$returnData[2]);
    foreach(@detailedData) {
      print "$_\n";
    }
    #$serverStatus{$returnData[0]} = $returnData[1];
}

exit;

################################################################################################################
# Function : queries the PING OID and returns Available / Unavailable status
# History  : Name            Date        Ver   Details
#          : James Potter    05/04/2011  1.0   Funcation created
# Input    : Server Name
#          : Community Name
#          : OID to query
# Output   : Server Name
#          : Status (1 = Available, 0 = Unavailable)
# Run Loc  : NA
# Usage    : push(@threads, threads->new(\&getDPStatus,$serverName, $serverCommunities[0], $queryOIDs{PING}));
################################################################################################################
sub getDPStatus
{
    my ($serverName, $community, $queryOID) = @_;
    my $snmpqueryStatus = 1;

    my @snmpData = `/usr/sbin/snmpinfo -t 1 -m next -h $serverName -c $community $queryOID 2>&1`;
    #print "/usr/sbin/snmpinfo -t 1 -m next -h $serverName -c $community $queryOID \n";
    foreach (@snmpData) {
      $snmpLine =~ s/^\s*|\s*$|\n//g;
      if (/No response|unknown host/) { $snmpqueryStatus = 0; next; }
    }
    return( $serverName, $snmpqueryStatus );
}

################################################################################################################
# Function : queries Various OIDs and returns details from that OID
# History  : Name            Date        Ver   Details
#          : James Potter    05/04/2011  1.0   Funcation created
# Input    : Server Name
#          : Community Name
#          : OID to query
# Output   : Server Name
#          : Status (1 = Available, 0 = Unavailable)
#          : OID Details - String (: separated per element with ¬ separated per OID details per device
# Run Loc  : NA
# Usage    : push(@threads, threads->new(\&getDPQuery,$serverName, $communityName, $queryOIDs{$runQuery}));
################################################################################################################
sub getDPQuery
{
    my ($serverName, $community, $queryOID) = @_;
    my $snmpqueryStatus = 1;
    my $maxInstance = -1;
    my $minInstance = 999999999;

    my @snmpData = `/usr/sbin/snmpinfo -t 1 -m dump -h $serverName -c $community $queryOID 2>&1`;
    foreach (@snmpData) {
      $snmpLine =~ s/^\s*|\s*$|\n//g;
print "DEBUG:$_:\n";
      if (/No response|unknown host/) { $snmpqueryStatus = 0; next; }

      my $oid;
      my $value;
      my $baseOid;
      my $instanceId;

      ($oid,$value) = split / = /, $_ , 2;
      if ($value =~ /:/) {
        $value =~ s/^\s*|\s*$//g;
        my $oldValue = $value;
        $value = pack ("H*", join ( '''' , split (/:/ , $value))); # strip out the semi colons and then convert from hex to ascii
        if ($value !~ /^([\012\014\015\040-\176])*$/) {
          $oldValue =~ s/:/_/g;
          $value = $oldValue;
        }
      }
      $value =~ s/^\s*|\s*$|\n//g;

      $oid =~ /(.*)\.(\d+)/;  # just capture the last digit of the oid as this corresponds to the instance number
      $baseOid = $1;
      $instanceId = $2;

      if ($instanceId > $maxInstance) { $maxInstance = $instanceId; }
      if ($instanceId < $minInstance) { $minInstance = $instanceId; }

      my $arrayName = $serverName . "_" . $community . "_" . $instanceId;
      push(@{$arrayName}, $value);

      #print "$serverName : $baseOid : $instanceId : $value :\n";
      #print "$arrayName : $value :\n";
    }

    my $outputDetails;

    for (my $i = $minInstance; $i <= $maxInstance; $i++) {
      my $arrayName = $serverName . "_" . $community . "_" . $i;
      if (scalar @{$arrayName} > 0) {
        $outputDetails .= "$serverName:$community:${serverName}_${community}";
        foreach(@{$arrayName}) {
          $outputDetails .= ":$_";
        }
      }
      $outputDetails .= "¬";
    }
    $outputDetails =~ s/¬$//g;
    return( $serverName, $snmpqueryStatus, $outputDetails);
}

Leave a Reply