From 0a3e6f1876d4d2c8b5c7791d627ca47519835e1e Mon Sep 17 00:00:00 2001 From: Quentin Garnier Date: Sun, 6 Oct 2013 22:22:29 +0000 Subject: [PATCH] Working on new command 'datastore-iops' - in progress git-svn-id: http://svn.merethis.net/centreon-esxd/trunk@85 a5eaa968-4c79-4d68-970d-af6011b5b055 --- connectors/vmware/centreon_esx_client.pl | 33 +++- connectors/vmware/centreonesxd.pm | 1 + connectors/vmware/lib/cmdcpuhost.pm | 2 +- connectors/vmware/lib/cmdcpuvm.pm | 2 +- connectors/vmware/lib/cmddatastoreio.pm | 2 +- connectors/vmware/lib/cmddatastoreiops.pm | 189 +++++++++++++++++++++ connectors/vmware/lib/cmddatastoreshost.pm | 2 +- connectors/vmware/lib/cmddatastoresvm.pm | 2 +- connectors/vmware/lib/cmdmemhost.pm | 2 +- connectors/vmware/lib/cmdmemvm.pm | 2 +- connectors/vmware/lib/cmdnethost.pm | 2 +- connectors/vmware/lib/cmdswaphost.pm | 2 +- connectors/vmware/lib/cmdswapvm.pm | 2 +- connectors/vmware/lib/common.pm | 70 ++++---- 14 files changed, 269 insertions(+), 44 deletions(-) create mode 100644 connectors/vmware/lib/cmddatastoreiops.pm diff --git a/connectors/vmware/centreon_esx_client.pl b/connectors/vmware/centreon_esx_client.pl index 100557fdc..1a8464158 100644 --- a/connectors/vmware/centreon_esx_client.pl +++ b/connectors/vmware/centreon_esx_client.pl @@ -125,6 +125,13 @@ sub print_usage () { print " --filter Use regexp for --datastore option (can check multiples datastores at once)\n"; print " --skip-errors Status OK if a datastore is not accessible (when you checks multiples)\n"; print "\n"; + print "'datastore-iops':\n"; + print " --datastore Datastore name to check (required)\n"; + print " -w (--warning) Warning Threshold (default none)\n"; + print " -c (--critical) Critical Threshold (default none)\n"; + print " --filter Use regexp for --datastore option (can check multiples datastores at once)\n"; + print " --skip-errors Status OK if a datastore is not accessible (when you checks multiples)\n"; + print "\n"; print "'datastore-io':\n"; print " --datastore Datastore name to check (required)\n"; print " -w (--warning) Warning Threshold in kBps (default none)\n"; @@ -354,8 +361,30 @@ sub datastoreusage_get_str { ('datastore-usage', $OPTION{vsphere}, $OPTION{datastore}, $OPTION{filter}, $OPTION{warning}, $OPTION{critical}, $OPTION{free}, $OPTION{units}, $OPTION{skip_errors})); } +sub datastoreiops_check_arg { + if (!defined($OPTION{datastore})) { + print "Option --datastore is required\n"; + print_usage(); + exit $ERRORS{UNKNOWN}; + } + if (!defined($OPTION{warning})) { + $OPTION{warning} = ''; + } + if (!defined($OPTION{critical})) { + $OPTION{critical} = ''; + } + $OPTION{filter} = (defined($OPTION{filter}) ? 1 : 0); + $OPTION{skip_errors} = (defined($OPTION{skip_errors}) ? 1 : 0); + return 0; +} + +sub datastoreiops_get_str { + return join($separatorin, + ('datastore-iops', $OPTION{vsphere}, $OPTION{datastore}, $OPTION{filter}, $OPTION{warning}, $OPTION{critical}, $OPTION{skip_errors})); +} + sub datastoreio_check_arg { - if (!defined($OPTION{'datastore'})) { + if (!defined($OPTION{datastore})) { print "Option --datastore is required\n"; print_usage(); exit $ERRORS{UNKNOWN}; @@ -795,7 +824,7 @@ if (!defined($OPTION{usage})) { print_usage(); exit $ERRORS{UNKNOWN}; } -if ($OPTION{usage} !~ /^(healthhost|datastore-usage|datastore-io|datastore-snapshots|maintenancehost|statushost|cpuhost|datastoreshost|nethost|memhost|swaphost|countvmhost|uptimehost|cpuvm|toolsvm|snapshotvm|limitvm|datastoresvm|memvm|swapvm|thinprovisioningvm|listhost|listdatastore|listnichost|getmap|stats)$/) { +if ($OPTION{usage} !~ /^(healthhost|datastore-usage|datastore-io|datastore-iops|datastore-snapshots|maintenancehost|statushost|cpuhost|datastoreshost|nethost|memhost|swaphost|countvmhost|uptimehost|cpuvm|toolsvm|snapshotvm|limitvm|datastoresvm|memvm|swapvm|thinprovisioningvm|listhost|listdatastore|listnichost|getmap|stats)$/) { print "Usage value is unknown\n"; print_usage(); exit $ERRORS{UNKNOWN}; diff --git a/connectors/vmware/centreonesxd.pm b/connectors/vmware/centreonesxd.pm index eb704b954..733e943c5 100644 --- a/connectors/vmware/centreonesxd.pm +++ b/connectors/vmware/centreonesxd.pm @@ -25,6 +25,7 @@ my @load_modules = ('centreon::esxd::cmdcountvmhost', 'centreon::esxd::cmdcpuhost', 'centreon::esxd::cmdcpuvm', 'centreon::esxd::cmddatastoreio', + 'centreon::esxd::cmddatastoreiops', 'centreon::esxd::cmddatastoreshost', 'centreon::esxd::cmddatastoresnapshots', 'centreon::esxd::cmddatastoresvm', diff --git a/connectors/vmware/lib/cmdcpuhost.pm b/connectors/vmware/lib/cmdcpuhost.pm index 58ad1e215..dca0a7241 100644 --- a/connectors/vmware/lib/cmdcpuhost.pm +++ b/connectors/vmware/lib/cmdcpuhost.pm @@ -72,7 +72,7 @@ sub run { my @instances = ('*'); my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'cpu.usage.average', 'instances' => \@instances}], $self->{obj_esxd}->{perfcounter_speriod}); return if (centreon::esxd::common::performance_errors($self->{obj_esxd}, $values) == 1); diff --git a/connectors/vmware/lib/cmdcpuvm.pm b/connectors/vmware/lib/cmdcpuvm.pm index c2bed345a..b65d83f48 100644 --- a/connectors/vmware/lib/cmdcpuvm.pm +++ b/connectors/vmware/lib/cmdcpuvm.pm @@ -88,7 +88,7 @@ sub run { my @instances = ('*'); my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'cpu.usage.average', 'instances' => \@instances}, {'label' => 'cpu.usagemhz.average', 'instances' => \@instances}, {'label' => 'cpu.ready.summation', 'instances' => \@instances}], diff --git a/connectors/vmware/lib/cmddatastoreio.pm b/connectors/vmware/lib/cmddatastoreio.pm index e610d50a0..5b7e3e73e 100644 --- a/connectors/vmware/lib/cmddatastoreio.pm +++ b/connectors/vmware/lib/cmddatastoreio.pm @@ -70,7 +70,7 @@ sub run { return if (centreon::esxd::common::datastore_state($self->{obj_esxd}, $self->{ds}, $$result[0]->{'summary.accessible'}) == 0); my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'datastore.read.average', 'instances' => ['']}, {'label' => 'datastore.write.average', 'instances' => ['']}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmddatastoreiops.pm b/connectors/vmware/lib/cmddatastoreiops.pm new file mode 100644 index 000000000..ab8a9df78 --- /dev/null +++ b/connectors/vmware/lib/cmddatastoreiops.pm @@ -0,0 +1,189 @@ + +package centreon::esxd::cmddatastoreiops; + +use strict; +use warnings; +use centreon::esxd::common; + +sub new { + my $class = shift; + my $self = {}; + $self->{logger} = shift; + $self->{obj_esxd} = shift; + $self->{commandName} = 'datastore-iops'; + + bless $self, $class; + return $self; +} + +sub getCommandName { + my $self = shift; + return $self->{commandName}; +} + +sub checkArgs { + my $self = shift; + my ($ds, $warn, $crit) = @_; + + if (!defined($ds) || $ds eq "") { + $self->{logger}->writeLogError("ARGS error: need datastore name"); + return 1; + } + if (defined($warn) && $warn ne "" && $warn !~ /^-?(?:\d+\.?|\.\d)\d*\z/) { + $self->{logger}->writeLogError("ARGS error: warn threshold must be a positive number"); + return 1; + } + if (defined($crit) && $crit ne "" && $crit !~ /^-?(?:\d+\.?|\.\d)\d*\z/) { + $self->{logger}->writeLogError("ARGS error: crit threshold must be a positive number"); + return 1; + } + if (defined($warn) && defined($crit) && $warn ne "" && $crit ne "" && $warn > $crit) { + $self->{logger}->writeLogError("ARGS error: warn threshold must be lower than crit threshold"); + return 1; + } + return 0; +} + +sub initArgs { + my $self = shift; + $self->{ds} = $_[0]; + $self->{filter} = (defined($_[1]) && $_[1] == 1) ? 1 : 0; + $self->{warn} = (defined($_[2]) ? $_[2] : ''); + $self->{crit} = (defined($_[3]) ? $_[3] : ''); + $self->{skip_errors} = (defined($_[4]) && $_[4] == 1) ? 1 : 0; +} + +sub run { + my $self = shift; + + if (!($self->{obj_esxd}->{perfcounter_speriod} > 0)) { + my $status = centreon::esxd::common::errors_mask(0, 'UNKNOWN'); + $self->{obj_esxd}->print_response(centreon::esxd::common::get_status($status) . "|Can't retrieve perf counters.\n"); + return ; + } + + my %filters = (); + if ($self->{filter} == 0) { + $filters{name} = qr/^\Q$self->{ds}\E$/; + } else { + $filters{name} = qr/$self->{ds}/; + } + + my @properties = ('summary.accessible', 'summary.name', 'vm', 'info'); + my $result = centreon::esxd::common::get_entities_host($self->{obj_esxd}, 'Datastore', \%filters, \@properties); + if (!defined($result)) { + return ; + } + + #my %uuid_list = (); + my %disk_name = (); + my %datastore_lun = (); + foreach (@$result) { + if ($_->info->isa('VmfsDatastoreInfo')) { + #$uuid_list{$_->volume->uuid} = $_->volume->name; + # Not need. We are on Datastore level (not LUN level) + foreach my $extent (@{$_->info->vmfs->extent}) { + $disk_name{$extent->diskName} = $_->info->vmfs->name; + if (!defined($datastore_lun{$_->info->vmfs->name})) { + %{$datastore_lun{$_->info->vmfs->name}} = ('disk.numberRead.summation' => 0, 'disk.numberWrite.summation' => 0); + } + } + } + #if ($_->info->isa('NasDatastoreInfo')) { + # Zero disk Info + #} + } + + use Data::Dumper; + + my @vm_array = (); + my %added_vm = (); + foreach my $entity_view (@$result) { + if (defined($entity_view->vm)) { + foreach (@{$entity_view->vm}) { + next if (defined($added_vm{$_->{value}})); + push @vm_array, $_; + $added_vm{$_->{value}} = 1; + } + } + } + + @properties = ('name', 'runtime.connectionState'); + my $result2 = centreon::esxd::common::get_views($self->{obj_esxd}, \@vm_array, \@properties); + if (!defined($result2)) { + return ; + } + + my %ref_ids_vm = (); + foreach (@$result2) { + $ref_ids_vm{$_->{mo_ref}->{value}} = $_->{name}; + } + + print STDERR Data::Dumper::Dumper(%ref_ids_vm); + + # Vsphere >= 4.1 + my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, + $result2, + [{'label' => 'disk.numberRead.summation', 'instances' => ['*']}, + {'label' => 'disk.numberWrite.summation', 'instances' => ['*']}], + $self->{obj_esxd}->{perfcounter_speriod}, 1, 1); + print STDERR Data::Dumper::Dumper($values); + return ; + + return if (centreon::esxd::common::performance_errors($self->{obj_esxd}, $values) == 1); + + + + foreach (keys %$values) { + my ($id, $disk_name) = split(/:/); + $datastore_lun{$disk_name{$disk_name}}{$self->{obj_esxd}->{perfcounter_cache_reverse}->{$id}} += $values->{$_}[0]; + } + + my $status = 0; # OK + my $output = ''; + my $output_append = ''; + my $output_warning = ''; + my $output_warning_append = ''; + my $output_critical = ''; + my $output_critical_append = ''; + my $perfdata = ''; + foreach (keys %datastore_lun) { + my $read_counter = centreon::esxd::common::simplify_number(centreon::esxd::common::convert_number($datastore_lun{$_}{'disk.numberRead.summation'} / $self->{obj_esxd}->{perfcounter_speriod})); + my $write_counter = centreon::esxd::common::simplify_number(centreon::esxd::common::convert_number($datastore_lun{$_}{'disk.numberWrite.summation'} / $self->{obj_esxd}->{perfcounter_speriod})); + + if (defined($self->{crit}) && $self->{crit} ne "" && ($read_counter >= $self->{crit})) { + centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ", + "read on '" . $_ . "' is $read_counter ms"); + $status = centreon::esxd::common::errors_mask($status, 'CRITICAL'); + } elsif (defined($self->{warn}) && $self->{warn} ne "" && ($read_counter >= $self->{warn})) { + centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ", + "read on '" . $_ . "' is $read_counter ms"); + $status = centreon::esxd::common::errors_mask($status, 'WARNING'); + } + if (defined($self->{crit}) && $self->{crit} ne "" && ($write_counter >= $self->{crit})) { + centreon::esxd::common::output_add(\$output_critical, \$output_critical_append, ", ", + "write on '" . $_ . "' is $write_counter ms"); + $status = centreon::esxd::common::errors_mask($status, 'CRITICAL'); + } elsif (defined($self->{warn}) && $self->{warn} ne "" && ($write_counter >= $self->{warn})) { + centreon::esxd::common::output_add(\$output_warning, \$output_warning_append, ", ", + "write on '" . $_ . "' is $write_counter ms"); + $status = centreon::esxd::common::errors_mask($status, 'WARNING'); + } + + $perfdata .= " 'riops_" . $_ . "'=" . $read_counter . "iops 'wiops_" . $_ . "'=" . $write_counter . 'iops'; + } + + if ($output_critical ne "") { + $output .= $output_append . "CRITICAL - Datastore IOPS counter: $output_critical"; + $output_append = ". "; + } + if ($output_warning ne "") { + $output .= $output_append . "WARNING - Datastore IOPS counter: $output_warning"; + } + if ($status == 0) { + $output = "All Datastore IOPS counters are ok"; + } + $self->{obj_esxd}->print_response(centreon::esxd::common::get_status($status) . "|$output|$perfdata\n"); +} + +1; diff --git a/connectors/vmware/lib/cmddatastoreshost.pm b/connectors/vmware/lib/cmddatastoreshost.pm index 931b90057..26e063d62 100644 --- a/connectors/vmware/lib/cmddatastoreshost.pm +++ b/connectors/vmware/lib/cmddatastoreshost.pm @@ -122,7 +122,7 @@ sub run { # Vsphere >= 4.1 # You get counters even if datastore is disconnect... my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'datastore.totalReadLatency.average', 'instances' => $instances}, {'label' => 'datastore.totalWriteLatency.average', 'instances' => $instances}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmddatastoresvm.pm b/connectors/vmware/lib/cmddatastoresvm.pm index c499cee3e..13351865a 100644 --- a/connectors/vmware/lib/cmddatastoresvm.pm +++ b/connectors/vmware/lib/cmddatastoresvm.pm @@ -104,7 +104,7 @@ sub run { # Vsphere >= 4.1 my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'disk.numberRead.summation', 'instances' => ['*']}, {'label' => 'disk.numberWrite.summation', 'instances' => ['*']}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmdmemhost.pm b/connectors/vmware/lib/cmdmemhost.pm index b7d90e824..88f88fadd 100644 --- a/connectors/vmware/lib/cmdmemhost.pm +++ b/connectors/vmware/lib/cmdmemhost.pm @@ -73,7 +73,7 @@ sub run { my $memory_size = $$result[0]->{'summary.hardware.memorySize'}; my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'mem.consumed.average', 'instances' => ['']}, {'label' => 'mem.overhead.average', 'instances' => ['']}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmdmemvm.pm b/connectors/vmware/lib/cmdmemvm.pm index 25d32c288..3740cad31 100644 --- a/connectors/vmware/lib/cmdmemvm.pm +++ b/connectors/vmware/lib/cmdmemvm.pm @@ -74,7 +74,7 @@ sub run { my $memory_size = $$result[0]->{'summary.config.memorySizeMB'} * 1024 * 1024; my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'mem.active.average', 'instances' => ['']}, {'label' => 'mem.overhead.average', 'instances' => ['']}, {'label' => 'mem.vmmemctl.average', 'instances' => ['']}, diff --git a/connectors/vmware/lib/cmdnethost.pm b/connectors/vmware/lib/cmdnethost.pm index cb645ef73..6e28604e6 100644 --- a/connectors/vmware/lib/cmdnethost.pm +++ b/connectors/vmware/lib/cmdnethost.pm @@ -122,7 +122,7 @@ sub run { my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'net.received.average', 'instances' => $instances}, {'label' => 'net.transmitted.average', 'instances' => $instances}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmdswaphost.pm b/connectors/vmware/lib/cmdswaphost.pm index 8384896e8..fbd52611f 100644 --- a/connectors/vmware/lib/cmdswaphost.pm +++ b/connectors/vmware/lib/cmdswaphost.pm @@ -71,7 +71,7 @@ sub run { $$result[0]->{'runtime.connectionState'}->val) == 0); my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'mem.swapinRate.average', 'instances' => ['']}, {'label' => 'mem.swapoutRate.average', 'instances' => ['']}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/cmdswapvm.pm b/connectors/vmware/lib/cmdswapvm.pm index 7c52a1e84..03a8df3f1 100644 --- a/connectors/vmware/lib/cmdswapvm.pm +++ b/connectors/vmware/lib/cmdswapvm.pm @@ -72,7 +72,7 @@ sub run { $$result[0]->{'runtime.powerState'}->val) == 0); my $values = centreon::esxd::common::generic_performance_values_historic($self->{obj_esxd}, - $$result[0], + $result, [{'label' => 'mem.swapinRate.average', 'instances' => ['']}, {'label' => 'mem.swapoutRate.average', 'instances' => ['']}], $self->{obj_esxd}->{perfcounter_speriod}); diff --git a/connectors/vmware/lib/common.pm b/connectors/vmware/lib/common.pm index 6a22442f6..6a82abd59 100644 --- a/connectors/vmware/lib/common.pm +++ b/connectors/vmware/lib/common.pm @@ -165,19 +165,15 @@ sub get_perf_metric_ids { } sub generic_performance_values_historic { - my ($obj_esxd, $view, $perfs, $interval, $skip_undef_counter) = @_; + my ($obj_esxd, $views, $perfs, $interval, $skip_undef_counter, $multiples) = @_; my $counter = 0; my %results; - if (!defined($skip_undef_counter)) { - - } - eval { my $perf_metric_ids = get_perf_metric_ids($obj_esxd, $perfs); return undef if (!defined($perf_metric_ids)); - my $perf_query_spec; + my @perf_query_spec; my $tstamp = time(); my (@t) = gmtime($tstamp - $interval); my $startTime = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", @@ -186,38 +182,48 @@ sub generic_performance_values_historic { my $endTime = sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", (1900+$t[5]),(1+$t[4]),$t[3],$t[2],$t[1],$t[0]); - if ($interval == 20) { - $perf_query_spec = PerfQuerySpec->new(entity => $view, - metricId => $perf_metric_ids, - format => 'normal', - intervalId => 20, - startTime => $startTime, - endTime => $endTime, - maxSample => 1); - } else { - $perf_query_spec = PerfQuerySpec->new(entity => $view, - metricId => $perf_metric_ids, - format => 'normal', - intervalId => $interval, - startTime => $startTime, - endTime => $endTime - ); - #maxSample => 1); + foreach (@$views) { + if ($interval == 20) { + push @perf_query_spec, PerfQuerySpec->new(entity => $_, + metricId => $perf_metric_ids, + format => 'normal', + intervalId => 20, + startTime => $startTime, + endTime => $endTime, + maxSample => 1); + } else { + push @perf_query_spec, PerfQuerySpec->new(entity => $_, + metricId => $perf_metric_ids, + format => 'normal', + intervalId => $interval, + startTime => $startTime, + endTime => $endTime + ); + #maxSample => 1); + } } - my $perfdata = $obj_esxd->{perfmanager_view}->QueryPerf(querySpec => $perf_query_spec); + my $perfdata = $obj_esxd->{perfmanager_view}->QueryPerf(querySpec => \@perf_query_spec); + if (!$$perfdata[0] || !defined($$perfdata[0]->value)) { $obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe you have call a wrong instance.\n"); return undef; } - foreach (@{$$perfdata[0]->value}) { - if (defined($skip_undef_counter) && $skip_undef_counter == 1 && !defined($_->value)) { - results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = undef; - next; - } elsif (!defined($_->value)) { - $obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe there is time sync problem (check the esxd server and the target also).\n"); - return undef; + foreach my $val (@$perfdata) { + foreach (@{$val->{value}}) { + if (defined($skip_undef_counter) && $skip_undef_counter == 1 && !defined($_->value)) { + $results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = undef; + next; + } elsif (!defined($_->value)) { + $obj_esxd->print_response("-3|Error: Cannot get value for counters. Maybe there is time sync problem (check the esxd server and the target also).\n"); + return undef; + } + + if (defined($multiples) && $multiples == 1) { + $results{$val->{entity}->{value} . ":" . $_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = $_->value; + } else { + $results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = $_->value; + } } - $results{$_->id->counterId . ":" . (defined($_->id->instance) ? $_->id->instance : "")} = $_->value; } }; if ($@) {