#! /usr/bin/perl -w
# Check Microsoft Cluster Server (MSCS)
# via HP Management Agents for Server
#
# Plugin uses SNMP connection to server (CPQCLUS1.MIB).
#
# Copyright (C) 2007 by Herbert Stadler
# email: hestadler@gmx.at
# License Information:
# 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 3 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, see .
#
#
############################################################################
use POSIX;
use strict;
use Getopt::Long;
#use Data::Dumper;
use lib ".";
use lib "/usr/lib/nagios/plugins";
use lib "/usr/lib64/nagios/plugins";
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS);
use Net::SNMP qw(oid_lex_sort oid_base_match :debug);
my ($opt_version,$opt_help,$opt_verbose,$opt_pgo);
my ($opt_addhosts,$opt_timeout,$opt_license,$opt_quorumdisk);
my ($opt_hostname,$opt_community,$opt_port,$opt_snmpvers);
my ($opt_snmpdebug,$opt_snmptimeout);
my ($PROGNAME,$REVISION);
my ($state,$msg);
my ($g_snmpdebug);
my (@t_pgo);
my $DEFAULT_TIMEOUT =30;
my $DEFAULT_SNMPTIMEOUT =2;
# MIB OID's of CPQCLUS1.MIB
my $Cluster_oid ="1.3.6.1.4.1.232.15";
my $ClMibRev_group ="1.3.6.1.4.1.232.15.1";
my $ClMibRevMajor_scalar ="1.3.6.1.4.1.232.15.1.1.0";
my $ClMibRevMinor_scalar ="1.3.6.1.4.1.232.15.1.2.0";
my $ClMibCondition_scalar ="1.3.6.1.4.1.232.15.1.3.0";
my $ClOsCommon_group ="1.3.6.1.4.1.232.15.2.1.4";
my $ClOsCommonPollFreq_scalar ="1.3.6.1.4.1.232.15.2.1.4.1.0";
my $ClOsCommonModuleTable ="1.3.6.1.4.1.232.15.2.1.4.2";
my $ClOsCommonModuleEntry ="1.3.6.1.4.1.232.15.2.1.4.2.1";
my $ClOsCommonModuleIndex_tabular ="1.3.6.1.4.1.232.15.2.1.4.2.1.1";
my $ClOsCommonModuleName_tabular ="1.3.6.1.4.1.232.15.2.1.4.2.1.2";
my $ClOsCommonModuleVersion_tabular ="1.3.6.1.4.1.232.15.2.1.4.2.1.3";
my $ClOsCommonModuleDate_tabular ="1.3.6.1.4.1.232.15.2.1.4.2.1.4";
my $ClOsCommonModulePurpose_tabular ="1.3.6.1.4.1.232.15.2.1.4.2.1.5";
my $ClInfo_group ="1.3.6.1.4.1.232.15.2.2";
my $ClName_scalar ="1.3.6.1.4.1.232.15.2.2.1.0";
my $ClCondition_scalar ="1.3.6.1.4.1.232.15.2.2.2.0";
my $ClIpAddress_scalar ="1.3.6.1.4.1.232.15.2.2.3.0";
my $ClQuorumResource_scalar ="1.3.6.1.4.1.232.15.2.2.4.0";
my $ClMajorVersion_scalar ="1.3.6.1.4.1.232.15.2.2.5.0";
my $ClMinorVersion_scalar ="1.3.6.1.4.1.232.15.2.2.6.0";
my $ClCSDVersion_scalar ="1.3.6.1.4.1.232.15.2.2.7.0";
my $ClVendorId_scalar ="1.3.6.1.4.1.232.15.2.2.8.0";
my $ClResourceAggregateCondition_scalar="1.3.6.1.4.1.232.15.2.2.9.0";
my $ClNetworkAggregateCondition_scalar ="1.3.6.1.4.1.232.15.2.2.10.0";
my $ClNode_group ="1.3.6.1.4.1.232.15.2.3";
my $ClNodeTable ="1.3.6.1.4.1.232.15.2.3.1";
my $ClNodeEntry ="1.3.6.1.4.1.232.15.2.3.1.1";
my $ClNodeIndex_tabular ="1.3.6.1.4.1.232.15.2.3.1.1.1";
my $ClNodeName_tabular ="1.3.6.1.4.1.232.15.2.3.1.1.2";
my $ClNodeStatus_tabular ="1.3.6.1.4.1.232.15.2.3.1.1.3";
my $ClNodeCondition_tabular ="1.3.6.1.4.1.232.15.2.3.1.1.4";
my $ClResource_group ="1.3.6.1.4.1.232.15.2.4";
my $ClResourceTable ="1.3.6.1.4.1.232.15.2.4.1";
my $ClResourceEntry ="1.3.6.1.4.1.232.15.2.4.1.1";
my $ClResourceIndex_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.1";
my $ClResourceName_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.2";
my $ClResourceType_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.3";
my $ClResourceState_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.4";
my $ClResourceOwnerNode_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.5";
my $ClResourcePhysId_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.6";
my $ClResourceCondition_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.7";
my $ClResourceDriveLetter_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.8";
my $ClResourceIpAddress_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.9";
my $ClResourceGroupName_tabular ="1.3.6.1.4.1.232.15.2.4.1.1.10";
my $ClInterconnect_group ="1.3.6.1.4.1.232.15.2.5";
my $ClInterconnectTable ="1.3.6.1.4.1.232.15.2.5.1";
my $ClInterconnectEntry ="1.3.6.1.4.1.232.15.2.5.1.1";
my $ClInterconnectIndex_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.1";
my $ClInterconnectPhysId_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.2";
my $ClInterconnectTransport_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.3";
my $ClInterconnectAddress_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.4";
my $ClInterconnectNetworkName_tabular="1.3.6.1.4.1.232.15.2.5.1.1.5";
my $ClInterconnectNodeName_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.6";
my $ClInterconnectRole_tabular ="1.3.6.1.4.1.232.15.2.5.1.1.7";
my $ClNetwork_group ="1.3.6.1.4.1.232.15.2.6";
my $ClNetworkTable ="1.3.6.1.4.1.232.15.2.6.1";
my $ClNetworkEntry ="1.3.6.1.4.1.232.15.2.6.1.1";
my $ClNetworkIndex_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.1";
my $ClNetworkName_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.2";
my $ClNetworkAddressMask_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.3";
my $ClNetworkDescription_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.4";
my $ClNetworkRole_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.5";
my $ClNetworkState_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.6";
my $ClNetworkCondition_tabular ="1.3.6.1.4.1.232.15.2.6.1.1.7";
# Textual description of the different values
my %ClMibCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClResourceAggregateCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClNetworkAggregateCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClNodeStatus_val = (
1 => "other",
2 => "nodeUp",
3 => "nodeDown",
4 => "nodePaused",
5 => "nodeJoining",
);
my %ClNodeCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClResourceState_val = (
1 => "other",
2 => "online",
3 => "offline",
4 => "failed",
5 => "onlinePending",
6 => "offlinePending",
);
my %ClResourceCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
my %ClInterconnectRole_val = (
1 => "none",
2 => "client",
3 => "internal",
4 => "clientAndInternal",
);
my %ClNetworkRole_val = (
1 => "none",
2 => "client",
3 => "internal",
4 => "clientAndInternal",
);
my %ClNetworkState_val = (
1 => "other",
2 => "online",
3 => "offline",
4 => "partitioned",
5 => "unavailable",
);
my %ClNetworkCondition_val = (
1 => "other",
2 => "ok",
3 => "degraded",
4 => "failed",
);
$ENV{'PATH'}='';
$ENV{'BASH_ENV'}='';
$ENV{'ENV'}='';
$PROGNAME = "check_mscs_hpma";
$REVISION = "1.8";
# checking commandline arguments
my $arg_status = check_args();
if ($arg_status){
print "ERROR: some arguments wrong\n";
exit $ERRORS{"UNKNOWN"};
}
if ($opt_snmpdebug) {
my $module="Net::SNMP";
printf( "%-20s Version: %s\n", $module, $module->VERSION );
}
# set alarmhandler for timeouthandling
$SIG{'ALRM'} = sub {
print ("ERROR: plugin timed out after $opt_timeout seconds \n");
exit $ERRORS{"UNKNOWN"};
};
alarm($opt_timeout);
# build array of hostnames in the cluster
my @t_hostnames;
push @t_hostnames,$opt_hostname;
if (defined $opt_addhosts){
my @t_temphosts=split(/,/,$opt_addhosts);
foreach (@t_temphosts) {
push @t_hostnames,$_;
}
}
# check the hosts if they want to speak with us, maybe some are down
# we take the first who is answering
my $s_found=0;
foreach my $l_hostname (@t_hostnames) {
my ($snmp_session_tmp,$snmp_error_tmp)=open_snmp_session($l_hostname);
if ( ! defined ($snmp_session_tmp)) {
next;
}
$snmp_session_tmp->translate(['-endofmibview'=>0,'-nosuchobject'=>0,'-nosuchinstance'=>0]);
my @oid_tmp;
push @oid_tmp,$ClName_scalar;
my $l_snmp_result_tmp=$snmp_session_tmp->get_request(
-varbindlist => \@oid_tmp,
);
#if ( ! defined ($l_snmp_result_tmp)) {
if ($snmp_session_tmp->error_status != 0) {
$snmp_session_tmp->close;
next;
}
# this one speaks to us, should normally be the host defined with "-H"
$opt_hostname=$l_hostname;
$snmp_session_tmp->close;
$s_found++;
last;
}
if ($s_found == 0) {
print "CLUSTER ERROR: Could not open connection to the host(s), all probably down\n";
exit $ERRORS{'UNKNOWN'};
}
# now we have a host who wants to speak with us
my ($snmp_session,$snmp_error)=open_snmp_session($opt_hostname);
if ( ! defined ($snmp_session)) {
print "CLUSTER ERROR: Could not open connection: $snmp_error \n";
exit $ERRORS{'UNKNOWN'};
}
$snmp_session->translate(['-endofmibview'=>0,'-nosuchobject'=>0,'-nosuchinstance'=>0]);
# get Cluster OS Common Module Table
my $p_ClOsCommonModuleTable=get_cluster_info_get_table_request ($ClOsCommonModuleTable);
# get Cluster Node Table
my $p_ClNodeTable=get_cluster_info_get_table_request ($ClNodeTable);
# get Cluster Resource Table
my $p_ClResourceTable=get_cluster_info_get_table_request ($ClResourceTable);
# get Cluster Interconnect Table
my $p_ClInterconnectTable=get_cluster_info_get_table_request ($ClInterconnectTable);
# get Cluster Network Table
my $p_ClNetworkTable=get_cluster_info_get_table_request ($ClNetworkTable);
# Reading necessary OIDs
my $oids=build_oid_table();
my $p_ClOids=get_cluster_info_get_request ($oids);
$snmp_session->close;
# Check if Cluster is installed on server
if ( $p_ClOids->{$ClName_scalar} eq "noSuchObject" ) {
print "CLUSTER ERROR: Please check Cluster Installation, something wrong!\n";
exit $ERRORS{'UNKNOWN'};
}
my $l_quorum_holder=get_quorum_holder($p_ClOids->{$ClQuorumResource_scalar});
if ( $opt_verbose ) {
print_Cluster_Info ();
print_Cluster_MIB_Revision ();
print_Cluster_OS_Common ();
print_Cluster_Node ();
print_Cluster_Resource ();
print_Cluster_Interconnect ();
print_Cluster_Network ();
}
# set standard values for program exit
$msg = "CLUSTER OK - No Problems found";
$state = $ERRORS{'OK'};
my $l_tmsg;
# checking of condition and status flags for the returncode
if ( $ClCondition_val{$p_ClOids->{$ClCondition_scalar}} ne "ok" ) {
# the overall cluster condition is not OK
# get some status information from the cluster nodes
my $l_node_status=get_cluster_node_status();
# get some status information from the cluster resources
my $l_resource_status=get_cluster_resource_status();
# get some status information from the cluster network
my $l_network_status=get_cluster_network_status();
# build the output message
create_msg($l_node_status,\$l_tmsg);
create_msg($l_resource_status,\$l_tmsg);
create_msg($l_network_status,\$l_tmsg);
if ( $ClCondition_val{$p_ClOids->{$ClCondition_scalar}} eq "degraded" ) {
$state = $ERRORS{'WARNING'};
} else {
$state = $ERRORS{'CRITICAL'};
}
}
# and now we check if some cluster group failed-over to another node
my $l_GroupFailedOver_status=get_GroupFailedOver_status();
if (defined $l_GroupFailedOver_status) {
create_msg($l_GroupFailedOver_status,\$l_tmsg);
if ($state == $ERRORS{'OK'}){
$state = $ERRORS{'WARNING'};
}
}
if ($state == $ERRORS{'WARNING'}){
$msg = "CLUSTER WARNING - ".$l_tmsg;
}elsif ($state == $ERRORS{'CRITICAL'}){
$msg = "CLUSTER CRITICAL - ".$l_tmsg;
}
if ( $opt_quorumdisk ) {
$msg.=sprintf(" (QuDisk on: %s)",$l_quorum_holder);
}
# and now "over and out"
print "$msg\n";
exit $state;
#--------------------------------------------------------------------------#
# S U B R O U T I N E S #
#--------------------------------------------------------------------------#
sub open_snmp_session {
my ($l_host)=@_;
# open SNMP Session to Server
my ($snmp_session,$snmp_error)=Net::SNMP->session(
-hostname => $l_host,
-community => $opt_community || 'public',
-port => $opt_port || 161,
-timeout => $opt_snmptimeout,
-retries => 3,
-debug => $g_snmpdebug,
#-maxmsgsize => 16384,
-maxmsgsize => 32768,
-version => $opt_snmpvers,
);
return ($snmp_session,$snmp_error);
}
sub create_msg {
my ($l_txt,$l_msg)=@_;
if (! defined $l_txt) {return};
if (defined $$l_msg) {
$$l_msg.=", ";
}
$$l_msg.=$l_txt;
}
sub build_oid_table {
my @l_oids;
push @l_oids,$ClMibRevMajor_scalar;
push @l_oids,$ClMibRevMinor_scalar;
push @l_oids,$ClMibCondition_scalar;
push @l_oids,$ClOsCommonPollFreq_scalar;
push @l_oids,$ClName_scalar;
push @l_oids,$ClCondition_scalar;
push @l_oids,$ClIpAddress_scalar;
push @l_oids,$ClQuorumResource_scalar;
push @l_oids,$ClMajorVersion_scalar;
push @l_oids,$ClMinorVersion_scalar;
push @l_oids,$ClCSDVersion_scalar;
push @l_oids,$ClVendorId_scalar;
push @l_oids,$ClResourceAggregateCondition_scalar;
push @l_oids,$ClNetworkAggregateCondition_scalar;
return \@l_oids;
}
sub get_cluster_info_get_table_request {
my ($l_oid)=@_;
my $l_snmp_result=$snmp_session->get_table(
-baseoid => $l_oid
);
#if ( ! defined ($l_snmp_result)) {
if ($snmp_session->error_status != 0) {
printf ("ERROR %d: get_table_request: (%s) %s\n",$snmp_session->error_status,$l_oid,$snmp_session->error);
$snmp_session->close;
exit $ERRORS{'UNKNOWN'};
}
return $l_snmp_result;
}
sub get_cluster_info_get_request {
my ($l_oid)=@_;
my $l_snmp_result=$snmp_session->get_request(
-varbindlist => $l_oid,
);
#if ( ! defined ($l_snmp_result)) {
if ($snmp_session->error_status != 0) {
print "ERROR %d get_request: ",$snmp_session->error_status,$snmp_session->error,"\n";
$snmp_session->close;
exit $ERRORS{'UNKNOWN'};
}
return $l_snmp_result;
}
sub check_args {
Getopt::Long::Configure('bundling');
GetOptions
("V" => \$opt_version,
"version" => \$opt_version,
"L" => \$opt_license,
"license" => \$opt_license,
"v" => \$opt_verbose,
"verbose" => \$opt_verbose,
"D" => \$opt_snmpdebug,
"debug" => \$opt_snmpdebug,
"h|?" => \$opt_help,
"help" => \$opt_help,
"T=i" => \$opt_snmptimeout,
"snmptimeout=i" => \$opt_snmptimeout,
"t=i" => \$opt_timeout,
"timeout=i" => \$opt_timeout,
"H=s" => \$opt_hostname,
"hostname=s" => \$opt_hostname,
"o=s" => \$opt_pgo,
"cgowner=s" => \$opt_pgo,
"a=s" => \$opt_addhosts,
"addnodes=s" => \$opt_addhosts,
"C=s" => \$opt_community,
"community=s" => \$opt_community,
"p=i" => \$opt_port,
"port=i" => \$opt_port,
"s=s" => \$opt_snmpvers,
"snmpvers=s" => \$opt_snmpvers,
"Q" => \$opt_quorumdisk,
"qudisk" => \$opt_quorumdisk,
);
if ($opt_license) {
print_gpl($PROGNAME,$REVISION);
exit $ERRORS{'OK'};
}
if ($opt_version) {
print_revision($PROGNAME,$REVISION);
exit $ERRORS{'OK'};
}
if ($opt_help) {
print_help();
exit $ERRORS{'OK'};
}
if ( ! defined($opt_hostname)){
print "\nERROR: Hostname not defined\n\n";
print_usage();
exit $ERRORS{'UNKNOWN'};
}
unless (defined $opt_snmpvers) {
$opt_snmpvers = "snmpv2c";
}
if ( ($opt_snmpvers ne "snmpv1") && ($opt_snmpvers ne "snmpv2c") ){
print "\nERROR: SNMP version unknown\n\n";
print_usage();
exit $ERRORS{'UNKNOWN'};
}
unless (defined $opt_timeout) {
$opt_timeout = $DEFAULT_TIMEOUT;
}
unless (defined $opt_snmptimeout) {
$opt_snmptimeout = $DEFAULT_SNMPTIMEOUT;
}
unless (defined $opt_port) {
$opt_port = 161;
}
if (defined $opt_pgo) {
# Separation of DoubleSlash //
my @l_hlp1=split(/\/\//,$opt_pgo);
foreach my $l (@l_hlp1){
my ($l_node,$l_others)=split(/:/,$l);
my @l_hlp2=split(/,/,$l_others);
foreach my $g (@l_hlp2){
my @tmp=($l_node,$g);
push @t_pgo,\@tmp;
}
}
}
unless (defined $opt_quorumdisk) {
$opt_quorumdisk = 0;
}
if ($opt_snmpdebug) {
$g_snmpdebug = DEBUG_ALL;
}else{
$g_snmpdebug = DEBUG_NONE;
}
return $ERRORS{'OK'};
}
sub print_usage {
print "Usage: $PROGNAME [-h] [-L] [-Q] [-t timeout] [-T snmptimeout] [-v] [-V] [-C community] [-p port] [-s snmpv1|snmpv2c] [-a addhosts] [-o cgroupowner] -H hostname \n";
}
sub print_help {
print_revision($PROGNAME,$REVISION);
print "\n";
print_usage();
print "\n";
print " Check Microsoft Cluster Server via SNMP\n";
print " using HP Managements Agents.\n\n";
print "-t (--timeout) Timeout in seconds (default = $DEFAULT_TIMEOUT)\n";
print "-T (--snmptimeout) SNMP CallTimeout in seconds (default = $DEFAULT_SNMPTIMEOUT)\n";
print "-H (--hostname) Host to monitor\n";
print "-a (--addhosts) additional hosts in clustergroup '-a host1,host2' \n";
print "-o (--cgowner) preferred clustergroup owner e.g: \n";
print " '-o 'node1:group1,group2//node2:group3,group4'\n";
print "-s (--snmpvers) SNMP Version [snmpv1|snmpv2c]\n";
print "-C (--community) SNMP Community\n";
print "-p (--port) SNMP Port\n";
print "-h (--help) Help\n";
print "-Q (--qudisk) Print information in message on which server QDisk is attached\n";
print "-V (--version) Programm version\n";
print "-v (--verbose) Print some useful information\n";
print "-L (--license) Print license information\n";
print "\n\n";
}
sub print_Cluster_Info {
printhead ("Cluster Info");
print ("============\n");
printscalar ("Cluster Name", $p_ClOids->{$ClName_scalar});
printscalar ("Cluster Condition", $ClCondition_val{$p_ClOids->{$ClCondition_scalar}});
printscalar ("Cluster IpAddress", $p_ClOids->{$ClIpAddress_scalar});
my $l_quorum=get_quorum_resource($p_ClOids->{$ClQuorumResource_scalar});
printscalar ("Cluster QuorumResource", $l_quorum);
printscalar ("Cluster SW MajorVersion",$p_ClOids->{$ClMajorVersion_scalar});
printscalar ("Cluster SW MinorVersion",$p_ClOids->{$ClMinorVersion_scalar});
printscalar ("Cluster CSDVersion", $p_ClOids->{$ClCSDVersion_scalar});
printscalar ("Cluster VendorId", $p_ClOids->{$ClVendorId_scalar});
printscalar ("Cluster ResourceAggregateCondition", $ClResourceAggregateCondition_val{$p_ClOids->{$ClResourceAggregateCondition_scalar}});
printscalar ("Cluster NetworkAggregateCondition", $ClNetworkAggregateCondition_val{$p_ClOids->{$ClNetworkAggregateCondition_scalar}});
}
sub get_quorum_holder {
my ($l_index)=@_;
my $l_quorum_holder="";
if ($l_index =~/^\d+$/) {
if ($l_index >= 0) {
$l_quorum_holder=$p_ClResourceTable->{$ClResourceOwnerNode_tabular.".".$l_index};
}
}
return ($l_quorum_holder);
}
sub get_quorum_resource {
my ($l_index)=@_;
my $l_quorum="";
if ($l_index =~/^\d+$/) {
if ($l_index >= 0) {
$l_quorum=$p_ClResourceTable->{$ClResourceName_tabular.".".$l_index};
}
}
return $l_quorum;
}
sub print_Cluster_MIB_Revision {
printhead ("Cluster MIB Revision Group");
print ("==========================\n");
printscalar ("Cluster MibRevMajor", $p_ClOids->{$ClMibRevMajor_scalar});
printscalar ("Cluster MibRevMinor", $p_ClOids->{$ClMibRevMinor_scalar});
printscalar ("Cluster MibCondition", $ClMibCondition_val{$p_ClOids->{$ClMibCondition_scalar}});
}
sub print_Cluster_OS_Common {
printhead ("Cluster OS Common Group");
print ("=======================\n");
printscalar ("Os Poll Frequency in sec",$p_ClOids->{$ClOsCommonPollFreq_scalar});
printtable ("Cluster OS Common Module Table");
print ("==============================\n");
foreach my $l_key (oid_lex_sort(keys(%$p_ClOsCommonModuleTable))){
if (!(oid_base_match($ClOsCommonModuleIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClOsCommonModuleTable->{$l_key};
printtabular("Os Common Module Name", $p_ClOsCommonModuleTable->{$ClOsCommonModuleName_tabular.".".$l_val});
printtabular("Os Common Module Version", $p_ClOsCommonModuleTable->{$ClOsCommonModuleVersion_tabular.".".$l_val});
printtabular("Os Common Module Date", unpackDate($p_ClOsCommonModuleTable->{$ClOsCommonModuleDate_tabular.".".$l_val}));
printtabular("Os Common Module Purpose", $p_ClOsCommonModuleTable->{$ClOsCommonModulePurpose_tabular.".".$l_val});
print ("\n");
}
}
sub print_Cluster_Node {
printhead ("Cluster Node Group");
print ("==================\n");
printtable ("Cluster Node Table");
print ("==================\n");
foreach my $l_key (oid_lex_sort(keys(%$p_ClNodeTable))){
if (!(oid_base_match($ClNodeIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClNodeTable->{$l_key};
printtabular("Node Name", $p_ClNodeTable->{$ClNodeName_tabular.".".$l_val});
printtabular("Node Status", $ClNodeStatus_val{$p_ClNodeTable->{$ClNodeStatus_tabular.".".$l_val}});
printtabular("Node Condition",$ClNodeCondition_val{$p_ClNodeTable->{$ClNodeCondition_tabular.".".$l_val}});
print ("\n");
}
}
sub print_Cluster_Resource {
printhead ("Cluster Resource Group");
print ("======================\n");
printtable ("Cluster Resource Table");
print ("======================\n");
foreach my $l_key (oid_lex_sort(keys(%$p_ClResourceTable))){
if (!(oid_base_match($ClResourceIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClResourceTable->{$l_key};
printtabular("Resource Name", $p_ClResourceTable->{$ClResourceName_tabular.".".$l_val});
printtabular("Resource Type", $p_ClResourceTable->{$ClResourceType_tabular.".".$l_val});
printtabular("Resource State", $ClResourceState_val{$p_ClResourceTable->{$ClResourceState_tabular.".".$l_val}});
printtabular("Resource Owner Node", $p_ClResourceTable->{$ClResourceOwnerNode_tabular.".".$l_val});
printtabular("Resource PhysId", $p_ClResourceTable->{$ClResourcePhysId_tabular.".".$l_val});
printtabular("Resource Condition", $ClResourceCondition_val{$p_ClResourceTable->{$ClResourceCondition_tabular.".".$l_val}});
printtabular("Resource Drive Letter", $p_ClResourceTable->{$ClResourceDriveLetter_tabular.".".$l_val});
printtabular("Resource Ip Address", $p_ClResourceTable->{$ClResourceIpAddress_tabular.".".$l_val});
printtabular("Resource Group Name", $p_ClResourceTable->{$ClResourceGroupName_tabular.".".$l_val});
print ("\n");
}
}
sub print_Cluster_Interconnect {
printhead ("Cluster Interconnect Group");
print ("==========================\n");
printtable ("Cluster Interconnect Table");
print ("==========================\n");
foreach my $l_key (oid_lex_sort(keys(%$p_ClInterconnectTable))){
if (!(oid_base_match($ClInterconnectIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClInterconnectTable->{$l_key};
printtabular("Interconnect PhysId", $p_ClInterconnectTable->{$ClInterconnectPhysId_tabular.".".$l_val});
printtabular("Interconnect Transport", $p_ClInterconnectTable->{$ClInterconnectTransport_tabular.".".$l_val});
printtabular("Interconnect Address", $p_ClInterconnectTable->{$ClInterconnectAddress_tabular.".".$l_val});
printtabular("Interconnect Network Name",$p_ClInterconnectTable->{$ClInterconnectNetworkName_tabular.".".$l_val});
printtabular("Interconnect Node Name", $p_ClInterconnectTable->{$ClInterconnectNodeName_tabular.".".$l_val});
printtabular("Interconnect Role", $ClInterconnectRole_val{$p_ClInterconnectTable->{$ClInterconnectRole_tabular.".".$l_val}});
print ("\n");
}
}
sub print_Cluster_Network {
printhead ("Cluster Network Group");
print ("=====================\n");
printtable ("Cluster Network Table");
print ("=====================\n");
foreach my $l_key (oid_lex_sort(keys(%$p_ClNetworkTable))){
if (!(oid_base_match($ClNetworkIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClNetworkTable->{$l_key};
printtabular("Network Name", $p_ClNetworkTable->{$ClNetworkName_tabular.".".$l_val});
printtabular("Network Address Mask",$p_ClNetworkTable->{$ClNetworkAddressMask_tabular.".".$l_val});
printtabular("Network Description", $p_ClNetworkTable->{$ClNetworkDescription_tabular.".".$l_val});
printtabular("Network Role", $ClNetworkRole_val{$p_ClNetworkTable->{$ClNetworkRole_tabular.".".$l_val}});
printtabular("Network State", $ClNetworkState_val{$p_ClNetworkTable->{$ClNetworkState_tabular.".".$l_val}});
printtabular("Network Condition", $ClNetworkCondition_val{$p_ClNetworkTable->{$ClNetworkCondition_tabular.".".$l_val}});
print ("\n");
}
}
sub printhead {
my ($l_head)=@_;
printf ("\n%-40s\n",$l_head);
}
sub printtable {
my ($l_head)=@_;
printf ("%-40s\n",$l_head);
}
sub printscalar {
my ($l_arg,$l_oid)=@_;
printf ("%-35s: %-30s\n",$l_arg,$l_oid);
}
sub printtabular {
my ($l_arg,$l_oid)=@_;
printf ("%-35s: %-30s\n",$l_arg,$l_oid);
}
sub unpackDate {
my ($l_octet)=@_;
# field octets contents range
# ===== ====== ======= =====
# 1 1-2 year 0..65536
# 2 3 month 1..12
# 3 4 day 1..31
# 4 5 hour 0..23
# 5 6 minute 0..59
# 6 7 second 0..60
my @l_d=unpack("SCCCCC",$l_octet);
if ( $l_d[0] == 0 ) {
return "";
}
my $l_rdate=sprintf("%04d-%02-%02d %02d:%02d:%02d",$l_d[0],$l_d[1],$l_d[2],$l_d[3],$l_d[4],$l_d[5]);
return ($l_rdate);
}
sub print_gpl {
print <.
EOD
}
sub print_revision {
my ($l_prog,$l_revision)=@_;
print <{$l_key};
if ($ClNodeCondition_val{$p_ClNodeTable->{$ClNodeCondition_tabular.".".$l_val}} ne "ok" ) {
if ( defined $l_txt ) {
$l_txt.=", ";
}
$l_txt.=$p_ClNodeTable->{$ClNodeName_tabular.".".$l_val}.": ".$ClNodeStatus_val{$p_ClNodeTable->{$ClNodeStatus_tabular.".".$l_val}};
}
}
return $l_txt;
}
sub get_cluster_resource_status {
my $l_txt;
foreach my $l_key (oid_lex_sort(keys(%$p_ClResourceTable))){
if (!(oid_base_match($ClResourceIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClResourceTable->{$l_key};
if ( $ClResourceCondition_val{$p_ClResourceTable->{$ClResourceCondition_tabular.".".$l_val}} ne "ok" ) {
if ( defined $l_txt ) {
$l_txt.=", ";
}
$l_txt.=$p_ClResourceTable->{$ClResourceName_tabular.".".$l_val}.": ".$ClResourceState_val{$p_ClResourceTable->{$ClResourceState_tabular.".".$l_val}};
}
}
return $l_txt;
}
sub get_cluster_network_status {
my $l_txt;
foreach my $l_key (oid_lex_sort(keys(%$p_ClNetworkTable))){
if (!(oid_base_match($ClNetworkIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClNetworkTable->{$l_key};
if ($ClNetworkCondition_val{$p_ClNetworkTable->{$ClNetworkCondition_tabular.".".$l_val}} ne "ok" ) {
if ( defined $l_txt ) {
$l_txt.=", ";
}
$l_txt.=$p_ClNetworkTable->{$ClNetworkName_tabular.".".$l_val}.": ".$ClNetworkState_val{$p_ClNetworkTable->{$ClNetworkState_tabular.".".$l_val}};
}
}
return $l_txt;
}
sub get_GroupFailedOver_status {
my $l_txt;
my %h_pgo;
foreach my $l_key (oid_lex_sort(keys(%$p_ClResourceTable))){
if (!(oid_base_match($ClResourceIndex_tabular,$l_key))) {
next;
}
my $l_val=$p_ClResourceTable->{$l_key};
my $l_ro =$p_ClResourceTable->{$ClResourceOwnerNode_tabular.".".$l_val};
my $l_rg =$p_ClResourceTable->{$ClResourceGroupName_tabular.".".$l_val};
$h_pgo{$l_ro}{$l_rg}="dummy";
}
foreach my $x (@t_pgo) {
#print "$$x[0],$$x[1]\n";
# $$x[0] = owner node
# $$x[1] = group name
if (defined $h_pgo{$$x[0]}{$$x[1]}){
next;
} else {
if (defined $l_txt ) {
$l_txt.=", ";
}
if ( ! defined $l_txt ) {
$l_txt.="FailedOver: ";
}
$l_txt.=$$x[1];
}
}
return $l_txt;
}
#__END__
=head1 NAME
check_mscs_hpma
=head1 DESCRIPTION
Checking Microsoft Cluster Server via SNMP protocol.
HP Managements Agents have to be installed on the Server.
Plugin created for Nagios Monitoring.
=head1 SYNOPSIS
check_mscs_hpma -H
To check some additional hosts in the cluster group (in case of a
server down of the primary node).
check_mscs_hpma -H -a ,
To check if a cluster group is running on the preferred node,
you can enter nodes with the defined groups:
check_mscs_hpma -H
-o "node1:group1,group2//node2:group3,group4"
If group1 is not running on node1 a warning will be given to nagios.
for more information call:
check_mscs_hpma -h
=head1 AUTHOR
Herbert Stadler, Austria (hestadler@gmx.at)
December 2007
This plugin is my contribution to the nagios community.
=head1 REQUIRED SOFTWARE
from search.cpan.org
Net::SNMP Package e.g: Net-SNMP-5.2.0.tar.gz
Used MIB (not necessary for executing the script)
CPQCLUS1.MIB
easy to find on "www.mibdepot.com" (enterprise compaq)
=head1 HOW TO CHECK THE WINDOWS SERVER FUNCTIONALITY
snmpwalk 172.29.130.201 -v2c -c public enterprises.232.15
should return a lot of lines like these:
SNMPv2-SMI::enterprises.232.15.1.1.0 = INTEGER: 1
SNMPv2-SMI::enterprises.232.15.1.2.0 = INTEGER: 3
SNMPv2-SMI::enterprises.232.15.1.3.0 = INTEGER: 3
SNMPv2-SMI::enterprises.232.15.2.1.4.1.0 = INTEGER: 120
SNMPv2-SMI::enterprises.232.15.2.1.4.2.1.1.0 = INTEGER: 0
SNMPv2-SMI::enterprises.232.15.2.1.4.2.1.1.1 = INTEGER: 1
SNMPv2-SMI::enterprises.232.15.2.1.4.2.1.2.0 = STRING: "CPQCLUS.DLL"
SNMPv2-SMI::enterprises.232.15.2.1.4.2.1.2.1 = STRING: "HOSTMIB.DLL"
if not, check on windows server if "Clustering Information"
is an "Active Agent".
how can I check this ?
Control Panel
HP-Management Agents
Clustering Information (in Active Agents)
=head1 CONFIGURATION IN NAGIOS
Copy this plugin to the nagios plugin installation directory
e.g.: /usr/lib(64)/nagios/plugins
COMMAND DEFINITION:
# "check_mscs_hpma" command definition
define command{
command_name check_mscs_hpma
command_line $USER1$/check_mscs_hpma -H $HOSTADDRESS$
}
# "check_mscs_hpma_a" command definition with additional cluster nodes
define command{
command_name check_mscs_hpma_a
command_line $USER1$/check_mscs_hpma -H $HOSTADDRESS$ -a $ARG1$
}
# "check_mscs_hpma_ao" command definition with additional cluster nodes
# and clustergroup checking
# Please use apostrophes in case you have clustergroup definitions
# with spaces (like "SQL Server Group") for option "-o"
define command{
command_name check_mscs_hpma_a
command_line $USER1$/check_mscs_hpma -H $HOSTADDRESS$ -a $ARG1$
-o "$ARG2"
}
=head1 PLUGIN HISTORY
Version 1.8 - 2010-03-24 check error_status of snmp call
Version 1.7 - 2009-08-31 Checking if Cluster is installed and running
Version 1.6 - 2009-02-20 Debugging Parameter -D added
Parameter -T added
Version 1.5 - 2009-02-17 print OID in case of error
function get_cluster_info_get_table_request
Version 1.4 - 2008-11-26 show quorum disk holder (node) in message (flag -Q)
additional library path added
Version 1.3 - 2008-09-26 separation of parameters of -o option changed
from ";" to "//" because ";" is start of
comment under nagios control
Version 1.2 - 2007-12-19 fixed problem with **ePN
(Missing right curly or square ...)
Version 1.1 - 2007-12-04 small changes in documentation
Version 1.0 - 2007-12-01 first release
=head1 COPYRIGHT AND DISCLAIMER
Copyright (C) 2007 by Herbert Stadler
email: hestadler@gmx.at
License Information:
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 3 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, see .
=cut