#! /usr/bin/perl
#
# ccme_phone_count.pl - check (via SNMP) a Cisco CME router to see how
# many phones are registered.
#
# 2008 Andrew J. Cosgriff, In Systems <ajc@insys.com.au>
#
# based on the distributed Lithium service monitoring scripts, and as
# such inherits their license.
#
##########
use XML::Simple;
use Net::SNMP;
use Data::Dumper;
use Time::HiRes qw(gettimeofday tv_interval);
use Data::Types qw(:all);

$NORMAL = "1";
$CONN_REFUSED = "2";
$CONN_TIMEOUT = "3";
$PROTO_TIMEOUT = "4";
$PROTO_ERROR = "5";

###################################
#  Script Configuration Variables
###################################
my $ccmeEphoneTotRegistered = ".1.3.6.1.4.1.9.9.439.1.2.3.0";

%infostruct = (  'version' => '1.0',
                 'desc'  => "CCME Registered Phone Count",
                 'proto' => "SNMP",
                 'port'  => "161",
                 'transport' => "UDP",
                 'info' => "Verifies the number of registered phones on a CCME router via SNMP",
                  'config_variable'=> [
		      {
			  'name' => 'community',
			  'desc' => 'SNMP Community String',
			  'required' => 1
		      },
		      {
			  'name' => 'min_phones',
			  'desc' => 'minimum number of phones, eg. 4',
			  'required' => 1
		      }
                 ]
            );

%objectstruct = ();

###################################
#  Command processing
###################################

($ARGV[0] eq "info") and ($#ARGV == 0) and
   print &generateXml($xmlroot, \%infostruct);
 
($ARGV[0] eq "object") and ($#ARGV == 0) and
   print &generateXml($xmlroot, \%objectstruct);
 
($ARGV[0] eq "check") and ($#ARGV != 0) and
  checkService($ARGV[$#ARGV]);

###################################
# Service Check/Testing
###################################

sub checkService
{
  # 1 Parameter: Filename for the config XML
  my ($filename) = @_;

  # Extract Variables from XML and store in %variables Hash
  %variables = &getVariables($filename);
   
  # Set IP 
  my $ip;
  if (is_string(%variables->{alt_ip}->{value})) { $ip = %variables->{alt_ip}->{value}; }
  else { $ip = %variables->{dev_ip}->{value}; }

  # Set Port
  my $port;
  if (is_string(%variables->{alt_port}->{value})) { $port = %variables->{alt_port}->{value}; }
  else { $port = '161'; }

  # Set Communit String
  my $community;
  if (is_string(%variables->{community}->{value})) { $community = %variables->{community}->{value}; }
  else { $community = 'public'; }

  # Set Route
  my $min_phones;
  if (is_string(%variables->{min_phones}->{value})) { $min_phones = %variables->{min_phones}->{value}; }

  # Get Start Time
  $tstart = [gettimeofday];

  #print Dumper(%variables);

  my ($sess, $error) = Net::SNMP->session(
      -hostname  => $ip,
      -community => $community,
      -port      => $port
      );
  
  if (!defined($sess)) {
      $message = "ERROR: %s. " . $error;
      $status = 5;
  } elsif (defined $min_phones) {
      my $result = $sess->get_request(-varbindlist => [$ccmeEphoneTotRegistered]);
      $tresp = [gettimeofday];

      if (defined $result->{$ccmeEphoneTotRegistered} and
	  $result->{$ccmeEphoneTotRegistered} ne "") {
	  my $count=$result->{$ccmeEphoneTotRegistered};
	  if ($count >= $min_phones) {
	      $message="OK: $count phones registered.";
	      $status = 1;
	  } else {
	      $message="ERROR: only $count phones registered.";
	      $status = 5;
	  }
      } else {
	  $message="ERROR: couldn\'t retrieve registered phone count.";
	  $status = 5;
      }
  } else {
    $status = 5;
    $message = "ERROR: min_phones not defined."
  }

  $ttrans = [gettimeofday];

  %resultstruct = ('metric'=> [
                    { 'name' => 'status', 'value' => $status, },
                    { 'name' => 'resptime', 'value' => tv_interval($tstart, $tresp), },
                    { 'name' => 'transtime', 'value' => tv_interval($tstart, $ttrans), },
                    { 'name' => 'message', 'value' => $message, },
                  ]);
  print &generateXml($xmlroot, \%resultstruct);
}


###########################################
# Standard Functions
###########################################

sub generateXml
{
  # Create the XML from dictionary/array. 
  # You don't have to make changes to this sub.
  # To make changes to these XML Structures:
  #   Modify %configstruct %objectstruct at the 
  #   begining of this file

  # Parameter 1: Temporary XML File
  my ($xmlrool) = $_[0];
  my (%struct) = %{$_[1]};
  
  my $xml = new XML::Simple(NoAttr=>1, RootName=>"service_script",XMLDecl=>1);
  $data = $xml->XMLout(\%struct);
  return "$data";
}

sub getVariables 
{
  # Parameter: Filename for the XML
  my ($filename) = @_;

  # ------>Collect XML Info Here <----------
  my $xml = new XML::Simple; # create new XML object
  my $data = $xml->XMLin($filename);
  my %variables =%{$data->{variable}};
  return %variables;
}
