From bab9db080769003286d43870aa3edf838c68c6c5 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 15 May 2017 13:28:23 +0200 Subject: [PATCH] + add nutanix snmp plugin (Fix #602) --- .../cloud/nutanix/snmp/mode/clusterusage.pm | 290 +++++++++++++++ .../cloud/nutanix/snmp/mode/containerusage.pm | 245 +++++++++++++ .../cloud/nutanix/snmp/mode/diskusage.pm | 331 ++++++++++++++++++ .../nutanix/snmp/mode/hypervisorusage.pm | 245 +++++++++++++ .../cloud/nutanix/snmp/mode/listcontainers.pm | 114 ++++++ .../cloud/nutanix/snmp/mode/listdisks.pm | 129 +++++++ .../nutanix/snmp/mode/listhypervisors.pm | 114 ++++++ .../nutanix/snmp/mode/liststoragepools.pm | 114 ++++++ .../cloud/nutanix/snmp/mode/listvms.pm | 124 +++++++ .../nutanix/snmp/mode/storagepoolusage.pm | 245 +++++++++++++ .../cloud/nutanix/snmp/mode/vmusage.pm | 214 +++++++++++ centreon-plugins/cloud/nutanix/snmp/plugin.pm | 58 +++ 12 files changed, 2223 insertions(+) create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/clusterusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/containerusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/diskusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/hypervisorusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/listcontainers.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/listdisks.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/listhypervisors.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/liststoragepools.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/listvms.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/storagepoolusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/mode/vmusage.pm create mode 100644 centreon-plugins/cloud/nutanix/snmp/plugin.pm diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/clusterusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/clusterusage.pm new file mode 100644 index 000000000..ca3156227 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/clusterusage.pm @@ -0,0 +1,290 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::clusterusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; +my $cluster_name = ''; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'status : ' . $self->{result_values}->{status}; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_clusterStatus'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_clusterTotalStorageCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_clusterUsedStorageCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cluster', type => 0, cb_prefix_output => 'prefix_cluster_output', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{cluster} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'clusterStatus' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'clusterTotalStorageCapacity' }, { name => 'clusterUsedStorageCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'clusterLatency' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'clusterLatency_absolute', template => '%s', unit => 'µs', + min => 0 }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'clusterIops' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'clusterIops_absolute', template => '%s', unit => 'iops', + min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub prefix_cluster_output { + my ($self, %options) = @_; + + return "Cluster '" . $cluster_name . "' "; +} + +my $mapping = { + clusterName => { oid => '.1.3.6.1.4.1.41263.501' }, + clusterStatus => { oid => '.1.3.6.1.4.1.41263.503' }, + clusterTotalStorageCapacity => { oid => '.1.3.6.1.4.1.41263.504' }, + clusterUsedStorageCapacity => { oid => '.1.3.6.1.4.1.41263.505' }, + clusterIops => { oid => '.1.3.6.1.4.1.41263.506' }, + clusterLatency => { oid => '.1.3.6.1.4.1.41263.507' }, +}; +my $oid_nutanix = '.1.3.6.1.4.1.41263'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + my $snmp_result = $options{snmp}->get_table(oid => $oid_nutanix, + start => $mapping->{clusterName}->{oid}, end => $mapping->{clusterLatency}->{oid}, + nothing_quit => 1); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); + $self->{cluster} = { %$result }; + $cluster_name = centreon::plugins::misc::trim($result->{clusterName}); +} + +1; + +__END__ + +=head1 MODE + +Check cluster usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/containerusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/containerusage.pm new file mode 100644 index 000000000..0d1a30917 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/containerusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::containerusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_citTotalCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_citUsedCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'container', type => 1, cb_prefix_output => 'prefix_container_output', message_multiple => 'All containers are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{container} = [ + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'citUsedCapacity' }, { name => 'citTotalCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'citAvgLatencyUsecs' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'citAvgLatencyUsecs_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'citIOPerSecond' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'citIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_container_output { + my ($self, %options) = @_; + + return "Container '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + citContainerName => { oid => '.1.3.6.1.4.1.41263.8.1.3' }, + citTotalCapacity => { oid => '.1.3.6.1.4.1.41263.8.1.4' }, + citUsedCapacity => { oid => '.1.3.6.1.4.1.41263.8.1.5' }, + citIOPerSecond => { oid => '.1.3.6.1.4.1.41263.8.1.6' }, + citAvgLatencyUsecs => { oid => '.1.3.6.1.4.1.41263.8.1.7' }, +}; + +my $oid_citEntry = '.1.3.6.1.4.1.41263.8.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{container} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_citEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{citContainerName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{citContainerName} = centreon::plugins::misc::trim($result->{citContainerName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{citContainerName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{citContainerName} . "': no matching filter.", debug => 1); + next; + } + + $self->{container}->{$instance} = { display => $result->{citContainerName}, + %$result, + }; + } + + if (scalar(keys %{$self->{container}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No container found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check container usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter container name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/diskusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/diskusage.pm new file mode 100644 index 000000000..bbbea260e --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/diskusage.pm @@ -0,0 +1,331 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::diskusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'state : ' . $self->{result_values}->{state}; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_dstState'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_dstNumTotalBytes'}; + $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_dstNumFreeBytes'}; + $self->{result_values}->{used} = $self->{result_values}->{total} - $self->{result_values}->{free}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'disk', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disks are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{disk} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'dstState' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'dstNumFreeBytes' }, { name => 'dstNumTotalBytes' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'inodes', set => { + key_values => [ { name => 'inodes_used' }, { name => 'display' } ], + output_template => 'Inodes Used : %s %%', + perfdatas => [ + { label => 'inodes', value => 'inodes_used_absolute', template => '%s', unit => '%', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'dstAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'dstAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'dstNumberIops' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'dstNumberIops_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub prefix_disk_output { + my ($self, %options) = @_; + + return "Disk '" . $options{instance_value}->{display} . "' "; +} + +my %map_state = (1 => 'online', 2 => 'offline'); + +my $mapping = { + dstDiskId => { oid => '.1.3.6.1.4.1.41263.3.1.2' }, + dstNumTotalBytes => { oid => '.1.3.6.1.4.1.41263.3.1.6' }, + dstNumFreeBytes => { oid => '.1.3.6.1.4.1.41263.3.1.7' }, + dstNumTotalInodes => { oid => '.1.3.6.1.4.1.41263.3.1.8' }, + dstNumFreeInodes => { oid => '.1.3.6.1.4.1.41263.3.1.9' }, + dstAverageLatency => { oid => '.1.3.6.1.4.1.41263.3.1.10' }, + dstNumberIops => { oid => '.1.3.6.1.4.1.41263.3.1.12' }, + dstState => { oid => '.1.3.6.1.4.1.41263.3.1.13', map => \%map_state }, +}; + +my $oid_dstEntry = '.1.3.6.1.4.1.41263.3.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{disk} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_dstEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{dstDiskId}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{dstDiskId} = centreon::plugins::misc::trim($result->{dstDiskId}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{dstDiskId} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{dstDiskId} . "': no matching filter.", debug => 1); + next; + } + + my $inodes_used; + $inodes_used = 100 - ($result->{dstNumFreeInodes} * 100 / $result->{dstNumTotalInodes}) if ($result->{dstNumTotalInodes} > 0); + $self->{disk}->{$instance} = { display => $result->{dstDiskId}, + %$result, inodes_used => $inodes_used, + }; + } + + if (scalar(keys %{$self->{disk}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No disk found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check disk usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter disk name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--critical-status> + +Set critical threshold for status. +Can used special variables like: %{state}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'inodes' (%), 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'inodes' (%), 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/hypervisorusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/hypervisorusage.pm new file mode 100644 index 000000000..ef295314f --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/hypervisorusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::hypervisorusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'memory_used'; + my $value_perf = $self->{result_values}->{used}; + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (total => $self->{result_values}->{total}, cast_int => 1); + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Memory Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_hypervisorMemory'}; + $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_hypervisorMemoryUsagePercent'}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + $self->{result_values}->{used} = $self->{result_values}->{prct_used} * $self->{result_values}->{total} / 100; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'hypervisor', type => 1, cb_prefix_output => 'prefix_hypervisor_output', message_multiple => 'All hypervisors are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{hypervisor} = [ + { label => 'cpu', set => { + key_values => [ { name => 'hypervisorCpuUsagePercent' }, { name => 'display' } ], + output_template => 'CPU Usage : %s %%', + perfdatas => [ + { label => 'cpu_usage', value => 'hypervisorCpuUsagePercent_absolute', template => '%s', unit => '%', + min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'memory', set => { + key_values => [ { name => 'display' }, { name => 'hypervisorMemory' }, { name => 'hypervisorMemoryUsagePercent' } ], + threshold_use => 'prct_used', + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'hypervisorAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'hypervisorAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'read-iops', set => { + key_values => [ { name => 'hypervisorReadIOPerSecond' }, { name => 'display' } ], + output_template => 'Read IOPs : %s', + perfdatas => [ + { label => 'read_iops', value => 'hypervisorReadIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'write-iops', set => { + key_values => [ { name => 'hypervisorWriteIOPerSecond' }, { name => 'display' } ], + output_template => 'Write IOPs : %s', + perfdatas => [ + { label => 'write_iops', value => 'hypervisorWriteIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'vm-count', set => { + key_values => [ { name => 'hypervisorVmCount' }, { name => 'display' } ], + output_template => 'VM Count : %s', + perfdatas => [ + { label => 'vm_count', value => 'hypervisorVmCount_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_hypervisor_output { + my ($self, %options) = @_; + + return "Hypervisor '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + hypervisorName => { oid => '.1.3.6.1.4.1.41263.9.1.3' }, + hypervisorVmCount => { oid => '.1.3.6.1.4.1.41263.9.1.4' }, + hypervisorCpuUsagePercent => { oid => '.1.3.6.1.4.1.41263.9.1.6' }, + hypervisorMemory => { oid => '.1.3.6.1.4.1.41263.9.1.7' }, + hypervisorMemoryUsagePercent => { oid => '.1.3.6.1.4.1.41263.9.1.8' }, + hypervisorReadIOPerSecond => { oid => '.1.3.6.1.4.1.41263.9.1.9' }, + hypervisorWriteIOPerSecond => { oid => '.1.3.6.1.4.1.41263.9.1.10' }, + hypervisorAverageLatency => { oid => '.1.3.6.1.4.1.41263.9.1.11' }, +}; + +my $oid_hypervisorEntry = '.1.3.6.1.4.1.41263.9.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{hypervisor} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_hypervisorEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{hypervisorName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{hypervisorName} = centreon::plugins::misc::trim($result->{hypervisorName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{hypervisorName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{hypervisorName} . "': no matching filter.", debug => 1); + next; + } + + $self->{hypervisor}->{$instance} = { display => $result->{hypervisorName}, + %$result, + }; + } + + if (scalar(keys %{$self->{hypervisor}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No hypervisor found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check hypervisor usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory$' + +=item B<--filter-name> + +Filter hypervisor name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'memory' (%), 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'vm-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'memory' (%), 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'vm-count'. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/listcontainers.pm b/centreon-plugins/cloud/nutanix/snmp/mode/listcontainers.pm new file mode 100644 index 000000000..82e350f77 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/listcontainers.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listcontainers; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_citContainerName = '.1.3.6.1.4.1.41263.8.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_citContainerName, nothing_quit => 1); + $self->{container} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping container '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{container}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{container}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Containers:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{container}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List container. + +=over 8 + +=item B<--filter-name> + +Filter by container name. + +=back + +=cut + diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/listdisks.pm b/centreon-plugins/cloud/nutanix/snmp/mode/listdisks.pm new file mode 100644 index 000000000..bde130826 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/listdisks.pm @@ -0,0 +1,129 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listdisks; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my %map_state = ( + 1 => 'online', + 2 => 'offline', +); + +my $mapping = { + dstDiskId => { oid => '.1.3.6.1.4.1.41263.3.1.2' }, + dstState => { oid => '.1.3.6.1.4.1.41263.3.1.13', map => \%map_state }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{dstDiskId}->{oid} }, + { oid => $mapping->{dstState}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{disk} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{dstState}->{oid}\.(.*)$/); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $result->{dstDiskId} = centreon::plugins::misc::trim($result->{dstDiskId}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{dstDiskId} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping disk '" . $result->{dstDiskId} . "'.", debug => 1); + next; + } + + $self->{disk}->{$result->{dstDiskId}} = { %{$result} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{disk}}) { + $self->{output}->output_add(long_msg => "[disk_id = " . $self->{disk}->{$name}->{dstDiskId} . "] [state = " . $self->{disk}->{$name}->{dstState} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Disks:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['disk_id', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{disk}}) { + $self->{output}->add_disco_entry(disk_id => $self->{disk}->{$name}->{dstDiskId}, + state => $self->{disk}->{$name}->{dstState}); + } +} + +1; + +__END__ + +=head1 MODE + +List disks. + +=over 8 + +=item B<--filter-name> + +Filter by disk id. + +=back + +=cut + diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/listhypervisors.pm b/centreon-plugins/cloud/nutanix/snmp/mode/listhypervisors.pm new file mode 100644 index 000000000..d99d0a944 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/listhypervisors.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listhypervisors; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_hypervisorName = '.1.3.6.1.4.1.41263.9.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_hypervisorName, nothing_quit => 1); + $self->{hypervisor} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping hypervisor '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{hypervisor}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{hypervisor}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Hypervisors:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{hypervisor}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List hypervisors. + +=over 8 + +=item B<--filter-name> + +Filter by hypervisor name. + +=back + +=cut + diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/liststoragepools.pm b/centreon-plugins/cloud/nutanix/snmp/mode/liststoragepools.pm new file mode 100644 index 000000000..07499f79d --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/liststoragepools.pm @@ -0,0 +1,114 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::liststoragepools; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $oid_spitStoragePoolName = '.1.3.6.1.4.1.41263.7.1.3'; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_table(oid => $oid_spitStoragePoolName, nothing_quit => 1); + $self->{sp} = {}; + foreach my $oid (keys %{$snmp_result}) { + $snmp_result->{$oid} = centreon::plugins::misc::trim($snmp_result->{$oid}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$oid} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping storage pool '" . $snmp_result->{$oid} . "'.", debug => 1); + next; + } + + $self->{sp}->{$snmp_result->{$oid}} = { name => $snmp_result->{$oid} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sp}}) { + $self->{output}->output_add(long_msg => "'" . $name . "'"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Storage Pools:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{sp}}) { + $self->{output}->add_disco_entry(name => $name); + } +} + +1; + +__END__ + +=head1 MODE + +List storage pools. + +=over 8 + +=item B<--filter-name> + +Filter by storage pool name. + +=back + +=cut + diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/listvms.pm b/centreon-plugins/cloud/nutanix/snmp/mode/listvms.pm new file mode 100644 index 000000000..fe790f336 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/listvms.pm @@ -0,0 +1,124 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::listvms; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $mapping = { + vmName => { oid => '.1.3.6.1.4.1.41263.10.1.3' }, + vmPowerState => { oid => '.1.3.6.1.4.1.41263.10.1.5' }, +}; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $self->{snmp}->get_multiple_table(oids => [ + { oid => $mapping->{vmName}->{oid} }, + { oid => $mapping->{vmPowerState}->{oid} }, + ], return_type => 1, nothing_quit => 1); + $self->{vm} = {}; + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vmPowerState}->{oid}\.(.*)$/); + + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $result->{vmName} = centreon::plugins::misc::trim($result->{vmName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vmName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping virtual machine '" . $result->{vmName} . "'.", debug => 1); + next; + } + + $self->{vm}->{$result->{vmName}} = { %{$result} }; + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{vm}}) { + $self->{output}->output_add(long_msg => "[name = " . $self->{vm}->{$name}->{vmName} . "] [state = " . $self->{vm}->{$name}->{vmPowerState} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Virtual Machines:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(); + foreach my $name (sort keys %{$self->{vm}}) { + $self->{output}->add_disco_entry(name => $self->{vm}->{$name}->{vmName}, + state => $self->{vm}->{$name}->{vmPowerState}); + } +} + +1; + +__END__ + +=head1 MODE + +List virtual machines. + +=over 8 + +=item B<--filter-name> + +Filter by virtual machine name. + +=back + +=cut + diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/storagepoolusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/storagepoolusage.pm new file mode 100644 index 000000000..4cae44919 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/storagepoolusage.pm @@ -0,0 +1,245 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::storagepoolusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $label = 'used'; + my $value_perf = $self->{result_values}->{used}; + if (defined($instance_mode->{option_results}->{free})) { + $label = 'free'; + $value_perf = $self->{result_values}->{free}; + } + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%') { + $total_options{total} = $self->{result_values}->{total}; + $total_options{cast_int} = 1; + } + + $self->{output}->perfdata_add(label => $label . $extra_label, unit => 'B', + value => $value_perf, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options), + min => 0, max => $self->{result_values}->{total}); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_spitTotalCapacity'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_spitUsedCapacity'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sp', type => 1, cb_prefix_output => 'prefix_sp_output', message_multiple => 'All storage pools are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{sp} = [ + { label => 'usage', set => { + key_values => [ { name => 'display' }, { name => 'spitUsedCapacity' }, { name => 'spitTotalCapacity' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'spitAvgLatencyUsecs' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'spitAvgLatencyUsecs_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'iops', set => { + key_values => [ { name => 'spitIOPerSecond' }, { name => 'display' } ], + output_template => 'IOPs : %s', + perfdatas => [ + { label => 'iops', value => 'spitIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_sp_output { + my ($self, %options) = @_; + + return "Storage Pool '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + spitStoragePoolName => { oid => '.1.3.6.1.4.1.41263.7.1.3' }, + spitTotalCapacity => { oid => '.1.3.6.1.4.1.41263.7.1.4' }, + spitUsedCapacity => { oid => '.1.3.6.1.4.1.41263.7.1.5' }, + spitIOPerSecond => { oid => '.1.3.6.1.4.1.41263.7.1.6' }, + spitAvgLatencyUsecs => { oid => '.1.3.6.1.4.1.41263.7.1.7' }, +}; + +my $oid_spitEntry = '.1.3.6.1.4.1.41263.7.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{sp} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_spitEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{spitStoragePoolName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{spitStoragePoolName} = centreon::plugins::misc::trim($result->{spitStoragePoolName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{spitStoragePoolName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{spitStoragePoolName} . "': no matching filter.", debug => 1); + next; + } + + $self->{sp}->{$instance} = { display => $result->{spitStoragePoolName}, + %$result, + }; + } + + if (scalar(keys %{$self->{sp}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No storage pool found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check storage pool usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^usage$' + +=item B<--filter-name> + +Filter storage pool name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'usage', 'avg-latency', 'iops'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/mode/vmusage.pm b/centreon-plugins/cloud/nutanix/snmp/mode/vmusage.pm new file mode 100644 index 000000000..760421f31 --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/mode/vmusage.pm @@ -0,0 +1,214 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::mode::vmusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vm', type => 1, cb_prefix_output => 'prefix_vm_output', message_multiple => 'All virtual machines are ok', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{vm} = [ + { label => 'cpu', set => { + key_values => [ { name => 'vmCpuUsagePercent' }, { name => 'display' } ], + output_template => 'CPU Usage : %s %%', + perfdatas => [ + { label => 'cpu_usage', value => 'vmCpuUsagePercent_absolute', template => '%s', unit => '%', + min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'avg-latency', set => { + key_values => [ { name => 'vmAverageLatency' }, { name => 'display' } ], + output_template => 'Average Latency : %s µs', + perfdatas => [ + { label => 'avg_latency', value => 'vmAverageLatency_absolute', template => '%s', unit => 'µs', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'read-iops', set => { + key_values => [ { name => 'vmReadIOPerSecond' }, { name => 'display' } ], + output_template => 'Read IOPs : %s', + perfdatas => [ + { label => 'read_iops', value => 'vmReadIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'write-iops', set => { + key_values => [ { name => 'vmWriteIOPerSecond' }, { name => 'display' } ], + output_template => 'Write IOPs : %s', + perfdatas => [ + { label => 'write_iops', value => 'vmWriteIOPerSecond_absolute', template => '%s', unit => 'iops', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-in', set => { + key_values => [ { name => 'vmRxBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic In : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_in', value => 'vmRxBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'vmTxBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic Out : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_out', value => 'vmTxBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub prefix_vm_output { + my ($self, %options) = @_; + + return "Virtual machine '" . $options{instance_value}->{display} . "' "; +} + +my $mapping = { + vmName => { oid => '.1.3.6.1.4.1.41263.10.1.3' }, + vmCpuUsagePercent => { oid => '.1.3.6.1.4.1.41263.10.1.7' }, + vmMemory => { oid => '.1.3.6.1.4.1.41263.10.1.8' }, + vmMemoryUsagePercent => { oid => '.1.3.6.1.4.1.41263.10.1.9' }, + vmReadIOPerSecond => { oid => '.1.3.6.1.4.1.41263.10.1.10' }, + vmWriteIOPerSecond => { oid => '.1.3.6.1.4.1.41263.10.1.11' }, + vmAverageLatency => { oid => '.1.3.6.1.4.1.41263.10.1.12' }, + vmRxBytes => { oid => '.1.3.6.1.4.1.41263.10.1.14' }, + vmTxBytes => { oid => '.1.3.6.1.4.1.41263.10.1.15' }, +}; + +my $oid_vmEntry = '.1.3.6.1.4.1.41263.10.1'; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + $self->{vm} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_vmEntry, + nothing_quit => 1); + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vmName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $result->{vmName} = centreon::plugins::misc::trim($result->{vmName}); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vmName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vmName} . "': no matching filter.", debug => 1); + next; + } + + $result->{vmRxBytes} *= 8; + $result->{vmTxBytes} *= 8; + $self->{vm}->{$instance} = { display => $result->{vmName}, + %$result, + }; + } + + if (scalar(keys %{$self->{vm}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual machine found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "nutanix_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check virtual machine usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^memory$' + +=item B<--filter-name> + +Filter virtual machine name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'traffic-in', 'traffic-out'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'avg-latency', 'read-iops', 'write-iops', +'cpu' (%), 'traffic-in', 'traffic-out'. + +=back + +=cut diff --git a/centreon-plugins/cloud/nutanix/snmp/plugin.pm b/centreon-plugins/cloud/nutanix/snmp/plugin.pm new file mode 100644 index 000000000..019f2e53e --- /dev/null +++ b/centreon-plugins/cloud/nutanix/snmp/plugin.pm @@ -0,0 +1,58 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package cloud::nutanix::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cluster-usage' => 'cloud::nutanix::snmp::mode::clusterusage', + 'container-usage' => 'cloud::nutanix::snmp::mode::containerusage', + 'disk-usage' => 'cloud::nutanix::snmp::mode::diskusage', + 'hypervisor-usage' => 'cloud::nutanix::snmp::mode::hypervisorusage', + 'list-containers' => 'cloud::nutanix::snmp::mode::listcontainers', + 'list-disks' => 'cloud::nutanix::snmp::mode::listdisks', + 'list-hypervisors' => 'cloud::nutanix::snmp::mode::listhypervisors', + 'list-storage-pools' => 'cloud::nutanix::snmp::mode::liststoragepools', + 'list-vms' => 'cloud::nutanix::snmp::mode::listvms', + 'storage-pool-usage' => 'cloud::nutanix::snmp::mode::storagepoolusage', + 'vm-usage' => 'cloud::nutanix::snmp::mode::vmusage', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Nutanix in SNMP. + +=cut