diff --git a/storage/netapp/ontap/snmp/mode/aggregates.pm b/storage/netapp/ontap/snmp/mode/aggregates.pm new file mode 100644 index 000000000..6f5a5d402 --- /dev/null +++ b/storage/netapp/ontap/snmp/mode/aggregates.pm @@ -0,0 +1,166 @@ +# +# Copyright 2021 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::ontap::snmp::mode::aggregates; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub prefix_agg_output { + my ($self, %options) = @_; + + return "Aggregate '" . $options{instance_value}->{name} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'agg', type => 1, cb_prefix_output => 'prefix_agg_output', message_multiple => 'All aggregates are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{agg} = [ + { label => 'state', type => 2, critical_default => '%{state} =~ /offline/i',set => { + key_values => [ { name => 'state' }, { name => 'name' } ], + output_template => "state: %s", + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'status', type => 2, critical_default => '%{status} !~ /normal|mirrored/i', set => { + key_values => [ { name => 'status' }, { name => 'name' } ], + output_template => "status: '%s'", + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-name:s' => { name => 'filter_name' } + }); + + return $self; +} + +my $mapping = { + state => { oid => '.1.3.6.1.4.1.789.1.5.11.1.5' }, # aggrState + status => { oid => '.1.3.6.1.4.1.789.1.5.11.1.6' } # aggrStatus +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_aggrName = '.1.3.6.1.4.1.789.1.5.11.1.2'; + + $self->{agg} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_aggrName, nothing_quit => 1); + foreach my $oid (keys %$snmp_result) { + $oid =~ /^$oid_aggrName\.(.*)$/; + my $instance = $1; + my $name = $snmp_result->{$oid}; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping aggregatge '" . $name . "'.", debug => 1); + next; + } + + $self->{agg}->{$instance} = { name => $name }; + } + + if (scalar(keys %{$self->{agg}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No aggregate found"); + $self->{output}->option_exit(); + } + + $options{snmp}->load( + oids => [ + map($_->{oid}, values(%$mapping)) + ], + instances => [keys %{$self->{agg}}], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + + foreach (keys %{$self->{agg}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); + + $self->{agg}->{$_}->{state} = $result->{state}; + $self->{agg}->{$_}->{status} = $result->{status}; + } +} + +1; + +__END__ + +=head1 MODE + +Check aggregates. + +=over 8 + +=item B<--filter-name> + +Filter aggregates by name. + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{status}, %{name} + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{name} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /normal|mirrored/i'). +Can used special variables like: %{status}, %{name} + +=item B<--unknown-state> + +Set unknown threshold for state. +Can used special variables like: %{state}, %{name} + +=item B<--warning-state> + +Set warning threshold for state. +Can used special variables like: %{state}, %{name} + +=item B<--critical-state> + +Set critical threshold for state (Default: '%{state} =~ /offline/i'). +Can used special variables like: %{state}, %{name} + +=back + +=cut diff --git a/storage/netapp/ontap/snmp/mode/aggregatestate.pm b/storage/netapp/ontap/snmp/mode/aggregatestate.pm deleted file mode 100644 index 6e791ffb4..000000000 --- a/storage/netapp/ontap/snmp/mode/aggregatestate.pm +++ /dev/null @@ -1,220 +0,0 @@ -# -# Copyright 2021 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::ontap::snmp::mode::aggregatestate; - -use base qw(centreon::plugins::templates::counter); - -use strict; -use warnings; - -sub custom_state_threshold { - my ($self, %options) = @_; - - return $self->{instance_mode}->get_severity(section => 'state', value => $self->{result_values}->{aggrState}); -} - -sub custom_state_calc { - my ($self, %options) = @_; - - $self->{result_values}->{aggrState} = $options{new_datas}->{$self->{instance} . '_aggrState'}; - return 0; -} - -sub custom_status_threshold { - my ($self, %options) = @_; - - return $self->{instance_mode}->get_severity(section => 'status', value => $self->{result_values}->{aggrStatus}); -} - -sub custom_status_calc { - my ($self, %options) = @_; - - $self->{result_values}->{aggrStatus} = $options{new_datas}->{$self->{instance} . '_aggrStatus'}; - return 0; -} - -sub set_counters { - my ($self, %options) = @_; - - $self->{maps_counters_type} = [ - { name => 'agg', type => 1, cb_prefix_output => 'prefix_agg_output', message_multiple => 'All aggregates are ok' }, - ]; - - $self->{maps_counters}->{agg} = [ - { label => 'state', set => { - key_values => [ { name => 'aggrState' } ], - closure_custom_calc => $self->can('custom_state_calc'), - output_template => "State : '%s'", output_error_template => "State : '%s'", - output_use => 'aggrState', - closure_custom_perfdata => sub { return 0; }, - closure_custom_threshold_check => $self->can('custom_state_threshold'), - } - }, - { label => 'status', set => { - key_values => [ { name => 'aggrStatus' } ], - closure_custom_calc => $self->can('custom_status_calc'), - output_template => "Status : '%s'", output_error_template => "Status : '%s'", - output_use => 'aggrStatus', - closure_custom_perfdata => sub { return 0; }, - closure_custom_threshold_check => $self->can('custom_status_threshold'), - } - }, - ]; -} - -sub prefix_agg_output { - my ($self, %options) = @_; - - return "Aggregate '" . $options{instance_value}->{aggrName} . "' "; -} - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $options{options}->add_options(arguments => { - 'filter-name:s' => { name => 'filter_name' }, - 'threshold-overload:s@' => { name => 'threshold_overload' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } -} - -my $thresholds = { - state => [ - ['online', 'OK'], - ['offline', 'CRITICAL'], - ], - status => [ - ['normal', 'OK'], - ['mirrored', 'OK'], - ['.*', 'CRITICAL'], - ], -}; - -sub get_severity { - my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } - } - } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; -} - -sub manage_selection { - my ($self, %options) = @_; - - my $oid_aggrName = '.1.3.6.1.4.1.789.1.5.11.1.2'; - my $oid_aggrState = '.1.3.6.1.4.1.789.1.5.11.1.5'; - my $oid_aggrStatus = '.1.3.6.1.4.1.789.1.5.11.1.6'; - my $snmp_result = $options{snmp}->get_multiple_table( - oids => [ - { oid => $oid_aggrName }, - { oid => $oid_aggrState }, - { oid => $oid_aggrStatus }, - ], - nothing_quit => 1 - ); - - $self->{agg} = {}; - foreach my $oid (keys %{$snmp_result->{$oid_aggrState}}) { - next if ($oid !~ /^$oid_aggrState\.(.*)$/); - my $instance = $1; - my $name = $snmp_result->{$oid_aggrName}->{$oid_aggrName . '.' . $instance}; - my $state = $snmp_result->{$oid_aggrState}->{$oid_aggrState . '.' . $instance}; - my $status = $snmp_result->{$oid_aggrStatus}->{$oid_aggrStatus . '.' . $instance}; - - if (!defined($state) || $state eq '') { - $self->{output}->output_add(long_msg => "skipping '" . $name . "': state value not set."); - next; - } - if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $name !~ /$self->{option_results}->{filter_name}/) { - $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter name."); - next; - } - - $self->{agg}->{$instance} = { aggrName => $name, aggrState => $state, aggrStatus => $status}; - } - - if (scalar(keys %{$self->{agg}}) <= 0) { - $self->{output}->add_option_msg(short_msg => "No aggregate found."); - $self->{output}->option_exit(); - } -} - -1; - -__END__ - -=head1 MODE - -Check state and status from aggregates. - -=over 8 - -=item B<--filter-name> - -Filter by aggregate name. - -=item B<--threshold-overload> - -Set to overload default threshold values (syntax: section,status,regexp) -It used before default thresholds (order stays). -Example: --threshold-overload='state,CRITICAL,^(?!(online)$)' - -=back - -=cut diff --git a/storage/netapp/ontap/snmp/mode/clusternodes.pm b/storage/netapp/ontap/snmp/mode/clusternodes.pm new file mode 100644 index 000000000..e098cb6ec --- /dev/null +++ b/storage/netapp/ontap/snmp/mode/clusternodes.pm @@ -0,0 +1,458 @@ +# +# Copyright 2021 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::ontap::snmp::mode::clusternodes; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use Digest::MD5 qw(md5_hex); + +sub custom_node_status_output { + my ($self, %options) = @_; + + return sprintf( + "node status: %s", + $self->{result_values}->{node_status} + ); +} + +sub custom_bbu_status_output { + my ($self, %options) = @_; + + return sprintf( + "nvram battery status: %s", + $self->{result_values}->{bbu_status} + ); +} + +sub custom_cpu_calc { + my ($self, %options) = @_; + + my $diff_uptime = $options{new_datas}->{$self->{instance} . '_cpuUptime'} - $options{old_datas}->{$self->{instance} . '_cpuUptime'}; + my $diff_busy = $options{new_datas}->{$self->{instance} . '_cpuBusyTime'} - $options{old_datas}->{$self->{instance} . '_cpuBusyTime'}; + + if ($diff_uptime == 0) { + $self->{result_values}->{cpu_used} = 0; + } else { + $self->{result_values}->{cpu_used} = $diff_busy * 100 / $diff_uptime; + } + + return 0; +} + +sub custom_port_link_status_output { + my ($self, %options) = @_; + + return sprintf( + "operational status: %s [admin: %s]", + $self->{result_values}->{opstatus}, + $self->{result_values}->{admstatus} + ); +} + +sub custom_port_health_output { + my ($self, %options) = @_; + + return sprintf( + "health: %s", + $self->{result_values}->{health} + ); +} + +sub node_long_output { + my ($self, %options) = @_; + + return sprintf( + "checking node '%s' ", + $options{instance_value}->{name} + ); +} + +sub prefix_node_output { + my ($self, %options) = @_; + + return sprintf( + "node '%s' ", + $options{instance_value}->{name} + ); +} + +sub prefix_port_output { + my ($self, %options) = @_; + + return sprintf( + "port '%s' [role: %s] ", + $options{instance_value}->{port_id}, + $options{instance_value}->{role} + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'nodes', type => 3, cb_prefix_output => 'prefix_node_output', cb_long_output => 'node_long_output', + indent_long_output => ' ', message_multiple => 'All nodes are ok', + group => [ + { name => 'status', type => 0, skipped_code => { -10 => 1 } }, + { name => 'cpu', type => 0, skipped_code => { -10 => 1 } }, + { name => 'env', type => 0, skipped_code => { -10 => 1 } }, + { name => 'ports', type => 1, cb_prefix_output => 'prefix_port_output', message_multiple => 'ports are ok', display_long => 1, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{status} = [ + { label => 'node-status', type => 2, critical_default => '%{node_status} eq "clusterComLost"', set => { + key_values => [ + { name => 'node_status' }, { name => 'node_name' } + ], + closure_custom_output => $self->can('custom_node_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'bbu-status', type => 2, critical_default => '%{bbu_status} !~ /fullyCharged|ok/i', set => { + key_values => [ + { name => 'bbu_status' }, { name => 'node_name' } + ], + closure_custom_output => $self->can('custom_bbu_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{cpu} = [ + { label => 'cpu-utilization', nlabel => 'node.cpu.utilization.percentage', set => { + key_values => [ { name => 'cpuUptime' }, { name => 'cpuBusyTime' } ], + closure_custom_calc => $self->can('custom_cpu_calc'), + output_template => 'cpu utilization: %.2f%%', + output_use => 'cpu_used', threshold_use => 'cpu_used', + perfdatas => [ + { value => 'cpu_used', template => '%s', min => 0, max => 100, unit => '%', label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{env} = [ + { label => 'fan-failed', nlabel => 'node.hardware.fans.failed.count', set => { + key_values => [ { name => 'envFailedFanCount' } ], + output_template => 'number of fans failed: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'psu-failed', nlabel => 'node.hardware.power_supplies.failed.count', set => { + key_values => [ { name => 'envFailedPSUCount' } ], + output_template => 'number of power supplies failed: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'temperature-overrange', nlabel => 'node.hardware.temperatures.over_range.count', set => { + key_values => [ { name => 'envOverTemp' } ], + output_template => 'number of temperatures over range: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{ports} = [ + { label => 'port-link-status', type => 2, critical_default => '%{admstatus} eq "up" and %{opstatus} ne "up"', set => { + key_values => [ + { name => 'admstatus' }, { name => 'opstatus' }, { name => 'port_id' }, { name => 'node_name' } + ], + closure_custom_output => $self->can('custom_port_link_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'port-health', type => 2, warning_default => '%{health} eq "degraded"', set => { + key_values => [ + { name => 'health' }, { name => 'port_id' }, { name => 'node_name' } + ], + closure_custom_output => $self->can('custom_port_health_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, statefile => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-node-name:s' => { name => 'filter_node_name' }, + 'filter-port-id:s' => { name => 'filter_port_id' }, + 'filter-port-role:s' => { name => 'filter_port_role' } + }); + + return $self; +} + +my $map_node_health = { + 0 => 'clusterComLost', 1 => 'clusterComOk' +}; +my $map_nvram_status = { + 1 => 'ok', 2 => 'partiallyDischarged', + 3 => 'fullyDischarged', 4 => 'notPresent', + 5 => 'nearEndOfLife', 6 => 'atEndOfLife', + 7 => 'unknown', 8 => 'overCharged', 9 => 'fullyCharged' +}; +my $map_port_admin = { + 0 => 'down', 1 => 'up' +}; +my $map_port_state = { + 0 => 'undef', 1 => 'off', 2 => 'up', 3 => 'down' +}; +my $map_port_health = { + -1 => 'unknown', 0 => 'healthy', 1 => 'degraded' +}; +my $map_port_role = { + 0 => 'undef', 1 => 'cluster', 2 => 'data', + 3 => 'node-mgmt', 4 => 'intercluster', 5 => 'cluster-mgmt' +}; + +my $mapping = { + health => { oid => '.1.3.6.1.4.1.789.1.25.2.1.11', map => $map_node_health }, # nodeHealth + cpuUptime => { oid => '.1.3.6.1.4.1.789.1.25.2.1.15' }, # nodeCpuUptime + cpuBusyTime => { oid => '.1.3.6.1.4.1.789.1.25.2.1.16' }, # nodeCpuBusyTime + bbuStatus => { oid => '.1.3.6.1.4.1.789.1.25.2.1.17', map => $map_nvram_status }, # nodeNvramBatteryStatus + envOverTemp => { oid => '.1.3.6.1.4.1.789.1.25.2.1.18' }, # nodeEnvOverTemperature + envFailedFanCount => { oid => '.1.3.6.1.4.1.789.1.25.2.1.19' }, # nodeEnvFailedFanCount + envFailedPSUCount => { oid => '.1.3.6.1.4.1.789.1.25.2.1.21' } # nodeEnvFailedPowerSupplyCount +}; +my $mapping_port = { + port_id => { oid => '.1.3.6.1.4.1.789.1.22.2.1.2' }, # netportPort + role => { oid => '.1.3.6.1.4.1.789.1.22.2.1.3', map => $map_port_role }, # netportRole + opstatus => { oid => '.1.3.6.1.4.1.789.1.22.2.1.4', map => $map_port_state }, # netportLinkState + admstatus => { oid => '.1.3.6.1.4.1.789.1.22.2.1.14', map => $map_port_admin }, # netportUpAdmin + health => { oid => '.1.3.6.1.4.1.789.1.22.2.1.30', map => $map_port_health } # netportHealthStatus +}; + +sub add_ports { + my ($self, %options) = @_; + + my $oid_netportNode = '.1.3.6.1.4.1.789.1.22.2.1.1'; + my $snmp_result = $options{snmp}->get_table( + oid => $oid_netportNode + ); + my $instances = {}; + foreach (keys %$snmp_result) { + next if (!defined($self->{nodes}->{ $snmp_result->{$_} })); + + /^$oid_netportNode\.(.*)$/; + $instances->{$1} = $snmp_result->{$_}; + } + + return if (scalar(keys %$instances) <= 0); + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping_port)) ], + instances => [ keys %$instances ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + foreach (keys %$instances) { + my $result = $options{snmp}->map_instance(mapping => $mapping_port, results => $snmp_result, instance => $_); + + if (defined($self->{option_results}->{filter_port_id}) && $self->{option_results}->{filter_port_id} ne '' && + $result->{port_id} !~ /$self->{option_results}->{filter_port_id}/) { + $self->{output}->output_add(long_msg => "skipping port '" . $result->{port_id} . "'.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_port_role}) && $self->{option_results}->{filter_port_role} ne '' && + $result->{role} !~ /$self->{option_results}->{filter_port_role}/) { + $self->{output}->output_add(long_msg => "skipping port '" . $result->{port_id} . "'.", debug => 1); + next; + } + + $self->{nodes}->{ $instances->{$_} }->{ports}->{ $result->{port_id} } = $result; + $self->{nodes}->{ $instances->{$_} }->{ports}->{ $result->{port_id} }->{node_name} = $instances->{$_}; + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_nodeName = '.1.3.6.1.4.1.789.1.25.2.1.1'; + my $snmp_result = $options{snmp}->get_table( + oid => $oid_nodeName, + nothing_quit => 1 + ); + + $self->{nodes} = {}; + foreach (keys %$snmp_result) { + /$oid_nodeName\.(.*)$/; + + my $instance = $1; + my $name = $snmp_result->{$_}; + if (defined($self->{option_results}->{filter_node_name}) && $self->{option_results}->{filter_node_name} ne '' && + $name !~ /$self->{option_results}->{filter_node_name}/) { + $self->{output}->output_add(long_msg => "skipping node '" . $name . "'.", debug => 1); + next; + } + + $self->{nodes}->{$name} = { + instance => $instance, + name => $name, + status => { name => $name }, + ports => {} + }; + } + + return if (scalar(keys %{$self->{nodes}}) <= 0); + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ map($_->{instance}, values(%{$self->{nodes}})) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + foreach (keys %{$self->{nodes}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $self->{nodes}->{$_}->{instance}); + + $self->{nodes}->{$_}->{status}->{node_status} = $result->{node_status}; + $self->{nodes}->{$_}->{status}->{bbu_status} = $result->{bbu_status}; + + $self->{nodes}->{$_}->{cpu} = { + cpuUptime => $result->{cpuUptime}, + cpuBusyTime => $result->{cpuBusyTime} + }; + $self->{nodes}->{$_}->{env} = { + envOverTemp => $result->{envOverTemp}, + envFailedFanCount => $result->{envFailedFanCount}, + envFailedPSUCount => $result->{envFailedPSUCount} + }; + } + + $self->add_ports(snmp => $options{snmp}); + + $self->{cache_name} = 'netapp_ontap_' . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + md5_hex( + (defined($self->{option_results}->{filter_counters}) ? $self->{option_results}->{filter_counters} : 'all') . '_' . + (defined($self->{option_results}->{filter_node_name}) ? $self->{option_results}->{filter_node_name} : 'all') . '_' . + (defined($self->{option_results}->{filter_port_id}) ? $self->{option_results}->{filter_port_id} : 'all') . '_' . + (defined($self->{option_results}->{filter_port_role}) ? $self->{option_results}->{filter_port_role} : 'all') + ); +} + +1; + +__END__ + +=head1 MODE + +Check cluster nodes. + +=over 8 + +=item B<--filter-node-id> + +Filter nodes by id (can be a regexp). + +=item B<--filter-port-id> + +Filter ports by id (can be a regexp). + +=item B<--filter-port-role> + +Filter ports by role (can be a regexp). + +=item B<--unknown-node-status> + +Set unknown threshold for status. +Can used special variables like: %{node_status}, %{node_name} + +=item B<--warning-node-status> + +Set warning threshold for status. +Can used special variables like: %{node_status}, %{node_name} + +=item B<--critical-node-status> + +Set critical threshold for status (Default: '%{node_status} eq "clusterComLost"'). +Can used special variables like: %{node_status}, %{node_name} + +=item B<--unknown-bbu-status> + +Set unknown threshold for status. +Can used special variables like: %{bbu_status}, %{node_name} + +=item B<--warning-bbu-status> + +Set warning threshold for status. +Can used special variables like: %{bbu_status}, %{node_name} + +=item B<--critical-bbu-status> + +Set critical threshold for status (Default: '%{bbu_status} !~ /fullyCharged|ok/i'). +Can used special variables like: %{bbu_status}, %{node_name} + +=item B<--unknown-port-link-status> + +Set unknown threshold for status. +Can used special variables like: %{admstatus}, %{opstatus}, %{port_id}, %{node_name} + +=item B<--warning-port-link-status> + +Set warning threshold for status. +Can used special variables like: %{admstatus}, %{opstatus}, %{port_id}, %{node_name} + +=item B<--critical-port-link-status> + +Set critical threshold for status (Default: '%{admstatus} eq "up" and %{opstatus} ne "up"'). +Can used special variables like: %{admstatus}, %{opstatus}, %{port_id}, %{node_name} + +=item B<--unknown-port-health> + +Set unknown threshold for status. +Can used special variables like: %{health}, %{port_id}, %{node_name} + +=item B<--warning-port-health> + +Set warning threshold for status (Default: '%{health} eq "degraded"'). +Can used special variables like: %{health}, %{port_id}, %{node_name} + +=item B<--critical-port-health> + +Set critical threshold for status. +Can used special variables like: %{health}, %{port_id}, %{node_name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'cpu-utilization', 'temperature-overrange', 'fan-failed', 'psu-failed'. + +=back + +=cut diff --git a/storage/netapp/ontap/snmp/mode/fan.pm b/storage/netapp/ontap/snmp/mode/fan.pm index a3fec8e03..524910639 100644 --- a/storage/netapp/ontap/snmp/mode/fan.pm +++ b/storage/netapp/ontap/snmp/mode/fan.pm @@ -50,38 +50,57 @@ sub run { my $oid_nodeName = '.1.3.6.1.4.1.789.1.25.2.1.1'; my $oid_nodeEnvFailedFanCount = '.1.3.6.1.4.1.789.1.25.2.1.19'; my $oid_nodeEnvFailedFanMessage = '.1.3.6.1.4.1.789.1.25.2.1.20'; - my $results = $self->{snmp}->get_multiple_table(oids => [ - { oid => $oid_envFailedFanCount }, - { oid => $oid_envFailedFanMessage }, - { oid => $oid_nodeName }, - { oid => $oid_nodeEnvFailedFanCount }, - { oid => $oid_nodeEnvFailedFanMessage } - ], nothing_quit => 1); + my $results = $self->{snmp}->get_multiple_table( + oids => [ + { oid => $oid_envFailedFanCount }, + { oid => $oid_envFailedFanMessage }, + { oid => $oid_nodeName }, + { oid => $oid_nodeEnvFailedFanCount }, + { oid => $oid_nodeEnvFailedFanMessage } + ], + nothing_quit => 1 + ); if (defined($results->{$oid_envFailedFanCount}->{$oid_envFailedFanCount . '.0'})) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Fans are ok.'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'Fans are ok.' + ); if ($results->{$oid_envFailedFanCount}->{$oid_envFailedFanCount . '.0'} != 0) { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("'%d' fans are failed [message: %s].", - $results->{$oid_envFailedFanCount}->{$oid_envFailedFanCount . '.0'}, - $results->{$oid_envFailedFanMessage}->{$oid_envFailedFanMessage . '.0'})); + $self->{output}->output_add( + severity => 'CRITICAL', + short_msg => sprintf( + "'%d' fans are failed [message: %s].", + $results->{$oid_envFailedFanCount}->{$oid_envFailedFanCount . '.0'}, + $results->{$oid_envFailedFanMessage}->{$oid_envFailedFanMessage . '.0'} + ) + ); } } else { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Fans are ok on all nodes'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'Fans are ok on all nodes' + ); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$results->{$oid_nodeEnvFailedFanCount}})) { $oid =~ /^$oid_nodeEnvFailedFanCount\.(.*)$/; my $instance = $1; my $name = $results->{$oid_nodeName}->{$oid_nodeName . '.' . $instance}; my $count = $results->{$oid_nodeEnvFailedFanCount}->{$oid}; my $message = $results->{$oid_nodeEnvFailedFanMessage}->{$oid_nodeEnvFailedFanMessage . '.' . $instance}; - $self->{output}->output_add(long_msg => sprintf("'%d' fans are failed on node '%s' [message: %s]", - $count, $name, defined($message) ? $message : '-')); + $self->{output}->output_add( + long_msg => sprintf( + "'%d' fans are failed on node '%s' [message: %s]", + $count, $name, defined($message) ? $message : '-' + ) + ); if ($count != 0) { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("'%d' fans are failed on node '%s' [message: %s]", - $count, $name, defined($message) ? $message : '-')); + $self->{output}->output_add( + severity => 'CRITICAL', + short_msg => sprintf( + "'%d' fans are failed on node '%s' [message: %s]", + $count, $name, defined($message) ? $message : '-' + ) + ); } } } diff --git a/storage/netapp/ontap/snmp/mode/listclusternodes.pm b/storage/netapp/ontap/snmp/mode/listclusternodes.pm new file mode 100644 index 000000000..f726e8180 --- /dev/null +++ b/storage/netapp/ontap/snmp/mode/listclusternodes.pm @@ -0,0 +1,123 @@ +# +# Copyright 2021 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::ontap::snmp::mode::listclusternodes; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my $mapping = { + location => { oid => '.1.3.6.1.4.1.789.1.25.2.1.3' }, # nodeLocation + model => { oid => '.1.3.6.1.4.1.789.1.25.2.1.4' }, # nodeModel + product => { oid => '.1.3.6.1.4.1.789.1.25.2.1.23' }, # nodeProductVersion + firmware => { oid => '.1.3.6.1.4.1.789.1.25.2.1.24' } # nodeFirmwareVersion +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_name = '.1.3.6.1.4.1.789.1.25.2.1.1'; # nodeName + my $snmp_result = $options{snmp}->get_table(oid => $oid_name); + my $results = {}; + foreach (keys %$snmp_result) { + /^$oid_name\.(.*)$/; + + $results->{$1} = { name => $snmp_result->{$_} }; + } + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ map($_, keys(%$results)) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + foreach (keys %$results) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); + + $results->{$_} = { %$result, %{$results->{$_}} }; + } + + return $results; +} + +sub run { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach my $instance (sort keys %$results) { + $self->{output}->output_add(long_msg => + join('', map("[$_ = " . $results->{$instance}->{$_} . ']', ('name', keys(%$mapping)))) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List cluster nodes:' + ); + $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', keys %$mapping]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach (sort keys %$results) { + $self->{output}->add_disco_entry( + %{$results->{$_}} + ); + } +} +1; + +__END__ + +=head1 MODE + +List cluster nodes. + +=over 8 + +=back + +=cut diff --git a/storage/netapp/ontap/snmp/mode/listplexes.pm b/storage/netapp/ontap/snmp/mode/listplexes.pm new file mode 100644 index 000000000..51bf2776b --- /dev/null +++ b/storage/netapp/ontap/snmp/mode/listplexes.pm @@ -0,0 +1,114 @@ +# +# Copyright 2021 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::ontap::snmp::mode::listplexes; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my $map_plex_status = { + 1 => 'offline', 2 => 'resyncing', 3 => 'online' +}; + +my $mapping = { + name => { oid => '.1.3.6.1.4.1.789.1.6.11.1.2' }, # plexName + aggregate => { oid => '.1.3.6.1.4.1.789.1.6.11.1.3' }, # plexVolName + status => { oid => '.1.3.6.1.4.1.789.1.6.11.1.4', map => $map_plex_status } # plexStatus +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_table = '.1.3.6.1.4.1.789.1.6.11'; # plexTable + my $snmp_result = $options{snmp}->get_table(oid => $oid_table, end => $mapping->{status}->{oid}); + my $results = {}; + foreach (keys %$snmp_result) { + next if (! /^$mapping->{name}->{oid}\.(.*)$/); + + $results->{$1} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + } + + return $results; +} + +sub run { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach my $instance (sort keys %$results) { + $self->{output}->output_add(long_msg => + join('', map("[$_: " . $results->{$instance}->{$_} . ']', keys(%$mapping))) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List plexes:' + ); + $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 => [keys %$mapping]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach (sort keys %$results) { + $self->{output}->add_disco_entry( + %{$results->{$_}} + ); + } +} +1; + +__END__ + +=head1 MODE + +List plexes. + +=over 8 + +=back + +=cut diff --git a/storage/netapp/ontap/snmp/mode/plexes.pm b/storage/netapp/ontap/snmp/mode/plexes.pm new file mode 100644 index 000000000..4b8b877e7 --- /dev/null +++ b/storage/netapp/ontap/snmp/mode/plexes.pm @@ -0,0 +1,230 @@ +# +# Copyright 2021 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::ontap::snmp::mode::plexes; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_temp_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => '%', + instances => [$self->{result_values}->{name}, $self->{result_values}->{aggregate}], + value => $self->{result_values}->{resync}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0, max => 100 + ); +} + +sub prefix_plex_output { + my ($self, %options) = @_; + + return sprintf( + "Plex '%s' [aggregate: %s] ", + $options{instance_value}->{name}, + $options{instance_value}->{aggregate} + ); +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Plex '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, + { name => 'plexes', type => 1, cb_prefix_output => 'prefix_plex_output', message_multiple => 'All plexes are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total-online', display_ok => 0, nlabel => 'plexes.online.count', set => { + key_values => [ { name => 'online' } ], + output_template => 'online: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-offline', display_ok => 0, nlabel => 'plexes.offline.count', set => { + key_values => [ { name => 'offline' } ], + output_template => 'offline: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'total-resyncing', display_ok => 0, nlabel => 'plexes.resyncing.count', set => { + key_values => [ { name => 'resyncing' } ], + output_template => 'resyncing: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + ]; + + $self->{maps_counters}->{plexes} = [ + { + label => 'status', + type => 2, + warning_default => '%{status} eq "resyncing"', + critical_default => '%{status} eq "offline"', + set => { + key_values => [ { name => 'status' }, { name => 'aggregate' }, { name => 'name' } ], + output_template => "status: %s", + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'resyncing', nlabel => 'plex.resyncing.percentage', set => { + key_values => [ { name => 'resync' }, { name => 'aggregate' }, { name => 'name' } ], + output_template => 'resyncing: %.2f %%', + closure_custom_perfdata => $self->can('custom_temp_perfdata') + } + } + ]; +} + +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-name:s' => { name => 'filter_name' }, + 'filter-aggregate:s' => { name => 'filter_aggregate' } + }); + + return $self; +} + +my $map_plex_status = { + 1 => 'offline', 2 => 'resyncing', 3 => 'online' +}; + +my $mapping = { + aggregate => { oid => '.1.3.6.1.4.1.789.1.6.11.1.3' }, # plexVolName + status => { oid => '.1.3.6.1.4.1.789.1.6.11.1.4', map => $map_plex_status }, # plexStatus + resync => { oid => '.1.3.6.1.4.1.789.1.6.11.1.5' } # plexPercentResyncing +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_plexName = '.1.3.6.1.4.1.789.1.6.11.1.2'; + + $self->{global} = { offline => 0, resyncing => 0, online => 0 }; + $self->{plexes} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_plexName, nothing_quit => 1); + foreach my $oid (keys %$snmp_result) { + $oid =~ /^$oid_plexName\.(.*)$/; + my $instance = $1; + my $name = $snmp_result->{$oid}; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping plex '" . $name . "'.", debug => 1); + next; + } + + $self->{plexes}->{$instance} = { name => $name }; + } + + if (scalar(keys %{$self->{plexes}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No plex found"); + $self->{output}->option_exit(); + } + + $options{snmp}->load( + oids => [ + map($_->{oid}, values(%$mapping)) + ], + instances => [keys %{$self->{plexes}}], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + + foreach (keys %{$self->{plexes}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $_); + if (defined($self->{option_results}->{filter_aggregate}) && $self->{option_results}->{filter_aggregate} ne '' && + $result->{aggregate} !~ /$self->{option_results}->{filter_aggregate}/) { + $self->{output}->output_add(long_msg => "skipping aggregatge '" . $result->{aggregate} . "'.", debug => 1); + next; + } + + $self->{plexes}->{$_}->{status} = $result->{status}; + $self->{plexes}->{$_}->{aggregate} = $result->{aggregate}; + $self->{plexes}->{$_}->{resync} = $result->{resync} if ($result->{status} eq 'resyncing'); + $self->{global}->{ $result->{status} }++; + } +} + +1; + +__END__ + +=head1 MODE + +Check plexes. + +=over 8 + +=item B<--filter-name> + +Filter plexes by name. + +=item B<--filter-aggregate> + +Filter plexes by aggregate name. + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{status}, %{name}, %{aggregate} + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{status} eq "resyncing"'). +Can used special variables like: %{status}, %{name}, %{aggregate} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} eq "offline"'). +Can used special variables like: %{status}, %{name}, %{aggregate} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'total-online', 'total-offline', 'total-resyncing', 'resyncing'. + +=back + +=cut diff --git a/storage/netapp/ontap/snmp/mode/temperature.pm b/storage/netapp/ontap/snmp/mode/temperature.pm index 953b5640f..9ac2441e4 100644 --- a/storage/netapp/ontap/snmp/mode/temperature.pm +++ b/storage/netapp/ontap/snmp/mode/temperature.pm @@ -57,31 +57,43 @@ sub run { oids => [ { oid => $oid_envOverTemperature }, { oid => $oid_nodeName }, - { oid => $oid_nodeEnvOverTemperature }, + { oid => $oid_nodeEnvOverTemperature } ], nothing_quit => 1 ); if (defined($results->{$oid_envOverTemperature}->{$oid_envOverTemperature . '.0'})) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Hardware temperature is ok.'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'Hardware temperature is ok.' + ); if ($mapping_temperature{$results->{$oid_envOverTemperature}->{$oid_envOverTemperature . '.0'}} eq 'yes') { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => 'Hardware temperature is over temperature range.'); + $self->{output}->output_add( + severity => 'CRITICAL', + short_msg => 'Hardware temperature is over temperature range.' + ); } } else { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Hardware temperature are ok on all nodes'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'Hardware temperature are ok on all nodes' + ); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$results->{$oid_nodeEnvOverTemperature}})) { $oid =~ /^$oid_nodeEnvOverTemperature\.(.*)$/; my $instance = $1; my $name = $results->{$oid_nodeName}->{$oid_nodeName . '.' . $instance}; my $temp = $results->{$oid_nodeEnvOverTemperature}->{$oid}; - $self->{output}->output_add(long_msg => sprintf("hardware temperature on node '%s' is over range: '%s'", - $name, $mapping_temperature{$temp})); + $self->{output}->output_add( + long_msg => sprintf( + "hardware temperature on node '%s' is over range: '%s'", + $name, $mapping_temperature{$temp} + ) + ); if ($mapping_temperature{$temp} eq 'yes') { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("Hardware temperature is over temperature range on node '%s'", $name)); + $self->{output}->output_add( + severity => 'CRITICAL', + short_msg => sprintf("Hardware temperature is over temperature range on node '%s'", $name) + ); } } } diff --git a/storage/netapp/ontap/snmp/plugin.pm b/storage/netapp/ontap/snmp/plugin.pm index b1da9ea17..5336c592b 100644 --- a/storage/netapp/ontap/snmp/plugin.pm +++ b/storage/netapp/ontap/snmp/plugin.pm @@ -30,33 +30,37 @@ sub new { bless $self, $class; $self->{version} = '1.0'; - %{$self->{modes}} = ( - 'aggregatestate' => 'storage::netapp::ontap::snmp::mode::aggregatestate', - 'cache-age' => 'storage::netapp::ontap::snmp::mode::cacheage', - 'cp-statistics' => 'storage::netapp::ontap::snmp::mode::cpstatistics', - 'cpuload' => 'storage::netapp::ontap::snmp::mode::cpuload', - 'diskfailed' => 'storage::netapp::ontap::snmp::mode::diskfailed', - 'failover' => 'storage::netapp::ontap::snmp::mode::failover', - 'fan' => 'storage::netapp::ontap::snmp::mode::fan', - 'filesys' => 'storage::netapp::ontap::snmp::mode::filesys', - 'list-filesys' => 'storage::netapp::ontap::snmp::mode::listfilesys', - 'list-snapvault' => 'storage::netapp::ontap::snmp::mode::listsnapvault', - 'global-status' => 'storage::netapp::ontap::snmp::mode::globalstatus', - 'ndmpsessions' => 'storage::netapp::ontap::snmp::mode::ndmpsessions', - 'nvram' => 'storage::netapp::ontap::snmp::mode::nvram', - 'partnerstatus' => 'storage::netapp::ontap::snmp::mode::partnerstatus', - 'psu' => 'storage::netapp::ontap::snmp::mode::psu', - 'qtree-usage' => 'storage::netapp::ontap::snmp::mode::qtreeusage', - 'share-calls' => 'storage::netapp::ontap::snmp::mode::sharecalls', - 'shelf' => 'storage::netapp::ontap::snmp::mode::shelf', - 'sis' => 'storage::netapp::ontap::snmp::mode::sis', - 'snapmirrorlag' => 'storage::netapp::ontap::snmp::mode::snapmirrorlag', - 'snapshotage' => 'storage::netapp::ontap::snmp::mode::snapshotage', - 'snapvault-usage' => 'storage::netapp::ontap::snmp::mode::snapvaultusage', - 'temperature' => 'storage::netapp::ontap::snmp::mode::temperature', - 'uptime' => 'snmp_standard::mode::uptime', - 'volumeoptions' => 'storage::netapp::ontap::snmp::mode::volumeoptions' - ); + $self->{modes} = { + 'aggregates' => 'storage::netapp::ontap::snmp::mode::aggregates', + 'cache-age' => 'storage::netapp::ontap::snmp::mode::cacheage', + 'cluster-nodes' => 'storage::netapp::ontap::snmp::mode::clusternodes', + 'cp-statistics' => 'storage::netapp::ontap::snmp::mode::cpstatistics', + 'cpuload' => 'storage::netapp::ontap::snmp::mode::cpuload', + 'diskfailed' => 'storage::netapp::ontap::snmp::mode::diskfailed', + 'failover' => 'storage::netapp::ontap::snmp::mode::failover', + 'fan' => 'storage::netapp::ontap::snmp::mode::fan', + 'filesys' => 'storage::netapp::ontap::snmp::mode::filesys', + 'list-cluster-nodes' => 'storage::netapp::ontap::snmp::mode::listclusternodes', + 'list-filesys' => 'storage::netapp::ontap::snmp::mode::listfilesys', + 'list-plexes' => 'storage::netapp::ontap::snmp::mode::listplexes', + 'list-snapvault' => 'storage::netapp::ontap::snmp::mode::listsnapvault', + 'global-status' => 'storage::netapp::ontap::snmp::mode::globalstatus', + 'ndmpsessions' => 'storage::netapp::ontap::snmp::mode::ndmpsessions', + 'nvram' => 'storage::netapp::ontap::snmp::mode::nvram', + 'partnerstatus' => 'storage::netapp::ontap::snmp::mode::partnerstatus', + 'plexes' => 'storage::netapp::ontap::snmp::mode::plexes', + 'psu' => 'storage::netapp::ontap::snmp::mode::psu', + 'qtree-usage' => 'storage::netapp::ontap::snmp::mode::qtreeusage', + 'share-calls' => 'storage::netapp::ontap::snmp::mode::sharecalls', + 'shelf' => 'storage::netapp::ontap::snmp::mode::shelf', + 'sis' => 'storage::netapp::ontap::snmp::mode::sis', + 'snapmirrorlag' => 'storage::netapp::ontap::snmp::mode::snapmirrorlag', + 'snapshotage' => 'storage::netapp::ontap::snmp::mode::snapshotage', + 'snapvault-usage' => 'storage::netapp::ontap::snmp::mode::snapvaultusage', + 'temperature' => 'storage::netapp::ontap::snmp::mode::temperature', + 'uptime' => 'snmp_standard::mode::uptime', + 'volumeoptions' => 'storage::netapp::ontap::snmp::mode::volumeoptions' + }; return $self; }