From c31f096929de97a073e405021e70b8beb80bd8cd Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 6 May 2020 16:26:04 +0200 Subject: [PATCH] Fix #1807 --- .../netapp/santricity/restapi/custom/api.pm | 4 +- .../santricity/restapi/mode/storagepools.pm | 176 ++++++++++++++++ .../santricity/restapi/mode/storagesystems.pm | 194 ++++++++++++++++++ .../santricity/restapi/mode/storagevolumes.pm | 189 +++++++++++++++++ storage/netapp/santricity/restapi/plugin.pm | 5 +- 5 files changed, 566 insertions(+), 2 deletions(-) create mode 100644 storage/netapp/santricity/restapi/mode/storagepools.pm create mode 100644 storage/netapp/santricity/restapi/mode/storagesystems.pm create mode 100644 storage/netapp/santricity/restapi/mode/storagevolumes.pm diff --git a/storage/netapp/santricity/restapi/custom/api.pm b/storage/netapp/santricity/restapi/custom/api.pm index ac5f26aa5..227aaeb99 100644 --- a/storage/netapp/santricity/restapi/custom/api.pm +++ b/storage/netapp/santricity/restapi/custom/api.pm @@ -184,7 +184,7 @@ sub execute_storages_request { my $content = do { local $/ = undef; - if (!open my $fh, "<", '/home/qgarnier/clients/plugins/todo/santricity/test-inventory.txt') { + if (!open my $fh, "<", '/home/qgarnier/clients/plugins/todo/santricity/test-storages.txt') { $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{$_} : $!"); $self->{output}->option_exit(); } @@ -196,6 +196,8 @@ sub execute_storages_request { return $content; my $storages = $self->request_api(name => 'storages', endpoint => '/storage-systems'); + return $storages if (!defined($options{endpoint})); + for (my $i = 0; $i < scalar(@{$storages->{storages}}); $i++) { next if (defined($options{filter_name}) && $options{filter_name} ne '' && $storages->{storages}->{$i}->{name} !~ /$options{filter_name}/); diff --git a/storage/netapp/santricity/restapi/mode/storagepools.pm b/storage/netapp/santricity/restapi/mode/storagepools.pm new file mode 100644 index 000000000..ce91c0354 --- /dev/null +++ b/storage/netapp/santricity/restapi/mode/storagepools.pm @@ -0,0 +1,176 @@ +# +# Copyright 2020 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 storage::netapp::santricity::restapi::mode::storagepools; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'state: %s [raid status: %s]', + $self->{result_values}->{state}, + $self->{result_values}->{raid_status} + ); +} + +sub ss_long_output { + my ($self, %options) = @_; + + return "checking storage system '" . $options{instance_value}->{display} . "'"; +} + +sub prefix_ss_output { + my ($self, %options) = @_; + + return "storage system '" . $options{instance_value}->{display} . "' "; +} + +sub prefix_pool_output { + my ($self, %options) = @_; + + return "pool '" . $options{instance_value}->{display} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'ss', type => 3, cb_prefix_output => 'prefix_ss_output', cb_long_output => 'ss_long_output', indent_long_output => ' ', message_multiple => 'All storage systems are ok', + group => [ + { name => 'pools', display_long => 1, cb_prefix_output => 'prefix_pool_output', message_multiple => 'pools are ok', type => 1, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{pools} = [ + { label => 'pool-status', threshold => 0, set => { + key_values => [ { name => 'raid_status' }, { name => 'state'}, { name => 'display' } ], + closure_custom_calc => \&catalog_status_calc, + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-storage-name:s' => { name => 'filter_storage_name' }, + 'filter-pool-name:s' => { name => 'filter_pool_name' }, + 'unknown-pool-status:s' => { name => 'unknown_pool_status', default => '' }, + 'warning-pool-status:s' => { name => 'warning_pool_status', default => '%{raid_status} =~ /degraded/i' }, + 'critical-pool-status:s' => { name => 'critical_pool_status', default => '%{raid_status} =~ /failed/i' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_pool_status', 'critical_pool_status', 'unknown_pool_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->execute_storages_request( + endpoint => '/storage-pools', + filter_name => $self->{option_results}->{filter_storage_name} + ); + + $self->{ss} = {}; + foreach (@{$results->{storages}}) { + my $storage_name = $_->{name}; + + $self->{ss}->{$storage_name} = { + display => $storage_name, + pools => {} + }; + + next if (!defined($_->{'/storage-pools'})); + + foreach my $entry (@{$_->{'/storage-pools'}}) { + + next if (defined($self->{option_results}->{filter_pool_name}) && $self->{option_results}->{filter_pool_name} ne '' && + $entry->{name} !~ /$self->{option_results}->{filter_pool_name}/); + + $self->{ss}->{$storage_name}->{pools}->{ $entry->{name} } = { + display => $entry->{name}, + state => $entry->{state}, + raid_status => $entry->{raidStatus} + }; + } + } +} + +1; + +__END__ + +=head1 MODE + +Check storage pools. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^pool-status$' + +=item B<--filter-storage-name> + +Filter storage name (can be a regexp). + +=item B<--filter-pool-name> + +Filter pool name (can be a regexp). + +=item B<--unknown-pool-status> + +Set unknown threshold for status. +Can used special variables like: %{raid_status}, %{state}, %{display} + +=item B<--warning-pool-status> + +Set warning threshold for status (Default: '%{raid_status} =~ /degraded/i'). +Can used special variables like: %{raid_status}, %{state}, %{display} + +=item B<--critical-pool-status> + +Set critical threshold for status (Default: '%{raid_status} =~ /failed/i'). +Can used special variables like: %{raid_status}, %{state}, %{display} + +=back + +=cut diff --git a/storage/netapp/santricity/restapi/mode/storagesystems.pm b/storage/netapp/santricity/restapi/mode/storagesystems.pm new file mode 100644 index 000000000..a1ca67925 --- /dev/null +++ b/storage/netapp/santricity/restapi/mode/storagesystems.pm @@ -0,0 +1,194 @@ +# +# Copyright 2020 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 storage::netapp::santricity::restapi::mode::storagesystems; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'status: %s', + $self->{result_values}->{status} + ); +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space_absolute}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space_absolute}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space_absolute}); + my $msg = sprintf( + 'space 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_space_absolute}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space_absolute} + ); + return $msg; +} + +sub prefix_ss_output { + my ($self, %options) = @_; + + return "storage system '" . $options{instance_value}->{display} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'ss', type => 1, cb_prefix_output => 'prefix_ss_output', message_multiple => 'All storage systems are ok' } + ]; + + $self->{maps_counters}->{ss} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' } ], + closure_custom_calc => \&catalog_status_calc, + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold + } + }, + { label => 'usage', nlabel => 'pool.space.usage.bytes', set => { + key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'display' }, ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { value => 'used_space_absolute', template => '%d', min => 0, max => 'total_space_absolute', + unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'usage-free', nlabel => 'pool.space.free.bytes', display_ok => 0, set => { + key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' }, { name => 'display' }, ], + closure_custom_output => $self->can('custom_usage_output'), + perfdatas => [ + { value => 'free_space_absolute', template => '%d', min => 0, max => 'total_space_absolute', + unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'usage-prct', nlabel => 'pool.space.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'prct_used_space' }, { name => 'display' } ], + output_template => 'used : %.2f %%', + perfdatas => [ + { value => 'prct_used_space_absolute', template => '%.2f', min => 0, max => 100, + unit => '%', label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-storage-name:s' => { name => 'filter_storage_name' }, + 'unknown-status:s' => { name => 'unknown_status', default => '' }, + 'warning-status:s' => { name => 'warning_status', default => '' }, + 'critical-status:s' => { name => 'critical_status', default => '%{status} =~ /needsAttn/i' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->execute_storages_request(); + + $self->{ss} = {}; + foreach (@{$results->{storages}}) { + my $storage_name = $_->{name}; + + next if (defined($options{filter_storage_name}) && $options{filter_storage_name} ne '' && + $storage_name !~ /$options{filter_storage_name}/); + + $self->{ss}->{$storage_name} = { + display => $_->{name}, + status => $_->{status}, + total_space => $_->{usedPoolSpace} + $_->{freePoolSpace}, + used_space => $_->{usedPoolSpace}, + free_space => $_->{freePoolSpace}, + prct_used_space => + ($_->{usedPoolSpace} * 100 / ($_->{usedPoolSpace} + $_->{freePoolSpace})), + prct_free_space => + ($_->{freePoolSpace} * 100 / ($_->{usedPoolSpace} + $_->{freePoolSpace})) + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check storage systems. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='status' + +=item B<--filter-storage-name> + +Filter storage name (can be a regexp). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{status}, %{state}, %{display} + +=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 (Default: '%{status} =~ /needsAttn/i'). +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%). + +=back + +=cut diff --git a/storage/netapp/santricity/restapi/mode/storagevolumes.pm b/storage/netapp/santricity/restapi/mode/storagevolumes.pm new file mode 100644 index 000000000..1746a8052 --- /dev/null +++ b/storage/netapp/santricity/restapi/mode/storagevolumes.pm @@ -0,0 +1,189 @@ +# +# Copyright 2020 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 storage::netapp::santricity::restapi::mode::storagevolumes; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold catalog_status_calc); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'status: %s', + $self->{result_values}->{status} + ); +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space_absolute}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space_absolute}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space_absolute}); + my $msg = sprintf( + 'space 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_space_absolute}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space_absolute} + ); + return $msg; +} + +sub ss_long_output { + my ($self, %options) = @_; + + return "checking storage system '" . $options{instance_value}->{display} . "'"; +} + +sub prefix_ss_output { + my ($self, %options) = @_; + + return "storage system '" . $options{instance_value}->{display} . "' "; +} + +sub prefix_volume_output { + my ($self, %options) = @_; + + return "volume '" . $options{instance_value}->{display} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'ss', type => 3, cb_prefix_output => 'prefix_ss_output', cb_long_output => 'ss_long_output', indent_long_output => ' ', message_multiple => 'All storage systems are ok', + group => [ + { name => 'volumes', display_long => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'volumes are ok', type => 1, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{volumes} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' } ], + closure_custom_calc => \&catalog_status_calc, + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-storage-name:s' => { name => 'filter_storage_name' }, + 'filter-volume-name:s' => { name => 'filter_volume_name' }, + 'unknown-volyme-status:s' => { name => 'unknown_volume_status', default => '' }, + 'warning-volume-status:s' => { name => 'warning_volume_status', default => '%{status} =~ /degraded/i' }, + 'critical-volume-status:s' => { name => 'critical_volume_status', default => '%{status} =~ /failed/i' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_volume_status', 'critical_volume_status', 'unknown_volume_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->execute_storages_request( + endpoint => '/storage-volumes', + filter_name => $self->{option_results}->{filter_storage_name} + ); + + $self->{ss} = {}; + foreach (@{$results->{storages}}) { + my $storage_name = $_->{name}; + + $self->{ss}->{$storage_name} = { + display => $storage_name, + volumes => {} + }; + + next if (!defined($_->{'/storage-volumes'})); + + foreach my $entry (@{$_->{'/storage-volumes'}}) { + + next if (defined($options{filter_volume_name}) && $options{filter_volume_name} ne '' && + $entry->{name} !~ /$options{filter_volume_name}/); + + $self->{ss}->{$storage_name}->{volumes}->{ $entry->{name} } = { + display => $entry->{name}, + status => $entry->{status} + }; + } + } +} + +1; + +__END__ + +=head1 MODE + +Check storage volumes. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='volume-status' + +=item B<--filter-storage-name> + +Filter storage name (can be a regexp). + +=item B<--filter-volume-name> + +Filter volume name (can be a regexp). + +=item B<--unknown-volume-status> + +Set unknown threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--warning-volume-status> + +Set warning threshold for status (Default: '%{status} =~ /degraded/i'). +Can used special variables like: %{status}, %{display} + +=item B<--critical-volume-status> + +Set critical threshold for status (Default: '%{status} =~ /failed/i'). +Can used special variables like: %{status}, %{display} + +=back + +=cut diff --git a/storage/netapp/santricity/restapi/plugin.pm b/storage/netapp/santricity/restapi/plugin.pm index d201c68c0..1ede0b11e 100644 --- a/storage/netapp/santricity/restapi/plugin.pm +++ b/storage/netapp/santricity/restapi/plugin.pm @@ -31,7 +31,10 @@ sub new { $self->{version} = '0.1'; %{ $self->{modes} } = ( - 'hardware' => 'storage::netapp::santricity::restapi::mode::hardware' + 'hardware' => 'storage::netapp::santricity::restapi::mode::hardware', + 'storage-pools' => 'storage::netapp::santricity::restapi::mode::storagepools', + 'storage-systems' => 'storage::netapp::santricity::restapi::mode::storagesystems', + 'storage-volumes' => 'storage::netapp::santricity::restapi::mode::storagevolumes' ); $self->{custom_modes}{api} = 'storage::netapp::santricity::restapi::custom::api';