From 4d715dd2ca746b48d0898277b649dce27c72147e Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sat, 13 Feb 2016 23:39:09 +0100 Subject: [PATCH 01/20] + ref #201: WIP (still some components todo) --- .../idrac/snmp/mode/components/amperage.pm | 122 ++++++++ .../snmp/mode/components/coolingdevice.pm | 113 ++++++++ .../idrac/snmp/mode/components/coolingunit.pm | 74 +++++ .../dell/idrac/snmp/mode/components/memory.pm | 74 +++++ .../idrac/snmp/mode/components/network.pm | 66 +++++ .../dell/idrac/snmp/mode/components/pci.pm | 74 +++++ .../idrac/snmp/mode/components/processor.pm | 74 +++++ .../dell/idrac/snmp/mode/components/psu.pm | 67 +++++ .../dell/idrac/snmp/mode/components/punit.pm | 74 +++++ .../idrac/snmp/mode/components/resources.pm | 87 ++++++ .../snmp/mode/components/systembattery.pm | 74 +++++ .../idrac/snmp/mode/components/temperature.pm | 55 ++-- .../idrac/snmp/mode/components/voltage.pm | 113 ++++++++ .../server/dell/idrac/snmp/mode/hardware.pm | 264 ++++-------------- 14 files changed, 1091 insertions(+), 240 deletions(-) create mode 100644 hardware/server/dell/idrac/snmp/mode/components/amperage.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/coolingunit.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/memory.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/network.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/pci.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/processor.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/psu.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/punit.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/resources.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/systembattery.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/voltage.pm diff --git a/hardware/server/dell/idrac/snmp/mode/components/amperage.pm b/hardware/server/dell/idrac/snmp/mode/components/amperage.pm new file mode 100644 index 000000000..1ebd18442 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/amperage.pm @@ -0,0 +1,122 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::amperage; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state %map_amperage_type); + +my $mapping = { + amperageProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.4', map => \%map_state }, + amperageProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.5', map => \%map_probe_status }, + amperageProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.6' }, + amperageProbeType => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.7', map => \%map_amperage_type }, + amperageProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.8' }, + amperageProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.10' }, + amperageProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.11' }, + amperageProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.12' }, + amperageProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.30.1.13' }, +}; +my $oid_amperageProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.30.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_amperageProbeTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking amperages"); + $self->{components}->{amperage} = {name => 'amperages', total => 0, skip => 0}; + return if ($self->check_filter(section => 'amperage')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_amperageProbeTableEntry}})) { + next if ($oid !~ /^$mapping->{amperageProbeStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_amperageProbeTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'amperage', instance => $instance)); + $self->{components}->{amperage}->{total}++; + + my ($divisor, $unit) = (1000, 'A'); + if ($result->{amperageProbeType} =~ /amperageProbeTypeIsPowerSupplyAmps|amperageProbeTypeIsSystemAmps/) { + $divisor = 10; + } elsif ($result->{amperageProbeType} =~ /amperageProbeTypeIsPowerSupplyWatts|amperageProbeTypeIsSystemWatts/) { + $unit = 'W'; + } + $result->{amperageProbeReading} = (defined($result->{amperageProbeReading})) ? $result->{amperageProbeReading} / $divisor : 'unknown'; + $self->{output}->output_add(long_msg => sprintf("amperage '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", + $result->{amperageProbeLocationName}, $result->{amperageProbeStatus}, $instance, + $result->{amperageProbeStateSettings}, $result->{amperageProbeReading})); + + my $exit = $self->get_severity(label => 'default.state', section => 'amperage.state', value => $result->{amperageProbeStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Amperage '%s' state is '%s'", $result->{amperageProbeLocationName}, $result->{amperageProbeStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'probe.status', section => 'amperage.status', value => $result->{amperageProbeStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Amperage '%s' status is '%s'", $result->{amperageProbeLocationName}, $result->{amperageProbeStatus})); + } + + next if ($result->{amperageProbeType} =~ /amperageProbeTypeIsDiscrete/); + + if (defined($result->{amperageProbeReading}) && $result->{amperageProbeReading} =~ /[0-9]/) { + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'amperage', instance => $instance, value => $result->{amperageProbeReading}); + if ($checked == 0) { + $result->{amperageProbeLowerNonCriticalThreshold} = (defined($result->{amperageProbeLowerNonCriticalThreshold}) && $result->{amperageProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? + $result->{amperageProbeLowerNonCriticalThreshold} / $divisor : ''; + $result->{amperageProbeLowerCriticalThreshold} = (defined($result->{amperageProbeLowerCriticalThreshold}) && $result->{amperageProbeLowerCriticalThreshold} =~ /[0-9]/) ? + $result->{amperageProbeLowerCriticalThreshold} / $divisor : ''; + $result->{amperageProbeUpperNonCriticalThreshold} = (defined($result->{amperageProbeUpperNonCriticalThreshold}) && $result->{amperageProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? + $result->{amperageProbeUpperNonCriticalThreshold} / $divisor : ''; + $result->{amperageProbeUpperCriticalThreshold} = (defined($result->{amperageProbeUpperCriticalThreshold}) && $result->{amperageProbeUpperCriticalThreshold} =~ /[0-9]/) ? + $result->{amperageProbeUpperCriticalThreshold} / $divisor : ''; + my $warn_th = $result->{amperageProbeLowerNonCriticalThreshold} . ':' . $result->{amperageProbeUpperNonCriticalThreshold}; + my $crit_th = $result->{amperageProbeLowerCriticalThreshold} . ':' . $result->{amperageProbeUpperCriticalThreshold}; + $self->{perfdata}->threshold_validate(label => 'warning-amperage-instance-' . $instance, value => $warn_th); + $self->{perfdata}->threshold_validate(label => 'critical-amperage-instance-' . $instance, value => $crit_th); + + $exit = $self->{perfdata}->threshold_check(value => $result->{amperageProbeReading}, threshold => [ { label => 'critical-amperage-instance-' . $instance, exit_litteral => 'critical' }, + { label => 'warning-amperage-instance-' . $instance, exit_litteral => 'warning' } ]); + $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-amperage-instance-' . $instance); + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-amperage-instance-' . $instance) + } + + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Amperage '%s' is %s %s", $result->{amperageProbeLocationName}, $result->{amperageProbeReading}, $unit)); + } + $self->{output}->perfdata_add(label => 'amperage_' . $result->{amperageProbeLocationName}, unit => $unit, + value => $result->{amperageProbeReading}, + warning => $warn, + critical => $crit, + ); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm b/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm new file mode 100644 index 000000000..9eaf13818 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm @@ -0,0 +1,113 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::coolingdevice; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); + +my $mapping = { + coolingDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.4', map => \%map_state }, + coolingDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.5', map => \%map_probe_status }, + coolingDeviceReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.6' }, + coolingDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.8' }, + coolingDeviceUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.10' }, + coolingDeviceUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.11' }, + coolingDeviceLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.12' }, + coolingDeviceLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.12.1.13' }, +}; +my $oid_coolingDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.12.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_coolingDeviceTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking cooling devices"); + $self->{components}->{coolingdevice} = {name => 'cooling devices', total => 0, skip => 0}; + return if ($self->check_filter(section => 'coolingdevice')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingDeviceTableEntry}})) { + next if ($oid !~ /^$mapping->{coolingDeviceStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingDeviceTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'coolingdevice', instance => $instance)); + $self->{components}->{coolingdevice}->{total}++; + + $result->{coolingDeviceReading} = (defined($result->{coolingDeviceReading})) ? $result->{coolingDeviceReading} : 'unknown'; + $self->{output}->output_add(long_msg => sprintf("cooling device '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", + $result->{coolingDeviceLocationName}, $result->{coolingDeviceStatus}, $instance, + $result->{coolingDeviceStateSettings}, $result->{coolingDeviceReading})); + + my $exit = $self->get_severity(label => 'default.state', section => 'coolingdevice.state', value => $result->{coolingDeviceStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Cooling device '%s' state is '%s'", $result->{coolingDeviceLocationName}, $result->{coolingDeviceStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'probe.status', section => 'coolingdevice.status', value => $result->{coolingDeviceStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Cooling device '%s' status is '%s'", $result->{coolingDeviceLocationName}, $result->{coolingDeviceStatus})); + } + + if (defined($result->{coolingDeviceReading}) && $result->{coolingDeviceReading} =~ /[0-9]/) { + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'coolingdevice', instance => $instance, value => $result->{coolingDeviceReading}); + if ($checked == 0) { + $result->{coolingDeviceLowerNonCriticalThreshold} = (defined($result->{coolingDeviceLowerNonCriticalThreshold}) && $result->{coolingDeviceLowerNonCriticalThreshold} =~ /[0-9]/) ? + $result->{coolingDeviceLowerNonCriticalThreshold} / 10 : ''; + $result->{coolingDeviceLowerCriticalThreshold} = (defined($result->{coolingDeviceLowerCriticalThreshold}) && $result->{coolingDeviceLowerCriticalThreshold} =~ /[0-9]/) ? + $result->{coolingDeviceLowerCriticalThreshold} / 10 : ''; + $result->{coolingDeviceUpperNonCriticalThreshold} = (defined($result->{coolingDeviceUpperNonCriticalThreshold}) && $result->{coolingDeviceUpperNonCriticalThreshold} =~ /[0-9]/) ? + $result->{coolingDeviceUpperNonCriticalThreshold} / 10 : ''; + $result->{coolingDeviceUpperCriticalThreshold} = (defined($result->{coolingDeviceUpperCriticalThreshold}) && $result->{coolingDeviceUpperCriticalThreshold} =~ /[0-9]/) ? + $result->{coolingDeviceUpperCriticalThreshold} : ''; + my $warn_th = $result->{coolingDeviceLowerNonCriticalThreshold} . ':' . $result->{coolingDeviceUpperNonCriticalThreshold}; + my $crit_th = $result->{coolingDeviceLowerCriticalThreshold} . ':' . $result->{coolingDeviceUpperCriticalThreshold}; + $self->{perfdata}->threshold_validate(label => 'warning-coolingdevice-instance-' . $instance, value => $warn_th); + $self->{perfdata}->threshold_validate(label => 'critical-coolingdevice-instance-' . $instance, value => $crit_th); + + $exit = $self->{perfdata}->threshold_check(value => $result->{coolingDeviceReading}, threshold => [ { label => 'critical-coolingdevice-instance-' . $instance, exit_litteral => 'critical' }, + { label => 'warning-coolingdevice-instance-' . $instance, exit_litteral => 'warning' } ]); + $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-coolingdevice-instance-' . $instance); + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-coolingdevice-instance-' . $instance) + } + + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Cooling device '%s' is %s rpm", $result->{coolingDeviceLocationName}, $result->{coolingDeviceReading})); + } + $self->{output}->perfdata_add(label => 'fan_' . $result->{coolingDeviceLocationName}, unit => 'rpm', + value => $result->{coolingDeviceReading}, + warning => $warn, + critical => $crit, + ); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/coolingunit.pm b/hardware/server/dell/idrac/snmp/mode/components/coolingunit.pm new file mode 100644 index 000000000..6968331a6 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/coolingunit.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::coolingunit; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + coolingUnitStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.4', map => \%map_state }, + coolingUnitName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.7' }, + coolingUnitStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.10.1.8', map => \%map_status }, +}; +my $oid_coolingUnitTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.10.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_coolingUnitTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking cooling units"); + $self->{components}->{coolingunit} = {name => 'cooling units', total => 0, skip => 0}; + return if ($self->check_filter(section => 'coolingunit')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_coolingUnitTableEntry}})) { + next if ($oid !~ /^$mapping->{coolingUnitStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_coolingUnitTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'coolingunit', instance => $instance)); + $self->{components}->{coolingunit}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("cooling unit '%s' status is '%s' [instance = %s] [state = %s]", + $result->{coolingUnitName}, $result->{coolingUnitStatus}, $instance, + $result->{coolingUnitStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'coolingunit.state', value => $result->{coolingUnitStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Cooling unit '%s' state is '%s'", $result->{coolingUnitName}, $result->{coolingUnitStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'coolingunit.status', value => $result->{coolingUnitStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Cooling unit '%s' status is '%s'", $result->{coolingUnitName}, $result->{coolingUnitStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/memory.pm b/hardware/server/dell/idrac/snmp/mode/components/memory.pm new file mode 100644 index 000000000..00d08f636 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/memory.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::memory; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + memoryDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.4', map => \%map_state }, + memoryDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.5', map => \%map_status }, + memoryDeviceLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.50.1.8' }, +}; +my $oid_memoryDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.50.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_memoryDeviceTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking memories"); + $self->{components}->{memory} = {name => 'memories', total => 0, skip => 0}; + return if ($self->check_filter(section => 'memory')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_memoryDeviceTableEntry}})) { + next if ($oid !~ /^$mapping->{memoryDeviceStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_memoryDeviceTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'memory', instance => $instance)); + $self->{components}->{memory}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("memory '%s' status is '%s' [instance = %s] [state = %s]", + $result->{memoryDeviceLocationName}, $result->{memoryDeviceStatus}, $instance, + $result->{memoryDeviceStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'memory.state', value => $result->{memoryDeviceStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Memory '%s' state is '%s'", $result->{memoryDeviceLocationName}, $result->{memoryDeviceStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'memory.status', value => $result->{memoryDeviceStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Memory '%s' status is '%s'", $result->{memoryDeviceLocationName}, $result->{memoryDeviceStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/network.pm b/hardware/server/dell/idrac/snmp/mode/components/network.pm new file mode 100644 index 000000000..e83342b77 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/network.pm @@ -0,0 +1,66 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::network; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + networkDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.90.1.3', map => \%map_status }, + networkDeviceProductName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.90.1.6' }, +}; +my $oid_networkDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.90.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_networkDeviceTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking networks"); + $self->{components}->{network} = {name => 'networks', total => 0, skip => 0}; + return if ($self->check_filter(section => 'network')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_networkDeviceTableEntry}})) { + next if ($oid !~ /^$mapping->{networkDeviceStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_networkDeviceTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'network', instance => $instance)); + $self->{components}->{network}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("network '%s' status is '%s' [instance = %s]", + $result->{networkDeviceProductName}, $result->{networkDeviceStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default.status', section => 'network.status', value => $result->{networkDeviceStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Network '%s' status is '%s'", $result->{networkDeviceProductName}, $result->{networkDeviceStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/pci.pm b/hardware/server/dell/idrac/snmp/mode/components/pci.pm new file mode 100644 index 000000000..497e99352 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/pci.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::pci; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + pCIDeviceStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.4', map => \%map_state }, + pCIDeviceStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.5', map => \%map_status }, + pCIDeviceDescriptionName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.80.1.9' }, +}; +my $oid_pCIDeviceTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.80.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_pCIDeviceTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking pci"); + $self->{components}->{pci} = {name => 'pci', total => 0, skip => 0}; + return if ($self->check_filter(section => 'pci')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_pCIDeviceTableEntry}})) { + next if ($oid !~ /^$mapping->{pCIDeviceStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_pCIDeviceTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'pci', instance => $instance)); + $self->{components}->{pci}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("pci '%s' status is '%s' [instance = %s] [state = %s]", + $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStatus}, $instance, + $result->{pCIDeviceStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'pci.state', value => $result->{pCIDeviceStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("PCI '%s' state is '%s'", $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'pci.status', value => $result->{pCIDeviceStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("PCI '%s' status is '%s'", $result->{pCIDeviceDescriptionName}, $result->{pCIDeviceStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/processor.pm b/hardware/server/dell/idrac/snmp/mode/components/processor.pm new file mode 100644 index 000000000..bc2a896ad --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/processor.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::processor; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + processorDeviceStatusStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.32.1.4', map => \%map_state }, + processorDeviceStatusStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.32.1.5', map => \%map_status }, + processorDeviceStatusLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1100.32.1.7' }, +}; +my $oid_processorDeviceStatusTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1100.32.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_processorDeviceStatusTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking processors"); + $self->{components}->{processor} = {name => 'processors', total => 0, skip => 0}; + return if ($self->check_filter(section => 'processor')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_processorDeviceStatusTableEntry}})) { + next if ($oid !~ /^$mapping->{processorDeviceStatusStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_processorDeviceStatusTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'processor', instance => $instance)); + $self->{components}->{processor}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("processor '%s' status is '%s' [instance = %s] [state = %s]", + $result->{processorDeviceStatusLocationName}, $result->{processorDeviceStatusStatus}, $instance, + $result->{processorDeviceStatusStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'processor.state', value => $result->{processorDeviceStatusStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Processor '%s' state is '%s'", $result->{processorDeviceStatusLocationName}, $result->{processorDeviceStatusStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'processor.status', value => $result->{processorDeviceStatusStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Processor '%s' status is '%s'", $result->{processorDeviceStatusLocationName}, $result->{processorDeviceStatusStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/psu.pm b/hardware/server/dell/idrac/snmp/mode/components/psu.pm new file mode 100644 index 000000000..c866a1720 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/psu.pm @@ -0,0 +1,67 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::psu; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + powerSupplyStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.12.1.5', map => \%map_status }, + powerSupplyLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.12.1.8' }, +}; +my $oid_powerSupplyTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.12.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_powerSupplyTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking power supplies"); + $self->{components}->{psu} = {name => 'power supplies', total => 0, skip => 0}; + return if ($self->check_filter(section => 'psu')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerSupplyTableEntry}})) { + next if ($oid !~ /^$mapping->{powerSupplyStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerSupplyTableEntry}, 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]", + $result->{powerSupplyLocationName}, $result->{powerSupplyStatus}, $instance, + )); + + + my $exit = $self->get_severity(label => 'default.status', section => 'psu.status', value => $result->{powerSupplyStatus}); + 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'", $result->{powerSupplyLocationName}, $result->{powerSupplyStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/punit.pm b/hardware/server/dell/idrac/snmp/mode/components/punit.pm new file mode 100644 index 000000000..d42aead49 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/punit.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::punit; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + powerUnitStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.4', map => \%map_state }, + powerUnitName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.7' }, + powerUnitStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.10.1.8', map => \%map_status }, +}; +my $oid_powerUnitTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.10.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_powerUnitTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking power units"); + $self->{components}->{punit} = {name => 'power units', total => 0, skip => 0}; + return if ($self->check_filter(section => 'punit')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_powerUnitTableEntry}})) { + next if ($oid !~ /^$mapping->{powerUnitStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_powerUnitTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'punit', instance => $instance)); + $self->{components}->{punit}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("power unit '%s' status is '%s' [instance = %s] [state = %s]", + $result->{powerUnitName}, $result->{powerUnitStatus}, $instance, + $result->{powerUnitStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'punit.state', value => $result->{powerUnitStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power unit '%s' state is '%s'", $result->{powerUnitName}, $result->{powerUnitStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'punit.status', value => $result->{powerUnitStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power unit '%s' status is '%s'", $result->{powerUnitName}, $result->{powerUnitStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/resources.pm b/hardware/server/dell/idrac/snmp/mode/components/resources.pm new file mode 100644 index 000000000..2cbad5fb8 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/resources.pm @@ -0,0 +1,87 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::resources; + +use strict; +use warnings; +use Exporter; + +our %map_state; +our %map_status; +our %map_probe_status; +our %map_amperage_type; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(%map_probe_status %map_state %map_status %map_amperage_type); + +%map_probe_status = ( + 1 => 'other', + 2 => 'unknown', + 3 => 'ok', + 4 => 'nonCriticalUpper', + 5 => 'criticalUpper', + 6 => 'nonRecoverableUpper', + 7 => 'nonCriticalLower', + 8 => 'criticalLower', + 9 => 'nonRecoverableLower', + 10 => 'failed', +); + +%map_status = ( + 1 => 'other', + 2 => 'unknown', + 3 => 'ok', + 4 => 'nonCritical', + 5 => 'critical', + 6 => 'nonRecoverable', +); + +%map_state = ( + 1 => 'unknown', + 2 => 'enabled', + 4 => 'notReady', + 6 => 'enabledAndNotReady', +); + +%map_amperage_type = ( + 1 => 'amperageProbeTypeIsOther', + 2 => 'amperageProbeTypeIsUnknown', + 3 => 'amperageProbeTypeIs1Point5Volt', + 4 => 'amperageProbeTypeIs3Point3volt', + 5 => 'amperageProbeTypeIs5Volt', + 6 => 'amperageProbeTypeIsMinus5Volt', + 7 => 'amperageProbeTypeIs12Volt', + 8 => 'amperageProbeTypeIsMinus12Volt', + 9 => 'amperageProbeTypeIsIO', + 10 => 'amperageProbeTypeIsCore', + 11 => 'amperageProbeTypeIsFLEA', + 12 => 'amperageProbeTypeIsBattery', + 13 => 'amperageProbeTypeIsTerminator', + 14 => 'amperageProbeTypeIs2Point5Volt', + 15 => 'amperageProbeTypeIsGTL', + 16 => 'amperageProbeTypeIsDiscrete', + 23 => 'amperageProbeTypeIsPowerSupplyAmps', + 24 => 'amperageProbeTypeIsPowerSupplyWatts', + 25 => 'amperageProbeTypeIsSystemAmps', + 26 => 'amperageProbeTypeIsSystemWatts', +); + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/systembattery.pm b/hardware/server/dell/idrac/snmp/mode/components/systembattery.pm new file mode 100644 index 000000000..6d595dee8 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/systembattery.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::systembattery; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_state); + +my $mapping = { + systemBatteryStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.4', map => \%map_state }, + systemBatteryStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.5', map => \%map_status }, + systemBatteryLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.50.1.7' }, +}; +my $oid_systemBatteryTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.50.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_systemBatteryTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking system batteries"); + $self->{components}->{systembattery} = {name => 'system batteries', total => 0, skip => 0}; + return if ($self->check_filter(section => 'systembattery')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_systemBatteryTableEntry}})) { + next if ($oid !~ /^$mapping->{systemBatteryStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_systemBatteryTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'systembattery', instance => $instance)); + $self->{components}->{systembattery}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("system battery '%s' status is '%s' [instance = %s] [state = %s]", + $result->{systemBatteryLocationName}, $result->{systemBatteryStatus}, $instance, + $result->{systemBatteryStateSettings})); + + my $exit = $self->get_severity(label => 'default.state', section => 'systembattery.state', value => $result->{systemBatteryStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("System battery '%s' state is '%s'", $result->{systemBatteryLocationName}, $result->{systemBatteryStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'systembattery.status', value => $result->{systemBatteryStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("System battery '%s' status is '%s'", $result->{systemBatteryLocationName}, $result->{systemBatteryStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/temperature.pm b/hardware/server/dell/idrac/snmp/mode/components/temperature.pm index 68fe2a743..95213638a 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/temperature.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/temperature.pm @@ -22,25 +22,8 @@ package hardware::server::dell::idrac::snmp::mode::components::temperature; use strict; use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); -my %map_temp_status = ( - 1 => 'other', - 2 => 'unknown', - 3 => 'ok', - 4 => 'nonCriticalUpper', - 5 => 'criticalUpper', - 6 => 'nonRecoverableUpper', - 7 => 'nonCriticalLower', - 8 => 'criticalLower', - 9 => 'nonRecoverableLower', - 10 => 'failed', -); -my %map_temp_state = ( - 1 => 'unknown', - 2 => 'enabled', - 4 => 'notReady', - 6 => 'enabledAndNotReady', -); my %map_temp_type = ( 1 => 'temperatureProbeTypeIsOther', 2 => 'temperatureProbeTypeIsUnknown', @@ -49,22 +32,22 @@ my %map_temp_type = ( ); my $mapping = { - temperatureProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.4', map => \%map_temp_state }, - temperatureProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.5', map => \%map_temp_status }, + temperatureProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.4', map => \%map_state }, + temperatureProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.5', map => \%map_probe_status }, temperatureProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.6' }, temperatureProbeType => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.7', map => \%map_temp_type }, temperatureProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.8' }, temperatureProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.10' }, - temperatureProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.10' }, - temperatureProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.11' }, - temperatureProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.12' }, + temperatureProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.11' }, + temperatureProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.12' }, + temperatureProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.700.20.1.13' }, }; my $oid_temperatureProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.700.20.1'; sub load { - my (%options) = @_; + my ($self) = @_; - push @{$options{request}}, { oid => $oid_temperatureProbeTableEntry, begin => $mapping->{temperatureProbeStateSettings}->{oid}, end => $mapping->{temperatureProbeLowerCriticalThreshold}->{oid} }; + push @{$self->{request}}, { oid => $oid_temperatureProbeTableEntry, begin => $mapping->{temperatureProbeStateSettings}->{oid}, end => $mapping->{temperatureProbeLowerCriticalThreshold}->{oid} }; } sub check { @@ -72,29 +55,29 @@ sub check { $self->{output}->output_add(long_msg => "Checking temperatures"); $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; - return if ($self->check_exclude(section => 'temperature')); + return if ($self->check_filter(section => 'temperature')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_temperatureProbeTableEntry}})) { next if ($oid !~ /^$mapping->{temperatureProbeStatus}->{oid}\.(.*)$/); my $instance = $1; my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_temperatureProbeTableEntry}, instance => $instance); - next if ($self->check_exclude(section => 'temperature', instance => $instance)); + next if ($self->check_filter(section => 'temperature', instance => $instance)); $self->{components}->{temperature}->{total}++; $result->{temperatureProbeReading} = (defined($result->{temperatureProbeReading})) ? $result->{temperatureProbeReading} / 10 : 'unknown'; - $self->{output}->output_add(long_msg => sprintf("Temperature '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", + $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStatus}, $instance, $result->{temperatureProbeStateSettings}, $result->{temperatureProbeReading})); - my $exit = $self->get_severity(section => 'temperature-state', value => $result->{temperatureProbeStateSettings}); + my $exit = $self->get_severity(label => 'default.state', section => 'temperature.state', value => $result->{temperatureProbeStateSettings}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' state is '%s'", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStateSettings})); next; } - $exit = $self->get_severity(section => 'temperature-status', value => $result->{temperatureProbeStatus}); + $exit = $self->get_severity(label => 'probe.status', section => 'temperature.status', value => $result->{temperatureProbeStatus}); 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'", $result->{temperatureProbeLocationName}, $result->{temperatureProbeStatus})); @@ -103,7 +86,15 @@ sub check { if (defined($result->{temperatureProbeReading}) && $result->{temperatureProbeReading} =~ /[0-9]/) { my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{temperatureProbeReading}); if ($checked == 0) { - my $warn_th = $result->{temperatureProbeLowerNonCriticalThreshold} . ':' . $result->{temperatureProbeUpperCriticalThreshold}; + $result->{temperatureProbeLowerNonCriticalThreshold} = (defined($result->{temperatureProbeLowerNonCriticalThreshold}) && $result->{temperatureProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? + $result->{temperatureProbeLowerNonCriticalThreshold} / 10 : ''; + $result->{temperatureProbeLowerCriticalThreshold} = (defined($result->{temperatureProbeLowerCriticalThreshold}) && $result->{temperatureProbeLowerCriticalThreshold} =~ /[0-9]/) ? + $result->{temperatureProbeLowerCriticalThreshold} / 10 : ''; + $result->{temperatureProbeUpperNonCriticalThreshold} = (defined($result->{temperatureProbeUpperNonCriticalThreshold}) && $result->{temperatureProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? + $result->{temperatureProbeUpperNonCriticalThreshold} / 10 : ''; + $result->{temperatureProbeUpperCriticalThreshold} = (defined($result->{temperatureProbeUpperCriticalThreshold}) && $result->{temperatureProbeUpperCriticalThreshold} =~ /[0-9]/) ? + $result->{temperatureProbeUpperCriticalThreshold} / 10 : ''; + my $warn_th = $result->{temperatureProbeLowerNonCriticalThreshold} . ':' . $result->{temperatureProbeUpperNonCriticalThreshold}; my $crit_th = $result->{temperatureProbeLowerCriticalThreshold} . ':' . $result->{temperatureProbeUpperCriticalThreshold}; $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); @@ -118,7 +109,7 @@ sub check { $self->{output}->output_add(severity => $exit, short_msg => sprintf("Temperature '%s' is %s degree centigrade", $result->{temperatureProbeLocationName}, $result->{temperatureProbeReading})); } - $self->{output}->perfdata_add(label => 'temp_' . $instance, unit => 'C', + $self->{output}->perfdata_add(label => 'temp_' . $result->{temperatureProbeLocationName}, unit => 'C', value => $result->{temperatureProbeReading}, warning => $warn, critical => $crit, diff --git a/hardware/server/dell/idrac/snmp/mode/components/voltage.pm b/hardware/server/dell/idrac/snmp/mode/components/voltage.pm new file mode 100644 index 000000000..ff3399c7b --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/voltage.pm @@ -0,0 +1,113 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::voltage; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_probe_status %map_state); + +my $mapping = { + voltageProbeStateSettings => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.4', map => \%map_state }, + voltageProbeStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.5', map => \%map_probe_status }, + voltageProbeReading => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.6' }, + voltageProbeLocationName => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.8' }, + voltageProbeUpperCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.10' }, + voltageProbeUpperNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.11' }, + voltageProbeLowerNonCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.12' }, + voltageProbeLowerCriticalThreshold => { oid => '.1.3.6.1.4.1.674.10892.5.4.600.20.1.13' }, +}; +my $oid_voltageProbeTableEntry = '.1.3.6.1.4.1.674.10892.5.4.600.20.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_voltageProbeTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking voltages"); + $self->{components}->{voltage} = {name => 'voltages', total => 0, skip => 0}; + return if ($self->check_filter(section => 'voltage')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_voltageProbeTableEntry}})) { + next if ($oid !~ /^$mapping->{voltageProbeStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_voltageProbeTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'voltage', instance => $instance)); + $self->{components}->{voltage}->{total}++; + + $result->{voltageProbeReading} = (defined($result->{voltageProbeReading})) ? $result->{voltageProbeReading} / 1000 : 'unknown'; + $self->{output}->output_add(long_msg => sprintf("voltage '%s' status is '%s' [instance = %s] [state = %s] [value = %s]", + $result->{voltageProbeLocationName}, $result->{voltageProbeStatus}, $instance, + $result->{voltageProbeStateSettings}, $result->{voltageProbeReading})); + + my $exit = $self->get_severity(label => 'default.state', section => 'voltage.state', value => $result->{voltageProbeStateSettings}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Voltage '%s' state is '%s'", $result->{voltageProbeLocationName}, $result->{voltageProbeStateSettings})); + next; + } + + $exit = $self->get_severity(label => 'probe.status', section => 'voltage.status', value => $result->{voltageProbeStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Voltage '%s' status is '%s'", $result->{voltageProbeLocationName}, $result->{voltageProbeStatus})); + } + + if (defined($result->{voltageProbeReading}) && $result->{voltageProbeReading} =~ /[0-9]/) { + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'voltage', instance => $instance, value => $result->{voltageProbeReading}); + if ($checked == 0) { + $result->{voltageProbeLowerNonCriticalThreshold} = (defined($result->{voltageProbeLowerNonCriticalThreshold}) && $result->{voltageProbeLowerNonCriticalThreshold} =~ /[0-9]/) ? + $result->{voltageProbeLowerNonCriticalThreshold} / 1000 : ''; + $result->{voltageProbeLowerCriticalThreshold} = (defined($result->{voltageProbeLowerCriticalThreshold}) && $result->{voltageProbeLowerCriticalThreshold} =~ /[0-9]/) ? + $result->{voltageProbeLowerCriticalThreshold} / 1000 : ''; + $result->{voltageProbeUpperNonCriticalThreshold} = (defined($result->{voltageProbeUpperNonCriticalThreshold}) && $result->{voltageProbeUpperNonCriticalThreshold} =~ /[0-9]/) ? + $result->{voltageProbeUpperNonCriticalThreshold} / 1000 : ''; + $result->{voltageProbeUpperCriticalThreshold} = (defined($result->{voltageProbeUpperCriticalThreshold}) && $result->{voltageProbeUpperCriticalThreshold} =~ /[0-9]/) ? + $result->{voltageProbeUpperCriticalThreshold} / 1000 : ''; + my $warn_th = $result->{voltageProbeLowerNonCriticalThreshold} . ':' . $result->{voltageProbeUpperNonCriticalThreshold}; + my $crit_th = $result->{voltageProbeLowerCriticalThreshold} . ':' . $result->{voltageProbeUpperCriticalThreshold}; + $self->{perfdata}->threshold_validate(label => 'warning-voltage-instance-' . $instance, value => $warn_th); + $self->{perfdata}->threshold_validate(label => 'critical-voltage-instance-' . $instance, value => $crit_th); + + $exit = $self->{perfdata}->threshold_check(value => $result->{voltageProbeReading}, threshold => [ { label => 'critical-voltage-instance-' . $instance, exit_litteral => 'critical' }, + { label => 'warning-voltage-instance-' . $instance, exit_litteral => 'warning' } ]); + $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-voltage-instance-' . $instance); + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-voltage-instance-' . $instance) + } + + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Voltage '%s' is %s V", $result->{voltageProbeLocationName}, $result->{voltageProbeReading})); + } + $self->{output}->perfdata_add(label => 'voltage_' . $result->{voltageProbeLocationName}, unit => 'V', + value => $result->{voltageProbeReading}, + warning => $warn, + critical => $crit, + ); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/hardware.pm b/hardware/server/dell/idrac/snmp/mode/hardware.pm index 57e57e7f0..a1e0b9802 100644 --- a/hardware/server/dell/idrac/snmp/mode/hardware.pm +++ b/hardware/server/dell/idrac/snmp/mode/hardware.pm @@ -20,33 +20,60 @@ package hardware::server::dell::idrac::snmp::mode::hardware; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::hardware); use strict; use warnings; -use centreon::plugins::misc; -my $thresholds = { - 'temperature-state' => [ - ['unknown', 'UNKNOWN'], - ['enabled', 'OK'], - ['notReady', 'WARNING'], - ['enabledAndNotReady', 'WARNING'], - ['.*', 'UNKNOWN'], - ], - 'temperature-status' => [ - ['other', 'UNKNOWN'], - ['unknown', 'UNKNOWN'], - ['ok', 'OK'], - ['nonCriticalUpper', 'WARNING'], - ['criticalUpper', 'CRITICAL'], - ['nonCriticalLower', 'WARNING'], - ['criticalLower', 'CRITICAL'], - ['nonRecoverableLower', 'CRITICAL'], - ['failed', 'CRITICAL'], - ['.*', 'UNKNOWN'], - ], -}; +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(psu|punit|temperature|voltage|amperage|systembattery|coolingunit|coolingdevice|processor|memory|pci|network)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|voltage|amperage|coolingdevice)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + 'default.state' => [ + ['unknown', 'UNKNOWN'], + ['enabled', 'OK'], + ['notReady', 'WARNING'], + ['enabledAndNotReady', 'WARNING'], + ], + 'default.status' => [ + ['other', 'UNKNOWN'], + ['unknown', 'UNKNOWN'], + ['ok', 'OK'], + ['nonCritical', 'WARNING'], + ['critical', 'CRITICAL'], + ['nonRecoverable', 'CRITICAL'], + ], + 'probe.status' => [ + ['other', 'UNKNOWN'], + ['unknown', 'UNKNOWN'], + ['ok', 'OK'], + ['nonCriticalUpper', 'WARNING'], + ['criticalUpper', 'CRITICAL'], + ['nonCriticalLower', 'WARNING'], + ['criticalLower', 'CRITICAL'], + ['nonRecoverableLower', 'CRITICAL'], + ['failed', 'CRITICAL'], + ], + }; + + # need also: fru, systemslot, storagectrl (storage controller), storagebattery + # physicaldisk, virtualdisk + $self->{components_path} = 'hardware::server::dell::idrac::snmp::mode::components'; + $self->{components_module} = ['psu', 'punit', 'temperature', 'voltage', 'amperage', + 'systembattery', 'coolingunit', 'coolingdevice', 'processor', 'memory', 'pci', 'network']; +} + +sub snmp_execute { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); +} sub new { my ($class, %options) = @_; @@ -56,189 +83,11 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { - "exclude:s" => { name => 'exclude' }, - "component:s" => { name => 'component', default => '.*' }, - "no-component:s" => { name => 'no_component' }, - "threshold-overload:s@" => { name => 'threshold_overload' }, - "warning:s@" => { name => 'warning' }, - "critical:s@" => { name => 'critical' }, }); - - $self->{components} = {}; - $self->{no_components} = undef; + return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (defined($self->{option_results}->{no_component})) { - if ($self->{option_results}->{no_component} ne '') { - $self->{no_components} = $self->{option_results}->{no_component}; - } else { - $self->{no_components} = 'critical'; - } - } - - $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}; - } - - $self->{numeric_threshold} = {}; - foreach my $option (('warning', 'critical')) { - foreach my $val (@{$self->{option_results}->{$option}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $regexp, $value) = ($1, $2, $3); - if ($section !~ /(temperature)/) { - $self->{output}->add_option_msg(short_msg => "Wrong $option option '" . $val . "' (type must be: temperature)."); - $self->{output}->option_exit(); - } - my $position = 0; - if (defined($self->{numeric_threshold}->{$section})) { - $position = scalar(@{$self->{numeric_threshold}->{$section}}); - } - if (($self->{perfdata}->threshold_validate(label => $option . '-' . $section . '-' . $position, value => $value)) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong $option threshold '" . $value . "'."); - $self->{output}->option_exit(); - } - $self->{numeric_threshold}->{$section} = [] if (!defined($self->{numeric_threshold}->{$section})); - push @{$self->{numeric_threshold}->{$section}}, { label => $option . '-' . $section . '-' . $position, threshold => $option, regexp => $regexp }; - } - } -} - -sub run { - my ($self, %options) = @_; - # $options{snmp} = snmp object - $self->{snmp} = $options{snmp}; - - my $snmp_request = []; - my @components = ('temperature'); - foreach (@components) { - if (/$self->{option_results}->{component}/) { - my $mod_name = "hardware::server::dell::idrac::snmp::mode::components::$_"; - centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name, - error_msg => "Cannot load module '$mod_name'."); - my $func = $mod_name->can('load'); - $func->(request => $snmp_request); - } - } - - if (scalar(@{$snmp_request}) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong option. Cannot find component '" . $self->{option_results}->{component} . "'."); - $self->{output}->option_exit(); - } - $self->{results} = $self->{snmp}->get_multiple_table(oids => $snmp_request); - - foreach (@components) { - if (/$self->{option_results}->{component}/) { - my $mod_name = "hardware::server::dell::idrac::snmp::mode::components::$_"; - my $func = $mod_name->can('check'); - $func->($self); - } - } - - my $total_components = 0; - my $display_by_component = ''; - my $display_by_component_append = ''; - foreach my $comp (sort(keys %{$self->{components}})) { - # Skipping short msg when no components - next if ($self->{components}->{$comp}->{total} == 0 && $self->{components}->{$comp}->{skip} == 0); - $total_components += $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - my $count_by_components = $self->{components}->{$comp}->{total} + $self->{components}->{$comp}->{skip}; - $display_by_component .= $display_by_component_append . $self->{components}->{$comp}->{total} . '/' . $count_by_components . ' ' . $self->{components}->{$comp}->{name}; - $display_by_component_append = ', '; - } - - $self->{output}->output_add(severity => 'OK', - short_msg => sprintf("All %s components are ok [%s].", - $total_components, - $display_by_component) - ); - - if (defined($self->{option_results}->{no_component}) && $total_components == 0) { - $self->{output}->output_add(severity => $self->{no_components}, - short_msg => 'No components are checked.'); - } - - $self->{output}->display(); - $self->{output}->exit(); -} - -sub check_exclude { - my ($self, %options) = @_; - - if (defined($options{instance})) { - if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)${options{section}}[^,]*#\Q$options{instance}\E#/) { - $self->{components}->{$options{section}}->{skip}++; - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance.")); - return 1; - } - } elsif (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} =~ /(^|\s|,)$options{section}(\s|,|$)/) { - $self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section.")); - return 1; - } - return 0; -} - -sub get_severity_numeric { - my ($self, %options) = @_; - my $status = 'OK'; # default - my $thresholds = { warning => undef, critical => undef }; - my $checked = 0; - - if (defined($self->{numeric_threshold}->{$options{section}})) { - my $exits = []; - foreach (@{$self->{numeric_threshold}->{$options{section}}}) { - if ($options{instance} =~ /$_->{regexp}/) { - push @{$exits}, $self->{perfdata}->threshold_check(value => $options{value}, threshold => [ { label => $_->{label}, exit_litteral => $_->{threshold} } ]); - $thresholds->{$_->{threshold}} = $self->{perfdata}->get_perfdata_for_output(label => $_->{label}); - $checked = 1; - } - } - $status = $self->{output}->get_most_critical(status => $exits) if (scalar(@{$exits}) > 0); - } - - return ($status, $thresholds->{warning}, $thresholds->{critical}, $checked); -} - -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; -} - 1; __END__ @@ -246,7 +95,6 @@ __END__ =head1 MODE Check hardware components (temperatures,...). -Mode is in WIP. =over 8 @@ -255,10 +103,10 @@ Mode is in WIP. Which component to check (Default: '.*'). Can be: 'temperature', -=item B<--exclude> +=item B<--filter> -Exclude some parts (comma seperated list) (Example: --exclude=psu) -Can also exclude specific instance: --exclude='temperature#1.1#' +Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=psu) +Can also exclude specific instance: --filter=temperature,1.1 =item B<--no-component> @@ -267,9 +115,9 @@ If total (with skipped) is 0. (Default: 'critical' returns). =item B<--threshold-overload> -Set to overload default threshold values (syntax: section,status,regexp) +Set to overload default threshold values (syntax: section,[instance,]status,regexp) It used before default thresholds (order stays). -Example: --threshold-overload='temperature-state,CRITICAL,^(?!(enabled)$)' +Example: --threshold-overload='temperature.state,CRITICAL,^(?!(enabled)$)' =item B<--warning> From 37f9a4c6aead55c749fc5737998975025793760d Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 14 Feb 2016 21:10:08 +0100 Subject: [PATCH 02/20] + Fix #201 --- .../dell/idrac/snmp/mode/components/fru.pm | 66 +++++++++++++++++ .../dell/idrac/snmp/mode/components/pdisk.pm | 74 +++++++++++++++++++ .../idrac/snmp/mode/components/resources.pm | 23 +++++- .../dell/idrac/snmp/mode/components/slot.pm | 66 +++++++++++++++++ .../snmp/mode/components/storagebattery.pm | 66 +++++++++++++++++ .../idrac/snmp/mode/components/storagectrl.pm | 66 +++++++++++++++++ .../dell/idrac/snmp/mode/components/vdisk.pm | 67 +++++++++++++++++ .../server/dell/idrac/snmp/mode/hardware.pm | 38 +++++++--- 8 files changed, 456 insertions(+), 10 deletions(-) create mode 100644 hardware/server/dell/idrac/snmp/mode/components/fru.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/pdisk.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/slot.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/storagebattery.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/storagectrl.pm create mode 100644 hardware/server/dell/idrac/snmp/mode/components/vdisk.pm diff --git a/hardware/server/dell/idrac/snmp/mode/components/fru.pm b/hardware/server/dell/idrac/snmp/mode/components/fru.pm new file mode 100644 index 000000000..f69778544 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/fru.pm @@ -0,0 +1,66 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::fru; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + fruInformationStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.2000.10.1.3', map => \%map_status }, + fruSerialNumberName => { oid => '.1.3.6.1.4.1.674.10892.5.4.2000.10.1.7' }, +}; +my $oid_fruTableEntry = '.1.3.6.1.4.1.674.10892.5.4.2000.10.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_fruTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking fru"); + $self->{components}->{fru} = {name => 'fru', total => 0, skip => 0}; + return if ($self->check_filter(section => 'fru')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fruTableEntry}})) { + next if ($oid !~ /^$mapping->{fruInformationStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fruTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'fru', instance => $instance)); + $self->{components}->{fru}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("fru '%s' status is '%s' [instance = %s]", + $result->{fruSerialNumberName}, $result->{fruInformationStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default.status', section => 'fru.status', value => $result->{fruInformationStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fru '%s' status is '%s'", $result->{fruSerialNumberName}, $result->{fruInformationStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/pdisk.pm b/hardware/server/dell/idrac/snmp/mode/components/pdisk.pm new file mode 100644 index 000000000..3e7d42eac --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/pdisk.pm @@ -0,0 +1,74 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::pdisk; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status %map_pdisk_state); + +my $mapping = { + physicalDiskState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.4', map => \%map_pdisk_state }, + physicalDiskComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.24', map => \%map_status }, + physicalDiskFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1.54' }, +}; +my $oid_physicalDiskTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.130.4.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_physicalDiskTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking physical disks"); + $self->{components}->{pdisk} = {name => 'physical disks', total => 0, skip => 0}; + return if ($self->check_filter(section => 'pdisk')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_physicalDiskTableEntry}})) { + next if ($oid !~ /^$mapping->{physicalDiskComponentStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_physicalDiskTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'pdisk', instance => $instance)); + $self->{components}->{pdisk}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("power unit '%s' status is '%s' [instance = %s] [state = %s]", + $result->{physicalDiskFQDD}, $result->{physicalDiskComponentStatus}, $instance, + $result->{physicalDiskState})); + + my $exit = $self->get_severity(section => 'pdisk.state', value => $result->{physicalDiskState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power unit '%s' state is '%s'", $result->{physicalDiskFQDD}, $result->{physicalDiskState})); + next; + } + + $exit = $self->get_severity(label => 'default.status', section => 'pdisk.status', value => $result->{physicalDiskComponentStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power unit '%s' status is '%s'", $result->{physicalDiskFQDD}, $result->{physicalDiskComponentStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/resources.pm b/hardware/server/dell/idrac/snmp/mode/components/resources.pm index 2cbad5fb8..c90f092c0 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/resources.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/resources.pm @@ -28,9 +28,11 @@ our %map_state; our %map_status; our %map_probe_status; our %map_amperage_type; +our %map_pdisk_state; +our %map_vdisk_state; our @ISA = qw(Exporter); -our @EXPORT_OK = qw(%map_probe_status %map_state %map_status %map_amperage_type); +our @EXPORT_OK = qw(%map_probe_status %map_state %map_status %map_amperage_type %map_pdisk_state %map_vdisk_state); %map_probe_status = ( 1 => 'other', @@ -61,6 +63,25 @@ our @EXPORT_OK = qw(%map_probe_status %map_state %map_status %map_amperage_type) 6 => 'enabledAndNotReady', ); +%map_pdisk_state = ( + 1 => 'unknown', + 2 => 'ready', + 3 => 'online', + 4 => 'foreign', + 5 => 'offline', + 6 => 'blocked', + 7 => 'failed', + 8 => 'non-raid', + 9 => 'removed', +); + +%map_vdisk_state = ( + 1 => 'unknown', + 2 => 'online', + 3 => 'failed', + 4 => 'degraded', +); + %map_amperage_type = ( 1 => 'amperageProbeTypeIsOther', 2 => 'amperageProbeTypeIsUnknown', diff --git a/hardware/server/dell/idrac/snmp/mode/components/slot.pm b/hardware/server/dell/idrac/snmp/mode/components/slot.pm new file mode 100644 index 000000000..6635f6b07 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/slot.pm @@ -0,0 +1,66 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::slot; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + systemSlotStatus => { oid => '.1.3.6.1.4.1.674.10892.5.4.1200.10.1.5', map => \%map_status }, + systemSlotSlotExternalSlotName => { oid => '.1.3.6.1.4.1.674.10892.5.4.1200.10.1.8' }, +}; +my $oid_systemSlotTableEntry = '.1.3.6.1.4.1.674.10892.5.4.1200.10.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_systemSlotTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking slots"); + $self->{components}->{slot} = {name => 'slots', total => 0, skip => 0}; + return if ($self->check_filter(section => 'slot')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_systemSlotTableEntry}})) { + next if ($oid !~ /^$mapping->{systemSlotStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_systemSlotTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'slot', instance => $instance)); + $self->{components}->{slot}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("slot '%s' status is '%s' [instance = %s]", + $result->{systemSlotSlotExternalSlotName}, $result->{systemSlotStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default.status', section => 'slot.status', value => $result->{systemSlotStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Slot '%s' status is '%s'", $result->{systemSlotSlotExternalSlotName}, $result->{systemSlotStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/storagebattery.pm b/hardware/server/dell/idrac/snmp/mode/components/storagebattery.pm new file mode 100644 index 000000000..13d76bb0e --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/storagebattery.pm @@ -0,0 +1,66 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::storagebattery; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + batteryComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.15.1.6', map => \%map_status }, + batteryFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.15.1.20' }, +}; +my $oid_batteryTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.130.15.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_batteryTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking storage batteries"); + $self->{components}->{storagebattery} = {name => 'storage batteries', total => 0, skip => 0}; + return if ($self->check_filter(section => 'storagebattery')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_batteryTableEntry}})) { + next if ($oid !~ /^$mapping->{batteryComponentStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_batteryTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'storagebattery', instance => $instance)); + $self->{components}->{storagebattery}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("storage battery '%s' status is '%s' [instance = %s]", + $result->{batteryFQDD}, $result->{batteryComponentStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default.status', section => 'storagebattery.status', value => $result->{batteryComponentStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Storage battery '%s' status is '%s'", $result->{batteryFQDD}, $result->{batteryComponentStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/storagectrl.pm b/hardware/server/dell/idrac/snmp/mode/components/storagectrl.pm new file mode 100644 index 000000000..f25df4572 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/storagectrl.pm @@ -0,0 +1,66 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::storagectrl; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_status); + +my $mapping = { + controllerComponentStatus => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.1.1.38', map => \%map_status }, + controllerFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.130.1.1.78' }, +}; +my $oid_controllerTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.130.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_controllerTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking storage controllers"); + $self->{components}->{storagectrl} = {name => 'storage controllers', total => 0, skip => 0}; + return if ($self->check_filter(section => 'storagectrl')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_controllerTableEntry}})) { + next if ($oid !~ /^$mapping->{controllerComponentStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_controllerTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'storagectrl', instance => $instance)); + $self->{components}->{storagectrl}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("storage controller '%s' status is '%s' [instance = %s]", + $result->{controllerFQDD}, $result->{controllerComponentStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default.status', section => 'storagectrl.status', value => $result->{controllerComponentStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Storage controllers '%s' status is '%s'", $result->{controllerFQDD}, $result->{controllerComponentStatus})); + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/components/vdisk.pm b/hardware/server/dell/idrac/snmp/mode/components/vdisk.pm new file mode 100644 index 000000000..ecf397788 --- /dev/null +++ b/hardware/server/dell/idrac/snmp/mode/components/vdisk.pm @@ -0,0 +1,67 @@ +# +# Copyright 2016 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 hardware::server::dell::idrac::snmp::mode::components::vdisk; + +use strict; +use warnings; +use hardware::server::dell::idrac::snmp::mode::components::resources qw(%map_vdisk_state); + +my $mapping = { + virtualDiskState => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.140.1.1.4', map => \%map_vdisk_state }, + virtualDiskFQDD => { oid => '.1.3.6.1.4.1.674.10892.5.5.1.20.140.1.1.35' }, +}; +my $oid_virtualDiskTableEntry = '.1.3.6.1.4.1.674.10892.5.5.1.20.140.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_virtualDiskTableEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking virtual disks"); + $self->{components}->{vdisk} = {name => 'virtual disks', total => 0, skip => 0}; + return if ($self->check_filter(section => 'vdisk')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_virtualDiskTableEntry}})) { + next if ($oid !~ /^$mapping->{virtualDiskState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_virtualDiskTableEntry}, instance => $instance); + + next if ($self->check_filter(section => 'vdisk', instance => $instance)); + $self->{components}->{vdisk}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("virtual disk '%s' state is '%s' [instance = %s]", + $result->{virtualDiskFQDD}, $result->{virtualDiskState}, $instance, + )); + + my $exit = $self->get_severity(section => 'vdisk.state', value => $result->{virtualDiskState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Virtual disk '%s' state is '%s'", $result->{virtualDiskFQDD}, $result->{virtualDiskState})); + next; + } + } +} + +1; \ No newline at end of file diff --git a/hardware/server/dell/idrac/snmp/mode/hardware.pm b/hardware/server/dell/idrac/snmp/mode/hardware.pm index a1e0b9802..e5914295a 100644 --- a/hardware/server/dell/idrac/snmp/mode/hardware.pm +++ b/hardware/server/dell/idrac/snmp/mode/hardware.pm @@ -28,7 +28,6 @@ use warnings; sub set_system { my ($self, %options) = @_; - $self->{regexp_threshold_overload_check_section_option} = '^(psu|punit|temperature|voltage|amperage|systembattery|coolingunit|coolingdevice|processor|memory|pci|network)$'; $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|voltage|amperage|coolingdevice)$'; $self->{cb_hook2} = 'snmp_execute'; @@ -59,13 +58,32 @@ sub set_system { ['nonRecoverableLower', 'CRITICAL'], ['failed', 'CRITICAL'], ], + 'pdisk.state' => [ + ['unknown', 'UNKNOWN'], + ['ready', 'OK'], + ['online', 'OK'], + ['foreign', 'OK'], + ['offline', 'WARNING'], + ['blocked', 'WARNING'], + ['failed', 'CRITICAL'], + ['non-raid', 'OK'], + ['removed', 'OK'], + ], + 'vdisk.state' => [ + ['unknown', 'UNKNOWN'], + ['online', 'OK'], + ['failed', 'CRITICAL'], + ['degraded', 'WARNING'], + ], }; - - # need also: fru, systemslot, storagectrl (storage controller), storagebattery - # physicaldisk, virtualdisk + $self->{components_path} = 'hardware::server::dell::idrac::snmp::mode::components'; $self->{components_module} = ['psu', 'punit', 'temperature', 'voltage', 'amperage', - 'systembattery', 'coolingunit', 'coolingdevice', 'processor', 'memory', 'pci', 'network']; + 'systembattery', 'coolingunit', 'coolingdevice', 'processor', 'memory', 'pci', 'network', + 'slot', 'fru', 'storagectrl', 'storagebattery', 'pdisk', 'vdisk']; + + $self->{regexp_threshold_overload_check_section_option} = + '^(' . join('|', @{$self->{components_module}}). ')$'; } sub snmp_execute { @@ -94,14 +112,16 @@ __END__ =head1 MODE -Check hardware components (temperatures,...). +Check hardware components. =over 8 =item B<--component> Which component to check (Default: '.*'). -Can be: 'temperature', +Can be: 'psu', 'punit', 'temperature', 'voltage', 'amperage', +'systembattery', 'coolingunit', 'coolingdevice', 'processor', 'memory', 'pci', 'network', +'slot', 'fru', 'storagectrl', 'storagebattery', 'pdisk', 'vdisk'. =item B<--filter> @@ -121,12 +141,12 @@ Example: --threshold-overload='temperature.state,CRITICAL,^(?!(enabled)$)' =item B<--warning> -Set warning threshold for temperature (syntax: type,regexp,treshold) +Set warning threshold (syntax: type,regexp,treshold) Example: --warning='temperature,.*,30' =item B<--critical> -Set critical threshold for temperature (syntax: type,regexp,treshold) +Set critical threshold (syntax: type,regexp,treshold) Example: --critical='temperature,.*,40' =back From f053ed6ffad24106076cc47e28fab488965f11db Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Tue, 16 Feb 2016 14:38:31 +0100 Subject: [PATCH 03/20] + add modes for netbackup --- .../netbackup/local/mode/dedupstatus.pm | 267 +++++++++++ apps/backup/netbackup/local/mode/jobstatus.pm | 421 ++++++++++++++++++ .../netbackup/local/mode/listpolicies.pm | 189 ++++++++ apps/backup/netbackup/local/plugin.pm | 3 + 4 files changed, 880 insertions(+) create mode 100644 apps/backup/netbackup/local/mode/dedupstatus.pm create mode 100644 apps/backup/netbackup/local/mode/jobstatus.pm create mode 100644 apps/backup/netbackup/local/mode/listpolicies.pm diff --git a/apps/backup/netbackup/local/mode/dedupstatus.pm b/apps/backup/netbackup/local/mode/dedupstatus.pm new file mode 100644 index 000000000..c95cc81cb --- /dev/null +++ b/apps/backup/netbackup/local/mode/dedupstatus.pm @@ -0,0 +1,267 @@ +# +# Copyright 2016 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 apps::backup::netbackup::local::mode::dedupstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; + +my $instance_mode; + +sub custom_threshold_output { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = 'status : ' . $self->{result_values}->{status}; + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'pool', type => 1, cb_prefix_output => 'prefix_pool_output', message_multiple => 'All dedup status are ok' } + ]; + + $self->{maps_counters}->{pool} = [ + { label => 'status', threshold => 0, 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 => $self->can('custom_threshold_output'), + } + }, + { label => 'usage', set => { + key_values => [ { name => 'usage' }, { name => 'display' } ], + output_template => 'Use: %s %%', + perfdatas => [ + { label => 'used', value => 'usage_absolute', template => '%s', + unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "remote" => { name => 'remote' }, + "ssh-option:s@" => { name => 'ssh_option' }, + "ssh-path:s" => { name => 'ssh_path' }, + "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, + "timeout:s" => { name => 'timeout', default => 30 }, + "sudo" => { name => 'sudo' }, + "command:s" => { name => 'command', default => 'nbdevquery' }, + "command-path:s" => { name => 'command_path' }, + "command-options:s" => { name => 'command_options', default => '-listdv -U -stype PureDisk 2>&1' }, + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /up/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_pool_output { + my ($self, %options) = @_; + + return "Disk pool name '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $stdout = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); + $self->{pool} = {}; + #Disk Pool Name : NBU-MASTER-DP + #Disk Type : PureDisk + #Disk Volume Name : PureDiskVolume + #Disk Media ID : @aaaah + #Total Capacity (GB) : 9777.56 + #Free Space (GB) : 837.72 + #Use% : 91 + #Status : UP + #Flag : ReadOnWrite + #Flag : AdminUp + #Flag : InternalUp + while ($stdout =~ /^(Disk Pool Name.*?)(?=Disk Pool Name|\z)/msig) { + my $pool = $1; + + my ($display, $usage, $status); + $display = centreon::plugins::misc::trim($1) if ($pool =~ /^Disk Pool Name\s*:\s*(.*?)\n/msi); + $status = $1 if ($pool =~ /^Status\s*:\s*(.*?)\n/msi); + $usage = $1 if ($pool =~ /^Use%\s*:\s*(.*?)\n/msi); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $display !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); + next; + } + + $self->{pool}->{$display} = { display => $display, usage => $usage, status => $status }; + } + + if (scalar(keys %{$self->{pool}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No pool found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check deduplication status. + +=over 8 + +=item B<--remote> + +Execute command remotely in 'ssh'. + +=item B<--hostname> + +Hostname to query (need --remote). + +=item B<--ssh-option> + +Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). + +=item B<--ssh-path> + +Specify ssh command path (default: none) + +=item B<--ssh-command> + +Specify ssh command (default: 'ssh'). Useful to use 'plink'. + +=item B<--timeout> + +Timeout in seconds for the command (Default: 30). + +=item B<--sudo> + +Use 'sudo' to execute the command. + +=item B<--command> + +Command to get information (Default: 'nbdevquery'). +Can be changed if you have output in a file. + +=item B<--command-path> + +Command path (Default: none). + +=item B<--command-options> + +Command options (Default: '-listdv -U -stype PureDisk 2>&1'). + +=item B<--filter-name> + +Filter pool name (can be a regexp). + +=item B<--warning-usage> + +Set warning threshold in percent. + +=item B<--critical-usage> + +Set critical threshold in percent. + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{display}, %{status} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /up/i'). +Can used special variables like: %{display}, %{status} + +=back + +=cut diff --git a/apps/backup/netbackup/local/mode/jobstatus.pm b/apps/backup/netbackup/local/mode/jobstatus.pm new file mode 100644 index 000000000..287f064a8 --- /dev/null +++ b/apps/backup/netbackup/local/mode/jobstatus.pm @@ -0,0 +1,421 @@ +# +# Copyright 2016 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 apps::backup::netbackup::local::mode::jobstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::misc; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + # To exclude some OK + if (defined($instance_mode->{option_results}->{ok_status}) && $instance_mode->{option_results}->{ok_status} ne '' && + eval "$instance_mode->{option_results}->{ok_status}") { + $status = 'ok'; + } elsif (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = 'status : ' . $self->{result_values}->{status}; + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; + return 0; +} + +sub custom_long_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_long}) && $instance_mode->{option_results}->{critical_long} ne '' && + eval "$instance_mode->{option_results}->{critical_long}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_long}) && $instance_mode->{option_results}->{warning_long} ne '' && + eval "$instance_mode->{option_results}->{warning_long}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_long_output { + my ($self, %options) = @_; + my $msg = 'started since : ' . centreon::plugins::misc::change_seconds(value => $self->{result_values}->{elapsed}); + + return $msg; +} + +sub custom_long_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; + $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; + + return -11 if ($self->{result_values}->{state} !~ /queued|active/); + + return 0; +} + +my $last_status_frozen; + +sub custom_frozen_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_frozen}) && $instance_mode->{option_results}->{critical_frozen} ne '' && + eval "$instance_mode->{option_results}->{critical_frozen}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_frozen}) && $instance_mode->{option_results}->{warning_frozen} ne '' && + eval "$instance_mode->{option_results}->{warning_frozen}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + $last_status_frozen = $status; + return $status; +} + +sub custom_frozen_output { + my ($self, %options) = @_; + my $msg = 'frozen : no'; + + if (!$self->{output}->is_status(value => $last_status_frozen, compare => 'ok', litteral => 1)) { + $msg = 'frozen: yes'; + } + return $msg; +} + +sub custom_frozen_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{elapsed} = $options{new_datas}->{$self->{instance} . '_elapsed'}; + $self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_type'}; + $self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'}; + $self->{result_values}->{kb} = $options{new_datas}->{$self->{instance} . '_kb'} - $options{old_datas}->{$self->{instance} . '_kb'}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'job', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok', skipped_code => { -11 => 1 } } + ]; + + $self->{maps_counters}->{job} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' }, { name => 'type' }, { name => 'state' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'long', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' }, { name => 'state' } ], + closure_custom_calc => $self->can('custom_long_calc'), + closure_custom_output => $self->can('custom_long_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_long_threshold'), + } + }, + { label => 'frozen', threshold => 0, set => { + key_values => [ { name => 'kb', diff => 1 }, { name => 'status' }, { name => 'display' }, { name => 'elapsed' }, { name => 'type' }, { name => 'state' } ], + closure_custom_calc => $self->can('custom_frozen_calc'), + closure_custom_output => $self->can('custom_frozen_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_frozen_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "remote" => { name => 'remote' }, + "ssh-option:s@" => { name => 'ssh_option' }, + "ssh-path:s" => { name => 'ssh_path' }, + "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, + "timeout:s" => { name => 'timeout', default => 30 }, + "sudo" => { name => 'sudo' }, + "command:s" => { name => 'command', default => 'bpdbjobs' }, + "command-path:s" => { name => 'command_path' }, + "command-options:s" => { name => 'command_options', default => '-report -most_columns 2>&1' }, + "filter-policy-name:s" => { name => 'filter_policy_name' }, + "filter-end-time:s" => { name => 'filter_end_time', default => 86400 }, + "ok-status:s" => { name => 'ok_status', default => '%{status} == 0' }, + "warning-status:s" => { name => 'warning_status', default => '%{status} == 1' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} > 1' }, + "warning-long:s" => { name => 'warning_long' }, + "critical-long:s" => { name => 'critical_long' }, + "warning-frozen:s" => { name => 'warning_frozen' }, + "critical-frozen:s" => { name => 'critical_frozen', default => '%{state} =~ /active|queue/ && %{kb} == 0' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_job_output { + my ($self, %options) = @_; + + return "Job '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('ok_status', 'warning_status', 'critical_status', 'warning_long', 'critical_long', 'warning_frozen', 'critical_frozen')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +my %job_type = ( + 0 => 'backup', 1 => 'archive', 2 => 'restore', 3 => 'verify', 4 => 'duplicate', 5 => 'phase 1 or phase 2 import', + 6 => 'catalog backup', 7 => 'vault duplicate', 8 => 'label tape', 9 => 'erase tape', + 10 => 'tape request', 11 => 'clean tape', 12 => 'format tape', 13 => 'physical inventory of robotic library', + 14 => 'qualification test of drive or robotic library', 15 => 'catalog recovery', 16 => 'media contents', + 17 => 'image cleanup', 18 => 'LiveUpdate', 20 => 'Replication (Auto Image Replication)', 21 => 'Import (Auto Image Replication)', + 22 => 'backup From Snapshot', 23 => 'Replication (snap)', 24 => 'Import (snap)', 25 => 'application state capture', + 26 => 'indexing', 27 => 'index cleanup', 28 => 'Snapshot', + 29 => 'SnapIndex', 30 => 'ActivateInstantRecovery', 31 => 'DeactivateInstantRecovery', + 32 => 'ReactivateInstantRecovery', 33 => 'StopInstantRecovery', 34 => 'InstantRecovery', +); + +my %job_state = ( + 0 => 'queued and awaiting resources', + 1 => 'active', + 2 => 'requeued and awaiting resources', + 3 => 'done', 4 => 'suspended', 5 => 'incomplete', +); + +sub manage_selection { + my ($self, %options) = @_; + + $self->{cache_name} = "netbackup_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{sudo} : 'me') . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); + + my $stdout = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); + $self->{job} = {}; + my $current_time = time(); + foreach my $line (split /\n/, $stdout) { + my @values = split /,/, $line; + my ($job_id, $job_type, $job_state, $job_status, $job_pname, $job_start_time, $job_end_time, $job_kb) = + ($values[0], $values[1], $values[2], $values[3], $values[4], $values[8], $values[10], $values[14]); + + my $display = $job_pname . '/' . $job_id; + if (defined($self->{option_results}->{filter_policy_name}) && $self->{option_results}->{filter_policy_name} ne '' && + $job_pname !~ /$self->{option_results}->{filter_policy_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_end_time}) && $self->{option_results}->{filter_end_time} =~ /[0-9]+/ && + defined($job_end_time) && $job_end_time =~ /[0-9]+/ && $job_end_time < $current_time - $self->{option_results}->{filter_end_time}) { + $self->{output}->output_add(long_msg => "skipping '" . $display . "': too old.", debug => 1); + next; + } + + my $elapsed_time = $current_time - $job_start_time; + $self->{job}->{$display} = { display => $display, elapsed => $elapsed_time, + status => $job_status, state => $job_state{$job_state}, type => $job_type{$job_type}, + kb => $job_kb }; + } + + if (scalar(keys %{$self->{job}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No job found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check job status. + +=over 8 + +=item B<--remote> + +Execute command remotely in 'ssh'. + +=item B<--hostname> + +Hostname to query (need --remote). + +=item B<--ssh-option> + +Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). + +=item B<--ssh-path> + +Specify ssh command path (default: none) + +=item B<--ssh-command> + +Specify ssh command (default: 'ssh'). Useful to use 'plink'. + +=item B<--timeout> + +Timeout in seconds for the command (Default: 30). + +=item B<--sudo> + +Use 'sudo' to execute the command. + +=item B<--command> + +Command to get information (Default: 'bpdbjobs'). +Can be changed if you have output in a file. + +=item B<--command-path> + +Command path (Default: none). + +=item B<--command-options> + +Command options (Default: '-report -most_columns 2>&1'). + +=item B<--filter-policy-name> + +Filter job policy name (can be a regexp). + +=item B<--filter-end-time> + +Filter job with end time greater than current time less value in seconds (Default: 86400). + +=item B<--ok-status> + +Set ok threshold for status (Default: '%{status} == 0') +Can used special variables like: %{display}, %{status} + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{status} == 1') +Can used special variables like: %{display}, %{status}, %{type} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} > 1'). +Can used special variables like: %{display}, %{status}, %{type} + +=item B<--warning-long> + +Set warning threshold for long jobs (Default: none) +Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} + +=item B<--critical-long> + +Set critical threshold for long jobs (Default: none). +Can used special variables like: %{display}, %{status}, %{elapsed}, %{type} + +=item B<--warning-frozen> + +Set warning threshold for frozen jobs (Default: none) +Can used special variables like: %{display}, %{status}, %{elapsed}, %{type}, %{kb} + +=item B<--critical-frozen> + +Set critical threshold for frozen jobs (Default: '%{state} =~ /active|queue/ && %{kb} == 0'). +Can used special variables like: %{display}, %{status}, %{elapsed}, %{type}, %{kb} + +=back + +=cut diff --git a/apps/backup/netbackup/local/mode/listpolicies.pm b/apps/backup/netbackup/local/mode/listpolicies.pm new file mode 100644 index 000000000..4868e741e --- /dev/null +++ b/apps/backup/netbackup/local/mode/listpolicies.pm @@ -0,0 +1,189 @@ +# +# Copyright 2016 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 apps::backup::netbackup::local::mode::listpolicies; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "remote" => { name => 'remote' }, + "ssh-option:s@" => { name => 'ssh_option' }, + "ssh-path:s" => { name => 'ssh_path' }, + "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, + "timeout:s" => { name => 'timeout', default => 30 }, + "sudo" => { name => 'sudo' }, + "command:s" => { name => 'command', default => 'bppllist' }, + "command-path:s" => { name => 'command_path' }, + "command-options:s" => { name => 'command_options', default => '' }, + "command2:s" => { name => 'command2', default => 'bpplinfo %{policy_name} -L' }, + "filter-name:s" => { name => 'filter_name' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + + foreach (sort keys %{$self->{policies}}) { + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $_ !~ /$self->{option_results}->{filter_name}/i) { + $self->{output}->output_add(long_msg => "skipping policy '" . $_ . "': no type or no matching filter type"); + next; + } + + $self->{output}->output_add(long_msg => "'" . $_ . "' [active = " . $self->{policies}->{$_}->{active} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List policy:'); + $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', 'active']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach (sort keys %{$self->{policies}}) { + next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $_ !~ /$self->{option_results}->{filter_name}/i); + + $self->{output}->add_disco_entry(name => $_, + active => $self->{policies}->{$_}->{active} + ); + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $stdout = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); + $self->{policies} = {}; + my @lines = split /\n/, $stdout; + foreach my $policy_name (@lines) { + my $command2 = $self->{option_results}->{command2}; + $command2 =~ s/%{policy_name}/$policy_name/g; + my $stdout2 = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $command2); + + #Policy Type: NBU-Catalog (35) + #Active: yes + my $active = ''; + $active = $1 if ($stdout2 =~ /^Active\s*:\s+(\S+)/msi); + $self->{policies}->{$policy_name} = { active => $active }; + } +} + +1; + +__END__ + +=head1 MODE + +List policies. + +=over 8 + +=item B<--remote> + +Execute command remotely in 'ssh'. + +=item B<--hostname> + +Hostname to query (need --remote). + +=item B<--ssh-option> + +Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). + +=item B<--ssh-path> + +Specify ssh command path (default: none) + +=item B<--ssh-command> + +Specify ssh command (default: 'ssh'). Useful to use 'plink'. + +=item B<--timeout> + +Timeout in seconds for the command (Default: 30). + +=item B<--sudo> + +Use 'sudo' to execute the command. + +=item B<--command> + +Command to get information (Default: 'bppllist'). +Can be changed if you have output in a file. + +=item B<--command-path> + +Command path (Default: none). + +=item B<--command-options> + +Command options (Default: none). + +=item B<--command2> + +Command to get active policy information (Default: 'bpplinfo %{policy_name} -L'). +Can be changed if you have output in a file. + +=item B<--filter-name> + +Filter policy name (can be a regexp). + +=back + +=cut diff --git a/apps/backup/netbackup/local/plugin.pm b/apps/backup/netbackup/local/plugin.pm index a99c2b50d..66a3b91e6 100644 --- a/apps/backup/netbackup/local/plugin.pm +++ b/apps/backup/netbackup/local/plugin.pm @@ -32,8 +32,11 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( + 'dedup-status' => 'apps::backup::netbackup::local::mode::dedupstatus', 'drive-cleaning' => 'apps::backup::netbackup::local::mode::drivecleaning', 'drive-status' => 'apps::backup::netbackup::local::mode::drivestatus', + 'job-status' => 'apps::backup::netbackup::local::mode::jobstatus', + 'list-policies' => 'apps::backup::netbackup::local::mode::listpolicies', ); return $self; From 19e4f3591252228f4de556614f743e412d686e7c Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 17 Feb 2016 10:17:08 +0100 Subject: [PATCH 04/20] + Fix netbackup plugin --- .../netbackup/local/mode/dedupstatus.pm | 16 +++++++-------- .../netbackup/local/mode/drivecleaning.pm | 16 +++++++-------- .../netbackup/local/mode/drivestatus.pm | 16 +++++++-------- apps/backup/netbackup/local/mode/jobstatus.pm | 20 +++++++++---------- .../netbackup/local/mode/listpolicies.pm | 20 +++++++++---------- centreon/plugins/misc.pm | 12 ++++++++++- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/apps/backup/netbackup/local/mode/dedupstatus.pm b/apps/backup/netbackup/local/mode/dedupstatus.pm index c95cc81cb..3baa279e6 100644 --- a/apps/backup/netbackup/local/mode/dedupstatus.pm +++ b/apps/backup/netbackup/local/mode/dedupstatus.pm @@ -112,7 +112,7 @@ sub new { "sudo" => { name => 'sudo' }, "command:s" => { name => 'command', default => 'nbdevquery' }, "command-path:s" => { name => 'command_path' }, - "command-options:s" => { name => 'command_options', default => '-listdv -U -stype PureDisk 2>&1' }, + "command-options:s" => { name => 'command_options', default => '-listdv -U -stype PureDisk' }, "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /up/i' }, @@ -148,12 +148,12 @@ sub change_macros { sub manage_selection { my ($self, %options) = @_; - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => $self->{option_results}->{command_options}); + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); $self->{pool} = {}; #Disk Pool Name : NBU-MASTER-DP #Disk Type : PureDisk @@ -238,7 +238,7 @@ Command path (Default: none). =item B<--command-options> -Command options (Default: '-listdv -U -stype PureDisk 2>&1'). +Command options (Default: '-listdv -U -stype PureDisk'). =item B<--filter-name> diff --git a/apps/backup/netbackup/local/mode/drivecleaning.pm b/apps/backup/netbackup/local/mode/drivecleaning.pm index ce8f8a721..22422bbfa 100644 --- a/apps/backup/netbackup/local/mode/drivecleaning.pm +++ b/apps/backup/netbackup/local/mode/drivecleaning.pm @@ -63,7 +63,7 @@ sub new { "sudo" => { name => 'sudo' }, "command:s" => { name => 'command', default => 'tpconfig' }, "command-path:s" => { name => 'command_path' }, - "command-options:s" => { name => 'command_options', default => '-l 2>&1' }, + "command-options:s" => { name => 'command_options', default => '-l' }, "filter-name:s" => { name => 'filter_name' }, }); @@ -73,12 +73,12 @@ sub new { sub manage_selection { my ($self, %options) = @_; - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => $self->{option_results}->{command_options}); + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); $self->{drive} = { total => 0, num_cleaning => 0 }; #Drive Name Type Mount Time Frequency Last Cleaned Comment #********** **** ********** ********* **************** ******* @@ -158,7 +158,7 @@ Command path (Default: none). =item B<--command-options> -Command options (Default: '-l 2>&1'). +Command options (Default: '-l'). =item B<--filter-name> diff --git a/apps/backup/netbackup/local/mode/drivestatus.pm b/apps/backup/netbackup/local/mode/drivestatus.pm index 683f6f99f..423420ff3 100644 --- a/apps/backup/netbackup/local/mode/drivestatus.pm +++ b/apps/backup/netbackup/local/mode/drivestatus.pm @@ -103,7 +103,7 @@ sub new { "sudo" => { name => 'sudo' }, "command:s" => { name => 'command', default => 'tpconfig' }, "command-path:s" => { name => 'command_path' }, - "command-options:s" => { name => 'command_options', default => '-l 2>&1' }, + "command-options:s" => { name => 'command_options', default => '-l' }, "filter-name:s" => { name => 'filter_name' }, "warning-status:s" => { name => 'warning_status', default => '' }, "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /up/i' }, @@ -139,12 +139,12 @@ sub change_macros { sub manage_selection { my ($self, %options) = @_; - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => $self->{option_results}->{command_options}); + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); $self->{drive} = {}; #robot 0 - TLD - - - - {3,0,0,1} # drive - 0 hcart2 2 UP - IBM.ULT3580-HH5.000 {3,0,1,0} @@ -218,7 +218,7 @@ Command path (Default: none). =item B<--command-options> -Command options (Default: '-l 2>&1'). +Command options (Default: '-l'). =item B<--filter-name> diff --git a/apps/backup/netbackup/local/mode/jobstatus.pm b/apps/backup/netbackup/local/mode/jobstatus.pm index 287f064a8..a4b275d83 100644 --- a/apps/backup/netbackup/local/mode/jobstatus.pm +++ b/apps/backup/netbackup/local/mode/jobstatus.pm @@ -221,7 +221,7 @@ sub new { "sudo" => { name => 'sudo' }, "command:s" => { name => 'command', default => 'bpdbjobs' }, "command-path:s" => { name => 'command_path' }, - "command-options:s" => { name => 'command_options', default => '-report -most_columns 2>&1' }, + "command-options:s" => { name => 'command_options', default => '-report -most_columns' }, "filter-policy-name:s" => { name => 'filter_policy_name' }, "filter-end-time:s" => { name => 'filter_end_time', default => 86400 }, "ok-status:s" => { name => 'ok_status', default => '%{status} == 0' }, @@ -285,12 +285,12 @@ sub manage_selection { $self->{cache_name} = "netbackup_" . $self->{mode} . '_' . (defined($self->{option_results}->{hostname}) ? $self->{option_results}->{sudo} : 'me') . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => $self->{option_results}->{command_options}); + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); $self->{job} = {}; my $current_time = time(); foreach my $line (split /\n/, $stdout) { @@ -298,7 +298,7 @@ sub manage_selection { my ($job_id, $job_type, $job_state, $job_status, $job_pname, $job_start_time, $job_end_time, $job_kb) = ($values[0], $values[1], $values[2], $values[3], $values[4], $values[8], $values[10], $values[14]); - my $display = $job_pname . '/' . $job_id; + my $display = (defined($job_pname) ? $job_pname : '-') . '/' . $job_id; if (defined($self->{option_results}->{filter_policy_name}) && $self->{option_results}->{filter_policy_name} ne '' && $job_pname !~ /$self->{option_results}->{filter_policy_name}/) { $self->{output}->output_add(long_msg => "skipping '" . $display . "': no matching filter.", debug => 1); @@ -313,7 +313,7 @@ sub manage_selection { my $elapsed_time = $current_time - $job_start_time; $self->{job}->{$display} = { display => $display, elapsed => $elapsed_time, status => $job_status, state => $job_state{$job_state}, type => $job_type{$job_type}, - kb => $job_kb }; + kb => defined($job_kb) && $job_kb =~ /[0-9]+/ ? $job_kb : undef }; } if (scalar(keys %{$self->{job}}) <= 0) { @@ -371,7 +371,7 @@ Command path (Default: none). =item B<--command-options> -Command options (Default: '-report -most_columns 2>&1'). +Command options (Default: '-report -most_columns'). =item B<--filter-policy-name> diff --git a/apps/backup/netbackup/local/mode/listpolicies.pm b/apps/backup/netbackup/local/mode/listpolicies.pm index 4868e741e..b27e48404 100644 --- a/apps/backup/netbackup/local/mode/listpolicies.pm +++ b/apps/backup/netbackup/local/mode/listpolicies.pm @@ -100,21 +100,21 @@ sub disco_show { sub manage_selection { my ($self, %options) = @_; - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => $self->{option_results}->{command_options}); + my ($stdout) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}); $self->{policies} = {}; my @lines = split /\n/, $stdout; foreach my $policy_name (@lines) { my $command2 = $self->{option_results}->{command2}; $command2 =~ s/%{policy_name}/$policy_name/g; - my $stdout2 = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - sudo => $self->{option_results}->{sudo}, - command => $command2); + my ($stdout2) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + sudo => $self->{option_results}->{sudo}, + command => $command2); #Policy Type: NBU-Catalog (35) #Active: yes diff --git a/centreon/plugins/misc.pm b/centreon/plugins/misc.pm index 863114257..13e8377cb 100644 --- a/centreon/plugins/misc.pm +++ b/centreon/plugins/misc.pm @@ -24,6 +24,16 @@ use strict; use warnings; use utf8; +sub execute { + my (%options) = @_; + + if ($^O eq 'MSWin32') { + return windows_execute(%options, timeout => $options{options}->{timeout}); + } else { + return unix_execute(%options); + } +} + sub windows_execute { my (%options) = @_; my $result; @@ -109,7 +119,7 @@ sub windows_execute { return ($stdout, $result->{$pid}->{exitcode}); } -sub execute { +sub unix_execute { my (%options) = @_; my $cmd = ''; my $args = []; From 299fb77020bae7511ba7a61ff983a11f59b247f7 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 17 Feb 2016 11:27:08 +0100 Subject: [PATCH 05/20] + add kemp plugin --- network/kemp/snmp/mode/listvs.pm | 133 +++++++++++++++ network/kemp/snmp/mode/rsstatus.pm | 252 +++++++++++++++++++++++++++++ network/kemp/snmp/mode/vsstatus.pm | 250 ++++++++++++++++++++++++++++ network/kemp/snmp/plugin.pm | 55 +++++++ 4 files changed, 690 insertions(+) create mode 100644 network/kemp/snmp/mode/listvs.pm create mode 100644 network/kemp/snmp/mode/rsstatus.pm create mode 100644 network/kemp/snmp/mode/vsstatus.pm create mode 100644 network/kemp/snmp/plugin.pm diff --git a/network/kemp/snmp/mode/listvs.pm b/network/kemp/snmp/mode/listvs.pm new file mode 100644 index 000000000..f8629fa30 --- /dev/null +++ b/network/kemp/snmp/mode/listvs.pm @@ -0,0 +1,133 @@ +# +# Copyright 2016 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 network::kemp::snmp::mode::listvs; + +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; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + $self->{vs_id_selected} = []; + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my %map_state = ( + 1 => 'inService', + 2 => 'outOfService', + 4 => 'disabled', + 5 => 'sorry', + 6 => 'redirect', + 7 => 'errormsg', +); +my $mapping = { + vSname => { oid => '.1.3.6.1.4.1.12196.13.1.1.13' }, + vSstate => { oid => '.1.3.6.1.4.1.12196.13.1.1.14', map => \%map_state }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $mapping->{vSname}->{oid} }, { oid => $mapping->{vSstate}->{oid} } ], + nothing_quit => 1, return_type => 1); + foreach my $oid (keys %{$self->{results}}) { + next if ($oid !~ /^$mapping->{vSname}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vSname} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vSname} . "': no matching filter.", debug => 1); + next; + } + + push @{$self->{vs_id_selected}}, $instance; + } +} + +sub run { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + $self->manage_selection(); + foreach my $instance (sort @{$self->{vs_id_selected}}) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + $self->{output}->output_add(long_msg => "'" . $result->{vSname} . "' [state = " . $result->{vSstate} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Virtual Servers:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(disco => 1); + foreach my $instance (sort @{$self->{vs_id_selected}}) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + $self->{output}->add_disco_entry(name => $result->{vSname}, state => $result->{vSstate}); + } +} + +1; + +__END__ + +=head1 MODE + +List virtual servers. + +=over 8 + +=item B<--filter-name> + +Set the virtual server name. + +=back + +=cut + \ No newline at end of file diff --git a/network/kemp/snmp/mode/rsstatus.pm b/network/kemp/snmp/mode/rsstatus.pm new file mode 100644 index 000000000..703fe851d --- /dev/null +++ b/network/kemp/snmp/mode/rsstatus.pm @@ -0,0 +1,252 @@ +# +# Copyright 2016 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 network::kemp::snmp::mode::rsstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = '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; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'rs', type => 1, cb_prefix_output => 'prefix_rs_output', message_multiple => 'All real servers are ok' } + ]; + + $self->{maps_counters}->{rs} = [ + { label => 'status', threshold => 0, 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 => $self->can('custom_status_threshold'), + } + }, + { label => 'active', set => { + key_values => [ { name => 'rSActiveConns' }, { name => 'display' } ], + output_template => 'Active connections : %s', + perfdatas => [ + { label => 'active', value => 'rSActiveConns_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'in-traffic', set => { + key_values => [ { name => 'rSInBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic In : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_in', value => 'rSInBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'out-traffic', set => { + key_values => [ { name => 'rSOutBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic Out : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_out', value => 'rSOutBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /inService|disabled/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_rs_output { + my ($self, %options) = @_; + + return "Real server '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +my %map_state = ( + 1 => 'inService', + 2 => 'outOfService', + 4 => 'disabled', +); +my $mapping = { + rSvsidx => { oid => '.1.3.6.1.4.1.12196.13.2.1.1' }, + rSip => { oid => '.1.3.6.1.4.1.12196.13.2.1.2' }, + rSport => { oid => '.1.3.6.1.4.1.12196.13.2.1.3' }, + rSstate => { oid => '.1.3.6.1.4.1.12196.13.2.1.8', map => \%map_state }, + rSInBytes => { oid => '.1.3.6.1.4.1.12196.13.2.1.15' }, + rSOutBytes => { oid => '.1.3.6.1.4.1.12196.13.2.1.16' }, + rSActiveConns => { oid => '.1.3.6.1.4.1.12196.13.2.1.17' }, +}; + +my $oid_rsEntry = '.1.3.6.1.4.1.12196.13.2.1'; +my $oid_vSname = '.1.3.6.1.4.1.12196.13.1.1.13'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{rs} = {}; + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_rsEntry }, { oid => $oid_vSname } ], + nothing_quit => 1); + + + foreach my $oid (keys %{$snmp_result->{$oid_rsEntry}}) { + next if ($oid !~ /^$mapping->{rSstate}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_rsEntry}, instance => $instance); + my $vs_name = $snmp_result->{$oid_vSname}->{$oid_vSname . '.' . $result->{rSvsidx}}; + + my $display_name = $vs_name . '/' . $result->{rSip} . ':' . $result->{rSport}; + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $display_name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $display_name . "': no matching filter.", debug => 1); + next; + } + + $self->{rs}->{$instance} = { display => $display_name, + status => $result->{rSstate}, + rSInBytes => $result->{rSInBytes} * 8, rSOutBytes => $result->{rSOutBytes} * 8, rSActiveConns => $result->{rSActiveConns} }; + } + + if (scalar(keys %{$self->{rs}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No real server found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "kemp_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check real server status. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^status$' + +=item B<--filter-name> + +Filter real server name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /inService|disabled/i'). +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'active', 'in-traffic' (b/s), 'out-traffic' (b/s). + +=item B<--critical-*> + +Threshold critical. +Can be: 'active', 'in-traffic' (b/s), 'out-traffic' (b/s). + +=back + +=cut diff --git a/network/kemp/snmp/mode/vsstatus.pm b/network/kemp/snmp/mode/vsstatus.pm new file mode 100644 index 000000000..3f73101dc --- /dev/null +++ b/network/kemp/snmp/mode/vsstatus.pm @@ -0,0 +1,250 @@ +# +# Copyright 2016 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 network::kemp::snmp::mode::vsstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = '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; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vs', type => 1, cb_prefix_output => 'prefix_vs_output', message_multiple => 'All virtual servers are ok' } + ]; + + $self->{maps_counters}->{vs} = [ + { label => 'status', threshold => 0, 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 => $self->can('custom_status_threshold'), + } + }, + { label => 'active', set => { + key_values => [ { name => 'vSActivConns' }, { name => 'display' } ], + output_template => 'Active connections : %s', + perfdatas => [ + { label => 'active', value => 'vSActivConns_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'in-traffic', set => { + key_values => [ { name => 'vSInBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic In : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_in', value => 'vSInBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'out-traffic', set => { + key_values => [ { name => 'vSOutBytes', diff => 1 }, { name => 'display' } ], + output_template => 'Traffic Out : %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_out', value => 'vSOutBytes_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} !~ /inService|disabled|redirect/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_vs_output { + my ($self, %options) = @_; + + return "Virtual server '" . $options{instance_value}->{display} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +my %map_state = ( + 1 => 'inService', + 2 => 'outOfService', + 4 => 'disabled', + 5 => 'sorry', + 6 => 'redirect', + 7 => 'errormsg', +); +my $mapping = { + vSname => { oid => '.1.3.6.1.4.1.12196.13.1.1.13' }, + vSstate => { oid => '.1.3.6.1.4.1.12196.13.1.1.14', map => \%map_state }, + vSInBytes => { oid => '.1.3.6.1.4.1.12196.13.1.1.19' }, + vSOutBytes => { oid => '.1.3.6.1.4.1.12196.13.1.1.20' }, + vSActivConns => { oid => '.1.3.6.1.4.1.12196.13.1.1.21' }, +}; + +my $oid_vsEntry = '.1.3.6.1.4.1.12196.13.1.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vs} = {}; + my $snmp_result = $options{snmp}->get_table(oid => $oid_vsEntry, + nothing_quit => 1); + + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vSstate}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vSname} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vSname} . "': no matching filter.", debug => 1); + next; + } + + $self->{vs}->{$instance} = { display => $result->{vSname}, + status => $result->{vSstate}, + vSInBytes => $result->{vSInBytes} * 8, vSOutBytes => $result->{vSOutBytes} * 8, vSActivConns => $result->{vSActivConns} }; + } + + if (scalar(keys %{$self->{vs}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No virtual server found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = "kemp_" . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check virtual server status. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^status$' + +=item B<--filter-name> + +Filter virtual server name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{status}, %{display} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /inService|disabled|redirect/i'). +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> + +Threshold warning. +Can be: 'active', 'in-traffic' (b/s), 'out-traffic' (b/s). + +=item B<--critical-*> + +Threshold critical. +Can be: 'active', 'in-traffic' (b/s), 'out-traffic' (b/s). + +=back + +=cut diff --git a/network/kemp/snmp/plugin.pm b/network/kemp/snmp/plugin.pm new file mode 100644 index 000000000..eac98d26a --- /dev/null +++ b/network/kemp/snmp/plugin.pm @@ -0,0 +1,55 @@ +# +# Copyright 2016 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 network::kemp::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'cpu-detailed' => 'snmp_standard::mode::cpudetailed', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'load' => 'snmp_standard::mode::loadaverage', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'list-vs' => 'network::kemp::snmp::mode::listvs', + 'memory' => 'snmp_standard::mode::memory', + 'rs-status' => 'network::kemp::snmp::mode::rsstatus', + 'vs-status' => 'network::kemp::snmp::mode::vsstatus', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Kemp equipments in SNMP. + +=cut From 61c7ea43abc7dd6ac5580a3789754ac74560eff1 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 17 Feb 2016 15:12:15 +0100 Subject: [PATCH 06/20] + add ha-status mode for kemp --- network/kemp/snmp/mode/hastatus.pm | 210 +++++++++++++++++++++++++++++ network/kemp/snmp/plugin.pm | 1 + 2 files changed, 211 insertions(+) create mode 100644 network/kemp/snmp/mode/hastatus.pm diff --git a/network/kemp/snmp/mode/hastatus.pm b/network/kemp/snmp/mode/hastatus.pm new file mode 100644 index 000000000..15ef72920 --- /dev/null +++ b/network/kemp/snmp/mode/hastatus.pm @@ -0,0 +1,210 @@ +# +# Copyright 2016 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 network::kemp::snmp::mode::hastatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{'critical_' . $self->{result_values}->{label}}) && $instance_mode->{option_results}->{'critical_' . $self->{result_values}->{label}} ne '' && + eval "$instance_mode->{option_results}->{\"critical_\" . $self->{result_values}->{label}}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{'warning_' . $self->{result_values}->{label}}) && $instance_mode->{option_results}->{'warning_' . $self->{result_values}->{label}} ne '' && + eval "$instance_mode->{option_results}->{\"warning_\" . $self->{result_values}->{label}}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_hastatus_output { + my ($self, %options) = @_; + + my $msg = 'HA status : ' . $self->{result_values}->{status}; + return $msg; +} + +sub custom_syncstatus_output { + my ($self, %options) = @_; + + my $msg = 'Synchronization l4 status : ' . $self->{result_values}->{status}; + return $msg; +} + +sub custom_hastatus_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_hAstate'}; + $self->{result_values}->{label} = 'ha_status'; + return 0; +} + +sub custom_syncstatus_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_daemonState'}; + $self->{result_values}->{label} = 'sync_status'; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, message_separator => ' - ' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'ha-status', threshold => 0, set => { + key_values => [ { name => 'hAstate' } ], + closure_custom_calc => $self->can('custom_hastatus_calc'), + closure_custom_output => $self->can('custom_hastatus_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'sync-status', threshold => 0, set => { + key_values => [ { name => 'daemonState' } ], + closure_custom_calc => $self->can('custom_syncstatus_calc'), + closure_custom_output => $self->can('custom_syncstatus_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning-ha-status:s" => { name => 'warning_ha_status', default => '' }, + "critical-ha-status:s" => { name => 'critical_ha_status', default => '' }, + "warning-sync-status:s" => { name => 'warning_sync_status', default => '' }, + "critical-sync-status:s" => { name => 'critical_sync_status', default => '' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_ha_status', 'critical_ha_status', 'warning_sync_status', 'critical_sync_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +my %map_daemon_state = ( + 0 => 'none', + 1 => 'master', + 2 => 'backup', +); +my %map_ha_state = ( + 0 => 'none', + 1 => 'master', + 2 => 'standby', + 3 => 'passive', +); +my $mapping = { + daemonState => { oid => '.1.3.6.1.4.1.12196.13.0.7', map => \%map_daemon_state }, + hAstate => { oid => '.1.3.6.1.4.1.12196.13.0.9', map => \%map_ha_state }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{vs} = {}; + my $snmp_result = $options{snmp}->get_leef(oids => [ $mapping->{daemonState}->{oid} . '.0', $mapping->{hAstate}->{oid} . '.0' ], + nothing_quit => 1); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => '0'); + + $self->{global} = { %$result }; +} + +1; + +__END__ + +=head1 MODE + +Check ha status. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^ha-status$' + +=item B<--warning-ha-status> + +Set warning threshold for status (Default: none). +Can used special variables like: %{status}, %{display} + +=item B<--critical-ha-status> + +Set critical threshold for status (Default: none). +Can used special variables like: %{status}, %{display} + +=item B<--warning-sync-status> + +Set warning threshold for status (Default: none). +Can used special variables like: %{status}, %{display} + +=item B<--critical-sync-status> + +Set critical threshold for status (Default: none). +Can used special variables like: %{status}, %{display} + +=back + +=cut diff --git a/network/kemp/snmp/plugin.pm b/network/kemp/snmp/plugin.pm index eac98d26a..3e6367ce3 100644 --- a/network/kemp/snmp/plugin.pm +++ b/network/kemp/snmp/plugin.pm @@ -36,6 +36,7 @@ sub new { 'load' => 'snmp_standard::mode::loadaverage', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', 'list-vs' => 'network::kemp::snmp::mode::listvs', + 'ha-status' => 'network::kemp::snmp::mode::hastatus', 'memory' => 'snmp_standard::mode::memory', 'rs-status' => 'network::kemp::snmp::mode::rsstatus', 'vs-status' => 'network::kemp::snmp::mode::vsstatus', From 9462b301ea46f0d4d547a353e1f0adacc8716dd3 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 17 Feb 2016 17:13:04 +0100 Subject: [PATCH 07/20] + update version and changelog --- centreon/plugins/script.pm | 2 +- changelog | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/centreon/plugins/script.pm b/centreon/plugins/script.pm index 61f97788c..ed90ea232 100644 --- a/centreon/plugins/script.pm +++ b/centreon/plugins/script.pm @@ -31,7 +31,7 @@ use Pod::Find qw(pod_where); my %handlers = (DIE => {}); -my $global_version = 20160122; +my $global_version = 20160217; sub new { my $class = shift; diff --git a/changelog b/changelog index 64f50d1de..3bc5034ab 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,20 @@ +2016-02-17 Quentin Garnier + * Plugin added: to check Kemp + * Plugin added: to check Netbackup + * Plugin added: to check Ucopia Wireless Controller + * Plugin added: to check Emerson Liebert PDU + * Plugin added: to check Microsoft Lync 2013 + * Plugin added: to check TemPERHum sensors + * Mode added: [mysql] 'table-size' + * Mode added: [centreon] 'count-services' + * Mode added: [iDrac] 'hardware' (for iDrac 8) + * Enhancement: [xtremio] hardened code + * Enhancement: [cisco asa]{sessions} better metrics (#315) + * Enhancement: [freebsd]{memory} More real values + * Fix: [oracle]{tablespace-usage} Usage more than 100% + * Fix: [clariion]{disks} Last disks was missing + * Fix: [mssql]{failed-jobs} wrong thresholds + 2016-01-22 Quentin Garnier * Plugin added: Add a plugin to check Juniper Trapeze in SNMP * Plugin added: Add a plugin to check Dell ML6000 in SNMP From f931e836f14e16800cfaf4ad418c4d2cf8040e2e Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 18 Feb 2016 15:06:54 +0100 Subject: [PATCH 08/20] + fix kemp warn message with snmpv1 --- network/kemp/snmp/mode/rsstatus.pm | 4 +++- network/kemp/snmp/mode/vsstatus.pm | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/network/kemp/snmp/mode/rsstatus.pm b/network/kemp/snmp/mode/rsstatus.pm index 703fe851d..f221a1001 100644 --- a/network/kemp/snmp/mode/rsstatus.pm +++ b/network/kemp/snmp/mode/rsstatus.pm @@ -196,7 +196,9 @@ sub manage_selection { $self->{rs}->{$instance} = { display => $display_name, status => $result->{rSstate}, - rSInBytes => $result->{rSInBytes} * 8, rSOutBytes => $result->{rSOutBytes} * 8, rSActiveConns => $result->{rSActiveConns} }; + rSInBytes => defined($result->{rSInBytes}) ? $result->{rSInBytes} * 8 : undef, + rSOutBytes => defined($result->{rSOutBytes}) ? $result->{rSOutBytes} * 8 : undef, + rSActiveConns => $result->{rSActiveConns} }; } if (scalar(keys %{$self->{rs}}) <= 0) { diff --git a/network/kemp/snmp/mode/vsstatus.pm b/network/kemp/snmp/mode/vsstatus.pm index 3f73101dc..95b406aab 100644 --- a/network/kemp/snmp/mode/vsstatus.pm +++ b/network/kemp/snmp/mode/vsstatus.pm @@ -194,7 +194,9 @@ sub manage_selection { $self->{vs}->{$instance} = { display => $result->{vSname}, status => $result->{vSstate}, - vSInBytes => $result->{vSInBytes} * 8, vSOutBytes => $result->{vSOutBytes} * 8, vSActivConns => $result->{vSActivConns} }; + vSInBytes => defined($result->{vSInBytes}) ? $result->{vSInBytes} * 8 : undef, + vSOutBytes => defined($result->{vSOutBytes}) ? $result->{vSOutBytes} * 8 : undef, + vSActivConns => $result->{vSActivConns} }; } if (scalar(keys %{$self->{vs}}) <= 0) { From 0cf9a0160bd9ebdbefcdf91316d94b447d168741 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Fri, 19 Feb 2016 15:27:58 +0100 Subject: [PATCH 09/20] + Enhance to have mode display --- centreon/plugins/options.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/centreon/plugins/options.pm b/centreon/plugins/options.pm index 33e8ce3ce..bbbc59b03 100644 --- a/centreon/plugins/options.pm +++ b/centreon/plugins/options.pm @@ -79,9 +79,10 @@ sub display_help { { local *STDOUT; open STDOUT, '>', \$stdout; - pod2usage(-exitval => 'NOEXIT', -input => pod_where({-inc => 1}, $_->{package}), + my $where = pod_where({-inc => 1}, $_->{package}); + pod2usage(-exitval => 'NOEXIT', -input => $where, -verbose => 99, - -sections => $_->{sections}); + -sections => $_->{sections}) if (defined($where)); } $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); From 952c293c4446e688150144bcb012bed5e7c3eaaf Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sat, 20 Feb 2016 16:19:57 +0100 Subject: [PATCH 10/20] + add some code in core to display help with fatpacker build --- .../plugins/alternative/FatPackerOptions.pm | 64 +++++++++++++++++++ centreon/plugins/script.pm | 22 ++++++- 2 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 centreon/plugins/alternative/FatPackerOptions.pm diff --git a/centreon/plugins/alternative/FatPackerOptions.pm b/centreon/plugins/alternative/FatPackerOptions.pm new file mode 100644 index 000000000..c8a6b0a67 --- /dev/null +++ b/centreon/plugins/alternative/FatPackerOptions.pm @@ -0,0 +1,64 @@ +# +# Copyright 2016 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::plugins::alternative::FatPackerOptions; + +use base qw(centreon::plugins::options); + +use strict; +use warnings; +use Pod::Usage; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + return $self; +} + +sub display_help { + my ($self, %options) = @_; + + my $stdout; + foreach (@{$self->{pod_package}}) { + + { + my $pp = $_->{package} . ".pm"; + $pp =~ s{::}{/}g; + my $content_class = $INC{$pp}->{$pp}; + open my $str_fh, '<', \$content_class; + + local *STDOUT; + open STDOUT, '>', \$stdout; + pod2usage(-exitval => 'NOEXIT', -input => $str_fh, + -verbose => 99, + -sections => $_->{sections}); + + close $str_fh; + } + + $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); + } +} + +1; + +__END__ diff --git a/centreon/plugins/script.pm b/centreon/plugins/script.pm index ed90ea232..81e81dfd8 100644 --- a/centreon/plugins/script.pm +++ b/centreon/plugins/script.pm @@ -22,7 +22,6 @@ package centreon::plugins::script; use strict; use warnings; -use centreon::plugins::options; use centreon::plugins::output; use centreon::plugins::misc; use FindBin; @@ -32,6 +31,7 @@ use Pod::Find qw(pod_where); my %handlers = (DIE => {}); my $global_version = 20160217; +my $alternative_fatpacker = 0; sub new { my $class = shift; @@ -84,7 +84,13 @@ sub get_plugin { ###### # Need to load global 'Output' and 'Options' ###### - $self->{options} = centreon::plugins::options->new(); + if ($alternative_fatpacker == 0) { + require centreon::plugins::options; + $self->{options} = centreon::plugins::options->new(); + } else { + require centreon::plugins::alternative::FatPackerOptions; + $self->{options} = centreon::plugins::alternative::FatPackerOptions->new(); + } $self->{output} = centreon::plugins::output->new(options => $self->{options}); $self->{options}->set_output(output => $self->{output}); @@ -122,7 +128,17 @@ sub display_local_help { if ($self->{help}) { local *STDOUT; open STDOUT, '>', \$stdout; - pod2usage(-exitval => "NOEXIT", -input => pod_where({-inc => 1}, __PACKAGE__)); + + if ($alternative_fatpacker == 0) { + pod2usage(-exitval => "NOEXIT", -input => pod_where({-inc => 1}, __PACKAGE__)); + } else { + my $pp = __PACKAGE__ . ".pm"; + $pp =~ s{::}{/}g; + my $content_class = $INC{$pp}->{$pp}; + open my $str_fh, '<', \$content_class; + pod2usage(-exitval => "NOEXIT", -input => $str_fh); + close $str_fh; + } } $self->{output}->add_option_msg(long_msg => $stdout) if (defined($stdout)); From 81594909993f4876189731ef4594b851a54339e5 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sat, 20 Feb 2016 16:48:33 +0100 Subject: [PATCH 11/20] + update changelog --- centreon/plugins/script.pm | 2 +- changelog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/centreon/plugins/script.pm b/centreon/plugins/script.pm index 81e81dfd8..babc300a8 100644 --- a/centreon/plugins/script.pm +++ b/centreon/plugins/script.pm @@ -30,7 +30,7 @@ use Pod::Find qw(pod_where); my %handlers = (DIE => {}); -my $global_version = 20160217; +my $global_version = 20160220; my $alternative_fatpacker = 0; sub new { diff --git a/changelog b/changelog index 3bc5034ab..8d5e2bccf 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,6 @@ +2016-02-20 Quentin Garnier + * Add a class for FatPacker system + 2016-02-17 Quentin Garnier * Plugin added: to check Kemp * Plugin added: to check Netbackup From f7ebb59e7fdbe427b902787275fe8a60f52b3103 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 22 Feb 2016 12:47:15 +0100 Subject: [PATCH 12/20] + Fix #342 --- .../ibm/bladecenter/snmp/mode/components/blade.pm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hardware/server/ibm/bladecenter/snmp/mode/components/blade.pm b/hardware/server/ibm/bladecenter/snmp/mode/components/blade.pm index c48e4007b..add7e90c6 100644 --- a/hardware/server/ibm/bladecenter/snmp/mode/components/blade.pm +++ b/hardware/server/ibm/bladecenter/snmp/mode/components/blade.pm @@ -82,20 +82,23 @@ sub check { next; } $self->{components}->{blade}->{total}++; + $result->{bladeName} = defined($result->{bladeName}) ? $result->{bladeName} : '-'; if ($result->{bladePowerState} =~ /off/) { - $self->{output}->output_add(long_msg => sprintf("Blade '%s' power state is %s", - $result->{bladeId}, $result->{bladePowerState})); + $self->{output}->output_add(long_msg => sprintf("Blade '%s/%s' power state is %s", + $result->{bladeName}, $result->{bladeId}, $result->{bladePowerState}, + )); next; } - $self->{output}->output_add(long_msg => sprintf("Blade '%s' state is %s [power state: %s]", - $result->{bladeId}, $result->{bladeHealthState}, $result->{bladePowerState})); + $self->{output}->output_add(long_msg => sprintf("Blade '%s/%s' state is %s [power state: %s]", + $result->{bladeName}, $result->{bladeId}, $result->{bladeHealthState}, $result->{bladePowerState}, + )); my $exit = $self->get_severity(section => 'blade', value => $result->{bladeHealthState}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Blade '%s' state is %s", - $result->{bladeId}, $result->{bladeHealthState})); + short_msg => sprintf("Blade '%s/%s' state is %s", + $result->{bladeName}, $result->{bladeId}, $result->{bladeHealthState})); } } } From 1cdd63c3cb7c15edf2cd42c9d2c4dc9ffda2f050 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 28 Feb 2016 15:56:51 +0100 Subject: [PATCH 13/20] + Fix #347 --- .../akcp/snmp/mode/components/humidity.pm | 106 +++++++++++++++ .../akcp/snmp/mode/components/resources.pm | 62 +++++++++ .../akcp/snmp/mode/components/serial.pm | 72 +++++++++++ .../akcp/snmp/mode/components/switch.pm | 72 +++++++++++ .../akcp/snmp/mode/components/temperature.pm | 107 ++++++++++++++++ hardware/sensors/akcp/snmp/mode/sensors.pm | 121 ++++++++++++++++++ hardware/sensors/akcp/snmp/plugin.pm | 48 +++++++ .../idrac/snmp/mode/components/amperage.pm | 2 +- .../snmp/mode/components/coolingdevice.pm | 2 +- .../idrac/snmp/mode/components/temperature.pm | 2 +- .../idrac/snmp/mode/components/voltage.pm | 2 +- 11 files changed, 592 insertions(+), 4 deletions(-) create mode 100644 hardware/sensors/akcp/snmp/mode/components/humidity.pm create mode 100644 hardware/sensors/akcp/snmp/mode/components/resources.pm create mode 100644 hardware/sensors/akcp/snmp/mode/components/serial.pm create mode 100644 hardware/sensors/akcp/snmp/mode/components/switch.pm create mode 100644 hardware/sensors/akcp/snmp/mode/components/temperature.pm create mode 100644 hardware/sensors/akcp/snmp/mode/sensors.pm create mode 100644 hardware/sensors/akcp/snmp/plugin.pm diff --git a/hardware/sensors/akcp/snmp/mode/components/humidity.pm b/hardware/sensors/akcp/snmp/mode/components/humidity.pm new file mode 100644 index 000000000..27d0376b6 --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/components/humidity.pm @@ -0,0 +1,106 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::components::humidity; + +use strict; +use warnings; +use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default1_status %map_online); + +my $mapping = { + hhmsSensorArrayHumidityDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.1' }, + hhmsSensorArrayHumidityPercent => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.3' }, + hhmsSensorArrayHumidityStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.4', map => \%map_default1_status }, + hhmsSensorArrayHumidityOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.5', map => \%map_online }, + hhmsSensorArrayHumidityHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.7' }, + hhmsSensorArrayHumidityHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.8' }, + hhmsSensorArrayHumidityLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.9' }, + hhmsSensorArrayHumidityLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.17.1.10' }, +}; +my $oid_hhmsSensorArrayHumidityEntry = '.1.3.6.1.4.1.3854.1.2.2.1.17.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_hhmsSensorArrayHumidityEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking humidities"); + $self->{components}->{humidity} = {name => 'humidities', total => 0, skip => 0}; + return if ($self->check_filter(section => 'humidity')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArrayHumidityEntry}})) { + next if ($oid !~ /^$mapping->{hhmsSensorArrayHumidityOnline}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArrayHumidityEntry}, instance => $instance); + + next if ($self->check_filter(section => 'humidity', instance => $instance)); + if ($result->{hhmsSensorArrayHumidityOnline} eq 'offline') { + $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArrayHumidityDescription})); + next; + } + $self->{components}->{humidity}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("humidity '%s' status is '%s' [instance = %s] [value = %s]", + $result->{hhmsSensorArrayHumidityDescription}, $result->{hhmsSensorArrayHumidityStatus}, $instance, + $result->{hhmsSensorArrayHumidityPercent})); + + my $exit = $self->get_severity(label => 'default1', section => 'humidity', value => $result->{hhmsSensorArrayHumidityStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Humdity '%s' status is '%s'", $result->{hhmsSensorArrayHumidityDescription}, $result->{hhmsSensorArrayHumidityStatus})); + next; + } + + my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'humidity', instance => $instance, value => $result->{hhmsSensorArrayHumidityPercent}); + if ($checked == 0) { + $result->{hhmsSensorArrayHumidityLowWarning} = (defined($result->{hhmsSensorArrayHumidityLowWarning}) && $result->{hhmsSensorArrayHumidityLowWarning} =~ /[0-9]/) ? + $result->{hhmsSensorArrayHumidityLowWarning} : ''; + $result->{hhmsSensorArrayHumidityLowCritical} = (defined($result->{hhmsSensorArrayHumidityLowCritical}) && $result->{hhmsSensorArrayHumidityLowCritical} =~ /[0-9]/) ? + $result->{hhmsSensorArrayHumidityLowCritical} : ''; + $result->{hhmsSensorArrayHumidityHighWarning} = (defined($result->{hhmsSensorArrayHumidityHighWarning}) && $result->{hhmsSensorArrayHumidityHighWarning} =~ /[0-9]/) ? + $result->{hhmsSensorArrayHumidityHighWarning} : ''; + $result->{hhmsSensorArrayHumidityHighCritical} = (defined($result->{hhmsSensorArrayHumidityHighCritical}) && $result->{hhmsSensorArrayHumidityHighCritical} =~ /[0-9]/) ? + $result->{hhmsSensorArrayHumidityHighCritical} : ''; + my $warn_th = $result->{hhmsSensorArrayHumidityLowWarning} . ':' . $result->{hhmsSensorArrayHumidityHighWarning}; + my $crit_th = $result->{hhmsSensorArrayHumidityLowCritical} . ':' . $result->{hhmsSensorArrayHumidityHighCritical}; + $self->{perfdata}->threshold_validate(label => 'warning-humidity-instance-' . $instance, value => $warn_th); + $self->{perfdata}->threshold_validate(label => 'critical-humidity-instance-' . $instance, value => $crit_th); + + $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-humidity-instance-' . $instance); + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-humidity-instance-' . $instance); + } + + if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit2, + short_msg => sprintf("Humdity '%s' is %s %%", $result->{hhmsSensorArrayHumidityDescription}, $result->{hhmsSensorArrayHumidityPercent})); + } + $self->{output}->perfdata_add(label => 'humidity_' . $result->{hhmsSensorArrayHumidityDescription}, unit => '%', + value => $result->{hhmsSensorArrayHumidityPercent}, + warning => $warn, + critical => $crit, + min => 0, max => 100); + } +} + +1; \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/mode/components/resources.pm b/hardware/sensors/akcp/snmp/mode/components/resources.pm new file mode 100644 index 000000000..413abeb9e --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/components/resources.pm @@ -0,0 +1,62 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::components::resources; + +use strict; +use warnings; +use Exporter; + +our %map_default1_status; +our %map_default2_status; +our %map_online; +our %map_degree_type; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(%map_default1_status %map_default2_status %map_online %map_degree_type); + +%map_default1_status = ( + 1 => 'noStatus', + 2 => 'normal', + 3 => 'highWarning', + 4 => 'highCritical', + 5 => 'lowWarning', + 6 => 'lowCritical', + 7 => 'sensorError', +); + +%map_default2_status = ( + 1 => 'noStatus', + 2 => 'normal', + 4 => 'critical', + 7 => 'sensorError', +); + +%map_online = ( + 1 => 'online', + 2 => 'offline', +); + +%map_degree_type = ( + 0 => 'F', + 1 => 'C', +); + +1; \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/mode/components/serial.pm b/hardware/sensors/akcp/snmp/mode/components/serial.pm new file mode 100644 index 000000000..0b524dde0 --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/components/serial.pm @@ -0,0 +1,72 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::components::serial; + +use strict; +use warnings; +use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default2_status %map_online); + +my $mapping = { + hhmsSensorArraySerialDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.1' }, + hhmsSensorArraySerialStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.3', map => \%map_default2_status }, + hhmsSensorArraySerialOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.19.1.4', map => \%map_online }, +}; +my $oid_hhmsSensorArraySwitchEntry = '.1.3.6.1.4.1.3854.1.2.2.1.18.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_hhmsSensorArraySwitchEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking serials"); + $self->{components}->{serial} = {name => 'serials', total => 0, skip => 0}; + return if ($self->check_filter(section => 'serial')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArraySwitchEntry}})) { + next if ($oid !~ /^$mapping->{hhmsSensorArraySerialOnline}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArraySwitchEntry}, instance => $instance); + + next if ($self->check_filter(section => 'serial', instance => $instance)); + if ($result->{hhmsSensorArraySerialOnline} eq 'offline') { + $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArraySerialDescription})); + next; + } + $self->{components}->{serial}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("serial '%s' status is '%s' [instance = %s]", + $result->{hhmsSensorArraySerialDescription}, $result->{hhmsSensorArraySerialStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default2', section => 'serial', value => $result->{hhmsSensorArraySerialStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Serial '%s' status is '%s'", $result->{hhmsSensorArraySerialDescription}, $result->{hhmsSensorArraySerialStatus})); + next; + } + } +} + +1; \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/mode/components/switch.pm b/hardware/sensors/akcp/snmp/mode/components/switch.pm new file mode 100644 index 000000000..d3b3f93dd --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/components/switch.pm @@ -0,0 +1,72 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::components::switch; + +use strict; +use warnings; +use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default2_status %map_online); + +my $mapping = { + hhmsSensorArraySwitchDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.1' }, + hhmsSensorArraySwitchStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.3', map => \%map_default2_status }, + hhmsSensorArraySwitchOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.18.1.4', map => \%map_online }, +}; +my $oid_hhmsSensorArraySwitchEntry = '.1.3.6.1.4.1.3854.1.2.2.1.18.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_hhmsSensorArraySwitchEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking switches"); + $self->{components}->{switch} = {name => 'switches', total => 0, skip => 0}; + return if ($self->check_filter(section => 'switch')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArraySwitchEntry}})) { + next if ($oid !~ /^$mapping->{hhmsSensorArraySwitchOnline}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArraySwitchEntry}, instance => $instance); + + next if ($self->check_filter(section => 'switch', instance => $instance)); + if ($result->{hhmsSensorArraySwitchOnline} eq 'offline') { + $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArraySwitchDescription})); + next; + } + $self->{components}->{switch}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("switch '%s' status is '%s' [instance = %s]", + $result->{hhmsSensorArraySwitchDescription}, $result->{hhmsSensorArraySwitchStatus}, $instance, + )); + + my $exit = $self->get_severity(label => 'default2', section => 'switch', value => $result->{hhmsSensorArraySwitchStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Switch '%s' status is '%s'", $result->{hhmsSensorArraySwitchDescription}, $result->{hhmsSensorArraySwitchStatus})); + next; + } + } +} + +1; \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/mode/components/temperature.pm b/hardware/sensors/akcp/snmp/mode/components/temperature.pm new file mode 100644 index 000000000..20a4894ba --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/components/temperature.pm @@ -0,0 +1,107 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::components::temperature; + +use strict; +use warnings; +use hardware::sensors::akcp::snmp::mode::components::resources qw(%map_default1_status %map_online %map_degree_type); + +my $mapping = { + hhmsSensorArrayTempDescription => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.1' }, + hhmsSensorArrayTempDegree => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.3' }, + hhmsSensorArrayTempStatus => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.4', map => \%map_default1_status }, + hhmsSensorArrayTempOnline => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.5', map => \%map_online }, + hhmsSensorArrayTempHighWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.7' }, + hhmsSensorArrayTempHighCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.8' }, + hhmsSensorArrayTempLowWarning => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.9' }, + hhmsSensorArrayTempLowCritical => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.10' }, + hhmsSensorArrayTempDegreeType => { oid => '.1.3.6.1.4.1.3854.1.2.2.1.16.1.12', map => \%map_degree_type }, +}; +my $oid_hhmsSensorArrayTempEntry = '.1.3.6.1.4.1.3854.1.2.2.1.16.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_hhmsSensorArrayTempEntry }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => "Checking temperatures"); + $self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0}; + return if ($self->check_filter(section => 'temperature')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_hhmsSensorArrayTempEntry}})) { + next if ($oid !~ /^$mapping->{hhmsSensorArrayTempOnline}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_hhmsSensorArrayTempEntry}, instance => $instance); + + next if ($self->check_filter(section => 'temperature', instance => $instance)); + if ($result->{hhmsSensorArrayTempOnline} eq 'offline') { + $self->{output}->output_add(long_msg => sprintf("skipping '%s': is offline", $result->{hhmsSensorArrayTempDescription})); + next; + } + $self->{components}->{temperature}->{total}++; + + $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s] [value = %s]", + $result->{hhmsSensorArrayTempDescription}, $result->{hhmsSensorArrayTempStatus}, $instance, + $result->{hhmsSensorArrayTempDegree})); + + my $exit = $self->get_severity(label => 'default1', section => 'temperature', value => $result->{hhmsSensorArrayTempStatus}); + 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'", $result->{hhmsSensorArrayTempDescription}, $result->{hhmsSensorArrayTempStatus})); + next; + } + + my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{hhmsSensorArrayTempDegree}); + if ($checked == 0) { + $result->{hhmsSensorArrayTempLowWarning} = (defined($result->{hhmsSensorArrayTempLowWarning}) && $result->{hhmsSensorArrayTempLowWarning} =~ /[0-9]/) ? + $result->{hhmsSensorArrayTempLowWarning} : ''; + $result->{hhmsSensorArrayTempLowCritical} = (defined($result->{hhmsSensorArrayTempLowCritical}) && $result->{hhmsSensorArrayTempLowCritical} =~ /[0-9]/) ? + $result->{hhmsSensorArrayTempLowCritical} : ''; + $result->{hhmsSensorArrayTempHighWarning} = (defined($result->{hhmsSensorArrayTempHighWarning}) && $result->{hhmsSensorArrayTempHighWarning} =~ /[0-9]/) ? + $result->{hhmsSensorArrayTempHighWarning} : ''; + $result->{hhmsSensorArrayTempHighCritical} = (defined($result->{hhmsSensorArrayTempHighCritical}) && $result->{hhmsSensorArrayTempHighCritical} =~ /[0-9]/) ? + $result->{hhmsSensorArrayTempHighCritical} : ''; + my $warn_th = $result->{hhmsSensorArrayTempLowWarning} . ':' . $result->{hhmsSensorArrayTempHighWarning}; + my $crit_th = $result->{hhmsSensorArrayTempLowCritical} . ':' . $result->{hhmsSensorArrayTempHighCritical}; + $self->{perfdata}->threshold_validate(label => 'warning-temperature-instance-' . $instance, value => $warn_th); + $self->{perfdata}->threshold_validate(label => 'critical-temperature-instance-' . $instance, value => $crit_th); + + $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); + } + + if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit2, + short_msg => sprintf("Temperature '%s' is %s %s", $result->{hhmsSensorArrayTempDescription}, $result->{hhmsSensorArrayTempDegree}, $result->{hhmsSensorArrayTempDegreeType})); + } + $self->{output}->perfdata_add(label => 'temperature_' . $result->{hhmsSensorArrayTempDescription}, unit => $result->{hhmsSensorArrayTempDegreeType}, + value => $result->{hhmsSensorArrayTempDegree}, + warning => $warn, + critical => $crit, + ); + } +} + +1; \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/mode/sensors.pm b/hardware/sensors/akcp/snmp/mode/sensors.pm new file mode 100644 index 000000000..02c20526e --- /dev/null +++ b/hardware/sensors/akcp/snmp/mode/sensors.pm @@ -0,0 +1,121 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::mode::sensors; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(temperature|humidity|switch|serial)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|humidity)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + default1 => [ + ['noStatus', 'OK'], + ['normal', 'OK'], + ['highWarning', 'WARNING'], + ['highCritical', 'CRITICAL'], + ['lowWarning', 'WARNING'], + ['lowCritical', 'CRITICAL'], + ['sensorError', 'CRITICAL'], + ], + default2 => [ + ['noStatus', 'OK'], + ['normal', 'OK'], + ['critical', 'CRITICAL'], + ['sensorError', 'CRITICAL'], + ], + }; + + $self->{components_path} = 'hardware::sensors::akcp::snmp::mode::components'; + $self->{components_module} = ['temperature', 'humidity', 'switch', 'serial']; +} + +sub snmp_execute { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + $self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}); +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check sensors. + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'temperature', 'humidity', 'switch', 'serial'. + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) +Can also exclude specific instance: --filter=fan,101 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='psu,CRITICAL,^(?!(presentOK)$)' + +=item B<--warning> + +Set warning threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) +Example: --warning='temperature,1,30' + +=item B<--critical> + +Set critical threshold for 'temperature', 'humidity' (syntax: type,regexp,threshold) +Example: --warning='temperature,1,50' + +=back + +=cut \ No newline at end of file diff --git a/hardware/sensors/akcp/snmp/plugin.pm b/hardware/sensors/akcp/snmp/plugin.pm new file mode 100644 index 000000000..ca4f3e967 --- /dev/null +++ b/hardware/sensors/akcp/snmp/plugin.pm @@ -0,0 +1,48 @@ +# +# Copyright 2016 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 hardware::sensors::akcp::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'sensors' => 'hardware::sensors::akcp::snmp::mode::sensors', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check AKCP sensors in SNMP. + +=cut diff --git a/hardware/server/dell/idrac/snmp/mode/components/amperage.pm b/hardware/server/dell/idrac/snmp/mode/components/amperage.pm index 1ebd18442..ad1d0ead1 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/amperage.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/amperage.pm @@ -103,7 +103,7 @@ sub check { $exit = $self->{perfdata}->threshold_check(value => $result->{amperageProbeReading}, threshold => [ { label => 'critical-amperage-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-amperage-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-amperage-instance-' . $instance); - $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-amperage-instance-' . $instance) + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-amperage-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm b/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm index 9eaf13818..73a99338b 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/coolingdevice.pm @@ -94,7 +94,7 @@ sub check { $exit = $self->{perfdata}->threshold_check(value => $result->{coolingDeviceReading}, threshold => [ { label => 'critical-coolingdevice-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-coolingdevice-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-coolingdevice-instance-' . $instance); - $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-coolingdevice-instance-' . $instance) + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-coolingdevice-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/hardware/server/dell/idrac/snmp/mode/components/temperature.pm b/hardware/server/dell/idrac/snmp/mode/components/temperature.pm index 95213638a..fca6c432d 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/temperature.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/temperature.pm @@ -102,7 +102,7 @@ sub check { $exit = $self->{perfdata}->threshold_check(value => $result->{temperatureProbeReading}, threshold => [ { label => 'critical-temperature-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-temperature-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-temperature-instance-' . $instance); - $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance) + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-temperature-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { diff --git a/hardware/server/dell/idrac/snmp/mode/components/voltage.pm b/hardware/server/dell/idrac/snmp/mode/components/voltage.pm index ff3399c7b..67cee6160 100644 --- a/hardware/server/dell/idrac/snmp/mode/components/voltage.pm +++ b/hardware/server/dell/idrac/snmp/mode/components/voltage.pm @@ -94,7 +94,7 @@ sub check { $exit = $self->{perfdata}->threshold_check(value => $result->{voltageProbeReading}, threshold => [ { label => 'critical-voltage-instance-' . $instance, exit_litteral => 'critical' }, { label => 'warning-voltage-instance-' . $instance, exit_litteral => 'warning' } ]); $warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-voltage-instance-' . $instance); - $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-voltage-instance-' . $instance) + $crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-voltage-instance-' . $instance); } if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { From 904ca70714c511f43e21b65027cc36ce2f33d18c Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 28 Feb 2016 16:22:57 +0100 Subject: [PATCH 14/20] + Fix #334 --- .../standard/rfc1628/snmp/mode/inputlines.pm | 207 +++++++----------- 1 file changed, 75 insertions(+), 132 deletions(-) diff --git a/hardware/ups/standard/rfc1628/snmp/mode/inputlines.pm b/hardware/ups/standard/rfc1628/snmp/mode/inputlines.pm index 2407632f6..579e594c7 100644 --- a/hardware/ups/standard/rfc1628/snmp/mode/inputlines.pm +++ b/hardware/ups/standard/rfc1628/snmp/mode/inputlines.pm @@ -20,48 +20,63 @@ package hardware::ups::standard::rfc1628::snmp::mode::inputlines; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::counter); use strict; use warnings; -my %oids = ( - '.1.3.6.1.2.1.33.1.3.3.1.2' => { counter => 'frequence' }, # in dH upsInputFrequency - '.1.3.6.1.2.1.33.1.3.3.1.3' => { counter => 'voltage' }, # in Volt upsInputVoltage - '.1.3.6.1.2.1.33.1.3.3.1.4' => { counter => 'current' }, # in dA upsInputCurrent - '.1.3.6.1.2.1.33.1.3.3.1.5' => { counter => 'power' }, # in Watt upsInputTruePower -); +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'line', type => 1, cb_prefix_output => 'prefix_line_output', message_multiple => 'All input lines are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{line} = [ + { label => 'frequence', set => { + key_values => [ { name => 'upsInputFrequency' }, { name => 'display' } ], + output_template => 'Frequence : %.2f Hz', + perfdatas => [ + { label => 'frequence', value => 'upsInputFrequency_absolute', template => '%s', + unit => 'Hz', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'voltage', set => { + key_values => [ { name => 'upsInputVoltage' }, { name => 'display' } ], + output_template => 'Voltage : %.2f V', + perfdatas => [ + { label => 'voltage', value => 'upsInputVoltage_absolute', template => '%s', + unit => 'V', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'current', set => { + key_values => [ { name => 'upsInputCurrent' }, { name => 'display' } ], + output_template => 'Current : %.2f A', + perfdatas => [ + { label => 'current', value => 'upsInputCurrent_absolute', template => '%s', + unit => 'A', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'power', set => { + key_values => [ { name => 'upsInputTruePower' }, { name => 'display' } ], + output_template => 'Power : %.2f W', + perfdatas => [ + { label => 'power', value => 'upsInputTruePower_absolute', template => '%s', + unit => 'W', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} -my $maps_counters = { - frequence => { thresholds => { - warning_frequence => { label => 'warning-frequence', exit_value => 'warning' }, - critical_frequence => { label => 'critical-frequence', exit_value => 'critical' }, - }, - output_msg => 'Frequence : %.2f Hz', - factor => 0.1, unit => 'Hz', - }, - voltage => { thresholds => { - warning_voltage => { label => 'warning-voltage', exit_value => 'warning' }, - critical_voltage => { label => 'critical-voltage', exit_value => 'critical' }, - }, - output_msg => 'Voltage : %.2f V', - factor => 1, unit => 'V', - }, - current => { thresholds => { - warning_current => { label => 'warning-current', exit_value => 'warning' }, - critical_current => { label => 'critical-current', exit_value => 'critical' }, - }, - output_msg => 'Current : %.2f A', - factor => 0.1, unit => 'A', - }, - power => { thresholds => { - warning_power => { label => 'warning-power', exit_value => 'warning' }, - critical_power => { label => 'critical-power', exit_value => 'critical' }, - }, - output_msg => 'Power : %.2f W', - factor => 1, unit => 'W', - }, -}; +sub prefix_line_output { + my ($self, %options) = @_; + + return "Input Line '" . $options{instance_value}->{display} . "' "; +} sub new { my ($class, %options) = @_; @@ -72,110 +87,33 @@ sub new { $options{options}->add_options(arguments => { }); - foreach (keys %{$maps_counters}) { - foreach my $name (keys %{$maps_counters->{$_}->{thresholds}}) { - $options{options}->add_options(arguments => { - $maps_counters->{$_}->{thresholds}->{$name}->{label} . ':s' => { name => $name }, - }); - } - } - - $self->{counters_value} = {}; - $self->{instances_done} = {}; + return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); +my $oids = { + '.1.3.6.1.2.1.33.1.3.3.1.2' => { name => 'upsInputFrequency', factor => 0.1 }, # in dH + '.1.3.6.1.2.1.33.1.3.3.1.3' => { name => 'upsInputVoltage', factor => 1 }, # in Volt + '.1.3.6.1.2.1.33.1.3.3.1.4' => { name => 'upsInputCurrent', factor => 0.1 }, # in dA + '.1.3.6.1.2.1.33.1.3.3.1.5' => { name => 'upsInputTruePower', factor => 1 }, # in Watt +}; - foreach (keys %{$maps_counters}) { - foreach my $name (keys %{$maps_counters->{$_}->{thresholds}}) { - if (($self->{perfdata}->threshold_validate(label => $maps_counters->{$_}->{thresholds}->{$name}->{label}, value => $self->{option_results}->{$name})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong " . $maps_counters->{$_}->{thresholds}->{$name}->{label} . " threshold '" . $self->{option_results}->{$name} . "'."); - $self->{output}->option_exit(); - } - } - } -} - -sub build_values { +sub manage_selection { my ($self, %options) = @_; - my $counters_value = {}; - my $instance = undef; - - foreach my $oid (keys %oids) { - if ($options{current} =~ /^$oid\.(.*)/) { - $instance = $1; - last; - } - } - - # Skip already done - if (!defined($instance) || defined($self->{instances_done}->{$instance})) { - return 0; - } - - $self->{instances_done}->{$instance} = 1; - $self->{counters_value}->{$instance} = {}; - foreach my $oid (keys %oids) { - $self->{counters_value}->{$instance}->{$oids{$oid}->{counter}} = defined($options{result}->{$oid . '.' . $instance}) ? $options{result}->{$oid . '.' . $instance} : 0; - } -} -sub run { - my ($self, %options) = @_; - # $options{snmp} = snmp object - $self->{snmp} = $options{snmp}; - my $oid_upsInputEntry = '.1.3.6.1.2.1.33.1.3.3.1'; - my $result = $self->{snmp}->get_table(oid => $oid_upsInputEntry, nothing_quit => 1); - foreach my $key ($self->{snmp}->oid_lex_sort(keys %$result)) { - $self->build_values(current => $key, result => $result); - } - - my $num = scalar(keys %{$self->{instances_done}}); - foreach my $instance (keys %{$self->{instances_done}}) { - my $instance_output = $instance; - $instance_output =~ s/\./#/g; + my $results = $options{snmp}->get_table(oid => $oid_upsInputEntry, nothing_quit => 1); + + $self->{line} = {}; + foreach my $oid (keys %{$results}) { + next if ($oid !~ /^(.*)\.(.*?)\.(.*?)$/); + my ($base, $instance) = ($1 . '.' . $2, $3); + next if (!defined($oids->{$base})); + next if ($results->{$oid} !~ /\d/ || $results->{$oid} == 0); - my @exits; - foreach (keys %{$maps_counters}) { - foreach my $name (keys %{$maps_counters->{$_}->{thresholds}}) { - if (defined($self->{counters_value}->{$instance}->{$_}) && $self->{counters_value}->{$instance}->{$_} =~ /\d/ && $self->{counters_value}->{$instance}->{$_} != 0) { - push @exits, $self->{perfdata}->threshold_check(value => $self->{counters_value}->{$instance}->{$_} * $maps_counters->{$_}->{factor}, threshold => [ { label => $maps_counters->{$_}->{thresholds}->{$name}->{label}, 'exit_litteral' => $maps_counters->{$_}->{thresholds}->{$name}->{exit_value} }]); - } - } - } - - my $exit = $self->{output}->get_most_critical(status => [ @exits ]); - my $extra_label = ''; - $extra_label = '_' . $instance_output if ($num > 1); - - my $str_output = "Input Line '$instance_output' "; - my $str_append = ''; - foreach (keys %{$maps_counters}) { - next if (!defined($self->{counters_value}->{$instance}->{$_}) || $self->{counters_value}->{$instance}->{$_} !~ /\d/ || $self->{counters_value}->{$instance}->{$_} == 0); - - $str_output .= $str_append . sprintf($maps_counters->{$_}->{output_msg}, $self->{counters_value}->{$instance}->{$_} * $maps_counters->{$_}->{factor}); - $str_append = ', '; - my ($warning, $critical); - foreach my $name (keys %{$maps_counters->{$_}->{thresholds}}) { - $warning = $self->{perfdata}->get_perfdata_for_output(label => $maps_counters->{$_}->{thresholds}->{$name}->{label}) if ($maps_counters->{$_}->{thresholds}->{$name}->{exit_value} eq 'warning'); - $critical = $self->{perfdata}->get_perfdata_for_output(label => $maps_counters->{$_}->{thresholds}->{$name}->{label}) if ($maps_counters->{$_}->{thresholds}->{$name}->{exit_value} eq 'critical'); - } - - $self->{output}->perfdata_add(label => $_ . $extra_label, unit => $maps_counters->{$_}->{unit}, - value => sprintf("%.2f", $self->{counters_value}->{$instance}->{$_} * $maps_counters->{$_}->{factor}), - warning => $warning, - critical => $critical); - } - $self->{output}->output_add(severity => $exit, - short_msg => $str_output); + $self->{line}->{$instance} = { display => $instance } if (!defined($self->{line}->{$instance})); + $self->{line}->{$instance}->{$oids->{$base}->{name}} = $results->{$oid} * $oids->{$base}->{factor}; } - - $self->{output}->display(); - $self->{output}->exit(); } 1; @@ -188,6 +126,11 @@ Check Input lines metrics (frequence, voltage, current and true power). =over 8 +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^power$' + =item B<--warning-*> Threshold warning. From 5be92d771abe1cf322b6487e966db0aa5ce782bc Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 28 Feb 2016 16:45:10 +0100 Subject: [PATCH 15/20] + Fix #348 : problem with onOff --- hardware/pdu/raritan/snmp/mode/components/resources.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/pdu/raritan/snmp/mode/components/resources.pm b/hardware/pdu/raritan/snmp/mode/components/resources.pm index 9483bee88..1e0043db7 100644 --- a/hardware/pdu/raritan/snmp/mode/components/resources.pm +++ b/hardware/pdu/raritan/snmp/mode/components/resources.pm @@ -191,7 +191,7 @@ $thresholds = { ], onoff => [ ['unavailable', 'UNKNOWN'], - ['ok', 'OK'], + ['on', 'OK'], ['off', 'OK'], ], contact => [ From 2b8b3c57899da861fb3b7c5324c921df1f6a877b Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 3 Mar 2016 14:01:41 +0100 Subject: [PATCH 16/20] + fix help numeric value --- apps/protocols/jmx/mode/numericvalue.pm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/protocols/jmx/mode/numericvalue.pm b/apps/protocols/jmx/mode/numericvalue.pm index 6eb9e3ae0..00a64d7db 100644 --- a/apps/protocols/jmx/mode/numericvalue.pm +++ b/apps/protocols/jmx/mode/numericvalue.pm @@ -258,10 +258,6 @@ perl centreon_plugins.pl --plugin=apps::protocols::jmx::plugin --custommode=jolo =over 8 -=item B<--oid> - -OID value to check (numeric format only). - =item B<--lookup-path> What to lookup (from internal Jmx4Perl). Use --lookup-jpath for complex matching. @@ -279,9 +275,9 @@ Threshold warning. Threshold critical. -=item B<--oid-type> +=item B<--type> -Type of the OID (Default: 'gauge'). +Type (Default: 'gauge'). Can be 'counter' also. 'counter' will use a retention file. =item B<--counter-per-seconds> From e46ed8941ee8067b36399f46325ac1f641d70eb1 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 3 Mar 2016 17:47:41 +0100 Subject: [PATCH 17/20] + Fix #228 --- snmp_standard/mode/stringvalue.pm | 303 +++++++++++++++++++++++++----- 1 file changed, 256 insertions(+), 47 deletions(-) diff --git a/snmp_standard/mode/stringvalue.pm b/snmp_standard/mode/stringvalue.pm index 52cfbae7a..de2bbb0db 100644 --- a/snmp_standard/mode/stringvalue.pm +++ b/snmp_standard/mode/stringvalue.pm @@ -35,15 +35,44 @@ sub new { $options{options}->add_options(arguments => { "oid:s" => { name => 'oid' }, + "oid-leef:s" => { name => 'oid_leef' }, + "oid-table:s" => { name => 'oid_table' }, + "oid-instance:s" => { name => 'oid_instance' }, + "filter-table:s" => { name => 'filter_table' }, + "warning-regexp:s" => { name => 'warning_regexp' }, "critical-regexp:s" => { name => 'critical_regexp' }, "unknown-regexp:s" => { name => 'unknown_regexp' }, - "format:s" => { name => 'format', default => 'current value is %s' }, - "map-values:s" => { name => 'map_values' }, - "map-values-separator:s" => { name => 'map_values_separator', default => ',' }, - "regexp-map-values" => { name => 'use_regexp_map_values' }, "regexp-isensitive" => { name => 'use_iregexp' }, + + "warning-absent:s@" => { name => 'warning_absent' }, + "critical-absent:s@" => { name => 'critical_absent' }, + "unknown-absent:s@" => { name => 'unknown_absent' }, + "warning-present:s@" => { name => 'warning_present' }, + "critical-present:s@" => { name => 'critical_present' }, + "unknown-present:s@" => { name => 'unknown_present' }, + + "format-ok:s" => { name => 'format_ok', default => '%{filter_rows} value(s)' }, + "format-warning:s" => { name => 'format_warning', default => 'value(s): %{details_warning}' }, + "format-critical:s" => { name => 'format_critical', default => 'value(s): %{details_critical}' }, + "format-unknown:s" => { name => 'format_unknown', default => 'value(s): %{details_unknown}' }, + + "format-details-ok:s" => { name => 'format_details_ok', default => '%{value}' }, + "format-details-warning:s" => { name => 'format_details_warning', default => '%{value}' }, + "format-details-critical:s" => { name => 'format_details_critical', default => '%{value}' }, + "format-details-unknown:s" => { name => 'format_details_unknown', default => '%{value}' }, + + "format-details-separator-ok:s" => { name => 'format_details_separator_ok', default => ', ' }, + "format-details-separator-warning:s" => { name => 'format_details_separator_warning', default => ', ' }, + "format-details-separator-critical:s" => { name => 'format_details_separator_critical', default => ', ' }, + "format-details-separator-unknown:s" => { name => 'format_details_separator_unknown', default => ', ' }, + + "map-values:s" => { name => 'map_values' }, + "map-value-other:s" => { name => 'map_value_other' }, + "map-values-separator:s" => { name => 'map_values_separator', default => ',' }, }); + + $self->{macros} = { ok => {}, warning => {}, critical => {}, unknown => {} }; return $self; } @@ -51,12 +80,16 @@ sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); - if (!defined($self->{option_results}->{oid}) || $self->{option_results}->{oid} eq '') { - $self->{output}->add_option_msg(short_msg => "Need to specify an OID."); + $self->{option_results}->{oid_leef} = $self->{option_results}->{oid} if (defined($self->{option_results}->{oid}) && $self->{option_results}->{oid} ne ''); + if ((!defined($self->{option_results}->{oid_leef}) || $self->{option_results}->{oid_leef} eq '') && + (!defined($self->{option_results}->{oid_table}) || $self->{option_results}->{oid_table} eq '')) { + $self->{output}->add_option_msg(short_msg => "Need to specify an OID with option --oid-leef or --oid-table."); $self->{output}->option_exit(); } - $self->{option_results}->{oid} = '.' . $self->{option_results}->{oid} if ($self->{option_results}->{oid} !~ /^\./); - + foreach (('oid_leef', 'oid_table', 'oid_instance')) { + $self->{option_results}->{$_} = '.' . $self->{option_results}->{$_} if (defined($self->{option_results}->{$_}) && $self->{option_results}->{$_} ne '' && $self->{option_results}->{$_} !~ /^\./); + } + $self->{map_values} = {}; if (defined($self->{option_results}->{map_values})) { foreach (split /$self->{option_results}->{map_values_separator}/, $self->{option_results}->{map_values}) { @@ -66,47 +99,196 @@ sub check_options { } } -sub check_regexp { +sub get_instance_value { + my ($self, %options) = @_; + + if (!defined($self->{option_results}->{oid_instance}) || $self->{option_results}->{oid_instance} eq '' + || !defined($self->{results}->{$self->{option_results}->{oid_instance} . '.' . $options{instance}})) { + return $options{instance}; + } + + return $self->{results}->{$self->{option_results}->{oid_instance} . '.' . $options{instance}}; +} + +sub get_map_value { + my ($self, %options) = @_; + + my $value = $options{value}; + return '' if (!defined($options{value})); + if (defined($self->{map_values}->{$options{value}})) { + $value = $self->{map_values}->{$options{value}}; + } elsif (defined($self->{option_results}->{map_value_other}) && $self->{option_results}->{map_value_other} ne '') { + $value = $self->{option_results}->{map_value_other}; + } + + return $value; +} + +sub get_snmp_values { + my ($self, %options) = @_; + + $self->{instances} = {}; + if (defined($self->{option_results}->{oid_leef}) && $self->{option_results}->{oid_leef} ne '') { + $self->{results} = $self->{snmp}->get_leef(oids => [$self->{option_results}->{oid_leef}], nothing_quit => 1); + $self->{macros}->{rows} = 1; + $self->{macros}->{filter_rows} = 1; + $self->{instances}->{0} = $self->get_map_value(value => $self->{results}->{$self->{option_results}->{oid_leef}}); + return 0; + } + + my $tables = [ { oid => $self->{option_results}->{oid_table}} ]; + push @$tables, { oid => $self->{option_results}->{oid_instance} } if (defined($self->{option_results}->{oid_instance}) && $self->{option_results}->{oid_instance} ne ''); + $self->{results} = $self->{snmp}->get_multiple_table(oids => $tables, nothing_quit => 1, return_type => 1); + my ($row, $filter_row) = (0, 0); + foreach (keys %{$self->{results}}) { + next if ($_ !~ /^$self->{option_results}->{oid_table}\.(.*)$/); + + $row++; + my $instance = $self->get_instance_value(instance => $1); + my $value = $self->get_map_value(value => $self->{results}->{$_}); + $self->{output}->output_add(long_msg => sprintf("[instance: %s][value: %s]", $_, $value), debug => 1); + if (defined($self->{option_results}->{filter_table}) && $self->{option_results}->{filter_table} ne '' && + $value !~ /$self->{option_results}->{filter_table}/) { + $self->{output}->output_add(long_msg => sprintf("skipping oid '%s' value '%s': not matching the filter", $_, $value), debug => 1); + next; + } + + $self->{instances}->{$instance} = $value; + $filter_row++; + } + $self->{macros}->{rows} = $row; + $self->{macros}->{filter_rows} = $filter_row; + + return 0; +} + +sub checking_regexp { my ($self, %options) = @_; return 0 if (!defined($self->{option_results}->{$options{severity} . '_regexp'})); my $regexp = $self->{option_results}->{$options{severity} . '_regexp'}; if (defined($self->{option_results}->{use_iregexp}) && $options{value} =~ /$regexp/i) { - $self->{exit_code} = $options{severity}; + $self->{instances}->{$options{severity}}->{$options{instance}} = $options{value}; return 1; } elsif (!defined($self->{option_results}->{use_iregexp}) && $options{value} =~ /$regexp/) { - $self->{exit_code} = $options{severity}; + $self->{instances}->{$options{severity}}->{$options{instance}} = $options{value}; return 1; - } + } return 0; } -sub run { +sub store_ok { my ($self, %options) = @_; - # $options{snmp} = snmp object - $self->{snmp} = $options{snmp}; - - my $result = $self->{snmp}->get_leef(oids => [$self->{option_results}->{oid}], nothing_quit => 1); - my $value_check = $result->{$self->{option_results}->{oid}}; - my $value_display = $value_check; - if (defined($self->{option_results}->{map_values})) { - # If we don't find it. We keep the original value - $value_display = defined($self->{map_values}->{$value_check}) ? $self->{map_values}->{$value_check} : $value_check; - if (defined($self->{option_results}->{use_regexp_map_values})) { - $value_check = $value_display; + foreach my $severity (('critical', 'warning', 'unknown')) { + foreach my $type (('absent', 'present')) { + if (defined($self->{option_results}->{$severity . '_' . $type}) && scalar(@{$self->{option_results}->{$severity . '_' . $type}}) > 0) { + return 0; + } } } - - $self->{exit_code} = 'ok'; - $self->check_regexp(severity => 'critical', value => $value_check) || - $self->check_regexp(severity => 'warning', value => $value_check) || - $self->check_regexp(severity => 'unknown', value => $value_check); - $self->{output}->output_add(severity => $self->{exit_code}, - short_msg => sprintf($self->{option_results}->{format}, $value_display)); + $self->{instances}->{ok}->{$options{instance}} = $options{value}; +} + +sub checking_exist { + my ($self, %options) = @_; + + foreach my $severity (('critical', 'warning', 'unknown')) { + foreach my $absent (@{$self->{option_results}->{$severity . '_absent'}}) { + my $match = 0; + foreach (keys %{$self->{instances}}) { + if ($self->{instances}->{$_} eq $absent) { + $match = 1; + last; + } + } + + if ($match == 0) { + $self->{instances}->{$severity}->{$absent} = $absent; + } + } + + foreach my $present (@{$self->{option_results}->{$severity . '_present'}}) { + my $match = 0; + foreach (keys %{$self->{instances}}) { + if ($self->{instances}->{$_} eq $present) { + $self->{instances}->{$severity}->{$_} = $self->{instances}->{$_}; + } + } + } + } +} + +sub change_macros { + my ($self, %options) = @_; + + my $value = $self->{option_results}->{'format_' . $options{severity}}; + while ($value =~ /%\{(.*?)\}/g) { + $value =~ s/%\{($1)\}/\$self->{macros}->{$1}/g; + } + + return $value; +} + +sub build_format_details { + my ($self, %options) = @_; + + foreach my $severity (('ok', 'critical', 'warning', 'unknown')) { + $self->{macros}->{'details_' . $severity} = ''; + my $append = ''; + foreach my $instance (sort keys %{$self->{instances}->{$severity}}) { + my $details = $self->{option_results}->{'format_details_' . $severity}; + $details =~ s/%{rows}/$self->{macros}->{rows}/g; + $details =~ s/%{filter_rows}/$self->{macros}->{filter_rows}/g; + $details =~ s/%{instance}/$instance/g; + $details =~ s/%{value}/$self->{instances}->{$severity}->{$instance}/g; + + $self->{macros}->{'details_' . $severity} .= $append . $details; + $append = $self->{option_results}->{'format_details_separator_' . $severity}; + } + } +} + +sub display_severity { + my ($self, %options) = @_; + + if (!(defined($options{force}) && $options{force} == 1) && scalar(keys %{$self->{instances}->{$options{severity}}}) == 0) { + return 0; + } + + my $display = $self->change_macros(severity => $options{severity}); + eval "\$display = \"$display\""; + $self->{output}->output_add(severity => $options{severity}, + short_msg => $display); +} + +sub display_result { + my ($self, %options) = @_; + + $self->build_format_details(); + $self->display_severity(severity => 'ok', force => 1); + foreach my $severity (('critical', 'warning', 'unknown')) { + $self->display_severity(severity => $severity); + } +} + +sub run { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->get_snmp_values(); + + foreach (keys %{$self->{instances}}) { + $self->checking_regexp(severity => 'critical', instance => $_, value => $self->{instances}->{$_}) || + $self->checking_regexp(severity => 'warning', instance => $_, value => $self->{instances}->{$_}) || + $self->checking_regexp(severity => 'unknown', instance => $_, value => $self->{instances}->{$_}) || + $self->store_ok(instance => $_, value => $self->{instances}->{$_}); + } + $self->checking_exist(); + $self->display_result(); $self->{output}->display(); $self->{output}->exit(); @@ -118,47 +300,74 @@ __END__ =head1 MODE -Check an SNMP string value (can be a String or an Integer). +Check SNMP string values (can be a String or an Integer). +Check values absent: +centreon_plugins.pl --plugin=snmp_standard::plugin --mode=string-value --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public + --oid-table='.1.3.6.1.2.1.25.4.2.1.2' --format-ok='%{filter_rows} processes' --format-critical='processes are absent: %{details_critical}' --critical-absent='centengine' --critical-absent='crond' --filter-table='centengine|crond' + +Check table status: +centreon_plugins.pl --plugin=snmp_standard::plugin --mode=string-value --hostname=127.0.0.1 --snmp-version=2c --snmp-community=akcp + --oid-table='.1.3.6.1.4.1.3854.1.2.2.1.16.1.4' --oid-instance='.1.3.6.1.4.1.3854.1.2.2.1.16.1.1' --map-values='1=>noStatus,2=>normal,3=>highWarning,4=>highCritical,5=>lowWarning,6=>lowCritical,7=>sensorError' --map-value-other='unknown' --format-ok='All %{rows} entries [%{filter_rows}/%{rows} Temperatures] are ok.' --format-critical='%{details_critical}' --format-details-critical='%{instance} status is %{value}' --critical-regexp='highCritical|lowCritical|sensorError' + +Check like the old plugin: +centreon_plugins.pl --plugin=snmp_standard::plugin --mode=string-value --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public + --oid='.1.3.6.1.2.1.1.1.0' --format-ok='current value is: %{details_ok}' --format-details-warning='current value is: %{details_warning}' --format-details-critical='current value is: %{details_critical}' + =over 8 -=item B<--oid> +=item B<--oid> or <--oid-leef> OID value to check (numeric format only). +=item B<--oid-table> + +OID table value to check (numeric format only). + +=item B<--oid-instance> + +OID table value for the instance (numeric format only). +Can be used to have human readable instance name. + +=item B<--filter-table> + +Filter value from --oid-table option (can be a regexp). + =item B<--warning-regexp> -Return Warning if the oid value match the regexp. +Return Warning if an oid value match the regexp. =item B<--critical-regexp> -Return Critical if the oid value match the regexp. +Return Critical if an oid value match the regexp. -=item B<--unknown-regexp> +=item B<--regexp-isensitive> -Return Unknown if the oid value match the regexp. +Allows to use regexp non case-sensitive. -=item B<--format> +=item B<--format-*> -Output format (Default: 'current value is %s'). +Output format according the threshold. +Can be: +'ok' (default: '%{filter_rows} value(s)'), +'warning' (default: 'value(s): %{details_warning}'), +'critical' (default: 'value(s): %{details_critical}'), +'unknown' (default: 'value(s): %{details_unknown}'). +Can used: %{rows}, %{filter_rows}, %{details_warning}, %{details_ok}, %{details_critical}, %{details_unknown} =item B<--map-values> Use to transform an integer value in most common case. Example: --map-values='1=>ok,10=>fan failed,11=>psu recovery' +=item B<--map-value-other> + +Use to transform an integer value not defined in --map-values option. + =item B<--map-values-separator> Separator uses between values (default: coma). -=item B<--regexp-map-values> - -Use the 'map values' to match in regexp (need --map-values option). - -=item B<--regexp-isensitive> - -Allows to use regexp non case-sensitive. - =back =cut From e42de5927a768fb12dbe3fe4940de2d6fa9b22e1 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Thu, 3 Mar 2016 18:03:15 +0100 Subject: [PATCH 18/20] + change filter --- snmp_standard/mode/stringvalue.pm | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/snmp_standard/mode/stringvalue.pm b/snmp_standard/mode/stringvalue.pm index de2bbb0db..ad8c5c01f 100644 --- a/snmp_standard/mode/stringvalue.pm +++ b/snmp_standard/mode/stringvalue.pm @@ -38,7 +38,8 @@ sub new { "oid-leef:s" => { name => 'oid_leef' }, "oid-table:s" => { name => 'oid_table' }, "oid-instance:s" => { name => 'oid_instance' }, - "filter-table:s" => { name => 'filter_table' }, + "filter-table-value:s" => { name => 'filter_table_value' }, + "filter-table-instance:s" => { name => 'filter_table_instance' }, "warning-regexp:s" => { name => 'warning_regexp' }, "critical-regexp:s" => { name => 'critical_regexp' }, @@ -147,11 +148,16 @@ sub get_snmp_values { my $instance = $self->get_instance_value(instance => $1); my $value = $self->get_map_value(value => $self->{results}->{$_}); $self->{output}->output_add(long_msg => sprintf("[instance: %s][value: %s]", $_, $value), debug => 1); - if (defined($self->{option_results}->{filter_table}) && $self->{option_results}->{filter_table} ne '' && - $value !~ /$self->{option_results}->{filter_table}/) { + if (defined($self->{option_results}->{filter_table_value}) && $self->{option_results}->{filter_table_value} ne '' && + $value !~ /$self->{option_results}->{filter_table_value}/) { $self->{output}->output_add(long_msg => sprintf("skipping oid '%s' value '%s': not matching the filter", $_, $value), debug => 1); next; } + if (defined($self->{option_results}->{filter_table_instance}) && $self->{option_results}->{filter_table_instance} ne '' && + $instance !~ /$self->{option_results}->{filter_table_instance}/) { + $self->{output}->output_add(long_msg => sprintf("skipping oid '%s' instance '%s': not matching the filter", $_, $instance), debug => 1); + next; + } $self->{instances}->{$instance} = $value; $filter_row++; @@ -304,7 +310,7 @@ Check SNMP string values (can be a String or an Integer). Check values absent: centreon_plugins.pl --plugin=snmp_standard::plugin --mode=string-value --hostname=127.0.0.1 --snmp-version=2c --snmp-community=public - --oid-table='.1.3.6.1.2.1.25.4.2.1.2' --format-ok='%{filter_rows} processes' --format-critical='processes are absent: %{details_critical}' --critical-absent='centengine' --critical-absent='crond' --filter-table='centengine|crond' + --oid-table='.1.3.6.1.2.1.25.4.2.1.2' --format-ok='%{filter_rows} processes' --format-critical='processes are absent: %{details_critical}' --critical-absent='centengine' --critical-absent='crond' --filter-table-value='centengine|crond' Check table status: centreon_plugins.pl --plugin=snmp_standard::plugin --mode=string-value --hostname=127.0.0.1 --snmp-version=2c --snmp-community=akcp @@ -329,10 +335,14 @@ OID table value to check (numeric format only). OID table value for the instance (numeric format only). Can be used to have human readable instance name. -=item B<--filter-table> +=item B<--filter-table-value> Filter value from --oid-table option (can be a regexp). +=item B<--filter-table-instance> + +Filter instance from --oid-table option (can be a regexp). + =item B<--warning-regexp> Return Warning if an oid value match the regexp. From 40a3cb8bb49017694558b231afbd0dea8f9e8aa8 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 7 Mar 2016 15:52:22 +0100 Subject: [PATCH 19/20] + add juniper isg (Fix #316) --- network/juniper/isg/plugin.pm | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 network/juniper/isg/plugin.pm diff --git a/network/juniper/isg/plugin.pm b/network/juniper/isg/plugin.pm new file mode 100644 index 000000000..d949df4f5 --- /dev/null +++ b/network/juniper/isg/plugin.pm @@ -0,0 +1,53 @@ +# +# Copyright 2016 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 network::juniper::ssg::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cpu' => 'network::juniper::common::screenos::mode::cpu', + 'memory' => 'network::juniper::common::screenos::mode::memory', + 'sessions' => 'network::juniper::common::screenos::mode::sessions', + 'hardware' => 'network::juniper::common::screenos::mode::hardware', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Juniper ISG series in SNMP. + +=cut From 563d4f99d3c47f99f2210017992371611660fb24 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 7 Mar 2016 21:57:10 +0100 Subject: [PATCH 20/20] + Fix juniper isg --- network/juniper/isg/plugin.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/juniper/isg/plugin.pm b/network/juniper/isg/plugin.pm index d949df4f5..c3bbc8d20 100644 --- a/network/juniper/isg/plugin.pm +++ b/network/juniper/isg/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::juniper::ssg::plugin; +package network::juniper::isg::plugin; use strict; use warnings;