From c7f45064c6603c605530e1659d5dfa2c06893713 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Mon, 2 Mar 2026 15:53:28 +0100 Subject: [PATCH 1/9] move network-extreme to network-extreme-standard --- .../snmp/mode/components/fan.pm | 2 +- .../snmp/mode/components/poe.pm | 2 +- .../snmp/mode/components/psu.pm | 2 +- .../snmp/mode/components/slot.pm | 2 +- .../snmp/mode/components/temperature.pm | 2 +- .../extreme/{ => standard}/snmp/mode/cpu.pm | 2 +- .../{ => standard}/snmp/mode/hardware.pm | 4 +-- .../{ => standard}/snmp/mode/interfaces.pm | 2 +- .../{ => standard}/snmp/mode/memory.pm | 2 +- .../extreme/{ => standard}/snmp/mode/stack.pm | 2 +- .../extreme/{ => standard}/snmp/plugin.pm | 12 +++---- tests/network/extreme/snmp/cpu.robot | 2 +- tests/network/extreme/snmp/hardware.robot | 2 +- tests/network/extreme/snmp/hardware.robot~ | 35 +++++++++++++++++++ tests/network/extreme/snmp/memory.robot | 2 +- tests/network/extreme/snmp/stack.robot | 2 +- 16 files changed, 56 insertions(+), 21 deletions(-) rename src/network/extreme/{ => standard}/snmp/mode/components/fan.pm (98%) rename src/network/extreme/{ => standard}/snmp/mode/components/poe.pm (98%) rename src/network/extreme/{ => standard}/snmp/mode/components/psu.pm (98%) rename src/network/extreme/{ => standard}/snmp/mode/components/slot.pm (98%) rename src/network/extreme/{ => standard}/snmp/mode/components/temperature.pm (97%) rename src/network/extreme/{ => standard}/snmp/mode/cpu.pm (99%) rename src/network/extreme/{ => standard}/snmp/mode/hardware.pm (96%) rename src/network/extreme/{ => standard}/snmp/mode/interfaces.pm (99%) rename src/network/extreme/{ => standard}/snmp/mode/memory.pm (99%) rename src/network/extreme/{ => standard}/snmp/mode/stack.pm (99%) rename src/network/extreme/{ => standard}/snmp/plugin.pm (73%) create mode 100644 tests/network/extreme/snmp/hardware.robot~ diff --git a/src/network/extreme/snmp/mode/components/fan.pm b/src/network/extreme/standard/snmp/mode/components/fan.pm similarity index 98% rename from src/network/extreme/snmp/mode/components/fan.pm rename to src/network/extreme/standard/snmp/mode/components/fan.pm index 54aa9ee541..4afd5fd858 100644 --- a/src/network/extreme/snmp/mode/components/fan.pm +++ b/src/network/extreme/standard/snmp/mode/components/fan.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::components::fan; +package network::extreme::standard::snmp::mode::components::fan; use strict; use warnings; diff --git a/src/network/extreme/snmp/mode/components/poe.pm b/src/network/extreme/standard/snmp/mode/components/poe.pm similarity index 98% rename from src/network/extreme/snmp/mode/components/poe.pm rename to src/network/extreme/standard/snmp/mode/components/poe.pm index 3581554e2c..1868bc9bc1 100644 --- a/src/network/extreme/snmp/mode/components/poe.pm +++ b/src/network/extreme/standard/snmp/mode/components/poe.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::components::poe; +package network::extreme::standard::snmp::mode::components::poe; use strict; use warnings; diff --git a/src/network/extreme/snmp/mode/components/psu.pm b/src/network/extreme/standard/snmp/mode/components/psu.pm similarity index 98% rename from src/network/extreme/snmp/mode/components/psu.pm rename to src/network/extreme/standard/snmp/mode/components/psu.pm index 1963873fc5..b71591e622 100644 --- a/src/network/extreme/snmp/mode/components/psu.pm +++ b/src/network/extreme/standard/snmp/mode/components/psu.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::components::psu; +package network::extreme::standard::snmp::mode::components::psu; use strict; use warnings; diff --git a/src/network/extreme/snmp/mode/components/slot.pm b/src/network/extreme/standard/snmp/mode/components/slot.pm similarity index 98% rename from src/network/extreme/snmp/mode/components/slot.pm rename to src/network/extreme/standard/snmp/mode/components/slot.pm index e67302259b..ee8f9f6542 100644 --- a/src/network/extreme/snmp/mode/components/slot.pm +++ b/src/network/extreme/standard/snmp/mode/components/slot.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::components::slot; +package network::extreme::standard::snmp::mode::components::slot; use strict; use warnings; diff --git a/src/network/extreme/snmp/mode/components/temperature.pm b/src/network/extreme/standard/snmp/mode/components/temperature.pm similarity index 97% rename from src/network/extreme/snmp/mode/components/temperature.pm rename to src/network/extreme/standard/snmp/mode/components/temperature.pm index 2e0ea48051..86b399f372 100644 --- a/src/network/extreme/snmp/mode/components/temperature.pm +++ b/src/network/extreme/standard/snmp/mode/components/temperature.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::components::temperature; +package network::extreme::standard::snmp::mode::components::temperature; use strict; use warnings; diff --git a/src/network/extreme/snmp/mode/cpu.pm b/src/network/extreme/standard/snmp/mode/cpu.pm similarity index 99% rename from src/network/extreme/snmp/mode/cpu.pm rename to src/network/extreme/standard/snmp/mode/cpu.pm index 86ccc5f1a5..20f95d5ce2 100644 --- a/src/network/extreme/snmp/mode/cpu.pm +++ b/src/network/extreme/standard/snmp/mode/cpu.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::cpu; +package network::extreme::standard::snmp::mode::cpu; use base qw(centreon::plugins::templates::counter); diff --git a/src/network/extreme/snmp/mode/hardware.pm b/src/network/extreme/standard/snmp/mode/hardware.pm similarity index 96% rename from src/network/extreme/snmp/mode/hardware.pm rename to src/network/extreme/standard/snmp/mode/hardware.pm index d5c76655fd..a036e0fad0 100644 --- a/src/network/extreme/snmp/mode/hardware.pm +++ b/src/network/extreme/standard/snmp/mode/hardware.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::hardware; +package network::extreme::standard::snmp::mode::hardware; use base qw(centreon::plugins::templates::hardware); @@ -74,7 +74,7 @@ sub set_system { ], }; - $self->{components_path} = 'network::extreme::snmp::mode::components'; + $self->{components_path} = 'network::extreme::standard::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'slot', 'temperature', 'poe']; } diff --git a/src/network/extreme/snmp/mode/interfaces.pm b/src/network/extreme/standard/snmp/mode/interfaces.pm similarity index 99% rename from src/network/extreme/snmp/mode/interfaces.pm rename to src/network/extreme/standard/snmp/mode/interfaces.pm index ac4e328dc3..bd41a6c889 100644 --- a/src/network/extreme/snmp/mode/interfaces.pm +++ b/src/network/extreme/standard/snmp/mode/interfaces.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::interfaces; +package network::extreme::standard::snmp::mode::interfaces; use base qw(snmp_standard::mode::interfaces); diff --git a/src/network/extreme/snmp/mode/memory.pm b/src/network/extreme/standard/snmp/mode/memory.pm similarity index 99% rename from src/network/extreme/snmp/mode/memory.pm rename to src/network/extreme/standard/snmp/mode/memory.pm index 7af3ede40a..1ae89323f3 100644 --- a/src/network/extreme/snmp/mode/memory.pm +++ b/src/network/extreme/standard/snmp/mode/memory.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::memory; +package network::extreme::standard::snmp::mode::memory; use base qw(centreon::plugins::templates::counter); diff --git a/src/network/extreme/snmp/mode/stack.pm b/src/network/extreme/standard/snmp/mode/stack.pm similarity index 99% rename from src/network/extreme/snmp/mode/stack.pm rename to src/network/extreme/standard/snmp/mode/stack.pm index db6b4e9be8..10704f99c3 100644 --- a/src/network/extreme/snmp/mode/stack.pm +++ b/src/network/extreme/standard/snmp/mode/stack.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::mode::stack; +package network::extreme::standard::snmp::mode::stack; use base qw(centreon::plugins::templates::counter); diff --git a/src/network/extreme/snmp/plugin.pm b/src/network/extreme/standard/snmp/plugin.pm similarity index 73% rename from src/network/extreme/snmp/plugin.pm rename to src/network/extreme/standard/snmp/plugin.pm index 57a6a7f5a9..e13ed9b818 100644 --- a/src/network/extreme/snmp/plugin.pm +++ b/src/network/extreme/standard/snmp/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::extreme::snmp::plugin; +package network::extreme::standard::snmp::plugin; use strict; use warnings; @@ -31,12 +31,12 @@ sub new { $self->{version} = '1.0'; $self->{modes} = { - 'cpu' => 'network::extreme::snmp::mode::cpu', - 'hardware' => 'network::extreme::snmp::mode::hardware', - 'interfaces' => 'network::extreme::snmp::mode::interfaces', + 'cpu' => 'network::extreme::standard::snmp::mode::cpu', + 'hardware' => 'network::extreme::standard::snmp::mode::hardware', + 'interfaces' => 'network::extreme::standard::snmp::mode::interfaces', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', - 'memory' => 'network::extreme::snmp::mode::memory', - 'stack' => 'network::extreme::snmp::mode::stack' + 'memory' => 'network::extreme::standard::snmp::mode::memory', + 'stack' => 'network::extreme::standard::snmp::mode::stack' }; return $self; diff --git a/tests/network/extreme/snmp/cpu.robot b/tests/network/extreme/snmp/cpu.robot index cc1ec819bb..b9e33d9a5e 100644 --- a/tests/network/extreme/snmp/cpu.robot +++ b/tests/network/extreme/snmp/cpu.robot @@ -7,7 +7,7 @@ Test Timeout 120s *** Variables *** -${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::snmp::plugin +${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::standard::snmp::plugin *** Test Cases *** diff --git a/tests/network/extreme/snmp/hardware.robot b/tests/network/extreme/snmp/hardware.robot index 4e60d37c80..d619c420a4 100644 --- a/tests/network/extreme/snmp/hardware.robot +++ b/tests/network/extreme/snmp/hardware.robot @@ -7,7 +7,7 @@ Test Timeout 120s *** Variables *** -${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::snmp::plugin +${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::standard::snmp::plugin *** Test Cases *** diff --git a/tests/network/extreme/snmp/hardware.robot~ b/tests/network/extreme/snmp/hardware.robot~ new file mode 100644 index 0000000000..4e60d37c80 --- /dev/null +++ b/tests/network/extreme/snmp/hardware.robot~ @@ -0,0 +1,35 @@ +*** Settings *** +Resource ${CURDIR}${/}..${/}..${/}..${/}resources/import.resource + +Suite Setup Ctn Generic Suite Setup +Suite Teardown Ctn Generic Suite Teardown +Test Timeout 120s + + +*** Variables *** +${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::snmp::plugin + + +*** Test Cases *** +hardware-x435-8p-4s ${tc} + [Tags] network snmp + ${command} Catenate + ... ${CMD} + ... --mode=hardware + ... --hostname=${HOSTNAME} + ... --snmp-port=${SNMPPORT} + ... --snmp-community=network/extreme/snmp/x435-8p-4s + ... --component=${component} + ... ${extra_options} + + Ctn Run Command And Check Result As Strings ${command} ${expected_result} + + Examples: tc component extra_options expected_result -- + ... 1 ${EMPTY} ${EMPTY} OK: All 4 components are ok [1/1 poes, 1/1 power supplies, 1/1 slots, 1/1 temperatures]. | 'temp'=82C;;;; 'poe_power_1'=0.000W;;;0; 'count_poe'=1;;;; 'count_psu'=1;;;; 'count_slot'=1;;;; 'count_temperature'=1;;;; + ... 2 fan ${EMPTY} CRITICAL: No components are checked. + ... 3 psu ${EMPTY} OK: All 1 components are ok [1/1 power supplies]. | 'count_psu'=1;;;; + ... 4 slot ${EMPTY} OK: All 1 components are ok [1/1 slots]. | 'count_slot'=1;;;; + ... 5 temperature ${EMPTY} OK: All 1 components are ok [1/1 temperatures]. | 'temp'=82C;;;; 'count_temperature'=1;;;; + ... 5.1 temperature --warning='temperature,.*,25' WARNING: Temperature is 82 degree centigrade | 'temp'=82C;0:25;;; 'count_temperature'=1;;;; + ... 5.2 temperature --critical='temperature,.*,25' CRITICAL: Temperature is 82 degree centigrade | 'temp'=82C;;0:25;; 'count_temperature'=1;;;; + ... 6 poe ${EMPTY} OK: All 1 components are ok [1/1 poes]. | 'poe_power_1'=0.000W;;;0; 'count_poe'=1;;;; diff --git a/tests/network/extreme/snmp/memory.robot b/tests/network/extreme/snmp/memory.robot index b2a83bc23b..fcdf960630 100644 --- a/tests/network/extreme/snmp/memory.robot +++ b/tests/network/extreme/snmp/memory.robot @@ -7,7 +7,7 @@ Test Timeout 120s *** Variables *** -${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::snmp::plugin +${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::standard::snmp::plugin *** Test Cases *** diff --git a/tests/network/extreme/snmp/stack.robot b/tests/network/extreme/snmp/stack.robot index d8c7fa7bd6..78f610b5a2 100644 --- a/tests/network/extreme/snmp/stack.robot +++ b/tests/network/extreme/snmp/stack.robot @@ -7,7 +7,7 @@ Test Timeout 120s *** Variables *** -${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::snmp::plugin +${CMD} ${CENTREON_PLUGINS} --plugin=network::extreme::standard::snmp::plugin *** Test Cases *** From 786ab5ba85c0722cf65c7eef3b5dd6bb6e61508a Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Tue, 3 Mar 2026 10:03:02 +0100 Subject: [PATCH 2/9] init commit --- .../extreme/mlx/snmp/mode/components/board.pm | 90 ++++++ .../extreme/mlx/snmp/mode/components/fan.pm | 82 ++++++ .../extreme/mlx/snmp/mode/components/fan.pm~ | 82 ++++++ .../extreme/mlx/snmp/mode/components/psu.pm | 89 ++++++ .../mlx/snmp/mode/components/resources.pm | 36 +++ .../mlx/snmp/mode/components/temperature.pm | 95 ++++++ src/network/extreme/mlx/snmp/mode/cpu.pm | 120 ++++++++ src/network/extreme/mlx/snmp/mode/hardware.pm | 117 ++++++++ .../extreme/mlx/snmp/mode/listsfpports.pm | 144 +++++++++ src/network/extreme/mlx/snmp/mode/memory.pm | 90 ++++++ src/network/extreme/mlx/snmp/mode/sfpport.pm | 274 ++++++++++++++++++ src/network/extreme/mlx/snmp/plugin.pm | 56 ++++ 12 files changed, 1275 insertions(+) create mode 100644 src/network/extreme/mlx/snmp/mode/components/board.pm create mode 100644 src/network/extreme/mlx/snmp/mode/components/fan.pm create mode 100644 src/network/extreme/mlx/snmp/mode/components/fan.pm~ create mode 100644 src/network/extreme/mlx/snmp/mode/components/psu.pm create mode 100644 src/network/extreme/mlx/snmp/mode/components/resources.pm create mode 100644 src/network/extreme/mlx/snmp/mode/components/temperature.pm create mode 100644 src/network/extreme/mlx/snmp/mode/cpu.pm create mode 100644 src/network/extreme/mlx/snmp/mode/hardware.pm create mode 100644 src/network/extreme/mlx/snmp/mode/listsfpports.pm create mode 100644 src/network/extreme/mlx/snmp/mode/memory.pm create mode 100644 src/network/extreme/mlx/snmp/mode/sfpport.pm create mode 100644 src/network/extreme/mlx/snmp/plugin.pm diff --git a/src/network/extreme/mlx/snmp/mode/components/board.pm b/src/network/extreme/mlx/snmp/mode/components/board.pm new file mode 100644 index 0000000000..1f1337d20c --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/board.pm @@ -0,0 +1,90 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::board; + +use strict; +use warnings; + +my $mapping_board_status = { + 0 => 'moduleEmpty', + 2 => 'moduleGoingDown', + 3 => 'moduleRejected', + 4 => 'moduleBad', + 8 => 'moduleConfigured', + 9 => 'moduleComingUp', + 10 => 'moduleRunning', + 11 => 'moduleBlocked' +}; + +my $mapping = { + snAgentBrdMainBrdDescription => { oid => '.1.3.6.1.4.1.1991.1.1.2.2.1.1.2' }, + snAgentBrdModuleStatus => { oid => '.1.3.6.1.4.1.1991.1.1.2.2.1.1.12', map => $mapping_board_status } +}; +sub load { + my ($self) = @_; + + push @{$self->{request}}, + { oid => $mapping->{snAgentBrdMainBrdDescription}->{oid} }, + { oid => $mapping->{snAgentBrdModuleStatus}->{oid} }; +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking boards'); + $self->{components}->{board} = { name => 'boards', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'board')); + + my $result = { + %{$self->{results}->{ $mapping->{snAgentBrdMainBrdDescription}->{oid} }}, + %{$self->{results}->{ $mapping->{snAgentBrdModuleStatus}->{oid} }} + }; + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$result)) { + next if ($oid !~ /^$mapping->{snAgentBrdModuleStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $result, instance => $instance); + + next if ($self->check_filter(section => 'board', instance => $instance)); + $self->{components}->{board}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "board '%s' status is '%s' [instance: %s].", + $result->{snAgentBrdMainBrdDescription}, + $result->{snAgentBrdModuleStatus}, + $instance + ) + ); + my $exit = $self->get_severity(section => 'board', value => $result->{snAgentBrdModuleStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "board '%s' status is '%s'", + $result->{snAgentBrdMainBrdDescription}, + $result->{snAgentBrdModuleStatus} + ) + ); + } + } +} + +1; diff --git a/src/network/extreme/mlx/snmp/mode/components/fan.pm b/src/network/extreme/mlx/snmp/mode/components/fan.pm new file mode 100644 index 0000000000..6aa78f7600 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/fan.pm @@ -0,0 +1,82 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::fan; + +use strict; +use warnings; +use network::extreme::mlx::snmp::mode::components::resources qw($map_status); + +my $mapping = { + snChasFanDescription => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.2' }, + snChasFanOperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.3', map => $map_status } +}; +my $oid_snChasFan2Entry = '.1.3.6.1.4.1.1991.1.1.1.3.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_snChasFan2Entry, + start => $mapping->{snChasFanDescription}->{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_snChasFan2Entry}})) { + next if ($oid !~ /^$mapping->{snChasFanOperStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => + $mapping, + results => + $self->{results}->{$oid_snChasFan2Entry}, + instance => + $instance); + + next if ($self->check_filter(section => 'fan', instance => $instance)); + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "fan '%s' status is '%s' [instance = %s]", + $result->{snChasFanDescription}, $result->{snChasFanOperStatus}, $instance + ) + ); + + my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{snChasFanOperStatus}); + 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'", + $result->{snChasFanDescription}, $result->{snChasFanOperStatus} + ) + ); + } + } +} + +1; diff --git a/src/network/extreme/mlx/snmp/mode/components/fan.pm~ b/src/network/extreme/mlx/snmp/mode/components/fan.pm~ new file mode 100644 index 0000000000..30bc579c49 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/fan.pm~ @@ -0,0 +1,82 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::fan; + +use strict; +use warnings; +use network::extreme::mlx::snmp::mode::components::resources qw($map_status); + +my $mapping = { + snChasFan2Description => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.2' }, + snChasFan2OperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.3', map => $map_status } +}; +my $oid_snChasFan2Entry = '.1.3.6.1.4.1.1991.1.1.1.3.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_snChasFan2Entry, + start => $mapping->{snChasFan2Description}->{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_snChasFan2Entry}})) { + next if ($oid !~ /^$mapping->{snChasFan2OperStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => + $mapping, + results => + $self->{results}->{$oid_snChasFan2Entry}, + instance => + $instance); + + next if ($self->check_filter(section => 'fan', instance => $instance)); + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "fan '%s' status is '%s' [instance = %s]", + $result->{snChasFan2Description}, $result->{snChasFan2OperStatus}, $instance + ) + ); + + my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{snChasFan2OperStatus}); + 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'", + $result->{snChasFan2Description}, $result->{snChasFan2OperStatus} + ) + ); + } + } +} + +1; diff --git a/src/network/extreme/mlx/snmp/mode/components/psu.pm b/src/network/extreme/mlx/snmp/mode/components/psu.pm new file mode 100644 index 0000000000..0a6479633a --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/psu.pm @@ -0,0 +1,89 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::psu; + +use strict; +use warnings; +use network::extreme::mlx::snmp::mode::components::resources qw($map_status); + +my $mapping = { + snChasPwrSupplyDescription => { oid => '.1.3.6.1.4.1.1991.1.1.1.2.1.1.2' }, + snChasPwrSupplyOperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.2.1.1.3', map => $map_status } +}; +my $oid_snChasPwrSupply2Entry = '.1.3.6.1.4.1.1991.1.1.1.2.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_snChasPwrSupply2Entry, + start => $mapping->{snChasPwrSupplyDescription}->{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_snChasPwrSupply2Entry}})) { + next if ($oid !~ /^$mapping->{snChasPwrSupplyOperStatus}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => + $mapping, + results => + $self->{results}->{$oid_snChasPwrSupply2Entry}, + 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->{snChasPwrSupplyDescription}, + $result->{snChasPwrSupplyOperStatus}, + $instance + ) + ); + my $exit = $self->get_severity(label => + 'default', + section => + 'psu', + value => + $result->{snChasPwrSupplyOperStatus}); + 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->{snChasPwrSupplyDescription}, + $result->{snChasPwrSupplyOperStatus} + ) + ); + } + } +} + +1; diff --git a/src/network/extreme/mlx/snmp/mode/components/resources.pm b/src/network/extreme/mlx/snmp/mode/components/resources.pm new file mode 100644 index 0000000000..d0f7f5e1b1 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/resources.pm @@ -0,0 +1,36 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::resources; + +use strict; +use warnings; +use Exporter; + +our $map_status; + +our @ISA = qw(Exporter); +our @EXPORT_OK = qw($map_status); + +$map_status = { + 1 => 'other', 2 => 'normal', 3 => 'failure' +}; + +1; diff --git a/src/network/extreme/mlx/snmp/mode/components/temperature.pm b/src/network/extreme/mlx/snmp/mode/components/temperature.pm new file mode 100644 index 0000000000..66805988b3 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/components/temperature.pm @@ -0,0 +1,95 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::components::temperature; + +use strict; +use warnings; + +my $mapping = { + snAgentTempSensorDescr => { oid => '.1.3.6.1.4.1.1991.1.1.2.13.1.1.3' }, + snAgentTempValue => { oid => '.1.3.6.1.4.1.1991.1.1.2.13.1.1.4' }, +}; +my $oid_snAgentTempEntry = '.1.3.6.1.4.1.1991.1.1.2.13.1.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { + oid => $oid_snAgentTempEntry, + start => $mapping->{snAgentTempSensorDescr}->{oid} + }; +} + +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_snAgentTempEntry}})) { + next if ($oid !~ /^$mapping->{snAgentTempSensorDescr}->{oid}\.(.*)$/); + my $instance = $1; + next if ($self->{results}->{$oid_snAgentTempEntry}->{$oid} !~ /temperature/i); + my $result = $self->{snmp}->map_instance(mapping => + $mapping, + results => + $self->{results}->{$oid_snAgentTempEntry}, + instance => + $instance); + + next if ($self->check_filter(section => 'temperature', instance => $instance)); + if ($result->{snAgentTempValue} == 0) { + $self->{output}->output_add(long_msg => sprintf("skipping temperature '%s' (counter is 0)", + $result->{snAgentTempSensorDescr})); + next; + } + + $self->{components}->{temperature}->{total}++; + $self->{output}->output_add(long_msg => sprintf("temperature '%s' is %s C [instance = %s]", + $result->{snAgentTempSensorDescr}, $result->{snAgentTempValue}, $instance)); + + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => + 'temperature', + instance => + $instance, + value => + $result->{snAgentTempValue}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => + $exit, + short_msg => + sprintf("Temperature '%s' is %s C", + $result->{snAgentTempSensorDescr}, + $result->{snAgentTempValue})); + } + $self->{output}->perfdata_add( + label => 'temp', unit => 'C', + nlabel => 'hardware.temperature.celsius', + instances => $result->{snAgentTempSensorDescr}, + value => $result->{snAgentTempValue}, + warning => $warn, + critical => $crit, min => 0 + ); + } +} + +1; diff --git a/src/network/extreme/mlx/snmp/mode/cpu.pm b/src/network/extreme/mlx/snmp/mode/cpu.pm new file mode 100644 index 0000000000..dd9cec5f19 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/cpu.pm @@ -0,0 +1,120 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::cpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs are ok' } + ]; + + $self->{maps_counters}->{cpu} = [ + { label => 'utilization-5s', nlabel => 'cpu.utilization.5s.percentage', set => { + key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], + output_template => '%.2f %% (5s)', + perfdatas => [ + { value => 'cpu_5s', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + }, + { label => 'utilization-1m', nlabel => 'cpu.utilization.1m.percentage', set => { + key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], + output_template => '%.2f %% (1m)', + perfdatas => [ + { value => 'cpu_1m', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + }, + { label => 'utilization-5m', nlabel => 'cpu.utilization.5m.percentage', set => { + key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], + output_template => '%.2f %% (5m)', + perfdatas => [ + { value => 'cpu_5m', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + } + ]; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU '" . $options{instance_value}->{display} . "' usage: "; +} + +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; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_snAgentCpuUtilPercent = '.1.3.6.1.4.1.1991.1.1.2.11.1.1.5'; + my $snmp_result = $options{snmp}->get_table(oid => $oid_snAgentCpuUtilPercent, nothing_quit => 1); + + $self->{cpu} = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$oid_snAgentCpuUtilPercent\.(.*?)\.(.*?)\.60/); + my $instance = "slot$1:cpu$2"; + + $self->{cpu}->{$instance} = { + display => $instance, + cpu_5s => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.5' }, + cpu_1m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.60' }, + cpu_5m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.300' } + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check CPU usage. + +=over 8 + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'utilization-5s', 'utilization-1m', 'utilization-5m'. + +=back + +=cut diff --git a/src/network/extreme/mlx/snmp/mode/hardware.pm b/src/network/extreme/mlx/snmp/mode/hardware.pm new file mode 100644 index 0000000000..bac42c9756 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/hardware.pm @@ -0,0 +1,117 @@ +# +# Copyright 2024 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::extreme::mlx::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} = '^(?:temperature)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + default => [ + ['other', 'UNKNOWN'], + ['normal', 'OK'], + ['failure', 'CRITICAL'] + ], + board => [ + ['moduleEmpty', 'OK'], + ['moduleGoingDown', 'WARNING'], + ['moduleRejected', 'CRITICAL'], + ['moduleBad', 'CRITICAL'], + ['moduleConfigured', 'OK'], + ['moduleComingUp', 'OK'], + ['moduleRunning', 'OK'] + ] + }; + + $self->{components_path} = 'network::extreme::mlx::snmp::mode::components'; + $self->{components_module} = ['board', 'fan', 'psu', 'temperature']; +} + +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, 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: 'board', 'fan', 'temperature', 'psu'. + +=item B<--filter> + +Exclude the items given as a comma-separated list (example: --filter=fan --filter=psu). +You can also exclude items from specific instances: --filter=fan,1.1 + +=item B<--no-component> + +Define the expected status if no components are found (default: critical). + + +=item B<--threshold-overload> + +Use this option to override the status returned by the plugin when the status label matches a regular expression (syntax: section,[instance,]status,regexp). +Example: --threshold-overload='psu,CRITICAL,fail' + +=item B<--warning> + +Set warning threshold for 'temperature' (syntax: type,regexp,threshold) +Example: --warning='temperature,.*,30' + +=item B<--critical> + +Set critical threshold for 'temperature' (syntax: type,regexp,threshold) +Example: --critical='temperature,.*,50' + +=back + +=cut + diff --git a/src/network/extreme/mlx/snmp/mode/listsfpports.pm b/src/network/extreme/mlx/snmp/mode/listsfpports.pm new file mode 100644 index 0000000000..c221a9001d --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/listsfpports.pm @@ -0,0 +1,144 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::listsfpports; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options( + arguments => { + 'add-interface-name' => { name => 'add_interface_name' }, + }); + + return $self; +} + +my @labels = ('number'); + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + if (defined($self->{option_results}->{add_interface_name}) || defined($self->{option_results}->{add_interface_name})) { + push @labels, 'interface_name'; + } +} + +sub manage_selection { + my ($self, %options) = @_; + + # Select relevant oids for discovery function + my $mapping = { + sfpTemp => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.1' },# snIfOpticalMonitoringTemperature + }; + + my $snmp_result = $options{snmp}->get_multiple_table( + oids => [ + { oid => $mapping->{sfpTemp}->{oid} } + ], + return_type => 1, nothing_quit => 1 + ); + + my $results = {}; + my $names = undef; + my $oid_name = '.1.3.6.1.2.1.31.1.1.1.1'; + + if (defined($self->{option_results}->{add_interface_name}) || defined($self->{option_results}->{add_interface_name})) { + $names = $options{snmp}->get_table( + oid => $oid_name, + nothing_quit => 1 + ); + } + + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{sfpTemp}->{oid}\.(.*)$/); + + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + + $results->{$instance} = { + number => $instance, + interface_name => defined($names->{$oid_name . '.' . $instance}) ? + $names->{$oid_name . '.' . $instance} : '' + }; + } + + return $results; +} + +sub run { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach my $number (sort keys %$results) { + $self->{output}->output_add(long_msg => + join('', map("[$_: " . $results->{$number}->{$_} . ']', @labels)) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List SFP' + ); + $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 => [ @labels ]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $results = $self->manage_selection(snmp => $options{snmp}); + foreach (sort keys %$results) { + $self->{output}->add_disco_entry( + %{$results->{$_}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List SFP ports. + +=over 8 + +=item B<--add-interface-name> + +Add the corresponding interface name when set. + +=back + +=cut \ No newline at end of file diff --git a/src/network/extreme/mlx/snmp/mode/memory.pm b/src/network/extreme/mlx/snmp/mode/memory.pm new file mode 100644 index 0000000000..779fe936bc --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/memory.pm @@ -0,0 +1,90 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'memory', type => 0 } + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'memory-utilization', nlabel => 'memory.utilization.percentage', set => { + key_values => [ { name => 'memory_usage' } ], + output_template => 'memory usage is: %.2f%%', + perfdatas => [ + { template => '%.2f', unit => '%', min => 0, max => 100 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_agentCurrentMemoryUtilization = '.1.3.6.1.4.1.1991.1.1.2.12.4.1.0'; + my $snmp_result = $options{snmp}->get_leef( + oids => [ $oid_agentCurrentMemoryUtilization ], + nothing_quit => 1 + ); + + $self->{memory} = { memory_usage => $snmp_result->{$oid_agentCurrentMemoryUtilization} }; +} + +1; + +__END__ + +=head1 MODE + +Check Memory usage. + +=over 8 + +=item B<--warning-memory-utilization> + +Warning threshold in percent. + +=item B<--critical-memory-utilization> + +Critical threshold in percent. + +=back + +=cut diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm new file mode 100644 index 0000000000..f1ce79ad06 --- /dev/null +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -0,0 +1,274 @@ +# +# Copyright 2024 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::extreme::mlx::snmp::mode::sfpport; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub sfp_long_output { + my ($self, %options) = @_; + + return sprintf( + "checking sfp port '%s' - Temp: %.2f C - RX: %.2f dBm - TX: %.2f dBm - Bias: %s mA ", + $options{instance}, + $options{instance_value}->{temperature}->{temperature}, + $options{instance_value}->{perf}->{rx_input_dbm}, + $options{instance_value}->{perf}->{tx_output_dbm}, + $options{instance_value}->{perf}->{bias_current}, + ); +} + +sub prefix_sfp_output { + my ($self, %options) = @_; + + return sprintf( + "sfp port '%s' ", + $options{instance} + ); +} + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + "Temp: %s, RX: %s, TX: %s, Bias: %s", + $self->{result_values}->{temp_status}, + $self->{result_values}->{rx_power_status}, + $self->{result_values}->{tx_power_status}, + $self->{result_values}->{bias_status}, + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { + name => 'sfp', + type => 3, + cb_prefix_output => 'prefix_sfp_output', + cb_long_output => 'sfp_long_output', + indent_long_output => ' ', + message_multiple => 'All sfp ports are ok', + group => + [ + { name => 'status', type => 0, skipped_code => { -10 => 1 } }, + { name => 'perf', type => 0, skipped_code => { -10 => 1 } }, + { name => 'temperature', type => 0, skipped_code => { -10 => 1 } }, + ] + } + ]; + + $self->{maps_counters}->{status} = [ + { + label => 'status', + type => 2, + critical_default => + '%{temp_status} =~ /alarm/ || %{tx_power_status} =~ /alarm/ || %{rx_power_status} =~ /alarm/ || %{bias_status} =~ /alarm/', + warning_default => + '%{temp_status} =~ /warn/ || %{tx_power_status} =~ /warn/ || %{rx_power_status} =~ /warn/ || %{bias_status} =~ /warn/', + unknown_default => + '%{temp_status} =~ /unknown/ || %{tx_power_status} =~ /unknown/ || %{rx_power_status} =~ /unknown/ || %{bias_status} =~ /unknown/', + set => + { + key_values => [ + { name => 'port' }, + { name => 'temp_status' }, + { name => 'tx_power_status' }, + { name => 'rx_power_status' }, + { name => 'bias_status' } + ], + 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}->{perf} = [ + { label => 'rx-input-power-dbm', display_ok => 0, nlabel => 'port.input.power.dbm', set => { + key_values => [ { name => 'rx_input_dbm' } ], + output_template => 'input power: %.2f dBm', + perfdatas => [ + { template => '%.2f', unit => 'dBm', label_extra_instance => 1 } + ] + } + }, + { label => 'tx-output-power-dbm', display_ok => 0, nlabel => 'port.output.power.dbm', set => { + key_values => [ { name => 'tx_output_dbm' } ], + output_template => 'output power: %.2f dBm', + perfdatas => [ + { template => '%.2f', unit => 'dBm', label_extra_instance => 1 } + ] + } + }, + { label => 'bias-current', display_ok => 0, nlabel => 'port.bias.current.milliampere', set => { + key_values => [ { name => 'bias_current' } ], + output_template => 'Bias Current : %.2f mA', + perfdatas => [ + { template => '%.2f', unit => 'mA', label_extra_instance => 1, instance_use => 'display' } + ] + } + } + ]; + + $self->{maps_counters}->{temperature} = [ + { label => 'temperature', display_ok => 0, nlabel => 'port.temperature.celsius', set => { + key_values => [ { name => 'temperature' } ], + output_template => 'temperature: %.2f C', + perfdatas => [ + { template => '%s', unit => 'C', 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-port:s' => { name => 'filter_port' } }); + + return $self; +} + +my $mapping = { + sfpTxdBmPower => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.2' },# snIfOpticalMonitoringTxPower + sfpRxdBmPower => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.3' },# snIfOpticalMonitoringRxPower + sfpTxBiasCurrent => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.4' },# snIfOpticalMonitoringTxBiasCurrent + sfpTemp => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.1' },# snIfOpticalMonitoringTemperature +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_port = '.1.3.6.1.4.1.1991.1.1.3.3.6.1';# snIfOpticalMonitoringInfoEntry + my $snmp_result = $options{snmp}->get_table(oid => $oid_port, nothing_quit => 1); + + $self->{sfp} = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$mapping->{sfpTemp}->{oid}\.(.*)$/); + my $instance = $1; + + if (defined($self->{option_results}->{filter_port}) && $self->{option_results}->{filter_port} ne '' && + $instance !~ /$self->{option_results}->{filter_port}/) { + $self->{output}->output_add(long_msg => "skipping '" . $instance . "': no matching filter.", debug => 1); + next; + } + + $self->{sfp}->{$instance} = { + instance => $instance, + status => { port => $instance }, + perf => {}, + temperature => {} + }; + } + + if (scalar(keys %{$self->{sfp}}) <= 0) { + $self->{output}->add_option_msg(short_msg => 'No sfp port found.'); + $self->{output}->option_exit(); + } + + $options{snmp}->load( + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ map($_->{instance}, values(%{$self->{sfp}})) ], + instance_regexp => '^(.*)$' + ); + $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); + + foreach (keys %{$self->{sfp}}) { + my $result = $options{snmp}->map_instance( + mapping => $mapping, + results => $snmp_result, + instance => $self->{sfp}->{$_}->{instance} + ); + + my ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTemp}); + $self->{sfp}->{$_}->{status}->{temp_status} = join ' ', @status; + $self->{sfp}->{$_}->{temperature}->{temperature} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + + ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpRxdBmPower}); + $self->{sfp}->{$_}->{perf}->{rx_input_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$_}->{status}->{rx_power_status} = join ' ', @status;; + + ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTxdBmPower}); + $self->{sfp}->{$_}->{perf}->{tx_output_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$_}->{status}->{tx_power_status} = join ' ', @status;; + + ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTxBiasCurrent}); + $self->{sfp}->{$_}->{perf}->{bias_current} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$_}->{status}->{bias_status} = join ' ', @status;; + } +} + +sub normalize_oid_value { + my ($self, %options) = @_; + + # Remove optional trailing colon from unit (e.g. "C:") + $options{value} =~ s/://; + $options{value} =~ s/^\s+//;# remove leading spaces + $options{value} =~ s/\s+$//;# remove trailing spaces + + return $options{value} +} + +1; + +__END__ + +=head1 MODE + +Check SFP port. + +=over 8 + +=item B<--filter-port> + +Filter ports by index (can be a regexp). + +=item B<--unknown-status> + +Define the conditions to match for the status to be WARNING (default: '%{temp_status} =~ /unknown/ || %{tx_power_status} =~ /unknown/ || %{rx_power_status} =~ /unknown/ || %{bias_status} =~ /unknown/'). +You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_power_status}, %{bias_status} + +=item B<--warning-status> + +Define the conditions to match for the status to be WARNING (default: '%{temp_status} =~ /warn/ || %{tx_power_status} =~ /warn/ || %{rx_power_status} =~ /warn/ || %{bias_status} =~ /warn/'). +You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_power_status}, %{bias_status} + +=item B<--critical-status> + +Define the conditions to match for the status to be CRITICAL '%{temp_status} =~ /alarm/ || %{tx_power_status} =~ /alarm/ || %{rx_power_status} =~ /alarm/ || %{bias_status} =~ /alarm/'). +You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_power_status}, %{bias_status} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: C, C, C, C, C. + +=back + +=cut \ No newline at end of file diff --git a/src/network/extreme/mlx/snmp/plugin.pm b/src/network/extreme/mlx/snmp/plugin.pm new file mode 100644 index 0000000000..e0689a9a9c --- /dev/null +++ b/src/network/extreme/mlx/snmp/plugin.pm @@ -0,0 +1,56 @@ +# +# Copyright 2024 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::extreme::mlx::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.5'; + $self->{modes} = { + 'cpu' => 'network::extreme::mlx::snmp::mode::cpu', + 'hardware' => 'network::extreme::mlx::snmp::mode::hardware', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'list-sfp-ports' => 'network::extreme::mlx::snmp::mode::listsfpports', + 'memory' => 'network::extreme::mlx::snmp::mode::memory', + 'tcp-con' => 'snmp_standard::mode::tcpcon', + 'udp-con' => 'snmp_standard::mode::udpcon', + 'uptime' => 'snmp_standard::mode::uptime', + }; + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Extreme Networks MLXe series in SNMP. + +=cut From 5e59574fccf9d985603363787205a5ace824eeab Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Wed, 4 Mar 2026 15:02:23 +0100 Subject: [PATCH 3/9] extreme-mlx: add sfp-port --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 2 +- src/network/extreme/mlx/snmp/plugin.pm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index f1ce79ad06..7b0ab5c1ca 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -267,7 +267,7 @@ You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_po =item B<--warning-*> B<--critical-*> Thresholds. -Can be: C, C, C, C, C. +Can be: C, C, C, C. =back diff --git a/src/network/extreme/mlx/snmp/plugin.pm b/src/network/extreme/mlx/snmp/plugin.pm index e0689a9a9c..2ab9299e29 100644 --- a/src/network/extreme/mlx/snmp/plugin.pm +++ b/src/network/extreme/mlx/snmp/plugin.pm @@ -37,6 +37,7 @@ sub new { 'list-interfaces' => 'snmp_standard::mode::listinterfaces', 'list-sfp-ports' => 'network::extreme::mlx::snmp::mode::listsfpports', 'memory' => 'network::extreme::mlx::snmp::mode::memory', + 'sfp-port' => 'network::extreme::mlx::snmp::mode::sfpport', 'tcp-con' => 'snmp_standard::mode::tcpcon', 'udp-con' => 'snmp_standard::mode::udpcon', 'uptime' => 'snmp_standard::mode::uptime', From 517de2612d9cc960b2cb8599e7b453c3e30774f8 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Wed, 4 Mar 2026 15:42:07 +0100 Subject: [PATCH 4/9] --add-interface-name --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 32 +++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index 7b0ab5c1ca..a117d85550 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -42,10 +42,12 @@ sub sfp_long_output { sub prefix_sfp_output { my ($self, %options) = @_; - return sprintf( - "sfp port '%s' ", - $options{instance} - ); + my $output = sprintf("sfp port '%s' - ", $options{instance}); + if (defined($options{instance_value}->{interface}) && $options{instance_value}->{interface} ne '') { + $output .= "$options{instance_value}->{interface} - "; + } + + return $output; } sub custom_status_output { @@ -150,7 +152,12 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - $options{options}->add_options(arguments => { 'filter-port:s' => { name => 'filter_port' } }); + $options{options}->add_options( + arguments => { + 'filter-port:s' => { name => 'filter_port' }, + 'add-interface-name' => { name => 'add_interface_name' }, + } + ); return $self; } @@ -179,8 +186,19 @@ sub manage_selection { next; } + my $interface_name = undef; + if (defined($self->{option_results}->{add_interface_name}) || defined($self->{option_results}->{add_interface_name})) { + my $interface_oid = '.1.3.6.1.2.1.31.1.1.1.1' . '.' . $instance; + my $temp_snmp_result = $options{snmp}->get_leef( + oids => [ $interface_oid ], + nothing_quit => 1 + ); + $interface_name = $temp_snmp_result->{$interface_oid}; + } + $self->{sfp}->{$instance} = { instance => $instance, + interface => $interface_name, status => { port => $instance }, perf => {}, temperature => {} @@ -249,6 +267,10 @@ Check SFP port. Filter ports by index (can be a regexp). +=item B<--add-interface-name> + +Add the corresponding interface name when set. Used for the instance name in perf data, too. + =item B<--unknown-status> Define the conditions to match for the status to be WARNING (default: '%{temp_status} =~ /unknown/ || %{tx_power_status} =~ /unknown/ || %{rx_power_status} =~ /unknown/ || %{bias_status} =~ /unknown/'). From a94e5c3e6bee16d56364f1a69cf28901784167f4 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Wed, 8 Apr 2026 15:43:52 +0200 Subject: [PATCH 5/9] introduce centreon::plugins::statefile to cache and reduce snmp requests --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 175 ++++++++++++++----- 1 file changed, 128 insertions(+), 47 deletions(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index a117d85550..41800618a0 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -25,6 +25,7 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use centreon::plugins::statefile; sub sfp_long_output { my ($self, %options) = @_; @@ -110,23 +111,23 @@ sub set_counters { $self->{maps_counters}->{perf} = [ { label => 'rx-input-power-dbm', display_ok => 0, nlabel => 'port.input.power.dbm', set => { - key_values => [ { name => 'rx_input_dbm' } ], + key_values => [ { name => 'rx_input_dbm' }, { name => 'display' } ], output_template => 'input power: %.2f dBm', perfdatas => [ - { template => '%.2f', unit => 'dBm', label_extra_instance => 1 } + { template => '%.2f', unit => 'dBm', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'tx-output-power-dbm', display_ok => 0, nlabel => 'port.output.power.dbm', set => { - key_values => [ { name => 'tx_output_dbm' } ], + key_values => [ { name => 'tx_output_dbm' }, { name => 'display' } ], output_template => 'output power: %.2f dBm', perfdatas => [ - { template => '%.2f', unit => 'dBm', label_extra_instance => 1 } + { template => '%.2f', unit => 'dBm', label_extra_instance => 1, instance_use => 'display' } ] } }, { label => 'bias-current', display_ok => 0, nlabel => 'port.bias.current.milliampere', set => { - key_values => [ { name => 'bias_current' } ], + key_values => [ { name => 'bias_current' }, { name => 'display' } ], output_template => 'Bias Current : %.2f mA', perfdatas => [ { template => '%.2f', unit => 'mA', label_extra_instance => 1, instance_use => 'display' } @@ -137,10 +138,10 @@ sub set_counters { $self->{maps_counters}->{temperature} = [ { label => 'temperature', display_ok => 0, nlabel => 'port.temperature.celsius', set => { - key_values => [ { name => 'temperature' } ], + key_values => [ { name => 'temperature' }, { name => 'display' } ], output_template => 'temperature: %.2f C', perfdatas => [ - { template => '%s', unit => 'C', label_extra_instance => 1 } + { template => '%s', unit => 'C', label_extra_instance => 1, instance_use => 'display' } ] } } @@ -154,14 +155,25 @@ sub new { $options{options}->add_options( arguments => { - 'filter-port:s' => { name => 'filter_port' }, - 'add-interface-name' => { name => 'add_interface_name' }, + 'filter-port:s' => { name => 'filter_port' }, + 'filter-interface:s' => { name => 'filter_interface' }, + 'add-interface-name' => { name => 'add_interface_name' }, + 'reload-cache-time:s' => { name => 'reload_cache_time', default => 180 }, + 'show-cache' => { name => 'show_cache' }, } ); + $self->{statefile_cache} = centreon::plugins::statefile->new(%options); return $self; } +sub check_options { + my ($self, %options) = @_; + + $self->SUPER::check_options(%options); + $self->{statefile_cache}->check_options(%options); +} + my $mapping = { sfpTxdBmPower => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.2' },# snIfOpticalMonitoringTxPower sfpRxdBmPower => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.3' },# snIfOpticalMonitoringRxPower @@ -169,76 +181,141 @@ my $mapping = { sfpTemp => { oid => '.1.3.6.1.4.1.1991.1.1.3.3.6.1.1' },# snIfOpticalMonitoringTemperature }; -sub manage_selection { +sub reload_cache { my ($self, %options) = @_; + my $datas = {}; - my $oid_port = '.1.3.6.1.4.1.1991.1.1.3.3.6.1';# snIfOpticalMonitoringInfoEntry - my $snmp_result = $options{snmp}->get_table(oid => $oid_port, nothing_quit => 1); + $datas->{last_timestamp} = time(); + $datas->{sfp} = {}; + my $snmp_names = {}; - $self->{sfp} = {}; - foreach my $oid (keys %$snmp_result) { - next if ($oid !~ /^$mapping->{sfpTemp}->{oid}\.(.*)$/); + if (defined($self->{option_results}->{add_interface_name}) || defined($self->{option_results}->{add_interface_name})) { + my $oid_interface_name = '.1.3.6.1.2.1.31.1.1.1.1'; + my $result = $options{snmp}->get_table( + oid => $oid_interface_name, + ); + + foreach my $key (keys %$result) { + next if $key !~ /^$oid_interface_name\.(.*)$/; + my $instance = $1; + + $snmp_names->{$instance} = $self->{output}->decode($result->{$key}); + } + } + + my $oid_snIfOpticalMonitoringInfoEntry = '.1.3.6.1.4.1.1991.1.1.3.3.6.1'; + my $result = $options{snmp}->get_table( + oid => $oid_snIfOpticalMonitoringInfoEntry, + ); + + foreach my $key (keys %$result) { + next if ($key !~ /^$mapping->{sfpTemp}->{oid}\.(.*)$/); my $instance = $1; + $datas->{sfp}->{$instance} = exists($snmp_names->{$instance}) ? $snmp_names->{$instance} : ""; + } + + if (scalar(keys %{$datas->{sfp}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "Can't construct cache..."); + $self->{output}->option_exit(); + } + + $self->{statefile_cache}->write(data => $datas); + return $datas->{sfp}; +} + +sub get_selection { + my ($self, %options) = @_; + + # init cache file + my $has_cache_file = $self->{statefile_cache}->read(statefile => + 'cache_snmpstandard_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode}); + if (defined($self->{option_results}->{show_cache})) { + $self->{output}->add_option_msg(long_msg => $self->{statefile_cache}->get_string_content()); + $self->{output}->option_exit(); + } + + my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); + my $sfp_ports = $self->{statefile_cache}->get(name => 'sfp'); + if ($has_cache_file == 0 || !defined($timestamp_cache) || !defined($sfp_ports) || ((time() - $timestamp_cache) > (($self->{option_results}->{reload_cache_time}) * 60))) { + $sfp_ports = $self->reload_cache(snmp => $options{snmp}); + $self->{statefile_cache}->read(); + } + + my $results = {}; + foreach (keys %$sfp_ports) { if (defined($self->{option_results}->{filter_port}) && $self->{option_results}->{filter_port} ne '' && - $instance !~ /$self->{option_results}->{filter_port}/) { - $self->{output}->output_add(long_msg => "skipping '" . $instance . "': no matching filter.", debug => 1); + $_ !~ /$self->{option_results}->{filter_port}/) { + $self->{output}->output_add(long_msg => "skipping '" . $_ . "': no matching filter.", debug => 1); next; } - my $interface_name = undef; - if (defined($self->{option_results}->{add_interface_name}) || defined($self->{option_results}->{add_interface_name})) { - my $interface_oid = '.1.3.6.1.2.1.31.1.1.1.1' . '.' . $instance; - my $temp_snmp_result = $options{snmp}->get_leef( - oids => [ $interface_oid ], - nothing_quit => 1 + if (defined($self->{option_results}->{add_interface_name}) && + defined($self->{option_results}->{filter_interface}) && $self->{option_results}->{filter_interface} ne '' && + $sfp_ports->{$_} !~ /$self->{option_results}->{filter_interface}/) { + $self->{output}->output_add( + long_msg => "skipping '" . $sfp_ports->{$_} . "': no matching filter.", + debug => 1 ); - $interface_name = $temp_snmp_result->{$interface_oid}; + next; } - $self->{sfp}->{$instance} = { - instance => $instance, - interface => $interface_name, - status => { port => $instance }, - perf => {}, - temperature => {} - }; + $results->{$_} = $sfp_ports->{$_}; } - if (scalar(keys %{$self->{sfp}}) <= 0) { - $self->{output}->add_option_msg(short_msg => 'No sfp port found.'); + if (scalar(keys %$results) <= 0) { + $self->{output}->add_option_msg(short_msg => "No sfp ports found. Can be: filters, cache file."); $self->{output}->option_exit(); } + return $results; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $sfp_ports = $self->get_selection(snmp => $options{snmp}); + $options{snmp}->load( - oids => [ map($_->{oid}, values(%$mapping)) ], - instances => [ map($_->{instance}, values(%{$self->{sfp}})) ], - instance_regexp => '^(.*)$' + oids => [ map($_->{oid}, values(%$mapping)) ], + instances => [ keys %$sfp_ports ], + nothing_quit => 1 ); - $snmp_result = $options{snmp}->get_leef(nothing_quit => 1); + my $snmp_result = $options{snmp}->get_leef(); + + $self->{sfp} = {}; + + foreach (keys %$sfp_ports) { + my $instance = $_; - foreach (keys %{$self->{sfp}}) { my $result = $options{snmp}->map_instance( mapping => $mapping, results => $snmp_result, - instance => $self->{sfp}->{$_}->{instance} + instance => $instance ); + $self->{sfp}->{$instance}->{interface} = $sfp_ports->{$instance}; + + $self->{sfp}->{$instance}->{status}->{port} = $instance; my ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTemp}); - $self->{sfp}->{$_}->{status}->{temp_status} = join ' ', @status; - $self->{sfp}->{$_}->{temperature}->{temperature} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$instance}->{status}->{temp_status} = join ' ', @status; + $self->{sfp}->{$instance}->{temperature}->{temperature} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$instance}->{temperature}->{display} = defined($self->{option_results}->{add_interface_name}) ? + $instance . '-' . $sfp_ports->{$instance} : $instance; ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpRxdBmPower}); - $self->{sfp}->{$_}->{perf}->{rx_input_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); - $self->{sfp}->{$_}->{status}->{rx_power_status} = join ' ', @status;; + $self->{sfp}->{$instance}->{perf}->{rx_input_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$instance}->{status}->{rx_power_status} = join ' ', @status; + $self->{sfp}->{$instance}->{perf}->{display} = defined($self->{option_results}->{add_interface_name}) ? + $instance . '-' . $sfp_ports->{$instance} : $instance; ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTxdBmPower}); - $self->{sfp}->{$_}->{perf}->{tx_output_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); - $self->{sfp}->{$_}->{status}->{tx_power_status} = join ' ', @status;; + $self->{sfp}->{$instance}->{perf}->{tx_output_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$instance}->{status}->{tx_power_status} = join ' ', @status; ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTxBiasCurrent}); - $self->{sfp}->{$_}->{perf}->{bias_current} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); - $self->{sfp}->{$_}->{status}->{bias_status} = join ' ', @status;; + $self->{sfp}->{$instance}->{perf}->{bias_current} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); + $self->{sfp}->{$instance}->{status}->{bias_status} = join ' ', @status; } } @@ -267,6 +344,10 @@ Check SFP port. Filter ports by index (can be a regexp). +=item B<--filter-interface> + +Filter ports by interface name (can be a regexp). Can be used only together with --add-interface-name. + =item B<--add-interface-name> Add the corresponding interface name when set. Used for the instance name in perf data, too. From fed2c743f4de3400023e3101a12981f6c54893ef Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Wed, 8 Apr 2026 16:29:53 +0200 Subject: [PATCH 6/9] better 'display' handling for instance for label_extra_instance --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 24 +++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index 41800618a0..24707322e8 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -43,12 +43,11 @@ sub sfp_long_output { sub prefix_sfp_output { my ($self, %options) = @_; - my $output = sprintf("sfp port '%s' - ", $options{instance}); - if (defined($options{instance_value}->{interface}) && $options{instance_value}->{interface} ne '') { - $output .= "$options{instance_value}->{interface} - "; - } - - return $output; + return sprintf( + "sfp port '%s'%s ", + $options{instance}, + $options{instance_value}->{interface} ne '' ? ' - ' . $options{instance_value}->{interface} : '' + ); } sub custom_status_output { @@ -294,20 +293,23 @@ sub manage_selection { instance => $instance ); - $self->{sfp}->{$instance}->{interface} = $sfp_ports->{$instance}; + my $display = defined($self->{option_results}->{add_interface_name}) ? + $instance . '-' . $sfp_ports->{$instance} : $instance; + + $self->{sfp}->{$instance}->{interface} = defined($self->{option_results}->{add_interface_name}) + && defined($sfp_ports->{$instance}) ? + $sfp_ports->{$instance} : ''; $self->{sfp}->{$instance}->{status}->{port} = $instance; my ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTemp}); $self->{sfp}->{$instance}->{status}->{temp_status} = join ' ', @status; $self->{sfp}->{$instance}->{temperature}->{temperature} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); - $self->{sfp}->{$instance}->{temperature}->{display} = defined($self->{option_results}->{add_interface_name}) ? - $instance . '-' . $sfp_ports->{$instance} : $instance; + $self->{sfp}->{$instance}->{temperature}->{display} = $display; ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpRxdBmPower}); $self->{sfp}->{$instance}->{perf}->{rx_input_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); $self->{sfp}->{$instance}->{status}->{rx_power_status} = join ' ', @status; - $self->{sfp}->{$instance}->{perf}->{display} = defined($self->{option_results}->{add_interface_name}) ? - $instance . '-' . $sfp_ports->{$instance} : $instance; + $self->{sfp}->{$instance}->{perf}->{display} = $display; ($value, $unit, @status) = split /\s+/, $self->normalize_oid_value(value => $result->{sfpTxdBmPower}); $self->{sfp}->{$instance}->{perf}->{tx_output_dbm} = $1 if ($value =~ /([-+]?[0-9]+(?:\.[0-9]+)?)/); From af9e5e79e1b55bea87145eb851266ccb8fc6def9 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Thu, 9 Apr 2026 15:25:24 +0200 Subject: [PATCH 7/9] add Safe -> get_display_value --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 34 +++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index 24707322e8..7855e5ed2d 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -26,6 +26,7 @@ use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::statefile; +use Safe; sub sfp_long_output { my ($self, %options) = @_; @@ -154,15 +155,20 @@ sub new { $options{options}->add_options( arguments => { - 'filter-port:s' => { name => 'filter_port' }, - 'filter-interface:s' => { name => 'filter_interface' }, - 'add-interface-name' => { name => 'add_interface_name' }, - 'reload-cache-time:s' => { name => 'reload_cache_time', default => 180 }, - 'show-cache' => { name => 'show_cache' }, + 'filter-port:s' => { name => 'filter_port' }, + 'filter-interface:s' => { name => 'filter_interface' }, + 'add-interface-name' => { name => 'add_interface_name' }, + 'reload-cache-time:s' => { name => 'reload_cache_time', default => 180 }, + 'show-cache' => { name => 'show_cache' }, + 'display-transform-src:s' => { name => 'display_transform_src' }, + 'display-transform-dst:s' => { name => 'display_transform_dst' } } ); $self->{statefile_cache} = centreon::plugins::statefile->new(%options); + $self->{safe} = Safe->new(); + $self->{safe}->share('$assign_var'); + return $self; } @@ -295,6 +301,7 @@ sub manage_selection { my $display = defined($self->{option_results}->{add_interface_name}) ? $instance . '-' . $sfp_ports->{$instance} : $instance; + $display = $self->get_display_value(value => $display); $self->{sfp}->{$instance}->{interface} = defined($self->{option_results}->{add_interface_name}) && defined($sfp_ports->{$instance}) ? @@ -332,6 +339,23 @@ sub normalize_oid_value { return $options{value} } +sub get_display_value { + my ($self, %options) = @_; + + our $assign_var = $options{value}; + if (defined($self->{option_results}->{display_transform_src})) { + $self->{option_results}->{display_transform_dst} = '' if (!defined($self->{option_results}->{display_transform_dst})); + + $self->{safe}->reval("\$assign_var =~ s{$self->{option_results}->{display_transform_src}}{$self->{option_results}->{display_transform_dst}}", + 1); + if ($@) { + die 'Unsafe code evaluation: ' . $@; + } + } + + return $assign_var; +} + 1; __END__ From 97ed5596158a12b97329feef70d2051d2ad7b923 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Fri, 10 Apr 2026 17:44:25 +0200 Subject: [PATCH 8/9] fix - don't request the entire table on cache reload but only on OID per instance --- src/network/extreme/mlx/snmp/mode/sfpport.pm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index 7855e5ed2d..cb8cf15ec7 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -208,9 +208,8 @@ sub reload_cache { } } - my $oid_snIfOpticalMonitoringInfoEntry = '.1.3.6.1.4.1.1991.1.1.3.3.6.1'; my $result = $options{snmp}->get_table( - oid => $oid_snIfOpticalMonitoringInfoEntry, + oid => $mapping->{sfpTemp}->{oid}, ); foreach my $key (keys %$result) { From 2a4b1c402713a6392fc62da282d0e94ce56513d3 Mon Sep 17 00:00:00 2001 From: rmorandell_pgum Date: Wed, 20 May 2026 14:39:24 +0200 Subject: [PATCH 9/9] refactor new plugin standard --- .../extreme/mlx/snmp/mode/components/board.pm | 2 +- .../extreme/mlx/snmp/mode/components/fan.pm | 13 ++- .../extreme/mlx/snmp/mode/components/fan.pm~ | 82 ---------------- .../extreme/mlx/snmp/mode/components/psu.pm | 24 +++-- .../mlx/snmp/mode/components/resources.pm | 2 +- .../mlx/snmp/mode/components/temperature.pm | 40 ++++---- src/network/extreme/mlx/snmp/mode/cpu.pm | 58 ++++++----- src/network/extreme/mlx/snmp/mode/hardware.pm | 2 +- .../extreme/mlx/snmp/mode/listsfpports.pm | 2 +- src/network/extreme/mlx/snmp/mode/memory.pm | 14 +-- src/network/extreme/mlx/snmp/mode/sfpport.pm | 96 ++++++++++++------- src/network/extreme/mlx/snmp/plugin.pm | 9 +- 12 files changed, 149 insertions(+), 195 deletions(-) delete mode 100644 src/network/extreme/mlx/snmp/mode/components/fan.pm~ diff --git a/src/network/extreme/mlx/snmp/mode/components/board.pm b/src/network/extreme/mlx/snmp/mode/components/board.pm index 1f1337d20c..2a353efa09 100644 --- a/src/network/extreme/mlx/snmp/mode/components/board.pm +++ b/src/network/extreme/mlx/snmp/mode/components/board.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for diff --git a/src/network/extreme/mlx/snmp/mode/components/fan.pm b/src/network/extreme/mlx/snmp/mode/components/fan.pm index 6aa78f7600..f7ef5a8268 100644 --- a/src/network/extreme/mlx/snmp/mode/components/fan.pm +++ b/src/network/extreme/mlx/snmp/mode/components/fan.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -49,12 +49,11 @@ sub check { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_snChasFan2Entry}})) { next if ($oid !~ /^$mapping->{snChasFanOperStatus}->{oid}\.(.*)$/); my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => - $mapping, - results => - $self->{results}->{$oid_snChasFan2Entry}, - instance => - $instance); + my $result = $self->{snmp}->map_instance( + mapping => $mapping, + results => $self->{results}->{$oid_snChasFan2Entry}, + instance => $instance + ); next if ($self->check_filter(section => 'fan', instance => $instance)); diff --git a/src/network/extreme/mlx/snmp/mode/components/fan.pm~ b/src/network/extreme/mlx/snmp/mode/components/fan.pm~ deleted file mode 100644 index 30bc579c49..0000000000 --- a/src/network/extreme/mlx/snmp/mode/components/fan.pm~ +++ /dev/null @@ -1,82 +0,0 @@ -# -# Copyright 2024 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::extreme::mlx::snmp::mode::components::fan; - -use strict; -use warnings; -use network::extreme::mlx::snmp::mode::components::resources qw($map_status); - -my $mapping = { - snChasFan2Description => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.2' }, - snChasFan2OperStatus => { oid => '.1.3.6.1.4.1.1991.1.1.1.3.1.1.3', map => $map_status } -}; -my $oid_snChasFan2Entry = '.1.3.6.1.4.1.1991.1.1.1.3.1.1'; - -sub load { - my ($self) = @_; - - push @{$self->{request}}, { - oid => $oid_snChasFan2Entry, - start => $mapping->{snChasFan2Description}->{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_snChasFan2Entry}})) { - next if ($oid !~ /^$mapping->{snChasFan2OperStatus}->{oid}\.(.*)$/); - my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => - $mapping, - results => - $self->{results}->{$oid_snChasFan2Entry}, - instance => - $instance); - - next if ($self->check_filter(section => 'fan', instance => $instance)); - - $self->{components}->{fan}->{total}++; - $self->{output}->output_add( - long_msg => sprintf( - "fan '%s' status is '%s' [instance = %s]", - $result->{snChasFan2Description}, $result->{snChasFan2OperStatus}, $instance - ) - ); - - my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{snChasFan2OperStatus}); - 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'", - $result->{snChasFan2Description}, $result->{snChasFan2OperStatus} - ) - ); - } - } -} - -1; diff --git a/src/network/extreme/mlx/snmp/mode/components/psu.pm b/src/network/extreme/mlx/snmp/mode/components/psu.pm index 0a6479633a..61aac8735c 100644 --- a/src/network/extreme/mlx/snmp/mode/components/psu.pm +++ b/src/network/extreme/mlx/snmp/mode/components/psu.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -49,12 +49,11 @@ sub check { foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_snChasPwrSupply2Entry}})) { next if ($oid !~ /^$mapping->{snChasPwrSupplyOperStatus}->{oid}\.(.*)$/); my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => - $mapping, - results => - $self->{results}->{$oid_snChasPwrSupply2Entry}, - instance => - $instance); + my $result = $self->{snmp}->map_instance( + mapping => $mapping, + results => $self->{results}->{$oid_snChasPwrSupply2Entry}, + instance => $instance + ); next if ($self->check_filter(section => 'psu', instance => $instance)); $self->{components}->{psu}->{total}++; @@ -67,12 +66,11 @@ sub check { $instance ) ); - my $exit = $self->get_severity(label => - 'default', - section => - 'psu', - value => - $result->{snChasPwrSupplyOperStatus}); + my $exit = $self->get_severity( + label => 'default', + section => 'psu', + value => $result->{snChasPwrSupplyOperStatus} + ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, diff --git a/src/network/extreme/mlx/snmp/mode/components/resources.pm b/src/network/extreme/mlx/snmp/mode/components/resources.pm index d0f7f5e1b1..c071874f5f 100644 --- a/src/network/extreme/mlx/snmp/mode/components/resources.pm +++ b/src/network/extreme/mlx/snmp/mode/components/resources.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for diff --git a/src/network/extreme/mlx/snmp/mode/components/temperature.pm b/src/network/extreme/mlx/snmp/mode/components/temperature.pm index 66805988b3..07c6c59e98 100644 --- a/src/network/extreme/mlx/snmp/mode/components/temperature.pm +++ b/src/network/extreme/mlx/snmp/mode/components/temperature.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -49,16 +49,15 @@ sub check { next if ($oid !~ /^$mapping->{snAgentTempSensorDescr}->{oid}\.(.*)$/); my $instance = $1; next if ($self->{results}->{$oid_snAgentTempEntry}->{$oid} !~ /temperature/i); - my $result = $self->{snmp}->map_instance(mapping => - $mapping, - results => - $self->{results}->{$oid_snAgentTempEntry}, - instance => - $instance); + my $result = $self->{snmp}->map_instance( + mapping => $mapping, + results => $self->{results}->{$oid_snAgentTempEntry}, + instance => $instance + ); next if ($self->check_filter(section => 'temperature', instance => $instance)); - if ($result->{snAgentTempValue} == 0) { - $self->{output}->output_add(long_msg => sprintf("skipping temperature '%s' (counter is 0)", + if (!defined($result->{snAgentTempValue}) || $result->{snAgentTempValue} == 0) { + $self->{output}->output_add(long_msg => sprintf("skipping temperature '%s'", $result->{snAgentTempSensorDescr})); next; } @@ -67,19 +66,18 @@ sub check { $self->{output}->output_add(long_msg => sprintf("temperature '%s' is %s C [instance = %s]", $result->{snAgentTempSensorDescr}, $result->{snAgentTempValue}, $instance)); - my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => - 'temperature', - instance => - $instance, - value => - $result->{snAgentTempValue}); + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric( + section => 'temperature', + instance => $instance, + value => $result->{snAgentTempValue} + ); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => - $exit, - short_msg => - sprintf("Temperature '%s' is %s C", - $result->{snAgentTempSensorDescr}, - $result->{snAgentTempValue})); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Temperature '%s' is %s C", $result->{snAgentTempSensorDescr}, + $result->{snAgentTempValue}) + ); } $self->{output}->perfdata_add( label => 'temp', unit => 'C', diff --git a/src/network/extreme/mlx/snmp/mode/cpu.pm b/src/network/extreme/mlx/snmp/mode/cpu.pm index dd9cec5f19..3be46dd96c 100644 --- a/src/network/extreme/mlx/snmp/mode/cpu.pm +++ b/src/network/extreme/mlx/snmp/mode/cpu.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -24,41 +24,47 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; +use centreon::plugins::constants qw(:counters :values); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'cpu', type => 1, cb_prefix_output => 'prefix_cpu_output', message_multiple => 'All CPUs are ok' } + { + name => 'cpu', + type => COUNTER_TYPE_INSTANCE, + cb_prefix_output => 'prefix_cpu_output', + message_multiple => 'All CPUs are ok' + } ]; $self->{maps_counters}->{cpu} = [ { label => 'utilization-5s', nlabel => 'cpu.utilization.5s.percentage', set => { - key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], - output_template => '%.2f %% (5s)', - perfdatas => [ - { value => 'cpu_5s', template => '%.2f', - unit => '%', min => 0, max => 100, label_extra_instance => 1 } - ] - } + key_values => [ { name => 'cpu_5s' }, { name => 'display' } ], + output_template => '%.2f %% (5s)', + perfdatas => [ + { value => 'cpu_5s', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } }, { label => 'utilization-1m', nlabel => 'cpu.utilization.1m.percentage', set => { - key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], - output_template => '%.2f %% (1m)', - perfdatas => [ - { value => 'cpu_1m', template => '%.2f', - unit => '%', min => 0, max => 100, label_extra_instance => 1 } - ] - } + key_values => [ { name => 'cpu_1m' }, { name => 'display' } ], + output_template => '%.2f %% (1m)', + perfdatas => [ + { value => 'cpu_1m', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } }, { label => 'utilization-5m', nlabel => 'cpu.utilization.5m.percentage', set => { - key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], - output_template => '%.2f %% (5m)', - perfdatas => [ - { value => 'cpu_5m', template => '%.2f', - unit => '%', min => 0, max => 100, label_extra_instance => 1 } - ] - } + key_values => [ { name => 'cpu_5m' }, { name => 'display' } ], + output_template => '%.2f %% (5m)', + perfdatas => [ + { value => 'cpu_5m', template => '%.2f', + unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } } ]; } @@ -93,9 +99,9 @@ sub manage_selection { $self->{cpu}->{$instance} = { display => $instance, - cpu_5s => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.5' }, - cpu_1m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.60' }, - cpu_5m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.300' } + cpu_5s => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.5' }, + cpu_1m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.60' }, + cpu_5m => $snmp_result->{ $oid_snAgentCpuUtilPercent . '.' . $1 . '.' . $2 . '.300' } }; } } diff --git a/src/network/extreme/mlx/snmp/mode/hardware.pm b/src/network/extreme/mlx/snmp/mode/hardware.pm index bac42c9756..240725f845 100644 --- a/src/network/extreme/mlx/snmp/mode/hardware.pm +++ b/src/network/extreme/mlx/snmp/mode/hardware.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for diff --git a/src/network/extreme/mlx/snmp/mode/listsfpports.pm b/src/network/extreme/mlx/snmp/mode/listsfpports.pm index c221a9001d..a22fc4880f 100644 --- a/src/network/extreme/mlx/snmp/mode/listsfpports.pm +++ b/src/network/extreme/mlx/snmp/mode/listsfpports.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for diff --git a/src/network/extreme/mlx/snmp/mode/memory.pm b/src/network/extreme/mlx/snmp/mode/memory.pm index 779fe936bc..8d86bae2fe 100644 --- a/src/network/extreme/mlx/snmp/mode/memory.pm +++ b/src/network/extreme/mlx/snmp/mode/memory.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -24,19 +24,20 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; +use centreon::plugins::constants qw(:counters :values); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'memory', type => 0 } + { name => 'memory', type => COUNTER_TYPE_GLOBAL } ]; $self->{maps_counters}->{memory} = [ { label => 'memory-utilization', nlabel => 'memory.utilization.percentage', set => { - key_values => [ { name => 'memory_usage' } ], + key_values => [ { name => 'memory_usage' } ], output_template => 'memory usage is: %.2f%%', - perfdatas => [ + perfdatas => [ { template => '%.2f', unit => '%', min => 0, max => 100 } ] } @@ -49,8 +50,7 @@ sub new { my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; - $options{options}->add_options(arguments => { - }); + $options{options}->add_options(arguments => {}); return $self; } @@ -60,7 +60,7 @@ sub manage_selection { my $oid_agentCurrentMemoryUtilization = '.1.3.6.1.4.1.1991.1.1.2.12.4.1.0'; my $snmp_result = $options{snmp}->get_leef( - oids => [ $oid_agentCurrentMemoryUtilization ], + oids => [ $oid_agentCurrentMemoryUtilization ], nothing_quit => 1 ); diff --git a/src/network/extreme/mlx/snmp/mode/sfpport.pm b/src/network/extreme/mlx/snmp/mode/sfpport.pm index cb8cf15ec7..3597566437 100644 --- a/src/network/extreme/mlx/snmp/mode/sfpport.pm +++ b/src/network/extreme/mlx/snmp/mode/sfpport.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -26,6 +26,8 @@ use strict; use warnings; use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); use centreon::plugins::statefile; +use centreon::plugins::constants qw(:counters :values); +use centreon::plugins::misc qw/is_excluded/; use Safe; sub sfp_long_output { @@ -69,16 +71,16 @@ sub set_counters { $self->{maps_counters_type} = [ { name => 'sfp', - type => 3, + type => COUNTER_TYPE_MULTIPLE, cb_prefix_output => 'prefix_sfp_output', cb_long_output => 'sfp_long_output', indent_long_output => ' ', message_multiple => 'All sfp ports are ok', group => [ - { name => 'status', type => 0, skipped_code => { -10 => 1 } }, - { name => 'perf', type => 0, skipped_code => { -10 => 1 } }, - { name => 'temperature', type => 0, skipped_code => { -10 => 1 } }, + { name => 'status', type => COUNTER_MULTIPLE_INSTANCE, skipped_code => { NO_VALUE() => 1 } }, + { name => 'perf', type => COUNTER_MULTIPLE_INSTANCE, skipped_code => { NO_VALUE() => 1 } }, + { name => 'temperature', type => COUNTER_MULTIPLE_INSTANCE, skipped_code => { NO_VALUE() => 1 } }, ] } ]; @@ -86,7 +88,7 @@ sub set_counters { $self->{maps_counters}->{status} = [ { label => 'status', - type => 2, + type => COUNTER_KIND_TEXT, critical_default => '%{temp_status} =~ /alarm/ || %{tx_power_status} =~ /alarm/ || %{rx_power_status} =~ /alarm/ || %{bias_status} =~ /alarm/', warning_default => @@ -155,8 +157,10 @@ sub new { $options{options}->add_options( arguments => { - 'filter-port:s' => { name => 'filter_port' }, - 'filter-interface:s' => { name => 'filter_interface' }, + 'include-port:s' => { name => 'include_port' }, + 'exclude-port:s' => { name => 'exclude_port' }, + 'include-interface:s' => { name => 'include_interface' }, + 'exclude-interface:s' => { name => 'exclude_interface' }, 'add-interface-name' => { name => 'add_interface_name' }, 'reload-cache-time:s' => { name => 'reload_cache_time', default => 180 }, 'show-cache' => { name => 'show_cache' }, @@ -220,8 +224,7 @@ sub reload_cache { } if (scalar(keys %{$datas->{sfp}}) <= 0) { - $self->{output}->add_option_msg(short_msg => "Can't construct cache..."); - $self->{output}->option_exit(); + $self->{output}->option_exit(short_msg => "Can't construct cache..."); } $self->{statefile_cache}->write(data => $datas); @@ -235,8 +238,7 @@ sub get_selection { my $has_cache_file = $self->{statefile_cache}->read(statefile => 'cache_snmpstandard_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode}); if (defined($self->{option_results}->{show_cache})) { - $self->{output}->add_option_msg(long_msg => $self->{statefile_cache}->get_string_content()); - $self->{output}->option_exit(); + $self->{output}->option_exit(long_msg => $self->{statefile_cache}->get_string_content()); } my $timestamp_cache = $self->{statefile_cache}->get(name => 'last_timestamp'); @@ -248,28 +250,19 @@ sub get_selection { my $results = {}; foreach (keys %$sfp_ports) { - if (defined($self->{option_results}->{filter_port}) && $self->{option_results}->{filter_port} ne '' && - $_ !~ /$self->{option_results}->{filter_port}/) { - $self->{output}->output_add(long_msg => "skipping '" . $_ . "': no matching filter.", debug => 1); - next; - } - - if (defined($self->{option_results}->{add_interface_name}) && - defined($self->{option_results}->{filter_interface}) && $self->{option_results}->{filter_interface} ne '' && - $sfp_ports->{$_} !~ /$self->{option_results}->{filter_interface}/) { - $self->{output}->output_add( - long_msg => "skipping '" . $sfp_ports->{$_} . "': no matching filter.", - debug => 1 + next if is_excluded($_, $self->{option_results}->{include_port}, $self->{option_results}->{exclude_port}); + next if defined($self->{option_results}->{add_interface_name}) && + is_excluded( + $sfp_ports->{$_}, + $self->{option_results}->{include_interface}, + $self->{option_results}->{exclude_interface} ); - next; - } $results->{$_} = $sfp_ports->{$_}; } if (scalar(keys %$results) <= 0) { - $self->{output}->add_option_msg(short_msg => "No sfp ports found. Can be: filters, cache file."); - $self->{output}->option_exit(); + $self->{output}->option_exit(short_msg => "No sfp ports found. Can be: filters, cache file."); } return $results; @@ -289,7 +282,7 @@ sub manage_selection { $self->{sfp} = {}; - foreach (keys %$sfp_ports) { + foreach (sort keys %$sfp_ports) { my $instance = $_; my $result = $options{snmp}->map_instance( @@ -365,14 +358,22 @@ Check SFP port. =over 8 -=item B<--filter-port> +=item B<--include-port> Filter ports by index (can be a regexp). -=item B<--filter-interface> +=item B<--exclude-port> + +Exclude ports by index (can be a regexp). + +=item B<--include-interface> Filter ports by interface name (can be a regexp). Can be used only together with --add-interface-name. +=item B<--exclude-interface> + +Exclude ports by interface name (can be a regexp). Can be used only together with --add-interface-name. + =item B<--add-interface-name> Add the corresponding interface name when set. Used for the instance name in perf data, too. @@ -392,10 +393,37 @@ You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_po Define the conditions to match for the status to be CRITICAL '%{temp_status} =~ /alarm/ || %{tx_power_status} =~ /alarm/ || %{rx_power_status} =~ /alarm/ || %{bias_status} =~ /alarm/'). You can use the following variables: %{temp_status}, %{tx_power_status}, %{rx_power_status}, %{bias_status} -=item B<--warning-*> B<--critical-*> +=item B<--warning-rx-input-power-dbm> + +Thresholds. (dBm) + +=item B<--critical-rx-input-power-dbm> + +Thresholds. (dBm) + +=item B<--warning-tx-output-power-dbm> + +Thresholds. (dBm) + +=item B<--critical-tx-output-power-dbm> + +Thresholds. (dBm) + +=item B<--warning-bias-current> + +Thresholds. (mA) + +=item B<--critical-bias-current> + +Thresholds. (mA) + +=item B<--warning-temperature> + +Thresholds. (C) + +=item B<--critical-temperature> -Thresholds. -Can be: C, C, C, C. +Thresholds. (C) =back diff --git a/src/network/extreme/mlx/snmp/plugin.pm b/src/network/extreme/mlx/snmp/plugin.pm index 2ab9299e29..346334e63b 100644 --- a/src/network/extreme/mlx/snmp/plugin.pm +++ b/src/network/extreme/mlx/snmp/plugin.pm @@ -1,5 +1,5 @@ # -# Copyright 2024 Centreon (http://www.centreon.com/) +# Copyright 2026 Centreon (http://www.centreon.com/) # # Centreon is a full-fledged industry-strength solution that meets # the needs in IT infrastructure and application monitoring for @@ -43,6 +43,13 @@ sub new { 'uptime' => 'snmp_standard::mode::uptime', }; + $self->{modes_options} = { + 'interfaces' => { force_new_perfdata => 1 }, + 'tcpcon' => { force_new_perfdata => 1 }, + 'udpcon' => { force_new_perfdata => 1 }, + 'uptime' => { force_new_perfdata => 1 } + }; + return $self; }