#! /usr/bin/perl
###############################################################################
#                                                                             #
#             Check a Riverbed Steelhead's health status via SNMP             #
#                                                                             #
###############################################################################
#
# Copyright (c) 2007 Simon Butcher <simon@butcher.name>
#
# 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
#
##############################################################################
#
#
# Performance data:
#    +-------+-----------------------------------------------+
#    | Field | Description                                   |
#    +-------+-----------------------------------------------+
#    |   1   | Model number				     |
#    |   2   | Serial number				     |
#    |   3   | Health (string)				     |
#    |   4   | Service status (string)			     |
#    |   5   | Software version string			     |
#    +-------+-----------------------------------------------+
#
##############################################################################


use Net::SNMP;
use Getopt::Std;

$script = "check_snmp_riverbed_steelhead";
$script_title =
  "Check a Riverbed Steelhead's health status via SNMP";
$script_version = "20070709";

# SNMP options
$version = "1";
$timeout = 2;

# Various SNMP OID prefixes to look at..
$oid_rbtsh			= ".1.3.6.1.4.1.17163.1.1"; # Steelhead
$oid_rbtsh_system		= ".1"; # System
$oid_rbtsh_system_model 	= ".1.0"; # System's model
$oid_rbtsh_system_serial	= ".2.0"; # System's serial number
$oid_rbtsh_system_version	= ".3.0"; # System's version string
$oid_rbtsh_status		= ".2"; # Status
$oid_rbtsh_status_healthstr	= ".2.0"; # Health status (string)
$oid_rbtsh_status_servicestr	= ".3.0"; # Service status (string)
$oid_rbtsh_status_healthenum    = ".7.0"; # Health as an enum
					  # (10000 = healthy,
					  #  30000 = degraded,
					  #  31000 = admission control
					  #  50000 = critical)
$oid_rbtsh_status_serviceenum	= ".8.0"; # Service status as an enum
					  # (0 = none,
					  #  1 = unmanaged,
					  #  2 = running,
					  #  3 = sentTerm1,
					  #  4 = sentTerm2,
					  #  5 = sentTerm3
					  #  6 = pending,
					  #  7 = stopped)


# Return values
$rbtsh_system_model = "Unknown";
$rbtsh_system_serial = "";
$rbtsh_system_version = "";
$rbtsh_status_healthstr = "Unknown";
$rbtsh_status_servicestr = "unknown";
$rbtsh_status_healthenum = -1;
$rbtsh_status_serviceenum = -1;

# Our return status - we start with 0 (OK) and hope for the best
$status = 0;

# Our return string with lots of interesting stuff in it
$returnstr = "";

# The SNMP hostname and community to use for the query
$hostname = "";
$community = "public";


# Grab the command line options
getopts("h:H:C:");

# If we didn't get any options, show some help and quit
if ($opt_h) {
    usage();
    exit(-1); # Unknown
}

# Get the hostname, if it was given..
if (defined($opt_H)) {
    $hostname = $opt_H;
} else {
    # We really need a hostname
    usage();
    exit(-1); # Unknown
}

# Get the SNMP community
if (defined($opt_C)) {
    $community = $opt_C;
}


# Initialise the SNMP session via the Net::SNMP perl module
my ($snmp_session, $snmp_error) = Net::SNMP->session(
    -community => $community,
    -hostname => $hostname,
    -version => $version,
    -timeout => $timeout,
);

# Grab interesting details
check_device();
    
# Shut down the SNMP session
$snmp_session->close();

# Return the return string and return status
print "$returnstr\n";
exit($status);


##############################################################################
##############################################################################
#
# Change the status level
#
sub status {
    my $newstatus = $_[0];

    # If the new status is greater than the old status, change the old status
    if ($newstatus > $status) {
	$status = $newstatus;
    }
}


##############################################################################
##############################################################################
#
# Grab a value from snmp
#
sub grab_snmp_value {
    my $this_oid = $_[0];
    my $this_value = "";

    # Try to grab the OID's value, if it exists
    if (defined($snmp_session->get_request($this_oid))) {
        foreach ($snmp_session->var_bind_names()) {
            $this_value = $snmp_session->var_bind_list()->{$_};
        }
    }

    # Return the value we got..
    return $this_value;
}


##############################################################################
##############################################################################
#
# Grab lots of interesting info from the probe
#
sub check_device {
    # Grab some values
    $rbtsh_system_model =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_system .
	    		$oid_rbtsh_system_model);
    $rbtsh_system_serial =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_system .
	    		$oid_rbtsh_system_serial);
    $rbtsh_system_version =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_system .
	    		$oid_rbtsh_system_version);
    $rbtsh_status_healthstr = 
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_status .
	    		$oid_rbtsh_status_healthstr);
    $rbtsh_status_servicestr =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_status .
	    		$oid_rbtsh_status_servicestr);
    $rbtsh_status_healthenum =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_status .
	    		$oid_rbtsh_status_healthenum);
    $rbtsh_status_serviceenum =
	grab_snmp_value($oid_rbtsh .
	    		$oid_rbtsh_status .
	    		$oid_rbtsh_status_serviceenum);


    
    # Check the health...
    if ($rbtsh_status_healthenum == 50000) { # Critical
	status(2); # Critical
    } elsif (($rbtsh_status_healthenum == 30000) || # Degraded
	     ($rbtsh_status_healthenum == 31000)) { # Admission control
	status(1); # Warning
    }
    
    # Check the optimisation process status
    if ($rbtsh_status_serviceenum == 7) { # Stopped
	status(2); # Critical
    } elsif ($rbtsh_status_serviceenum != 2) { # Running
	status(1); # Warning
    }
    
    # Build the return string
    if ($rbtsh_system_model == "") {
	$returnstr =
	  "No information returned from SNMP";
	status(2); # Critical
    } else {
	$returnstr = 
	    ("Steelhead " . 
	     $rbtsh_system_model . 
	     ": " .
	     $rbtsh_status_healthstr .
	     ", optimisation service: " .
	     $rbtsh_status_servicestr);
    }
    
    # Add on some performance monitoring stuff to the return string :)
    $returnstr =
	"$returnstr" .
        "|$rbtsh_system_model;$rbtsh_system_serial;$rbtsh_status_healthstr" .
        ";$rbtsh_status_servicestr;$rbtsh_system_version" .
	";";
}


##############################################################################
##############################################################################
#
# Usage information
#
sub usage {
    print << "USAGE";
$script ($script_version)
Copyright (c) 2007 Simon Butcher <simon@butcher.name>

$script_title

Usage: $script -H <hostname> [-C <community>]

Options:
    -H 	Hostname or IP address of the Steelhead appliance
    -C 	SNMP read community (default is $community)

USAGE
     exit(-1); # Unknown
}
