ras-usage

Author Wim Nelis
Compatibility Xymon 4.2
Requirements Perl, unix
Download None
Last Update 2010-06-09

Script ras-usage.pl monitors the number of web users of a Juniper RAS cluster, as well as the state of each node in the cluster: active or passive. It is a server-side script, which uses SNMP to retrieve the information. It reports results in two tests, “usage” en “cluster”.

Test “usage” measures the number of web-users, and uses NCV to report it to Xymon. The number of active users is checked against the number of licenses. If more than 90% of the licenses are in use, the status of this test becomes yellow.

Test “cluster” shows which node is active and which nodes are passive. This test is reported both to the individual nodes and to the cluster service. If a node is passive, it's status will be “clear”. This allows Xymon to build a history of state changes, while a status change does not result in an alert.

As the script is a server-side script, all istallation steps below are performed at the Xymon server.

Copy script ras-usage.pl into an appropriate directory, typically ~xymon/server/ext. Modify the installation constants to match your environment. Those constants are shown between angle brackets, e.g. <Cluster>.

Edit file ~xymon/server/etc/hobbitserver.cfg:

TEST2RRD="....,usage=ncv"
GRAPHS="....,usage"
NCV_usage="usage:GAUGE"

Edit file ~xymon/server/etc/hobbitlaunch.cfg to include:

[usage]
        ENVFILE /home/xymon/server/etc/hobbitserver.cfg
        CMD /home/xymon/server/ext/ras-usage.pl
        LOGFILE $BBSERVERLOGS/ras-usage.log
        INTERVAL 5m

You might need to adapt the pathnames to match your environment.

Edit file ~xymon/server/etc/hobbitgraph.cfg to include:

[usage]
        TITLE , Concurrent usage
        YAXIS VPN clients []
        -l 0
        DEF:cnt=usage.rrd:usage:AVERAGE
#       DEF:max=usage.rrd:usage:MAX
#       CDEF:xtr=max,cnt,-
        AREA:cnt#00CC00:Usage
        GPRINT:cnt:MAX: Max\: %6.2lf %s
        GPRINT:cnt:AVERAGE:Avg\: %6.2lf %s
        GPRINT:cnt:LAST:Cur\: %6.2lf %s\n
#       AREA:xtr#0000CC:MaxUse:STACK
#       GPRINT:max:MAX:Max\: %6.2lf %s
#       GPRINT:max:AVERAGE:Avg\: %6.2lf %s
#       GPRINT:max:LAST:Cur\: %6.2lf %s

If you have defined the consolidation function (CF) MAX in the RRD created by Xymon, the comment lines can be un-commented to show the maximum use as well.

ras-usage.pl

Show ras-usage.pl ⇲

Hide ras-usage.pl ⇱

#!/usr/bin/perl -w
#
# RAS-usage: determine the number of users (VPN clients) of the Juniper
#  SA-2500 remote access cluster. All members of the cluster know how many
#  users there are. The result is reported to Xymon using the clustername
#  as hostname.
#
# - Added test cluster, which is reported for each multi-node cluster
#   showing which node is active and which node(s) are passive. Based
#   on ideas of Tom Schmitt.
#
use strict ;
use POSIX qw/ strftime / ;              # Format time

#
# Installation constants.
#
my $XyDisp= $ENV{BBSERVERHOSTNAME} ;    # Name of monitor server
my $XySend= $ENV{BB} ;                  # Monitor interface program
my $FmtDate= '%Y.%m.%d %H:%M:%S' ;      # Default date format
   $FmtDate= $ENV{BBDATEFORMAT} if defined $ENV{BBDATEFORMAT} ;
my $TestName= 'usage' ;                 # Xymon test name

#
# Define the Juniper RAS clusters.
# Each entry describes one cluster. The key of an entry is name of the cluster.
# The value of an entry is a reference to a list of names of the physical nodes
# in the cluster. It is assumed that the DNS name is equal to the Xymon name in
# all these cases.
#
my %Ras= (
        <cluster>  => [ '<Node-0>', '<Node-1>' ],
   ) ;
#
# Define the number of available licenses per cluster.
#
my %MaxUsers= (                         # Number of available licenses
        <cluster>  => <Count>,
   ) ;

#
# Define the SNMP query command to determine the number of users. The OIDs
# of interest in subtree .1.3.6.1.4.1.12532. are:
#   2.0 - Number of Signed-In Web Users
#   3.0 - Number of Signed-In Mail Users
#   9.0 - the number of concurrent meeting users
#  12.0 - The Total number of Users Logged In for the IVE Node
#  13.0 - The Total number of Users Logged In for the Cluster
#
my $SnmpUser   = 'snmpget -c <ComString> -v 2c %s .1.3.6.1.4.1.12532.2.0' ;

#
# Define the SNMP query to determine which physical server holds the Virtual
# IP address of the cluster.
#
my $SnmpCluster= 'snmpget -c <ComString> -v 2c %s .1.3.6.1.2.1.4.20.1.1.%s' ;

