From 190f003b0002218d2751256eecf6a4ac662129e2 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 13 Dec 2022 11:25:23 +0000 Subject: [PATCH] (plugin) storage::hitachi::hnas::snmp - add mode virtual-volumes-quotas + metric v2 (#4065) --- .../common/bluearc/snmp/mode/clusterstatus.pm | 83 ++- .../bluearc/snmp/mode/components/battery.pm | 28 +- .../bluearc/snmp/mode/components/fan.pm | 42 +- .../bluearc/snmp/mode/components/psu.pm | 30 +- .../bluearc/snmp/mode/components/sysdrive.pm | 29 +- .../snmp/mode/components/temperature.pm | 40 +- .../common/bluearc/snmp/mode/hardware.pm | 23 +- .../common/bluearc/snmp/mode/interfaces.pm | 194 +++++++ .../bluearc/snmp/mode/listinterfaces.pm | 108 ++++ .../common/bluearc/snmp/mode/listvolumes.pm | 126 +++++ .../bluearc/snmp/mode/virtualvolumesquotas.pm | 477 ++++++++++++++++++ .../common/bluearc/snmp/mode/volumeusage.pm | 110 ++-- .../storage/hitachi/hnas/snmp/plugin.pm | 17 +- 13 files changed, 1115 insertions(+), 192 deletions(-) create mode 100644 centreon-plugins/centreon/common/bluearc/snmp/mode/interfaces.pm create mode 100644 centreon-plugins/centreon/common/bluearc/snmp/mode/listinterfaces.pm create mode 100644 centreon-plugins/centreon/common/bluearc/snmp/mode/listvolumes.pm create mode 100644 centreon-plugins/centreon/common/bluearc/snmp/mode/virtualvolumesquotas.pm diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/clusterstatus.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/clusterstatus.pm index cffe2517f..f1a3d748b 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/clusterstatus.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/clusterstatus.pm @@ -24,7 +24,19 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_status_output { + my ($self, %options) = @_; + + return 'state : ' . $self->{result_values}->{state}; +} + +sub prefix_node_output { + my ($self, %options) = @_; + + return "Node '" . $options{instance_value}->{display} . "' "; +} sub set_counters { my ($self, %options) = @_; @@ -34,70 +46,42 @@ sub set_counters { ]; $self->{maps_counters}->{node} = [ - { label => 'status', threshold => 0, set => { + { + label => 'status', + type => 2, + unknown_default => '%{state} =~ /unknown/', + critical_default => '%{state} =~ /offline/i', + set => { key_values => [ { name => 'state' }, { 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 => \&catalog_status_threshold, + closure_custom_threshold_check => \&catalog_status_threshold_ng } - }, + } ]; } -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} . '_state'}; - $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; - return 0; -} - -sub prefix_node_output { - my ($self, %options) = @_; - - return "Node '" . $options{instance_value}->{display} . "' "; -} - 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' }, - "unknown-status:s" => { name => 'unknown_status', default => '%{state} =~ /unknown/' }, - "warning-status:s" => { name => 'warning_status', default => '' }, - "critical-status:s" => { name => 'critical_status', default => '%{state} =~ /offline/i' }, - }); + $options{options}->add_options(arguments => { + 'filter-name:s' => { name => 'filter_name' } + }); return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::check_options(%options); - - $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); -} - my %map_vnode_status = ( 1 => 'unknown', 2 => 'onLine', - 3 => 'offLine', + 3 => 'offLine' ); my $mapping = { clusterVNodeName => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1.2' }, - clusterVNodeStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1.4', map => \%map_vnode_status }, + clusterVNodeStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1.4', map => \%map_vnode_status } }; my $oid_clusterVNodeEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.5.11.1'; @@ -105,8 +89,7 @@ sub manage_selection { my ($self, %options) = @_; $self->{node} = {}; - $self->{results} = $options{snmp}->get_table(oid => $oid_clusterVNodeEntry, - nothing_quit => 1); + $self->{results} = $options{snmp}->get_table(oid => $oid_clusterVNodeEntry, nothing_quit => 1); foreach my $oid (keys %{$self->{results}}) { next if ($oid !~ /^$mapping->{clusterVNodeStatus}->{oid}\.(.*)$/); my $instance = $1; @@ -117,13 +100,17 @@ sub manage_selection { next; } - $self->{node}->{$instance} = { display => $result->{clusterVNodeName}, - state => $result->{clusterVNodeStatus}}; + $self->{node}->{$instance} = { + display => $result->{clusterVNodeName}, + state => $result->{clusterVNodeStatus} + }; } if (scalar(keys %{$self->{node}}) <= 0) { - $self->{output}->output_add(severity => 'OK', - short_msg => 'No node(s) found'); + $self->{output}->output_add( + severity => 'OK', + short_msg => 'No node(s) found' + ); } } diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/battery.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/battery.pm index 38f36f0b3..622fd421e 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/battery.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/battery.pm @@ -38,7 +38,7 @@ my %map_status = ( ); my $mapping = { - batteryStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.17.1.3', map => \%map_status }, + batteryStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.17.1.3', map => \%map_status } }; my $oid_batteryEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.17.1'; @@ -56,22 +56,30 @@ sub check { return if ($self->check_filter(section => 'battery')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_batteryEntry}})) { - next if ($oid !~ /^$mapping->{batteryStatus}->{oid}\.(.*)$/); - my $instance = $1; + next if ($oid !~ /^$mapping->{batteryStatus}->{oid}\.(.*)\.(.*)$/); + my $name = $self->{pnodes}->{$1} . '.' . $2; + my $instance = $1 . '.' . $2; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_batteryEntry}, instance => $instance); next if ($self->check_filter(section => 'battery', instance => $instance)); $self->{components}->{battery}->{total}++; - $self->{output}->output_add(long_msg => sprintf("Battery '%s' status is '%s' [instance: %s].", - $instance, $result->{batteryStatus}, - $instance - )); + $self->{output}->output_add( + long_msg => sprintf( + "battery '%s' status is '%s' [instance: %s].", + $name, $result->{batteryStatus}, + $instance + ) + ); my $exit = $self->get_severity(section => 'battery', value => $result->{batteryStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Battery '%s' status is '%s'", - $instance, $result->{batteryStatus})); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Battery '%s' status is '%s'", + $name, $result->{batteryStatus} + ) + ); } } } diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/fan.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/fan.pm index 6766204c6..33f2460a8 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/fan.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/fan.pm @@ -27,12 +27,12 @@ my %map_speed_status = ( 1 => 'ok', 2 => 'warning', 3 => 'severe', - 4 => 'unknown', + 4 => 'unknown' ); my $mapping = { fanSpeedStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1.4', map => \%map_speed_status }, - fanSpeed => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1.5' }, + fanSpeed => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1.5' } }; my $oid_fanEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.11.1'; @@ -50,35 +50,43 @@ sub check { return if ($self->check_filter(section => 'fan')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fanEntry}})) { - next if ($oid !~ /^$mapping->{fanSpeedStatus}->{oid}\.(.*)$/); - my $instance = $1; + next if ($oid !~ /^$mapping->{fanSpeedStatus}->{oid}\.(.*)\.(.*)$/); + my $name = $self->{pnodes}->{$1} . '.' . $2; + my $instance = $1 . '.' . $2; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fanEntry}, instance => $instance); next if ($self->check_filter(section => 'fan', instance => $instance)); $self->{components}->{fan}->{total}++; - $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s] [value = %s]", - $instance, $result->{fanSpeedStatus}, $instance, - $result->{fanSpeedStatus})); - + $self->{output}->output_add( + long_msg => sprintf( + "fan '%s' status is '%s' [instance: %s] [value: %s]", + $name, $result->{fanSpeedStatus}, $instance, + $result->{fanSpeedStatus} + ) + ); + my $exit = $self->get_severity(section => 'fan.speed', value => $result->{fanSpeedStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{fanSpeedStatus})); - next; + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Fan '%s' status is '%s'", $name, $result->{fanSpeedStatus}) + ); } - + if (defined($result->{fanSpeedStatus}) && $result->{fanSpeedStatus} =~ /[0-9]/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{temperatureSensorCReading}); - + if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit2, - short_msg => sprintf("Fan '%s' is %s rpm", $instance, $result->{fanSpeedStatus})); + $self->{output}->output_add( + severity => $exit2, + short_msg => sprintf("Fan '%s' is %s rpm", $name, $result->{fanSpeedStatus}) + ); } $self->{output}->perfdata_add( - label => 'fan', unit => 'rpm', nlabel => 'hardware.fan.speed.rpm', - instances => $instance, + unit => 'rpm', + instances => $name, value => $result->{fanSpeedStatus}, warning => $warn, critical => $crit, diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/psu.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/psu.pm index 51be38265..4342ac3be 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/psu.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/psu.pm @@ -27,7 +27,7 @@ my %map_status = ( 1 => 'ok', 2 => 'failed', 3 => 'notFitted', - 4 => 'unknown', + 4 => 'unknown' ); my $mapping = { @@ -49,24 +49,32 @@ sub check { return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_psuEntry}})) { - next if ($oid !~ /^$mapping->{psuStatus}->{oid}\.(.*)$/); - my $instance = $1; + next if ($oid !~ /^$mapping->{psuStatus}->{oid}\.(.*)\.(.*)$/); + my $name = $self->{pnodes}->{$1} . '.' . $2; + my $instance = $1 . '.' . $2; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_psuEntry}, instance => $instance); next if ($self->check_filter(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; - $self->{output}->output_add(long_msg => sprintf("power supply '%s' status is '%s' [instance: %s].", - $instance, $result->{psuStatus}, - $instance - )); + $self->{output}->output_add( + long_msg => sprintf( + "power supply '%s' status is '%s' [instance: %s].", + $name, $result->{psuStatus}, + $instance + ) + ); my $exit = $self->get_severity(section => 'psu', value => $result->{psuStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Power supply '%s' status is '%s'", - $instance, $result->{psuStatus})); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Power supply '%s' status is '%s'", + $name, $result->{psuStatus} + ) + ); } } } -1; \ No newline at end of file +1; diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/sysdrive.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/sysdrive.pm index 22afd6d30..a867375d1 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/sysdrive.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/sysdrive.pm @@ -27,18 +27,18 @@ my %map_status = ( 1 => 'online', 2 => 'corrupt', 3 => 'failed', 4 => 'notPresent', 5 => 'disconnected', 6 => 'offline', 7 => 'initializing', - 8 => 'formatting', 9 => 'unknown', + 8 => 'formatting', 9 => 'unknown' ); my $mapping = { sysDriveWWN => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1.2' }, - sysDriveStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1.4', map => \%map_status }, + sysDriveStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1.4', map => \%map_status } }; my $oid_sysDriveEntry = '.1.3.6.1.4.1.11096.6.1.1.1.3.4.2.1'; sub load { my ($self) = @_; - + push @{$self->{request}}, { oid => $oid_sysDriveEntry }; } @@ -57,17 +57,24 @@ sub check { next if ($self->check_filter(section => 'sysdrive', instance => $result->{sysDriveWWN})); $self->{components}->{sysdrive}->{total}++; - $self->{output}->output_add(long_msg => sprintf("system drive '%s' status is '%s' [instance: %s].", - $result->{sysDriveWWN}, $result->{sysDriveStatus}, - $result->{sysDriveWWN} - )); + $self->{output}->output_add( + long_msg => sprintf( + "system drive '%s' status is '%s' [instance: %s].", + $result->{sysDriveWWN}, $result->{sysDriveStatus}, + $result->{sysDriveWWN} + ) + ); my $exit = $self->get_severity(section => 'sysdrive', value => $result->{sysDriveStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("System drive '%s' status is '%s'", - $result->{sysDriveWWN}, $result->{sysDriveStatus})); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "System drive '%s' status is '%s'", + $result->{sysDriveWWN}, $result->{sysDriveStatus} + ) + ); } } } -1; \ No newline at end of file +1; diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/temperature.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/temperature.pm index 48edd45a1..93b9f7ba3 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/components/temperature.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/components/temperature.pm @@ -26,12 +26,12 @@ use warnings; my %map_status = ( 1 => 'ok', 2 => 'tempWarning', 3 => 'tempSevere', 4 => 'tempSensorFailed', 5 => 'tempSensorWarning', - 6 => 'unknown', + 6 => 'unknown' ); my $mapping = { temperatureSensorStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1.3', map => \%map_status }, - temperatureSensorCReading => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1.4' }, + temperatureSensorCReading => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1.4' } }; my $oid_temperatureSensorEntry = '.1.3.6.1.4.1.11096.6.1.1.1.2.1.9.1'; @@ -49,38 +49,46 @@ sub check { return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureSensorEntry}})) { - next if ($oid !~ /^$mapping->{temperatureSensorStatus}->{oid}\.(.*)$/); - my $instance = $1; + next if ($oid !~ /^$mapping->{temperatureSensorStatus}->{oid}\.(.*)\.(.*)$/); + my $name = $self->{pnodes}->{$1} . '.' . $2; + my $instance = $1 . '.' . $2; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureSensorEntry}, instance => $instance); next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; - $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", - $instance, $result->{temperatureSensorStatus}, $instance, - $result->{temperatureSensorCReading})); - + $self->{output}->output_add( + long_msg => sprintf( + "temperature '%s' status is '%s' [instance: %s] [value: %s]", + $name, $result->{temperatureSensorStatus}, $instance, + $result->{temperatureSensorCReading} + ) + ); + my $exit = $self->get_severity(section => 'temperature', value => $result->{temperatureSensorStatus}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{temperatureSensorStatus})); - next; + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Temperature '%s' status is '%s'", $name, $result->{temperatureSensorStatus}) + ); } if (defined($result->{temperatureSensorCReading}) && $result->{temperatureSensorCReading} =~ /[0-9]/) { my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperatureSensorCReading}); if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit2, - short_msg => sprintf("Temperature '%s' is %s degree centigrade", $instance, $result->{temperatureSensorCReading})); + $self->{output}->output_add( + severity => $exit2, + short_msg => sprintf("Temperature '%s' is %s degree centigrade", $name, $result->{temperatureSensorCReading}) + ); } $self->{output}->perfdata_add( - label => 'temp', unit => 'C', nlabel => 'hardware.temperature.celsius', - instances => $instance, + unit => 'C', + instances => $name, value => $result->{temperatureSensorCReading}, warning => $warn, - critical => $crit, + critical => $crit ); } } diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/hardware.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/hardware.pm index 19c0d619a..edfea8392 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/hardware.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/hardware.pm @@ -37,13 +37,13 @@ sub set_system { ['ok', 'OK'], ['failed', 'CRITICAL'], ['notFitted', 'WARNING'], - ['unknown', 'UNKNOWN'], + ['unknown', 'UNKNOWN'] ], 'fan.speed' => [ ['ok', 'OK'], ['warning', 'WARNING'], ['severe', 'CRITICAL'], - ['unknown', 'UNKNOWN'], + ['unknown', 'UNKNOWN'] ], temperature => [ ['ok', 'OK'], @@ -51,7 +51,7 @@ sub set_system { ['tempSevere', 'CRITICAL'], ['tempSensorFailed', 'CRITICAL'], ['tempSensorWarning', 'CRITICAL'], - ['unknown', 'UNKNOWN'], + ['unknown', 'UNKNOWN'] ], sysdrive => [ ['online', 'OK'], @@ -62,7 +62,7 @@ sub set_system { ['offline', 'OK'], ['initializing', 'OK'], ['formatting', 'OK'], - ['unknown', 'UNKNOWN'], + ['unknown', 'UNKNOWN'] ], battery => [ ['ok', 'OK'], @@ -75,8 +75,8 @@ sub set_system { ['notResponding', 'CRITICAL'], ['low', 'WARNING'], ['veryLow', 'CRITICAL'], - ['ignore', 'UNKNOWN'], - ], + ['ignore', 'UNKNOWN'] + ] }; $self->{components_path} = 'centreon::common::bluearc::snmp::mode::components'; @@ -86,13 +86,22 @@ sub set_system { sub snmp_execute { my ($self, %options) = @_; + my $oid_clusterPNodeName = '.1.3.6.1.4.1.11096.6.1.1.1.2.5.9.1.2'; + push @{$self->{request}}, { oid => $oid_clusterPNodeName }; + $self->{snmp} = $options{snmp}; $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); + + $self->{pnodes} = {}; + foreach (keys %{$self->{results}->{$oid_clusterPNodeName}}) { + /^$oid_clusterPNodeName\.(.*)$/; + $self->{pnodes}->{$1} = $self->{results}->{$oid_clusterPNodeName}->{$_}; + } } sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/interfaces.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/interfaces.pm new file mode 100644 index 000000000..6c3e627d8 --- /dev/null +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/interfaces.pm @@ -0,0 +1,194 @@ +# +# Copyright 2022 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 centreon::common::bluearc::snmp::mode::interfaces; + +use base qw(snmp_standard::mode::interfaces); + +use strict; +use warnings; + +sub default_oid_filter_name { + my ($self, %options) = @_; + + return 'ifdesc'; +} + +sub default_oid_display_name { + my ($self, %options) = @_; + + return 'ifdesc'; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check interfaces. + +=over 8 + +=item B<--add-global> + +Check global port statistics (By default if no --add-* option is set). + +=item B<--add-status> + +Check interface status. + +=item B<--add-duplex-status> + +Check duplex status (with --warning-status and --critical-status). + +=item B<--add-traffic> + +Check interface traffic. + +=item B<--add-errors> + +Check interface errors. + +=item B<--add-cast> + +Check interface cast. + +=item B<--add-speed> + +Check interface speed. + +=item B<--add-volume> + +Check interface data volume between two checks (not supposed to be graphed, useful for BI reporting). + +=item B<--check-metrics> + +If the expression is true, metrics are checked (Default: '%{opstatus} eq "up"'). + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{admstatus}, %{opstatus}, %{duplexstatus}, %{display} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{admstatus} eq "up" and %{opstatus} ne "up"'). +Can used special variables like: %{admstatus}, %{opstatus}, %{duplexstatus}, %{display} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'total-port', 'total-admin-up', 'total-admin-down', 'total-oper-up', 'total-oper-down', +'in-traffic', 'out-traffic', 'in-error', 'in-discard', 'out-error', 'out-discard', +'in-ucast', 'in-bcast', 'in-mcast', 'out-ucast', 'out-bcast', 'out-mcast', +'speed' (b/s). + +=item B<--units-traffic> + +Units of thresholds for the traffic (Default: 'percent_delta') ('percent_delta', 'bps', 'counter'). + +=item B<--units-errors> + +Units of thresholds for errors/discards (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', 'counter'). + +=item B<--units-cast> + +Units of thresholds for communication types (Default: 'percent_delta') ('percent_delta', 'percent', 'delta', 'counter'). + +=item B<--nagvis-perfdata> + +Display traffic perfdata to be compatible with nagvis widget. + +=item B<--interface> + +Set the interface (number expected) ex: 1,2,... (empty means 'check all interface'). + +=item B<--name> + +Allows to use interface name with option --interface instead of interface oid index (Can be a regexp) + +=item B<--speed> + +Set interface speed for incoming/outgoing traffic (in Mb). + +=item B<--speed-in> + +Set interface speed for incoming traffic (in Mb). + +=item B<--speed-out> + +Set interface speed for outgoing traffic (in Mb). + +=item B<--map-speed-dsl> + +Get interface speed configuration for interface type 'adsl' and 'vdsl2'. + +Syntax: --map-speed-dsl=interface-src-name,interface-dsl-name + +E.g: --map-speed-dsl=Et0.835,Et0-vdsl2 + +=item B<--force-counters64> + +Force to use 64 bits counters only. Can be used to improve performance. + +=item B<--force-counters32> + +Force to use 32 bits counters (even in snmp v2c and v3). Should be used when 64 bits counters are buggy. + +=item B<--reload-cache-time> + +Time in minutes before reloading cache file (default: 180). + +=item B<--oid-filter> + +Choose OID used to filter interface (default: ifDesc) (values: ifDesc, ifAlias, ifName, IpAddr). + +=item B<--oid-display> + +Choose OID used to display interface (default: ifDesc) (values: ifDesc, ifAlias, ifName, IpAddr). + +=item B<--oid-extra-display> + +Add an OID to display. + +=item B<--display-transform-src> + +Regexp src to transform display value. + +=item B<--display-transform-dst> + +Regexp dst to transform display value. + +=item B<--show-cache> + +Display cache interface datas. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/listinterfaces.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/listinterfaces.pm new file mode 100644 index 000000000..2b970be9f --- /dev/null +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/listinterfaces.pm @@ -0,0 +1,108 @@ +# +# Copyright 2022 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 centreon::common::bluearc::snmp::mode::listinterfaces; + +use base qw(snmp_standard::mode::listinterfaces); + +use strict; +use warnings; + +sub default_oid_filter_name { + my ($self, %options) = @_; + + return 'ifdesc'; +} + +sub default_oid_display_name { + my ($self, %options) = @_; + + return 'ifdesc'; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + return $self; +} + +1; + +__END__ + +=head1 MODE + +=over 8 + +=item B<--interface> + +Set the interface (number expected) ex: 1,2,... (empty means 'check all interface'). + +=item B<--name> + +Allows to use interface name with option --interface instead of interface oid index (Can be a regexp) + +=item B<--speed> + +Set interface speed (in Mb). + +=item B<--skip-speed0> + +Don't display interface with speed 0. + +=item B<--filter-status> + +Display interfaces matching the filter (example: 'up'). + +=item B<--use-adminstatus> + +Display interfaces with AdminStatus 'up'. + +=item B<--oid-filter> + +Choose OID used to filter interface (default: ifDesc) (values: ifDesc, ifAlias, ifName). + +=item B<--oid-display> + +Choose OID used to display interface (default: ifDesc) (values: ifDesc, ifAlias, ifName). + +=item B<--display-transform-src> + +Regexp src to transform display value. (security risk!!!) + +=item B<--display-transform-dst> + +Regexp dst to transform display value. (security risk!!!) + +=item B<--add-extra-oid> + +Display an OID. +Example: --add-extra-oid='alias,.1.3.6.1.2.1.31.1.1.1.18' +or --add-extra-oid='vlan,.1.3.6.1.2.1.31.19,%{instance}\..*' + +=item B<--add-mac-address> + +Display interface mac address. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/listvolumes.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/listvolumes.pm new file mode 100644 index 000000000..164e86af6 --- /dev/null +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/listvolumes.pm @@ -0,0 +1,126 @@ +# +# Copyright 2022 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 centreon::common::bluearc::snmp::mode::listvolumes; + +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_volume_status = { + 1 => 'unformatted', + 2 => 'mounted', + 3 => 'formatted', + 4 => 'needsChecking' +}; +my $mapping = { + label => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.3' }, # volumeLabel + status => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.4', map => $map_volume_status } # volumeStatus +}; +my $oid_volumeEntry = '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1'; + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_table( + oid => $oid_volumeEntry, + start => $mapping->{label}->{oid}, + end => $mapping->{status}->{oid} + ); + + my $volumes = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$mapping->{label}->{oid}\.(.*)$/); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $volumes->{$1} = $result; + } + + return $volumes; +} + +sub run { + my ($self, %options) = @_; + + my $volumes = $self->manage_selection(%options); + foreach (sort keys %$volumes) { + $self->{output}->output_add( + long_msg => sprintf( + '[label: %s] [status: %s]', + $volumes->{$_}->{label}, + $volumes->{$_}->{status} + ) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List volumes:' + ); + $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 $volumes = $self->manage_selection(%options); + foreach (sort keys %$volumes) { + $self->{output}->add_disco_entry( + %{$volumes->{$_}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List volumes. + +=over 8 + +=back + +=cut diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/virtualvolumesquotas.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/virtualvolumesquotas.pm new file mode 100644 index 000000000..945b334d2 --- /dev/null +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/virtualvolumesquotas.pm @@ -0,0 +1,477 @@ +# +# Copyright 2022 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 centreon::common::bluearc::snmp::mode::virtualvolumesquotas; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($usage_value, $usage_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{usage}); + + my $msg; + if ($self->{result_values}->{usageLimit} > 0) { + my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{usageLimit}); + my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{usageLimit} - $self->{result_values}->{usage}); + my $usagePrct = $self->{result_values}->{usage} * 100 / $self->{result_values}->{usageLimit}; + $msg = sprintf( + 'usage total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)', + $total_value, $total_unit, + $usage_value, $usage_unit, + $usagePrct, + $free_value, $free_unit, + 100 - $usagePrct + ); + } else { + $msg = sprintf( + 'usage: %s %s', + $usage_value, $usage_unit + ); + } + + return $msg; +} + +sub custom_files_output { + my ($self, %options) = @_; + + my $msg; + if ($self->{result_values}->{fileCountLimit} > 0) { + my $usagePrct = $self->{result_values}->{fileCount} * 100 / $self->{result_values}->{fileCountLimit}; + $msg = sprintf( + 'files total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $self->{result_values}->{fileCountLimit}, + $self->{result_values}->{fileCount}, + $usagePrct, + $self->{result_values}->{fileCountLimit} - $self->{result_values}->{fileCount}, + 100 - $usagePrct + ); + } else { + $msg = sprintf( + 'files: %s', + $self->{result_values}->{fileCount} + ); + } + + return $msg; +} + +sub custom_files_calc { + my ($self, %options) = @_; + + return -10 if ($options{new_datas}->{$self->{instance} . '_fileCountLimit'} <= 0); + + $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; + $self->{result_values}->{fsLabel} = $options{new_datas}->{$self->{instance} . '_fsLabel'}; + $self->{result_values}->{target} = $options{new_datas}->{$self->{instance} . '_target'}; + + $self->{result_values}->{fileCountLimit} = $options{new_datas}->{$self->{instance} . '_fileCountLimit'}; + $self->{result_values}->{fileCount} = $options{new_datas}->{$self->{instance} . '_fileCount'}; + $self->{result_values}->{fileFreeCount} = $self->{result_values}->{fileCountLimit} - $self->{result_values}->{fileCount}; + $self->{result_values}->{filePrct} = $self->{result_values}->{fileCount} * 100 / $self->{result_values}->{fileCountLimit}; + + return 0; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + return -10 if ($options{new_datas}->{$self->{instance} . '_usageLimit'} <= 0); + + $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; + $self->{result_values}->{fsLabel} = $options{new_datas}->{$self->{instance} . '_fsLabel'}; + $self->{result_values}->{target} = $options{new_datas}->{$self->{instance} . '_target'}; + + $self->{result_values}->{usageLimit} = $options{new_datas}->{$self->{instance} . '_usageLimit'}; + $self->{result_values}->{usage} = $options{new_datas}->{$self->{instance} . '_usage'}; + $self->{result_values}->{free} = $self->{result_values}->{usageLimit} - $self->{result_values}->{usage}; + $self->{result_values}->{usagePrct} = $self->{result_values}->{usage} * 100 / $self->{result_values}->{usageLimit}; + + return 0; +} + +sub prefix_vvq_output { + my ($self, %options) = @_; + + return sprintf( + "virtual volume '%s' [fs: %s] [target: %s] quota ", + $options{instance_value}->{name}, + $options{instance_value}->{fsLabel}, + $options{instance_value}->{target} + ); +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Virtual volumes quotas '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', }, + { name => 'vvq', type => 1, cb_prefix_output => 'prefix_vvq_output', message_multiple => 'All virtual volumes quotas are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'vvq-detected', display_ok => 0, nlabel => 'virtual_volumes.quotas.detected.count', set => { + key_values => [ { name => 'detected' } ], + output_template => 'detected: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + ]; + + $self->{maps_counters}->{vvq} = [ + { label => 'vvq-usage', nlabel => 'virtual_volume.quota.usage.bytes', set => { + key_values => [ + { name => 'usage' }, { name => 'usageLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{usage}, threshold => [ { label => 'critical-' . $self->{thlabel} . '-' . $self->{instance}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel} . '-' . $self->{instance}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => 'B', + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{usage}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel} . '-' . $self->{instance}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel} . '-' . $self->{instance}), + min => 0 + ); + } + } + }, + { label => 'vvq-usage-free', nlabel => 'virtual_volume.quota.free.bytes', display_ok => 0, set => { + key_values => [ + { name => 'usage' }, { name => 'usageLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{free}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => 'B', + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{free}, + 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 => $self->{result_values}->{usageLimit} + ); + } + } + }, + { label => 'vvq-usage-prct', nlabel => 'virtual_volume.quota.usage.percentage', display_ok => 0, set => { + key_values => [ + { name => 'usage' }, { name => 'usageLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{usagePrct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => '%', + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{usagePrct}, + 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 + ); + } + } + }, + { label => 'vvq-files', nlabel => 'virtual_volume.quota.files.count', set => { + key_values => [ + { name => 'fileCount' }, { name => 'fileCountLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_output => $self->can('custom_files_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{fileCount}, threshold => [ { label => 'critical-' . $self->{thlabel} . '-' . $self->{instance}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel} . '-' . $self->{instance}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{fileCount}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel} . '-' . $self->{instance}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel} . '-' . $self->{instance}), + min => 0 + ); + } + } + }, + { label => 'vvq-files-free', nlabel => 'virtual_volume.quota.files.free.count', set => { + key_values => [ + { name => 'fileCount' }, { name => 'fileCountLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_calc => $self->can('custom_files_calc'), + closure_custom_output => $self->can('custom_files_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{fileFreeCount}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{fileFreeCount}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0 + ); + } + } + }, + { label => 'vvq-files-prct', nlabel => 'virtual_volume.quota.files.percentage', set => { + key_values => [ + { name => 'fileCount' }, { name => 'fileCountLimit' }, + { name => 'name' }, { name => 'fsLabel' }, { name => 'target' } + ], + closure_custom_calc => $self->can('custom_files_calc'), + closure_custom_output => $self->can('custom_files_output'), + closure_custom_threshold_check => sub { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check(value => $self->{result_values}->{filePrct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]); + }, + closure_custom_perfdata => sub { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + unit => '%', + instances => [$self->{result_values}->{name}, $self->{result_values}->{fsLabel}, $self->{result_values}->{target}], + value => $self->{result_values}->{filePrct}, + 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 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-filesystem-label:s' => { name => 'filter_filesystem_label' }, + 'filter-volume-name:s' => { name => 'filter_volume_name' }, + 'filter-target:s' => { name => 'filter_target' } + }); + + return $self; +} + +my $mapping_vvq = { + target => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.1' }, # virtualVolumeTitanQuotasTarget + targetType => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.3' } # virtualVolumeTitanQuotasTargetType +}; +my $mapping_stats = { + usage => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.4' }, # virtualVolumeTitanQuotasUsage + fileCount => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.5' }, # virtualVolumeTitanQuotasFileCount + usageLimit => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.6' }, # virtualVolumeTitanQuotasUsageLimit + usageWarn => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.9' }, # virtualVolumeTitanQuotasUsageWarning + usageCrit => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.10' }, # virtualVolumeTitanQuotasUsageCritical + fileCountLimit => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.11' }, # virtualVolumeTitanQuotasFileCountLimit + fileCountWarn => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.14' }, # virtualVolumeTitanQuotasFileCountWarning + fileCountCrit => { oid => '.1.3.6.1.4.1.11096.6.2.1.2.1.7.1.15' } # virtualVolumeTitanQuotasFileCountCritical +}; + +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 $oid_fsLabel = '.1.3.6.1.4.1.11096.6.1.1.6.3.2.1.2'; # fsStatsFsLabel + my $oid_vvName = '.1.3.6.1.4.1.11096.6.2.1.2.1.2.1.2'; # virtualVolumeTitanName + my $oid_vvqTable = '.1.3.6.1.4.1.11096.6.2.1.2.1.7'; # virtualVolumeTitanQuotasTable + my $snmp_result = $options{snmp}->get_multiple_table( + oids => [ + { oid => $oid_fsLabel }, + { oid => $oid_vvqTable, start => $mapping_vvq->{target}->{oid}, end => $mapping_vvq->{targetType}->{oid} } + ], + nothing_quit => 1 + ); + + $self->{global} = { detected => 0 }; + $self->{vvq} = {}; + foreach my $oid (keys %{$snmp_result->{$oid_vvqTable}}) { + next if ($oid !~ /^$mapping_vvq->{target}->{oid}\.(.*)$/); + my $instance = $1; + + my $instanceTarget = ''; + $instanceTarget = '.' . join('.', map(ord($_), split(//, $snmp_result->{$oid_vvqTable}->{$oid}))) + if ($snmp_result->{$oid_vvqTable}->{$oid} ne ''); + $oid =~ /^$mapping_vvq->{target}->{oid}\.(\d+)\.(.*?)$instanceTarget\.\d+$/; + my $spanId = $1; + my @indexes = split(/\./, $2); + + my $fsLabel = $snmp_result->{$oid_fsLabel}->{$oid_fsLabel . '.' . $spanId}; + my $name = $self->{output}->decode(join('', map(chr($_), @indexes))); + + my $result = $options{snmp}->map_instance(mapping => $mapping_vvq, results => $snmp_result->{$oid_vvqTable}, instance => $instance); + my $target = 'virtualVolume'; + if ($result->{targetType} == 1) { + $target = 'user:' . $result->{target}; + } elsif ($result->{targetType} == 2) { + $target = 'group:' . $result->{target}; + } + + next if (defined($self->{option_results}->{filter_filesystem_label}) && $self->{option_results}->{filter_filesystem_label} ne '' && + $fsLabel !~ /$self->{option_results}->{filter_filesystem_label}/); + next if (defined($self->{option_results}->{filter_volume_name}) && $self->{option_results}->{filter_volume_name} ne '' && + $name !~ /$self->{option_results}->{filter_volume_name}/); + next if (defined($self->{option_results}->{filter_target}) && $self->{option_results}->{filter_target} ne '' && + $target !~ /$self->{option_results}->{filter_target}/); + + $self->{vvq}->{$instance} = { + fsLabel => $fsLabel, + target => $target, + name => $name + }; + } + + return if (scalar(keys %{$self->{vvq}}) <= 0); + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping_stats)) ], + instances => [ map($_, keys %{$self->{vvq}}) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + + foreach (keys %{$self->{vvq}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping_stats, results => $snmp_result, instance => $_); + + $self->{vvq}->{$_}->{usage} = $result->{usage}; + $self->{vvq}->{$_}->{usageLimit} = $result->{usageLimit}; + $self->{vvq}->{$_}->{fileCount} = $result->{fileCount}; + $self->{vvq}->{$_}->{fileCountLimit} = $result->{fileCountLimit}; + $self->{global}->{detected}++; + + if (defined($self->{option_results}->{'warning-instance-virtual_volume-quota-usage-bytes'}) && $self->{option_results}->{'warning-instance-virtual_volume-quota-usage-bytes'} ne '') { + $self->{perfdata}->threshold_validate(label => 'warning-instance-virtual_volume-quota-usage-bytes-' . $_, value => $self->{option_results}->{'warning-instance-virtual_volume-quota-usage-bytes'}); + } elsif (defined($result->{usageWarn}) && $result->{usageWarn} > 0) { + $self->{perfdata}->threshold_validate(label => 'warning-instance-virtual_volume-quota-usage-bytes-' . $_, value => $result->{usageWarn}); + } + + if (defined($self->{option_results}->{'critical-instance-virtual_volume-quota-usage-bytes'}) && $self->{option_results}->{'critical-instance-virtual_volume-quota-usage-bytes'} ne '') { + $self->{perfdata}->threshold_validate(label => 'critical-instance-virtual_volume-quota-usage-bytes-' . $_, value => $self->{option_results}->{'critical-instance-virtual_volume-quota-usage-bytes'}); + } elsif (defined($result->{usageCrit}) && $result->{usageCrit} > 0) { + $self->{perfdata}->threshold_validate(label => 'critical-instance-virtual_volume-quota-usage-bytes-' . $_, value => $result->{usageCrit}); + } + + if (defined($self->{option_results}->{'warning-instance-virtual_volume-quota-files-count'}) && $self->{option_results}->{'warning-instance-virtual_volume-quota-files-count'} ne '') { + $self->{perfdata}->threshold_validate(label => 'warning-instance-virtual_volume-quota-files-count-' . $_, value => $self->{option_results}->{'warning-instance-virtual_volume-quota-files-count'}); + } elsif (defined($result->{fileCountWarn}) && $result->{fileCountWarn} > 0) { + $self->{perfdata}->threshold_validate(label => 'warning-instance-virtual_volume-quota-files-count-' . $_, value => $result->{fileCountWarn}); + } + + if (defined($self->{option_results}->{'critical-instance-virtual_volume-quota-files-count'}) && $self->{option_results}->{'critical-instance-virtual_volume-quota-files-count'} ne '') { + $self->{perfdata}->threshold_validate(label => 'critical-instance-virtual_volume-quota-files-count-' . $_, value => $self->{option_results}->{'critical-instance-virtual_volume-quota-files-count'}); + } elsif (defined($result->{fileCountCrit}) && $result->{fileCountCrit} > 0) { + $self->{perfdata}->threshold_validate(label => 'critical-instance-virtual_volume-quota-files-count-' . $_, value => $result->{fileCountCrit}); + } + } +} + +1; + +__END__ + +=head1 MODE + +Check virtual volumes quotas. + +=over 8 + +=item B<--filter-filesystem-label> + +Filter virtual volume quota by filesystem label. + +=item B<--filter-volume-name> + +Filter virtual volumes quota by volume name. + +=item B<--filter-target> + +Filter virtual volumes quota by target. + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'vvq-detected', +'vvq-usage', 'vvq-usage-free', 'vvq-usage-prct', +'vvq-files', 'vvq-files-free', 'vvq-files-prct'. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/bluearc/snmp/mode/volumeusage.pm b/centreon-plugins/centreon/common/bluearc/snmp/mode/volumeusage.pm index 64643298e..f874a502d 100644 --- a/centreon-plugins/centreon/common/bluearc/snmp/mode/volumeusage.pm +++ b/centreon-plugins/centreon/common/bluearc/snmp/mode/volumeusage.pm @@ -24,30 +24,21 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); 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} . '_status'}; - $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; - return 0; + return 'status: ' . $self->{result_values}->{status}; } sub custom_usage_perfdata { my ($self, %options) = @_; - - my $label = 'used'; + + my $nlabel = 'volume.space.usage.bytes'; my $value_perf = $self->{result_values}->{used}; if (defined($self->{instance_mode}->{option_results}->{free})) { - $label = 'free'; + $nlabel = 'volume.space.free.bytes'; $value_perf = $self->{result_values}->{free}; } @@ -58,8 +49,9 @@ sub custom_usage_perfdata { } $self->{output}->perfdata_add( - label => $label, unit => 'B', - instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, + nlabel => $nlabel, + unit => 'B', + instances => $self->{result_values}->{display}, value => $value_perf, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options), @@ -87,11 +79,12 @@ sub custom_usage_output { 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; + return 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} + ); } sub custom_usage_calc { @@ -107,6 +100,12 @@ sub custom_usage_calc { return 0; } +sub prefix_volume_output { + my ($self, %options) = @_; + + return "Volume '" . $options{instance_value}->{display} . "' "; +} + sub set_counters { my ($self, %options) = @_; @@ -115,12 +114,11 @@ sub set_counters { ]; $self->{maps_counters}->{volume} = [ - { label => 'status', threshold => 0, set => { + { label => 'status', type => 2, warning_default => '%{status} =~ /needsChecking/i', set => { key_values => [ { name => 'status' }, { 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 => \&catalog_status_threshold, + closure_custom_threshold_check => \&catalog_status_threshold_ng } }, { label => 'usage', set => { @@ -128,53 +126,38 @@ sub set_counters { 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'), + closure_custom_threshold_check => $self->can('custom_usage_threshold') } - }, + } ]; } sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %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' }, - "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /needsChecking/i' }, - "critical-status:s" => { name => 'critical_status', default => '' }, - "units:s" => { name => 'units', default => '%' }, - "free" => { name => 'free' }, + '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); - - $self->change_macros(macros => ['warning_status', 'critical_status']); -} - -sub prefix_volume_output { - my ($self, %options) = @_; - - return "Volume '" . $options{instance_value}->{display} . "' "; -} - -my %map_volume_status = ( +my %map_volume_status = ( 1 => 'unformatted', 2 => 'mounted', 3 => 'formatted', - 4 => 'needsChecking', + 4 => 'needsChecking' ); my $mapping = { volumeLabel => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.3' }, volumeStatus => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.4', map => \%map_volume_status }, volumeCapacity => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.5' }, - volumeFreeCapacity => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.6' }, + volumeFreeCapacity => { oid => '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1.6' } }; my $oid_volumeEntry = '.1.3.6.1.4.1.11096.6.1.1.1.3.5.2.1'; @@ -186,9 +169,12 @@ sub manage_selection { $self->{output}->option_exit(); } + $self->{results} = $options{snmp}->get_table( + oid => $oid_volumeEntry, + nothing_quit => 1 + ); + $self->{volume} = {}; - $self->{results} = $options{snmp}->get_table(oid => $oid_volumeEntry, - nothing_quit => 1); foreach my $oid (keys %{$self->{results}}) { next if ($oid !~ /^$mapping->{volumeStatus}->{oid}\.(.*)$/); my $instance = $1; @@ -199,13 +185,14 @@ sub manage_selection { next; } - $self->{volume}->{$instance} = { display => $result->{volumeLabel}, - status => $result->{volumeStatus}, - total => $result->{volumeCapacity}, - used => $result->{volumeCapacity} - $result->{volumeFreeCapacity} }; + $self->{volume}->{$instance} = { + display => $result->{volumeLabel}, + status => $result->{volumeStatus}, + total => $result->{volumeCapacity}, + used => $result->{volumeCapacity} - $result->{volumeFreeCapacity} + }; } - - + if (scalar(keys %{$self->{volume}}) <= 0) { $self->{output}->add_option_msg(short_msg => "No volume found."); $self->{output}->option_exit(); @@ -241,14 +228,9 @@ Can used special variables like: %{status}, %{display} Set critical threshold for status (Default: -). Can used special variables like: %{status}, %{display} -=item B<--warning-*> +=item B<--warning-*> B<--critical-*> -Threshold warning. -Can be: 'usage'. - -=item B<--critical-*> - -Threshold critical. +Thresholds. Can be: 'usage'. =item B<--units> diff --git a/centreon-plugins/storage/hitachi/hnas/snmp/plugin.pm b/centreon-plugins/storage/hitachi/hnas/snmp/plugin.pm index 1d7159675..065f84951 100644 --- a/centreon-plugins/storage/hitachi/hnas/snmp/plugin.pm +++ b/centreon-plugins/storage/hitachi/hnas/snmp/plugin.pm @@ -29,14 +29,15 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $self->{version} = '1.0'; - %{$self->{modes}} = ( - 'cluster-status' => 'centreon::common::bluearc::snmp::mode::clusterstatus', - 'interfaces' => 'snmp_standard::mode::interfaces', - 'list-interfaces' => 'snmp_standard::mode::listinterfaces', - 'hardware' => 'centreon::common::bluearc::snmp::mode::hardware', - 'volume-usage' => 'centreon::common::bluearc::snmp::mode::volumeusage', - ); + $self->{modes} = { + 'cluster-status' => 'centreon::common::bluearc::snmp::mode::clusterstatus', + 'interfaces' => 'centreon::common::bluearc::snmp::mode::interfaces', + 'list-interfaces' => 'centreon::common::bluearc::snmp::mode::listinterfaces', + 'list-volumes' => 'centreon::common::bluearc::snmp::mode::listvolumes', + 'hardware' => 'centreon::common::bluearc::snmp::mode::hardware', + 'virtual-volumes-quotas' => 'centreon::common::bluearc::snmp::mode::virtualvolumesquotas', + 'volume-usage' => 'centreon::common::bluearc::snmp::mode::volumeusage' + }; return $self; }