#!/usr/bin/perl # # AUTHORS: # Copyright (C) 2008 Altinity Limited # Written by Neil Ferguson, kindly sponsored by GotVMail # # This file is part of Opsview # # Opsview 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. # # Opsview 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 Opsview; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # use strict; use lib qw ( /usr/local/nagios/perl/lib ); use Net::SNMP; use Getopt::Std; # About us my $script = "check_snmp_vmware_memory"; my $script_version = "0.3"; my $hostname = ''; # SNMP variables my $oid_sysDescr = ".1.3.6.1.2.1.1.1.0"; # Used to check whether SNMP is actually responding my $oid_namebase = ".1.3.6.1.4.1.6876.2.1.1.2."; my $oid_vmidbase = ".1.3.6.1.4.1.6876.2.1.1.7."; my $oid_vmbase = ".1.3.6.1.4.1.6876."; my $oid_host_mem = "3.2.1.0"; my $oid_sc_mem = "3.2.2.0"; my $oid_vm_mem = "3.2.4.1.4."; my $community = "public"; # Default community my $timeout = 10; # SNMP timeout my $retval = 3; # Innocent until proven guilty my $retmsg = ""; # Text to return from plugin my $perfdata = ""; # Performance data my $version = "2c"; my $warning = 0; my $critical = 0; my $result_text = 0; my $mem_total = 0; my $sc_mem = 0; my $mem_used = 0; my $vm_name = ""; my $percent_used = 0; my $perf_data_percent = 0; our ( $s, $e ); # Command line arguments our ( $opt_h, $opt_H, $opt_C, $opt_t, $opt_w, $opt_c, $opt_a, $opt_v, $opt_p ); getopts("hH:C:t:w:c:av:p"); if ($opt_h) { usage(); exit 0; } if ($opt_H) { $hostname = $opt_H; } else { print "No hostname specified\n"; usage(); exit 3; } if ($opt_C) { $community = $opt_C; } if ($opt_t) { # Validity test - must be numeric unless ( $opt_t =~ /^\d+$/ ) { print "Specify time in seconds - $opt_t is not a valid integer\n"; exit 3; } $timeout = $opt_t; } # Thresholds if ($opt_w) { if ( $opt_w =~ /^\d+$/ ) { $warning = $opt_w; } else { print "Warning value must be an integer\n"; exit 3; } } if ($opt_c) { if ( $opt_c =~ /^\d+$/ ) { $critical = $opt_c; } else { print "Critical value must an integer\n"; exit 3; } } if ($opt_a) { $oid_vm_mem = "3.2.4.1.3."; } if ($opt_v) { $vm_name = $opt_v; } if ($opt_p) { $perf_data_percent = 1; } sub usage { print < -C [...] Options: -H Hostname or IP address -C SNMP community string -t SNMP timeout (in seconds) -w Warning threshold for free memory (MB) -c Critical threshold for free memory (MB) -a Report the total VM memory allocation, rather than actual memory utilization as reported by VMware (due to transparent page sharing) -v Report memory usage of this VM only -p Return performance data in percent This plugin returns the total memory used allocated to all virtual machines, including the service console. -------------------------------------------------------------------- Copyright 2008 Altinity Limited Plugin development was sponsored by GotVMail (http://www.gotvmail.com) This program is free software; you can redistribute it or modify it under the terms of the GNU General Public License ------------------------------------------------------------------ EOF } # Sensible units. sub two_dp { my $val = shift(@_); return int( $val * 100 ) / 100; } # Call this when you know you'll get a single value back sub get_oid_value { our ( $oid, $result, $status, $returnstring ); $oid = shift(@_); if ( !defined( $s->get_request($oid) ) ) { if ( !defined( $s->get_request($oid_sysDescr) ) ) { print "SNMP agent not responding\n"; exit 3; } else { #print "SNMP OID does not exist\n"; return ""; } } foreach ( $s->var_bind_names() ) { $result = $s->var_bind_list()->{$_}; } if ( $result eq "noSuchObject" || $result eq "noSuchInstance" ) { return ""; } return $result; } sub get_vm_id { my $name = shift; my $i = 0; my $result; # Avoid accidental infinite loops by limiting # ourselves to 100 VMs. Real solution is to # get the whole table. while ( $i < 100 ) { $result = get_oid_value( $oid_namebase . $i ); if ( $result eq "" || $result eq "noSuchInstance" ) { last; } elsif ( $result =~ /^$name$/i ) { return get_oid_value( $oid_vmidbase . $i ); } $i++; } return undef; } sub get_vm_mem_used { my $i = 0; my $result = 0; my $vmid = 0; if ($vm_name) { $vmid = get_vm_id($vm_name); return undef if !defined($vmid); return get_oid_value( $oid_vmbase . $oid_vm_mem . $vmid ); } else { ################## our ( $key, $response ); $response = $s->get_table( $oid_vmbase . $oid_vm_mem ); return undef if !defined($response); foreach $key ( keys %{$response} ) { $result = $result + $response->{$key}; } } ################## return $result; } # Create the SNMP session $version = "2c"; ( $s, $e ) = Net::SNMP->session( -community => $community, -hostname => $hostname, -version => $version, -timeout => $timeout, ); if ( !defined( $s->get_request($oid_sysDescr) ) ) { # If we can't connect using SNMPv1 lets try as SNMPv2 $s->close(); sleep 0.5; $version = "1"; ( $s, $e ) = Net::SNMP->session( -community => $community, -hostname => $hostname, -version => $version, -timeout => $timeout, ); if ( !defined( $s->get_request($oid_sysDescr) ) ) { print "Agent not responding, tried SNMP v1 and v2\n"; exit 3; } } # Check for an SNMP error first... if ( $s->error ) { print "UNKNOWN - " . $s->error . "|\n"; exit 3; } # Get all the mem info $mem_total = get_oid_value( $oid_vmbase . $oid_host_mem ); $sc_mem = get_oid_value( $oid_vmbase . $oid_sc_mem ); if ( $mem_total <= 0 ) { print "UNKNOWN - Could not retrieve host data from specified ESX host\n"; exit 3; } # We cannot assume that the service console will be using memory, # since this won't be the case under VMware 3i. Avoiding div by zero. if ( $sc_mem > 0 ) { $sc_mem = int( $sc_mem / 1024 ); } $mem_total = int( $mem_total / 1024 ); my $mem = get_vm_mem_used(); if ( !defined($mem) ) { if ( defined($vm_name) ) { print "Could not find VM $vm_name\n"; } else { print "Error retrieving memory data from SNMP\n"; } exit 3; } # We used to include sc_mem in the total... #$mem_used = int($mem/1024) + $sc_mem; # Now we don't... $mem_used = int( $mem / 1024 ); $percent_used = int( 1000 * $mem_used / $mem_total ) / 10; # Performance data as numbers or %? if ($perf_data_percent) { $perfdata = "vm_mem_used=" . two_dp( $mem_used / $mem_total * 100 ) . "%;$warning;$critical;; console_mem=" . two_dp( $sc_mem / $mem_total * 100 ) . "%;;;; total_mem_used=" . two_dp( ( $mem_used + $sc_mem ) / $mem_total * 100 ) . "%;;;; total=$mem_total;;;;"; } else { $perfdata = "vm_mem_used=$mem_used;$warning;$critical;; console_mem=$sc_mem;;;; total_mem_used=" . ( $mem_used + $sc_mem ) . ";;;; total=$mem_total;;;;"; } $result_text = "$mem_used MB used out of $mem_total MB total ($percent_used% used) | $perfdata"; # The results are in... if ( $mem_used > $critical && $critical > 0 ) { print "CRITICAL - $result_text\n"; exit 2; } elsif ( $mem_used > $warning && $warning > 0 ) { print "WARNING - $result_text\n"; exit 1; } print "OK - $result_text\n"; exit 0