#
# Variable allocation.
#
my $Now= strftime( $FmtDate, localtime ) ;      # Timestamp of tests
my $HostName ;                          # Xymon host name
my $Server ;                            # RAS node name
my $Cmd ;                               # Full blown snmpget command
my $Color ;                             # Test status
my $Users ;                             # Number of users
my %Cluster ;                           # Status of cluster nodes
my @Lines ;                             # Command output
my $Result ;                            # Test result

#
# Function UnpackIp transforms a binary formatted IPv4 address into a
# dotted decimal encoded string.
#
sub UnpackIp($) { return join('.',unpack('C4',$_[0])) } ;

#
# Main program.
# -------------
#
foreach $HostName ( keys %Ras ) {
  $Color = 'green' ;                    # Preset variables
  $Users = undef ;
  $Result= '' ;

 #
 # -A- Determine for each cluster the number of web users.
 #
 # The number of users is retrieved from the nodes. It was found that an
 # `snmpget` often fails if it is directed to the cluster service.
 #
  foreach $Server ( @{$Ras{$HostName}} ) {
    $Cmd= sprintf( $SnmpUser, $Server ) ;
    @Lines= `$Cmd` ;
    next                        unless defined $Lines[0] ;
    next                        unless $Lines[0]=~ m/ = Gauge32: (\d+)\s*$/ ;
    $Users= $1 ;                        # Concurrent web users
    last ;
  }  # of foreach

  #
  # Determine the test status and build the tail of the message.
  #
  unless ( defined $Users ) {
    $Color= 'red' ;
    $Result= "&$Color Cluster members are not accessible.\"\n" ;
  } else {
    if ( $Users > 0.9 * $MaxUsers{$HostName} ) {
      $Color = 'yellow' ;
      $Result= "&$Color High number of users&#58; $Users\n" ;
    }  # of if
    $Result.= "<!--\nusage = $Users\n-->" ;
  }  # of else
  
  #
  # Build the header of the message, and send it to Xymon.
  #
  $Result= "\"status $HostName.$TestName $Color $Now\n" .
         "Number of users of Remote Access Service\n\n" .
         $Result . "\"\n" ;
  `$XySend $XyDisp $Result` ;           # Inform Xymon

 #
 # -B- Determine the cluster status of each multi-node cluster.
 #     Test 'cluster' shows which node is active, and which are passive.
 #
  next                          unless @{$Ras{$HostName}} > 1 ;

  $Color  = 'green' ;
  $Result = '' ;
  %Cluster= () ;
  my $VirtualIp= UnpackIp( gethostbyname($HostName) ) ;

  foreach $Server ( @{$Ras{$HostName}} ) {
    $Cmd= sprintf( $SnmpCluster, $Server, $VirtualIp ) ;
    @Lines= `$Cmd` ;
    if ( defined $Lines[0] ) {
      if ( $Lines[0]=~ m/$VirtualIp$/ ) {
        $Cluster{$Server}= [ 'green', "$Server is the active node in cluster $HostName" ] ;
        $Result.= "&green $Server  active node\n" ;
      } elsif ( $Lines[0]=~ m/No Such Instance currently exists at this OID$/ ) {
        $Cluster{$Server}= [ 'clear', "$Server is a passive node in cluster $HostName" ] ;
        $Result.= "&green $Server  passive node\n" ;
      } else {
        $Color  = 'yellow'      unless $Color eq 'red' ;
        $Cluster{$Server}= [ 'yellow', "$Server has sent an unrecognised response:\n" .
                                       "  $Lines[0]" ] ;
        $Result.= "&yellow $Server  unrecognised response\n" ;
      }  # of else
    } else {
      $Color  = 'red' ;
      $Cluster{$Server}= [ $Color, "$Server has sent no response" ] ;
      $Result.= "&$Color $Server  no response\n" ;
    }  # of else
  }  # of foreach

  #
  # Report the status of all nodes together for the cluster service.
  #
  $Result= "\"status $HostName.cluster $Color $Now\n" .
         "Node status in this cluster\n\n" .
         $Result . "\"\n" ;
  `$XySend $XyDisp $Result` ;           # Inform Xymon

  #
  # Report the individual node status to each node individually.
  #
  foreach $Server ( keys %Cluster ) {
    $Color = $Cluster{$Server}[0] ;
    $Result= "\"status $Server.cluster $Color $Now\n" .
           $Cluster{$Server}[1] . "\"\n" ;
    `$XySend $XyDisp $Result` ;         # Inform Xymon
  }  # of foreach
}  # of foreach

This script is used to monitor a two-node Juniper SA-2500 cluster. I assume it will work as well on the other Juniper RAS clusters.

Test “cluster” is an implementation of ideas of Tom Schmitt.

  • 2010-06-09
    • Initial release
  • monitors/rasusagepl.txt
  • Last modified: 2010/06/09 07:51
  • (external edit)