From 12eea0efd5b364be24fb198610e0cff45bc8160b Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 26 Apr 2021 16:02:06 +0200 Subject: [PATCH] add(plugin): huawei oceanstor snmp (#2737) --- .../oceanstor/snmp/mode/components/bbu.pm | 84 ++++++ .../oceanstor/snmp/mode/components/disk.pm | 103 +++++++ .../snmp/mode/components/enclosure.pm | 103 +++++++ .../snmp/mode/components/expboard.pm | 84 ++++++ .../oceanstor/snmp/mode/components/fan.pm | 84 ++++++ .../oceanstor/snmp/mode/components/psu.pm | 84 ++++++ .../huawei/oceanstor/snmp/mode/controllers.pm | 213 ++++++++++++++ .../huawei/oceanstor/snmp/mode/hardware.pm | 113 ++++++++ .../oceanstor/snmp/mode/listcontrollers.pm | 123 +++++++++ .../oceanstor/snmp/mode/liststoragepools.pm | 125 +++++++++ .../huawei/oceanstor/snmp/mode/resources.pm | 86 ++++++ .../oceanstor/snmp/mode/storagepools.pm | 259 ++++++++++++++++++ storage/huawei/oceanstor/snmp/plugin.pm | 52 ++++ 13 files changed, 1513 insertions(+) create mode 100644 storage/huawei/oceanstor/snmp/mode/components/bbu.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/components/disk.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/components/enclosure.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/components/expboard.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/components/fan.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/components/psu.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/controllers.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/hardware.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/listcontrollers.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/liststoragepools.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/resources.pm create mode 100644 storage/huawei/oceanstor/snmp/mode/storagepools.pm create mode 100644 storage/huawei/oceanstor/snmp/plugin.pm diff --git a/storage/huawei/oceanstor/snmp/mode/components/bbu.pm b/storage/huawei/oceanstor/snmp/mode/components/bbu.pm new file mode 100644 index 000000000..6b81d56b5 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/bbu.pm @@ -0,0 +1,84 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::bbu; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.5.1.1' }, # hwInfoBBUID + location => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.5.1.2' }, # hwInfoBBULocation + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.5.1.3', map => $health_status }, # hwInfoBBUHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.5.1.4', map => $running_status } # hwInfoBBURunningStatus +}; +my $oid_bbu_entry = '.1.3.6.1.4.1.34774.4.1.23.5.5.1'; # hwInfoBBUEntry + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_bbu_entry, + end => $mapping->{running_status}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking bbu'); + $self->{components}->{bbu} = { name => 'bbu', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'bbu')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_bbu_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_bbu_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{location} . ':' . $result->{id}; + + next if ($self->check_filter(section => 'bbu', instance => $instance, name => $name)); + + $self->{components}->{bbu}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "bbu '%s' status is '%s' [instance: %s, location: %s, running status: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{location}, + $result->{running_status} + ) + ); + my $exit = $self->get_severity(label => 'default', section => 'bbu', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "BBU '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/components/disk.pm b/storage/huawei/oceanstor/snmp/mode/components/disk.pm new file mode 100644 index 000000000..2a7f0fe2a --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/disk.pm @@ -0,0 +1,103 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::disk; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.1.1.1' }, # hwInfoDiskID + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.1.1.2', map => $health_status }, # hwInfoDiskHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.1.1.3', map => $running_status }, # hwInfoDiskRunningStatus + location => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.1.1.4' }, # hwInfoDiskLocation + temperature => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.1.1.11' } # hwInfoDiskTemperature +}; +my $oid_disk_entry = '.1.3.6.1.4.1.34774.4.1.23.5.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_disk_entry, + end => $mapping->{temperature}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking disks'); + $self->{components}->{disk} = { name => 'disks', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'disk')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_disk_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_disk_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{location} . ':' . $result->{id}; + + next if ($self->check_filter(section => 'disk', instance => $instance, name => $name)); + + $self->{components}->{disk}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "disk '%s' status is '%s' [instance: %s, location: %s, running status: %s, temperature: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{location}, + $result->{running_status}, + $result->{temperature} + ) + ); + $exit = $self->get_severity(label => 'default', section => 'disk', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Disk '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'disk.temperature', instance => $instance, name => $name, value => $result->{temperature}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Disk temperature '%s' is '%s' C", $instance, $result->{temperature}) + ); + } + $self->{output}->perfdata_add( + nlabel => 'hardware.disk.temperature.celsius', + unit => 'C', + instances => $instance, + value => $result->{temperature}, + warning => $warn, + critical => $crit + ); + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/components/enclosure.pm b/storage/huawei/oceanstor/snmp/mode/components/enclosure.pm new file mode 100644 index 000000000..9b99e8cbf --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/enclosure.pm @@ -0,0 +1,103 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::enclosure; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.6.1.1' }, # hwInfoEnclosureID + name => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.6.1.2' }, # hwInfoEnclosureName + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.6.1.4', map => $health_status }, # hwInfoEnclosureHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.6.1.5', map => $running_status }, # hwInfoEnclosureRunningStatus + temperature => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.6.1.8' } # hwInfoEnclosureTemperature +}; +my $oid_enclosure_entry = '.1.3.6.1.4.1.34774.4.1.23.5.6.1'; # hwInfoEnclosureEntry + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_enclosure_entry, + end => $mapping->{temperature}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking enclosures'); + $self->{components}->{enclosure} = { name => 'enclosures', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'enclosure')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_enclosure_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_enclosure_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{name}; + + next if ($self->check_filter(section => 'enclosure', instance => $instance, name => $name)); + + $self->{components}->{enclosure}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "enclosure '%s' status is '%s' [instance: %s, name: %s, running status: %s, temperature: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{name}, + $result->{running_status}, + $result->{temperature} + ) + ); + $exit = $self->get_severity(label => 'default', section => 'enclosure', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Enclosure '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'enclosure.temperature', instance => $instance, name => $name, value => $result->{temperature}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Enclosure temperature '%s' is '%s' C", $instance, $result->{temperature}) + ); + } + $self->{output}->perfdata_add( + nlabel => 'hardware.enclosure.temperature.celsius', + unit => 'C', + instances => $instance, + value => $result->{temperature}, + warning => $warn, + critical => $crit + ); + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/components/expboard.pm b/storage/huawei/oceanstor/snmp/mode/components/expboard.pm new file mode 100644 index 000000000..3ccb106a0 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/expboard.pm @@ -0,0 +1,84 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::expboard; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.14.1.1' }, # hwInfoExpBoardID + location => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.14.1.2' }, # hwInfoExpBoardLocation + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.14.1.3', map => $health_status }, # hwInfoExpBoardHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.14.1.4', map => $running_status } # hwInfoExpBoardRunningStatus +}; +my $oid_expboard_entry = '.1.3.6.1.4.1.34774.4.1.23.5.14.1'; # hwInfoExpBoardEntry + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_expboard_entry, + end => $mapping->{running_status}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking expansion boards'); + $self->{components}->{expboard} = { name => 'expboards', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'expboard')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_expboard_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_expboard_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{location} . ':' . $result->{id}; + + next if ($self->check_filter(section => 'expboard', instance => $instance, name => $name)); + + $self->{components}->{expboard}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "expansion board '%s' status is '%s' [instance: %s, location: %s, running status: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{location}, + $result->{running_status} + ) + ); + my $exit = $self->get_severity(label => 'default', section => 'expboard', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Expansion board '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/components/fan.pm b/storage/huawei/oceanstor/snmp/mode/components/fan.pm new file mode 100644 index 000000000..4bbee4725 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/fan.pm @@ -0,0 +1,84 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::fan; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.4.1.1' }, # hwInfoFanID + location => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.4.1.2' }, # hwInfoFanLocation + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.4.1.3', map => $health_status }, # hwInfoFanHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.4.1.4', map => $running_status } # hwInfoFanRunningStatus +}; +my $oid_fan_entry = '.1.3.6.1.4.1.34774.4.1.23.5.4.1'; # hwInfoFanEntry + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_fan_entry, + end => $mapping->{running_status}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking fans'); + $self->{components}->{fan} = { name => 'fans', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'fan')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_fan_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_fan_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{location} . ':' . $result->{id}; + + next if ($self->check_filter(section => 'fan', instance => $instance, name => $name)); + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "fan '%s' status is '%s' [instance: %s, location: %s, running status: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{location}, + $result->{running_status} + ) + ); + my $exit = $self->get_severity(label => 'default', section => 'fan', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Fan '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/components/psu.pm b/storage/huawei/oceanstor/snmp/mode/components/psu.pm new file mode 100644 index 000000000..aa377ad10 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/components/psu.pm @@ -0,0 +1,84 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::components::psu; + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.3.1.1' }, # hwInfoPowerID + location => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.3.1.2' }, # hwInfoPowerLocation + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.3.1.3', map => $health_status }, # hwInfoPowerHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.3.1.4', map => $running_status } # hwInfoPowerRunningStatus +}; +my $oid_psu_entry = '.1.3.6.1.4.1.34774.4.1.23.5.3.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_psu_entry, + end => $mapping->{running_status}->{oid} + }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking power supplies'); + $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'psu')); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_psu_entry}})) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_psu_entry}, instance => $1); + my $instance = $result->{id}; + my $name = $result->{location} . ':' . $result->{id}; + + next if ($self->check_filter(section => 'psu', instance => $instance, name => $name)); + + $self->{components}->{psu}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "power supply '%s' status is '%s' [instance: %s, location: %s, running status: %s]", + $instance, + $result->{health_status}, + $instance, + $result->{location}, + $result->{running_status} + ) + ); + my $exit = $self->get_severity(label => 'default', section => 'psu', name => $name, value => $result->{health_status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Power supply '%s' status is '%s'", + $instance, + $result->{health_status} + ) + ); + } + } +} + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/controllers.pm b/storage/huawei/oceanstor/snmp/mode/controllers.pm new file mode 100644 index 000000000..076372e8b --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/controllers.pm @@ -0,0 +1,213 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::controllers; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'health status: %s [running status: %s]', + $self->{result_values}->{health_status}, + $self->{result_values}->{running_status} + ); +} + +sub ctrl_long_output { + my ($self, %options) = @_; + + return sprintf( + "checking controller '%s'", + $options{instance_value}->{id} + ); +} + +sub prefix_ctrl_output { + my ($self, %options) = @_; + + return sprintf( + "controller '%s' ", + $options{instance_value}->{id} + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'controllers', type => 3, cb_prefix_output => 'prefix_ctrl_output', cb_long_output => 'ctrl_long_output', + indent_long_output => ' ', message_multiple => 'All controllers are ok', + group => [ + { name => 'status', type => 0, skipped_code => { -10 => 1 } }, + { name => 'cpu', type => 0, skipped_code => { -10 => 1 } }, + { name => 'memory', type => 0, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{status} = [ + { + label => 'status', + type => 2, + warning_default => '%{health_status} =~ /degraded|partially broken/i', + critical_default => '%{health_status} =~ /fault|fail/i', + set => { + key_values => [ { name => 'health_status' }, { name => 'running_status' }, { name => 'id' } ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{cpu} = [ + { label => 'cpu-utilization', nlabel => 'controller.cpu.utilization.percentage', set => { + key_values => [ { name => 'cpu_usage' } ], + output_template => 'cpu usage: %.2f %%', + perfdatas => [ + { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + } + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'memory-usage', nlabel => 'controller.memory.usage.percentage', set => { + key_values => [ { name => 'memory_usage' } ], + output_template => 'memory used: %.2f %%', + output_change_bytes => 1, + perfdatas => [ + { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-id:s' => { name => 'filter_id' } + }); + + return $self; +} + +my $mapping = { + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.2', map => $health_status }, # hwInfoControllerHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.3', map => $running_status }, # hwInfoControllerRunningStatus + cpu_usage => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.8' }, # hwInfoControllerCPUUsage + memory_usage => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.9' }, # hwInfoControllerMemoryUsage +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_controller_id = '.1.3.6.1.4.1.34774.4.1.23.5.2.1.1'; # hwInfoControllerID + my $snmp_result = $options{snmp}->get_table( + oid => $oid_controller_id, + nothing_quit => 1 + ); + + $self->{controllers} = {}; + foreach (keys %$snmp_result) { + /^$oid_controller_id\.(.*)$/; + my $instance = $1; + + if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' && + $snmp_result->{$_} !~ /$self->{option_results}->{filter_id}/) { + $self->{output}->output_add(long_msg => "skipping controller '" . $snmp_result->{$_} . "'.", debug => 1); + next; + } + + $self->{controllers}->{ $snmp_result->{$_} } = { + id => $snmp_result->{$_}, + instance => $instance + }; + } + + return if (scalar(keys %{$self->{controllers}}) <= 0); + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ map($_->{instance}, values(%{$self->{controllers}})) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + foreach (keys %{$self->{controllers}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $self->{controllers}->{$_}->{instance}); + + $self->{controllers}->{$_}->{memory} = { memory_usage => $result->{memory_usage} }; + $self->{controllers}->{$_}->{cpu} = { cpu_usage => $result->{cpu_usage} }; + $self->{controllers}->{$_}->{status} = { + running_status => $result->{running_status}, + health_status => $result->{health_status}, + id => $_ + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check controllers. + +=over 8 + +=item B<--filter-id> + +Filter controller by ID (can be a regexp). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{health_status}, %{running_status}, %{id} + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{health_status} =~ /degraded|partially broken/i'). +Can used special variables like: %{health_status}, %{running_status}, %{id} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{health_status} =~ /fault|fail/i'). +Can used special variables like: %{health_status}, %{running_status}, %{id} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'cpu-utilization', 'memory-usage'. + +=back + +=cut diff --git a/storage/huawei/oceanstor/snmp/mode/hardware.pm b/storage/huawei/oceanstor/snmp/mode/hardware.pm new file mode 100644 index 000000000..9354466f7 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/hardware.pm @@ -0,0 +1,113 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_numeric_check_section_option} = '^(?:enclosure\.temperature|disk\.temperature)$'; + + $self->{cb_hook2} = 'snmp_execute'; + $self->{thresholds} = { + default => [ + ['normal', 'OK'], + ['pre-fail', 'WARNING'], + ['fault', 'CRITICAL'], + ['degraded', 'WARNING'], + ['partially broken', 'WARNING'], + ['invalid', 'CRITICAL'] + ] + }; + + $self->{components_path} = 'storage::huawei::oceanstor::snmp::mode::components'; + $self->{components_module} = ['bbu', 'disk', 'enclosure', 'expboard', 'fan', 'psu']; +} + +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, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check hardware. + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'bbu', 'disk', 'enclosure', 'expboard', 'fan', 'psu'. + +=item B<--add-name-instance> + +Add literal description for instance value (used in filter and threshold options). + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=psu) +Can also exclude specific instance: --filter=psu,0.0A.0 + +=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,degraded' + +=item B<--warning> + +Set warning threshold for 'disk.temperature', 'enclosure.temperature' (syntax: type,regexp,threshold) +Example: --warning='enclosure.temperature,.*,40' + +=item B<--critical> + +Set critical threshold for 'disk.temperature', 'enclosure.temperature' (syntax: type,regexp,threshold) +Example: --critical='enclosure.temperature,.*,50' + +=back + +=cut diff --git a/storage/huawei/oceanstor/snmp/mode/listcontrollers.pm b/storage/huawei/oceanstor/snmp/mode/listcontrollers.pm new file mode 100644 index 000000000..633ed9fba --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/listcontrollers.pm @@ -0,0 +1,123 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::listcontrollers; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => { + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my $mapping = { + id => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.1' }, # hwInfoControllerID + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.2', map => $health_status }, # hwInfoControllerHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.5.2.1.3', map => $running_status }, # hwInfoControllerRunningStatus +}; +my $oid_controller_entry = '.1.3.6.1.4.1.34774.4.1.23.5.2.1'; # hwInfoControllerEntry + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_table( + oid => $oid_controller_entry, + end => $mapping->{running_status}->{oid} + ); + + my $controllers = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$mapping->{id}->{oid}\.(.*)$/); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $controllers->{$1} = $result; + } + + return $controllers; +} + +sub run { + my ($self, %options) = @_; + + my $controllers = $self->manage_selection(%options); + foreach (sort keys %$controllers) { + $self->{output}->output_add( + long_msg => sprintf( + '[id: %s] [health status: %s] [running status: %s]', + $controllers->{$_}->{id}, + $controllers->{$_}->{health_status}, + $controllers->{$_}->{running_status} + ) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List controllers:' + ); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => [keys %$mapping]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $controllers = $self->manage_selection(%options); + foreach (sort keys %$controllers) { + $self->{output}->add_disco_entry( + %{$controllers->{$_}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List controllers. + +=over 8 + +=back + +=cut + diff --git a/storage/huawei/oceanstor/snmp/mode/liststoragepools.pm b/storage/huawei/oceanstor/snmp/mode/liststoragepools.pm new file mode 100644 index 000000000..0b9287e15 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/liststoragepools.pm @@ -0,0 +1,125 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::liststoragepools; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => { + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my $mapping = { + name => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.2' }, # hwInfoStoragePoolName + domain_name => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.4' }, # hwInfoStoragePoolDiskDomainName + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.5', map => $health_status }, # hwInfoStoragePoolHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.6', map => $running_status }, # hwInfoStoragePoolRunningStatus +}; +my $oid_sp_entry = '.1.3.6.1.4.1.34774.4.1.23.4.2.1'; # hwInfoStoragePoolEntry + +sub manage_selection { + my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_table( + oid => $oid_sp_entry, + end => $mapping->{running_status}->{oid} + ); + + my $sp = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $1); + $sp->{$1} = $result; + } + + return $sp; +} + +sub run { + my ($self, %options) = @_; + + my $sp = $self->manage_selection(%options); + foreach (sort keys %$sp) { + $self->{output}->output_add( + long_msg => sprintf( + '[name: %s] [domain name: %s] [health status: %s] [running status: %s]', + $sp->{$_}->{name}, + $sp->{$_}->{domain_name}, + $sp->{$_}->{health_status}, + $sp->{$_}->{running_status} + ) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List storage pools:' + ); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => [keys %$mapping]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $sp = $self->manage_selection(%options); + foreach (sort keys %$sp) { + $self->{output}->add_disco_entry( + %{$sp->{$_}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List storage pools. + +=over 8 + +=back + +=cut + diff --git a/storage/huawei/oceanstor/snmp/mode/resources.pm b/storage/huawei/oceanstor/snmp/mode/resources.pm new file mode 100644 index 000000000..ea11adc02 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/resources.pm @@ -0,0 +1,86 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::resources; + +use strict; +use warnings; +use Exporter; + +our $health_status; +our $running_status; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw($health_status $running_status); + +$health_status = { + 0 => '--', 1 => 'Normal', + 2 => 'Fault', 3 => 'Pre-Fail', + 4 => 'Partially Broken', 5 => 'Degraded', + 6 => 'Bad Sectors Found', 7 => 'Bit Errors Found', + 8 => 'Consistent', 9 => 'Inconsistent', + 10 => 'Busy', 11 => 'No Input', + 12 => 'Low Battery', 13 => 'Single Link Fault', + 14 => 'Invalid', 15 => 'Write Protect' +}; + +$running_status = { + 0 => '--', 1 => 'Normal', 2 => 'Running', + 3 => 'Not running', 4 => 'Not existed', + 5 => 'Sleep in high temperature', 6 => 'Starting', + 7 => 'Power failure rotection', 8 => 'Sping down', + 9 => 'Started', 10 => 'Link Up', 11 => 'Link Down', + 12 => 'Powering on', 13 => 'Powered off', 14 => 'Pre-copy', + 15 => 'Copyback', 16 => 'Reconstruction', 17 => 'Expansion', + 18 => 'Unformatted', 19 => 'Formatting', 20 => 'Unmapped', + 21 => 'Initial synchronizing', 22 => 'Consistent', + 23 => 'Synchronizing', 24 => 'Synchronized', + 25 => 'Unsynchronized', 26 => 'Split', 27 => 'Online', + 28 => 'Offline', 29 => 'Locked', 30 => 'Enabled', + 31 => 'Disabled', 32 => 'Balancing', 33 => 'To be recovered', + 34 => 'Interrupted', 35 => 'Invalid', 36 => 'Not start', + 37 => 'Queuing', 38 => 'Stopped', 39 => 'Copying', + 40 => 'Completed', 41 => 'Paused', 42 => 'Reverse synchronizing', + 43 => 'Activated', 44 => 'Restore', 45 => 'Inactive', + 46 => 'Idle', 47 => 'Powering off', 48 => 'Charging', + 49 => 'Charging completed', 50 => 'Discharging', + 51 => 'Upgrading', 52 => 'Power Lost', 53 => 'Initializing', + 54 => 'Apply change', 55 => 'Online disable', 56 => 'Offline disable', + 57 => 'Online frozen', 58 => 'Offline frozen', 59 => 'Closed', + 60 => 'Removing', 61 => 'In service', 62 => 'Out of service', + 63 => 'Running normal', 64 => 'Running fail', 65 => 'Running success', + 66 => 'Running success', 67 => 'Running failed', 68 => 'Waiting', + 69 => 'Canceling', 70 => 'Canceled', 71 => 'About to synchronize', + 72 => 'Synchronizing data', 73 => 'Failed to synchronize', + 74 => 'Fault', 75 => 'Migrating', 76 => 'Migrated', + 77 => 'Activating', 78 => 'Deactivating', 79 => 'Start failed', + 80 => 'Stop failed', 81 => 'Decommissioning', 82 => 'Decommissioned', + 83 => 'Recommissioning', 84 => 'Replacing node', 85 => 'Scheduling', + 86 => 'Pausing', 87 => 'Suspending', 88 => 'Suspended', 89 => 'Overload', + 90 => 'To be switch', 91 => 'Switching', 92 => 'To be cleanup', + 93 => 'Forced start', 94 => 'Error', 95 => 'Job completed', + 96 => 'Partition Migrating', 97 => 'Mount', 98 => 'Umount', + 99 => 'INSTALLING', 100 => 'To Be Synchronized', 101 => 'Connecting', + 102 => 'Service Switching', 103 => 'Power-on failed', 104 => 'REPAIRING', + 105 => 'abnormal', 106 => 'Deleting', 107 => 'Modifying', + 108 => 'Running(clearing data)', 109 => 'Running(synchronizing data)' +}; + +1; diff --git a/storage/huawei/oceanstor/snmp/mode/storagepools.pm b/storage/huawei/oceanstor/snmp/mode/storagepools.pm new file mode 100644 index 000000000..fd65900f2 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/mode/storagepools.pm @@ -0,0 +1,259 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::snmp::mode::storagepools; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use storage::huawei::oceanstor::snmp::mode::resources qw($health_status $running_status); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'health status: %s [running status: %s]', + $self->{result_values}->{health_status}, + $self->{result_values}->{running_status} + ); +} + +sub custom_space_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space}); + return sprintf( + 'space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space} + ); +} + +sub sp_long_output { + my ($self, %options) = @_; + + return sprintf( + "checking storage pool '%s' [domain: %s]", + $options{instance_value}->{name}, + $options{instance_value}->{domain_name} + ); +} + +sub prefix_sp_output { + my ($self, %options) = @_; + + return sprintf( + "storage pool '%s' [domain: %s] ", + $options{instance_value}->{name}, + $options{instance_value}->{domain_name} + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'sp', type => 3, cb_prefix_output => 'prefix_sp_output', cb_long_output => 'sp_long_output', + indent_long_output => ' ', message_multiple => 'All storage pools are ok', + group => [ + { name => 'status', type => 0, skipped_code => { -10 => 1 } }, + { name => 'space', type => 0, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{status} = [ + { + label => 'status', + type => 2, + warning_default => '%{health_status} =~ /degraded|partially broken/i', + critical_default => '%{health_status} =~ /fault|fail/i', + set => { + key_values => [ { name => 'health_status' }, { name => 'running_status' }, { name => 'id' } ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{space} = [ + { label => 'space-usage', nlabel => 'storage_pool.space.usage.bytes', set => { + key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_space_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'space-usage-free', nlabel => 'storage_pool.space.free.bytes', display_ok => 0, set => { + key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_space_usage_output'), + perfdatas => [ + { template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 } + ] + } + }, + { label => 'space-usage-prct', nlabel => 'storage_pool.space.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ], + closure_custom_output => $self->can('custom_space_usage_output'), + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-name:s' => { name => 'filter_name' }, + 'filter-domain-name:s' => { name => 'filter_domain_name' } + }); + + return $self; +} + +my $mapping = { + domain_name => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.4' }, # hwInfoStoragePoolDiskDomainName + health_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.5', map => $health_status }, # hwInfoStoragePoolHealthStatus + running_status => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.6', map => $running_status }, # hwInfoStoragePoolRunningStatus + total_space => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.7' }, # hwInfoStoragePoolTotalCapacity (MB) + free_space => { oid => '.1.3.6.1.4.1.34774.4.1.23.4.2.1.9' } # hwInfoStoragePoolFreeCapacity (MB) +}; + +sub manage_selection { + my ($self, %options) = @_; + + if ($options{snmp}->is_snmpv1()) { + $self->{output}->add_option_msg(short_msg => "Need to use SNMP v2c or v3."); + $self->{output}->option_exit(); + } + + my $oid_sp_name = '.1.3.6.1.4.1.34774.4.1.23.4.2.1.2'; # hwInfoStoragePoolName + my $snmp_result = $options{snmp}->get_table( + oid => $oid_sp_name, + nothing_quit => 1 + ); + + $self->{sp} = {}; + foreach (keys %$snmp_result) { + /^$oid_sp_name\.(.*)$/; + my $instance = $1; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $snmp_result->{$_} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping storage pool '" . $snmp_result->{$_} . "'.", debug => 1); + next; + } + + $self->{sp}->{ $snmp_result->{$_} } = { + name => $snmp_result->{$_}, + instance => $instance + }; + } + + return if (scalar(keys %{$self->{sp}}) <= 0); + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ map($_->{instance}, values(%{$self->{sp}})) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(); + foreach (keys %{$self->{sp}}) { + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $self->{sp}->{$_}->{instance}); + + if (defined($self->{option_results}->{filter_domain_name}) && $self->{option_results}->{filter_domain_name} ne '' && + $result->{domain_name} !~ /$self->{option_results}->{filter_domain_name}/) { + $self->{output}->output_add(long_msg => "skipping storage pool '" . $_ . "'.", debug => 1); + next; + } + + $self->{sp}->{$_}->{domain_name} = $result->{domain_name}; + $result->{total_space} *= 1024 * 1024; + $result->{free_space} *= 1024 * 1024; + $self->{sp}->{$_}->{space} = { + name => $_, + total_space => $result->{total_space}, + used_space => $result->{total_space} - $result->{free_space}, + free_space => $result->{free_space}, + prct_used_space => 100 - ($result->{free_space} * 100 / $result->{total_space}), + prct_free_space => ($result->{free_space} * 100 / $result->{total_space}) + }; + $self->{sp}->{$_}->{status} = { + running_status => $result->{running_status}, + health_status => $result->{health_status}, + name => $_, + domain_name => $result->{domain_name} + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check storage pools. + +=over 8 + +=item B<--filter-name> + +Filter storage pool by name (can be a regexp). + +=item B<--filter-domain-name> + +Filter storage pool by domain name (can be a regexp). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{health_status}, %{running_status}, %{name} + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{health_status} =~ /degraded|partially broken/i'). +Can used special variables like: %{health_status}, %{running_status}, %{name} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{health_status} =~ /fault|fail/i'). +Can used special variables like: %{health_status}, %{running_status}, %{name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'space-usage', 'space-usage-free', 'space-usage-prct'. + +=back + +=cut diff --git a/storage/huawei/oceanstor/snmp/plugin.pm b/storage/huawei/oceanstor/snmp/plugin.pm new file mode 100644 index 000000000..841b5e430 --- /dev/null +++ b/storage/huawei/oceanstor/snmp/plugin.pm @@ -0,0 +1,52 @@ +# +# Copyright 2021 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package storage::huawei::oceanstor::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} = { + 'controllers' => 'storage::huawei::oceanstor::snmp::mode::controllers', + 'hardware' => 'storage::huawei::oceanstor::snmp::mode::hardware', + 'list-controllers' => 'storage::huawei::oceanstor::snmp::mode::listcontrollers', + 'list-storage-pools' => 'storage::huawei::oceanstor::snmp::mode::liststoragepools', + 'storage-pools' => 'storage::huawei::oceanstor::snmp::mode::storagepools' + }; + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Huawei OceanStor in SNMP. + +=cut