From 8b1d670ea036b61bdd5ce6b194c74a2ce79ce5c2 Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Fri, 29 Jul 2022 16:52:33 +0200 Subject: [PATCH] network::alcatel::oxe::snmp - add new metrics to domain check & add new trunk usage mode (#3793) * + add new metric to OXE * + apply latest guidelines * + apply latest guidelines bis * + add OXE trunk monitoring * + trunk mode indent * + mention not used OIDs exhaustively * + fix following review * + fix following review * + fix some copy/paste * + make it modern * + modern --- .../snmp/mode/{domainusage.pm => domains.pm} | 112 +++++++-- .../network/alcatel/oxe/snmp/mode/trunks.pm | 226 ++++++++++++++++++ .../network/alcatel/oxe/snmp/plugin.pm | 15 +- 3 files changed, 326 insertions(+), 27 deletions(-) rename centreon-plugins/network/alcatel/oxe/snmp/mode/{domainusage.pm => domains.pm} (57%) create mode 100644 centreon-plugins/network/alcatel/oxe/snmp/mode/trunks.pm diff --git a/centreon-plugins/network/alcatel/oxe/snmp/mode/domainusage.pm b/centreon-plugins/network/alcatel/oxe/snmp/mode/domains.pm similarity index 57% rename from centreon-plugins/network/alcatel/oxe/snmp/mode/domainusage.pm rename to centreon-plugins/network/alcatel/oxe/snmp/mode/domains.pm index 19971eeb6..d7aaf4c9c 100644 --- a/centreon-plugins/network/alcatel/oxe/snmp/mode/domainusage.pm +++ b/centreon-plugins/network/alcatel/oxe/snmp/mode/domains.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::alcatel::oxe::snmp::mode::domainusage; +package network::alcatel::oxe::snmp::mode::domains; use base qw(centreon::plugins::templates::counter); @@ -29,9 +29,8 @@ sub custom_usage_perfdata { my ($self, %options) = @_; $self->{output}->perfdata_add( - label => $self->{result_values}->{label_perf} . '_used', nlabel => $self->{nlabel}, - instances => $self->use_instances(extra_instance => $options{extra_instance}) ? $self->{result_values}->{display} : undef, + instances => $self->{result_values}->{display}, value => $self->{result_values}->{used}, warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), @@ -42,7 +41,13 @@ sub custom_usage_perfdata { sub custom_usage_threshold { my ($self, %options) = @_; - my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + my $exit = $self->{perfdata}->threshold_check( + value => $self->{result_values}->{prct_used}, + threshold => [ + { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, + { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } + ] + ); return $exit; } @@ -70,7 +75,6 @@ sub custom_cac_usage_calc { $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; - $self->{result_values}->{label_perf} = $options{extra_options}->{label_perf}; $self->{result_values}->{label_output} = $options{extra_options}->{label_output}; return 0; } @@ -88,7 +92,23 @@ sub custom_conference_usage_calc { $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; - $self->{result_values}->{label_perf} = $options{extra_options}->{label_perf}; + $self->{result_values}->{label_output} = $options{extra_options}->{label_output}; + return 0; +} + +sub custom_dsp_usage_calc { + my ($self, %options) = @_; + + if ($options{new_datas}->{$self->{instance} . '_dspRessAvailable'} <= 0) { + $self->{error_msg} = "skipped (no available)"; + return -2; + } + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_dspRessAvailable'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_dspRessBusy'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; $self->{result_values}->{label_output} = $options{extra_options}->{label_output}; return 0; } @@ -97,28 +117,69 @@ sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'domain', type => 1, cb_prefix_output => 'prefix_domain_output', message_multiple => 'All domain are ok', skipped_code => { -2 => 1, -10 => 1 } } + { name => 'domain', type => 1, cb_prefix_output => 'prefix_domain_output', message_multiple => 'All domains are ok', skipped_code => { -2 => 1, -10 => 1 } } ]; $self->{maps_counters}->{domain} = [ { label => 'cac-usage', nlabel => 'domain.communications.external.current.count', set => { - key_values => [ { name => 'display' }, { name => 'cacUsed' }, { name => 'cacAllowed' } ], + key_values => [ { name => 'cacUsed' }, { name => 'cacAllowed' }, { name => 'display '} ], closure_custom_calc => $self->can('custom_cac_usage_calc'), - closure_custom_calc_extra_options => { label_output => 'External Communication', label_perf => 'cac' }, + closure_custom_calc_extra_options => { label_output => 'External Communication' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), } }, + { label => 'cac-overrun', nlabel => 'domain.communications.external.overrun.count', set => { + key_values => [ { name => 'cacOverrun' } ], + output_template => 'conference overrun: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + }, { label => 'conference-usage', nlabel => 'domain.conference.circuits.current.count', set => { - key_values => [ { name => 'display' }, { name => 'confBusy' }, { name => 'confAvailable' } ], + key_values => [ { name => 'confBusy' }, { name => 'confAvailable' }, { name => 'display '} ], closure_custom_calc => $self->can('custom_conference_usage_calc'), - closure_custom_calc_extra_options => { label_output => 'Conference circuits', label_perf => 'conference' }, + closure_custom_calc_extra_options => { label_output => 'Conference circuits' }, closure_custom_output => $self->can('custom_usage_output'), closure_custom_perfdata => $self->can('custom_usage_perfdata'), closure_custom_threshold_check => $self->can('custom_usage_threshold'), } }, + { label => 'conf-outoforder', nlabel => 'domain.conference.circuits.outoforder.count', set => { + key_values => [ { name => 'confOutOfOrder' } ], + output_template => 'conference out of order: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + }, + { label => 'dsp-usage', nlabel => 'domain.compressors.current.count', set => { + key_values => [ { name => 'dspRessBusy' }, { name => 'dspRessAvailable' }, { name => 'display '} ], + closure_custom_calc => $self->can('custom_dsp_usage_calc'), + closure_custom_calc_extra_options => { label_output => 'DSP Compressors' }, + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'dsp-outofservice', nlabel => 'domain.compressors.outofservice.count', set => { + key_values => [ { name => 'dspRessOutOfService' } ], + output_template => 'compressor out of service: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + }, + }, + { label => 'dsp-overrun', nlabel => 'domain.compressors.overrun.count', set => { + key_values => [ { name => 'dspRessOverrun' } ], + output_template => 'compressor overrun: %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + }, + } ]; } @@ -130,7 +191,7 @@ sub prefix_domain_output { sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => { @@ -141,11 +202,16 @@ sub new { } my $mapping = { - confAvailable => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.2' }, - confBusy => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.3' }, - confOutOfOrder => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.4' }, - cacAllowed => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.9' }, - cacUsed => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.10' }, + confAvailable => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.2' }, + confBusy => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.3' }, + confOutOfOrder => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.4' }, + dspRessAvailable => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.5' }, + dspRessBusy => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.6' }, + dspRessOutOfService => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.7' }, + dspRessOverrun => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.8' }, + cacAllowed => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.9' }, + cacUsed => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.10' }, + cacOverrun => { oid => '.1.3.6.1.4.1.637.64.4400.1.3.1.10' } }; sub manage_selection { @@ -197,13 +263,19 @@ Filter by domain (regexp can be used). =item B<--warning-*> Threshold warning. -Can be: 'cac-usage' (%), 'conference-usage' (%). +Can be: 'cac-usage' (%), 'conference-usage' (%), +'cac-overrun' (absolute), conf-outoforder (absolute), +'dsp-usage' (absolute), 'dsp-outofservice' (absolute), +'dsp-overrun' (absolute) =item B<--critical-*> Threshold critical. -Can be: 'cac-usage' (%), 'conference-usage' (%). +Can be: 'cac-usage' (%), 'conference-usage' (%), +'cac-overrun' (absolute), conf-outoforder (absolute), +'dsp-usage' (absolute), 'dsp-outofservice' (absolute), +'dsp-overrun' (absolute) =back -=cut +=cut \ No newline at end of file diff --git a/centreon-plugins/network/alcatel/oxe/snmp/mode/trunks.pm b/centreon-plugins/network/alcatel/oxe/snmp/mode/trunks.pm new file mode 100644 index 000000000..b98c61c90 --- /dev/null +++ b/centreon-plugins/network/alcatel/oxe/snmp/mode/trunks.pm @@ -0,0 +1,226 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::alcatel::oxe::snmp::mode::trunks; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_status_output { + my ($self, %options) = @_; + + return ' status: ' . $self->{result_values}->{cluster_status}; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + instances => $self->{result_values}->{display}, + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total} + ); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my $exit = $self->{perfdata}->threshold_check( + value => $self->{result_values}->{prct_used}, + threshold => [ + { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, + { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } + ] + ); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $self->{result_values}->{total}, + $self->{result_values}->{used}, $self->{result_values}->{prct_used}, + $self->{result_values}->{free}, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_trunk_usage_calc { + my ($self, %options) = @_; + + if ($options{new_datas}->{$self->{instance} . '_cacAllowed'} <= 0) { + $self->{error_msg} = "skipped (no allowed)"; + return -2; + } + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . 'freechan'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_busychan'}; + $self->{result_values}->{total} = $self->{result_values}->{free} + $self->{result_values}->{used}; + $self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'trunk', type => 1, cb_prefix_output => 'prefix_trunk_output', message_multiple => 'All trunks are ok', skipped_code => { -2 => 1, -10 => 1 } } + ]; + + $self->{maps_counters}->{trunk} = [ + { label => 'trunk-status', type => 2, critical_default => '%{trunkstatus} =~ /oos/i', set => { + key_values => [ { name => 'trunkstatus' } ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'channel-usage', nlabel => 'trunk.channels.current.count', set => { + key_values => [ { name => 'busychan' }, { name => 'freechan' }, { name => 'display '} ], + closure_custom_calc => $self->can('custom_trunk_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + { label => 'channel-outofservice', nlabel => 'trunk.channels.outofservice.count', set => { + key_values => [ { name => 'ooschan' } ], + output_template => 'channel out of service %s', + perfdatas => [ + { template => '%s', min => 0, label_extra_instance => 1 } + ] + } + } + ]; +} + +sub prefix_trunk_output { + my ($self, %options) = @_; + + return "Trunk '" . $options{instance_value}->{display} . "' "; +} + +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-trunk:s" => { name => 'filter_trunk' }, + }); + + return $self; +} + +my $map_trunk_status = { + 0 => 'OOS', + 1 => 'INS' +}; + +my $mapping = { + trunkname => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.2' }, + crystalno => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.3' }, # not used + couplerno => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.4' }, # not used + trunktype => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.5' }, # not used + nodepbx => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.6' }, # not used + freechan => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.7' }, + busychan => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.8' }, + ooschan => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.9' }, + trunkstatus => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.10', map => $map_trunk_status }, + cumuloos => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.11' }, # not used + cumuloverrun => { oid => '1.3.6.1.4.1.637.64.4400.1.9.1.12' }, # not used +}; + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_trunkEntry = '1.3.6.1.4.1.637.64.4400.1.9.1'; + my $snmp_result = $options{snmp}->get_table( + oid => $oid_trunkEntry, + nothing_quit => 1 + ); + + $self->{trunk} = {}; + foreach my $oid (keys %$snmp_result) { + next if ($oid !~ /^$mapping->{trunkname}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); + if (defined($self->{option_results}->{filter_trunk}) && $self->{option_results}->{filter_trunk} ne '' && + $result->{trunkname} !~ /$self->{option_results}->{filter_trunk}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{trunkname} . "': no matching filter.", debug => 1); + next; + } + + $self->{trunk}->{$result->{trunkname}} = { + display => $result->{trunkname}, + %{$result} + }; + } + + if (scalar(keys %{$self->{trunk}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No trunk found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check Trunk usages. + +=over 8 + +=item B<--filter-trunk> + +Filter by trunk name (regexp can be used). + +=item B<--warning-trunk-status> + +Set warning threshold for status +Can used special variables like: %{trunkstatus} + +=item B<--critical-trunk-status> + +Set critical threshold for status (Default: '%{trunkstatus} =~ /oos/i'). +Can used special variables like: %{trunkstatus} + +=item B<--warning-*> + +Threshold warning. +Can be: 'channel-usage' (%), 'channel-outofservice' (absolute) + +=item B<--critical-*> + +Threshold critical. +Can be: 'channel-usage' (%), 'channel-outofservice' (absolute) + +=back + +=cut \ No newline at end of file diff --git a/centreon-plugins/network/alcatel/oxe/snmp/plugin.pm b/centreon-plugins/network/alcatel/oxe/snmp/plugin.pm index cb3915c4f..f90f37bd1 100644 --- a/centreon-plugins/network/alcatel/oxe/snmp/plugin.pm +++ b/centreon-plugins/network/alcatel/oxe/snmp/plugin.pm @@ -31,13 +31,14 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( - 'cpu' => 'snmp_standard::mode::cpu', - 'domain-usage' => 'network::alcatel::oxe::snmp::mode::domainusage', - 'memory' => 'snmp_standard::mode::memory', - 'pbx-state' => 'network::alcatel::oxe::snmp::mode::pbxstate', - 'pbx-role' => 'network::alcatel::oxe::snmp::mode::pbxrole', - 'storage' => 'snmp_standard::mode::storage', - 'swap' => 'snmp_standard::mode::swap', + 'cpu' => 'snmp_standard::mode::cpu', + 'domains' => 'network::alcatel::oxe::snmp::mode::domains', + 'memory' => 'snmp_standard::mode::memory', + 'pbx-state' => 'network::alcatel::oxe::snmp::mode::pbxstate', + 'pbx-role' => 'network::alcatel::oxe::snmp::mode::pbxrole', + 'storage' => 'snmp_standard::mode::storage', + 'swap' => 'snmp_standard::mode::swap', + 'trunks' => 'network::alcatel::oxe::snmp::mode::trunks' ); return $self;