File check_esx3 of Package nagios-plugins-snmp
x
1
#!/usr/bin/perl -w
2
# vim:ts=4
3
# check_esx Version 3.0
4
#
5
# Check the status of a virtual machine on a VMware ESX server, via SNMP
6
# Return status in format for either Nagios or MRTG
7
#
8
# Steve Shipway (www.steveshipway.org) Nov 2004, Dec 2006, Aug 2007
9
# Released under GNU GPL
10
#
11
# Version 2.0: Added SNMP agent extension to get memory split and ready time
12
# 2.1: Corrected some bugs. Use >0.01 instead of >0.
13
# 2.2: corrected opt_r bug, fa bug
14
# 2.3:
15
# 2.4: simpler guest names for list report
16
# 2.5: Thresholds for LIST given more sensible defaults
17
# Added -a alternate for MRTG/Nagios in MEM and CPU
18
# 2.6: Final tests under ESX3
19
# 3.0: Merge in GW additions, change -v to -V to standardise
20
21
use Net::SNMP;
22
use Getopt::Std;
23
24
my($VERSION) = "3.0";
25
######## CONFIGURABLE
26
my($STATEFILE) = "/var/tmp/esx_state"; # For rate counter (if not agent)
27
my($SWAPINCRIT) = 1024; # this many bps swap in is critical (else warn)
28
my($SWAPINWARN) = 128;
29
my($SWAPPCCRIT) = 4; # this % of gruest memory in swap is critical (else warn)
30
my($SWAPPCWARN) = 1; # under ESX3, this is always >0 by a tiny bit
31
my($warn,$crit) = (70,90); # usage warn/crit: 70/90 is virtualcentre default
32
my($rwarn,$rcrit) = (10,15); # cpu readytime warn/crit: VMWare say to crit at 5%
33
my($community) = 'public'; # Default community string
34
my($TRUNC) = 16; # truncte guest names in report to this length (use 99 to stop)
35
######## END
36
my($VMOID) = "1.3.6.1.4.1.6876"; # VMware MIB
37
my($UCDOID) = "1.3.6.1.4.1.2021.1000.10"; # where to find the agent plugin
38
my($SYSOID) = "1.3.6.1.2.1.1.1.0"; # system object to test SNMP working
39
my($OK,$WARNING,$CRITICAL,$UNKNOWN) = (0,1,2,3);
40
my(%VisibleStatus) = ($OK => "OK", $WARNING => "WARNING", $CRITICAL => "CRITICAL", $UNKNOWN => "UNKNOWN");
41
my($TIMEOUT) = 5;
42
my($RETRIES) = 1;
43
my($from,$to) = (0,99999);
44
my(%snmp,$snmp,$resp,$snmperr);
45
my($hostname) = '';
46
my($vhost) = '';
47
my($A, $B, $MSG) = ('U','U','');
48
my($STATUS) = $UNKNOWN;
49
my($MODE) = 0;
50
my($VMID) = -1; # set to -1 if not running
51
my($VMNO) = -1; # set to -1 if not defined
52
my(%lookup) = ();
53
my(%states) = ();
54
my(%tmpnet) = ();
55
my($fa,$sa,$fb,$sb);
56
my(@perf) = (); # for performance stats
57
# For debugging
58
my($DEBUG) = 0;
59
my($SNMPFILE) = "testdata/snmp.txt"; # for test/debug mode only
60
my($VMWARESTATS) = "./vmware-stats -d"; # for test/debug mode only
61
# End
62
63
use vars qw($opt_C $opt_H $opt_N $opt_M $opt_h $opt_c $opt_t $opt_i $opt_d $opt_w $opt_l $opt_v $opt_r $opt_R $opt_a $opt_V);
64
65
sub base($) {
66
return '?' if(!$_[0]);
67
return $1 if( $_[0]=~/^(\S+)/ );
68
return $_[0];
69
}
70
71
sub dohelp {
72
print "Usage: $0 [-h] [-v] [-d] -H host [-C community] [-N | -M [-r]]\n";
73
print " [-l check [-V vhost] [-i interface] [-w warn -c crit]]\n";
74
print " [-t timeout] [-R retries]\n";
75
print " -h: just prints this help message\n";
76
print " -v: just prints the script version number\n";
77
print " -d: puts the script into debug mode\n";
78
print " -H host: ESX server machine\n";
79
print " -C community: the SNMP community string (default is \"public\")\n";
80
print " -N: Nagios mode (the default); need -w and -c for CPU, MEM\n";
81
print " -M: MRTG mode (-r specifies rate rather than counter)\n";
82
print " -l check: can be CPU MEM STATE LIST NET LISTNET (default is LIST)\n";
83
print " -V virtualhost: restrict probing to that one guest host; required for STATE;\n";
84
print " if not specified, probes total ESX system statistics\n";
85
print " -i interface: Only valid for NET\n";
86
print " -w warn -c crit: Nagios thresholds\n";
87
print " -t timeout: ([1..60] seconds) for individual SNMP queries\n";
88
print " -R retries: # of retries ([0..20]) for individual SNMP queries\n";
89
print "\nFor MRTG,\n";
90
print " CPU is total seconds (counter) for vhost or total over all if no vhost given.\n";
91
print " MEM is memory remaining in K.\n";
92
print " STATE is 1 for up, 0 for down.\n";
93
print " LIST is number of vhosts.\n";
94
print " NET is network throughput in bytes for specified vhost and/or interface\n";
95
print " (total of all if not specified).\n";
96
print "\nFor Nagios, specify thresholds as follows.\n";
97
print " CPU is percentage of allocated CPU (for vhosts) and of total CPU (if no vhost).\n";
98
print " MEM is active memory (for vhosts) or free phys memory (if no vhost) in K or %.\n";
99
print " STATE is CRITICAL if vhost is down.\n";
100
print " LIST is WARN if some are down, CRIT is all vhosts are down.\n";
101
print " NET is bytes/sec since last check, if possible (otherwise UNKNOWN).\n";
102
print "\nThresholds for MEM or LIST under Nagios, can be in K or %\n";
103
print " e.g.: -l MEM -w 2048K -c 1024K\n";
104
print " e.g.: -l MEM -V vhost -w 80% -c 90%\n";
105
print " e.g.: -l LIST -w 90% -c 0\n";
106
print " e.g.: -l LIST -w 10 -c 1\n";
107
print "Thresholds for CPU are in % (the trailing % symbol is optional)\n";
108
print " e.g.: -l CPU -w 80 -c 90\n";
109
print "Thresholds for NET are in BYTES/SEC (cannot use %)\n";
110
exit 0;
111
}
112
113
sub readstate {
114
return if(! -r $STATEFILE);
115
open STATE, "<$STATEFILE";
116
flock STATE,1; # read lock
117
while( <STATE> ) { $states{$1}=$2 if( /^(\S+)=(\d+)/ ); }
118
flock STATE,8; # unlock
119
close STATE;
120
}
121
122
# Big fixes for the race condition from GroundWork
123
sub writestate {
124
my(%new) = @_;
125
126
if(-r $STATEFILE) {
127
open STATE, "+<$STATEFILE"
128
or do { $A=$B="U"; $MSG="$STATEFILE: $!"; $STATUS=3; &dooutput; };
129
flock STATE,2; # write lock
130
while( <STATE> ) { $states{$1}=$2 if( /^(\S+)=(\d+)/ ); }
131
} else {
132
open STATE, ">>$STATEFILE"
133
or do { $A=$B="U"; $MSG="$STATEFILE: $!"; $STATUS=3; &dooutput; };
134
flock STATE,2; # write lock
135
136
}
137
seek STATE,0,0; # rewind
138
truncate STATE,0;
139
foreach ( keys %new ) { $states{$_} = $new{$_}; }
140
foreach ( keys %states ) { print STATE "$_=".$states{$_}."\n"; }
141
flock STATE,8; # unlock
142
close STATE;
143
}
144
145
sub dooutput {
146
if( $MODE ) {
147
# MRTG
148
$A = 'U' if(!defined $A);
149
$B = $A if(!defined $B);
150
$MSG = "Returned values: $A, $B\n" if(!$MSG);
151
print "$A\n$B\n\n$MSG\n";
152
exit 0;
153
} else {
154
# Nagios: now supporting performance stats
155
print "".($VisibleStatus{$STATUS} || "UNKNOWN").": $MSG"
156
.(scalar @perf ? "|" . join(" ",@perf) : ""), "\n";
157
exit $STATUS;
158
}
159
# should never get here
160
}
161
162
sub snmpfile($) {
163
my(%resp);
164
my($k) = $_[0];
165
foreach ( keys %snmp ) { $resp{$_} = $snmp{$_} if( /^$k\./); }
166
return \%resp;
167
}
168
169
sub makesnmp() {
170
if ($DEBUG and $SNMPFILE) {
171
open SNMP,"<$SNMPFILE" or return;
172
while(<SNMP>) { chomp; if(/^(\S+)\s+=\s+\S+:\s+"?([^"]+)/) { $snmp{$1}=$2; } }
173
close SNMP;
174
return;
175
}
176
($snmp,$snmperr) = Net::SNMP->session( -hostname=>$hostname,
177
-community=>$community, -timeout=>$TIMEOUT, -retries=>$RETRIES );
178
if($snmperr) {
179
$A = $B = 'U';
180
print "($snmperr)\n" if($DEBUG);
181
$MSG = "Error: $snmperr";
182
$STATUS = $UNKNOWN;
183
dooutput; # exit
184
exit(0);
185
}
186
}
187
188
###########################################################################
189
# Read detailed memory and CPU data from extended snmp daemon, if possible
190
my(%stats) = ();
191
my($donereadagent) = 0;
192
sub readagent {
193
return "" if($donereadagent);
194
$MSG = "";
195
makesnmp() if(!$snmp);
196
if($DEBUG and $VMWARESTATS) {
197
open STATS,"$VMWARESTATS|" or return 0;
198
while( <STATS> ) {
199
# print;
200
chomp; $stats{$1}=$2 if(/^(\S+)\s*=\s*(\S.*)/); }
201
close STATS;
202
$donereadagent = 1;
203
return 0;
204
}
205
$resp = $snmp->get_request( -varbindlist=>["$UCDOID.2.1"] );
206
if(!$resp) { # Fall back to the old way
207
return 1;
208
}
209
if( $resp->{"$UCDOID.2.1"} ne 'vmware' ) {
210
$MSG = "Incorrect SNMPD configuration: found '".$resp->{"$UCDOID.2.1"}."' when expected 'vmware'";
211
$STATUS = $UNKNOWN;
212
return 1;
213
}
214
$resp = $snmp->get_table( -baseoid=>"$UCDOID.101" );
215
if(!$resp) { # Fall back to the old way
216
# $MSG = "SNMP error: ".$snmp->error;
217
return 1;
218
}
219
# Convert the retrieved values to lookup hash
220
foreach my $oid ( keys %$resp ) {
221
if(( $oid =~ /\.101\.\d+$/ ) and ( $resp->{$oid}=~/^(\S+)=(.*)$/)) {
222
$stats{$1}=$2;
223
}
224
}
225
$donereadagent = 1;
226
return "";
227
}
228
229
###########################################################################
230
sub getesxversion {
231
print "(snmp lookup)\n" if($DEBUG);
232
makesnmp() if(!$snmp);
233
$resp = $snmp->get_request( -varbindlist=>[ "$VMOID.1.2.0" ] );
234
if(!$resp) {
235
if(readagent) {
236
$MSG = "Error: No VMWare SNMP sub-agent running (vmware-snmpd)"
237
if(!$MSG);
238
$STATUS = $UNKNOWN;
239
dooutput; # exit
240
exit(0);
241
}
242
if(!$stats{'has-names'}) {
243
$MSG = "Error: No VMWare SNMP sub-agent running (vmware-snmpd)";
244
$STATUS = $UNKNOWN;
245
dooutput; # exit
246
exit(0);
247
}
248
$esx_version = 2; # just a blind assumption
249
} else {
250
$esx_version = $resp->{"$VMOID.1.2.0"};
251
$esx_version =~ s/\..*//;
252
}
253
}
254
255
# Read all the VM IDs from the vmware-snmpd MIB
256
sub getvmid {
257
print "(snmp lookup)\n" if($DEBUG);
258
259
makesnmp() if(!$snmp);
260
if(!readagent and $stats{'has-names'}) {
261
foreach ( keys %stats ) {
262
if( /vhost-(\d+)-name/ ) {
263
$lookup{$1} = $stats{$_}; # id->name
264
$lookup{$stats{$_}} = "vmno-$1" ; # name->dummyOID
265
$lookup{"vmno-$1"} = $1 ; # dummyOID->id
266
}
267
}
268
} else {
269
$resp = $snmp->get_table( -baseoid=>"$VMOID.2.1.1");
270
if(!$resp) {
271
$resp = $snmp->get_request( -varbindlist=>[ "$VMOID.1.1.0" ] );
272
if(!$resp) {
273
$MSG = "Error: No VMWare SNMP sub-agent running (vmware-snmpd)"
274
if(!$MSG);
275
$STATUS = $UNKNOWN;
276
dooutput; # exit
277
exit(0);
278
} else {
279
print "No guests are defined on this server\n" if($DEBUG);
280
$MSG = "No guests defined on this server";
281
return;
282
}
283
} else {
284
foreach my $oid ( keys %$resp ) {
285
$oid =~ /(\d+)\.(\d+)$/;
286
if( $1 == 2 ) {
287
$lookup{$resp->{$oid}} = $2;
288
$lookup{$2} = $resp->{"$VMOID.2.1.1.7.$2"};
289
$lookup{$resp->{"$VMOID.2.1.1.7.$2"}} = $resp->{$oid};
290
$lookup{"vmGuestState-$2"} = $resp->{"$VMOID.2.1.1.8.$2"};
291
}
292
}
293
}
294
}
295
return if(!$vhost); # we're just getting the table
296
if(defined $lookup{$vhost}) {
297
$VMNO = $lookup{$vhost};
298
if( defined $lookup{$VMNO} ) {
299
$VMID = $lookup{$VMNO};
300
if ( defined $lookup{"vmGuestState-$VMNO"} ) {
301
$vmGuestState = $lookup{"vmGuestState-$VMNO"};
302
}
303
} else {
304
$STATUS = $CRITICAL;
305
$MSG = "Virtual host $vhost($VMNO) is not running!";
306
}
307
} else {
308
# lets see if they just gave part of the vhost name?
309
$VMNO = "U";
310
foreach ( keys %lookup ) {
311
if( /^$vhost/i ) {
312
$VMNO = $lookup{$_};
313
if( defined $lookup{$VMNO} ) {
314
$VMID = $lookup{$VMNO};
315
if ( defined $lookup{"vmGuestState-$VMNO"} ) {
316
$vmGuestState = $lookup{"vmGuestState-$VMNO"};
317
}
318
$vhost = $_;
319
} else {
320
$STATUS = $CRITICAL;
321
$MSG = "Virtual host $vhost($VMNO) is not running!";
322
}
323
last;
324
}
325
}
326
if($VMNO eq "U") {
327
$STATUS = $UNKNOWN;
328
$MSG = "Virtual host $vhost is not defined!";
329
dooutput; # exit
330
exit(0);
331
}
332
}
333
334
print "(hostno=$VMNO, ID=$VMID)\n" if($DEBUG);
335
}
336
337
sub listvm {
338
my(@vh);
339
%lookup = (); @vh = ();
340
print "(snmp lookup)\n" if($DEBUG);
341
makesnmp() if(!$snmp);
342
if(!readagent and $stats{'has-names'}) {
343
foreach ( keys %stats ) {
344
if( /vhost-(\d+)-name/ ) {
345
$lookup{$1} = $stats{$_}; # id->name
346
$lookup{$stats{$_}} = "vmno-$1" ; # name->dummyOID
347
$lookup{"vmno-$1"} = $1 ; # dummyOID->id
348
push @vh,$stats{$_};
349
}
350
}
351
} else {
352
$resp = $snmp->get_table( -baseoid=>"$VMOID.2.1.1");
353
if(!$resp) {
354
if(readagent) {
355
$A = $B = 'U';
356
$MSG = "Error: No VMWare SNMP sub-agent running (vmware-snmpd)"
357
if(!$MSG);
358
$STATUS = $UNKNOWN;
359
dooutput; # exit
360
exit(0);
361
}
362
if(!$stats{'has-names'}) {
363
$MSG = "Error: No VMWare SNMP sub-agent running (vmware-snmpd)";
364
$STATUS = $UNKNOWN;
365
dooutput; # exit
366
exit(0);
367
}
368
foreach ( keys %stats ) {
369
if( /vhost-(\d+)-name/ ) {
370
$lookup{$1} = $stats{$_}; # id->name
371
$lookup{$stats{$_}} = "vmno-$1" ; # name->dummyOID
372
$lookup{"vmno-$1"} = $1 ; # dummyOID->id
373
push @vh,$stats{$_};
374
}
375
}
376
377
} else {
378
foreach my $oid ( sort keys %$resp ) {
379
$oid =~ /(\d+)\.(\d+)$/;
380
if( $1 == 2 ) {
381
$lookup{$resp->{$oid}} = $2;
382
push @vh, $resp->{$oid};
383
} elsif( $esx_version == 2 && $1 == 7 ) {
384
$lookup{$2} = $resp->{$oid};
385
} elsif( $esx_version == 3 && $1 == 8 ) {
386
$lookup{$2} = $resp->{$oid};
387
}
388
}
389
390
}
391
} # stats available
392
$A = $B = 0;
393
foreach ( @vh ) {
394
next if(!$_);
395
$B++;
396
if ( $esx_version == 2 ) {
397
if( defined $lookup{$lookup{$_}} and ($lookup{$lookup{$_}} > 0)) {
398
$_ = (substr $_,0,$TRUNC)."(".$lookup{$lookup{$_}}.")"; $A++;
399
} else {
400
$_ = (substr $_,0,$TRUNC)."(DOWN)";
401
}
402
} else {
403
# This logic is for ESX 3.
404
#print "$lookup{$lookup{$_}} \n";
405
if( defined $lookup{$lookup{$_}} and ($lookup{$lookup{$_}} > 0 )) {
406
$_ = (substr $_,0,$TRUNC)."(UP)"; $A++;
407
} else {
408
$_ = (substr $_,0,$TRUNC)."(DOWN)";
409
}
410
}
411
$_ =~ s/ *\([^\)]+\)(\(.*\))/$1/;
412
}
413
$MSG = "VHosts: $A/$B up: ".(join ", ",@vh);
414
push @perf, "allvms_up_ct=$A;;;0;$B";
415
push @perf, "allvms_up_pc=". int($A/$B*10000)/100.0 ."%;;;0;100";
416
$STATUS = $OK;
417
}
418
419
sub readnet {
420
my($found);
421
422
if($SNMPFILE and $DEBUG) {
423
$resp = snmpfile("$VMOID.3.4.1");
424
} else {
425
$resp = $snmp->get_table( -baseoid=>"$VMOID.3.4.1");
426
}
427
if(!$resp) {
428
$resp = $snmp->get_request( -varbindlist=>[ "$VMOID.1.1" ] );
429
if($resp) { $A = $B = 0;
430
$MSG = "No VHosts defined"; $STATUS = $OK; return; }
431
$MSG = "Error: Unable to retrieve SNMP data";
432
$STATUS = $UNKNOWN;
433
return;
434
}
435
foreach my $oid ( keys %$resp ) {
436
$oid =~ /(\d+)\.(\d+)$/; # Type, index.
437
if( $1 == 3 ) {
438
$tmpnet{$2} = [
439
$resp->{$oid},
440
$resp->{"$VMOID.3.4.1.2.$2"},
441
($resp->{"$VMOID.3.4.1.7.$2"}*1024),
442
($resp->{"$VMOID.3.4.1.9.$2"}*1024)
443
];
444
}
445
}
446
return if($opt_l =~ /LIST/);
447
# We now have all the network statistics indexed by card or VMID
448
$A = $B = 0; $found = 0;
449
foreach ( keys %tmpnet ) {
450
if((($VMID<0) or ($VMID == $tmpnet{$_}[0])) # vm matches
451
and ((!$opt_i) or ($opt_i eq $tmpnet{$_}[1]))) { # net matches
452
$A += $tmpnet{$_}[2];
453
$B += $tmpnet{$_}[3];
454
$found = 1;
455
}
456
}
457
if(!$found) {
458
$MSG = "No network interfaces exist for ";
459
$MSG .= "vhost $vhost" if($VMID>-1);
460
$MSG .= " and " if($VMID>-1 and $opt_i);
461
$MSG .= " interface $opt_i" if ($opt_i);
462
$STATUS = $UNKNOWN;
463
}
464
}
465
466
###########################################################################
467
# Read general memory and CPU data from vmware-snmpd
468
# This is what we do if we can't get the detailed information.
469
sub readcpu {
470
my($k,@k);
471
my($t1,$t2,$a1);
472
473
$MSG = ""; $A = 0; $B = 0;
474
if( !$MODE or $opt_r ) {
475
readstate;
476
$t1 = $states{"$hostname-CPU-$vhost-time"};
477
$a1 = $states{"$hostname-CPU-$vhost"};
478
$t2 = time;
479
}
480
481
@k = ();
482
if( $VMID < 0 ) {
483
foreach ( keys %lookup ) {
484
push @k, "$VMOID.3.1.2.1.3.".$_ if( /^\d+$/ and $_>99);
485
}
486
} else {
487
$k = "$VMOID.3.1.2.1.3.$VMID";
488
@k = ( $k );
489
}
490
foreach $k ( @k ) { print "(retrieving $k)\n" if($DEBUG); }
491
$resp = $snmp->get_request( -varbindlist=>\@k );
492
if( $resp ) {
493
if($VMID<0){
494
$A = 0;
495
foreach ( keys %$resp ) { $A += $resp->{$_};
496
print "$_: ".$resp->{$_}."\n" if($DEBUG); }
497
} else {
498
$A = $resp->{$k};
499
}
500
$B = 0;
501
} else {
502
$A = $B = 'U';
503
if($VMID<0){
504
$MSG = "Unable to retrieve CPU statistics for ESX server: ".$snmp->error;
505
} else {
506
$MSG = "Unable to retrieve CPU statistics for $vhost: ".$snmp->error;
507
}
508
$STATUS = $UNKNOWN;
509
}
510
if(!$MSG){ # IE, no errors
511
$MSG = "CPU has used $A seconds";
512
$MSG .= " on $vhost" if($vhost);
513
if( !$MODE or $opt_r ) {
514
writestate( "$hostname-CPU-$vhost"=>$A, "$hostname-CPU-$vhost-time"=>$t2 )
515
if(!$t1 or ($t2-$t1)>30);
516
if(!$t1 or !$a1 or ($t1 >= $t2) or ( ($t2-$t1)>1000 ) ) {
517
if($vhost) {
518
$MSG = "No saved state for $vhost CPU time yet - please wait for next poll.";
519
} else {
520
$MSG = "No saved state for ESX system CPU time yet - please wait for next poll.";
521
}
522
$A = $B = "U";
523
$STATUS = $UNKNOWN;
524
} else {
525
print "Usage: $A-$a1 in $t2-$t1 = ".($A-$a1)." in ".($t2-$t1)
526
if($DEBUG);
527
$A = int((($A - $a1)/($t2 - $t1))*10000)/100;
528
print " = $A\n" if($DEBUG);
529
$B = 0;
530
$MSG = "CPU usage is $A% ";
531
$MSG .= "on $vhost" if($vhost);
532
$MSG .= " (".($t2-$t1)."s average)";
533
if($A>110 or $A<0) {
534
$B = $A = 0;
535
$MSG = "Error reading CPU usage information."
536
}
537
}
538
}
539
}
540
}
541
542
sub readmem {
543
my($k1,$k2);
544
545
if($VMID < 0) {
546
$k1 = "$VMOID.3.2.1.0"; # Total physical present
547
$k2 = "$VMOID.3.2.3.0"; # Memory free
548
} else {
549
$k1 = "$VMOID.3.2.4.1.3.$VMID"; # VM memory max
550
$k2 = "$VMOID.3.2.4.1.4.$VMID"; # VM memory used
551
}
552
print "(retrieving $k1,$k2)\n" if($DEBUG);
553
$resp = $snmp->get_request( -varbindlist=>[$k1,$k2] );
554
if( $resp ) {
555
if($VMID < 0 ) {
556
$A = $resp->{$k2}; $B = $resp->{$k1};
557
} else {
558
$A = $resp->{$k2}; $B = $resp->{$k1};
559
$B *= 1024 if($B<10240 or $B<$A); # ESX3 gives it in Kb, ESX2 gives it in Mb (argh!)
560
# we can assume noone has a VM with <10Mb or >10Gb!
561
$A = $B - $A; # memory remaining
562
}
563
} else {
564
$A = $B = 'U';
565
if($VMID<0) {
566
$MSG = "Unable to retrieve memory statistics for ESX server: ".$snmp->error;
567
} else {
568
$MSG = "Unable to retrieve memory statistics for $vhost: ".$snmp->error;
569
}
570
$STATUS = $UNKNOWN;
571
}
572
}
573
sub readconsolemempc {
574
my($k1,$k2);
575
576
$k1 = "$VMOID.3.2.1.0"; # Total physical present (vmwMemory.memSize.0)
577
$k2 = "$VMOID.3.2.2.0"; # Memory used by console (vmwMemory.memCOS.0)
578
print "(retrieving $k1,$k2)\n" if($DEBUG);
579
$resp = $snmp->get_request( -varbindlist=>[$k1,$k2] );
580
if( $resp ) {
581
return int( $resp->{$k2} / $resp->{$k1} * 10000) / 100.0;
582
} else {
583
return 'U';
584
}
585
}
586
587
sub vmavgready {
588
my($c) = 0;
589
my($t) = 0;
590
foreach my $k ( keys %stats ) {
591
if( $k =~ /vhost-.*-cpu-ready-pc/ ) {
592
$c += 1;
593
$t += $stats{$k};
594
print "$k : ".$stats{$k}."\n" if($DEBUG);
595
}
596
}
597
print "$c vhosts total ready $t, avg is ".($t/$c)."\n" if($DEBUG);
598
return ($c?($t/$c):undef);
599
}
600
sub readrpc {
601
$MSG = ""; $A = 0; $B = 0; $STATUS = 0;
602
if( readagent ) {
603
$A = $B = "U";
604
print "(readagent failed: $MSG)\n" if($DEBUG);
605
$STATUS = 3 if(!$STATUS);
606
$MSG = "Unable to retrieve statistics" if(!$MSG);
607
dooutput;
608
exit $STATUS;
609
}
610
if( ! $stats{'has-rpc'} ) {
611
$A = $B = "U";
612
print "(old version agent)\n" if($DEBUG);
613
$STATUS = 3 if(!$STATUS);
614
$MSG = "Remote agent does not support RPC: upgrade to vmware-stats v2.5 or later!";
615
dooutput;
616
exit $STATUS;
617
}
618
if($vhost) {
619
$A = $stats{"vhost-$VMID-rpc-count"};
620
$B = $stats{"vhost-$VMID-rpc-rate"};
621
if(!defined $A) { $A= $B = 'U'; $MSG="Unable to retrieve data";
622
$STATUS = 3; dooutput; exit 3; }
623
$B = 0 if(!$B);
624
} else {
625
$A = $B = 0;
626
foreach ( keys %stats ) {
627
$A += $stats{$_} if( /-rpc-count/ );
628
$B += $stats{$_} if( /-rpc-rate/ );
629
}
630
}
631
}
632
sub readxcpu {
633
my($k,$C);
634
$MSG = ""; $A = 0; $B = 0; $STATUS = 0;
635
if( readagent ) {
636
print "(readagent failed: $MSG)\n" if($DEBUG);
637
readcpu if(!$MSG); # no vmware agent, no error
638
return;
639
}
640
if($vhost) {
641
if ( $esx_version <= 2 ) {
642
$k = "vhost-$VMID";
643
} else {
644
foreach my $key ( keys %stats ) {
645
if ( $stats{$key} eq $lookup{$lookup{$VMNO}} ) {
646
$key =~ /vhost-(\d+)-name/;
647
$k = "vhost-$1";
648
last;
649
}
650
}
651
}
652
if ( defined $k ) {
653
$A = $stats{"$k-cpu-used-pc"};
654
$B = $stats{"$k-cpu-ready-pc"};
655
} else {
656
$A = undef;
657
$B = undef;
658
}
659
$C = $A;
660
} else {
661
$k = "sys";
662
if($opt_a) {
663
$A = $stats{"sys-cpu-used-pc"} + $stats{"allvms-cpu-used-pc"}
664
if($stats{"allvms-cpu-used-pc"});
665
$B = vmavgready();
666
$C = $B if(defined $B);
667
} else {
668
$A = $stats{"sys-cpu-used-pc"};
669
$B = $stats{"allvms-cpu-used-pc"};
670
$C = $A + $B if(defined $A and defined $B);
671
}
672
}
673
if(!defined $A or !defined $B) {
674
$A=$B='U'; $MSG="No saved CPU statistics available - please wait for next poll.";
675
$STATUS = 3;
676
# Fill in some dummy performance data anyway, to keep downstream processes somewhat happy.
677
if ($vhost) {
678
push @perf, "vhost_cpu_used_pc=U%;;;0;100";
679
push @perf, "vhost_cpu_ready_pc=U%;;;0;100";
680
} else {
681
push @perf, "sys_cpu_used_pc=U%;;;0;100";
682
push @perf, "allvms_cpu_used_pc=U%;;;0;100";
683
push @perf, "sys_cpu_ready_pc=U%;;;0;100";
684
}
685
686
dooutput; exit 3;
687
}
688
689
if($opt_a) {
690
if($vhost) { $MSG = "vhost CPU used=$A% ready=$B%"; }
691
else { $MSG = "CPU used total=$A% avgvhostreadytime=$B%"; }
692
} else {
693
if($vhost) { $MSG = "vhost CPU used=$A% ready=$B%"; }
694
else { $MSG = "CPU used sys=$A% vhosts=$B% sysreadytime="
695
.$stats{'sys-cpu-ready-pc'}."%"; }
696
}
697
698
if($vhost) {
699
$MSG = "vhost CPU used=$A% ready=$B%";
700
push @perf, "vhost_cpu_used_pc=$A%;;;0;100";
701
push @perf, "vhost_cpu_ready_pc=$B%;;;0;100";
702
} else {
703
$MSG = "CPU used sys=$A% vhosts=$B% readytime=".$stats{'sys-cpu-ready-pc'}."%";
704
push @perf, "sys_cpu_used_pc=$A%;;;0;100";
705
push @perf, "allvms_cpu_used_pc=$B%;;;0;100";
706
push @perf, "sys_cpu_ready_pc=".$stats{'sys-cpu-ready-pc'}."%;;;0;100";
707
}
708
709
# MRTG only
710
if($MODE) { dooutput; exit 0; }
711
# Nagios only
712
if(!$vhost and $opt_a) {
713
if($C>=$rcrit) {
714
$MSG .= "<BR>" if($MSG);
715
$MSG .= "Ready time is CRITICAL ($C\%)";
716
$STATUS = 2;
717
} elsif($C>=$rwarn) {
718
$MSG .= "<BR>" if($MSG);
719
$MSG .= "Ready time is WARNING ($C\%)";
720
$STATUS = 1 if($STATUS<2);
721
}
722
} else {
723
$crit =~ s/[^\d\.]//g; $warn =~ s/[^\d\.]//g;
724
$crit = 100 if(!$crit); $warn = 100 if(!$warn);
725
if( $C >= $crit ) {
726
$MSG .= "<BR>" if($MSG);
727
$MSG .= "CPU usage is CRITICAL ($C\%)";
728
$STATUS = 2;
729
} elsif( $C >= $warn ) {
730
$MSG .= "<BR>" if($MSG);
731
$MSG .= "CPU usage is WARNING ($C\%)";
732
$STATUS = 1 if($STATUS<2);
733
}
734
735
# Ready time
736
if( $stats{"$k-cpu-ready-pc"} >= $rcrit ) {
737
$MSG .= "<BR>" if($MSG);
738
$MSG .= "Ready time is CRITICAL (".$stats{"$k-cpu-ready-pc"}."\%)";
739
$STATUS = 2;
740
} elsif( $stats{"$k-cpu-ready-pc"} >= $rwarn ) {
741
$MSG .= "<BR>" if($MSG);
742
$MSG .= "Ready time is WARNING (".$stats{"$k-cpu-ready-pc"}."\%)";
743
$STATUS = 1 if($STATUS<2);
744
}
745
}
746
if(!$vhost) { # check all vhosts
747
foreach ( keys %lookup ) {
748
next if(!defined $stats{"vhost-$_-cpu-used-pc"});
749
$C=$stats{"vhost-$_-cpu-used-pc"};
750
if( $C >= $crit ) {
751
$MSG .= "<BR>" if($MSG);
752
$MSG .= "'".base($lookup{$_})."' CPU CRITICAL ($C\%)";
753
$STATUS = 2;
754
} elsif( $C >= $warn ) {
755
$MSG .= "<BR>" if($MSG);
756
$MSG .= "'".base($lookup{$_})."' CPU WARNING ($C\%)";
757
$STATUS = 1 if($STATUS<2);
758
}
759
if( $stats{"vhost-$_-cpu-ready-pc"} >= $rcrit ) {
760
$MSG .= "<BR>" if($MSG);
761
$MSG .= "'".base($lookup{$_})."' Ready time CRITICAL (".$stats{"vhost-$_-cpu-ready-pc"}."\%)";
762
$STATUS = 2;
763
} elsif( $stats{"vhost-$_-cpu-ready-pc"} >= $rwarn ) {
764
$MSG .= "<BR>" if($MSG);
765
$MSG .= "'".base($lookup{$_})."' Ready time WARNING (".$stats{"vhost-$_-cpu-ready-pc"}."\%)";
766
$STATUS = 1 if($STATUS<2);
767
}
768
}
769
}
770
dooutput;
771
exit 3; # not reached
772
}
773
sub readxmem {
774
my($pc,$max,$k,$memVMID);
775
776
$MSG = ""; $A = 0; $B = 0;
777
if( readagent() ) {
778
print "(readagent failed: $MSG)\n" if($DEBUG);
779
readmem if(!$MSG); # no vmware agent, no error
780
return;
781
}
782
783
if( $vhost ) {
784
if ( $esx_version <= 2 ) {
785
$k = "vhost-$VMID";
786
} else {
787
# for ESX Version 3
788
foreach my $key ( keys %stats ) {
789
if ( $stats{$key} eq $lookup{$lookup{$VMNO}} ) {
790
$key =~ /vhost-(\d+)-name/;
791
$memVMID = $1 - 1; # why this is off by one, we don't know, but it is
792
$k = "unknown-$memVMID";
793
last;
794
}
795
}
796
}
797
$A = $stats{"$k-mem-active"};
798
$B = $stats{"$k-mem-max"};
799
$max = $stats{"$k-mem-max"};
800
801
if(!defined $A or !defined $B) { $A=$B='U';
802
$MSG="Problem reading memory data on ESX server"; $STATUS=3;
803
push @perf, "vhost_mem_act_pc=U\%;;;0;100";
804
push @perf, "vhost_mem_pvt_pc=U\%;;;0;100";
805
push @perf, "vhost_mem_shr_pc=U\%;;;0;100";
806
push @perf, "vhost_mem_bal_pc=U\%;;;0;100";
807
push @perf, "vhost_mem_swp_pc=U\%;;;0;100";
808
dooutput; exit 0;
809
}
810
$pc = int($A/$B*10000)/100.0;
811
$MSG = "Memory active: ".int($A/1024000)."Mb ($pc\%) [Total available ".int($B/1024000)."Mb]";
812
push @perf, "vhost_mem_act_pc=$pc\%;;;0;100";
813
if($pc>=$crit) { $STATUS=2; $MSG = "CRIT: $MSG"; }
814
elsif($pc>=$warn) { $STATUS=1; $MSG = "WARN: $MSG"; }
815
if($opt_a) { $A = $B = $pc; }
816
} else {
817
$k = "allvms";
818
# $A = $stats{'mem-avail'};
819
# $B = $stats{'mem-total'};
820
$A = $stats{'mem-free'};
821
$B = $stats{'mem-total'};
822
$max = $stats{"$k-mem-max"};
823
if(!defined $A or !defined $B) { $A=$B='U';
824
$MSG="Problem reading memory data on ESX server."; $STATUS=3;
825
push @perf, "mem_free_pc=U\%;;;0;100";
826
if ( $esx_version == 3 ) {
827
push @perf, "console_mem_pc=U\%;;;0;100";
828
}
829
push @perf, "allvms_mem_pvt_pc=U\%;;;0;100";
830
push @perf, "allvms_mem_shr_pc=U\%;;;0;100";
831
push @perf, "allvms_mem_bal_pc=U\%;;;0;100";
832
push @perf, "allvms_mem_swp_pc=U\%;;;0;100";
833
dooutput; exit 0;
834
}
835
$pc = int($A/$B*10000)/100.0;
836
$MSG = "Memory unreserved: ".int($A/1024000)."Mb ($pc\%) [Total managed ".int($B/1024000)."Mb]";
837
push @perf, "mem_free_pc=$pc\%;;;0;100";
838
if ( $esx_version == 3 ) {
839
my ($consolemempc) = readconsolemempc;
840
$MSG .= " [Console=$consolemempc\%]";
841
push @perf, "console_mem_pc=" . $consolemempc . "\%;;;0;100";
842
}
843
if($pc<=$crit) { $STATUS=2; $MSG = "CRIT: $MSG"; }
844
elsif($pc<=$warn) { $STATUS=1; $MSG = "WARN: $MSG"; }
845
if($opt_a) {
846
$MSG = "Memory used: ".int(($B-$A)/1024000)."Mb (".(100-$pc)."\%) [Total available ".int($B/1024000)."Mb]";
847
$A = 100 - $pc; $B = $pc;
848
}
849
}
850
851
# MRTG
852
if($MODE) { dooutput; exit 0; }
853
854
# Nagios
855
if($max) {
856
$MSG .= "<BR>Memory split: pvt/shr/bal/swp = "
857
.(int(10000*$stats{"$k-mem-private"}/$max)/100.0)."\%/"
858
.(int(10000*$stats{"$k-mem-shared"}/$max)/100.0)."\%/"
859
.(int(10000*$stats{"$k-mem-balloon"}/$max)/100.0)."\%/"
860
.(int(10000*$stats{"$k-mem-swap"}/$max)/100.0)."\%";
861
if ($vhost) {
862
push @perf, "vhost_mem_pvt_pc=" . (int(10000*$stats{"$k-mem-private"}/$max)/100.0) . "\%;;;0;100";
863
push @perf, "vhost_mem_shr_pc=" . (int(10000*$stats{"$k-mem-shared" }/$max)/100.0) . "\%;;;0;100";
864
push @perf, "vhost_mem_bal_pc=" . (int(10000*$stats{"$k-mem-balloon"}/$max)/100.0) . "\%;;;0;100";
865
push @perf, "vhost_mem_swp_pc=" . (int(10000*$stats{"$k-mem-swap" }/$max)/100.0) . "\%;;;0;100";
866
} else {
867
push @perf, "allvms_mem_pvt_pc=" . (int(10000*$stats{"$k-mem-private"}/$max)/100.0) . "\%;;;0;100";
868
push @perf, "allvms_mem_shr_pc=" . (int(10000*$stats{"$k-mem-shared" }/$max)/100.0) . "\%;;;0;100";
869
push @perf, "allvms_mem_bal_pc=" . (int(10000*$stats{"$k-mem-balloon"}/$max)/100.0) . "\%;;;0;100";
870
push @perf, "allvms_mem_swp_pc=" . (int(10000*$stats{"$k-mem-swap" }/$max)/100.0) . "\%;;;0;100";
871
}
872
873
if($stats{"$k-mem-balloon"}) {
874
$pc = int(100000*$stats{"$k-mem-balloon"}/$max)/1000.0;
875
if($pc>=25) {
876
$MSG .= "<BR>CRIT: Balloon drivers in action! ($pc\%)";
877
$STATUS = 2;
878
} elsif($pc>=0.01) {
879
$MSG .= "<BR>WARN: Balloon drivers in action! ($pc\%)";
880
$STATUS = 1 if($STATUS<2);
881
}
882
}
883
}
884
if($stats{"$k-swap-in-bps"} and $stats{"$k-swap-in-bps"}>10) {
885
if($stats{"$k-swap-in-bps"}>$SWAPINCRIT) {
886
$MSG .= "<BR>CRIT: VMware swapping in action! (".$stats{"$k-swap-in-bps"}."Bps)";
887
$STATUS = 2;
888
} else {
889
$MSG .= "<BR>WARN: VMware swapping is starting!";
890
$STATUS = 1 if($STATUS<2);
891
}
892
} elsif($max and $stats{"$k-mem-swap"}) {
893
$pc = int(100000*$stats{"$k-mem-swap"}/$max)/1000.0;
894
if($pc>=$SWAPPCCRIT) {
895
$MSG .= "<BR>CRIT: VMWare swap space in use! ($pc\%)";
896
$STATUS = 2;
897
} elsif($pc>=$SWAPPCWARN) {
898
$MSG .= "<BR>WARN: VMWare swap space in use! ($pc\%)";
899
$STATUS = 1 if($STATUS<2);
900
}
901
}
902
903
dooutput;
904
exit 3; # not reached
905
}
906
907
###########################################################################
908
getopts('vahrdNMH:c:t:V:w:C:l:i:R:');
909
$hostname = $opt_H if($opt_H);
910
$vhost = $opt_V if($opt_V);
911
$warn = $opt_w if($opt_w);
912
$crit = $opt_c if($opt_c);
913
$TIMEOUT = $opt_t if($opt_t);
914
$RETRIES = $opt_R if($opt_R);
915
$MODE = 1 if($opt_M);
916
$community = $opt_C if($opt_C);
917
$DEBUG = 1 if($opt_d);
918
dohelp if($opt_h);
919
920
if($opt_v) {
921
print "(did you mean to use -V?) " if($opt_C or $opt_H);
922
print "check_esx version $VERSION\n";
923
exit 0;
924
}
925
if(!$hostname) {
926
$MSG = "No ESX server hostname specified with -H";
927
dooutput;
928
exit 0;
929
}
930
if( !$opt_l ) {
931
# $MSG = "You need to specify a command with -l";
932
# dooutput;
933
# exit 0;
934
$opt_l = "LIST";
935
}
936
getesxversion;
937
if( $opt_l =~ /LISTNET/i ) {
938
getvmid;
939
$MSG = "";
940
readnet;
941
if(!$MSG) {
942
my($tk);
943
foreach ( keys %tmpnet ) {
944
if(!$vhost or ($VMID eq $tmpnet{$_}[0]) ) {
945
$tk=$tmpnet{$_}[1];
946
next if($MSG=~/$tk/);
947
$MSG .= ', ' if($MSG);
948
# $MSG .= $lookup{$tmpnet{$_}[0]}."/" if(!$opt_v);
949
$MSG .= $tk;
950
}
951
}
952
$STATUS = $OK;
953
}
954
dooutput;
955
exit 0;
956
}
957
if( $opt_l =~ /LIST/i ) {
958
listvm;
959
if(!$opt_w) { $warn = $B - 1; }
960
if(!$opt_c) { $crit = 0; }
961
if($warn =~ /(\d+)\%/) {
962
$warn = $B * $1 / 100;
963
} elsif( $warn < 0 ) { $warn = $B - 1; }
964
if($crit =~ /(\d+)\%/) {
965
$crit = $B * $1 / 100;
966
} elsif( $crit < 0 ) { $crit = 0; }
967
$STATUS = $WARNING if($A<=$warn); # If SOME are down
968
$STATUS = $CRITICAL if($A<=$crit); # If NONE are up
969
$STATUS = $OK if(!$B); # No guests at all
970
dooutput;
971
exit 3;
972
}
973
if( $opt_l !~ /NET|CPU|MEM|STAT|RPC/i ) {
974
$MSG = "Bad command $opt_l!";
975
dooutput;
976
exit 3;
977
}
978
if( $opt_l =~ /MEM|CPU|NET|RPC/ and !$MODE and ($crit<0 or $warn<0)) {
979
$MSG = "Invalid warn/critical thresholds for '$opt_l' (need -w and -c)";
980
dooutput;
981
exit 3;
982
}
983
984
985
# Now, we have host, vhost, community, and command
986
getvmid; # also opens SNMP object
987
if( $opt_l =~ /STAT/i ) {
988
if(!$vhost) {
989
$MSG = "No virtual hostname specified with -v";
990
dooutput;
991
exit 0;
992
}
993
if( ( $esx_version == 2 && $VMID < 0 ) || ( $esx_version == 3 && $vmGuestState ne "running" ) ) {
994
$STATUS = $CRITICAL; ($A,$B) = (0,0);
995
$MSG = "VHost $vhost is down or undefined.";
996
} else {
997
$STATUS = $OK; ($A,$B) = (1,1);
998
$MSG = "VHost $vhost is up (ID: $VMID)";
999
}
1000
push @perf, "vhost_up=$A;;;0;1";
1001
dooutput;
1002
exit 0;
1003
}
1004
if($vhost and ( $esx_version == 2 && $VMID < 0 || $esx_version == 3 && $vmGuestState ne "running" )) {
1005
$STATUS = $CRITICAL;
1006
$MSG = "$vhost is not running." if(!$MSG);
1007
if( $opt_l =~ /CPU/i ) {
1008
# Fill in some dummy performance data anyway, to keep downstream processes happy.
1009
push @perf, "vhost_cpu_used_pc=U%;;;0;100";
1010
push @perf, "vhost_cpu_ready_pc=U%;;;0;100";
1011
}
1012
if( $opt_l =~ /MEM/i ) {
1013
# Fill in some dummy performance data anyway, to keep
1014
# downstream processes happy.
1015
push @perf, "vhost_mem_act_pc=U%;;;0;100";
1016
push @perf, "vhost_mem_pvt_pc=U%;;;0;100";
1017
push @perf, "vhost_mem_shr_pc=U%;;;0;100";
1018
push @perf, "vhost_mem_bal_pc=U%;;;0;100";
1019
push @perf, "vhost_mem_swp_pc=U%;;;0;100";
1020
}
1021
if( $opt_l =~ /NET/i ) {
1022
# Fill in some dummy performance data anyway, to keep
1023
#downstream processes happy.
1024
push @perf, "vhost_net_read=U;;;0";
1025
push @perf, "vhost_net_write=U;;;0";
1026
}
1027
dooutput;
1028
exit 0;
1029
}
1030
1031
$STATUS = $OK;
1032
if( $opt_l =~ /CPU/i ) {
1033
$warn = 70 if(!$opt_w);
1034
$crit = 90 if(!$opt_c);
1035
$MSG = "";
1036
readxcpu; # attempt to use extended MIB, else use VMWare MIB
1037
} elsif( $opt_l =~ /NET/i ) {
1038
my($t1,$t2,$a1,$b1);
1039
$opt_i = "" if(!defined $opt_i);
1040
$vhost = "" if(!defined $vhost);
1041
if( !$MODE or $opt_r ) {
1042
readstate;
1043
$t1 = $states{"$hostname-NET-$vhost-$opt_i-time"};
1044
$a1 = $states{"$hostname-NET-$vhost-$opt_i-r"};
1045
$b1 = $states{"$hostname-NET-$vhost-$opt_i-w"};
1046
$t2 = time;
1047
}
1048
$MSG = "";
1049
readnet;
1050
if(!$MSG){ # IE, no errors
1051
$MSG = "Network counters Read=$A Write=$B";
1052
$MSG .= " on $vhost" if($vhost);
1053
if( $opt_i ) {
1054
if( $vhost ) { $MSG .= '/'; } else { $MSG .= ' on '; }
1055
$MSG .= $opt_i;
1056
}
1057
if( !$MODE or $opt_r ) {
1058
writestate( "$hostname-NET-$vhost-$opt_i-r"=>$A,
1059
"$hostname-NET-$vhost-$opt_i-w"=>$B,
1060
"$hostname-NET-$vhost-$opt_i-time"=>$t2 )
1061
if(!$t1 or ($t2-$t1)>30);
1062
if(!$t1 or (!$a1 and !$b1) or ($t1 >= $t2) or (($t2 - $t1)>3600)) {
1063
$MSG = "Gathering network statistics - please wait for next poll.";
1064
$A = $B = "U";
1065
$STATUS = $UNKNOWN;
1066
if ($vhost) {
1067
push @perf, "vhost_net_read=U;;;0";
1068
push @perf, "vhost_net_write=U;;;0";
1069
} else {
1070
push @perf, "allvms_net_read=U;;;0";
1071
push @perf, "allvms_net_write=U;;;0";
1072
}
1073
} else {
1074
$A = ($A - $a1)/($t2 - $t1);
1075
$B = ($B - $b1)/($t2 - $t1);
1076
($fa,$sa,$fb,$sb) = ( $A, "", $B, "" );
1077
if($fa >= 1048576) { $fa /= 1048576; $sa = 'M'; }
1078
elsif($fa >= 1024) { $fa /= 1024; $sa = 'K'; }
1079
if($fb >= 1048576) { $fb /= 1048576; $sb = 'M'; }
1080
elsif($fb >= 1024) { $fb /= 1024; $sb = 'K'; }
1081
$fa = int($fa * 100)/100; $fb = int($fb * 100)/100;
1082
$MSG = "Network traffic $fa ".$sa."B/s read, $fb ".$sb."B/s write ";
1083
$MSG .= "on $vhost" if($vhost);
1084
if( $opt_i ) {
1085
if( $vhost ) { $MSG .= '/'; } else { $MSG .= 'on '; }
1086
$MSG .= $opt_i;
1087
}
1088
$MSG .= " (".($t2-$t1)."s average)";
1089
if ($vhost) {
1090
push @perf, "vhost_net_read=".(int(100*$A)/100.0).";;;0";
1091
push @perf, "vhost_net_write=".(int(100*$B)/100.0).";;;0";
1092
} else {
1093
push @perf, "allvms_net_read=".(int(100*$A)/100.0).";;;0";
1094
push @perf, "allvms_net_write=".(int(100*$B)/100.0).";;;0";
1095
}
1096
}
1097
}
1098
}
1099
} elsif( $opt_l =~ /MEM/i ) {
1100
my($pc,$tot,$av,$sfx);
1101
$MSG = "";
1102
if($opt_v) {
1103
$warn = 70 if(!$opt_w);
1104
$crit = 90 if(!$opt_c);
1105
} else {
1106
$warn = 30 if(!$opt_w);
1107
$crit = 10 if(!$opt_c);
1108
}
1109
readxmem;
1110
if(!$MSG) {
1111
$pc = int($A/$B*10000.0)/100.0;
1112
$sfx = "Kb"; $av = $A;
1113
if($av>2047) { $av = int($av/10.24)/100.0; $sfx="Mb"; }
1114
$av .= $sfx;
1115
$sfx = "Kb"; $tot = $B;
1116
if($tot>2047) { $tot = int($tot/10.24)/100.0; $sfx="Mb"; }
1117
$tot .= $sfx;
1118
$MSG = "Memory free: $av ($pc\%) [Total available $tot]" ;
1119
$MSG .= " on vhost $vhost" if($vhost);
1120
}
1121
} elsif( $opt_l =~ /RPC/i ) {
1122
$MSG = "";
1123
readrpc;
1124
if(!$MSG) {
1125
$MSG = "RPC calls ".(int($B*100)/100)."/sec (Total: $A)";
1126
}
1127
} else {
1128
$MSG = "Invalid command $opt_l";
1129
$STATUS = $UNKNOWN;
1130
}
1131
1132
if( !$MODE and $STATUS==$OK ) {
1133
# Set Nagios thresholds
1134
if( $opt_l=~/MEM/i and $warn =~ /([\d\.]+)%/ ) { $warn = $B * $1 / 100.0; }
1135
elsif( $warn =~ /([\d\.]+)M/i ) { $warn = $1 * 1024; }
1136
elsif( $warn =~ /([\d\.]+)/i ) { $warn = $1; }
1137
if( $opt_l=~/MEM/i and $crit =~ /([\d\.]+)%/ ) { $crit = $B * $1 / 100.0; }
1138
elsif( $crit =~ /([\d\.]+)M/i ) { $crit = $1 * 1024; }
1139
elsif( $crit =~ /([\d\.]+)/i ) { $crit = $1; }
1140
if( $opt_l =~ /MEM/i ) {
1141
print "$A : $warn : $crit \n" if ($DEBUG);
1142
$STATUS = $WARNING if( $A <= $warn );
1143
$STATUS = $CRITICAL if( $A <= $crit );
1144
} elsif( $opt_l =~ /CPU/i ) {
1145
$STATUS = $WARNING if( ($A+$B) >= $warn );
1146
$STATUS = $CRITICAL if( ($A+$B) >= $crit );
1147
} elsif( $opt_l =~ /NET/i ) {
1148
$STATUS = $WARNING if( $A >= $warn );
1149
$STATUS = $WARNING if( $B >= $warn );
1150
$STATUS = $CRITICAL if( $A >= $crit );
1151
$STATUS = $CRITICAL if( $B >= $crit );
1152
} elsif( $opt_l =~ /RPC/i ) {
1153
$STATUS = $WARNING if( $B >= $warn );
1154
$STATUS = $CRITICAL if( $B >= $crit );
1155
} else {
1156
$STATUS = $WARNING if( $A <= $warn );
1157
$STATUS = $CRITICAL if( $A <= $crit );
1158
}
1159
}
1160
1161
$snmp->close if($snmp);;
1162
dooutput;
1163
exit 0;
1164