From fd70da8f089764c0ba99303ad0b59c188d89254d Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 21 Nov 2017 11:09:20 +0100 Subject: [PATCH 01/45] enable kaminario --- .../storage/kaminario/restapi/custom/api.pm | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/centreon-plugins/storage/kaminario/restapi/custom/api.pm b/centreon-plugins/storage/kaminario/restapi/custom/api.pm index 4ea8dd4a8..022bfdc2d 100644 --- a/centreon-plugins/storage/kaminario/restapi/custom/api.pm +++ b/centreon-plugins/storage/kaminario/restapi/custom/api.pm @@ -129,18 +129,9 @@ sub get_performance { my ($self, %options) = @_; $self->settings(); - #my $content = $self->{http}->request(url_path => '/api/v2' . $options{path} . '&__resolution=' . $self->{resolution}, - # critical_status => '', warning_status => ''); - my $content = do { - local $/ = undef; - if (!open my $fh, "<", '/tmp/4.json') { - $self->{output}->add_option_msg(short_msg => "Could not open file toto : $!"); - $self->{output}->option_exit(); - } - <$fh>; - }; - - #my $response = $self->{http}->get_response(); + my $content = $self->{http}->request(url_path => '/api/v2' . $options{path} . '&__resolution=' . $self->{resolution}, + critical_status => '', warning_status => ''); + my $response = $self->{http}->get_response(); my $decoded; eval { @@ -151,10 +142,10 @@ sub get_performance { $self->{output}->option_exit(); } - #if ($response->code() != 200) { - # $self->{output}->add_option_msg(short_msg => "Connection issue: " . $decoded->{message}); - # $self->{output}->option_exit(); - #} + if ($response->code() != 200) { + $self->{output}->add_option_msg(short_msg => "Connection issue: " . $decoded->{message}); + $self->{output}->option_exit(); + } return $decoded; } From 2206bdaf6502f6b0a7abce8bc84beb91141b5bc0 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 21 Nov 2017 13:16:22 +0100 Subject: [PATCH 02/45] freebox plugin: wip --- .../network/freebox/restapi/custom/api.pm | 272 ++++++++++++++++++ .../network/freebox/restapi/mode/system.pm | 225 +++++++++++++++ .../network/freebox/restapi/plugin.pm | 49 ++++ 3 files changed, 546 insertions(+) create mode 100644 centreon-plugins/network/freebox/restapi/custom/api.pm create mode 100644 centreon-plugins/network/freebox/restapi/mode/system.pm create mode 100644 centreon-plugins/network/freebox/restapi/plugin.pm diff --git a/centreon-plugins/network/freebox/restapi/custom/api.pm b/centreon-plugins/network/freebox/restapi/custom/api.pm new file mode 100644 index 000000000..13e31220c --- /dev/null +++ b/centreon-plugins/network/freebox/restapi/custom/api.pm @@ -0,0 +1,272 @@ +# +# Copyright 2017 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::freebox::restapi::custom::api; + +use strict; +use warnings; +use centreon::plugins::http; +use JSON; +use Digest::SHA qw(hmac_sha1_hex); + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "hostname:s@" => { name => 'hostname' }, + "freebox-app-id:s@" => { name => 'freebox_app_id' }, + "freebox-app-token:s@" => { name => 'freebox_app_token' }, + "freebox-api-version:s@" => { name => 'freebox_api_version', }, + "proxyurl:s@" => { name => 'proxyurl' }, + "timeout:s@" => { name => 'timeout' }, + "precision:s@" => { name => 'precision' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + $self->{http} = centreon::plugins::http->new(output => $self->{output}); + + $self->{session_token} = undef; + + return $self; + +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults { + my ($self, %options) = @_; + + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : 'mafreebox.free.fr'; + $self->{freebox_app_id} = (defined($self->{option_results}->{freebox_app_id})) ? shift(@{$self->{option_results}->{freebox_app_id}}) : undef; + $self->{freebox_app_token} = (defined($self->{option_results}->{freebox_app_token})) ? shift(@{$self->{option_results}->{freebox_app_token}}) : undef; + $self->{freebox_api_version} = (defined($self->{option_results}->{freebox_api_version})) ? shift(@{$self->{option_results}->{freebox_api_version}}) : 'v4'; + $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; + $self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? shift(@{$self->{option_results}->{proxyurl}}) : undef; + $self->{resolution} = (defined($self->{option_results}->{resolution})) ? shift(@{$self->{option_results}->{resolution}}) : 300; + + if (!defined($self->{hostname})) { + $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); + $self->{output}->option_exit(); + } + if (!defined($self->{freebox_app_id})) { + $self->{output}->add_option_msg(short_msg => "Need to specify freebox-app-id option."); + $self->{output}->option_exit(); + } + if (!defined($self->{freebox_app_token})) { + $self->{output}->add_option_msg(short_msg => "Need to specify freebox-app-token option."); + $self->{output}->option_exit(); + } + + if (!defined($self->{option_results}->{freebox_app_id}) || + scalar(@{$self->{option_results}->{freebox_app_id}}) == 0) { + return 0; + } + return 1; +} + +sub build_options_for_httplib { + my ($self, %options) = @_; + + $self->{option_results}->{hostname} = $self->{hostname}; + $self->{option_results}->{timeout} = $self->{timeout}; + $self->{option_results}->{port} = 80; + $self->{option_results}->{proto} = 'http'; + $self->{option_results}->{proxyurl} = $self->{proxyurl}; +} + +sub settings { + my ($self, %options) = @_; + + $self->build_options_for_httplib(); + if (defined($self->{session_token})) { + $self->{http}->add_header(key => 'X-Fbx-App-Auth', value => $self->{session_token}); + } + $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->set_options(%{$self->{option_results}}); +} + +sub manage_response { + my ($self, %options) = @_; + + my $response = $self->{http}->get_response(); + if ($response->code() != 200) { + $self->{output}->add_option_msg(short_msg => "Connection issue: " . $options{content}); + $self->{output}->option_exit(); + } + + my $decoded; + eval { + $decoded = decode_json($options{content}); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + $self->{output}->option_exit(); + } + + if (!$decoded->{success}) { + $self->{output}->add_option_msg(short_msg => "Unsuccessful $options{type} response"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +sub get_session { + my ($self, %options) = @_; + + $self->settings(); + my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/login/', + critical_status => '', warning_status => ''); + my $decoded = $self->manage_response(content => $content); + my $challenge = $decoded->{result}->{challenge}; + my $password = hmac_sha1_hex($challenge, $self->{freebox_app_token}); + + my $json_request = { app_id => $self->{freebox_app_id}, password => $password }; + my $encoded; + eval { + $encoded = encode_json($json_request); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); + $self->{output}->option_exit(); + } + + $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/login/session/', method => 'POST', + query_form_post => $encoded, critical_status => '', warning_status => ''); + $decoded = $self->manage_response(content => $content); + + $self->{session_token} = $decoded->{result}->{session_token}; +} + +sub get_data { + my ($self, %options) = @_; + + if (!defined($self->{session_token})) { + $self->get_session(); + } + + $self->settings(); + my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/' . $options{path}, + critical_status => '', warning_status => ''); + my $decoded = $self->manage_response(content => $content); + return $decoded->{result}; +} + +sub get_performance { + my ($self, %options) = @_; + + +} + +sub DESTROY { + my $self = shift; + + if (defined($self->{session_token})) { + $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/login/logout/', method => 'POST'); + } +} + +1; + +__END__ + +=head1 NAME + +FREEBOX REST API + +=head1 SYNOPSIS + +Freebox Rest API custom mode + +=head1 REST API OPTIONS + +=over 8 + +=item B<--hostname> + +Freebox hostname (Default: 'mafreebox.free.fr'). + +=item B<--freebox-app-id> + +Freebox App ID. + +=item B<--freebox-app-token> + +Freebox App Token. + +=item B<--freebox-api-version> + +Freebox API version (Default: 'v4'). + +=item B<--proxyurl> + +Proxy URL if any. + +=item B<--timeout> + +Set HTTP timeout in seconds (Default: '10'). + +=item B<--precision> + +Selected data performance resolution in seconds (Default: '300'). + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/network/freebox/restapi/mode/system.pm b/centreon-plugins/network/freebox/restapi/mode/system.pm new file mode 100644 index 000000000..81f8db97e --- /dev/null +++ b/centreon-plugins/network/freebox/restapi/mode/system.pm @@ -0,0 +1,225 @@ +# +# Copyright 2017 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::freebox::restapi::mode::system; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'temperature-cpum', set => { + key_values => [ { name => 'temp_cpum' } ], + output_template => 'Temperature cpum : %s C', + perfdatas => [ + { label => 'temp_cpum', value => 'temp_cpum_absolute', template => '%s', + unit => 'C' }, + ], + } + }, + { label => 'temperature-cpub', set => { + key_values => [ { name => 'temp_cpub' } ], + output_template => 'Temperature cpub : %s C', + perfdatas => [ + { label => 'temp_cpub', value => 'temp_cpub_absolute', template => '%s', + unit => 'C' }, + ], + } + }, + { label => 'temperature-switch', set => { + key_values => [ { name => 'temp_sw' } ], + output_template => 'Temperature switch : %s C', + perfdatas => [ + { label => 'temp_sw', value => 'temp_sw_absolute', template => '%s', + unit => 'C' }, + ], + } + }, + { label => 'fan-speed', set => { + key_values => [ { name => 'fan_rpm' } ], + output_template => 'fan speed : %s rpm', + perfdatas => [ + { label => 'fan_rpm', value => 'fan_rpm_absolute', template => '%s', + min => 0, unit => 'rpm' }, + ], + } + }, + { label => 'disk-status', threshold => 0, set => { + key_values => [ { name => 'disk_status' } ], + closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'disk' }, + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'wifi-status', threshold => 0, set => { + key_values => [ { name => 'wifi_status' } ], + closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'wifi' }, + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + my $label = $self->{label}; + $label =~ s/-/_/g; + if (defined($instance_mode->{option_results}->{'critical_' . $label}) && $instance_mode->{option_results}->{'critical_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'critical_' . $label}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{'warning_' . $label}) && $instance_mode->{option_results}->{'warning_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'warning_' . $label}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + my $msg = ucfirst($self->{result_values}->{label}) . ' status : ' . $self->{result_values}->{status}; + + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{label} = $options{extra_options}->{label_ref}; + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label} . '_status'}; + return 0; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "warning-wifi-status:s" => { name => 'warning_wifi_status', default => '%{status} =~ /bad_param/i' }, + "critical-wifi-status:s" => { name => 'critical_wifi_status', default => '%{status} =~ /failed/i' }, + "warning-disk-status:s" => { name => 'warning_disk_status', default => '' }, + "critical-disk-status:s" => { name => 'critical_disk_status', default => '%{status} =~ /error/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_wifi_status', 'critical_wifi_status', 'warning_disk_status', 'critical_disk_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $result = $options{custom}->get_data(path => 'system/'); + $self->{global} = { %{$result} }; + + $result = $options{custom}->get_data(path => 'wifi/ap/'); + $self->{global}->{wifi_status} = $result->{status}->{state}; +} + +1; + +__END__ + +=head1 MODE + +Check system. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^temperature-cpum$' + +=item B<--warning-wifi-status> + +Set warning threshold for wifi status (Default: '%{status} =~ /bad_param/i'). +Can used special variables like: %{status} + +=item B<--critical-wifi-status> + +Set critical threshold for wifi status (Default: '%{status} =~ /failed/i'). +Can used special variables like: %{status} + +=item B<--warning-disk-status> + +Set warning threshold for disk status. +Can used special variables like: %{status} + +=item B<--critical-disk-status> + +Set critical threshold for disk status (Default: '%{status} =~ /error/i'). +Can used special variables like: %{status} + +=item B<--warning-*> + +Threshold warning. +Can be: 'temperature-cpum', 'temperature-cpub', 'temperature-switch', 'fan-speed'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'temperature-cpum', 'temperature-cpub', 'temperature-switch', 'fan-speed'. + +=back + +=cut diff --git a/centreon-plugins/network/freebox/restapi/plugin.pm b/centreon-plugins/network/freebox/restapi/plugin.pm new file mode 100644 index 000000000..4f0451268 --- /dev/null +++ b/centreon-plugins/network/freebox/restapi/plugin.pm @@ -0,0 +1,49 @@ +# +# Copyright 2017 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::freebox::restapi::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'system' => 'network::freebox::restapi::mode::system', + ); + + $self->{custom_modes}{api} = 'network::freebox::restapi::custom::api'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Freebox through HTTP/REST API. + +=cut From 9ff128889c357e8d6b6289dfce002f7166fd5a4f Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 21 Nov 2017 15:50:37 +0100 Subject: [PATCH 03/45] freebox plugin: wip --- .../network/freebox/restapi/custom/api.pm | 37 ++++- .../network/freebox/restapi/mode/dslusage.pm | 128 +++++++++++++++ .../network/freebox/restapi/mode/netusage.pm | 146 ++++++++++++++++++ .../network/freebox/restapi/plugin.pm | 6 +- 4 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 centreon-plugins/network/freebox/restapi/mode/dslusage.pm create mode 100644 centreon-plugins/network/freebox/restapi/mode/netusage.pm diff --git a/centreon-plugins/network/freebox/restapi/custom/api.pm b/centreon-plugins/network/freebox/restapi/custom/api.pm index 13e31220c..b52bc4a6c 100644 --- a/centreon-plugins/network/freebox/restapi/custom/api.pm +++ b/centreon-plugins/network/freebox/restapi/custom/api.pm @@ -49,7 +49,7 @@ sub new { "freebox-api-version:s@" => { name => 'freebox_api_version', }, "proxyurl:s@" => { name => 'proxyurl' }, "timeout:s@" => { name => 'timeout' }, - "precision:s@" => { name => 'precision' }, + "resolution:s@" => { name => 'resolution' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -208,7 +208,40 @@ sub get_data { sub get_performance { my ($self, %options) = @_; + if (!defined($self->{session_token})) { + $self->get_session(); + } + my $json_request = { db => $options{db}, date_start => time() - $self->{resolution}, precision => 100 }; + my $encoded; + eval { + $encoded = encode_json($json_request); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot encode json request"); + $self->{output}->option_exit(); + } + + $self->settings(); + my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/' . $options{path}, + method => 'POST', query_form_post => $encoded, + critical_status => '', warning_status => ''); + my $decoded = $self->manage_response(content => $content); + my ($datas, $total) = ({}, 0); + foreach my $data (@{$decoded->{result}->{datas}}) { + foreach my $label (keys %$data) { + next if ($label eq 'time'); + $datas->{label} = 0 if (!defined($datas->{$label})); + $datas->{label} += $datas->{$label}; + } + $total++; + } + + foreach (keys %$datas) { + $datas->{$_} /= $total; + } + + return $datas; } sub DESTROY { @@ -259,7 +292,7 @@ Proxy URL if any. Set HTTP timeout in seconds (Default: '10'). -=item B<--precision> +=item B<--resolution> Selected data performance resolution in seconds (Default: '300'). diff --git a/centreon-plugins/network/freebox/restapi/mode/dslusage.pm b/centreon-plugins/network/freebox/restapi/mode/dslusage.pm new file mode 100644 index 000000000..cc804e111 --- /dev/null +++ b/centreon-plugins/network/freebox/restapi/mode/dslusage.pm @@ -0,0 +1,128 @@ +# +# Copyright 2017 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::freebox::restapi::mode::dslusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'rate-up', set => { + key_values => [ { name => 'rate_up' } ], + output_template => 'Dsl available upload bandwidth : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'rate_up', value => 'rate_up_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'rate-down', set => { + key_values => [ { name => 'rate_down' } ], + output_template => 'Dsl available download bandwidth : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'rate_down', value => 'rate_down_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'snr-up', set => { + key_values => [ { name => 'snr_up' } ], + output_template => 'Dsl upload signal/noise ratio : %.2f dB', + output_change_bytes => 2, + perfdatas => [ + { label => 'snr_up', value => 'snr_up_absolute', template => '%.2f', + unit => 'dB' }, + ], + } + }, + { label => 'snr-down', set => { + key_values => [ { name => 'snr_down' } ], + output_template => 'Dsl download signal/noise ratio : %.2f dB', + output_change_bytes => 2, + perfdatas => [ + { label => 'snr_down', value => 'snr_down_absolute', template => '%.2f', + unit => 'dB' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $result = $options{custom}->get_performance(db => 'dsl', path => 'rrd/'); + $result->{snr_up} *= 10 if (defined($result->{snr_up})); + $result->{snr_down} *= 10 if (defined($result->{snr_down})); + $self->{global} = { %{$result} }; +} + +1; + +__END__ + +=head1 MODE + +Check dsl usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^rate-up$' + +=item B<--warning-*> + +Threshold warning. +Can be: 'rate-up', 'rate-down', 'snr-up', 'snr-down'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'rate-up', 'rate-down', 'snr-up', 'snr-down'. + +=back + +=cut diff --git a/centreon-plugins/network/freebox/restapi/mode/netusage.pm b/centreon-plugins/network/freebox/restapi/mode/netusage.pm new file mode 100644 index 000000000..3a2ce7113 --- /dev/null +++ b/centreon-plugins/network/freebox/restapi/mode/netusage.pm @@ -0,0 +1,146 @@ +# +# Copyright 2017 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::freebox::restapi::mode::netusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'bw-up', set => { + key_values => [ { name => 'bw_up' } ], + output_template => 'Upload available bandwidth : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'bw_up', value => 'bw_up_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'bw-down', set => { + key_values => [ { name => 'bw_down' } ], + output_template => 'Download available bandwidth : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'bw_down', value => 'bw_down_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'rate-up', set => { + key_values => [ { name => 'rate_up' } ], + output_template => 'Upload rate : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'rate_up', value => 'rate_up_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'rate-down', set => { + key_values => [ { name => 'rate_down' } ], + output_template => 'Download rate : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'rate_down', value => 'rate_down_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'vpn-rate-up', set => { + key_values => [ { name => 'vpn_rate_up' } ], + output_template => 'Vpn client upload rate : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'vpn_rate_up', value => 'vpn_rate_up_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + { label => 'vpn-rate-down', set => { + key_values => [ { name => 'vpn_rate_down' } ], + output_template => 'Vpn client download rate : %.2f %s/s', + output_change_bytes => 2, + perfdatas => [ + { label => 'vpn_rate_down', value => 'vpn_rate_down_absolute', template => '%.2f', + unit => 'b/s', min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $result = $options{custom}->get_performance(db => 'net', path => 'rrd/'); + $self->{global} = { %{$result} }; +} + +1; + +__END__ + +=head1 MODE + +Check network usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^bw-up$' + +=item B<--warning-*> + +Threshold warning. +Can be: 'bw-up', 'bw-down', 'rate-up', 'rate-down', 'vpn-rate-up', 'vpn-rate-down'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'bw-up', 'bw-down', 'rate-up', 'rate-down', 'vpn-rate-up', 'vpn-rate-down'. + +=back + +=cut diff --git a/centreon-plugins/network/freebox/restapi/plugin.pm b/centreon-plugins/network/freebox/restapi/plugin.pm index 4f0451268..e88849059 100644 --- a/centreon-plugins/network/freebox/restapi/plugin.pm +++ b/centreon-plugins/network/freebox/restapi/plugin.pm @@ -31,8 +31,10 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( - 'system' => 'network::freebox::restapi::mode::system', - ); + 'dsl-usage' => 'network::freebox::restapi::mode::dslusage', + 'net-usage' => 'network::freebox::restapi::mode::netusage', + 'system' => 'network::freebox::restapi::mode::system', + ); $self->{custom_modes}{api} = 'network::freebox::restapi::custom::api'; return $self; From 80fbf667a0e959fc343877d024f289b9cb249173 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 21 Nov 2017 23:22:04 +0100 Subject: [PATCH 04/45] freebox plugin: wip --- .../network/freebox/restapi/custom/api.pm | 21 ++++++++++--------- .../network/freebox/restapi/mode/netusage.pm | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/centreon-plugins/network/freebox/restapi/custom/api.pm b/centreon-plugins/network/freebox/restapi/custom/api.pm index b52bc4a6c..b75c9cfaa 100644 --- a/centreon-plugins/network/freebox/restapi/custom/api.pm +++ b/centreon-plugins/network/freebox/restapi/custom/api.pm @@ -135,6 +135,7 @@ sub settings { $self->{http}->add_header(key => 'X-Fbx-App-Auth', value => $self->{session_token}); } $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->add_header(key => 'Content-type', value => 'application/json'); $self->{http}->set_options(%{$self->{option_results}}); } @@ -169,8 +170,8 @@ sub get_session { $self->settings(); my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/login/', - critical_status => '', warning_status => ''); - my $decoded = $self->manage_response(content => $content); + critical_status => '', warning_status => '', unknown_status => ''); + my $decoded = $self->manage_response(content => $content, type => 'login'); my $challenge = $decoded->{result}->{challenge}; my $password = hmac_sha1_hex($challenge, $self->{freebox_app_token}); @@ -185,8 +186,8 @@ sub get_session { } $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/login/session/', method => 'POST', - query_form_post => $encoded, critical_status => '', warning_status => ''); - $decoded = $self->manage_response(content => $content); + query_form_post => $encoded, critical_status => '', warning_status => '', unknown_status => ''); + $decoded = $self->manage_response(content => $content, type => 'login/session'); $self->{session_token} = $decoded->{result}->{session_token}; } @@ -200,8 +201,8 @@ sub get_data { $self->settings(); my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/' . $options{path}, - critical_status => '', warning_status => ''); - my $decoded = $self->manage_response(content => $content); + critical_status => '', warning_status => '', unknown_status => ''); + my $decoded = $self->manage_response(content => $content, type => $options{path}); return $decoded->{result}; } @@ -225,14 +226,14 @@ sub get_performance { $self->settings(); my $content = $self->{http}->request(url_path => '/api/' . $self->{freebox_api_version} . '/' . $options{path}, method => 'POST', query_form_post => $encoded, - critical_status => '', warning_status => ''); + critical_status => '', warning_status => '', unknown_status => ''); my $decoded = $self->manage_response(content => $content); my ($datas, $total) = ({}, 0); - foreach my $data (@{$decoded->{result}->{datas}}) { + foreach my $data (@{$decoded->{result}->{data}}) { foreach my $label (keys %$data) { next if ($label eq 'time'); - $datas->{label} = 0 if (!defined($datas->{$label})); - $datas->{label} += $datas->{$label}; + $datas->{$label} = 0 if (!defined($datas->{$label})); + $datas->{$label} += $data->{$label}; } $total++; } diff --git a/centreon-plugins/network/freebox/restapi/mode/netusage.pm b/centreon-plugins/network/freebox/restapi/mode/netusage.pm index 3a2ce7113..f241dbfb2 100644 --- a/centreon-plugins/network/freebox/restapi/mode/netusage.pm +++ b/centreon-plugins/network/freebox/restapi/mode/netusage.pm @@ -29,7 +29,7 @@ sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0 }, + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ From 05e6a14120ed917fd4e8648f321615a6b54b0a1d Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 22 Nov 2017 09:16:18 +0100 Subject: [PATCH 05/45] freebox plugin: wip --- .../network/freebox/restapi/mode/system.pm | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/centreon-plugins/network/freebox/restapi/mode/system.pm b/centreon-plugins/network/freebox/restapi/mode/system.pm index 81f8db97e..4f11eb1ab 100644 --- a/centreon-plugins/network/freebox/restapi/mode/system.pm +++ b/centreon-plugins/network/freebox/restapi/mode/system.pm @@ -31,6 +31,7 @@ sub set_counters { $self->{maps_counters_type} = [ { name => 'global', type => 0 }, + { name => 'wifi', type => 1, cb_prefix_output => 'prefix_wifi_output', message_multiple => 'All wifis are ok' } ]; $self->{maps_counters}->{global} = [ @@ -72,16 +73,20 @@ sub set_counters { }, { label => 'disk-status', threshold => 0, set => { key_values => [ { name => 'disk_status' } ], - closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'disk' }, - closure_custom_output => $self->can('custom_status_output'), + closure_custom_calc => $self->can('custom_disk_status_calc'), + closure_custom_output => $self->can('custom_disk_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold'), } }, + + ]; + + $self->{maps_counters}->{wifi} = [ { label => 'wifi-status', threshold => 0, set => { - key_values => [ { name => 'wifi_status' } ], - closure_custom_calc => $self->can('custom_status_calc'), closure_custom_calc_extra_options => { label_ref => 'wifi' }, - closure_custom_output => $self->can('custom_status_output'), + key_values => [ { name => 'wifi_status' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_wifi_status_calc'), + closure_custom_output => $self->can('custom_wifi_status_output'), closure_custom_perfdata => sub { return 0; }, closure_custom_threshold_check => $self->can('custom_status_threshold'), } @@ -115,18 +120,32 @@ sub custom_status_threshold { return $status; } -sub custom_status_output { +sub custom_disk_status_output { my ($self, %options) = @_; - my $msg = ucfirst($self->{result_values}->{label}) . ' status : ' . $self->{result_values}->{status}; + my $msg = 'Disk status : ' . $self->{result_values}->{status}; return $msg; } -sub custom_status_calc { +sub custom_disk_status_calc { my ($self, %options) = @_; - $self->{result_values}->{label} = $options{extra_options}->{label_ref}; - $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_' . $self->{result_values}->{label} . '_status'}; + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_disk_status'}; + return 0; +} + +sub custom_wifi_status_output { + my ($self, %options) = @_; + my $msg = "Wifi '" . $self->{result_values}->{display} . "' status : " . $self->{result_values}->{status}; + + return $msg; +} + +sub custom_wifi_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_wifi_status'}; return 0; } @@ -172,7 +191,15 @@ sub manage_selection { $self->{global} = { %{$result} }; $result = $options{custom}->get_data(path => 'wifi/ap/'); - $self->{global}->{wifi_status} = $result->{status}->{state}; + $self->{wifi} = {}; + + $result = [$result] if (ref($result) ne 'ARRAY'); + foreach (@$result) { + $self->{wifi}->{$_->{id}} = { + display => $_->{name}, + wifi_status => $_->{status}->{state}, + }; + } } 1; @@ -193,12 +220,12 @@ Example: --filter-counters='^temperature-cpum$' =item B<--warning-wifi-status> Set warning threshold for wifi status (Default: '%{status} =~ /bad_param/i'). -Can used special variables like: %{status} +Can used special variables like: %{status}, %{display} =item B<--critical-wifi-status> Set critical threshold for wifi status (Default: '%{status} =~ /failed/i'). -Can used special variables like: %{status} +Can used special variables like: %{status}, %{display} =item B<--warning-disk-status> From 5ad9b3ea78ef30b2ec93ebcb3794d21b6f2390aa Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 22 Nov 2017 13:10:07 +0100 Subject: [PATCH 06/45] fix #439 --- .../centreon/plugins/statefile.pm | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/centreon-plugins/centreon/plugins/statefile.pm b/centreon-plugins/centreon/plugins/statefile.pm index 0275fa778..0915ee50a 100644 --- a/centreon-plugins/centreon/plugins/statefile.pm +++ b/centreon-plugins/centreon/plugins/statefile.pm @@ -37,6 +37,9 @@ sub new { $options{options}->add_options(arguments => { "memcached:s" => { name => 'memcached' }, + "redis-server:s" => { name => 'redis_server' }, + 'redis-attribute:s%' => { name => 'redis_attribute' }, + "memexpiration:s" => { name => 'memexpiration', default => 86400 }, "statefile-dir:s" => { name => 'statefile_dir', default => $default_dir }, "statefile-suffix:s" => { name => 'statefile_suffix', default => '' }, "statefile-concat-cwd" => { name => 'statefile_concat_cwd' }, @@ -67,6 +70,24 @@ sub check_options { $self->{memcached} = Memcached::libmemcached->new(); Memcached::libmemcached::memcached_server_add($self->{memcached}, $options{option_results}->{memcached}); } + + # Check redis + if (defined($options{option_results}->{redis_server})) { + $self->{redis_attributes} = ''; + if (defined($options{option_results}->{redis_attribute})) { + foreach (keys %{$options{option_results}->{redis_attribute}}) { + $self->{redis_attributes} .= "$_ => " . $options{option_results}->{redis_attribute}->{$_} . ", "; + } + } + + centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Redis', + error_msg => "Cannot load module 'Redis'."); + eval { + $self->{redis_cnx} = Redis->new(server => $options{option_results}->{redis_server}, + eval $self->{redis_attributes}); + }; + } + $self->{statefile_dir} = $options{option_results}->{statefile_dir}; if ($self->{statefile_dir} ne $default_dir && defined($options{option_results}->{statefile_concat_cwd})) { centreon::plugins::misc::mymodule_load(output => $self->{output}, module => 'Cwd', @@ -79,6 +100,7 @@ sub check_options { $self->{storable} = 1; } $self->{statefile_suffix} = $options{option_results}->{statefile_suffix}; + $self->{memexpiration} = $options{option_results}->{memexpiration}; } sub error { @@ -113,6 +135,18 @@ sub read { } } + if (defined($self->{redis_cnx})) { + my $val = $self->{redis_cnx}->get($self->{statefile_dir} . "/" . $self->{statefile}); + if (defined($val)) { + eval($val); + $self->{datas} = $datas; + $datas = {}; + return 1; + } + + return 0; + } + if (! -e $self->{statefile_dir} . "/" . $self->{statefile}) { if (! -w $self->{statefile_dir}) { $self->error(1); @@ -188,11 +222,15 @@ sub write { if ($self->{memcached_ok} == 1) { Memcached::libmemcached::memcached_set($self->{memcached}, $self->{statefile_dir} . "/" . $self->{statefile}, - Data::Dumper->Dump([$options{data}], ["datas"])); + Data::Dumper->Dump([$options{data}], ["datas"]), $self->{memexpiration}); if (defined($self->{memcached}->errstr) && $self->{memcached}->errstr =~ /^SUCCESS$/i) { return ; } } + if (defined($self->{redis_cnx})) { + return if (defined($self->{redis_cnx}->set($self->{statefile_dir} . "/" . $self->{statefile}, Data::Dumper->Dump([$options{data}], ["datas"]), + 'EX', $self->{memexpiration}))); + } open FILE, ">", $self->{statefile_dir} . "/" . $self->{statefile}; if ($self->{storable} == 1) { Storable::store_fd($options{data}, *FILE); @@ -222,6 +260,18 @@ Statefile class Memcached server to use (only one server). +=item B<--redis-server> + +Redis server to use (only one server). + +=item B<--redis-attribute> + +Set Redis Options (--redis-attribute="cnx_timeout=5"). + +=item B<--memexpiration> + +Time to keep data in seconds (Default: 86400). + =item B<--statefile-dir> Directory for statefile (Default: '/var/lib/centreon/centplugins'). From b9c1a2662c6a3536e6cac9c78d9e6a4f607da3f4 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 22 Nov 2017 14:14:08 +0100 Subject: [PATCH 07/45] Fix #794 --- .../snmp_standard/mode/printererror.pm | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/centreon-plugins/snmp_standard/mode/printererror.pm b/centreon-plugins/snmp_standard/mode/printererror.pm index a0b4688f8..4699e0d00 100644 --- a/centreon-plugins/snmp_standard/mode/printererror.pm +++ b/centreon-plugins/snmp_standard/mode/printererror.pm @@ -72,21 +72,14 @@ sub run { my $oid_hrPrinterDetectedErrorState = '.1.3.6.1.2.1.25.3.5.1.2'; my $result = $self->{snmp}->get_table(oid => $oid_hrPrinterDetectedErrorState, nothing_quit => 1); + use Data::Dumper; + print Data::Dumper::Dumper($result); foreach (keys %$result) { - my ($value1, $value2) = unpack('C', $result->{$_}); + # 16 bits value + my $value = unpack('S', $result->{$_}); - foreach my $key (keys %errors_printer) { - my ($byte_check, $pos); - if ($key >= 8) { - next if (!defined($value2)); - $byte_check = $value2; - $pos = $key - 8; - } else { - $byte_check = $value1; - $pos = $key - } - - if (($byte_check & (1 << $pos)) && + foreach my $key (keys %errors_printer) { + if (($value & (1 << $key)) && (!$self->{output}->is_status(value => ${$errors_printer{$key}}[1], compare => 'ok', litteral => 1))) { $self->{output}->output_add(severity => ${$errors_printer{$key}}[1], short_msg => sprintf(${$errors_printer{$key}}[0])); From e4afce1baf2c45fd3e6f9e358d25f469fa0d40b5 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 22 Nov 2017 14:14:22 +0100 Subject: [PATCH 08/45] Fix #794 --- centreon-plugins/snmp_standard/mode/printererror.pm | 2 -- 1 file changed, 2 deletions(-) diff --git a/centreon-plugins/snmp_standard/mode/printererror.pm b/centreon-plugins/snmp_standard/mode/printererror.pm index 4699e0d00..0cea63e51 100644 --- a/centreon-plugins/snmp_standard/mode/printererror.pm +++ b/centreon-plugins/snmp_standard/mode/printererror.pm @@ -72,8 +72,6 @@ sub run { my $oid_hrPrinterDetectedErrorState = '.1.3.6.1.2.1.25.3.5.1.2'; my $result = $self->{snmp}->get_table(oid => $oid_hrPrinterDetectedErrorState, nothing_quit => 1); - use Data::Dumper; - print Data::Dumper::Dumper($result); foreach (keys %$result) { # 16 bits value my $value = unpack('S', $result->{$_}); From 894d61df1c3dffd3a8c85b38752b6874366a4c46 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 22 Nov 2017 16:18:44 +0100 Subject: [PATCH 09/45] add plugin netgear mseries snmp --- .../mseries/snmp/mode/components/fan.pm | 86 +++++++++++ .../mseries/snmp/mode/components/psu.pm | 71 +++++++++ .../snmp/mode/components/temperature.pm | 86 +++++++++++ .../network/netgear/mseries/snmp/mode/cpu.pm | 123 ++++++++++++++++ .../netgear/mseries/snmp/mode/hardware.pm | 129 ++++++++++++++++ .../netgear/mseries/snmp/mode/memory.pm | 138 ++++++++++++++++++ .../network/netgear/mseries/snmp/plugin.pm | 52 +++++++ 7 files changed, 685 insertions(+) create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/components/fan.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/components/psu.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/components/temperature.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/cpu.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/hardware.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/mode/memory.pm create mode 100644 centreon-plugins/network/netgear/mseries/snmp/plugin.pm diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/components/fan.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/components/fan.pm new file mode 100644 index 000000000..04ab649b7 --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/components/fan.pm @@ -0,0 +1,86 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::mode::components::fan; + +use strict; +use warnings; + +my %map_fan_status = ( + 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', + 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' +); + +my $mapping = { + boxServicesFanItemState => { oid => '.1.3.6.1.4.1.4526.10.43.1.6.1.3', map => \%map_fan_status }, + boxServicesFanSpeed => { oid => '.1.3.6.1.4.1.4526.10.43.1.6.1.4' }, +}; +my $oid_boxServicesFansEntry = '.1.3.6.1.4.1.4526.10.43.1.6.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_boxServicesFansEntry, begin => $mapping->{boxServicesFanItemState}->{oid}, end => $mapping->{boxServicesFanSpeed}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesFansEntry}})) { + next if ($oid !~ /^$mapping->{boxServicesFanItemState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesFansEntry}, instance => $instance); + + next if ($self->check_filter(section => 'fan', instance => $instance)); + if ($result->{boxServicesFanItemState} =~ /notpresent/i) { + $self->absent_problem(section => 'fan', instance => $instance); + next; + } + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s, speed = %s]", + $instance, $result->{boxServicesFanItemState}, $instance, defined($result->{boxServicesFanSpeed}) ? $result->{boxServicesFanSpeed} : 'unknown')); + $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{boxServicesFanItemState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{boxServicesFanItemState})); + } + + next if (!defined($result->{boxServicesFanSpeed}) || $result->{boxServicesFanSpeed} !~ /[0-9]+/); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{boxServicesFanSpeed}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' is '%s' rpm", $instance, $result->{boxServicesFanSpeed})); + } + $self->{output}->perfdata_add(label => 'fan_' . $instance, unit => 'rpm', + value => $result->{boxServicesFanSpeed}, + warning => $warn, + critical => $crit, min => 0 + ); + } +} + +1; diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/components/psu.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/components/psu.pm new file mode 100644 index 000000000..e7e0ef28a --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/components/psu.pm @@ -0,0 +1,71 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::mode::components::psu; + +use strict; +use warnings; + +my %map_psu_status = ( + 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', + 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' +); + +my $mapping = { + boxServicesPowSupplyItemState => { oid => '.1.3.6.1.4.1.4526.10.43.1.7.1.3', map => \%map_psu_status }, +}; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $mapping->{boxServicesPowSupplyItemState}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}})) { + next if ($oid !~ /^$mapping->{boxServicesPowSupplyItemState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}, instance => $instance); + + next if ($self->check_filter(section => 'psu', instance => $instance)); + if ($result->{boxServicesPowSupplyItemState} =~ /notpresent/i) { + $self->absent_problem(section => 'psu', instance => $instance); + next; + } + + $self->{components}->{psu}->{total}++; + $self->{output}->output_add(long_msg => sprintf("power supply '%s' status is '%s' [instance = %s]", + $instance, $result->{boxServicesPowSupplyItemState}, $instance)); + $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{boxServicesPowSupplyItemState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{boxServicesPowSupplyItemState})); + } + } +} + +1; diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/components/temperature.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/components/temperature.pm new file mode 100644 index 000000000..36a1a6603 --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/components/temperature.pm @@ -0,0 +1,86 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::mode::components::temperature; + +use strict; +use warnings; + +my %map_temp_status = ( + 0 => 'low', 1 => 'normal', 2 => 'warning', 3 => 'critical', + 4 => 'shutdown', 5 => 'notpresent', 6 => 'notoperational', +); + +my $mapping = { + boxServicesTempSensorState => { oid => '.1.3.6.1.4.1.4526.10.43.1.8.1.4', map => \%map_temp_status }, + boxServicesTempSensorTemperature => { oid => '.1.3.6.1.4.1.4526.10.43.1.8.1.5' }, +}; +my $oid_boxServicesTempSensorsEntry = '.1.3.6.1.4.1.4526.10.43.1.8.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_boxServicesTempSensorsEntry, begin => $mapping->{boxServicesTempSensorState}->{oid}, end => $mapping->{boxServicesTempSensorTemperature}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesTempSensorsEntry}})) { + next if ($oid !~ /^$mapping->{boxServicesTempSensorState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesTempSensorsEntry}, instance => $instance); + + next if ($self->check_filter(section => 'temperature', instance => $instance)); + if ($result->{boxServicesTempSensorState} =~ /notpresent/i) { + $self->absent_problem(section => 'temperature', instance => $instance); + next; + } + + $self->{components}->{temperature}->{total}++; + $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s, temperature = %s]", + $instance, $result->{boxServicesTempSensorState}, $instance, defined($result->{boxServicesTempSensorTemperature}) ? $result->{boxServicesTempSensorTemperature} : 'unknown')); + $exit = $self->get_severity(section => 'temperature', value => $result->{boxServicesTempSensorState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{boxServicesTempSensorState})); + } + + next if (!defined($result->{boxServicesTempSensorTemperature}) || $result->{boxServicesTempSensorTemperature} !~ /[0-9]+/); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{boxServicesTempSensorTemperature}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Temperature '%s' is '%s' rpm", $instance, $result->{boxServicesTempSensorTemperature})); + } + $self->{output}->perfdata_add(label => 'temp_' . $instance, unit => 'C', + value => $result->{boxServicesTempSensorTemperature}, + warning => $warn, + critical => $crit, + ); + } +} + +1; diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/cpu.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/cpu.pm new file mode 100644 index 000000000..4ad787a62 --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/cpu.pm @@ -0,0 +1,123 @@ +# +# Copyright 2017 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::netgear::mseries::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 => 'global', type => 0, cb_prefix_output => 'prefix_cpu_output' } + ]; + + $self->{maps_counters}->{global} = [ + { label => '5s', set => { + key_values => [ { name => 'usage_5s' } ], + output_template => '%.2f %% (5sec)', output_error_template => "%s (5sec)", + perfdatas => [ + { label => 'cpu_5s', value => 'usage_5s_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '1m', set => { + key_values => [ { name => 'usage_1m' } ], + output_template => '%.2f %% (1m)', output_error_template => "%s (1min)", + perfdatas => [ + { label => 'cpu_1m', value => 'usage_1m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '5m', set => { + key_values => [ { name => 'usage_5m' } ], + output_template => '%.2f %% (5min)', output_error_template => "%s (5min)", + perfdatas => [ + { label => 'cpu_5m', value => 'usage_5m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + ]; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + # STRING: " 5 Secs ( 43.2625%) 60 Secs ( 13.9157%) 300 Secs ( 8.9274%)" + my $oid_agentSwitchCpuProcessTotalUtilization = '.1.3.6.1.4.1.4526.10.1.1.4.9.0'; + my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessTotalUtilization], nothing_quit => 1); + + $snmp_result->{$oid_agentSwitchCpuProcessTotalUtilization} =~ /\s*5\s*Secs\s*\(\s*(.*?)%\s*\)\s*60\s*Secs\s*\(\s*(.*?)%\s*\)\s*300\s*Secs\s*\(\s*(.*?)%\s*\)/i; + $self->{global} = { usage_5s => $1, usage_1m => $2, usage_5m => $3 }; +} + +1; + +__END__ + +=head1 MODE + +Check CPU usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='5m' + +=item B<--warning-*> + +Threshold warning. +Can be: '5s', '1m', '5m'. + +=item B<--critical-*> + +Threshold critical. +Can be: '5s', '1m', '5m'. + +=back + +=cut diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/hardware.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/hardware.pm new file mode 100644 index 000000000..3f48cfb07 --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/hardware.pm @@ -0,0 +1,129 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(temperature|fan|psu)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + default => [ + ['notPresent', 'OK'], + ['operational', 'OK'], + ['failed', 'CRITICAL'], + ['notpowering', 'WARNING'], + ['powering', 'OK'], + ['nopower', 'OK'], + ['incompatible', 'WARNING'], + ], + temperature => [ + ['low', 'OK'], + ['normal', 'OK'], + ['warning', 'WARNING'], + ['critical', 'CRITICAL'], + ['notpresent', 'OK'], + ['shutdown', 'OK'], + ['notoperational', 'WARNING'], + ], + }; + + $self->{components_path} = 'network::netgear::mseries::snmp::mode::components'; + $self->{components_module} = ['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); + bless $self, $class; + + $self->{version} = '1.0'; + $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: 'fan', 'psu', 'temperature'. + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) +Can also exclude specific instance: --filter=fan,1.1 + +=item B<--absent-problem> + +Return an error if an entity is not 'present' (default is skipping) (comma seperated list) +Can be specific or global: --absent-problem=fan,1 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='psu,CRITICAL,^(?!(operational)$)' + +=item B<--warning> + +Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --warning='temperature,.*,40' + +=item B<--critical> + +Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --critical='temperature,.*,50' + +=back + +=cut diff --git a/centreon-plugins/network/netgear/mseries/snmp/mode/memory.pm b/centreon-plugins/network/netgear/mseries/snmp/mode/memory.pm new file mode 100644 index 000000000..d2e2e646e --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/mode/memory.pm @@ -0,0 +1,138 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => 'used', unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, 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->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + + my $msg = sprintf("Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; + + $self->{result_values}->{used} = int($self->{result_values}->{prct_used} * $self->{result_values}->{total} / 100); + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'memory', type => 0 } + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'usage', set => { + key_values => [ { name => 'prct_used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_agentSwitchCpuProcessMemFree = '.1.3.6.1.4.1.4526.10.1.1.4.1.0'; # KB + my $oid_agentSwitchCpuProcessMemAvailable = '.1.3.6.1.4.1.4526.10.1.1.4.2.0'; # KB + my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessMemFree, $oid_agentSwitchCpuProcessMemAvailable], nothing_quit => 1); + + my $total = $snmp_result->{$oid_agentSwitchCpuProcessMemAvailable} * 1024; + $self->{memory} = { + prct_used => ($total - $snmp_result->{$oid_agentSwitchCpuProcessMemFree} * 1024) * 100 / $total, + total => $total, + }; +} + +1; + +__END__ + +=head1 MODE + +Check memory usage. + +=over 8 + +=item B<--warning-usage> + +Threshold warning (in percent). + +=item B<--critical-usage> + +Threshold critical (in percent). + +=back + +=cut diff --git a/centreon-plugins/network/netgear/mseries/snmp/plugin.pm b/centreon-plugins/network/netgear/mseries/snmp/plugin.pm new file mode 100644 index 000000000..454375a16 --- /dev/null +++ b/centreon-plugins/network/netgear/mseries/snmp/plugin.pm @@ -0,0 +1,52 @@ +# +# Copyright 2017 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::netgear::mseries::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cpu' => 'network::netgear::mseries::snmp::mode::cpu', + 'hardware' => 'network::netgear::mseries::snmp::mode::hardware', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'memory' => 'network::netgear::mseries::snmp::mode::memory', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Netgear Fully Managed Switches (M4200, M4300, M6100,...) in SNMP. + +=cut From 4701dacd0e3fd31d10414dea843614139bac34f7 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 10:51:43 +0100 Subject: [PATCH 10/45] add mode for tomcat jmx --- .../apps/tomcat/jmx/mode/datasourceusage.pm | 230 ++++++++++++++++++ .../apps/tomcat/jmx/mode/listdatasources.pm | 137 +++++++++++ .../apps/tomcat/jmx/mode/listwebapps.pm | 134 ++++++++++ .../apps/tomcat/jmx/mode/webappssessions.pm | 227 +++++++++++++++++ centreon-plugins/apps/tomcat/jmx/plugin.pm | 4 + 5 files changed, 732 insertions(+) create mode 100644 centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm create mode 100644 centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm create mode 100644 centreon-plugins/apps/tomcat/jmx/mode/listwebapps.pm create mode 100644 centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm diff --git a/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm new file mode 100644 index 000000000..eef003b5e --- /dev/null +++ b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm @@ -0,0 +1,230 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::tomcat::jmx::mode::datasourceusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'datasource', type => 1, cb_prefix_output => 'prefix_ds_output', message_multiple => 'All datasources are ok' }, + ]; + + $self->{maps_counters}->{datasource} = [ + { label => 'num-active', set => { + key_values => [ { name => 'numActive' }, { name => 'maxActive' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_calc_extra_options => { label_ref => 'Active', message => 'Current Num Active' }, + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + } + }, + { label => 'num-idle', set => { + key_values => [ { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_calc_extra_options => { label_ref => 'Idle', message => 'Current Num Idle' }, + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + } + }, + ]; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $use_th = 1; + $use_th = 0 if ($instance_mode->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); + + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + + my $value_perf = $self->{result_values}->{used}; + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { + $total_options{total} = $self->{result_values}->{max}; + $total_options{cast_int} = 1; + } + + my $label = $self->{label}; + $label =~ s/-/_/g; + $self->{output}->perfdata_add(label => $label . $extra_label, + value => $value_perf, + warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options) : undef, + critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options) : undef, + min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + # Cannot use percent without total + return 'ok' if ($self->{result_values}->{max} <= 0 && $instance_mode->{option_results}->{units} eq '%'); + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my $msg; + if ($self->{result_values}->{max} > 0) { + $msg = sprintf("%s Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $self->{result_values}->{message}, $self->{result_values}->{max}, + $self->{result_values}->{used}, $self->{result_values}->{prct_used}, + $self->{result_values}->{max} - $self->{result_values}->{used}, 100 - $self->{result_values}->{prct_used}); + } else { + $msg = sprintf("%s : %s", $self->{result_values}->{message}, $self->{result_values}->{used}); + } + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{message} = $options{extra_options}->{message}; + $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_max' . $options{extra_options}->{label_ref}}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_num' . $options{extra_options}->{label_ref}}; + if ($self->{result_values}->{max} > 0) { + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; + } + + return 0; +} + +sub prefix_ds_output { + my ($self, %options) = @_; + + return "Datasource '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + # maxActive or maxTotal + $self->{request} = [ + { mbean => "*:type=DataSource,class=*,context=*,host=*,name=*", attributes => + [ { name => 'numActive' }, { name => 'numIdle' }, { name => 'maxIdle' }, { name => 'maxTotal' }, { name => 'maxActive' } ] }, + ]; + + my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); + + $self->{datasource} = {}; + foreach my $key (keys %$result) { + $key =~ /(?:[:,])host=(.*?)(?:,|$)/; + my $ds_name = $1; + $key =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; + $ds_name .= '.' . $1; + $key =~ /(?:[:,])name=(.*?)(?:,|$)/; + $ds_name .= '.' . $1; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $ds_name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $ds_name . "': no matching filter.", debug => 1); + next; + } + + $self->{datasource}->{$ds_name} = { + display => $ds_name, + numActive => $result->{$key}->{numActive}, + maxActive => defined($result->{$key}->{maxTotal}) ? $result->{$key}->{maxTotal} : $result->{$key}->{maxActive}, + numIdle => $result->{$key}->{numIdle}, + maxIdle => $result->{$key}->{maxIdle}, + }; + } + + $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check data sources usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='num-active' + +=item B<--filter-name> + +Filter datasource name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'num-active', 'num-idle'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'num-active', 'num-idle'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'absolute'). + +=back + +=cut diff --git a/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm b/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm new file mode 100644 index 000000000..a3bb7ee3e --- /dev/null +++ b/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm @@ -0,0 +1,137 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::tomcat::jmx::mode::listdatasources; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-host:s" => { name => 'filter_host' }, + "filter-path:s" => { name => 'filter_path' }, + }); + $self->{ds} = {}; + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{request} = [ + { mbean => "*:type=DataSource,class=*,context=*,host=*,name=*", attributes => + [ { name => 'numActive' } ] }, + ]; + my $result = $options{custom}->get_attributes(request => $self->{request}); + + foreach my $mbean (keys %{$result}) { + $mbean =~ /(?:[:,])host=(.*?)(?:,|$)/; + my $host = $1; + $mbean =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; + my $path = $1; + $mbean =~ /(?:[:,])name=(.*?)(?:,|$)/; + my $name = $1; + + if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && + $host !~ /$self->{option_results}->{filter_host}/) { + $self->{output}->output_add(long_msg => "skipping '" . $host . "': no matching filter.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && + $path !~ /$self->{option_results}->{filter_path}/) { + $self->{output}->output_add(long_msg => "skipping '" . $path . "': no matching filter.", debug => 1); + next; + } + + $self->{ds}->{$host . '.' . $path} = { + host => $host, path => $path, name => $name, + }; + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{ds}}) { + $self->{output}->output_add(long_msg => '[host = ' . $self->{ds}->{$instance}->{host} . "]" . + " [path = '" . $self->{ds}->{$instance}->{path} . "']" . + " [name = '" . $self->{ds}->{$instance}->{name} . "']" + ); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List data sources:'); + $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 => ['host', 'path', 'name']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{ds}}) { + $self->{output}->add_disco_entry( + %{$self->{ds}->{$instance}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List data sources. + +=over 8 + +=item B<--filter-host> + +Filter by virtual host name (can be a regexp). + +=item B<--filter-path> + +Filter by application name (can be a regexp). + +=back + +=cut + diff --git a/centreon-plugins/apps/tomcat/jmx/mode/listwebapps.pm b/centreon-plugins/apps/tomcat/jmx/mode/listwebapps.pm new file mode 100644 index 000000000..d42afc749 --- /dev/null +++ b/centreon-plugins/apps/tomcat/jmx/mode/listwebapps.pm @@ -0,0 +1,134 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::tomcat::jmx::mode::listwebapps; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-host:s" => { name => 'filter_host' }, + "filter-path:s" => { name => 'filter_path' }, + }); + $self->{webapps} = {}; + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{request} = [ + { mbean => "*:context=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' } ] }, + { mbean => "*:path=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' } ] }, + ]; + my $result = $options{custom}->get_attributes(request => $self->{request}); + + foreach my $mbean (keys %{$result}) { + $mbean =~ /(?:[:,])host=(.*?)(?:,|$)/; + my $host = $1; + $mbean =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; + my $path = $1; + + if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && + $host !~ /$self->{option_results}->{filter_host}/) { + $self->{output}->output_add(long_msg => "skipping '" . $host . "': no matching filter.", debug => 1); + next; + } + if (defined($self->{option_results}->{filter_path}) && $self->{option_results}->{filter_path} ne '' && + $path !~ /$self->{option_results}->{filter_path}/) { + $self->{output}->output_add(long_msg => "skipping '" . $path . "': no matching filter.", debug => 1); + next; + } + + $self->{webapps}->{$host . '.' . $path} = { + host => $host, path => $path, + }; + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{webapps}}) { + $self->{output}->output_add(long_msg => '[host = ' . $self->{webapps}->{$instance}->{host} . "]" . + " [path = '" . $self->{webapps}->{$instance}->{path} . "']" + ); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List webapps:'); + $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 => ['host', 'path']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{webapps}}) { + $self->{output}->add_disco_entry( + %{$self->{webapps}->{$instance}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List webapps. + +=over 8 + +=item B<--filter-host> + +Filter by virtual host name (can be a regexp). + +=item B<--filter-path> + +Filter by application name (can be a regexp). + +=back + +=cut + diff --git a/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm b/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm new file mode 100644 index 000000000..b1f36813a --- /dev/null +++ b/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm @@ -0,0 +1,227 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::tomcat::jmx::mode::webappssessions; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'webapps', type => 1, cb_prefix_output => 'prefix_webapps_output', message_multiple => 'All webapp sessions are ok' }, + ]; + + $self->{maps_counters}->{webapps} = [ + { label => 'sessions-active', set => { + key_values => [ { name => 'activeSessions' }, { name => 'maxActiveSessions' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_calc_extra_options => { label_ref => 'currentThreadCount', message => 'Current Threads' }, + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + } + }, + { label => 'sessions-count', set => { + key_values => [ { name => 'sessionCounter', diff => 1 }, { name => 'display' } ], + output_template => 'Sessions Count : %s', + perfdatas => [ + { label => 'sessions_count', value => 'sessionCounter_absolute', template => '%s', + min => 0, label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + my $use_th = 1; + $use_th = 0 if ($instance_mode->{option_results}->{units} eq '%' && $self->{result_values}->{max} <= 0); + + my $extra_label = ''; + $extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0); + + my $value_perf = $self->{result_values}->{used}; + my %total_options = (); + if ($instance_mode->{option_results}->{units} eq '%' && $self->{result_values}->{max} > 0) { + $total_options{total} = $self->{result_values}->{max}; + $total_options{cast_int} = 1; + } + + my $label = $self->{label}; + $label =~ s/-/_/g; + $self->{output}->perfdata_add(label => $label . $extra_label, + value => $value_perf, + warning => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options) : undef, + critical => $use_th == 1 ? $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options) : undef, + min => 0, max => $self->{result_values}->{max} > 0 ? $self->{result_values}->{max} : undef); +} + +sub custom_usage_threshold { + my ($self, %options) = @_; + + # Cannot use percent without total + return 'ok' if ($self->{result_values}->{max} <= 0 && $instance_mode->{option_results}->{units} eq '%'); + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' }, { label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my $msg; + if ($self->{result_values}->{max} > 0) { + $msg = sprintf("Current Active Sessions Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $self->{result_values}->{max}, + $self->{result_values}->{used}, $self->{result_values}->{prct_used}, + $self->{result_values}->{max} - $self->{result_values}->{used}, 100 - $self->{result_values}->{prct_used}); + } else { + $msg = sprintf("Current Active Sessions : %s", $self->{result_values}->{used}); + } + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{max} = $options{new_datas}->{$self->{instance} . '_maxActiveSessions'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_activeSessions'}; + if ($self->{result_values}->{max} > 0) { + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{max}; + } + + return 0; +} + +sub prefix_webapps_output { + my ($self, %options) = @_; + + return "Webapp '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "units:s" => { name => 'units', default => '%' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + # can be path or context + # Tomcat: Catalina:context=/xxxxx,host=localhost,type=Manager + # Jboss: jboss.web:host=localhost,path=/invoker,type=Manager + # maxActiveSessions = -1 (no limit) + $self->{request} = [ + { mbean => "*:context=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' }, { name => 'sessionCounter' }, { name => 'maxActiveSessions' } ] }, + { mbean => "*:path=*,host=*,type=Manager", attributes => [ { name => 'activeSessions' }, { name => 'sessionCounter' }, { name => 'maxActiveSessions' } ] }, + ]; + + my $result = $options{custom}->get_attributes(request => $self->{request}, nothing_quit => 1); + + $self->{webapps} = {}; + foreach my $key (keys %$result) { + $key =~ /(?:[:,])host=(.*?)(?:,|$)/; + my $webapps = $1; + $key =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; + $webapps .= '.' . $1; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $webapps !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $webapps . "': no matching filter.", debug => 1); + next; + } + + $self->{webapps}->{$webapps} = { + display => $webapps, + %{$result->{$key}} + }; + } + + $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check webapps session usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='sessions-active' + +=item B<--filter-name> + +Filter webapps name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'sessions-count', 'sessions-active'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'sessions-count', 'sessions-active'. + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'absolute'). + +=back + +=cut diff --git a/centreon-plugins/apps/tomcat/jmx/plugin.pm b/centreon-plugins/apps/tomcat/jmx/plugin.pm index 25a5c57a6..2d732e713 100644 --- a/centreon-plugins/apps/tomcat/jmx/plugin.pm +++ b/centreon-plugins/apps/tomcat/jmx/plugin.pm @@ -34,12 +34,16 @@ sub new { 'class-count' => 'centreon::common::jvm::mode::classcount', 'connector-usage' => 'apps::tomcat::jmx::mode::connectorusage', 'cpu-load' => 'centreon::common::jvm::mode::cpuload', + 'datasource-usage' => 'apps::tomcat::jmx::mode::datasourceusage', 'fd-usage' => 'centreon::common::jvm::mode::fdusage', 'gc-usage' => 'centreon::common::jvm::mode::gcusage', + 'list-datasources' => 'apps::tomcat::jmx::mode::listdatasources', + 'list-webapps' => 'apps::tomcat::jmx::mode::listwebapps', 'load-average' => 'centreon::common::jvm::mode::loadaverage', 'memory' => 'centreon::common::jvm::mode::memory', 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', 'threads' => 'centreon::common::jvm::mode::threads', + 'webapps-sessions' => 'apps::tomcat::jmx::mode::webappssessions', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; From d0479b9f13aa8606c7b1558481c2fcebbb2230ed Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 15:25:37 +0100 Subject: [PATCH 11/45] enhance tomcat jmx --- centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm | 3 ++- centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm | 6 ++++-- centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm b/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm index cea015621..80aa205c8 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm @@ -197,7 +197,8 @@ sub manage_selection { $self->{tomcatconnector} = {}; foreach my $key (keys %$result) { $key =~ /name=(.*?),type=(.*)/; - my ($connector, $type) = ($1, $2); + my ($connector, $type) = ($1, $2); # double quote nivo du name si existe + $connector =~ s/^"(.*)"$/$1/g; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $connector !~ /$self->{option_results}->{filter_name}/) { diff --git a/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm index eef003b5e..80e60cfb6 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm @@ -168,9 +168,11 @@ sub manage_selection { $key =~ /(?:[:,])host=(.*?)(?:,|$)/; my $ds_name = $1; $key =~ /(?:[:,])(?:path|context)=(.*?)(?:,|$)/; - $ds_name .= '.' . $1; - $key =~ /(?:[:,])name=(.*?)(?:,|$)/; $ds_name .= '.' . $1; + $key =~ /(?:[:,])name=(.*?)(?:,|$)/; # double quote a virer + my $tmp_name = $1; + $tmp_name =~ s/^"(.*)"$/$1/; + $ds_name .= '.' . $tmp_name; if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && $ds_name !~ /$self->{option_results}->{filter_name}/) { diff --git a/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm b/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm index a3bb7ee3e..babbeec93 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/listdatasources.pm @@ -61,6 +61,7 @@ sub manage_selection { my $path = $1; $mbean =~ /(?:[:,])name=(.*?)(?:,|$)/; my $name = $1; + $name =~ s/^"(.*)"$/$1/; if (defined($self->{option_results}->{filter_host}) && $self->{option_results}->{filter_host} ne '' && $host !~ /$self->{option_results}->{filter_host}/) { From 27f048b7003c2a79c99a31584d29bfa6a965fa71 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 15:40:42 +0100 Subject: [PATCH 12/45] add plugin zyxel snmp --- .../network/zyxel/snmp/mode/cpu.pm | 132 ++++++++++ .../network/zyxel/snmp/mode/listvpn.pm | 133 ++++++++++ .../network/zyxel/snmp/mode/memory.pm | 111 ++++++++ .../network/zyxel/snmp/mode/vpnstatus.pm | 249 ++++++++++++++++++ centreon-plugins/network/zyxel/snmp/plugin.pm | 53 ++++ 5 files changed, 678 insertions(+) create mode 100644 centreon-plugins/network/zyxel/snmp/mode/cpu.pm create mode 100644 centreon-plugins/network/zyxel/snmp/mode/listvpn.pm create mode 100644 centreon-plugins/network/zyxel/snmp/mode/memory.pm create mode 100644 centreon-plugins/network/zyxel/snmp/mode/vpnstatus.pm create mode 100644 centreon-plugins/network/zyxel/snmp/plugin.pm diff --git a/centreon-plugins/network/zyxel/snmp/mode/cpu.pm b/centreon-plugins/network/zyxel/snmp/mode/cpu.pm new file mode 100644 index 000000000..88dcbc887 --- /dev/null +++ b/centreon-plugins/network/zyxel/snmp/mode/cpu.pm @@ -0,0 +1,132 @@ +# +# Copyright 2017 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::zyxel::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 => 'global', type => 0, cb_prefix_output => 'prefix_cpu_output' } + ]; + + $self->{maps_counters}->{global} = [ + { label => '5s', set => { + key_values => [ { name => 'usage_5s' } ], + output_template => '%.2f %% (5sec)', output_error_template => "%s (5sec)", + perfdatas => [ + { label => 'cpu_5s', value => 'usage_5s_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '1m', set => { + key_values => [ { name => 'usage_1m' } ], + output_template => '%.2f %% (1m)', output_error_template => "%s (1min)", + perfdatas => [ + { label => 'cpu_1m', value => 'usage_1m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '5m', set => { + key_values => [ { name => 'usage_5m' } ], + output_template => '%.2f %% (5min)', output_error_template => "%s (5min)", + perfdatas => [ + { label => 'cpu_5m', value => 'usage_5m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + ]; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_sysCPU5SecUsage = '.1.3.6.1.4.1.890.1.6.22.1.3.0'; + my $oid_sysCPU1MinUsage = '.1.3.6.1.4.1.890.1.6.22.1.4.0'; + my $oid_sysCPU5MinUsage = '.1.3.6.1.4.1.890.1.6.22.1.5.0'; + my $oid_sysMgmtCPU5SecUsage = '.1.3.6.1.4.1.890.1.15.3.2.7.0'; + my $oid_sysMgmtCPU1MinUsage = '.1.3.6.1.4.1.890.1.15.3.2.8.0'; + my $oid_sysMgmtCPU5MinUsage = '.1.3.6.1.4.1.890.1.15.3.2.9.0'; + my $snmp_result = $options{snmp}->get_leef(oids => [$oid_sysCPU5SecUsage, + $oid_sysCPU1MinUsage, $oid_sysCPU5MinUsage, $oid_sysMgmtCPU5SecUsage, + $oid_sysMgmtCPU1MinUsage, $oid_sysMgmtCPU5MinUsage], nothing_quit => 1); + + $self->{global} = { + usage_5s => defined($snmp_result->{$oid_sysCPU5SecUsage}) ? $snmp_result->{$oid_sysCPU5SecUsage} : $snmp_result->{$oid_sysMgmtCPU5SecUsage}, + usage_1m => defined($snmp_result->{$oid_sysCPU1MinUsage}) ? $snmp_result->{$oid_sysCPU1MinUsage} : $snmp_result->{$oid_sysMgmtCPU1MinUsage}, + usage_5m => defined($snmp_result->{$oid_sysCPU5MinUsage}) ? $snmp_result->{$oid_sysCPU5MinUsage} : $snmp_result->{$oid_sysMgmtCPU5MinUsage}, + }; +} + +1; + +__END__ + +=head1 MODE + +Check CPU usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='5m' + +=item B<--warning-*> + +Threshold warning. +Can be: '5s', '1m', '5m'. + +=item B<--critical-*> + +Threshold critical. +Can be: '5s', '1m', '5m'. + +=back + +=cut diff --git a/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm b/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm new file mode 100644 index 000000000..c15726f22 --- /dev/null +++ b/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm @@ -0,0 +1,133 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::kemp::snmp::mode::listvs; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + $self->{vs_id_selected} = []; + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my %map_state = ( + 1 => 'inService', + 2 => 'outOfService', + 4 => 'disabled', + 5 => 'sorry', + 6 => 'redirect', + 7 => 'errormsg', +); +my $mapping = { + vSname => { oid => '.1.3.6.1.4.1.12196.13.1.1.13' }, + vSstate => { oid => '.1.3.6.1.4.1.12196.13.1.1.14', map => \%map_state }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $mapping->{vSname}->{oid} }, { oid => $mapping->{vSstate}->{oid} } ], + nothing_quit => 1, return_type => 1); + foreach my $oid (keys %{$self->{results}}) { + next if ($oid !~ /^$mapping->{vSname}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vSname} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vSname} . "': no matching filter.", debug => 1); + next; + } + + push @{$self->{vs_id_selected}}, $instance; + } +} + +sub run { + my ($self, %options) = @_; + + $self->{snmp} = $options{snmp}; + $self->manage_selection(); + foreach my $instance (sort @{$self->{vs_id_selected}}) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + $self->{output}->output_add(long_msg => "'" . $result->{vSname} . "' [state = " . $result->{vSstate} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List Virtual Servers:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name', 'state']); +} + +sub disco_show { + my ($self, %options) = @_; + $self->{snmp} = $options{snmp}; + + $self->manage_selection(disco => 1); + foreach my $instance (sort @{$self->{vs_id_selected}}) { + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + + $self->{output}->add_disco_entry(name => $result->{vSname}, state => $result->{vSstate}); + } +} + +1; + +__END__ + +=head1 MODE + +List virtual servers. + +=over 8 + +=item B<--filter-name> + +Set the virtual server name. + +=back + +=cut + \ No newline at end of file diff --git a/centreon-plugins/network/zyxel/snmp/mode/memory.pm b/centreon-plugins/network/zyxel/snmp/mode/memory.pm new file mode 100644 index 000000000..5bfe7eb76 --- /dev/null +++ b/centreon-plugins/network/zyxel/snmp/mode/memory.pm @@ -0,0 +1,111 @@ +# +# Copyright 2017 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::zyxel::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 => 'mem-usage', set => { + key_values => [ { name => 'ram_used' } ], + output_template => 'Memory Used: %.2f%%', + perfdatas => [ + { label => 'memory_used', value => 'ram_used_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + { label => 'flash-usage', set => { + key_values => [ { name => 'flash_used' } ], + output_template => 'Flash Used: %.2f%%', + perfdatas => [ + { label => 'flash_used', value => 'flash_used_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_sysRAMUsage = '.1.3.6.1.4.1.890.1.6.22.1.2.0'; + my $oid_sysFLASHUsage = '.1.3.6.1.4.1.890.1.6.22.1.7.0'; + my $oid_sysMgmtMemUsage = '.1.3.6.1.4.1.890.1.15.3.2.5.0'; + my $oid_sysMgmtFlashUsage = '.1.3.6.1.4.1.890.1.15.3.2.6.0'; + my $snmp_result = $options{snmp}->get_leef(oids => [ + $oid_sysRAMUsage, $oid_sysFLASHUsage, + $oid_sysMgmtMemUsage, $oid_sysMgmtFlashUsage, + ], nothing_quit => 1); + + $self->{memory} = { + ram_used => defined($snmp_result->{$oid_sysRAMUsage}) ? $snmp_result->{$oid_sysRAMUsage} : $snmp_result->{$oid_sysMgmtMemUsage}, + flash_used => defined($snmp_result->{$oid_sysFLASHUsage}) ? $snmp_result->{$oid_sysFLASHUsage} : $snmp_result->{$oid_sysMgmtFlashUsage}, + }; +} + +1; + +__END__ + +=head1 MODE + +Check memory usage. + +=over 8 + +=item B<--warning-*> + +Threshold warning. +Can be: 'mem-usage' (%), 'flash-usage' (%). + +=item B<--critical-*> + +Threshold critical. +Can be: 'mem-usage' (%), 'flash-usage' (%). + + +=back + +=cut diff --git a/centreon-plugins/network/zyxel/snmp/mode/vpnstatus.pm b/centreon-plugins/network/zyxel/snmp/mode/vpnstatus.pm new file mode 100644 index 000000000..4671aef59 --- /dev/null +++ b/centreon-plugins/network/zyxel/snmp/mode/vpnstatus.pm @@ -0,0 +1,249 @@ +# +# Copyright 2017 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::zyxel::snmp::mode::vpnstatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = 'connection status : ' . $self->{result_values}->{connectstatus} . ' [activation status: ' . $self->{result_values}->{activestatus} . ']'; + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{activestatus} = $options{new_datas}->{$self->{instance} . '_activestatus'}; + $self->{result_values}->{connectstatus} = $options{new_datas}->{$self->{instance} . '_connectstatus'}; + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'vpn', type => 1, cb_prefix_output => 'prefix_vpn_output', message_multiple => 'All VPN tunnels are OK' }, + ]; + + $self->{maps_counters}->{vpn} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'activestatus' }, { name => 'connectstatus' }, { name => 'display' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + { label => 'traffic-in', set => { + key_values => [ { name => 'traffic_in', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic In: %s %s/s', + perfdatas => [ + { label => 'traffic_in', value => 'traffic_in_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'traffic_out', diff => 1 }, { name => 'display' } ], + per_second => 1, output_change_bytes => 2, + output_template => 'Traffic Out: %s %s/s', + perfdatas => [ + { label => 'traffic_out', value => 'traffic_out_per_second', template => '%.2f', + min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + } + ]; +} + +sub prefix_vpn_output { + my ($self, %options) = @_; + + return "VPN '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '' }, + "critical-status:s" => { name => 'critical_status', default => '%{connectstatus} eq "disconnected"' }, + }); + return $self; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(); + $instance_mode = $self; +} + +my %map_active_status = (0 => 'inactive', 1 => 'active'); +my %map_connect_status = (0 => 'disconnected', 1 => 'connected'); + +my $mapping = { + vpnStatusConnectionName => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.2' }, + vpnStatusActiveStatus => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.5', map => \%map_active_status }, + vpnStatusConnectStatus => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.6', map => \%map_connect_status }, +}; + +my $mapping2 = { + vpnSaMonitorConnectionName => { oid => '.1.3.6.1.4.1.890.1.6.22.2.6.1.2' }, + vpnSaMonitorInBytes => { oid => '.1.3.6.1.4.1.890.1.6.22.2.6.1.7' }, + vpnSaMonitorOutBytes => { oid => '.1.3.6.1.4.1.890.1.6.22.2.6.1.9' }, +}; + +my $oid_vpnStatusEntry = '.1.3.6.1.4.1.890.1.6.22.2.4.1'; +my $oid_vpnSaMonitorEntry = '.1.3.6.1.4.1.890.1.6.22.2.6.1'; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{cache_name} = "zyxel_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); + + $self->{vpn} = {}; + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ + { oid => $oid_vpnStatusEntry }, + { oid => $oid_vpnSaMonitorEntry }, + ], nothing_quit => 1); + + foreach my $oid (sort keys %{$snmp_result->{$oid_vpnStatusEntry}}) { + next if ($oid !~ /^$mapping->{vpnStatusConnectionName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_vpnStatusEntry}, instance => $instance); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $result->{vpnStatusConnectionName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vpnStatusConnectionName} . "': no matching filter.", debug => 1); + next; + } + + $self->{vpn}->{$result->{vpnStatusConnectionName}} = { + display => $result->{vpnStatusConnectionName}, + activestatus => $result->{vpnStatusActiveStatus}, + connectstatus => $result->{vpnStatusConnectStatus}, + }; + } + + foreach my $oid (sort keys %{$snmp_result->{$oid_vpnSaMonitorEntry}}) { + next if ($oid !~ /^$mapping2->{vpnSaMonitorConnectionName}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result->{$oid_vpnSaMonitorEntry}, instance => $instance); + next if (!defined($self->{vpn}->{$result->{vpnSaMonitorConnectionName}})); + + $self->{vpn}->{$result->{vpnSaMonitorConnectionName}}->{traffic_in} = $result->{vpnSaMonitorInBytes} * 8; + $self->{vpn}->{$result->{vpnSaMonitorConnectionName}}->{traffic_out} = $result->{vpnSaMonitorOutBytes} * 8; + } + + if (scalar(keys %{$self->{vpn}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No vpn found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check VPN state and traffic. + +=over 8 + +=item B<--filter-name> + +Filter vpn name with regexp. + +=item B<--warning-*> + +Threshold warning. +Can be: 'traffic-in', 'traffic-out'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'traffic-in', 'traffic-out'. + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{activestatus}, %{connectstatus}, %{display} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{connectstatus} eq "disconnected"'). +Can used special variables like: %{activestatus}, %{connectstatus}, %{display} + +=back + +=cut diff --git a/centreon-plugins/network/zyxel/snmp/plugin.pm b/centreon-plugins/network/zyxel/snmp/plugin.pm new file mode 100644 index 000000000..11acf60d9 --- /dev/null +++ b/centreon-plugins/network/zyxel/snmp/plugin.pm @@ -0,0 +1,53 @@ +# +# Copyright 2017 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::zyxel::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cpu' => 'network::zyxel::snmp::mode::cpu', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'list-vpn' => 'snmp_standard::mode::listvpn', + 'memory' => 'network::zyxel::snmp::mode::memory', + 'vpn-status' => 'network::zyxel::snmp::mode::vpnstatus', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Zyxel equipments in SNMP. + +=cut From 12ed053899300aa0d44d6521aa7876950c54ac54 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 15:41:07 +0100 Subject: [PATCH 13/45] prepare release --- centreon-plugins/centreon/plugins/script.pm | 2 +- centreon-plugins/changelog | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/centreon-plugins/centreon/plugins/script.pm b/centreon-plugins/centreon/plugins/script.pm index f652738d0..62492a571 100644 --- a/centreon-plugins/centreon/plugins/script.pm +++ b/centreon-plugins/centreon/plugins/script.pm @@ -30,7 +30,7 @@ use Pod::Find qw(pod_where); my %handlers = (DIE => {}); -my $global_version = 20171013; +my $global_version = 20171123; my $alternative_fatpacker = 0; sub new { diff --git a/centreon-plugins/changelog b/centreon-plugins/changelog index d3f82b033..1171c6209 100644 --- a/centreon-plugins/changelog +++ b/centreon-plugins/changelog @@ -1,3 +1,9 @@ +2017-11-23 Quentin Garnier + * Plugin added: Freebox Rest API + * Plugin added: Netgear Mseries SNMP + * Plugin added: Zyxel SNMP + * Add redis support for temporary datas + 2017-10-13 Quentin Garnier * Plugin added: Kaminario Rest API * Plugin added: Protocol SSH From 41b68ebddf7be2b6e34f88736050ecd44891ee8a Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 16:20:31 +0100 Subject: [PATCH 14/45] zyxel plugin add list vpn --- .../network/zyxel/snmp/mode/listvpn.pm | 75 +++++++++---------- centreon-plugins/network/zyxel/snmp/plugin.pm | 2 +- 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm b/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm index c15726f22..2b9323f09 100644 --- a/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm +++ b/centreon-plugins/network/zyxel/snmp/mode/listvpn.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::kemp::snmp::mode::listvs; +package network::zyxel::snmp::mode::listvpn; use base qw(centreon::plugins::mode); @@ -35,8 +35,7 @@ sub new { { "filter-name:s" => { name => 'filter_name' }, }); - $self->{vs_id_selected} = []; - + $self->{vpn} = {}; return $self; } @@ -45,52 +44,53 @@ sub check_options { $self->SUPER::init(%options); } -my %map_state = ( - 1 => 'inService', - 2 => 'outOfService', - 4 => 'disabled', - 5 => 'sorry', - 6 => 'redirect', - 7 => 'errormsg', -); +my %map_active_status = (0 => 'inactive', 1 => 'active'); +my %map_connect_status = (0 => 'disconnected', 1 => 'connected'); + my $mapping = { - vSname => { oid => '.1.3.6.1.4.1.12196.13.1.1.13' }, - vSstate => { oid => '.1.3.6.1.4.1.12196.13.1.1.14', map => \%map_state }, + vpnStatusConnectionName => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.2' }, + vpnStatusActiveStatus => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.5', map => \%map_active_status }, + vpnStatusConnectStatus => { oid => '.1.3.6.1.4.1.890.1.6.22.2.4.1.6', map => \%map_connect_status }, }; +my $oid_vpnStatusEntry = '.1.3.6.1.4.1.890.1.6.22.2.4.1'; + sub manage_selection { my ($self, %options) = @_; - $self->{results} = $self->{snmp}->get_multiple_table(oids => [ { oid => $mapping->{vSname}->{oid} }, { oid => $mapping->{vSstate}->{oid} } ], - nothing_quit => 1, return_type => 1); - foreach my $oid (keys %{$self->{results}}) { - next if ($oid !~ /^$mapping->{vSname}->{oid}\.(.*)$/); + my $snmp_result = $options{snmp}->get_table(oid => $oid_vpnStatusEntry, nothing_quit => 1); + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping->{vpnStatusConnectionName}->{oid}\.(.*)$/); my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); + my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance); if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $result->{vSname} !~ /$self->{option_results}->{filter_name}/) { - $self->{output}->output_add(long_msg => "skipping '" . $result->{vSname} . "': no matching filter.", debug => 1); + $result->{vpnStatusConnectionName} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $result->{vpnStatusConnectionName} . "': no matching filter.", debug => 1); next; } - push @{$self->{vs_id_selected}}, $instance; + $self->{vpn}->{$result->{vpnStatusConnectionName}} = { + name => $result->{vpnStatusConnectionName}, + active_status => $result->{vpnStatusActiveStatus}, + connect_status => $result->{vpnStatusConnectStatus}, + }; } } sub run { my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - $self->manage_selection(); - foreach my $instance (sort @{$self->{vs_id_selected}}) { - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); - - $self->{output}->output_add(long_msg => "'" . $result->{vSname} . "' [state = " . $result->{vSstate} . "]"); + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{vpn}}) { + $self->{output}->output_add(long_msg => '[name = ' . $self->{vpn}->{$instance}->{name} . "]" . + " [active status = '" . $self->{vpn}->{$instance}->{active_status} . "']" . + " [connect status = '" . $self->{vpn}->{$instance}->{connect_status} . "']" + ); } $self->{output}->output_add(severity => 'OK', - short_msg => 'List Virtual Servers:'); + short_msg => 'List VPNs:'); $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); $self->{output}->exit(); } @@ -98,18 +98,17 @@ sub run { sub disco_format { my ($self, %options) = @_; - $self->{output}->add_disco_format(elements => ['name', 'state']); + $self->{output}->add_disco_format(elements => ['name', 'active_status', 'connect_status']); } sub disco_show { my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - $self->manage_selection(disco => 1); - foreach my $instance (sort @{$self->{vs_id_selected}}) { - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}, instance => $instance); - - $self->{output}->add_disco_entry(name => $result->{vSname}, state => $result->{vSstate}); + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{vpn}}) { + $self->{output}->add_disco_entry( + %{$self->{vpn}->{$instance}} + ); } } @@ -119,15 +118,15 @@ __END__ =head1 MODE -List virtual servers. +List VPNs. =over 8 =item B<--filter-name> -Set the virtual server name. +Filter by VPN name. =back =cut - \ No newline at end of file + diff --git a/centreon-plugins/network/zyxel/snmp/plugin.pm b/centreon-plugins/network/zyxel/snmp/plugin.pm index 11acf60d9..bc3358807 100644 --- a/centreon-plugins/network/zyxel/snmp/plugin.pm +++ b/centreon-plugins/network/zyxel/snmp/plugin.pm @@ -34,7 +34,7 @@ sub new { 'cpu' => 'network::zyxel::snmp::mode::cpu', 'interfaces' => 'snmp_standard::mode::interfaces', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', - 'list-vpn' => 'snmp_standard::mode::listvpn', + 'list-vpn' => 'network::zyxel::snmp::mode::listvpn', 'memory' => 'network::zyxel::snmp::mode::memory', 'vpn-status' => 'network::zyxel::snmp::mode::vpnstatus', ); From 9fa24f06ac490658e7c89c937c0db77aa0960ba5 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 23 Nov 2017 16:58:37 +0100 Subject: [PATCH 15/45] fix help --- centreon-plugins/os/windows/local/mode/sessions.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/os/windows/local/mode/sessions.pm b/centreon-plugins/os/windows/local/mode/sessions.pm index a9d87dd29..e9b0d573e 100644 --- a/centreon-plugins/os/windows/local/mode/sessions.pm +++ b/centreon-plugins/os/windows/local/mode/sessions.pm @@ -285,12 +285,14 @@ Filter session name (can be a regexp). =item B<--warning-*> Threshold warning. -Can be: 'inactive', 'active'. +Can be: 'sessions-created', 'sessions-disconnected', +'sessions-reconnected', 'sessions-active'. =item B<--critical-*> Threshold critical. -Can be: 'inactive', 'active', 'time' (in seconds since the session starts). +Can be: 'sessions-created', 'sessions-disconnected', +'sessions-reconnected', 'sessions-active'. =back From 25f8fbfea071fa23fe3f16d9794f5cedd16d04ed Mon Sep 17 00:00:00 2001 From: qgarnier Date: Fri, 24 Nov 2017 14:24:56 +0100 Subject: [PATCH 16/45] Ref #805 --- .../apps/voip/asterisk/ami/custom/api.pm | 278 ++++++++++++++++++ .../voip/asterisk/ami/mode/channelusage.pm | 132 +++++++++ .../voip/asterisk/ami/mode/dahdistatus.pm | 192 ++++++++++++ .../voip/asterisk/ami/mode/sippeersusage.pm | 252 ++++++++++++++++ .../voip/asterisk/{remote => ami}/plugin.pm | 20 +- .../apps/voip/asterisk/remote/lib/ami.pm | 103 ------- .../voip/asterisk/remote/mode/activecalls.pm | 223 -------------- .../voip/asterisk/remote/mode/dahdistatus.pm | 230 --------------- .../asterisk/remote/mode/externalcalls.pm | 213 -------------- .../voip/asterisk/remote/mode/showpeers.pm | 277 ----------------- .../remote-script/asterisk_centreon.conf | 1 - .../remote-script/asterisk_sendcommand.pm | 114 ------- 12 files changed, 863 insertions(+), 1172 deletions(-) create mode 100644 centreon-plugins/apps/voip/asterisk/ami/custom/api.pm create mode 100644 centreon-plugins/apps/voip/asterisk/ami/mode/channelusage.pm create mode 100644 centreon-plugins/apps/voip/asterisk/ami/mode/dahdistatus.pm create mode 100644 centreon-plugins/apps/voip/asterisk/ami/mode/sippeersusage.pm rename centreon-plugins/apps/voip/asterisk/{remote => ami}/plugin.pm (63%) delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/lib/ami.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/mode/activecalls.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/mode/dahdistatus.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/mode/externalcalls.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/mode/showpeers.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_centreon.conf delete mode 100755 centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_sendcommand.pm diff --git a/centreon-plugins/apps/voip/asterisk/ami/custom/api.pm b/centreon-plugins/apps/voip/asterisk/ami/custom/api.pm new file mode 100644 index 000000000..0db61b7e2 --- /dev/null +++ b/centreon-plugins/apps/voip/asterisk/ami/custom/api.pm @@ -0,0 +1,278 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::voip::asterisk::ami::custom::api; + +use strict; +use warnings; +use IO::Socket::INET; +use IO::Select; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "ami-hostname:s@" => { name => 'ami_hostname' }, + "ami-port:s@" => { name => 'ami_port' }, + "ami-username:s@" => { name => 'ami_username' }, + "ami-password:s@" => { name => 'ami_password' }, + "timeout:s@" => { name => 'timeout' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + $self->{cnx_ami} = undef; + + return $self; + +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults { + my ($self, %options) = @_; + + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{ami_hostname} = (defined($self->{option_results}->{ami_hostname})) ? shift(@{$self->{option_results}->{ami_hostname}}) : undef; + $self->{ami_username} = (defined($self->{option_results}->{ami_username})) ? shift(@{$self->{option_results}->{ami_username}}) : undef; + $self->{ami_password} = (defined($self->{option_results}->{ami_password})) ? shift(@{$self->{option_results}->{ami_password}}) : undef; + $self->{ami_port} = (defined($self->{option_results}->{ami_port})) ? shift(@{$self->{option_results}->{ami_port}}) : 5038; + $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; + + if (!defined($self->{ami_hostname})) { + $self->{output}->add_option_msg(short_msg => "Need to specify --ami-hostname option."); + $self->{output}->option_exit(); + } + if (!defined($self->{ami_username})) { + $self->{output}->add_option_msg(short_msg => "Need to specify --ami-username option."); + $self->{output}->option_exit(); + } + if (!defined($self->{ami_password})) { + $self->{output}->add_option_msg(short_msg => "Need to specify --ami-password option."); + $self->{output}->option_exit(); + } + + if (!defined($self->{ami_hostname}) || + scalar(@{$self->{option_results}->{ami_hostname}}) == 0) { + return 0; + } + + return 1; +} + +sub get_connect_info { + my ($self, %options) = @_; + + return $self->{ami_hostname} . '_' . $self->{ami_port}; +} + +sub read_ami_protocol_end { + my ($self, %options) = @_; + + if (defined($options{response})) { + if ($options{response} eq 'Follows') { + return 1 if ($options{message} =~ /^--END COMMAND--/ms); + } else { + return 1 if ($options{message} =~ /^Message: (.*)(\r\n)/ms); + } + } + + return 0; +} + +sub read_ami_protocol { + my ($self, %options) = @_; + + my $select = IO::Select->new($self->{cnx_ami}); + # Two types of message: + # Response: Error + # Message: Authentication failed + # + # Response: Follows + # ... + # --END COMMAND-- + + my ($response, $read_msg); + my $message = ''; + while (1) { + if (!$select->can_read(10)) { + $response = 'Timeout'; + last; + } + + my $status = $self->{cnx_ami}->recv($read_msg, 4096); + if (!defined($response)) { + next if ($read_msg !~ /^Response: (.*?)(?:\r\n|\n)(.*)/ms); + ($response, $message) = ($1, $2); + } else { + $message .= $read_msg; + } + + last if ($self->read_ami_protocol_end(response => $response, message => $message)); + } + + $message =~ s/\r//msg; + if ($response !~ /Success|Follows/) { + $message =~ s/\n+$//msg; + $message =~ s/\n/ -- /msg; + $self->{output}->add_option_msg(short_msg => "Communication issue [" . $message . "]"); + $self->{output}->option_exit(); + } + + $self->{output}->output_add(long_msg => $message, debug => 1); + return $message; +} + +sub write_ami_protocol { + my ($self, %options) = @_; + + $self->{cnx_ami}->send($options{cmd}); +} + +sub login { + my ($self, %options) = @_; + + $self->write_ami_protocol(cmd => "Action:login +Username:$self->{ami_username} +Secret:$self->{ami_password} +Events: off + +"); + # don't need to get it. If it comes, it's success :) + $self->read_ami_protocol(); +} + +sub connect { + my ($self, %options) = @_; + + $self->{cnx_ami} = IO::Socket::INET->new( + PeerAddr => $self->{ami_hostname}, + PeerPort => $self->{ami_port}, + Proto => 'tcp', + Timeout => $self->{timeout}, + ); + if (!defined($self->{cnx_ami})) { + $self->{output}->add_option_msg(short_msg => "Can't bind : $@"); + $self->{output}->option_exit(); + } + + $self->{cnx_ami}->autoflush(1); + $self->login(); +} + +sub command { + my ($self, %options) = @_; + + if (!defined($self->{cnx_ami})) { + $self->connect(); + } + + $self->write_ami_protocol(cmd => "Action:command +Command:$options{cmd} + +"); + return $self->read_ami_protocol(); +} + +sub DESTROY { + my $self = shift; + + if (defined($self->{cnx_ami})) { + $self->{cnx_ami}->close(); + } +} + +1; + +__END__ + +=head1 NAME + +Asterisk AMI + +=head1 SYNOPSIS + +Asterisk AMI custom mode + +=head1 AMI API OPTIONS + +=over 8 + +=item B<--ami-hostname> + +AMI hostname (Required). + +=item B<--ami-port> + +AMI port (Default: 5038). + +=item B<--ami-username> + +AMI username. + +=item B<--ami-password> + +AMI password. + +=item B<--timeout> + +Set TCP timeout + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/apps/voip/asterisk/ami/mode/channelusage.pm b/centreon-plugins/apps/voip/asterisk/ami/mode/channelusage.pm new file mode 100644 index 000000000..e3f2b4e2a --- /dev/null +++ b/centreon-plugins/apps/voip/asterisk/ami/mode/channelusage.pm @@ -0,0 +1,132 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::voip::asterisk::ami::mode::channelusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'channels-active', set => { + key_values => [ { name => 'channels_active' } ], + output_template => 'Channels Active: %s', + perfdatas => [ + { label => 'channels_active', value => 'channels_active_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'calls-active', set => { + key_values => [ { name => 'calls_active' } ], + output_template => 'Calls Active: %s', + perfdatas => [ + { label => 'calls_active', value => 'calls_active_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'extcalls-active', set => { + key_values => [ { name => 'extcalls_active' } ], + output_template => 'External Calls Active: %s', + perfdatas => [ + { label => 'extcalls_active', value => 'extcalls_active_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'calls-count', set => { + key_values => [ { name => 'calls_count', diff => 1 } ], + output_template => 'Calls Count: %s', + perfdatas => [ + { label => 'calls_count', value => 'calls_count_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $result = $options{custom}->command(cmd => 'core show channels'); + $self->{global} = { channels_active => 0, calls_active => 0, + calls_count => undef, extcalls_active => 0 }; + + $self->{global}->{channels_active} = $1 + if ($result =~ /^(\d+)\s+active\s+channels/ms); + $self->{global}->{calls_active} = $1 + if ($result =~ /^(\d+)\s+active\s+calls/ms); + $self->{global}->{calls_count} = $1 + if ($result =~ /^(\d+)\s+calls\s+processed/ms); + + my $count = 0; + $count++ while ($result =~ /Outgoing\s+Line/msig); + $self->{global}->{extcalls_active} = $count; + + $self->{cache_name} = "asterisk_" . '_' . $self->{mode} . '_' . $options{custom}->get_connect_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check channel usage: active calls, external calls. + +=over 8 + +=item B<--warning-*> + +Threshold warning. +Can be: 'channels-active', 'calls-active', 'extcalls-active', +'calls-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'channels-active', 'calls-active', 'extcalls-active', +'calls-count'. + +=back + +=cut diff --git a/centreon-plugins/apps/voip/asterisk/ami/mode/dahdistatus.pm b/centreon-plugins/apps/voip/asterisk/ami/mode/dahdistatus.pm new file mode 100644 index 000000000..9c48d8ae8 --- /dev/null +++ b/centreon-plugins/apps/voip/asterisk/ami/mode/dahdistatus.pm @@ -0,0 +1,192 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::voip::asterisk::ami::mode::dahdistatus; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + my $label = $self->{label}; + $label =~ s/-/_/g; + if (defined($instance_mode->{option_results}->{'critical_' . $label}) && $instance_mode->{option_results}->{'critical_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'critical_' . $label}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{'warning_' . $label}) && $instance_mode->{option_results}->{'warning_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'warning_' . $label}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf('status : %s', $self->{result_values}->{status}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{description} = $options{new_datas}->{$self->{instance} . '_description'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'dahdi', type => 1, cb_prefix_output => 'prefix_dahdi_output', message_multiple => 'All dahdi lines are ok' }, + ]; + + $self->{maps_counters}->{dahdi} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'description' }, { name => 'status' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-description:s" => { name => 'filter_description' }, + "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /UNCONFIGURED|YEL|BLU/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /RED/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_dahdi_output { + my ($self, %options) = @_; + + return "Line '" . $options{instance_value}->{description} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + # Status can be: OK, UNCONFIGURED, BLU, YEL, RED, REC (recover), NOP (notopen), UUU + + #Description Alarms IRQ bpviol CRC4 + #Wildcard TDM410P Board 1 OK 0 0 0 + #Wildcard TDM800P Board 2 OK 0 0 0 + + #Description Alarms IRQ bpviol CRC Fra Codi Options LBO + #Wildcard TE131/TE133 Card 0 BLU/RED 0 0 0 CCS HDB3 0 db (CSU)/0-133 feet (DSX-1) + my $result = $options{custom}->command(cmd => 'dahdi show status'); + + $self->{dahdi} = {}; + foreach my $line (split /\n/, $result) { + if ($line =~ /^(.*?)\s+((?:OK|UNCONFIGURED|BLU|YEL|RED|REC|NOP|UUU)[^\s]*)\s+/msg) { + my ($description, $status) = ($1, $2); + if (defined($self->{option_results}->{filter_description}) && $self->{option_results}->{filter_description} ne '' && + $description !~ /$self->{option_results}->{filter_description}/) { + $self->{output}->output_add(long_msg => "skipping '" . $description . "': no matching filter.", debug => 1); + next; + } + + $self->{dahdi}->{$description} = { + description => $description, + status => $status, + }; + } + } + + if (scalar(keys %{$self->{dahdi}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No dahdi lines found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check status of dahdi lines. + +=over 8 + +=item B<--filter-description> + +Filter dahdi description (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{status} =~ /UNCONFIGURED|YEL|BLU/i'). +Can used special variables like: %{description}, %{status} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} =~ /RED/i'). +Can used special variables like: %{description}, %{status} + +=back + +=cut diff --git a/centreon-plugins/apps/voip/asterisk/ami/mode/sippeersusage.pm b/centreon-plugins/apps/voip/asterisk/ami/mode/sippeersusage.pm new file mode 100644 index 000000000..c926ceeb3 --- /dev/null +++ b/centreon-plugins/apps/voip/asterisk/ami/mode/sippeersusage.pm @@ -0,0 +1,252 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::voip::asterisk::ami::mode::sippeersusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $instance_mode; + +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + my $label = $self->{label}; + $label =~ s/-/_/g; + if (defined($instance_mode->{option_results}->{'critical_' . $label}) && $instance_mode->{option_results}->{'critical_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'critical_' . $label}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{'warning_' . $label}) && $instance_mode->{option_results}->{'warning_' . $label} ne '' && + eval "$instance_mode->{option_results}->{'warning_' . $label}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf('status : %s', $self->{result_values}->{status}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_name'}; + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + { name => 'sip', type => 1, cb_prefix_output => 'prefix_sip_output', message_multiple => 'All SIP peers are ok' }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total-peers', set => { + key_values => [ { name => 'total_peers' } ], + output_template => 'Total Peers: %s', + perfdatas => [ + { label => 'total_peers', value => 'total_peers_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'monitor-online-peers', set => { + key_values => [ { name => 'monitor_online_peers' } ], + output_template => 'Monitor Online Peers: %s', + perfdatas => [ + { label => 'monitor_online_peers', value => 'monitor_online_peers_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'monitor-offline-peers', set => { + key_values => [ { name => 'monitor_offline_peers' } ], + output_template => 'Monitor Offline Peers: %s', + perfdatas => [ + { label => 'monitor_offline_peers', value => 'monitor_offline_peers_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'unmonitor-online-peers', set => { + key_values => [ { name => 'unmonitor_online_peers' } ], + output_template => 'Unmonitor Online Peers: %s', + perfdatas => [ + { label => 'unmonitor_online_peers', value => 'unmonitor_online_peers_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'unmonitor-offline-peers', set => { + key_values => [ { name => 'unmonitor_offline_peers' } ], + output_template => 'Unmonitor Offline Peers: %s', + perfdatas => [ + { label => 'unmonitor_offline_peers', value => 'unmonitor_offline_peers_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; + $self->{maps_counters}->{sip} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'name' }, { name => 'status' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + "warning-status:s" => { name => 'warning_status', default => '%{status} =~ /LAGGED|UNKNOWN/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{status} =~ /UNREACHABLE/i' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); +} + +sub prefix_sip_output { + my ($self, %options) = @_; + + return "Peer '" . $options{instance_value}->{name} . "' "; +} + +sub change_macros { + my ($self, %options) = @_; + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + + # Status can be: UNREACHABLE, LAGGED (%d ms), OK (%d ms), UNKNOWN, Unmonitored + + #Name/username Host Dyn Forcerport Comedia ACL Port Status Description + #02l44k/02l44k 10.9.0.61 D No No 5060 Unmonitored + #0rafkw/0rafkw 10.9.0.28 D No No 5060 Unmonitored + #... + #55 sip peers [Monitored: 0 online, 0 offline Unmonitored: 43 online, 12 offline] + my $result = $options{custom}->command(cmd => 'sip show peers'); + + $self->{sip} = {}; + foreach my $line (split /\n/, $result) { + if ($line =~ /^(.*?)\s+.*(UNREACHABLE|LAGGED|OK|UNKNOWN|Unmonitored)\s/msg) { + my ($name, $status) = ($1, $2); + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{sip}->{$name} = { + name => $name, + status => $status, + }; + } + } + + $self->{global} = { + total_peers => $1, + monitor_online_peers => $2, monitor_offline_peers => $3, + unmonitor_online_peers => $4, unmonitor_offline_peers => $5, + } if ($result =~ /(\d+) sip peers \[Monitored: (\d+) online, (\d+) offline Unmonitored: (\d+) online, (\d+) offline]/msi); + + if (scalar(keys %{$self->{sip}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No sip peers found."); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check SIP peers usage. + +=over 8 + +=item B<--filter-name> + +Filter sip peer name (can be a regexp). + +=item B<--warning-status> + +Set warning threshold for status (Default: '%{status} =~ /LAGGED|UNKNOWN/i'). +Can used special variables like: %{name}, %{status} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} =~ /UNREACHABLE/i'). +Can used special variables like: %{name}, %{status} + +=item B<--warning-*> + +Threshold warning. +Can be: 'total-peers', 'monitor-online-peers', 'monitor-offline-peers', +'unmonitor-online-peers', 'unmonitor-offline-peers'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'total-peers', 'monitor-online-peers', 'monitor-offline-peers', +'unmonitor-online-peers', 'unmonitor-offline-peers'. + +=back + +=cut diff --git a/centreon-plugins/apps/voip/asterisk/remote/plugin.pm b/centreon-plugins/apps/voip/asterisk/ami/plugin.pm similarity index 63% rename from centreon-plugins/apps/voip/asterisk/remote/plugin.pm rename to centreon-plugins/apps/voip/asterisk/ami/plugin.pm index 40a94a11a..543256fa8 100644 --- a/centreon-plugins/apps/voip/asterisk/remote/plugin.pm +++ b/centreon-plugins/apps/voip/asterisk/ami/plugin.pm @@ -18,36 +18,34 @@ # limitations under the License. # -package apps::voip::asterisk::remote::plugin; +package apps::voip::asterisk::ami::plugin; use strict; use warnings; -use base qw(centreon::plugins::script_simple); +use base qw(centreon::plugins::script_custom); sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); bless $self, $class; - $self->{version} = '1.1'; + $self->{version} = '1.0'; %{$self->{modes}} = ( - 'showpeers' => 'apps::voip::asterisk::remote::mode::showpeers', - 'dahdistatus' => 'apps::voip::asterisk::remote::mode::dahdistatus', - 'activecalls' => 'apps::voip::asterisk::remote::mode::activecalls', - 'externalcalls' => 'apps::voip::asterisk::remote::mode::externalcalls', - ); + 'channel-usage' => 'apps::voip::asterisk::ami::mode::channelusage', + 'dahdi-status' => 'apps::voip::asterisk::ami::mode::dahdistatus', + 'sip-peers-usage' => 'apps::voip::asterisk::ami::mode::sippeersusage', + ); + $self->{custom_modes}{api} = 'apps::voip::asterisk::ami::custom::api'; return $self; } - 1; __END__ =head1 PLUGIN DESCRIPTION -Check Asterisk through AMI interface (AMI socket; telnet perl module required) +Check Asterisk through AMI interface. =cut diff --git a/centreon-plugins/apps/voip/asterisk/remote/lib/ami.pm b/centreon-plugins/apps/voip/asterisk/remote/lib/ami.pm deleted file mode 100644 index afc346116..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/lib/ami.pm +++ /dev/null @@ -1,103 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::remote::lib::ami; - -use strict; -use warnings; -use Net::Telnet; - -my $ami_handle; -my $line; -my @lines; -my @result; - -sub quit { - $ami_handle->print("Action: logoff"); - $ami_handle->print(""); - $ami_handle->close(); -} - -sub connect { - my ($self, %options) = @_; - - my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown'; - - $ami_handle = new Net::Telnet (Telnetmode => 0, - Timeout => $self->{option_results}->{timeout}, - Errmode => 'return', - ); - - $ami_handle->open(Host => $self->{option_results}->{hostname}, - Port => $self->{option_results}->{port}, - ); - - if ($ami_handle->errmsg) { - $self->{output}->output_add(severity => $connection_exit, - short_msg => 'Unable to connect to AMI: ' . $ami_handle->errmsg); - $self->{output}->display(); - $self->{output}->exit(); - } - - # Check connection message. - $line = $ami_handle->getline; - if ($line !~ /^Asterisk/) { - $self->{output}->output_add(severity => $connection_exit, - short_msg => 'Unable to connect to AMI: ' . $line); - $self->{output}->display(); - $self->{output}->exit(); - } - - # Authentication. - $ami_handle->print("Action: login"); - $ami_handle->print("Username: $self->{option_results}->{username}"); - $ami_handle->print("Secret: $self->{option_results}->{password}"); - $ami_handle->print("Events: off"); - $ami_handle->print(""); - - # Check authentication message (second message). - $line = $ami_handle->getline; - $line = $ami_handle->getline; - if ($line !~ /^Message: Authentication accepted/) { - $self->{output}->output_add(severity => $connection_exit, - short_msg => 'Unable to connect to AMI: ' . $line); - $self->{output}->display(); - $self->{output}->exit(); - } - -} - -sub action { - my ($self) = @_; - - $ami_handle->print("Action: command"); - $ami_handle->print("Command: $self->{asterisk_command}"); - $ami_handle->print(""); - - - my @return; - while (my $line = $ami_handle->getline(Timeout => 1)) { - push(@return,$line); - next if ($line !~ /END COMMAND/o); - } - return @return; -} - -1; diff --git a/centreon-plugins/apps/voip/asterisk/remote/mode/activecalls.pm b/centreon-plugins/apps/voip/asterisk/remote/mode/activecalls.pm deleted file mode 100644 index 9fc86dece..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/mode/activecalls.pm +++ /dev/null @@ -1,223 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::remote::mode::activecalls; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::misc; -use apps::voip::asterisk::remote::lib::ami; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '0.2'; - - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', default => 5038 }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "remote:s" => { name => 'remote', default => 'ssh' }, - "ssh-option:s@" => { name => 'ssh_option' }, - "ssh-path:s" => { name => 'ssh_path' }, - "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, - "timeout:s" => { name => 'timeout', default => 30 }, - "command:s" => { name => 'command', default => 'asterisk_sendcommand.pm' }, - "command-path:s" => { name => 'command_path', default => '/home/centreon/bin' }, - "protocol:s" => { name => 'protocol', }, - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); - $self->{result} = {}; - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (!defined($self->{option_results}->{hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); - $self->{output}->option_exit(); - } - - if ($self->{option_results}->{remote} eq 'ami') - { - if (!defined($self->{option_results}->{username})) { - $self->{output}->add_option_msg(short_msg => "Please set the --username option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{password})) { - $self->{output}->add_option_msg(short_msg => "Please set the --password option"); - $self->{output}->option_exit(); - } - } - - if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); - } -} - -sub manage_selection { - my ($self, %options) = @_; - my @result; - - $self->{asterisk_command} = 'core show channels'; - - if ($self->{option_results}->{remote} eq 'ami') - { - apps::voip::asterisk::remote::lib::ami::connect($self); - @result = apps::voip::asterisk::remote::lib::ami::action($self); - apps::voip::asterisk::remote::lib::ami::quit(); - } - else - { - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => "'".$self->{asterisk_command}."'", - ); - @result = split /\n/, $stdout; - } - - # Compute data - foreach my $line (@result) { - if ($line =~ /^(\d*) active call/) - { - $self->{result}->{activecalls} = {value => $1, status => '1'}; - } - elsif ($line =~ /^Unable to connect .*/) - { - $self->{result}->{activecalls} = {value => $line, status => '0'}; - } - } -} - -sub run { - my ($self, %options) = @_; - - my $msg; - my $old_status = 'ok'; - - $self->manage_selection(); - - # Send formated data to Centreon - if ($self->{result}->{activecalls}->{status} eq '0') - { - $self->{output}->output_add(severity => $self->{result}->{activecalls}->{status}, - short_msg => $self->{result}->{activecalls}->{value}); - $self->{output}->display(); - $self->{output}->exit(); - } - my $exit_code = $self->{perfdata}->threshold_check(value => $self->{result}->{activecalls}->{value}, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->perfdata_add(label => 'Active Calls', - value => $self->{result}->{activecalls}->{value}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Current active calls: %s", $self->{result}->{activecalls}->{value}) - ); - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Show number of current active calls - -=over 8 - -=item B<--warning> - -Threshold warning. - -=item B<--critical> - -Threshold critical. - -=item B<--remote> - -Execute command remotely; can be 'ami' or 'ssh' (default: ssh). - -=item B<--hostname> - -Hostname to query (need --remote option). - -=item B<--port> - -AMI remote port (default: 5038). - -=item B<--username> - -AMI username. - -=item B<--password> - -AMI password. - -=item B<--ssh-option> - -Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). - -=item B<--ssh-path> - -Specify ssh command path (default: none) - -=item B<--ssh-command> - -Specify ssh command (default: 'ssh'). Useful to use 'plink'. - -=item B<--timeout> - -Timeout in seconds for the command (Default: 30). - -=item B<--command> - -Command to get information (Default: 'asterisk_sendcommand.pm'). -Can be changed if you have output in a file. - -=item B<--command-path> - -Command path (Default: /home/centreon/bin). - -=back - -=cut diff --git a/centreon-plugins/apps/voip/asterisk/remote/mode/dahdistatus.pm b/centreon-plugins/apps/voip/asterisk/remote/mode/dahdistatus.pm deleted file mode 100644 index 027b5b886..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/mode/dahdistatus.pm +++ /dev/null @@ -1,230 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::remote::mode::dahdistatus; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::misc; -use apps::voip::asterisk::remote::lib::ami; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', default => 5038 }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "remote:s" => { name => 'remote', default => 'ssh' }, - "ssh-option:s@" => { name => 'ssh_option' }, - "ssh-path:s" => { name => 'ssh_path' }, - "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, - "timeout:s" => { name => 'timeout', default => 30 }, - "command:s" => { name => 'command', default => 'asterisk_sendcommand.pm' }, - "command-path:s" => { name => 'command_path', default => '/home/centreon/bin' }, - "filter-name:s" => { name => 'filter_name', }, - }); - $self->{result} = {}; - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (!defined($self->{option_results}->{hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); - $self->{output}->option_exit(); - } - - if ($self->{option_results}->{remote} eq 'ami') - { - if (!defined($self->{option_results}->{username})) { - $self->{output}->add_option_msg(short_msg => "Please set the --username option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{password})) { - $self->{output}->add_option_msg(short_msg => "Please set the --password option"); - $self->{output}->option_exit(); - } - } -} - -sub manage_selection { - my ($self, %options) = @_; - my @result; - - $self->{asterisk_command} = 'dahdi show status'; - - if ($self->{option_results}->{remote} eq 'ami') - { - apps::voip::asterisk::remote::lib::ami::connect($self); - @result = apps::voip::asterisk::remote::lib::ami::action($self); - apps::voip::asterisk::remote::lib::ami::quit(); - } - else - { - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => "'".$self->{asterisk_command}."'", - ); - @result = split /\n/, $stdout; - } - - # Compute data - foreach my $line (@result) { - if ($line =~ /^Description /) - { - next; - } - if ($line =~ /^(.{41})(\w*).*/) - { - my $status; - my ($trunkname, $trunkstatus) = ($1, $2); - $trunkname =~ s/^\s+|\s+$//g; - if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $trunkname !~ /$self->{option_results}->{filter_name}/) - { - $self->{output}->output_add(long_msg => "Skipping trunk '" . $trunkname . "': no matching filter name"); - next; - } - if ($trunkstatus eq 'Red' | $trunkstatus eq 'Yel' | $trunkstatus eq 'Blu') - { - $status = 'CRITICAL'; - } - elsif ($trunkstatus eq 'Unconfi') - { - $status = 'WARNING'; - } - $self->{result}->{$trunkname} = {name => $trunkname, status => $status, realstatus => $trunkstatus}; - } - elsif ($line =~ /^Unable to connect .*/) - { - $self->{result}->{$line} = {name => $line, status => 'CRITICAL'}; - } - } -} - -sub run { - my ($self, %options) = @_; - - my $msg; - my $old_status = 'ok'; - - $self->manage_selection(); - - # Send formated data to Centreon - if (scalar keys %{$self->{result}} >= 1) - { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Everything is OK'); - } - else - { - $self->{output}->output_add(severity => 'Unknown', - short_msg => 'Nothing to be monitored'); - } - - foreach my $name (sort(keys %{$self->{result}})) { - if (!$self->{output}->is_status(value => $self->{result}->{$name}->{status}, compare => 'ok', litteral => 1)) - { - $msg = sprintf("Trunk: %s", $self->{result}->{$name}->{name}); - $self->{output}->output_add(severity => $self->{result}->{$name}->{status}, - short_msg => $msg); - } - $self->{output}->output_add(long_msg => sprintf("%s : %s", $self->{result}->{$name}->{name}, $self->{result}->{$name}->{realstatus})); - } - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Show status of dahdi lines. - -=over 8 - -=item B<--remote> - -Execute command remotely; can be 'ami' or 'ssh' (default: ssh). - -=item B<--hostname> - -Hostname to query (need --remote option). - -=item B<--port> - -AMI remote port (default: 5038). - -=item B<--username> - -AMI username. - -=item B<--password> - -AMI password. - -=item B<--ssh-option> - -Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). - -=item B<--ssh-path> - -Specify ssh command path (default: none) - -=item B<--ssh-command> - -Specify ssh command (default: 'ssh'). Useful to use 'plink'. - -=item B<--timeout> - -Timeout in seconds for the command (Default: 30). - -=item B<--command> - -Command to get information (Default: 'asterisk_sendcommand.pm'). -Can be changed if you have output in a file. - -=item B<--command-path> - -Command path (Default: /home/centreon/bin). - -=item B<--filter-name> - -Filter on trunkname (regexp can be used). - -=back - -=cut \ No newline at end of file diff --git a/centreon-plugins/apps/voip/asterisk/remote/mode/externalcalls.pm b/centreon-plugins/apps/voip/asterisk/remote/mode/externalcalls.pm deleted file mode 100644 index 6144885af..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/mode/externalcalls.pm +++ /dev/null @@ -1,213 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::remote::mode::externalcalls; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::misc; -use apps::voip::asterisk::remote::lib::ami; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '0.1'; - - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', default => 5038 }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "remote:s" => { name => 'remote', default => 'ssh' }, - "ssh-option:s@" => { name => 'ssh_option' }, - "ssh-path:s" => { name => 'ssh_path' }, - "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, - "timeout:s" => { name => 'timeout', default => 30 }, - "command:s" => { name => 'command', default => 'asterisk_sendcommand.pm' }, - "command-path:s" => { name => 'command_path', default => '/home/centreon/bin' }, - "protocol:s" => { name => 'protocol', }, - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); - $self->{result} = {}; - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (!defined($self->{option_results}->{hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); - $self->{output}->option_exit(); - } - - if ($self->{option_results}->{remote} eq 'ami') - { - if (!defined($self->{option_results}->{username})) { - $self->{output}->add_option_msg(short_msg => "Please set the --username option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{password})) { - $self->{output}->add_option_msg(short_msg => "Please set the --password option"); - $self->{output}->option_exit(); - } - } - - if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); - } -} - -sub manage_selection { - my ($self, %options) = @_; - my @result; - - $self->{asterisk_command} = 'core show channels'; - - if ($self->{option_results}->{remote} eq 'ami') - { - apps::voip::asterisk::remote::lib::ami::connect($self); - @result = apps::voip::asterisk::remote::lib::ami::action($self); - apps::voip::asterisk::remote::lib::ami::quit(); - } - else - { - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => "'".$self->{asterisk_command}."'", - ); - @result = split /\n/, $stdout; - } - - # Compute data - $self->{option_results}->{extcallcounter} = '0'; - foreach my $line (@result) { - if ($line =~ /Outgoing Line/m) - { - $self->{option_results}->{extcallcounter}++; - } - } -} - -sub run { - my ($self, %options) = @_; - - my $msg; - my $old_status = 'ok'; - - $self->manage_selection(); - - # Send formated data to Centreon - my $exit_code = $self->{perfdata}->threshold_check(value => $self->{option_results}->{extcallcounter}, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->perfdata_add(label => 'External Calls', - value => $self->{option_results}->{extcallcounter}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Current external calls: %s", $self->{option_results}->{extcallcounter}) - ); - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Show number of current external calls - -=over 8 - -=item B<--warning> - -Threshold warning. - -=item B<--critical> - -Threshold critical. - -=item B<--remote> - -Execute command remotely; can be 'ami' or 'ssh' (default: ssh). - -=item B<--hostname> - -Hostname to query (need --remote option). - -=item B<--port> - -AMI remote port (default: 5038). - -=item B<--username> - -AMI username. - -=item B<--password> - -AMI password. - -=item B<--ssh-option> - -Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). - -=item B<--ssh-path> - -Specify ssh command path (default: none) - -=item B<--ssh-command> - -Specify ssh command (default: 'ssh'). Useful to use 'plink'. - -=item B<--timeout> - -Timeout in seconds for the command (Default: 30). - -=item B<--command> - -Command to get information (Default: 'asterisk_sendcommand.pm'). -Can be changed if you have output in a file. - -=item B<--command-path> - -Command path (Default: /home/centreon/bin). - -=back - -=cut diff --git a/centreon-plugins/apps/voip/asterisk/remote/mode/showpeers.pm b/centreon-plugins/apps/voip/asterisk/remote/mode/showpeers.pm deleted file mode 100644 index 6d92077c7..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/mode/showpeers.pm +++ /dev/null @@ -1,277 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::remote::mode::showpeers; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::misc; -use apps::voip::asterisk::remote::lib::ami; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - - $options{options}->add_options(arguments => - { - "hostname:s" => { name => 'hostname' }, - "port:s" => { name => 'port', default => 5038 }, - "username:s" => { name => 'username' }, - "password:s" => { name => 'password' }, - "remote:s" => { name => 'remote', default => 'ssh' }, - "ssh-option:s@" => { name => 'ssh_option' }, - "ssh-path:s" => { name => 'ssh_path' }, - "ssh-command:s" => { name => 'ssh_command', default => 'ssh' }, - "timeout:s" => { name => 'timeout', default => 30 }, - "command:s" => { name => 'command', default => 'asterisk_sendcommand.pm' }, - "command-path:s" => { name => 'command_path', default => '/home/centreon/bin' }, - "protocol:s" => { name => 'protocol', }, - "filter-name:s" => { name => 'filter_name', }, - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - }); - $self->{result} = {}; - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (!defined($self->{option_results}->{hostname})) { - $self->{output}->add_option_msg(short_msg => "Please set the --hostname option"); - $self->{output}->option_exit(); - } - - if ($self->{option_results}->{remote} eq 'ami') - { - if (!defined($self->{option_results}->{username})) { - $self->{output}->add_option_msg(short_msg => "Please set the --username option"); - $self->{output}->option_exit(); - } - - if (!defined($self->{option_results}->{password})) { - $self->{output}->add_option_msg(short_msg => "Please set the --password option"); - $self->{output}->option_exit(); - } - } - - if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); - } -} - -sub manage_selection { - my ($self, %options) = @_; - my @result; - - if ($self->{option_results}->{protocol} eq 'sip' || $self->{option_results}->{protocol} eq 'SIP') - { - $self->{asterisk_command} = 'sip show peers'; - } - elsif ($self->{option_results}->{protocol} eq 'iax' || $self->{option_results}->{protocol} eq 'IAX') - { - $self->{asterisk_command} = 'iax2 show peers'; - } - - if ($self->{option_results}->{remote} eq 'ami') - { - apps::voip::asterisk::remote::lib::ami::connect($self); - @result = apps::voip::asterisk::remote::lib::ami::action($self); - apps::voip::asterisk::remote::lib::ami::quit(); - } - else - { - my $stdout = centreon::plugins::misc::execute(output => $self->{output}, - options => $self->{option_results}, - command => $self->{option_results}->{command}, - command_path => $self->{option_results}->{command_path}, - command_options => "'".$self->{asterisk_command}."'", - ); - @result = split /\n/, $stdout; - } - - # Compute data - foreach my $line (@result) { - if ($line =~ /^([\w\-\/]*) *\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} .* (OK) \((.*) (.*)\)/) - { - my ($trunkname, $trunkstatus, $trunkvalue, $trunkunit) = ($1, $2, $3, $4); - - if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $trunkname !~ /$self->{option_results}->{filter_name}/) - { - $self->{output}->output_add(long_msg => "Skipping trunk '" . $trunkname . "': no matching filter name"); - next; - } - - $self->{result}->{$trunkname} = {name => $trunkname, status => 'OK', - realstatus => $trunkstatus, - value => $trunkvalue, - unit => $trunkunit}; - } - elsif ($line =~ /^([\w\-\/]*) *\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} .* (Unreachable)/) - { - my ($trunkname, $trunkstatus) = ($1, $2); - $self->{result}->{$trunkname} = {name => $trunkname, status => 'CRITICAL', realstatus => $trunkstatus}; - } - elsif ($line =~ /^Unable to connect .*/) - { - $self->{result}->{$line} = {name => $line, status => 'CRITICAL', realstatus => 'Unreachable'}; - } - } -} - -sub run { - my ($self, %options) = @_; - - my $msg; - my $old_status = 'ok'; - - $self->manage_selection(); - - # Send formated data to Centreon - if (scalar keys %{$self->{result}} >= 1) - { - $self->{output}->output_add(severity => 'OK', - short_msg => 'Everything is OK'); - } - else - { - $self->{output}->output_add(severity => 'Unknown', - short_msg => 'Nothing to be monitored'); - } - - foreach my $name (sort(keys %{$self->{result}})) { - if (defined($self->{result}->{$name}->{value}) && defined($self->{result}->{$name}->{unit})) - { - $self->{result}->{$name}->{status} = $self->{perfdata}->threshold_check(value => $self->{result}->{$name}->{value}, - threshold => [{ label => 'critical', exit_litteral => 'critical' }, - { label => 'warning', exit_litteral => 'warning' }]); - $self->{output}->perfdata_add(label => $self->{result}->{$name}->{name}, - value => $self->{result}->{$name}->{value}.$self->{result}->{$name}->{unit}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - } - - if (!$self->{output}->is_status(value => $self->{result}->{$name}->{status}, compare => 'ok', litteral => 1)) - { - $msg = sprintf("Trunk: %s", $self->{result}->{$name}->{name}); - $self->{output}->output_add(severity => $self->{result}->{$name}->{status}, - short_msg => $msg); - if ($self->{result}->{$name}->{realstatus} eq 'Unreachable') - { - $self->{output}->output_add(long_msg => sprintf("%s : %s", $self->{result}->{$name}->{name}, $self->{result}->{$name}->{realstatus})); - } - else - { - $self->{output}->output_add(long_msg => sprintf("%s : %s", $self->{result}->{$name}->{name}, $self->{result}->{$name}->{value})); - } - } - } - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Show peers for different protocols. - -=over 8 - -=item B<--warning> - -Threshold warning. - -=item B<--critical> - -Threshold critical. - -=item B<--remote> - -Execute command remotely; can be 'ami' or 'ssh' (default: ssh). - -=item B<--hostname> - -Hostname to query (need --remote option). - -=item B<--port> - -AMI remote port (default: 5038). - -=item B<--username> - -AMI username. - -=item B<--password> - -AMI password. - -=item B<--ssh-option> - -Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52'). - -=item B<--ssh-path> - -Specify ssh command path (default: none) - -=item B<--ssh-command> - -Specify ssh command (default: 'ssh'). Useful to use 'plink'. - -=item B<--timeout> - -Timeout in seconds for the command (Default: 30). - -=item B<--command> - -Command to get information (Default: 'asterisk_sendcommand.pm'). -Can be changed if you have output in a file. - -=item B<--command-path> - -Command path (Default: /home/centreon/bin). - -=item B<--filter-name> - -Filter on trunkname (regexp can be used). - -=item B<--protocol> - -show peer for the choosen protocol (sip or iax). - -=back - -=cut \ No newline at end of file diff --git a/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_centreon.conf b/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_centreon.conf deleted file mode 100644 index 0d3576665..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_centreon.conf +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_sendcommand.pm b/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_sendcommand.pm deleted file mode 100755 index 0b30a7050..000000000 --- a/centreon-plugins/apps/voip/asterisk/remote/remote-script/asterisk_sendcommand.pm +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (C) 2005 Rodolphe Quiedeville -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 dated June, -# 1991. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# If you improve this script please send your version to my email address -# with the copyright notice upgrade with your name. -# -# -# $Log$ -# Revision 1.0 2015/01/16 11:15 David Sabatie -# Release based on already existing munin script -# -# Parameters mandatory: -# -# username -# secret -# -#%# family=asterisk -#%# capabilities=autoconf - -use strict; -use File::Basename; - -my $ret = undef; -if (! eval "require Net::Telnet;") -{ - $ret = "Net::Telnet not found"; -} - -my $DIRNAME=dirname($0); -my $conffile=$DIRNAME."/asterisk_centreon.conf"; - -my $command; -if ( (defined($ARGV[0])) && ($ARGV[0] ne '') ) -{ - $command = $ARGV[0]; -} -else -{ - print 'No command to send'; - exit; -} - -my $host = exists $ENV{'host'} ? $ENV{'host'} : "127.0.0.1"; -my $port = exists $ENV{'port'} ? $ENV{'port'} : "5038"; - -#[asterisk_*] -#env.username xivo_centreon_user -#env.secret secretpass - -my ($username, $secret); - -open FILE, $conffile or die $!; -while (my $confline = ) -{ - ($username, $secret) = split(' ', $confline); -} -close(FILE); - -my $pop = new Net::Telnet (Telnetmode => 0); -$pop->open(Host => $host, - Port => $port); - -## Read connection message. -my $line = $pop->getline; -die $line unless $line =~ /^Asterisk/; - -## Send user name. -$pop->print("Action: login"); -$pop->print("Username: $username"); -$pop->print("Secret: $secret"); -$pop->print("Events: off"); -$pop->print(""); - -#Response: Success -#Message: Authentication accepted - -$line = $pop->getline; -$line = $pop->getline; -if ($line !~ /^Message: Authentication accepted/) { - print 'Unable to connect to AMI: ' . $line; - exit; -} - -## Request status of messages. -$pop->print("Action: command"); -$pop->print("Command: ".$command); -$pop->print(""); -$line = $pop->getline; -$line = $pop->getline; -$line = $pop->getline; -while (($line = $pop->getline) and ($line !~ /END COMMAND/o)) -{ - print $line; -} -$pop->print("Action: logoff"); -$pop->print(""); -$pop->close(); - -# vim:syntax=perl From d0363fb01e503361356d2b8000e89a69e7f3d2a0 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Fri, 24 Nov 2017 15:10:09 +0100 Subject: [PATCH 17/45] fix appeartv alarm mode --- .../hardware/devices/video/appeartv/snmp/mode/alarms.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centreon-plugins/hardware/devices/video/appeartv/snmp/mode/alarms.pm b/centreon-plugins/hardware/devices/video/appeartv/snmp/mode/alarms.pm index 7f62447a4..cadb15ed3 100644 --- a/centreon-plugins/hardware/devices/video/appeartv/snmp/mode/alarms.pm +++ b/centreon-plugins/hardware/devices/video/appeartv/snmp/mode/alarms.pm @@ -154,7 +154,7 @@ sub manage_selection { { oid => $mapping->{msgText}->{oid} }, { oid => $mapping->{msgGenerationTime}->{oid} }, { oid => $mapping->{msgSeverity}->{oid} }, - ], nothing_quit => 1, return_type => 1); + ], return_type => 1); my $last_time; if (defined($self->{option_results}->{memory})) { From 4d19c7cd34826c4e38c4720bac968a8b4cae616c Mon Sep 17 00:00:00 2001 From: qgarnier Date: Fri, 24 Nov 2017 16:07:22 +0100 Subject: [PATCH 18/45] update asterisk snmp --- .../voip/asterisk/snmp/mode/activecalls.pm | 127 ---------- .../voip/asterisk/snmp/mode/channelusage.pm | 121 ++++++++++ .../voip/asterisk/snmp/mode/externalcalls.pm | 224 ------------------ .../apps/voip/asterisk/snmp/plugin.pm | 5 +- 4 files changed, 123 insertions(+), 354 deletions(-) delete mode 100644 centreon-plugins/apps/voip/asterisk/snmp/mode/activecalls.pm create mode 100644 centreon-plugins/apps/voip/asterisk/snmp/mode/channelusage.pm delete mode 100644 centreon-plugins/apps/voip/asterisk/snmp/mode/externalcalls.pm diff --git a/centreon-plugins/apps/voip/asterisk/snmp/mode/activecalls.pm b/centreon-plugins/apps/voip/asterisk/snmp/mode/activecalls.pm deleted file mode 100644 index c9cf8fe06..000000000 --- a/centreon-plugins/apps/voip/asterisk/snmp/mode/activecalls.pm +++ /dev/null @@ -1,127 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::snmp::mode::activecalls; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; - -my $oid_astBase = '.1.3.6.1.4.1.22736'; -my $oid_astConfigCallsActive = $oid_astBase.'.1.2.5.0'; -#my $oid_AsteriskConfigCallsProcessed = $oid_AsteriskBase.'.1.2.6.0'; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.1'; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - "force-oid:s" => { name => 'force_oid', }, - }); - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); - } - - $self->{statefile_value}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - - my ($result, $value); - - if (defined($self->{option_results}->{force_oid})) { - $result = $self->{snmp}->get_leef(oids => [ $self->{option_results}->{force_oid} ], nothing_quit => 1); - $value = $result->{$self->{option_results}->{force_oid}}; - } else { - $result = $self->{snmp}->get_leef(oids => [ $oid_astConfigCallsActive ], nothing_quit => 1); - $value = $result->{$oid_astConfigCallsActive}; - } - - if (!defined($value)) { - $self->{output}->output_add(severity => 'Unknown', - short_msg => sprintf("No information available for active channel") - ); - $self->{output}->display(); - $self->{output}->exit(); - } - - my $exit_code = $self->{perfdata}->threshold_check(value => $value, - threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - $self->{output}->perfdata_add(label => 'Calls', - value => $value, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - - $self->{output}->output_add(severity => $exit_code, - short_msg => sprintf("Current active calls: %s", $value) - ); - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check number of active calls. - -=over 8 - -=item B<--warning> - -Threshold warning. - -=item B<--critical> - -Threshold critical. - -=item B<--force-oid> - -Can choose your oid (numeric format only). - -=back - -=cut diff --git a/centreon-plugins/apps/voip/asterisk/snmp/mode/channelusage.pm b/centreon-plugins/apps/voip/asterisk/snmp/mode/channelusage.pm new file mode 100644 index 000000000..1fb70b503 --- /dev/null +++ b/centreon-plugins/apps/voip/asterisk/snmp/mode/channelusage.pm @@ -0,0 +1,121 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::voip::asterisk::snmp::mode::channelusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + $self->{maps_counters}->{global} = [ + { label => 'channels-active', set => { + key_values => [ { name => 'channels_active' } ], + output_template => 'Channels Active: %s', + perfdatas => [ + { label => 'channels_active', value => 'channels_active_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'calls-active', set => { + key_values => [ { name => 'calls_active' } ], + output_template => 'Calls Active: %s', + perfdatas => [ + { label => 'calls_active', value => 'calls_active_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'calls-count', set => { + key_values => [ { name => 'calls_count', diff => 1 } ], + output_template => 'Calls Count: %s', + perfdatas => [ + { label => 'calls_count', value => 'calls_count_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_astConfigCallsActive = '.1.3.6.1.4.1.22736.1.2.5.0'; + my $oid_astConfigCallsProcessed = '.1.3.6.1.4.1.22736.1.2.6.0'; + my $oid_astNumChannels = '.1.3.6.1.4.1.22736.1.5.1.0'; + my $result = $options{snmp}->get_leef(oids => [$oid_astConfigCallsActive, $oid_astConfigCallsProcessed, $oid_astNumChannels], nothing_quit => 1); + + $self->{cache_name} = "asterisk_" . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' . $self->{mode} . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); + + $self->{global} = { + calls_active => $result->{$oid_astConfigCallsActive}, + calls_count => $result->{$oid_astConfigCallsProcessed}, + channels_active => $result->{$oid_astNumChannels}, + }; +} + +1; + +__END__ + +=head1 MODE + +Check channel usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='calls-active' + +=item B<--warning-*> + +Threshold warning. +Can be: 'channels-active', 'calls-active', 'calls-count'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'channels-active', 'calls-active', 'calls-count'. + +=back + +=cut diff --git a/centreon-plugins/apps/voip/asterisk/snmp/mode/externalcalls.pm b/centreon-plugins/apps/voip/asterisk/snmp/mode/externalcalls.pm deleted file mode 100644 index 31748c3f8..000000000 --- a/centreon-plugins/apps/voip/asterisk/snmp/mode/externalcalls.pm +++ /dev/null @@ -1,224 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::voip::asterisk::snmp::mode::externalcalls; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; -use centreon::plugins::statefile; - -my $oid_astBase = '.1.3.6.1.4.1.22736'; -my $oid_astConfigCallsActive = $oid_astBase.'.1.2.5.0'; -my $oid_astChanName = $oid_astBase.'.1.5.2.1.2'; # need an index at the end -my $oid_astChanIndex = $oid_astBase.'.1.5.2.1.1'; # need an index at the end -my $oid_astNumChannels = $oid_astBase.'.1.5.1.0'; - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - $options{options}->add_options(arguments => - { - "warning:s" => { name => 'warning', }, - "critical:s" => { name => 'critical', }, - "warnontrunk:s" => { name => 'warnontrunk', }, - "critontrunk:s" => { name => 'critontrunk', }, - "force-oid:s" => { name => 'force_oid', }, - "trunkusernamelist:s" => { name => 'trunkusernamelist', }, - "filter-name" => { name => 'filter-name' }, - }); - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'warnontrunk', value => $self->{option_results}->{warnontrunk})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warnontrunk} . "'."); - $self->{output}->option_exit(); - } - if (($self->{perfdata}->threshold_validate(label => 'critontrunk', value => $self->{option_results}->{critontrunk})) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critontrunk} . "'."); - $self->{output}->option_exit(); - } - if (!defined($self->{option_results}->{trunkusernamelist})) { - $self->{output}->add_option_msg(short_msg => "trunkusernamelist must be defined."); - $self->{output}->option_exit(); - } - - $self->{statefile_value}->check_options(%options); -} - -sub run { - my ($self, %options) = @_; - $self->{snmp} = $options{snmp}; - - my ($result, $value); - my (@callsbytrunk, @error_msg, @msg); - - # explode trunk list - my @trunkusernamelist = split(',',$self->{option_results}->{trunkusernamelist}); - foreach my $trunk (@trunkusernamelist) - { - if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $trunk !~ /$self->{option_results}->{filter_name}/) { - $self->{output}->output_add(long_msg => "Skipping trunk '" . $trunk . "': no matching filter name"); - next; - } - push @callsbytrunk , { trunk => $trunk, num => 0}; - } - # get chanName and sum calls for each - $result = $self->{snmp}->get_leef(oids => [ $oid_astNumChannels ], nothing_quit => 1); - my $astNumChannels = $result->{$oid_astNumChannels}; - my $astConfigCallsActive = 0; - foreach my $i (1..$astNumChannels) { - $result = $self->{snmp}->get_leef(oids => [ $oid_astChanName.'.'.$i ], nothing_quit => 1); - $value = $result->{$oid_astChanName.'.'.$i}; - $value =~ /^(.*)\/(.*)-.*/; - my ($protocol, $trunkname) = ($1, $2); - foreach my $val (@callsbytrunk) - { - if ( $val->{trunk} eq $trunkname ) - { - $val->{num} = $val->{num}+1; - $astConfigCallsActive = $astConfigCallsActive+1; - } - } - } - - # compute status based on total number of active calls - my $exit_code = $self->{perfdata}->threshold_check(value => $astConfigCallsActive, - threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]); - push @msg, {msg => sprintf("Current external calls: %s", $astConfigCallsActive)}; - - # Perfdata on all active calls - $self->{output}->perfdata_add(label => 'Total calls', - value => $astConfigCallsActive, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'), - min => 0); - - # Perfdata on number of calls for each trunk - my ($temp_exit, $exit_msg); - my (@trunk_msg, @out_msg); - my $trunk_exit_code = 'ok'; - foreach $value (@callsbytrunk) - { - $temp_exit = $self->{perfdata}->threshold_check(value => $value->{num}, - threshold => [ { label => 'critontrunk', exit_litteral => 'critical' }, { label => 'warnontrunk', exit_litteral => 'warning' } ]); - $self->{output}->perfdata_add(label => $value->{trunk}, - value => $value->{num}, - warning => $self->{perfdata}->get_perfdata_for_output(label => 'warnontrunk'), - critical => $self->{perfdata}->get_perfdata_for_output(label => 'critontrunk'), - min => 0); - $self->{output}->output_add(long_msg => sprintf("%s : %s", $value->{trunk}, $value->{num})); - - $trunk_exit_code = $self->{output}->get_most_critical(status => [ $temp_exit, $trunk_exit_code ]); - # create msg for most critical data .... - if ($self->{output}->is_status(value => $temp_exit, compare => $trunk_exit_code, litteral => 1)) - { - push @trunk_msg, {msg => sprintf("'%s': %s", $value->{trunk}, $value->{num})}; - } - } - if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1) && !$self->{output}->is_status(value => $trunk_exit_code, compare => 'ok', litteral => 1)) - { - unshift @trunk_msg, @msg; - $exit_code = $self->{output}->get_most_critical(status => [ $exit_code, $trunk_exit_code ]); - } - if (!$self->{output}->is_status(value => $trunk_exit_code, compare => 'ok', litteral => 1)) - { - @out_msg=@trunk_msg; - $exit_code = $trunk_exit_code ; - } - else - { - push @out_msg, @msg; - } - - $exit_msg = ''; - my $separator = ''; - foreach my $out (@out_msg) - { - $exit_msg .= $separator.$out->{msg}; - $separator = ', '; - } - $self->{output}->output_add(severity => $exit_code, - short_msg => $exit_msg - ); - - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check number of external calls (total and by trunk) - -=over 8 - -=item B<--warning> - -Threshold warning for total number of external calls. - -=item B<--critical> - -Threshold critical for total number of external calls. - -=item B<--warnontrunk> - -Threshold warning for trunks. - -=item B<--critontrunk> - -Threshold critical for trunks. - -=item B<--force-oid> - -Can choose your oid (numeric format only). - -=item B<--trunkusernamelist> - -List of outgoing trunks' username. - -=item B<--filter-name> - -Filter on trunk's username (regexp can be used). - -=back - -=cut \ No newline at end of file diff --git a/centreon-plugins/apps/voip/asterisk/snmp/plugin.pm b/centreon-plugins/apps/voip/asterisk/snmp/plugin.pm index d6811d6f3..61a0bb3b5 100644 --- a/centreon-plugins/apps/voip/asterisk/snmp/plugin.pm +++ b/centreon-plugins/apps/voip/asterisk/snmp/plugin.pm @@ -32,9 +32,8 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( - 'activecalls' => 'apps::voip::asterisk::snmp::mode::activecalls', - 'externalcalls' => 'apps::voip::asterisk::snmp::mode::externalcalls', - ); + 'channel-usage' => 'apps::voip::asterisk::snmp::mode::channelusage', + ); return $self; } From db1ec1b8129d735f3aeda12640e7feb02a6ef032 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 27 Nov 2017 14:06:55 +0100 Subject: [PATCH 19/45] add invalid object oracle mode --- .../database/oracle/mode/invalidobject.pm | 203 ++++++++++++++++++ centreon-plugins/database/oracle/plugin.pm | 1 + 2 files changed, 204 insertions(+) create mode 100644 centreon-plugins/database/oracle/mode/invalidobject.pm diff --git a/centreon-plugins/database/oracle/mode/invalidobject.pm b/centreon-plugins/database/oracle/mode/invalidobject.pm new file mode 100644 index 000000000..8ee9e2c69 --- /dev/null +++ b/centreon-plugins/database/oracle/mode/invalidobject.pm @@ -0,0 +1,203 @@ +# +# Copyright 2017 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 database::oracle::mode::invalidobject; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_invalid_output', skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'objects', set => { + key_values => [ { name => 'invalid_objects' } ], + output_template => 'objects : %s', + perfdatas => [ + { label => 'invalid_objects', value => 'invalid_objects_absolute', template => '%d', min => 0 }, + ], + } + }, + { label => 'indexes', set => { + key_values => [ { name => 'invalid_indexes' } ], + output_template => 'indexes : %s', + perfdatas => [ + { label => 'invalid_indexes', value => 'invalid_indexes_absolute', template => '%d', min => 0 }, + ], + } + }, + { label => 'ind-partitions', set => { + key_values => [ { name => 'invalid_ind_partitions' } ], + output_template => 'index partitions : %s', + perfdatas => [ + { label => 'invalid_ind_partitions', value => 'invalid_ind_partitions_absolute', template => '%d', min => 0 }, + ], + } + }, + { label => 'ind-subpartitions', set => { + key_values => [ { name => 'invalid_ind_subpartitions' } ], + output_template => 'index subpartitions : %s', + perfdatas => [ + { label => 'invalid_ind_subpartitions', value => 'invalid_ind_subpartitions_absolute', template => '%d', min => 0 }, + ], + } + }, + { label => 'registry-components', set => { + key_values => [ { name => 'invalid_registry_components' } ], + output_template => 'registry components : %s', + perfdatas => [ + { label => 'invalid_registry_components', value => 'invalid_registry_components_absolute', template => '%d', min => 0 }, + ], + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-message:s" => { name => 'filter_message' }, + "retention-objects:s" => { name => 'retention_objects', default => 3}, + }); + + return $self; +} + +sub prefix_invalid_output { + my ($self, %options) = @_; + + return "Invalid "; +} + +sub get_invalids { + my ($self, %options) = @_; + + $self->{global}->{$options{type}} = 0; + $options{sql}->query(query => $options{query}); + foreach ($options{sql}->fetchall_arrayref()) { + if (defined($self->{option_results}->{filter_message}) && $self->{option_results}->{filter_message} ne '' && + $_->[0] !~ /$self->{option_results}->{filter_message}/) { + $self->{output}->output_add(long_msg => "skipping $options{type} => '" . $_->[0] . "': no matching filter.", debug => 1); + next; + } + + $self->{global}->{$options{type}}++; + } +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{global} = {}; + $options{sql}->connect(); + + $self->get_invalids(%options, type => 'invalid_objects', query => q{ + SELECT + O.object_type||' '||O.owner||'.'||O.object_name||' is '||O.status + FROM dba_objects O + LEFT OUTER JOIN DBA_MVIEW_refresh_times V ON O.object_name = V.NAME AND O.owner = V.owner + WHERE (LAST_REFRESH <= (SELECT sysdate - } . $self->{option_results}->{retention_objects} . q{ FROM dual) OR LAST_REFRESH is null) AND + STATUS = 'INVALID' AND O.object_name NOT LIKE 'BIN$%' + }); + + $self->get_invalids(%options, type => 'invalid_indexes', query => q{ + SELECT index_type||' index '||owner||'.'||index_name||' of '||table_owner||'.'||table_name||' is '||status + FROM dba_indexes + WHERE status <> 'VALID' AND status <> 'N/A' + }); + + $self->get_invalids(%options, type => 'invalid_ind_partitions', query => q{ + SELECT partition_name||' of '||index_owner||'.'||index_name||' is '||status + FROM dba_ind_partitions + WHERE status <> 'USABLE' AND status <> 'N/A' + }); + + if ($self->{sql}->is_version_minimum(version => '10.x')) { + $self->get_invalids(%options, type => 'invalid_ind_subpartitions', query => q{ + SELECT subpartition_name||' of '||partition_name||' of '||index_owner||'.'||index_name||' is '||status + FROM dba_ind_subpartitions + WHERE status <> 'USABLE' AND status <> 'N/A' + }); + } + + if ($self->{sql}->is_version_minimum(version => '10.x')) { + $self->get_invalids(%options, type => 'invalid_registry_components', query => q{ + SELECT namespace||'.'||comp_name||'-'||version||' is '||status + FROM dba_registry + WHERE status <> 'VALID' AND status <> 'OPTION OFF' + }); + } else { + $self->get_invalids(%options, type => 'invalid_registry_components', query => q{ + SELECT 'SCHEMA.'||comp_name||'-'||version||' is '||status + FROM dba_registry + WHERE status <> 'VALID' AND status <> 'OPTION OFF' + }); + } +} + +1; + +__END__ + +=head1 MODE + +Check faulty objects, indices, partitions. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='^indexes$' + +=item B<--retention-objects> + +Retention in days for invalid objects (default : 3). + +=item B<--filter-message> + +Filter by message (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'objects', 'indexes', 'ind-partitions', 'ind-subpartitions', +'registry-components'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'objects', 'indexes', 'ind-partitions', 'ind-subpartitions', +'registry-components'. + +=back + +=cut diff --git a/centreon-plugins/database/oracle/plugin.pm b/centreon-plugins/database/oracle/plugin.pm index ad0cb4bae..b2e8a3c31 100644 --- a/centreon-plugins/database/oracle/plugin.pm +++ b/centreon-plugins/database/oracle/plugin.pm @@ -39,6 +39,7 @@ sub new { 'data-files-status' => 'database::oracle::mode::datafilesstatus', 'datacache-hitratio' => 'database::oracle::mode::datacachehitratio', 'event-waits-usage' => 'database::oracle::mode::eventwaitsusage', + 'invalid-object' => 'database::oracle::mode::invalidobject', 'long-queries' => 'database::oracle::mode::longqueries', 'process-usage' => 'database::oracle::mode::processusage', 'rman-backup-problems' => 'database::oracle::mode::rmanbackupproblems', From 65349d54a80f26bb34713e54f7e4561c84aef26d Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 27 Nov 2017 15:48:32 +0100 Subject: [PATCH 20/45] fix invalid object --- centreon-plugins/database/oracle/mode/invalidobject.pm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/centreon-plugins/database/oracle/mode/invalidobject.pm b/centreon-plugins/database/oracle/mode/invalidobject.pm index 8ee9e2c69..92b198274 100644 --- a/centreon-plugins/database/oracle/mode/invalidobject.pm +++ b/centreon-plugins/database/oracle/mode/invalidobject.pm @@ -102,7 +102,8 @@ sub get_invalids { $self->{global}->{$options{type}} = 0; $options{sql}->query(query => $options{query}); - foreach ($options{sql}->fetchall_arrayref()) { + my $result = $options{sql}->fetchall_arrayref(); + foreach (@$result) { if (defined($self->{option_results}->{filter_message}) && $self->{option_results}->{filter_message} ne '' && $_->[0] !~ /$self->{option_results}->{filter_message}/) { $self->{output}->output_add(long_msg => "skipping $options{type} => '" . $_->[0] . "': no matching filter.", debug => 1); @@ -140,7 +141,7 @@ sub manage_selection { WHERE status <> 'USABLE' AND status <> 'N/A' }); - if ($self->{sql}->is_version_minimum(version => '10.x')) { + if ($options{sql}->is_version_minimum(version => '10.x')) { $self->get_invalids(%options, type => 'invalid_ind_subpartitions', query => q{ SELECT subpartition_name||' of '||partition_name||' of '||index_owner||'.'||index_name||' is '||status FROM dba_ind_subpartitions @@ -148,7 +149,7 @@ sub manage_selection { }); } - if ($self->{sql}->is_version_minimum(version => '10.x')) { + if ($options{sql}->is_version_minimum(version => '10.x')) { $self->get_invalids(%options, type => 'invalid_registry_components', query => q{ SELECT namespace||'.'||comp_name||'-'||version||' is '||status FROM dba_registry From aa8d19e2685592a069db7dcb0e14053bb9d9f79e Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 27 Nov 2017 15:48:48 +0100 Subject: [PATCH 21/45] enhance node vm status hyperv --- .../common/powershell/hyperv/2012/nodevmstatus.pm | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm b/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm index 23ac2ced5..478c46fa3 100644 --- a/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm +++ b/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm @@ -39,10 +39,21 @@ Try { $ErrorActionPreference = "Stop" $vms = Get-VM + $node_is_clustered = 0 + Try { + If (@(Get-ClusterNode -ea Ignore).Count -ne 0) { + $node_is_clustered = 1 + } + } Catch { + } Foreach ($vm in $vms) { $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " - Write-Host "[name=" $vm.VMName "][state=" $vm.State "][status=" $vm.Status "][IsClustered=" $vm.IsClustered "][note=" $note "]" + $isClustered = $vm.IsClustered + if ($node_is_clustered == 0) { + $isClustered = "nodeNotClustered" + } + Write-Host "[name=" $vm.VMName "][state=" $vm.State "][status=" $vm.Status "][IsClustered=" $isClustered "][note=" $note "]" } } Catch { Write-Host $Error[0].Exception @@ -63,4 +74,4 @@ __END__ Method to get hyper-v informations. -=cut \ No newline at end of file +=cut From 5bc12f21090b8257fa5c1f388f1e5e0daeb9978a Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 28 Nov 2017 09:13:16 +0100 Subject: [PATCH 22/45] fix hyperv node-vm-status mode --- .../centreon/common/powershell/hyperv/2012/nodevmstatus.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm b/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm index 478c46fa3..4a4a792db 100644 --- a/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm +++ b/centreon-plugins/centreon/common/powershell/hyperv/2012/nodevmstatus.pm @@ -50,7 +50,7 @@ Try { $note = $vm.Notes -replace "\r","" $note = $note -replace "\n"," - " $isClustered = $vm.IsClustered - if ($node_is_clustered == 0) { + if ($node_is_clustered -eq 0) { $isClustered = "nodeNotClustered" } Write-Host "[name=" $vm.VMName "][state=" $vm.State "][status=" $vm.Status "][IsClustered=" $isClustered "][note=" $note "]" From 01a4c0e0e3126e9bb8e064a675058ce37faca527 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 28 Nov 2017 12:50:30 +0100 Subject: [PATCH 23/45] add cmd-return mode for windows --- .../os/windows/local/mode/cmdreturn.pm | 137 ++++++++++++++++++ centreon-plugins/os/windows/local/plugin.pm | 1 + 2 files changed, 138 insertions(+) create mode 100644 centreon-plugins/os/windows/local/mode/cmdreturn.pm diff --git a/centreon-plugins/os/windows/local/mode/cmdreturn.pm b/centreon-plugins/os/windows/local/mode/cmdreturn.pm new file mode 100644 index 000000000..f334997fa --- /dev/null +++ b/centreon-plugins/os/windows/local/mode/cmdreturn.pm @@ -0,0 +1,137 @@ +# +# Copyright 2017 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 os::windows::local::mode::cmdreturn; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::misc; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "timeout:s" => { name => 'timeout', default => 30 }, + "command:s" => { name => 'command' }, + "command-path:s" => { name => 'command_path' }, + "command-options:s" => { name => 'command_options' }, + "manage-returns:s" => { name => 'manage_returns', default => '' }, + }); + $self->{manage_returns} = {}; + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + if (!defined($self->{option_results}->{command})) { + $self->{output}->add_option_msg(short_msg => "Need to specify command option."); + $self->{output}->option_exit(); + } + + foreach my $entry (split(/#/, $self->{option_results}->{manage_returns})) { + next if (!($entry =~ /(.*?),(.*?),(.*)/)); + next if (!$self->{output}->is_litteral_status(status => $2)); + if ($1 ne '') { + $self->{manage_returns}->{$1} = {return => $2, msg => $3}; + } else { + $self->{manage_returns}->{default} = {return => $2, msg => $3}; + } + } + if ($self->{option_results}->{manage_returns} eq '' || scalar(keys %{$self->{manage_returns}}) == 0) { + $self->{output}->add_option_msg(short_msg => "Need to specify manage-returns option correctly."); + $self->{output}->option_exit(); + } +} + +sub run { + my ($self, %options) = @_; + + my ($stdout, $exit_code) = centreon::plugins::misc::execute(output => $self->{output}, + options => $self->{option_results}, + command => $self->{option_results}->{command}, + command_path => $self->{option_results}->{command_path}, + command_options => $self->{option_results}->{command_options}, + no_quit => 1); + my $long_msg = $stdout; + $long_msg =~ s/\|/-/mg; + $self->{output}->output_add(long_msg => $long_msg); + + if (defined($self->{manage_returns}->{$exit_code})) { + $self->{output}->output_add(severity => $self->{manage_returns}->{$exit_code}->{return}, + short_msg => $self->{manage_returns}->{$exit_code}->{msg}); + } elsif (defined($self->{manage_returns}->{default})) { + $self->{output}->output_add(severity => $self->{manage_returns}->{default}->{return}, + short_msg => $self->{manage_returns}->{default}->{msg}); + } else { + $self->{output}->output_add(severity => 'UNKNWON', + short_msg => 'Exit code from command'); + } + + if (defined($exit_code)) { + $self->{output}->perfdata_add(label => "code", + value => $exit_code); + } + + $self->{output}->display(); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Check command returns. + +=over 8 + +=item B<--manage-returns> + +Set action according command exit code. +Example: 0,OK,File xxx exist#1,CRITICAL,File xxx not exist#,UNKNOWN,Command problem + +=item B<--timeout> + +Timeout in seconds for the command (Default: 30). + +=item B<--command> + +Command to test (Default: none). + +=item B<--command-path> + +Command path (Default: none). + +=item B<--command-options> + +Command options (Default: none). + +=back + +=cut diff --git a/centreon-plugins/os/windows/local/plugin.pm b/centreon-plugins/os/windows/local/plugin.pm index 71795803d..0d428c699 100644 --- a/centreon-plugins/os/windows/local/plugin.pm +++ b/centreon-plugins/os/windows/local/plugin.pm @@ -31,6 +31,7 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( + 'cmd-return' => 'os::windows::local::mode::cmdreturn', 'pending-reboot' => 'os::windows::local::mode::pendingreboot', 'sessions' => 'os::windows::local::mode::sessions', 'time' => 'os::windows::local::mode::ntp', From 7988a425046264e17c9c08c06c594954dd8e8ef9 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 29 Nov 2017 09:49:53 +0100 Subject: [PATCH 24/45] add time in cmd-return --- .../os/windows/local/mode/cmdreturn.pm | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/centreon-plugins/os/windows/local/mode/cmdreturn.pm b/centreon-plugins/os/windows/local/mode/cmdreturn.pm index f334997fa..e03be3dd7 100644 --- a/centreon-plugins/os/windows/local/mode/cmdreturn.pm +++ b/centreon-plugins/os/windows/local/mode/cmdreturn.pm @@ -25,6 +25,7 @@ use base qw(centreon::plugins::mode); use strict; use warnings; use centreon::plugins::misc; +use Time::HiRes qw(gettimeofday tv_interval); sub new { my ($class, %options) = @_; @@ -34,6 +35,8 @@ sub new { $self->{version} = '1.0'; $options{options}->add_options(arguments => { + "warning-time:s" => { name => 'warning_time' }, + "critical-time:s" => { name => 'critical_time' }, "timeout:s" => { name => 'timeout', default => 30 }, "command:s" => { name => 'command' }, "command-path:s" => { name => 'command_path' }, @@ -66,17 +69,29 @@ sub check_options { $self->{output}->add_option_msg(short_msg => "Need to specify manage-returns option correctly."); $self->{output}->option_exit(); } + + if (($self->{perfdata}->threshold_validate(label => 'warning-time', value => $self->{option_results}->{warning_time})) == 0) { + $self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning_time} . "'."); + $self->{output}->option_exit(); + } + if (($self->{perfdata}->threshold_validate(label => 'critical-time', value => $self->{option_results}->{critical_time})) == 0) { + $self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical_time} . "'."); + $self->{output}->option_exit(); + } } sub run { my ($self, %options) = @_; + my $timing0 = [gettimeofday]; my ($stdout, $exit_code) = centreon::plugins::misc::execute(output => $self->{output}, options => $self->{option_results}, command => $self->{option_results}->{command}, command_path => $self->{option_results}->{command_path}, command_options => $self->{option_results}->{command_options}, no_quit => 1); + my $timeelapsed = tv_interval($timing0, [gettimeofday]); + my $long_msg = $stdout; $long_msg =~ s/\|/-/mg; $self->{output}->output_add(long_msg => $long_msg); @@ -97,6 +112,19 @@ sub run { value => $exit_code); } + my $exit = $self->{perfdata}->threshold_check(value => $timeelapsed, + threshold => [ { label => 'critical-time', exit_litteral => 'critical' }, { label => 'warning-time', exit_litteral => 'warning' } ]); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Response time %.3fs", $timeelapsed)); + } + + $self->{output}->perfdata_add(label => 'time', unit => 's', + value => sprintf('%.3f', $timeelapsed), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning_time'), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical_time'), + min => 0); + $self->{output}->display(); $self->{output}->exit(); } @@ -132,6 +160,14 @@ Command path (Default: none). Command options (Default: none). +=item B<--warning-time> + +Threshold warning in seconds. + +=item B<--critical-time> + +Threshold critical in seconds. + =back =cut From 5225ed0663628a84b61643310ac79f3ebe0d0963 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 29 Nov 2017 15:29:15 +0100 Subject: [PATCH 25/45] Fix #809 --- .../network/radware/alteon/snmp/mode/cpu.pm | 162 +++++++++++++++--- 1 file changed, 139 insertions(+), 23 deletions(-) diff --git a/centreon-plugins/network/radware/alteon/snmp/mode/cpu.pm b/centreon-plugins/network/radware/alteon/snmp/mode/cpu.pm index 17952b101..2f74dcacd 100644 --- a/centreon-plugins/network/radware/alteon/snmp/mode/cpu.pm +++ b/centreon-plugins/network/radware/alteon/snmp/mode/cpu.pm @@ -29,46 +29,120 @@ sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0, cb_prefix_output => 'prefix_cpu_output' } + { name => 'mp_cpu', type => 0, cb_prefix_output => 'prefix_mp_cpu_output', skipped_code => { -10 => 1 } }, + { name => 'sp_ga_avg', type => 0, skipped_code => { -10 => 1 } }, + { name => 'sp_ga', type => 1, cb_init => 'skip_sp_ga', cb_prefix_output => 'prefix_sp_ga_output', message_multiple => 'All SP GA CPU are ok' }, ]; - $self->{maps_counters}->{global} = [ - { label => '1s', set => { - key_values => [ { name => '1s' } ], + $self->{maps_counters}->{mp_cpu} = [ + { label => 'mp-1s', set => { + key_values => [ { name => 'mp_1s' } ], output_template => '%.2f%% (1sec)', perfdatas => [ - { label => 'cpu_1s', value => '1s_absolute', template => '%.2f', + { label => 'mp_cpu_1s', value => 'mp_1s_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, - { label => '4s', set => { - key_values => [ { name => '4s' } ], + { label => 'mp-4s', set => { + key_values => [ { name => 'mp_4s' } ], output_template => '%.2f%% (4sec)', perfdatas => [ - { label => 'cpu_4s', value => '4s_absolute', template => '%.2f', + { label => 'mp_cpu_4s', value => 'mp_4s_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, - { label => '64s', set => { - key_values => [ { name => '64s' } ], + { label => 'mp-64s', set => { + key_values => [ { name => 'mp_64s' } ], output_template => '%.2f%% (64sec)', perfdatas => [ - { label => 'cpu_64s', value => '64s_absolute', template => '%.2f', + { label => 'mp_cpu_64s', value => 'mp_64s_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, ], } }, ]; + + $self->{maps_counters}->{sp_ga_avg} = [ + { label => 'sp-ga-avg-1s', set => { + key_values => [ { name => 'sp_1s' } ], + output_template => 'SP GA Average CPU Usage: %.2f%% (1sec)', + perfdatas => [ + { label => 'avg_spga_cpu_1s', value => 'sp_1s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + { label => 'sp-ga-avg-4s', set => { + key_values => [ { name => 'sp_4s' } ], + output_template => '%.2f%% (4sec)', + perfdatas => [ + { label => 'avg_spga_cpu_4s', value => 'sp_4s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + { label => 'sp-ga-avg-64s', set => { + key_values => [ { name => 'sp_64s' } ], + output_template => '%.2f%% (64sec)', + perfdatas => [ + { label => 'avg_spga_cpu_64s', value => 'sp_64s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%' }, + ], + } + }, + ]; + + $self->{maps_counters}->{sp_ga} = [ + { label => 'sp-ga-1s', set => { + key_values => [ { name => 'sp_1s' }, { name => 'display' } ], + output_template => '%.2f%% (1sec)', + perfdatas => [ + { label => 'spga_cpu_1s', value => 'sp_1s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'sp-ga-4s', set => { + key_values => [ { name => 'sp_4s' }, { name => 'display' } ], + output_template => '%.2f%% (4sec)', + perfdatas => [ + { label => 'spga_cpu_4s', value => 'sp_4s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'sp-ga-64s', set => { + key_values => [ { name => 'sp_64s' }, { name => 'display' } ], + output_template => '%.2f%% (64sec)', + perfdatas => [ + { label => 'spga_cpu_64s', value => 'sp_64s_absolute', template => '%.2f', + min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; } -sub prefix_cpu_output { +sub prefix_mp_cpu_output { my ($self, %options) = @_; return "MP CPU Usage: "; } +sub prefix_sp_ga_output { + my ($self, %options) = @_; + + return "SP GA CPU '" . $options{instance_value}->{display} . "' Usage: "; +} + +sub skip_sp_ga { + my ($self, %options) = @_; + + scalar(keys %{$self->{sp_ga}}) <= 0 ? return(1) : return(0); +} + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -82,18 +156,56 @@ sub new { return $self; } +my $mapping = { + mpCpuStatsUtil1Second => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.2.1' }, + mpCpuStatsUtil4Seconds => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.2.2' }, + mpCpuStatsUtil64Seconds => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.2.3' }, +}; +my $mapping2 = { + spGAStatsCpuUtil1Second => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.13.1.1.3' }, + spGAStatsCpuUtil4Seconds => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.13.1.1.4' }, + spGAStatsCpuUtil64Seconds => { oid => '.1.3.6.1.4.1.1872.2.5.1.2.13.1.1.5' }, +}; +my $oid_mpCpuStats = '.1.3.6.1.4.1.1872.2.5.1.2.2'; +my $oid_spGAStatsCpuUtilTableEntry = '.1.3.6.1.4.1.1872.2.5.1.2.13.1.1'; + sub manage_selection { my ($self, %options) = @_; + + my $snmp_result = $options{snmp}->get_multiple_table(oids => [ { oid => $oid_mpCpuStats }, { oid => $oid_spGAStatsCpuUtilTableEntry } ], + return_type => 1, nothing_quit => 1); + $self->{sp_ga} = {}; + my ($avg_sp_1s, $avg_sp_4s, $avg_sp_64s) = (0, 0, 0); + foreach my $oid (keys %{$snmp_result}) { + next if ($oid !~ /^$mapping2->{spGAStatsCpuUtil64Seconds}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $options{snmp}->map_instance(mapping => $mapping2, results => $snmp_result, instance => $instance); - my $oid_mpCpuStatsUtil1Second = '.1.3.6.1.4.1.1872.2.5.1.2.2.1.0'; - my $oid_mpCpuStatsUtil4Seconds = '.1.3.6.1.4.1.1872.2.5.1.2.2.2.0'; - my $oid_mpCpuStatsUtil64Seconds = '.1.3.6.1.4.1.1872.2.5.1.2.2.3.0'; - my $snmp_result = $options{snmp}->get_leef(oids => [ - $oid_mpCpuStatsUtil1Second, $oid_mpCpuStatsUtil4Seconds, - $oid_mpCpuStatsUtil64Seconds], nothing_quit => 1); + $self->{sp_ga}->{$instance} = { + display => $instance, + sp_1s => $result->{spGAStatsCpuUtil1Second}, + sp_4s => $result->{spGAStatsCpuUtil4Seconds}, + sp_64s => $result->{spGAStatsCpuUtil64Seconds}, + }; + $avg_sp_1s += $result->{spGAStatsCpuUtil1Second}; + $avg_sp_4s += $result->{spGAStatsCpuUtil4Seconds}; + $avg_sp_64s += $result->{spGAStatsCpuUtil64Seconds}; + } - $self->{global} = { '1s' => $snmp_result->{$oid_mpCpuStatsUtil1Second}, '4s' => $snmp_result->{$oid_mpCpuStatsUtil4Seconds}, - '64s' => $snmp_result->{$oid_mpCpuStatsUtil64Seconds} }; + $self->{sp_ga_avg} = {}; + if (scalar(keys %{$self->{sp_ga}}) > 1) { + $self->{sp_ga_avg} = { + sp_1s => $avg_sp_1s / scalar(keys %{$self->{sp_ga}}), + sp_4s => $avg_sp_4s / scalar(keys %{$self->{sp_ga}}), + sp_64s => $avg_sp_64s / scalar(keys %{$self->{sp_ga}}), + }; + } + + $self->{mp_cpu} = { + mp_1s => $snmp_result->{$mapping->{mpCpuStatsUtil1Second}->{oid} . '.0'}, + mp_4s => $snmp_result->{$mapping->{mpCpuStatsUtil4Seconds}->{oid} . '.0'}, + mp_64s => $snmp_result->{$mapping->{mpCpuStatsUtil64Seconds}->{oid} . '.0'}, + }; } 1; @@ -114,14 +226,18 @@ Example: --filter-counters='^(64s)$' =item B<--warning-*> Threshold warning. -Can be: '1s', '4s', '64s'. +Can be: 'mp-1s', 'mp-4s', 'mp-64s', +'sp-ga-1s', 'sp-ga-4s', 'sp-ga-64s', +'sp-ga-avg-1s', 'sp-ga-avg-4s', 'sp-ga-avg-64s'. =item B<--critical-*> Threshold critical. -Can be: '1s', '4s', '64s'. +Can be: 'mp-1s', 'mp-4s', 'mp-64s', +'sp-ga-1s', 'sp-ga-4s', 'sp-ga-64s', +'sp-ga-avg-1s', 'sp-ga-avg-4s', 'sp-ga-avg-64s'. =back =cut - \ No newline at end of file + From 2c89cdabfae4823f182522c01042174004a5f217 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 30 Nov 2017 14:17:06 +0100 Subject: [PATCH 26/45] add nsclient rest api plugin --- .../apps/nsclient/restapi/mode/query.pm | 246 ++++++++++++++++++ .../apps/nsclient/restapi/plugin.pm | 48 ++++ 2 files changed, 294 insertions(+) create mode 100644 centreon-plugins/apps/nsclient/restapi/mode/query.pm create mode 100644 centreon-plugins/apps/nsclient/restapi/plugin.pm diff --git a/centreon-plugins/apps/nsclient/restapi/mode/query.pm b/centreon-plugins/apps/nsclient/restapi/mode/query.pm new file mode 100644 index 000000000..2cf3971dd --- /dev/null +++ b/centreon-plugins/apps/nsclient/restapi/mode/query.pm @@ -0,0 +1,246 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::nsclient::restapi::mode::query; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::http; +use JSON; +use URI::Encode; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.1'; + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "http-peer-addr:s" => { name => 'http_peer_addr' }, + "port:s" => { name => 'port', default => 8433 }, + "proto:s" => { name => 'proto', default => 'https' }, + "credentials" => { name => 'credentials' }, + "username:s" => { name => 'username' }, + "password:s" => { name => 'password' }, + "legacy-password:s" => { name => 'legacy_password' }, + "proxyurl:s" => { name => 'proxyurl' }, + "proxypac:s" => { name => 'proxypac' }, + "timeout:s" => { name => 'timeout' }, + "ssl:s" => { name => 'ssl' }, + "command:s" => { name => 'command' }, + "arg:s@" => { name => 'arg' }, + "unknown-status:s" => { name => 'unknown_status', default => '' }, + "warning-status:s" => { name => 'warning_status' }, + "critical-status:s" => { name => 'critical_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, + }); + + $self->{http} = centreon::plugins::http->new(output => $self->{output}); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + if (!defined($self->{option_results}->{command}) || $self->{option_results}->{command} eq '') { + $self->{output}->add_option_msg(short_msg => "Please set command option"); + $self->{output}->option_exit(); + } + if (defined($self->{option_results}->{legacy_password}) && $self->{option_results}->{legacy_password} ne '') { + $self->{http}->add_header(key => 'password', value => $self->{option_results}->{legacy_password}); + } + $self->{http}->set_options(%{$self->{option_results}}); +} + +# Two kind of outputs. +# 1- +# {"header":{"source_id":""},"payload":[{"command":"check_centreon_plugins","lines":[{"message":"OK: Reboot Pending : False | 'value1'=10;;;; 'value2'=10;;;;\r\nlong1\r\nlong2"}],"result":"OK"}]} +# 2- Can be also "int_value". +# { "header":{"source_id":""}, +# "payload": [ +# {"command":"check_drivesize", +# "lines": [ +# {"message":"OK All 1 drive(s) are ok", +# "perf":[ +# {"alias":"C:\\ used", +# "float_value": { +# "critical":44.690621566027403, +# "maximum":49.656246185302734, +# "minimum":0.00000000000000000, +# "unit":"GB", +# "value":21.684593200683594, +# "warning":39.724996947683394} +# }, +# {"alias":"C:\\ used %","float_value":{"critical":90.000000000000000,"maximum":100.00000000000000,"minimum":0.00000000000000000,"unit":"%","value":44.000000000000000,"warning":80.000000000000000}}]}], +# "result":"OK"}]} + +sub nscp_output_perf { + my ($self, %options) = @_; + + $self->{output}->output_add(severity => $options{result}, + short_msg => $options{data}->{message}); + foreach (@{$options{data}->{perf}}) { + my $perf = defined($_->{float_value}) ? $_->{float_value} : $_->{int_value}; + my $printf_format = '%d'; + $printf_format = '%.3f' if (defined($_->{float_value})); + + $self->{output}->perfdata_add(label => $_->{alias}, unit => $perf->{unit}, + value => sprintf($printf_format, $perf->{value}), + warning => defined($perf->{warning}) ? sprintf($printf_format, $perf->{warning}) : undef, + critical => defined($perf->{critical}) ? sprintf($printf_format, $perf->{critical}) : undef, + min => sprintf($printf_format, $perf->{minimum}), + max => sprintf($printf_format, $perf->{maximum}), + ); + } +} + +sub nscp_output_noperf { + my ($self, %options) = @_; + + $self->{output}->output_add(severity => $options{result}, + short_msg => $options{data}->{message}); +} + +sub check_nscp_result { + my ($self, %options) = @_; + + my $decoded; + eval { + $decoded = decode_json($options{content}); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + + my $entry = $decoded->{payload}->[0]; + $entry->{lines}->[0]->{message} =~ s/\r//msg; + if (defined($entry->{lines}->[0]->{perf})) { + $self->nscp_output_perf(result => $entry->{result}, data => $entry->{lines}->[0]); + $self->{output}->display(nolabel => 1); + } else { + $self->nscp_output_noperf(result => $entry->{result}, data => $entry->{lines}->[0]); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + } +} + +sub run { + my ($self, %options) = @_; + + my $uri = URI::Encode->new({encode_reserved => 1}); + my ($encoded_args, $append) = ('', ''); + if (defined($self->{option_results}->{arg})) { + foreach (@{$self->{option_results}->{arg}}) { + $encoded_args .= $append . $uri->encode($_); + $append = '&'; + } + } + + my ($content) = $self->{http}->request(url_path => '/query/' . $self->{option_results}->{command} . '?' . $encoded_args); + $self->check_nscp_result(content => $content); + + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Query NSClient Rest API. + +=over 8 + +=item B<--hostname> + +IP Addr/FQDN of the host + +=item B<--http-peer-addr> + +Set the address you want to connect (Useful if hostname is only a vhost. no ip resolve) + +=item B<--port> + +Port used (Default: 8443) + +=item B<--proto> + +Specify https if needed (Default: 'https') + +=item B<--credentials> + +Specify this option if you access webpage over basic authentification + +=item B<--username> + +Specify username for basic authentification (Mandatory if --credentials is specidied) + +=item B<--password> + +Specify password for basic authentification (Mandatory if --credentials is specidied) + +=item B<--legacy-password> + +Specify password for old authentification system. + +=item B<--proxyurl> + +Proxy URL + +=item B<--proxypac> + +Proxy pac file (can be an url or local file) + +=item B<--timeout> + +Threshold for HTTP timeout (Default: 5) + +=item B<--ssl> + +Specify SSL version (example : 'sslv3', 'tlsv1'...) + +=item B<--command> + +Set command. + +=item B<--arg> + +Set arguments (Multiple option. Example: --arg='arg1') + +=item B<--unknown-status> + +Threshold warning for http response code + +=item B<--warning-status> + +Threshold warning for http response code + +=item B<--critical-status> + +Threshold critical for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') + +=back + +=cut diff --git a/centreon-plugins/apps/nsclient/restapi/plugin.pm b/centreon-plugins/apps/nsclient/restapi/plugin.pm new file mode 100644 index 000000000..90a770dcc --- /dev/null +++ b/centreon-plugins/apps/nsclient/restapi/plugin.pm @@ -0,0 +1,48 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::nsclient::restapi::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_simple); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'query' => 'apps::nsclient::restapi::mode::query', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check nsclient Rest API. + +=cut From d884b1fe3b761bff80a1fa09949d82624fa95609 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 30 Nov 2017 14:27:03 +0100 Subject: [PATCH 27/45] fix port --- centreon-plugins/apps/nsclient/restapi/mode/query.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centreon-plugins/apps/nsclient/restapi/mode/query.pm b/centreon-plugins/apps/nsclient/restapi/mode/query.pm index 2cf3971dd..f6da6dfb3 100644 --- a/centreon-plugins/apps/nsclient/restapi/mode/query.pm +++ b/centreon-plugins/apps/nsclient/restapi/mode/query.pm @@ -38,7 +38,7 @@ sub new { { "hostname:s" => { name => 'hostname' }, "http-peer-addr:s" => { name => 'http_peer_addr' }, - "port:s" => { name => 'port', default => 8433 }, + "port:s" => { name => 'port', default => 8443 }, "proto:s" => { name => 'proto', default => 'https' }, "credentials" => { name => 'credentials' }, "username:s" => { name => 'username' }, From 2f359edf2bd8cdb23851ef27bb911beea9917710 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Thu, 30 Nov 2017 15:40:11 +0100 Subject: [PATCH 28/45] nsclient change default status error --- centreon-plugins/apps/nsclient/restapi/mode/query.pm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/centreon-plugins/apps/nsclient/restapi/mode/query.pm b/centreon-plugins/apps/nsclient/restapi/mode/query.pm index f6da6dfb3..182b763b9 100644 --- a/centreon-plugins/apps/nsclient/restapi/mode/query.pm +++ b/centreon-plugins/apps/nsclient/restapi/mode/query.pm @@ -50,9 +50,9 @@ sub new { "ssl:s" => { name => 'ssl' }, "command:s" => { name => 'command' }, "arg:s@" => { name => 'arg' }, - "unknown-status:s" => { name => 'unknown_status', default => '' }, + "unknown-status:s" => { name => 'unknown_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, "warning-status:s" => { name => 'warning_status' }, - "critical-status:s" => { name => 'critical_status', default => '%{http_code} < 200 or %{http_code} >= 300' }, + "critical-status:s" => { name => 'critical_status', default => '' }, }); $self->{http} = centreon::plugins::http->new(output => $self->{output}); @@ -231,15 +231,16 @@ Set arguments (Multiple option. Example: --arg='arg1') =item B<--unknown-status> -Threshold warning for http response code +Threshold warning for http response code. +(Default: '%{http_code} < 200 or %{http_code} >= 300') =item B<--warning-status> -Threshold warning for http response code +Threshold warning for http response code. =item B<--critical-status> -Threshold critical for http response code (Default: '%{http_code} < 200 or %{http_code} >= 300') +Threshold critical for http response code. =back From d83ecf7d2b364e912c751c2dc0ed8a13dd721ca9 Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Thu, 30 Nov 2017 16:52:02 +0100 Subject: [PATCH 29/45] + Add sqlstring mode --- .../common/protocols/sql/mode/sqlstring.pm | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 centreon-plugins/centreon/common/protocols/sql/mode/sqlstring.pm diff --git a/centreon-plugins/centreon/common/protocols/sql/mode/sqlstring.pm b/centreon-plugins/centreon/common/protocols/sql/mode/sqlstring.pm new file mode 100644 index 000000000..827c99918 --- /dev/null +++ b/centreon-plugins/centreon/common/protocols/sql/mode/sqlstring.pm @@ -0,0 +1,217 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::protocols::sql::mode::sqlstring; + +use base qw(centreon::plugins::templates::counter); +use strict; +use warnings; + +my $instance_mode; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'rows', type => 1, message_multiple => "SQL Query is OK" }, + ]; + + $self->{maps_counters}->{rows} = [ + { label => 'string', threshold => 0, set => { + key_values => [ { name => 'key_field' }, { name => 'value_field' } ], + closure_custom_calc => $self->can('custom_string_calc'), + closure_custom_output => $self->can('custom_string_output'), + closure_custom_threshold_check => $self->can('custom_string_threshold'), + closure_custom_perfdata => sub { return 0; }, + } + }, + ]; +} + +sub custom_string_calc { + my ($self, %options) = @_; + + $self->{result_values}->{key_field} = $options{new_datas}->{$self->{instance} . '_key_field'}; + $self->{result_values}->{value_field} = $options{new_datas}->{$self->{instance} . '_value_field'}; + + return 0; +} + +sub custom_string_output { + my ($self, %options) = @_; + + my $msg; + my $message; + + if (defined($instance_mode->{option_results}->{printf_format}) && $instance_mode->{option_results}->{printf_format} ne '') { + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + $msg = sprintf("$instance_mode->{option_results}->{printf_format}", eval $instance_mode->{option_results}->{printf_value}); + }; + } else { + $msg = sprintf("'%s'", $self->{result_values}->{value_field}); + } + + if (defined($message)) { + $self->{output}->output_add(long_msg => 'output value issue: ' . $message); + } + return $msg; +} + +sub custom_string_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_string}) && $instance_mode->{option_results}->{critical_string} ne '' && + eval "$instance_mode->{option_results}->{critical_string}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_string}) && $instance_mode->{option_results}->{warning_string} ne '' && + eval "$instance_mode->{option_results}->{warning_string}") { + $status = 'warning'; + } + }; + + if (defined($message)) { + $self->{output}->output_add(long_msg => 'threshold regex issue: ' . $message); + } + + return $status; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "sql-statement:s" => { name => 'sql_statement' }, + "key-column:s" => { name => 'key_column' }, + "value-column:s" => { name => 'value_column' }, + "warning-string:s" => { name => 'warning_string', default => '' }, + "critical-string:s" => { name => 'critical_string', default => '' }, + "printf-format:s" => { name => 'printf_format' }, + "printf-value:s" => { name => 'printf_value' }, + }); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + #$self->SUPER::init(%options); + $self->SUPER::check_options(%options); + $instance_mode = $self; + + if (!defined($instance_mode->{option_results}->{sql_statement}) || $instance_mode->{option_results}->{sql_statement} eq '') { + $instance_mode->{output}->add_option_msg(short_msg => "Need to specify '--sql-statement' option."); + $instance_mode->{output}->option_exit(); + } + + $instance_mode->change_macros(); +} + +sub change_macros { + my ($self, %options) = @_; + foreach (('warning_string', 'critical_string')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; + } + } +} + +sub manage_selection { + my ($self, %options) = @_; + $self->{sql} = $options{sql}; + $self->{sql}->connect(); + $self->{sql}->query(query => $self->{option_results}->{sql_statement}); + $self->{rows} = {}; + my $row_count = 0; + + while (my $row = $self->{sql}->fetchrow_hashref()) { + if (!defined($self->{option_results}->{key_column})) { + $self->{rows}->{$self->{option_results}->{value_column} . $row_count} = { key_field => $row->{$self->{option_results}->{value_column}}, + value_field => $row->{$self->{option_results}->{value_column}}}; + $row_count++; + } else { + $self->{rows}->{$self->{option_results}->{key_column} . $row_count} = { key_field => $row->{$self->{option_results}->{key_column}}, + value_field => $row->{$self->{option_results}->{value_column}}}; + $row_count++; + } + } + + if (scalar(keys %{$self->{rows}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No row returned or --key-column/--value-column do not correctly match selected field"); + $self->{output}->option_exit(); + } + +} + +1; + +__END__ + +=head1 MODE + +Check SQL statement to query string pattern (You cannot have more than to fiels in select) + +=over 8 + +=item B<--sql-statement> + +SQL statement that returns a string. + +=item B<--key-column> + +Key column (must be one of the selected field). NOT mandatory if you select only one field + +=item B<--value-column> + +Value column (must be one of the selected field). MANDATORY + +=item B<--printf-format> + +Specify a custom output message relying on printf formatting + +=item B<--printf-value> + +Specify scalar used to replace in printf +(Can be: $self->{result_values}->{key_field}, $self->{result_values}->{value_field}) + +=item B<--warning-string> + +Set warning condition (if statement syntax) for status evaluation. +(Can be: %{key_field}, %{value_field}) +e.g --warning-string '%{key_field} eq 'Central' && %{value_field} =~ /127.0.0.1/' + +=item B<--critical-string> + +Set critical condition (if statement syntax) for status evaluation. +(Can be: %{key_field} or %{value_field}) + +=back + +=cut From 849550172173c6c70160a6e335feb6bf4de7b8ec Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Thu, 30 Nov 2017 16:52:49 +0100 Subject: [PATCH 30/45] + add sqlstring to plugin.pm --- centreon-plugins/database/mssql/plugin.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/centreon-plugins/database/mssql/plugin.pm b/centreon-plugins/database/mssql/plugin.pm index f2e7a8761..a114cffd0 100644 --- a/centreon-plugins/database/mssql/plugin.pm +++ b/centreon-plugins/database/mssql/plugin.pm @@ -43,6 +43,7 @@ sub new { 'dead-locks' => 'database::mssql::mode::deadlocks', 'backup-age' => 'database::mssql::mode::backupage', 'sql' => 'centreon::common::protocols::sql::mode::sql', + 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', ); return $self; From 8d943f7f0e630bfecc27b700b2c94fff208d1eaf Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Thu, 30 Nov 2017 16:53:30 +0100 Subject: [PATCH 31/45] + add sqlstring to plugin.pm --- centreon-plugins/database/mysql/plugin.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/centreon-plugins/database/mysql/plugin.pm b/centreon-plugins/database/mysql/plugin.pm index f9ac4003f..2bd8692f1 100644 --- a/centreon-plugins/database/mysql/plugin.pm +++ b/centreon-plugins/database/mysql/plugin.pm @@ -47,7 +47,9 @@ sub new { 'threads-connected' => 'database::mysql::mode::threadsconnected', 'uptime' => 'database::mysql::mode::uptime', 'tables-size' => 'database::mysql::mode::tablessize', + 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', ); + $self->{sql_modes}{mysqlcmd} = 'database::mysql::mysqlcmd'; return $self; From 2ef4d6637dc87a3bdda91b224107027a6bf713ce Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Thu, 30 Nov 2017 16:53:54 +0100 Subject: [PATCH 32/45] + add sqlstring to plugin.pm --- centreon-plugins/database/oracle/plugin.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/centreon-plugins/database/oracle/plugin.pm b/centreon-plugins/database/oracle/plugin.pm index ad0cb4bae..3c9ad153a 100644 --- a/centreon-plugins/database/oracle/plugin.pm +++ b/centreon-plugins/database/oracle/plugin.pm @@ -48,6 +48,7 @@ sub new { 'tablespace-usage' => 'database::oracle::mode::tablespaceusage', 'session-usage' => 'database::oracle::mode::sessionusage', 'sql' => 'centreon::common::protocols::sql::mode::sql', + 'sql-string' => 'centreon::common::protocols::sql::mode::sqlstring', 'tnsping' => 'database::oracle::mode::tnsping', ); From 217384bd38a09c20c0162e5254094e5b474b4918 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Fri, 1 Dec 2017 10:24:32 +0100 Subject: [PATCH 33/45] move snmp plugin --- .../protocols/snmp}/plugin.pm | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename centreon-plugins/{snmp_standard => apps/protocols/snmp}/plugin.pm (69%) diff --git a/centreon-plugins/snmp_standard/plugin.pm b/centreon-plugins/apps/protocols/snmp/plugin.pm similarity index 69% rename from centreon-plugins/snmp_standard/plugin.pm rename to centreon-plugins/apps/protocols/snmp/plugin.pm index 2438cdf33..1e6460ab3 100644 --- a/centreon-plugins/snmp_standard/plugin.pm +++ b/centreon-plugins/apps/protocols/snmp/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package snmp_standard::plugin; +package apps::protocols::snmp::plugin; use strict; use warnings; @@ -31,11 +31,11 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( - 'numeric-value' => 'snmp_standard::mode::numericvalue', - 'string-value' => 'snmp_standard::mode::stringvalue', - 'dynamic-command' => 'snmp_standard::mode::dynamiccommand', - 'uptime' => 'snmp_standard::mode::uptime', - ); + 'dynamic-command' => 'snmp_standard::mode::dynamiccommand', + 'numeric-value' => 'snmp_standard::mode::numericvalue', + 'string-value' => 'snmp_standard::mode::stringvalue', + 'uptime' => 'snmp_standard::mode::uptime', + ); return $self; } @@ -46,6 +46,6 @@ __END__ =head1 PLUGIN DESCRIPTION -Check SNMP values (string, numeric or execute commands) or standard (uptime). +Check SNMP values (string, numeric or execute commands). =cut From 90e329a5e58c2dd994d7c204363b64a93421e440 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 4 Dec 2017 16:00:12 +0100 Subject: [PATCH 34/45] enhance jmx mode with statefile for proxy mode --- .../apps/java/hibernate/jmx/mode/stats.pm | 2 +- .../apps/java/solr/jmx/mode/cacheusage.pm | 2 +- .../java/solr/jmx/mode/requesthandlerusage.pm | 2 +- .../apps/java/zookeeper/jmx/mode/stats.pm | 2 +- .../apps/protocols/jmx/mode/numericvalue.pm | 2 +- .../apps/tomcat/jmx/mode/connectorusage.pm | 2 +- .../apps/tomcat/jmx/mode/datasourceusage.pm | 2 +- .../apps/tomcat/jmx/mode/webappssessions.pm | 2 +- .../centreon/common/jvm/mode/classcount.pm | 188 +++++------------- .../centreon/common/jvm/mode/gcusage.pm | 4 +- .../common/jvm/mode/memorydetailed.pm | 2 + .../centreon/common/jvm/mode/threads.pm | 185 +++++------------ .../common/protocols/jmx/custom/jolokia.pm | 8 + 13 files changed, 120 insertions(+), 283 deletions(-) diff --git a/centreon-plugins/apps/java/hibernate/jmx/mode/stats.pm b/centreon-plugins/apps/java/hibernate/jmx/mode/stats.pm index fad0cd08f..52a67d7b3 100644 --- a/centreon-plugins/apps/java/hibernate/jmx/mode/stats.pm +++ b/centreon-plugins/apps/java/hibernate/jmx/mode/stats.pm @@ -148,7 +148,7 @@ sub manage_selection { $self->{output}->option_exit(); } - $self->{cache_name} = "hibernate_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "hibernate_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/java/solr/jmx/mode/cacheusage.pm b/centreon-plugins/apps/java/solr/jmx/mode/cacheusage.pm index 0f8a1fe05..acbb09e12 100644 --- a/centreon-plugins/apps/java/solr/jmx/mode/cacheusage.pm +++ b/centreon-plugins/apps/java/solr/jmx/mode/cacheusage.pm @@ -131,7 +131,7 @@ sub manage_selection { $self->{output}->option_exit(); } - $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/java/solr/jmx/mode/requesthandlerusage.pm b/centreon-plugins/apps/java/solr/jmx/mode/requesthandlerusage.pm index 30f0cd6be..9f6814e7f 100644 --- a/centreon-plugins/apps/java/solr/jmx/mode/requesthandlerusage.pm +++ b/centreon-plugins/apps/java/solr/jmx/mode/requesthandlerusage.pm @@ -128,7 +128,7 @@ sub manage_selection { $self->{output}->option_exit(); } - $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "solr_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/java/zookeeper/jmx/mode/stats.pm b/centreon-plugins/apps/java/zookeeper/jmx/mode/stats.pm index 812dd2ee2..6b98b318e 100644 --- a/centreon-plugins/apps/java/zookeeper/jmx/mode/stats.pm +++ b/centreon-plugins/apps/java/zookeeper/jmx/mode/stats.pm @@ -141,7 +141,7 @@ sub manage_selection { $self->{output}->option_exit(); } - $self->{cache_name} = "zookeeper_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "zookeeper_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/protocols/jmx/mode/numericvalue.pm b/centreon-plugins/apps/protocols/jmx/mode/numericvalue.pm index 45f1e3ffb..9e48b2c8f 100644 --- a/centreon-plugins/apps/protocols/jmx/mode/numericvalue.pm +++ b/centreon-plugins/apps/protocols/jmx/mode/numericvalue.pm @@ -142,7 +142,7 @@ sub check_value { if ($self->{attributes}->{type} =~ /^counter$/i) { if (!defined($self->{datas})) { $self->{datas} = {}; - $self->{statefile_cache}->read(statefile => "jmxstandard_" . $self->{mode} . '_' . md5_hex($self->{connector}->{url} . ' ' . $self->{option_results}->{mbean_pattern})); + $self->{statefile_cache}->read(statefile => "jmxstandard_" . $self->{mode} . '_' . md5_hex($self->{connector}->get_connection_info() . ' ' . $self->{option_results}->{mbean_pattern})); } my $old_timestamp = $self->{statefile_cache}->get(name => 'timestamp'); diff --git a/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm b/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm index 80aa205c8..4ab1dedbc 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/connectorusage.pm @@ -213,7 +213,7 @@ sub manage_selection { $self->{tomcatconnector}->{$connector} = { %{$self->{tomcatconnector}->{$connector}}, %{$result->{$key}} }; } - $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm index 80e60cfb6..b1360f721 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/datasourceusage.pm @@ -189,7 +189,7 @@ sub manage_selection { }; } - $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm b/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm index b1f36813a..165826a02 100644 --- a/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm +++ b/centreon-plugins/apps/tomcat/jmx/mode/webappssessions.pm @@ -184,7 +184,7 @@ sub manage_selection { }; } - $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "tomcat_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } diff --git a/centreon-plugins/centreon/common/jvm/mode/classcount.pm b/centreon-plugins/centreon/common/jvm/mode/classcount.pm index 9558c4260..9282f35c5 100644 --- a/centreon-plugins/centreon/common/jvm/mode/classcount.pm +++ b/centreon-plugins/centreon/common/jvm/mode/classcount.pm @@ -20,168 +20,79 @@ package centreon::common::jvm::mode::classcount; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::counter); use strict; use warnings; -use centreon::plugins::values; -use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); -my $instance_mode; +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, + ]; -my $maps_counters = { - class => { - '000_current' => { set => { key_values => [ { name => 'current' } ], - output_template => 'Current : %s', - perfdatas => [ - { label => 'current', value => 'current_absolute', template => '%s', min => 0 }, - ], - } - }, - '001_loaded' => { set => { key_values => [ { name => 'loaded', diff => 1 } ], - output_template => 'Loaded : %s', - perfdatas => [ - { label => 'loaded', value => 'loaded_absolute', template => '%s', min => 0 }, - ], - } - }, - '003_unloaded' => { set => { key_values => [ { name => 'unloaded', diff => 1 } ], - output_template => 'Unloaded : %s', - perfdatas => [ - { label => 'unloaded', value => 'unloaded_absolute', template => '%s', min => 0 }, - ], - } - }, + $self->{maps_counters}->{global} = [ + { label => 'current', set => { + key_values => [ { name => 'LoadedClassCount' } ], + output_template => 'Current : %s', + perfdatas => [ + { label => 'current', value => 'LoadedClassCount_absolute', template => '%s', min => 0 }, + ], + } }, -}; + { label => 'loaded', set => { + key_values => [ { name => 'TotalLoadedClassCount', diff => 1 } ], + output_template => 'Loaded : %s', + perfdatas => [ + { label => 'loaded', value => 'TotalLoadedClassCount_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'unloaded', set => { + key_values => [ { name => 'UnloadedClassCount', diff => 1 } ], + output_template => 'Unloaded : %s', + perfdatas => [ + { label => 'unloaded', value => 'UnloadedClassCount_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return "Class "; +} sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - - foreach my $key (('class')) { - foreach (keys %{$maps_counters->{$key}}) { - my ($id, $name) = split /_/; - if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) { - $options{options}->add_options(arguments => { - 'warning-' . $name . ':s' => { name => 'warning-' . $name }, - 'critical-' . $name . ':s' => { name => 'critical-' . $name }, - }); - } - $maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new( - statefile => $self->{statefile_value}, - output => $self->{output}, perfdata => $self->{perfdata}, - label => $name); - $maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}}); - } - } return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - foreach my $key (('class')) { - foreach (keys %{$maps_counters->{$key}}) { - $maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results}); - } - } - - $self->{statefile_value}->check_options(%options); - $instance_mode = $self; - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } -} - -sub run { - my ($self, %options) = @_; - $self->{connector} = $options{custom}; - - $self->manage_selection(); - - $self->{new_datas} = {}; - $self->{statefile_value}->read(statefile => "jvm_standard_" . $self->{mode} . '_' . md5_hex($self->{connector}->{url})); - $self->{new_datas}->{last_timestamp} = time(); - - my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); - my @exits; - foreach (sort keys %{$maps_counters->{class}}) { - my $obj = $maps_counters->{class}->{$_}->{obj}; - $obj->set(instance => 'global'); - - my ($value_check) = $obj->execute(values => $self->{global}, - new_datas => $self->{new_datas}); - - if ($value_check != 0) { - $long_msg .= $long_msg_append . $obj->output_error(); - $long_msg_append = ', '; - next; - } - my $exit2 = $obj->threshold_check(); - push @exits, $exit2; - - my $output = $obj->output(); - $long_msg .= $long_msg_append . $output; - $long_msg_append = ', '; - - if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { - $short_msg .= $short_msg_append . $output; - $short_msg_append = ', '; - } - - $obj->perfdata(); - } - - my $exit = $self->{output}->get_most_critical(status => [ @exits ]); - if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { - $self->{output}->output_add(severity => $exit, - short_msg => "Class $short_msg" - ); - } else { - $self->{output}->output_add(short_msg => "Class $long_msg"); - } - - $self->{statefile_value}->write(data => $self->{new_datas}); - $self->{output}->display(); - $self->{output}->exit(); -} - sub manage_selection { my ($self, %options) = @_; my $mbean = 'java.lang:type=ClassLoading'; - $self->{request} = [ + my $request = [ { mbean => $mbean, attributes => [ { name => 'UnloadedClassCount' }, { name => 'LoadedClassCount' }, { name => 'TotalLoadedClassCount' } ] }, ]; - my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); + my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); + + $self->{global} = { %{$result->{$mbean}} }; - $self->{global} = {}; - $self->{global}->{unloaded} = $result->{$mbean}->{UnloadedClassCount} if (defined($result->{$mbean}->{UnloadedClassCount})); - $self->{global}->{loaded} = $result->{$mbean}->{TotalLoadedClassCount} if (defined($result->{$mbean}->{TotalLoadedClassCount})); - $self->{global}->{current} = $result->{$mbean}->{LoadedClassCount} if (defined($result->{$mbean}->{LoadedClassCount})); + $self->{cache_name} = "jvm_standard_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; @@ -194,6 +105,11 @@ Check Java Class Loading Mbean. =over 8 +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='current' + =item B<--warning-*> Threshold warning. @@ -206,4 +122,4 @@ Can be: 'unloaded', 'loaded', 'current'. =back -=cut \ No newline at end of file +=cut diff --git a/centreon-plugins/centreon/common/jvm/mode/gcusage.pm b/centreon-plugins/centreon/common/jvm/mode/gcusage.pm index 129f2f2f3..786add013 100644 --- a/centreon-plugins/centreon/common/jvm/mode/gcusage.pm +++ b/centreon-plugins/centreon/common/jvm/mode/gcusage.pm @@ -100,7 +100,7 @@ sub manage_selection { $self->{output}->option_exit(); } - $self->{cache_name} = "jvm_standard_" . $self->{mode} . '_' . md5_hex($options{custom}->{url}) . '_' . + $self->{cache_name} = "jvm_standard_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); } @@ -136,4 +136,4 @@ Can be: 'count', 'time' (ms). =back -=cut \ No newline at end of file +=cut diff --git a/centreon-plugins/centreon/common/jvm/mode/memorydetailed.pm b/centreon-plugins/centreon/common/jvm/mode/memorydetailed.pm index c9817e8e4..62ed2883d 100644 --- a/centreon-plugins/centreon/common/jvm/mode/memorydetailed.pm +++ b/centreon-plugins/centreon/common/jvm/mode/memorydetailed.pm @@ -36,7 +36,9 @@ my %mapping_memory = ( 'PS Perm Gen' => 'permanent', 'Perm Gen' => 'permanent', 'Metaspace' => 'permanent', + 'JIT data cache' => 'permanent', 'Code Cache' => 'code', + 'JIT Code Cache' => 'code', 'CMS Old Gen' => 'tenured', 'PS Old Gen' => 'tenured', 'Tenured Gen' => 'tenured', diff --git a/centreon-plugins/centreon/common/jvm/mode/threads.pm b/centreon-plugins/centreon/common/jvm/mode/threads.pm index c5e913ffa..544f0d21e 100644 --- a/centreon-plugins/centreon/common/jvm/mode/threads.pm +++ b/centreon-plugins/centreon/common/jvm/mode/threads.pm @@ -20,168 +20,79 @@ package centreon::common::jvm::mode::threads; -use base qw(centreon::plugins::mode); +use base qw(centreon::plugins::templates::counter); use strict; use warnings; -use centreon::plugins::values; -use centreon::plugins::statefile; use Digest::MD5 qw(md5_hex); -my $instance_mode; +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, + ]; -my $maps_counters = { - threads => { - '000_active' => { set => { key_values => [ { name => 'active' } ], - output_template => 'Active : %s', - perfdatas => [ - { label => 'active', value => 'active_absolute', template => '%s', min => 0 }, - ], - } - }, - '001_started' => { set => { key_values => [ { name => 'started', diff => 1 } ], - output_template => 'Started : %s', - perfdatas => [ - { label => 'started', value => 'started_absolute', template => '%s', min => 0 }, - ], - } - }, - '003_daemon' => { set => { key_values => [ { name => 'daemon' } ], - output_template => 'Daemon : %s', - perfdatas => [ - { label => 'daemon', value => 'daemon_absolute', template => '%s', min => 0 }, - ], - } - }, + $self->{maps_counters}->{global} = [ + { label => 'active', set => { + key_values => [ { name => 'ThreadCount' } ], + output_template => 'Active : %s', + perfdatas => [ + { label => 'active', value => 'ThreadCount_absolute', template => '%s', min => 0 }, + ], + } }, -}; + { label => 'started', set => { + key_values => [ { name => 'TotalStartedThreadCount', diff => 1 } ], + output_template => 'Started : %s', + perfdatas => [ + { label => 'started', value => 'TotalStartedThreadCount_absolute', template => '%s', min => 0 }, + ], + } + }, + { label => 'daemon', set => { + key_values => [ { name => 'DaemonThreadCount' } ], + output_template => 'Daemon : %s', + perfdatas => [ + { label => 'daemon', value => 'DaemonThreadCount_absolute', template => '%s', min => 0 }, + ], + } + }, + ]; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return "Threads "; +} sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $self->{version} = '1.0'; $options{options}->add_options(arguments => { }); - $self->{statefile_value} = centreon::plugins::statefile->new(%options); - - foreach my $key (('threads')) { - foreach (keys %{$maps_counters->{$key}}) { - my ($id, $name) = split /_/; - if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) { - $options{options}->add_options(arguments => { - 'warning-' . $name . ':s' => { name => 'warning-' . $name }, - 'critical-' . $name . ':s' => { name => 'critical-' . $name }, - }); - } - $maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new( - statefile => $self->{statefile_value}, - output => $self->{output}, perfdata => $self->{perfdata}, - label => $name); - $maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}}); - } - } return $self; } -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - foreach my $key (('threads')) { - foreach (keys %{$maps_counters->{$key}}) { - $maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results}); - } - } - - $self->{statefile_value}->check_options(%options); - $instance_mode = $self; - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } -} - -sub run { - my ($self, %options) = @_; - $self->{connector} = $options{custom}; - - $self->manage_selection(); - - $self->{new_datas} = {}; - $self->{statefile_value}->read(statefile => "jvm_standard_" . $self->{mode} . '_' . md5_hex($self->{connector}->{url})); - $self->{new_datas}->{last_timestamp} = time(); - - my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', ''); - my @exits; - foreach (sort keys %{$maps_counters->{threads}}) { - my $obj = $maps_counters->{threads}->{$_}->{obj}; - $obj->set(instance => 'global'); - - my ($value_check) = $obj->execute(values => $self->{global}, - new_datas => $self->{new_datas}); - - if ($value_check != 0) { - $long_msg .= $long_msg_append . $obj->output_error(); - $long_msg_append = ', '; - next; - } - my $exit2 = $obj->threshold_check(); - push @exits, $exit2; - - my $output = $obj->output(); - $long_msg .= $long_msg_append . $output; - $long_msg_append = ', '; - - if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) { - $short_msg .= $short_msg_append . $output; - $short_msg_append = ', '; - } - - $obj->perfdata(); - } - - my $exit = $self->{output}->get_most_critical(status => [ @exits ]); - if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { - $self->{output}->output_add(severity => $exit, - short_msg => "Threads $short_msg" - ); - } else { - $self->{output}->output_add(short_msg => "Threads $long_msg"); - } - - $self->{statefile_value}->write(data => $self->{new_datas}); - $self->{output}->display(); - $self->{output}->exit(); -} - sub manage_selection { my ($self, %options) = @_; my $mbean = 'java.lang:type=Threading'; - $self->{request} = [ - { mbean => $mbean, attributes => [ { name => 'TotalStartedThreadCount' }, { name => 'ThreadCount' }, { name => 'DaemonThreadCount' } ] }, + my $request = [ + { mbean => $mbean, attributes => [ { name => 'TotalStartedThreadCount' }, { name => 'ThreadCount' }, { name => 'DaemonThreadCount' } ] }, ]; - my $result = $self->{connector}->get_attributes(request => $self->{request}, nothing_quit => 1); + my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); + + $self->{global} = { %{$result->{$mbean}} }; - $self->{global} = {}; - $self->{global}->{started} = $result->{$mbean}->{TotalStartedThreadCount} if (defined($result->{$mbean}->{TotalStartedThreadCount})); - $self->{global}->{active} = $result->{$mbean}->{ThreadCount} if (defined($result->{$mbean}->{ThreadCount})); - $self->{global}->{daemon} = $result->{$mbean}->{DaemonThreadCount} if (defined($result->{$mbean}->{DaemonThreadCount})); + $self->{cache_name} = "jvm_standard_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); } 1; @@ -206,4 +117,4 @@ Can be: 'active', 'started', 'daemon'. =back -=cut \ No newline at end of file +=cut diff --git a/centreon-plugins/centreon/common/protocols/jmx/custom/jolokia.pm b/centreon-plugins/centreon/common/protocols/jmx/custom/jolokia.pm index fb1f83915..2d1a96b9d 100644 --- a/centreon-plugins/centreon/common/protocols/jmx/custom/jolokia.pm +++ b/centreon-plugins/centreon/common/protocols/jmx/custom/jolokia.pm @@ -146,6 +146,14 @@ sub check_options { return 1; } +sub get_connection_info { + my ($self, %options) = @_; + + my $connection_info = $self->{url}; + $connection_info .= '_' . $self->{proxy_url} if (defined($self->{proxy_url})); + return $connection_info; +} + sub connect { my ($self, %options) = @_; From 584289b28d9ae0628263682e177f8d715a061f06 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Mon, 4 Dec 2017 16:26:28 +0100 Subject: [PATCH 35/45] add an example for nsclient --- centreon-plugins/docs/en/user/guide.rst | 21 ++++++++++++++++----- centreon-plugins/docs/fr/user/guide.rst | 11 +++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/centreon-plugins/docs/en/user/guide.rst b/centreon-plugins/docs/en/user/guide.rst index 992736529..36ad83640 100644 --- a/centreon-plugins/docs/en/user/guide.rst +++ b/centreon-plugins/docs/en/user/guide.rst @@ -1119,33 +1119,44 @@ Design of configuration file Command line, output, threshold ... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Sample command : +Sample command: :: /usr/lib/nagios/plugins/centreon_plugins.pl --plugin database::mysql::plugin --dyn-mode apps::centreon::sql::mode::multiservices --host localhost --username centreon --password c3ntreon --config-file '/root/global-services.json' --verbose -Sample output : +Sample output: :: OK: Hosts state summary [up:4][down:2][unreachable:0] - Services state summary [ok:4][warning:0][critical:2][unknown:0] - Nothing special on groups | -Perfdatas : +Perfdatas: :: 'total_host_up'=4;;;0; 'total_host_down'=2;;;0; 'total_host_unreachable'=0;;;0; 'total_host_ok'=4;;;0; 'total_host_warning'=0;;;0; 'total_host_critical'=2;;;0; 'total_host_unknown'=0;;;0; 'host_up_ESX'=4;;;0; 'host_down_ESX'=0;;;0; 'host_unreachable_ESX'=0;;;0; 'service_ok_ESX'=4;;;0; 'service_warning_ESX'=0;;;0; 'service_critical_ESX'=0;;;0; 'service_unknown_ESX'=0;;;0; 'host_up_XIVO'=0;;;0; 'host_down_XIVO'=2;;;0; 'host_unreachable_XIVO'=0;;;0; 'service_ok_XIVO'=0;;;0; 'service_warning_XIVO'=0;;;0; 'service_critical_XIVO'=2;;;0; 'service_unknown_XIVO'=0;;;0; -Verbose mode (with display details set as true) : +Verbose mode (with display details set as true): :: Group 'ESX': HOSTS: [up: 4 (clus-esx-n1.com - clus-esx-n2.com - clus-esx-n3.com - clus-esx-n4.com)][down: 0][unreachable: 0] - SERVICES: [ok: 4 (clus-esx-n1.com/Esx-Status - clus-esx-n2.com/Esx-Status - clus-esx-n3.com/Esx-Status - clus-esx-n4.com/Esx-Status)][warning: 0][critical: 0][unknown: 0] Group 'XIVO': HOSTS: [up: 0][down: 2 (srvi-xivo-n1 - srvi-xivo-n2)][unreachable: 0] - SERVICES: [ok: 0][warning: 0][critical: 2 (srvi-xivo-n1/Ping - srvi-xivo-n2/Ping)][unknown: 0] -Concerning the threshold, you can use some example below : +Concerning the threshold, you can use some example below: :: --critical-total '%{total_down} > 4' --critical-groups '%{instance} eq 'ESX' && %{unknown} > 5' + +-------- +NSClient +-------- + +You can monitor Windows/Linux system with the Rest API of NSClient. Commands and arguments are the same than NRPE (look the NSClient documentation for more informations): + +:: + + $ perl centreon_plugins.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname="10.30.2.10" --port=443 --legacy-password=centreon --command=check_drivesize --arg="drive=*" --arg="perf-config=used(unit:B)used %(ignored:true)" --arg="filter=type = 'fixed' and name not regexp '.*yst.*'" --arg="warning=total_used>80%" --arg="critical=total_used>90%" + OK All 2 drive(s) are ok | '\\?\Volume{7cd2d555-9868-11e7-8199-806e6f6e6963}\ used'=289468416.000B;293598003.000;330297753.000;0.000;366997504.000 'C:\ used'=23285907456.000B;42654390681.000;47986189516.000;0.000;53317988352.000 diff --git a/centreon-plugins/docs/fr/user/guide.rst b/centreon-plugins/docs/fr/user/guide.rst index b31d74e55..706615686 100644 --- a/centreon-plugins/docs/fr/user/guide.rst +++ b/centreon-plugins/docs/fr/user/guide.rst @@ -1150,3 +1150,14 @@ Voici la manière de définir les seuils (total_statut pour les warning/critical :: --critical-total '%{total_down} > 4' --critical-groups '%{instance} eq 'ESX' && %{unknown} > 5' + +-------- +NSClient +-------- + +Vous pouvez superviser des systèmes Windows/Linux via l'API Rest de NSClient. Les commandes et arguments sont les mêmes que via NRPE (veuillez lire la documentation NSClient pour plus d'informations) : + +:: + + $ perl centreon_plugins.pl --plugin=apps::nsclient::restapi::plugin --mode=query --hostname="10.30.2.10" --port=443 --legacy-password=centreon --command=check_drivesize --arg="drive=*" --arg="perf-config=used(unit:B)used %(ignored:true)" --arg="filter=type = 'fixed' and name not regexp '.*yst.*'" --arg="warning=total_used>80%" --arg="critical=total_used>90%" + OK All 2 drive(s) are ok | '\\?\Volume{7cd2d555-9868-11e7-8199-806e6f6e6963}\ used'=289468416.000B;293598003.000;330297753.000;0.000;366997504.000 'C:\ used'=23285907456.000B;42654390681.000;47986189516.000;0.000;53317988352.000 From 2b81a461a688a3b2670cb1aba0a6a5e458155212 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 5 Dec 2017 10:46:06 +0100 Subject: [PATCH 36/45] working on jboss mode --- .../java/jboss/jmx/mode/datasourceusage.pm | 164 ++++++++++++++++++ .../java/jboss/jmx/mode/listdatasources.pm | 123 +++++++++++++ .../apps/java/jboss/jmx/plugin.pm | 50 ++++++ 3 files changed, 337 insertions(+) create mode 100644 centreon-plugins/apps/java/jboss/jmx/mode/datasourceusage.pm create mode 100644 centreon-plugins/apps/java/jboss/jmx/mode/listdatasources.pm create mode 100644 centreon-plugins/apps/java/jboss/jmx/plugin.pm diff --git a/centreon-plugins/apps/java/jboss/jmx/mode/datasourceusage.pm b/centreon-plugins/apps/java/jboss/jmx/mode/datasourceusage.pm new file mode 100644 index 000000000..7888a1869 --- /dev/null +++ b/centreon-plugins/apps/java/jboss/jmx/mode/datasourceusage.pm @@ -0,0 +1,164 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::java::jboss::jmx::mode::datasourceusage; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'datasource', type => 1, cb_prefix_output => 'prefix_ds_output', message_multiple => 'All datasources are ok' }, + ]; + + $self->{maps_counters}->{datasource} = [ + { label => 'active-con', set => { + key_values => [ { name => 'ActiveCount' }, { name => 'display' } ], + output_template => 'Current Active Connections : %s', + perfdatas => [ + { label => 'active_con', value => 'ActiveCount_absolute', template => '%s', min => 0, + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'available-con', set => { + key_values => [ { name => 'AvailableCount' }, { name => 'display' } ], + output_template => 'Current Available Connections : %s', + perfdatas => [ + { label => 'available_con', value => 'AvailableCount_absolute', template => '%s', min => 0, + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'in-use-con', set => { + key_values => [ { name => 'InUseCount' }, { name => 'display' } ], + output_template => 'Current In Use Connections : %s', + perfdatas => [ + { label => 'in_use_con', value => 'InUseCount_absolute', template => '%s', min => 0, + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + { label => 'created-con', set => { + key_values => [ { name => 'CreatedCount', diff => 1 }, { name => 'display' } ], + output_template => 'Created Connections : %s', + perfdatas => [ + { label => 'created_con', value => 'CreatedCount_absolute', template => '%s', min => 0, + label_extra_instance => 1, instance_use => 'display_absolute' }, + ], + } + }, + ]; +} + +sub prefix_ds_output { + my ($self, %options) = @_; + + return "Datasource '" . $options{instance_value}->{display} . "' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $request = [ + { mbean => "jboss.jca:name=*,service=ManagedConnectionPool", attributes => + [ { name => 'AvailableConnectionCount' }, { name => 'ConnectionCount' }, { name => 'ConnectionCreatedCount' }, { name => 'InUseConnectionCount' } ] }, + { mbean => "jboss.as:data-source=*,statistics=pool,subsystem=datasources", attributes => + [ { name => 'AvailableCount' }, { name => 'ActiveCount' }, { name => 'CreatedCount' }, { name => 'InUseCount' } ] }, + ]; + + my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1); + + $self->{datasource} = {}; + foreach my $key (keys %$result) { + $key =~ /(?:[:,])(?:name|data-source)=(.*?)(?:,|$)/; + my $ds_name = $1; + $ds_name =~ s/^"(.*)"$/$1/; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $ds_name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $ds_name . "': no matching filter.", debug => 1); + next; + } + + $self->{datasource}->{$ds_name} = { + display => $ds_name, + AvailableCount => defined($result->{$key}->{AvailableConnectionCount}) ? $result->{$key}->{AvailableConnectionCount} : $result->{$key}->{AvailableCount}, + ActiveCount => defined($result->{$key}->{ConnectionCount}) ? $result->{$key}->{ConnectionCount} : $result->{$key}->{ActiveCount}, + CreatedCount => defined($result->{$key}->{ConnectionCreatedCount}) ? $result->{$key}->{ConnectionCreatedCount} : $result->{$key}->{CreatedCount}, + InUseCount => defined($result->{$key}->{InUseConnectionCount}) ? $result->{$key}->{InUseConnectionCount} : $result->{$key}->{InUseCount}, + }; + } + + $self->{cache_name} = "jboss_" . $self->{mode} . '_' . md5_hex($options{custom}->get_connection_info()) . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check data sources usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='num-active' + +=item B<--filter-name> + +Filter datasource name (can be a regexp). + +=item B<--warning-*> + +Threshold warning. +Can be: 'active-con', 'available-con', 'created-con', 'in-use-con'. + +=item B<--critical-*> + +Threshold critical. +Can be: 'active-con', 'available-con', 'created-con', 'in-use-con'. + +=back + +=cut diff --git a/centreon-plugins/apps/java/jboss/jmx/mode/listdatasources.pm b/centreon-plugins/apps/java/jboss/jmx/mode/listdatasources.pm new file mode 100644 index 000000000..74c828e0b --- /dev/null +++ b/centreon-plugins/apps/java/jboss/jmx/mode/listdatasources.pm @@ -0,0 +1,123 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::java::jboss::jmx::mode::listdatasources; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + "filter-name:s" => { name => 'filter_name' }, + }); + $self->{ds} = {}; + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $request = [ + { mbean => "jboss.jca:name=*,service=ManagedConnectionPool", attributes => + [ { name => 'ConnectionCount' } ] }, + { mbean => "jboss.as:data-source=*,statistics=pool,subsystem=datasources", attributes => + [ { name => 'ActiveCount' } ] }, + ]; + my $result = $options{custom}->get_attributes(request => $request); + + foreach my $mbean (keys %{$result}) { + $mbean =~ /(?:[:,])(?:data-source|name)=(.*?)(?:,|$)/; + my $name = $1; + $name =~ s/^"(.*)"$/$1/; + + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $name !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping '" . $name . "': no matching filter.", debug => 1); + next; + } + + $self->{ds}->{$name} = { + name => $name, + }; + } +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{ds}}) { + $self->{output}->output_add(long_msg => '[name = ' . $self->{ds}->{$instance}->{name} . "]"); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List data sources:'); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => ['name']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach my $instance (sort keys %{$self->{ds}}) { + $self->{output}->add_disco_entry( + %{$self->{ds}->{$instance}} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List data sources. + +=over 8 + +=item B<--filter-name> + +Filter by name (can be a regexp). + +=back + +=cut + diff --git a/centreon-plugins/apps/java/jboss/jmx/plugin.pm b/centreon-plugins/apps/java/jboss/jmx/plugin.pm new file mode 100644 index 000000000..378cd1951 --- /dev/null +++ b/centreon-plugins/apps/java/jboss/jmx/plugin.pm @@ -0,0 +1,50 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::java::jboss::jmx::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + %{$self->{modes}} = ( + 'datasource-usage' => 'apps::java::jboss::jmx::mode::datasourceusage', + 'list-datasources' => 'apps::java::jboss::jmx::mode::listdatasources', + ); + + $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Jboss in JMX. Need Jolokia agent. + +=cut From d09a0e541242cb5a8ec49e300fc7313c6d6c0eed Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 5 Dec 2017 11:16:33 +0100 Subject: [PATCH 37/45] add modes for jboss --- centreon-plugins/apps/java/jboss/jmx/plugin.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/centreon-plugins/apps/java/jboss/jmx/plugin.pm b/centreon-plugins/apps/java/jboss/jmx/plugin.pm index 378cd1951..d37cc2ef3 100644 --- a/centreon-plugins/apps/java/jboss/jmx/plugin.pm +++ b/centreon-plugins/apps/java/jboss/jmx/plugin.pm @@ -31,8 +31,12 @@ sub new { $self->{version} = '0.1'; %{$self->{modes}} = ( + 'class-count' => 'centreon::common::jvm::mode::classcount', 'datasource-usage' => 'apps::java::jboss::jmx::mode::datasourceusage', 'list-datasources' => 'apps::java::jboss::jmx::mode::listdatasources', + 'memory' => 'centreon::common::jvm::mode::memory', + 'memory-detailed' => 'centreon::common::jvm::mode::memorydetailed', + 'threads' => 'centreon::common::jvm::mode::threads', ); $self->{custom_modes}{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia'; From e0ba4699dc1b5843ce1c48a2f6078aac2269f8be Mon Sep 17 00:00:00 2001 From: Colin GAGNAIRE Date: Tue, 5 Dec 2017 13:24:19 +0100 Subject: [PATCH 38/45] Add Redis plugin --- .../apps/redis/cli/custom/rediscli.pm | 148 ++++++++ .../apps/redis/cli/mode/clients.pm | 141 +++++++ .../apps/redis/cli/mode/cluster.pm | 128 +++++++ .../apps/redis/cli/mode/commands.pm | 116 ++++++ .../apps/redis/cli/mode/connections.pm | 163 ++++++++ centreon-plugins/apps/redis/cli/mode/cpu.pm | 147 ++++++++ .../apps/redis/cli/mode/memory.pm | 355 ++++++++++++++++++ .../apps/redis/cli/mode/persistence.pm | 237 ++++++++++++ .../apps/redis/cli/mode/replication.pm | 261 +++++++++++++ centreon-plugins/apps/redis/cli/plugin.pm | 60 +++ 10 files changed, 1756 insertions(+) create mode 100644 centreon-plugins/apps/redis/cli/custom/rediscli.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/clients.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/cluster.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/commands.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/connections.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/cpu.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/memory.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/persistence.pm create mode 100644 centreon-plugins/apps/redis/cli/mode/replication.pm create mode 100644 centreon-plugins/apps/redis/cli/plugin.pm diff --git a/centreon-plugins/apps/redis/cli/custom/rediscli.pm b/centreon-plugins/apps/redis/cli/custom/rediscli.pm new file mode 100644 index 000000000..f17c2d96e --- /dev/null +++ b/centreon-plugins/apps/redis/cli/custom/rediscli.pm @@ -0,0 +1,148 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::custom::rediscli; + +use strict; +use warnings; +use Redis; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class Custom: Need to specify 'output' argument.\n"; + exit 3; + } + + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => + { + "hostname:s" => { name => 'hostname' }, + "port:s" => { name => 'port' }, + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'REDIS CLI OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + + return $self; +} + +# Method to manage multiples +sub set_options { + my ($self, %options) = @_; + # options{options_result} + + $self->{option_results} = $options{option_results}; +} + +# Method to manage multiples +sub set_defaults { + my ($self, %options) = @_; + # options{default} + + # Manage default value + foreach (keys %{$options{default}}) { + if ($_ eq $self->{mode}) { + for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { + foreach my $opt (keys %{$options{default}->{$_}[$i]}) { + if (!defined($self->{option_results}->{$opt}[$i])) { + $self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt}; + } + } + } + } + } +} + +sub check_options { + my ($self, %options) = @_; + + $self->{hostname} = $self->{option_results}->{hostname}; + $self->{port} = $self->{option_results}->{port}; + + if (!defined($self->{hostname})) { + $self->{output}->add_option_msg(short_msg => "Need to specify hostname argument."); + $self->{output}->option_exit(); + } + if (!defined($self->{port})) { + $self->{output}->add_option_msg(short_msg => "Need to specify port argument."); + $self->{output}->option_exit(); + } + + return 0; +} + +sub get_info { + my ($self, %options) = @_; + + $self->{redis} = Redis->new(server => $self->{hostname}.":".$self->{port}); + + my $response = $self->{redis}->info; + + my $items; + + foreach my $attributes (keys %{$response}) { + $items->{$attributes} = $response->{$attributes}; + } + + return $items; +} + +1; + +__END__ + +=head1 NAME + +REDIS CLI + +=head1 SYNOPSIS + +Redis Cli custom mode + +=head1 REDIS CLI OPTIONS + +=over 8 + +=item B<--hostname> + +Redis hostname. + +=item B<--port> + +Redis port. + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/clients.pm b/centreon-plugins/apps/redis/cli/mode/clients.pm new file mode 100644 index 000000000..547e0e409 --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/clients.pm @@ -0,0 +1,141 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::clients; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'connected-clients', set => { + key_values => [ { name => 'connected_clients' } ], + output_template => 'Connected clients: %s', + perfdatas => [ + { label => 'connected_clients', value => 'connected_clients_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'blocked-clients', set => { + key_values => [ { name => 'blocked_clients' } ], + output_template => 'Blocked clients: %s', + perfdatas => [ + { label => 'blocked_clients', value => 'blocked_clients_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'client-longest-output-list', set => { + key_values => [ { name => 'client_longest_output_list' } ], + output_template => 'Client longest output list: %s', + perfdatas => [ + { label => 'client_longest_output_list', value => 'client_longest_output_list_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'client-biggest-input-buf', set => { + key_values => [ { name => 'client_biggest_input_buf' } ], + output_template => 'Client biggest input buffer: %s', + perfdatas => [ + { label => 'client_biggest_input_buf', value => 'client_biggest_input_buf_absolute', template => '%s', min => 0 }, + ], + }, + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + $self->{global} = { 'connected_clients' => $self->{results}->{connected_clients}, + 'blocked_clients' => $self->{results}->{blocked_clients}, + 'client_longest_output_list' => $self->{results}->{client_longest_output_list}, + 'client_biggest_input_buf' => $self->{results}->{client_biggest_input_buf}}; +} + +1; + +__END__ + +=head1 MODE + +Check number of connected and blocked clients + +=over 8 + +=item B<--warning-connected-clients> + +Warning threshold for number of connected clients + +=item B<--critical-connected-clients> + +Critical threshold for number of connected clients + +=item B<--warning-blocked-clients> + +Warning threshold for number of blocked clients + +=item B<--critical-blocked-clients> + +Critical threshold for number of blocked clients + +=item B<--warning-client-longest-output-list> + +Warning threshold for longest output list among current client connections + +=item B<--critical-client-longest-output-list> + +Critical threshold for longest output list among current client connections + +=item B<--warning-client-biggest-input-buf> + +Warning threshold for biggest input buffer among current client connections + +=item B<--critical-client-biggest-input-buf> + +Critical threshold for biggest input buffer among current client connections + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/cluster.pm b/centreon-plugins/apps/redis/cli/mode/cluster.pm new file mode 100644 index 000000000..0c0f613dc --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/cluster.pm @@ -0,0 +1,128 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::cluster; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +my $thresholds = { + global => [ + ['disabled', 'CRITICAL'], + ['enabled', 'OK'], + ], +}; + +my %map_status = ( + 0 => 'disabled', + 1 => 'enabled', +); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + "threshold-overload:s@" => { name => 'threshold_overload' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + $self->{overload_th} = {}; + foreach my $val (@{$self->{option_results}->{threshold_overload}}) { + if ($val !~ /^(.*?),(.*)$/) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); + $self->{output}->option_exit(); + } + my ($section, $status, $filter) = ('global', $1, $2); + if ($self->{output}->is_litteral_status(status => $status) == 0) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); + $self->{output}->option_exit(); + } + $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); + push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; + } +} + + +sub get_severity { + my ($self, %options) = @_; + my $status = 'UNKNOWN'; # default + + if (defined($self->{overload_th}->{$options{section}})) { + foreach (@{$self->{overload_th}->{$options{section}}}) { + if ($options{value} =~ /$_->{filter}/i) { + $status = $_->{status}; + return $status; + } + } + } + foreach (@{$thresholds->{$options{section}}}) { + if ($options{value} =~ /$$_[0]/i) { + $status = $$_[1]; + return $status; + } + } + + return $status; +} + +sub run { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + my $exit = $self->get_severity(section => 'global', value => $map_status{$items->{cluster_enabled}}); + + $self->{output}->output_add(severity => $exit, short_msg => sprintf("Cluster is '%s'", $map_status{$items->{cluster_enabled}})); + $self->{output}->display(); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Check cluster status + +=over 8 + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: status,regexp) +Example: --threshold-overload='CRITICAL,disabled' + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/commands.pm b/centreon-plugins/apps/redis/cli/mode/commands.pm new file mode 100644 index 000000000..f648019cc --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/commands.pm @@ -0,0 +1,116 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::commands; + +use base qw(centreon::plugins::templates::counter); +use Digest::MD5 qw(md5_hex); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'processed-commands', set => { + key_values => [ { name => 'total_commands_processed', diff => 1 } ], + output_template => 'Processed: %s', + perfdatas => [ + { label => 'processed_commands', value => 'total_commands_processed_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'ops-per-sec', set => { + key_values => [ { name => 'instantaneous_ops_per_sec' } ], + output_template => 'Processed per sec: %s', + perfdatas => [ + { label => 'ops_per_sec', value => 'instantaneous_ops_per_sec_absolute', template => '%s', min => 0, unit => 'ops/s' }, + ], + }, + }, + ]; +} + +sub prefix_output { + my ($self, %options) = @_; + + return "Number of commands: "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + $self->{global} = { 'total_commands_processed' => $self->{results}->{total_commands_processed}, + 'instantaneous_ops_per_sec' => $self->{results}->{instantaneous_ops_per_sec}}; +} + +1; + +__END__ + +=head1 MODE + +Check commands number + +=over 8 + +=item B<--warning-processed-commands> + +Warning threshold for number of commands processed by the server + +=item B<--critical-processed-commands> + +Critical threshold for number of commands processed by the server + +=item B<--warning-ops-per-sec> + +Warning threshold for number of commands processed per second + +=item B<--critical-ops-per-sec> + +Critical threshold for number of commands processed per second + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/connections.pm b/centreon-plugins/apps/redis/cli/mode/connections.pm new file mode 100644 index 000000000..e834f0a05 --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/connections.pm @@ -0,0 +1,163 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::connections; + +use base qw(centreon::plugins::templates::counter); +use Digest::MD5 qw(md5_hex); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' }, + { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' } + ]; + + $self->{maps_counters}->{connections} = [ + { label => 'received-connections', set => { + key_values => [ { name => 'total_connections_received', diff => 1 } ], + output_template => 'Received: %s', + perfdatas => [ + { label => 'received_connections', value => 'total_connections_received_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'rejected-connections', set => { + key_values => [ { name => 'rejected_connections', diff => 1 } ], + output_template => 'Rejected: %s', + perfdatas => [ + { label => 'rejected_connections', value => 'rejected_connections_absolute', template => '%s', min => 0 }, + ], + }, + }, + ]; + + $self->{maps_counters}->{traffic} = [ + { label => 'traffic-in', set => { + key_values => [ { name => 'total_net_input_bytes', diff => 1 } ], + output_template => 'Traffic In: %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_in', value => 'total_net_input_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + ], + }, + }, + { label => 'traffic-out', set => { + key_values => [ { name => 'total_net_output_bytes', diff => 1 } ], + output_template => 'Traffic Out: %s %s/s', + per_second => 1, output_change_bytes => 2, + perfdatas => [ + { label => 'traffic_out', value => 'total_net_output_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + ], + }, + }, + ]; +} + +sub prefix_connections_output { + my ($self, %options) = @_; + + return "Number of connections: "; +} + +sub prefix_traffic_output { + my ($self, %options) = @_; + + return "Network usage: "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + $self->{connections} = { 'total_connections_received' => $self->{results}->{total_connections_received}, + 'rejected_connections' => $self->{results}->{rejected_connections}}; + + $self->{traffic} = { 'total_net_input_bytes' => $self->{results}->{total_net_input_bytes}, + 'total_net_output_bytes' => $self->{results}->{total_net_output_bytes}}; +} + +1; + +__END__ + +=head1 MODE + +Check connections number and network usage + +=over 8 + +=item B<--warning-received-connections> + +Warning threshold for received connections + +=item B<--critical-received-connections> + +Critical threshold for received connections + +=item B<--warning-rejected-connections> + +Warning threshold for rejected connections + +=item B<--critical-rejected-connections> + +Critical threshold for rejected connections + +=item B<--warning-traffic-in> + +Warning threshold for inbound traffic (b/s) + +=item B<--critical-traffic-in> + +Critical threshold for inbound traffic (b/s) + +=item B<--warning-traffic-out> + +Warning threshold for outbound traffic (b/s) + +=item B<--critical-traffic-out> + +Critical thresholdfor outbound traffic (b/s) + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/cpu.pm b/centreon-plugins/apps/redis/cli/mode/cpu.pm new file mode 100644 index 000000000..7a483185a --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/cpu.pm @@ -0,0 +1,147 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::cpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'sys', set => { + key_values => [ { name => 'used_cpu_sys' } ], + output_template => 'System: %.2f %%', + perfdatas => [ + { label => 'sys', value => 'used_cpu_sys_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + ], + }, + }, + { label => 'user', set => { + key_values => [ { name => 'used_cpu_user' } ], + output_template => 'User: %.2f %%', + perfdatas => [ + { label => 'user', value => 'used_cpu_user_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + ], + }, + }, + { label => 'sys-children', set => { + key_values => [ { name => 'used_cpu_sys_children' } ], + output_template => 'System children: %.2f %%', + perfdatas => [ + { label => 'sys_children', value => 'used_cpu_sys_children_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + ], + }, + }, + { label => 'user-children', set => { + key_values => [ { name => 'used_cpu_user_children' } ], + output_template => 'User children: %.2f %%', + perfdatas => [ + { label => 'user_children', value => 'used_cpu_user_children_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + ], + }, + }, + ]; +} + +sub prefix_output { + my ($self, %options) = @_; + + return "CPU usage: "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + $self->{global} = { 'used_cpu_sys' => $self->{results}->{used_cpu_sys}, + 'used_cpu_user' => $self->{results}->{used_cpu_user}, + 'used_cpu_sys_children' => $self->{results}->{used_cpu_sys_children}, + 'used_cpu_user_children' => $self->{results}->{used_cpu_user_children}}; +} + +1; + +__END__ + +=head1 MODE + +Check CPU utilization + +=over 8 + +=item B<--warning-sys> + +Warning threshold for Sys CPU utilization + +=item B<--critical-sys> + +Critical threshold for Sys CPU utilization + +=item B<--warning-user> + +Warning threshold for User CPU utilization + +=item B<--critical-user> + +Critical threshold for User CPU utilization + +=item B<--warning-sys-children> + +Warning threshold for Sys Children CPU utilization + +=item B<--critical-sys-children> + +Critical threshold for Sys Children CPU utilization + +=item B<--warning-user-children> + +Warning threshold for User Children CPU utilization + +=item B<--critical-user-children> + +Critical threshold for User Children CPU utilization + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/memory.pm b/centreon-plugins/apps/redis/cli/mode/memory.pm new file mode 100644 index 000000000..5f2c69fa1 --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/memory.pm @@ -0,0 +1,355 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => $self->{result_values}->{label}, unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{result_values}->{label}, total => $self->{result_values}->{total}, cast_int => 1), + min => 0, max => $self->{result_values}->{total}); +} + +my $instance_mode; + +sub custom_usage_threshold { + my ($self, %options) = @_; + + my ($exit, $threshold_value); + $threshold_value = $self->{result_values}->{used}; + $threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free})); + if ($instance_mode->{option_results}->{units} eq '%') { + $threshold_value = $self->{result_values}->{prct_used}; + $threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free})); + } + $exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{result_values}->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{result_values}->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + + my $msg = sprintf($self->{result_values}->{display}.": %s (%.2f%%)", + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{label} = $options{new_datas}->{$self->{instance} . '_label'}; + $self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'}; + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'used', type => 0 }, + { name => 'rss', type => 0 }, + { name => 'peak', type => 0 }, + { name => 'overhead', type => 0 }, + { name => 'startup', type => 0 }, + { name => 'dataset', type => 0 }, + { name => 'lua', type => 0 }, + { name => 'stats', type => 0, cb_prefix_output => 'prefix_stats_output' } + ]; + + $self->{maps_counters}->{used} = [ + { label => 'used', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{rss} = [ + { label => 'rss', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{peak} = [ + { label => 'peak', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{overhead} = [ + { label => 'overhead', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{startup} = [ + { label => 'startup', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{dataset} = [ + { label => 'dataset', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{lua} = [ + { label => 'lua', set => { + key_values => [ { name => 'display' }, { name => 'label' }, { name => 'used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; + + $self->{maps_counters}->{stats} = [ + { label => 'fragmentation-ratio', set => { + key_values => [ { name => 'mem_fragmentation_ratio' } ], + output_template => 'Fragmentation ratio: %s', + perfdatas => [ + { label => 'fragmentation_ratio', value => 'mem_fragmentation_ratio_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'defrag-running', set => { + key_values => [ { name => 'active_defrag_running' } ], + output_template => 'Defragmentation running: %s', + perfdatas => [ + { label => 'defrag_running', value => 'active_defrag_running_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'lazyfree-pending-objects', set => { + key_values => [ { name => 'lazyfree_pending_objects' } ], + output_template => 'Lazyfree pending objects: %s', + perfdatas => [ + { label => 'lazyfree_pending_objects', value => 'lazyfree_pending_objects_absolute', template => '%s', min => 0 }, + ], + }, + }, + ]; +} + +sub prefix_stats_output { + my ($self, %options) = @_; + + return "Statistics: "; +} + + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + "units:s" => { name => 'units', default => '%' }, + "free" => { name => 'free' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $instance_mode = $self; +} + +my $metrics = { + 'used_memory' => { label => 'used', display => 'Used' }, + 'used_memory_rss' => { label => 'rss', display => 'Rss' }, + 'used_memory_peak' => { label => 'peak', display => 'Peak' }, + 'used_memory_overhead' => { label => 'overhead', display => 'Overhead' }, + 'used_memory_startup' => { label => 'startup', display => 'Startup' }, + 'used_memory_dataset' => { label => 'dataset', display => 'Dataset' }, + 'used_memory_lua' => { label => 'lua', display => 'Lua' }, +}; + +sub manage_selection { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + foreach my $type (keys $metrics) { + $self->{$metrics->{$type}->{label}} = { 'display' => $metrics->{$type}->{display}, + 'label' => $metrics->{$type}->{label}, + 'used' => $self->{results}->{$type}, + 'total' => $self->{results}->{total_system_memory} }; + } + + $self->{stats} = { 'mem_fragmentation_ratio' => $self->{results}->{mem_fragmentation_ratio}, + 'active_defrag_running' => $self->{results}->{active_defrag_running}, + 'lazyfree_pending_objects' => $self->{results}->{lazyfree_pending_objects} }; +} + +1; + +__END__ + +=head1 MODE + +Check memory utilization + +=over 8 + +=item B<--units> + +Units of thresholds (Default: '%') ('%', 'B'). + +=item B<--free> + +Thresholds are on free space left. + +=item B<--warning-used> + +Warning threshold for Used memory utilization + +=item B<--critical-used> + +Critical threshold for Used memory utilization + +=item B<--warning-rss> + +Warning threshold for Rss memory utilization + +=item B<--critical-rss> + +Critical threshold for Rss memory utilization + +=item B<--warning-peak> + +Warning threshold for Peak memory utilization + +=item B<--critical-peak> + +Critical threshold for Peak memory utilization + +=item B<--warning-overhead> + +Warning threshold for Overhead memory utilization + +=item B<--critical-overhead> + +Critical threshold for Overhead memory utilization + +=item B<--warning-startup> + +Warning threshold for Startup memory utilization + +=item B<--critical-startup> + +Critical threshold for Startup memory utilization + +=item B<--warning-dataset> + +Warning threshold for Dataset memory utilization + +=item B<--critical-dataset> + +Critical threshold for Dataset memory utilization + +=item B<--warning-lua> + +Warning threshold for Lua memory utilization + +=item B<--critical-lua> + +Critical threshold for Lua memory utilization + +=item B<--warning-fragmentation-ratio> + +Warning threshold for Fragmentation Ratio + +=item B<--critical-fragmentation-ratio> + +Critical threshold for Fragmentation Ratio + +=item B<--warning-defrag-running> + +Warning threshold for Running Defragmentation + +=item B<--critical-defrag-running> + +Critical threshold for Running Defragmentation + +=item B<--warning-lazyfree-pending-objects> + +Warning threshold for Lazyfree Pending Objects + +=item B<--critical-lazyfree-pending-objects> + +Critical threshold for Lazyfree Pending Objects + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/persistence.pm b/centreon-plugins/apps/redis/cli/mode/persistence.pm new file mode 100644 index 000000000..07bc62988 --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/persistence.pm @@ -0,0 +1,237 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::persistence; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $thresholds = { + status => [ + ['fail', 'CRITICAL'], + ['ok', 'OK'], + ], + progress => [ + ['stopped', 'WARNING'], + ['in progress', 'OK'], + ], +}; + +my %map_status = ( + 0 => 'stopped', + 1 => 'in progress', +); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'changes', set => { + key_values => [ { name => 'rdb_changes_since_last_save' } ], + output_template => 'Number of changes since the last dump: %s', + perfdatas => [ + { label => 'changes', value => 'rdb_changes_since_last_save_absolute', template => '%s', min => 0 }, + ], + }, + }, + { label => 'last-save', set => { + key_values => [ { name => 'rdb_last_save_time' }, { name => 'rdb_last_save_time_sec' } ], + output_template => 'Time since last successful save: %s', + perfdatas => [ + { label => 'last_save', value => 'rdb_last_save_time_sec_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + { label => 'save-size', set => { + key_values => [ { name => 'rdb_last_cow_size' } ], + output_template => 'Size of last save: %s %s', + output_change_bytes => 1, + perfdatas => [ + { label => 'save_size', value => 'rdb_last_cow_size_absolute', template => '%s', min => 0, unit => 'B' }, + ], + }, + }, + { label => 'last-save-duration', set => { + key_values => [ { name => 'rdb_last_bgsave_time' } ], + output_template => 'Duration of last save: %s s', + perfdatas => [ + { label => 'last_save_duration', value => 'rdb_last_bgsave_time_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + { label => 'current-save-duration', set => { + key_values => [ { name => 'rdb_current_bgsave_time' } ], + output_template => 'Duration of current save: %s s', + perfdatas => [ + { label => 'current_save_duration', value => 'rdb_current_bgsave_time_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + "threshold-overload:s@" => { name => 'threshold_overload' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + $self->{overload_th} = {}; + foreach my $val (@{$self->{option_results}->{threshold_overload}}) { + if ($val !~ /^(.*?),(.*?),(.*)$/) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); + $self->{output}->option_exit(); + } + my ($section, $status, $filter) = ($1, $2, $3); + if ($self->{output}->is_litteral_status(status => $status) == 0) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); + $self->{output}->option_exit(); + } + $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); + push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; + } +} + + +sub get_severity { + my ($self, %options) = @_; + my $status = 'UNKNOWN'; # default + + if (defined($self->{overload_th}->{$options{section}})) { + foreach (@{$self->{overload_th}->{$options{section}}}) { + if ($options{value} =~ /$_->{filter}/i) { + $status = $_->{status}; + return $status; + } + } + } + foreach (@{$thresholds->{$options{section}}}) { + if ($options{value} =~ /$$_[0]/i) { + $status = $$_[1]; + return $status; + } + } + + return $status; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + my @exits; + + push @exits, $self->get_severity(section => 'status', value => $self->{results}->{rdb_last_bgsave_status}); + push @exits, $self->get_severity(section => 'progess', value => $map_status{$self->{results}->{rdb_bgsave_in_progress}}); + + $self->{output}->output_add(short_msg => sprintf("RDB save is in '%s' status", $self->{results}->{rdb_last_bgsave_status})); + $self->{output}->output_add(short_msg => sprintf("RDB save is '%s'", $map_status{$self->{results}->{rdb_bgsave_in_progress}})); + + $self->{global} = { 'rdb_changes_since_last_save' => $self->{results}->{rdb_changes_since_last_save}, + 'rdb_last_save_time' => centreon::plugins::misc::change_seconds(value => time() - $self->{results}->{rdb_last_save_time}), + 'rdb_last_save_time_sec' => time() - $self->{results}->{rdb_last_save_time}, + 'rdb_last_cow_size' => $self->{results}->{rdb_last_cow_size}, + 'rdb_last_bgsave_time' => $self->{results}->{rdb_last_bgsave_time_sec}, + 'rdb_current_bgsave_time' => $self->{results}->{rdb_current_bgsave_time_sec}}; + + my $exit = $self->{output}->get_most_critical(status => \@exits); + $self->{output}->output_add(severity => $exit); +} + +1; + +__END__ + +=head1 MODE + +Check RDB persistence status + +=over 8 + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,status,regexp) +Example: --threshold-overload='status,CRITICAL,ok' +Section can be: 'status', 'progress' + +=item B<--warning-changes> + +Warning threshold for number of changes since the last dump + +=item B<--critical-changes> + +Critical threshold for number of changes since the last dump + +=item B<--warning-last-save> + +Warning threshold for time since last successful save (in second) + +=item B<--critical-last-save> + +Critical threshold for time since last successful save (in second) + +=item B<--warning-save-size> + +Warning threshold for size of last save (in bytes) + +=item B<--critical-save-size> + +Critical threshold for size of last save (in bytes) + +=item B<--warning-last-save-duration> + +Warning threshold for duration of last save (in second) + +=item B<--critical-last-save-duration> + +Critical threshold for duration of last save (in second) + +=item B<--warning-current-save-duration> + +Warning threshold for current of last save (in second) + +=item B<--critical-current-save-duration> + +Critical threshold for current of last save (in second) + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/mode/replication.pm b/centreon-plugins/apps/redis/cli/mode/replication.pm new file mode 100644 index 000000000..1004d545f --- /dev/null +++ b/centreon-plugins/apps/redis/cli/mode/replication.pm @@ -0,0 +1,261 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::mode::replication; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +my $thresholds = { + link => [ + ['down', 'CRITICAL'], + ['up', 'OK'], + ], + sync => [ + ['stopped', 'OK'], + ['in progress', 'WARNING'], + ], +}; + +my %map_sync = ( + 0 => 'stopped', + 1 => 'in progress', +); + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 }, + { name => 'master', type => 0 }, + { name => 'slave', type => 0 } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'connected-slaves', set => { + key_values => [ { name => 'connected_slaves' } ], + output_template => 'Number of connected slaves: %s', + perfdatas => [ + { label => 'connected_slaves', value => 'connected_slaves_absolute', template => '%s', min => 0 }, + ], + }, + }, + ]; + + $self->{maps_counters}->{master} = [ + { label => 'master-repl-offset', set => { + key_values => [ { name => 'master_repl_offset' } ], + output_template => 'Master replication offset: %s s', + perfdatas => [ + { label => 'master_repl_offset', value => 'master_repl_offset_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + ]; + + $self->{maps_counters}->{slave} = [ + { label => 'master-last-io', set => { + key_values => [ { name => 'master_last_io_seconds_ago' } ], + output_template => 'Last interaction with master: %s s', + perfdatas => [ + { label => 'master_last_io', value => 'master_last_io_seconds_ago_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + { label => 'slave-repl-offset', set => { + key_values => [ { name => 'slave_repl_offset' } ], + output_template => 'Slave replication offset: %s s', + perfdatas => [ + { label => 'slave_repl_offset', value => 'slave_repl_offset_absolute', template => '%s', min => 0, unit => 's' }, + ], + }, + }, + { label => 'slave-priority', set => { + key_values => [ { name => 'slave_priority' } ], + output_template => 'Slave replication offset: %s s', + perfdatas => [ + { label => 'slave_priority', value => 'slave_priority_absolute', template => '%s' }, + ], + }, + }, + { label => 'slave-read-only', set => { + key_values => [ { name => 'slave_read_only' } ], + output_template => 'Slave replication offset: %s s', + perfdatas => [ + { label => 'slave_read_only', value => 'slave_read_only_absolute', template => '%s' }, + ], + }, + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + + $options{options}->add_options(arguments => + { + "threshold-overload:s@" => { name => 'threshold_overload' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + $self->{overload_th} = {}; + foreach my $val (@{$self->{option_results}->{threshold_overload}}) { + if ($val !~ /^(.*?),(.*?),(.*)$/) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); + $self->{output}->option_exit(); + } + my ($section, $status, $filter) = ($1, $2, $3); + if ($self->{output}->is_litteral_status(status => $status) == 0) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); + $self->{output}->option_exit(); + } + $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); + push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; + } +} + + +sub get_severity { + my ($self, %options) = @_; + my $status = 'UNKNOWN'; # default + + if (defined($self->{overload_th}->{$options{section}})) { + foreach (@{$self->{overload_th}->{$options{section}}}) { + if ($options{value} =~ /$_->{filter}/i) { + $status = $_->{status}; + return $status; + } + } + } + foreach (@{$thresholds->{$options{section}}}) { + if ($options{value} =~ /$$_[0]/i) { + $status = $$_[1]; + return $status; + } + } + + return $status; +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{redis} = $options{custom}; + $self->{results} = $self->{redis}->get_info(); + + my @exits; + + $self->{output}->output_add(short_msg => sprintf("Node is '%s'", $self->{results}->{role})); + + $self->{global} = { 'connected_slaves' => $self->{results}->{connected_slaves} }; + + if ($self->{results}->{role} =~ /master/) { + $self->{master} = { 'master_repl_offset' => $self->{results}->{master_repl_offset} }; + } elsif ($self->{results}->{role} =~ /slave/) { + $self->{output}->output_add(short_msg => sprintf("Link with master '%s:%s' is '%s', Sync is '%s'", + $self->{results}->{master_host}, + $self->{results}->{master_port}, + $self->{results}->{master_link_status}, + $map_sync{$self->{results}->{master_sync_in_progress}})); + + push @exits, $self->get_severity(section => 'link', value => $self->{results}->{master_link_status}); + push @exits, $self->get_severity(section => 'sync', value => $map_sync{$self->{results}->{master_sync_in_progress}}); + + $self->{slave} = { 'master_last_io_seconds_ago' => $self->{results}->{master_last_io_seconds_ago}, + 'slave_repl_offset' => $self->{results}->{slave_repl_offset}, + 'slave_priority' => $self->{results}->{slave_priority}, + 'slave_read_only' => $self->{results}->{slave_read_only} }; + } + + my $exit = $self->{output}->get_most_critical(status => \@exits); + $self->{output}->output_add(severity => $exit); +} + +1; + +__END__ + +=head1 MODE + +Check replication status + +=over 8 + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,status,regexp) +Example: --threshold-overload='link,OK,down' +Section can be: 'link', 'sync' + +=item B<--warning-connected-slaves> + +Warning threshold for number of connected slave + +=item B<--critical-connected-slaves> + +Critical threshold for number of connected slave + +=item B<--warning-master-repl-offset> + +Warning threshold for master replication offset (in second) + +=item B<--critical-master-repl-offset> + +Critical threshold for master replication offset (in second) + +=item B<--warning-master-last-io> + +Warning threshold for last interaction with master (in second) + +=item B<--critical-master-last-io> + +Critical threshold for last interaction with master (in second) + +=item B<--warning-slave-priority> + +Warning threshold for slave priority + +=item B<--critical-slave-priority> + +Critical threshold for slave priority + +=item B<--warning-slave-read-only> + +Warning threshold for slave being in read-only + +=item B<--critical-slave-read-only> + +Critical threshold for slave being in read-only + +=back + +=cut diff --git a/centreon-plugins/apps/redis/cli/plugin.pm b/centreon-plugins/apps/redis/cli/plugin.pm new file mode 100644 index 000000000..2496285c5 --- /dev/null +++ b/centreon-plugins/apps/redis/cli/plugin.pm @@ -0,0 +1,60 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package apps::redis::cli::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'clients' => 'apps::redis::cli::mode::clients', + 'cluster' => 'apps::redis::cli::mode::cluster', + 'commands' => 'apps::redis::cli::mode::commands', + 'connections' => 'apps::redis::cli::mode::connections', + 'cpu' => 'apps::redis::cli::mode::cpu', + 'memory' => 'apps::redis::cli::mode::memory', + 'persistence' => 'apps::redis::cli::mode::persistence', + 'replication' => 'apps::redis::cli::mode::replication', + ); + + $self->{custom_modes}{rediscli} = 'apps::redis::cli::custom::rediscli'; + return $self; +} + +sub init { + my ($self, %options) = @_; + + $self->SUPER::init(%options); +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Redis server through Perl Cli binding library. From 73208cd88a29b7725ba5929dcb29dd7e700636d2 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 5 Dec 2017 15:57:28 +0100 Subject: [PATCH 39/45] enhance redis plugin --- .../apps/redis/cli/custom/rediscli.pm | 17 +- .../apps/redis/cli/mode/clients.pm | 14 +- .../apps/redis/cli/mode/cluster.pm | 128 ---------- .../apps/redis/cli/mode/commands.pm | 17 +- .../apps/redis/cli/mode/connections.pm | 26 +- centreon-plugins/apps/redis/cli/mode/cpu.pm | 13 +- .../apps/redis/cli/mode/memory.pm | 55 ++--- .../apps/redis/cli/mode/persistence.pm | 201 +++++++--------- .../apps/redis/cli/mode/replication.pm | 227 +++++++++--------- centreon-plugins/apps/redis/cli/plugin.pm | 1 - 10 files changed, 273 insertions(+), 426 deletions(-) delete mode 100644 centreon-plugins/apps/redis/cli/mode/cluster.pm diff --git a/centreon-plugins/apps/redis/cli/custom/rediscli.pm b/centreon-plugins/apps/redis/cli/custom/rediscli.pm index f17c2d96e..5b95f8e02 100644 --- a/centreon-plugins/apps/redis/cli/custom/rediscli.pm +++ b/centreon-plugins/apps/redis/cli/custom/rediscli.pm @@ -54,20 +54,15 @@ sub new { return $self; } -# Method to manage multiples sub set_options { my ($self, %options) = @_; - # options{options_result} $self->{option_results} = $options{option_results}; } -# Method to manage multiples sub set_defaults { my ($self, %options) = @_; - # options{default} - - # Manage default value + foreach (keys %{$options{default}}) { if ($_ eq $self->{mode}) { for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { @@ -99,15 +94,19 @@ sub check_options { return 0; } +sub get_connection_info { + my ($self, %options) = @_; + + return $self->{hostname} . ":" . $self->{port}; +} + sub get_info { my ($self, %options) = @_; - $self->{redis} = Redis->new(server => $self->{hostname}.":".$self->{port}); + $self->{redis} = Redis->new(server => $self->{hostname} . ":" . $self->{port}); my $response = $self->{redis}->info; - my $items; - foreach my $attributes (keys %{$response}) { $items->{$attributes} = $response->{$attributes}; } diff --git a/centreon-plugins/apps/redis/cli/mode/clients.pm b/centreon-plugins/apps/redis/cli/mode/clients.pm index 547e0e409..21a4cd312 100644 --- a/centreon-plugins/apps/redis/cli/mode/clients.pm +++ b/centreon-plugins/apps/redis/cli/mode/clients.pm @@ -85,13 +85,13 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - $self->{global} = { 'connected_clients' => $self->{results}->{connected_clients}, - 'blocked_clients' => $self->{results}->{blocked_clients}, - 'client_longest_output_list' => $self->{results}->{client_longest_output_list}, - 'client_biggest_input_buf' => $self->{results}->{client_biggest_input_buf}}; + my $results = $options{custom}->get_info(); + $self->{global} = { + connected_clients => $results->{connected_clients}, + blocked_clients => $results->{blocked_clients}, + client_longest_output_list => $results->{client_longest_output_list}, + client_biggest_input_buf => $results->{client_biggest_input_buf}, + }; } 1; diff --git a/centreon-plugins/apps/redis/cli/mode/cluster.pm b/centreon-plugins/apps/redis/cli/mode/cluster.pm deleted file mode 100644 index 0c0f613dc..000000000 --- a/centreon-plugins/apps/redis/cli/mode/cluster.pm +++ /dev/null @@ -1,128 +0,0 @@ -# -# Copyright 2017 Centreon (http://www.centreon.com/) -# -# Centreon is a full-fledged industry-strength solution that meets -# the needs in IT infrastructure and application monitoring for -# service performance. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -package apps::redis::cli::mode::cluster; - -use base qw(centreon::plugins::mode); - -use strict; -use warnings; - -my $thresholds = { - global => [ - ['disabled', 'CRITICAL'], - ['enabled', 'OK'], - ], -}; - -my %map_status = ( - 0 => 'disabled', - 1 => 'enabled', -); - -sub new { - my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); - bless $self, $class; - - $self->{version} = '1.0'; - - $options{options}->add_options(arguments => - { - "threshold-overload:s@" => { name => 'threshold_overload' }, - }); - - return $self; -} - -sub check_options { - my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ('global', $1, $2); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } -} - - -sub get_severity { - my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } - } - } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; -} - -sub run { - my ($self, %options) = @_; - - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my $exit = $self->get_severity(section => 'global', value => $map_status{$items->{cluster_enabled}}); - - $self->{output}->output_add(severity => $exit, short_msg => sprintf("Cluster is '%s'", $map_status{$items->{cluster_enabled}})); - $self->{output}->display(); - $self->{output}->exit(); -} - -1; - -__END__ - -=head1 MODE - -Check cluster status - -=over 8 - -=item B<--threshold-overload> - -Set to overload default threshold values (syntax: status,regexp) -Example: --threshold-overload='CRITICAL,disabled' - -=back - -=cut diff --git a/centreon-plugins/apps/redis/cli/mode/commands.pm b/centreon-plugins/apps/redis/cli/mode/commands.pm index f648019cc..0ceeab764 100644 --- a/centreon-plugins/apps/redis/cli/mode/commands.pm +++ b/centreon-plugins/apps/redis/cli/mode/commands.pm @@ -21,16 +21,16 @@ package apps::redis::cli::mode::commands; use base qw(centreon::plugins::templates::counter); -use Digest::MD5 qw(md5_hex); use strict; use warnings; +use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0, cb_prefix_output => 'prefix_output' } + { name => 'global', type => 0, cb_prefix_output => 'prefix_output' }, ]; $self->{maps_counters}->{global} = [ @@ -76,13 +76,14 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - $self->{global} = { 'total_commands_processed' => $self->{results}->{total_commands_processed}, - 'instantaneous_ops_per_sec' => $self->{results}->{instantaneous_ops_per_sec}}; + my $results = $options{custom}->get_info(); + $self->{global} = { + total_commands_processed => $results->{total_commands_processed}, + instantaneous_ops_per_sec => $results->{instantaneous_ops_per_sec}, + }; } 1; diff --git a/centreon-plugins/apps/redis/cli/mode/connections.pm b/centreon-plugins/apps/redis/cli/mode/connections.pm index e834f0a05..40032ba64 100644 --- a/centreon-plugins/apps/redis/cli/mode/connections.pm +++ b/centreon-plugins/apps/redis/cli/mode/connections.pm @@ -21,17 +21,17 @@ package apps::redis::cli::mode::connections; use base qw(centreon::plugins::templates::counter); -use Digest::MD5 qw(md5_hex); use strict; use warnings; +use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ { name => 'connections', type => 0, cb_prefix_output => 'prefix_connections_output' }, - { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' } + { name => 'traffic', type => 0, cb_prefix_output => 'prefix_traffic_output' }, ]; $self->{maps_counters}->{connections} = [ @@ -59,7 +59,7 @@ sub set_counters { output_template => 'Traffic In: %s %s/s', per_second => 1, output_change_bytes => 2, perfdatas => [ - { label => 'traffic_in', value => 'total_net_input_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + { label => 'traffic_in', value => 'total_net_input_bytes_per_second', template => '%d', min => 0, unit => 'b/s' }, ], }, }, @@ -68,7 +68,7 @@ sub set_counters { output_template => 'Traffic Out: %s %s/s', per_second => 1, output_change_bytes => 2, perfdatas => [ - { label => 'traffic_out', value => 'total_net_output_bytes_per_second', template => '%s', min => 0, unit => 'b/s' }, + { label => 'traffic_out', value => 'total_net_output_bytes_per_second', template => '%d', min => 0, unit => 'b/s' }, ], }, }, @@ -104,16 +104,20 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{cache_name} = "redis_" . $self->{mode} . '_' . $self->{option_results}->{hostname} . '_' . md5_hex('all'); + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); + my $results = $options{custom}->get_info(); - $self->{connections} = { 'total_connections_received' => $self->{results}->{total_connections_received}, - 'rejected_connections' => $self->{results}->{rejected_connections}}; + $self->{connections} = { + total_connections_received => $results->{total_connections_received}, + rejected_connections => $results->{rejected_connections}, + }; - $self->{traffic} = { 'total_net_input_bytes' => $self->{results}->{total_net_input_bytes}, - 'total_net_output_bytes' => $self->{results}->{total_net_output_bytes}}; + $self->{traffic} = { + total_net_input_bytes => $results->{total_net_input_bytes} * 8, + total_net_output_bytes => $results->{total_net_output_bytes} * 8, + }; } 1; diff --git a/centreon-plugins/apps/redis/cli/mode/cpu.pm b/centreon-plugins/apps/redis/cli/mode/cpu.pm index 7a483185a..84012de27 100644 --- a/centreon-plugins/apps/redis/cli/mode/cpu.pm +++ b/centreon-plugins/apps/redis/cli/mode/cpu.pm @@ -91,13 +91,14 @@ sub new { sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); + my $results = $options{custom}->get_info(); - $self->{global} = { 'used_cpu_sys' => $self->{results}->{used_cpu_sys}, - 'used_cpu_user' => $self->{results}->{used_cpu_user}, - 'used_cpu_sys_children' => $self->{results}->{used_cpu_sys_children}, - 'used_cpu_user_children' => $self->{results}->{used_cpu_user_children}}; + $self->{global} = { + used_cpu_sys => $results->{used_cpu_sys}, + used_cpu_user => $results->{used_cpu_user}, + used_cpu_sys_children => $results->{used_cpu_sys_children}, + used_cpu_user_children => $results->{used_cpu_user_children}, + }; } 1; diff --git a/centreon-plugins/apps/redis/cli/mode/memory.pm b/centreon-plugins/apps/redis/cli/mode/memory.pm index 5f2c69fa1..6aef79436 100644 --- a/centreon-plugins/apps/redis/cli/mode/memory.pm +++ b/centreon-plugins/apps/redis/cli/mode/memory.pm @@ -25,6 +25,8 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; +my $instance_mode; + sub custom_usage_perfdata { my ($self, %options) = @_; @@ -35,8 +37,6 @@ sub custom_usage_perfdata { min => 0, max => $self->{result_values}->{total}); } -my $instance_mode; - sub custom_usage_threshold { my ($self, %options) = @_; @@ -80,13 +80,13 @@ sub set_counters { $self->{maps_counters_type} = [ { name => 'used', type => 0 }, - { name => 'rss', type => 0 }, - { name => 'peak', type => 0 }, - { name => 'overhead', type => 0 }, - { name => 'startup', type => 0 }, - { name => 'dataset', type => 0 }, - { name => 'lua', type => 0 }, - { name => 'stats', type => 0, cb_prefix_output => 'prefix_stats_output' } + { name => 'rss', type => 0, skipped_code => { -10 => 1 } }, + { name => 'peak', type => 0, skipped_code => { -10 => 1 } }, + { name => 'overhead', type => 0, skipped_code => { -10 => 1 } }, + { name => 'startup', type => 0, skipped_code => { -10 => 1 } }, + { name => 'dataset', type => 0, skipped_code => { -10 => 1 } }, + { name => 'lua', type => 0, skipped_code => { -10 => 1 } }, + { name => 'stats', type => 0, cb_prefix_output => 'prefix_stats_output', skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{used} = [ @@ -225,31 +225,32 @@ sub check_options { } my $metrics = { - 'used_memory' => { label => 'used', display => 'Used' }, - 'used_memory_rss' => { label => 'rss', display => 'Rss' }, - 'used_memory_peak' => { label => 'peak', display => 'Peak' }, - 'used_memory_overhead' => { label => 'overhead', display => 'Overhead' }, - 'used_memory_startup' => { label => 'startup', display => 'Startup' }, - 'used_memory_dataset' => { label => 'dataset', display => 'Dataset' }, - 'used_memory_lua' => { label => 'lua', display => 'Lua' }, + used_memory => { label => 'used', display => 'Used' }, + used_memory_rss => { label => 'rss', display => 'Rss' }, + used_memory_peak => { label => 'peak', display => 'Peak' }, + used_memory_overhead => { label => 'overhead', display => 'Overhead' }, + used_memory_startup => { label => 'startup', display => 'Startup' }, + used_memory_dataset => { label => 'dataset', display => 'Dataset' }, + used_memory_lua => { label => 'lua', display => 'Lua' }, }; sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - foreach my $type (keys $metrics) { - $self->{$metrics->{$type}->{label}} = { 'display' => $metrics->{$type}->{display}, - 'label' => $metrics->{$type}->{label}, - 'used' => $self->{results}->{$type}, - 'total' => $self->{results}->{total_system_memory} }; + my $results = $options{custom}->get_info(); + foreach my $type (keys %$metrics) { + next if (!defined($results->{$type})); + $self->{$metrics->{$type}->{label}} = { display => $metrics->{$type}->{display}, + label => $metrics->{$type}->{label}, + used => $results->{$type}, + total => $results->{total_system_memory} }; } - $self->{stats} = { 'mem_fragmentation_ratio' => $self->{results}->{mem_fragmentation_ratio}, - 'active_defrag_running' => $self->{results}->{active_defrag_running}, - 'lazyfree_pending_objects' => $self->{results}->{lazyfree_pending_objects} }; + $self->{stats} = { + mem_fragmentation_ratio => $results->{mem_fragmentation_ratio}, + active_defrag_running => $results->{active_defrag_running}, + lazyfree_pending_objects => $results->{lazyfree_pending_objects}, + }; } 1; diff --git a/centreon-plugins/apps/redis/cli/mode/persistence.pm b/centreon-plugins/apps/redis/cli/mode/persistence.pm index 07bc62988..db141d38c 100644 --- a/centreon-plugins/apps/redis/cli/mode/persistence.pm +++ b/centreon-plugins/apps/redis/cli/mode/persistence.pm @@ -25,30 +25,24 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -my $thresholds = { - status => [ - ['fail', 'CRITICAL'], - ['ok', 'OK'], - ], - progress => [ - ['stopped', 'WARNING'], - ['in progress', 'OK'], - ], -}; - -my %map_status = ( - 0 => 'stopped', - 1 => 'in progress', -); +my $instance_mode; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0 } + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'progress_status' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, { label => 'changes', set => { key_values => [ { name => 'rdb_changes_since_last_save' } ], output_template => 'Number of changes since the last dump: %s', @@ -93,6 +87,45 @@ sub set_counters { ]; } +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("RDB save status is '%s' [progress status: %s]", $self->{result_values}->{status}, $self->{result_values}->{progress_status}); + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'}; + $self->{result_values}->{progress_status} = $options{new_datas}->{$self->{instance} . '_progress_status'}; + return 0; +} + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -102,7 +135,8 @@ sub new { $options{options}->add_options(arguments => { - "threshold-overload:s@" => { name => 'threshold_overload' }, + "warning-status:s" => { name => 'warning_status', default => '%{sync_status} =~ /in progress/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{link_status} =~ /down/i' }, }); return $self; @@ -110,70 +144,41 @@ sub new { sub check_options { my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); } - -sub get_severity { +sub change_macros { my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; } +my %map_status = ( + 0 => 'stopped', + 1 => 'in progress', +); + sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my @exits; - - push @exits, $self->get_severity(section => 'status', value => $self->{results}->{rdb_last_bgsave_status}); - push @exits, $self->get_severity(section => 'progess', value => $map_status{$self->{results}->{rdb_bgsave_in_progress}}); - - $self->{output}->output_add(short_msg => sprintf("RDB save is in '%s' status", $self->{results}->{rdb_last_bgsave_status})); - $self->{output}->output_add(short_msg => sprintf("RDB save is '%s'", $map_status{$self->{results}->{rdb_bgsave_in_progress}})); - - $self->{global} = { 'rdb_changes_since_last_save' => $self->{results}->{rdb_changes_since_last_save}, - 'rdb_last_save_time' => centreon::plugins::misc::change_seconds(value => time() - $self->{results}->{rdb_last_save_time}), - 'rdb_last_save_time_sec' => time() - $self->{results}->{rdb_last_save_time}, - 'rdb_last_cow_size' => $self->{results}->{rdb_last_cow_size}, - 'rdb_last_bgsave_time' => $self->{results}->{rdb_last_bgsave_time_sec}, - 'rdb_current_bgsave_time' => $self->{results}->{rdb_current_bgsave_time_sec}}; - - my $exit = $self->{output}->get_most_critical(status => \@exits); - $self->{output}->output_add(severity => $exit); + my $results = $options{custom}->get_info(); + $self->{global} = { + status => $results->{rdb_last_bgsave_status}, + progress_status => $map_status{$results->{rdb_bgsave_in_progress}}, + rdb_changes_since_last_save => $results->{rdb_changes_since_last_save}, + rdb_last_save_time => centreon::plugins::misc::change_seconds(value => time() - $results->{rdb_last_save_time}), + rdb_last_save_time_sec => time() - $results->{rdb_last_save_time}, + rdb_last_cow_size => $results->{rdb_last_cow_size}, + rdb_last_bgsave_time => $results->{rdb_last_bgsave_time_sec}, + rdb_current_bgsave_time => $results->{rdb_current_bgsave_time_sec} + }; } 1; @@ -182,55 +187,31 @@ __END__ =head1 MODE -Check RDB persistence status +Check RDB persistence status. =over 8 -=item B<--threshold-overload> +=item B<--warning-status> -Set to overload default threshold values (syntax: section,status,regexp) -Example: --threshold-overload='status,CRITICAL,ok' -Section can be: 'status', 'progress' +Set warning threshold for status (Default: '%{progress_status} =~ /in progress/i'). +Can used special variables like: %{progress_status}, %{status} -=item B<--warning-changes> +=item B<--critical-status> -Warning threshold for number of changes since the last dump +Set critical threshold for status (Default: '%{status} =~ /fail/i'). +Can used special variables like: %{progress_status}, %{status} -=item B<--critical-changes> +=item B<--warning-*> -Critical threshold for number of changes since the last dump +Threshold warning. +Can be: 'changes', 'last-save', 'save-size', +'last-save-duration', 'current-save-duration'. -=item B<--warning-last-save> +=item B<--critical-*> -Warning threshold for time since last successful save (in second) - -=item B<--critical-last-save> - -Critical threshold for time since last successful save (in second) - -=item B<--warning-save-size> - -Warning threshold for size of last save (in bytes) - -=item B<--critical-save-size> - -Critical threshold for size of last save (in bytes) - -=item B<--warning-last-save-duration> - -Warning threshold for duration of last save (in second) - -=item B<--critical-last-save-duration> - -Critical threshold for duration of last save (in second) - -=item B<--warning-current-save-duration> - -Warning threshold for current of last save (in second) - -=item B<--critical-current-save-duration> - -Critical threshold for current of last save (in second) +Threshold critical. +Can be: 'changes', 'last-save', 'save-size', +'last-save-duration', 'current-save-duration'. =back diff --git a/centreon-plugins/apps/redis/cli/mode/replication.pm b/centreon-plugins/apps/redis/cli/mode/replication.pm index 1004d545f..515d80518 100644 --- a/centreon-plugins/apps/redis/cli/mode/replication.pm +++ b/centreon-plugins/apps/redis/cli/mode/replication.pm @@ -25,32 +25,26 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; -my $thresholds = { - link => [ - ['down', 'CRITICAL'], - ['up', 'OK'], - ], - sync => [ - ['stopped', 'OK'], - ['in progress', 'WARNING'], - ], -}; - -my %map_sync = ( - 0 => 'stopped', - 1 => 'in progress', -); +my $instance_mode; sub set_counters { my ($self, %options) = @_; $self->{maps_counters_type} = [ - { name => 'global', type => 0 }, - { name => 'master', type => 0 }, - { name => 'slave', type => 0 } + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, + { name => 'master', type => 0, skipped_code => { -10 => 1 } }, + { name => 'slave', type => 0, skipped_code => { -10 => 1 } }, ]; $self->{maps_counters}->{global} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'link_status' }, { name => 'sync_status' }, { name => 'role' }, { name => 'cluster_state' } ], + closure_custom_calc => $self->can('custom_status_calc'), + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => $self->can('custom_status_threshold'), + } + }, { label => 'connected-slaves', set => { key_values => [ { name => 'connected_slaves' } ], output_template => 'Number of connected slaves: %s', @@ -108,6 +102,51 @@ sub set_counters { ]; } +sub custom_status_threshold { + my ($self, %options) = @_; + my $status = 'ok'; + my $message; + + eval { + local $SIG{__WARN__} = sub { $message = $_[0]; }; + local $SIG{__DIE__} = sub { $message = $_[0]; }; + + if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' && + eval "$instance_mode->{option_results}->{critical_status}") { + $status = 'critical'; + } elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' && + eval "$instance_mode->{option_results}->{warning_status}") { + $status = 'warning'; + } + }; + if (defined($message)) { + $self->{output}->output_add(long_msg => 'filter status issue: ' . $message); + } + + return $status; +} + +sub custom_status_output { + my ($self, %options) = @_; + + my $msg = sprintf("Node role is '%s' [cluster: %s]", $self->{result_values}->{role}, $self->{result_values}->{cluster_state}); + if ($self->{result_values}->{role} eq 'slave') { + $msg .= sprintf(" [link status: %s] [sync status: %s]", + $self->{result_values}->{link_status}, $self->{result_values}->{sync_status}); + } + return $msg; +} + +sub custom_status_calc { + my ($self, %options) = @_; + + $self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_role'}; + $self->{result_values}->{sync_status} = $options{new_datas}->{$self->{instance} . '_sync_status'}; + $self->{result_values}->{link_status} = $options{new_datas}->{$self->{instance} . '_link_status'}; + $self->{result_values}->{cluster_state} = $options{new_datas}->{$self->{instance} . '_cluster_state'}; + return 0; +} + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -117,7 +156,8 @@ sub new { $options{options}->add_options(arguments => { - "threshold-overload:s@" => { name => 'threshold_overload' }, + "warning-status:s" => { name => 'warning_status', default => '%{sync_status} =~ /in progress/i' }, + "critical-status:s" => { name => 'critical_status', default => '%{link_status} =~ /down/i' }, }); return $self; @@ -125,79 +165,52 @@ sub new { sub check_options { my ($self, %options) = @_; - $self->SUPER::init(%options); - - $self->{overload_th} = {}; - foreach my $val (@{$self->{option_results}->{threshold_overload}}) { - if ($val !~ /^(.*?),(.*?),(.*)$/) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); - $self->{output}->option_exit(); - } - my ($section, $status, $filter) = ($1, $2, $3); - if ($self->{output}->is_litteral_status(status => $status) == 0) { - $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'."); - $self->{output}->option_exit(); - } - $self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section})); - push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status}; - } + $self->SUPER::check_options(%options); + + $instance_mode = $self; + $self->change_macros(); } - -sub get_severity { +sub change_macros { my ($self, %options) = @_; - my $status = 'UNKNOWN'; # default - - if (defined($self->{overload_th}->{$options{section}})) { - foreach (@{$self->{overload_th}->{$options{section}}}) { - if ($options{value} =~ /$_->{filter}/i) { - $status = $_->{status}; - return $status; - } + + foreach (('warning_status', 'critical_status')) { + if (defined($self->{option_results}->{$_})) { + $self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g; } } - foreach (@{$thresholds->{$options{section}}}) { - if ($options{value} =~ /$$_[0]/i) { - $status = $$_[1]; - return $status; - } - } - - return $status; } +my %map_sync = ( + 0 => 'stopped', + 1 => 'in progress', +); + +my %map_cluster_state = ( + 0 => 'disabled', + 1 => 'enabled', +); + sub manage_selection { my ($self, %options) = @_; - $self->{redis} = $options{custom}; - $self->{results} = $self->{redis}->get_info(); - - my @exits; + my $results = $options{custom}->get_info(); - $self->{output}->output_add(short_msg => sprintf("Node is '%s'", $self->{results}->{role})); + $self->{global} = { + connected_slaves => $results->{connected_slaves}, + role => $results->{role}, + cluster_state => defined($results->{cluster_enabled}) ? $map_cluster_state{$results->{cluster_enabled}} : '-', + link_status => defined($results->{master_link_status}) ? $results->{master_link_status} : '-', + sync_status => defined($results->{master_sync_in_progress}) ? $map_sync{$results->{master_sync_in_progress}} : '-', + }; - $self->{global} = { 'connected_slaves' => $self->{results}->{connected_slaves} }; - - if ($self->{results}->{role} =~ /master/) { - $self->{master} = { 'master_repl_offset' => $self->{results}->{master_repl_offset} }; - } elsif ($self->{results}->{role} =~ /slave/) { - $self->{output}->output_add(short_msg => sprintf("Link with master '%s:%s' is '%s', Sync is '%s'", - $self->{results}->{master_host}, - $self->{results}->{master_port}, - $self->{results}->{master_link_status}, - $map_sync{$self->{results}->{master_sync_in_progress}})); - - push @exits, $self->get_severity(section => 'link', value => $self->{results}->{master_link_status}); - push @exits, $self->get_severity(section => 'sync', value => $map_sync{$self->{results}->{master_sync_in_progress}}); - - $self->{slave} = { 'master_last_io_seconds_ago' => $self->{results}->{master_last_io_seconds_ago}, - 'slave_repl_offset' => $self->{results}->{slave_repl_offset}, - 'slave_priority' => $self->{results}->{slave_priority}, - 'slave_read_only' => $self->{results}->{slave_read_only} }; - } - - my $exit = $self->{output}->get_most_critical(status => \@exits); - $self->{output}->output_add(severity => $exit); + $self->{master} = { master_repl_offset => $results->{master_repl_offset} }; + $self->{slave} = { + master_last_io_seconds_ago => $results->{master_last_io_seconds_ago}, + slave_repl_offset => $results->{slave_repl_offset}, + slave_priority => $results->{slave_priority}, + slave_read_only => $results->{slave_read_only}, + }; } 1; @@ -206,55 +219,31 @@ __END__ =head1 MODE -Check replication status +Check replication status. =over 8 -=item B<--threshold-overload> +=item B<--warning-status> -Set to overload default threshold values (syntax: section,status,regexp) -Example: --threshold-overload='link,OK,down' -Section can be: 'link', 'sync' +Set warning threshold for status (Default: '%{sync_status} =~ /in progress/i'). +Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} -=item B<--warning-connected-slaves> +=item B<--critical-status> -Warning threshold for number of connected slave +Set critical threshold for status (Default: '%{link_status} =~ /down/i'). +Can used special variables like: %{sync_status}, %{link_status}, %{cluster_state} -=item B<--critical-connected-slaves> +=item B<--warning-*> -Critical threshold for number of connected slave +Threshold warning. +Can be: 'connected-slaves', 'master-repl-offset', +'master-last-io', 'slave-priority', 'slave-read-only'. -=item B<--warning-master-repl-offset> +=item B<--critical-*> -Warning threshold for master replication offset (in second) - -=item B<--critical-master-repl-offset> - -Critical threshold for master replication offset (in second) - -=item B<--warning-master-last-io> - -Warning threshold for last interaction with master (in second) - -=item B<--critical-master-last-io> - -Critical threshold for last interaction with master (in second) - -=item B<--warning-slave-priority> - -Warning threshold for slave priority - -=item B<--critical-slave-priority> - -Critical threshold for slave priority - -=item B<--warning-slave-read-only> - -Warning threshold for slave being in read-only - -=item B<--critical-slave-read-only> - -Critical threshold for slave being in read-only +Threshold critical. +Can be: 'connected-slaves', 'master-repl-offset', +'master-last-io', 'slave-priority', 'slave-read-only'. =back diff --git a/centreon-plugins/apps/redis/cli/plugin.pm b/centreon-plugins/apps/redis/cli/plugin.pm index 2496285c5..a11ad34e1 100644 --- a/centreon-plugins/apps/redis/cli/plugin.pm +++ b/centreon-plugins/apps/redis/cli/plugin.pm @@ -32,7 +32,6 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( 'clients' => 'apps::redis::cli::mode::clients', - 'cluster' => 'apps::redis::cli::mode::cluster', 'commands' => 'apps::redis::cli::mode::commands', 'connections' => 'apps::redis::cli::mode::connections', 'cpu' => 'apps::redis::cli::mode::cpu', From 3e3b8b6bf11a28a5c218ca3e4827534040bad7ea Mon Sep 17 00:00:00 2001 From: Colin GAGNAIRE Date: Tue, 5 Dec 2017 17:03:28 +0100 Subject: [PATCH 40/45] Fix cpu mode --- centreon-plugins/apps/redis/cli/mode/cpu.pm | 57 ++++++++++++++------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/centreon-plugins/apps/redis/cli/mode/cpu.pm b/centreon-plugins/apps/redis/cli/mode/cpu.pm index 84012de27..8317d9527 100644 --- a/centreon-plugins/apps/redis/cli/mode/cpu.pm +++ b/centreon-plugins/apps/redis/cli/mode/cpu.pm @@ -24,6 +24,7 @@ use base qw(centreon::plugins::templates::counter); use strict; use warnings; +use Digest::MD5 qw(md5_hex); sub set_counters { my ($self, %options) = @_; @@ -34,36 +35,44 @@ sub set_counters { $self->{maps_counters}->{global} = [ { label => 'sys', set => { - key_values => [ { name => 'used_cpu_sys' } ], - output_template => 'System: %.2f %%', + key_values => [ { name => 'used_cpu_sys', diff => 1 } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_sys' }, + output_template => 'System: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', + per_second => 1, perfdatas => [ - { label => 'sys', value => 'used_cpu_sys_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + { label => 'sys', value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' }, ], - }, + } }, { label => 'user', set => { - key_values => [ { name => 'used_cpu_user' } ], - output_template => 'User: %.2f %%', + key_values => [ { name => 'used_cpu_user', diff => 1 } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_user' }, + output_template => 'User: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', + per_second => 1, perfdatas => [ - { label => 'user', value => 'used_cpu_user_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + { label => 'user', value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' }, ], - }, + } }, { label => 'sys-children', set => { - key_values => [ { name => 'used_cpu_sys_children' } ], - output_template => 'System children: %.2f %%', + key_values => [ { name => 'used_cpu_sys_children', diff => 1 } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_sys_children' }, + output_template => 'System children: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', + per_second => 1, perfdatas => [ - { label => 'sys_children', value => 'used_cpu_sys_children_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + { label => 'sys_children', value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' }, ], - }, + } }, { label => 'user-children', set => { - key_values => [ { name => 'used_cpu_user_children' } ], - output_template => 'User children: %.2f %%', + key_values => [ { name => 'used_cpu_user_children', diff => 1 } ], + closure_custom_calc => $self->can('custom_usage_calc'), closure_custom_calc_extra_options => { label_ref => 'used_cpu_user_children' }, + output_template => 'User children: %.2f %%', output_use => 'used_delta', threshold_use => 'used_delta', + per_second => 1, perfdatas => [ - { label => 'user_children', value => 'used_cpu_user_children_absolute', template => '%.2f', min => 0, max => 100, unit => '%' }, + { label => 'user_children', value => 'used_delta', template => '%.2f', min => 0, max => 100, unit => '%' }, ], - }, + } }, ]; } @@ -74,9 +83,18 @@ sub prefix_output { return "CPU usage: "; } +sub custom_usage_calc { + my ($self, %options) = @_; + + my $delta_total = $options{new_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}} - $options{old_datas}->{$self->{instance} . '_' . $options{extra_options}->{label_ref}}; + $self->{result_values}->{used_delta} = 100 * $delta_total / $options{delta_time}; + + return 0; +} + sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1); bless $self, $class; $self->{version} = '1.0'; @@ -90,6 +108,9 @@ sub new { sub manage_selection { my ($self, %options) = @_; + + $self->{cache_name} = "redis_" . $self->{mode} . '_' . $options{custom}->get_connection_info() . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); my $results = $options{custom}->get_info(); @@ -107,7 +128,7 @@ __END__ =head1 MODE -Check CPU utilization +Check CPU utilization. =over 8 From 9fbcc8b643659eb00ca375733576a56a1a80f31d Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 6 Dec 2017 10:36:50 +0100 Subject: [PATCH 41/45] move dell fastpath modes --- .../fastpath/snmp}/mode/components/fan.pm | 4 ++-- .../fastpath/snmp}/mode/components/psu.pm | 4 ++-- .../fastpath/snmp}/mode/components/temperature.pm | 4 ++-- .../common/{fastpath => dell/fastpath/snmp}/mode/cpu.pm | 2 +- .../{fastpath => dell/fastpath/snmp}/mode/environment.pm | 6 +++--- .../{fastpath => dell/fastpath/snmp}/mode/memory.pm | 2 +- centreon-plugins/network/dell/6200/{ => snmp}/plugin.pm | 8 ++++---- centreon-plugins/network/dell/n4000/{ => snmp}/plugin.pm | 8 ++++---- 8 files changed, 19 insertions(+), 19 deletions(-) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/components/fan.pm (98%) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/components/psu.pm (97%) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/components/temperature.pm (98%) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/cpu.pm (99%) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/environment.pm (95%) rename centreon-plugins/centreon/common/{fastpath => dell/fastpath/snmp}/mode/memory.pm (98%) rename centreon-plugins/network/dell/6200/{ => snmp}/plugin.pm (90%) rename centreon-plugins/network/dell/n4000/{ => snmp}/plugin.pm (90%) diff --git a/centreon-plugins/centreon/common/fastpath/mode/components/fan.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/fan.pm similarity index 98% rename from centreon-plugins/centreon/common/fastpath/mode/components/fan.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/fan.pm index 1017e753f..564834bf9 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/components/fan.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/fan.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::components::fan; +package centreon::common::dell::fastpath::snmp::mode::components::fan; use strict; use warnings; @@ -87,4 +87,4 @@ sub check { } } -1; \ No newline at end of file +1; diff --git a/centreon-plugins/centreon/common/fastpath/mode/components/psu.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/psu.pm similarity index 97% rename from centreon-plugins/centreon/common/fastpath/mode/components/psu.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/psu.pm index 0882fa895..e5b675f6b 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/components/psu.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/psu.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::components::psu; +package centreon::common::dell::fastpath::snmp::mode::components::psu; use strict; use warnings; @@ -75,4 +75,4 @@ sub check { } } -1; \ No newline at end of file +1; diff --git a/centreon-plugins/centreon/common/fastpath/mode/components/temperature.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/temperature.pm similarity index 98% rename from centreon-plugins/centreon/common/fastpath/mode/components/temperature.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/temperature.pm index 6f9c999aa..d72626baa 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/components/temperature.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/components/temperature.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::components::temperature; +package centreon::common::dell::fastpath::snmp::mode::components::temperature; use strict; use warnings; @@ -96,4 +96,4 @@ sub check { } } -1; \ No newline at end of file +1; diff --git a/centreon-plugins/centreon/common/fastpath/mode/cpu.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/cpu.pm similarity index 99% rename from centreon-plugins/centreon/common/fastpath/mode/cpu.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/cpu.pm index ac99e514d..8a61c0251 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/cpu.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/cpu.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::cpu; +package centreon::common::dell::fastpath::snmp::mode::cpu; use base qw(centreon::plugins::mode); diff --git a/centreon-plugins/centreon/common/fastpath/mode/environment.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/environment.pm similarity index 95% rename from centreon-plugins/centreon/common/fastpath/mode/environment.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/environment.pm index 5957b2a36..569c85100 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/environment.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/environment.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::environment; +package centreon::common::dell::fastpath::snmp::mode::environment; use base qw(centreon::plugins::templates::hardware); @@ -54,7 +54,7 @@ sub set_system { ], }; - $self->{components_path} = 'centreon::common::fastpath::mode::components'; + $self->{components_path} = 'centreon::common::dell::fastpath::snmp::mode::components'; $self->{components_module} = ['fan', 'psu', 'temperature']; } @@ -126,4 +126,4 @@ Example: --critical='fan,.*,2000' =back -=cut \ No newline at end of file +=cut diff --git a/centreon-plugins/centreon/common/fastpath/mode/memory.pm b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/memory.pm similarity index 98% rename from centreon-plugins/centreon/common/fastpath/mode/memory.pm rename to centreon-plugins/centreon/common/dell/fastpath/snmp/mode/memory.pm index c643a841f..43d53bd20 100644 --- a/centreon-plugins/centreon/common/fastpath/mode/memory.pm +++ b/centreon-plugins/centreon/common/dell/fastpath/snmp/mode/memory.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package centreon::common::fastpath::mode::memory; +package centreon::common::dell::fastpath::snmp::mode::memory; use base qw(centreon::plugins::mode); diff --git a/centreon-plugins/network/dell/6200/plugin.pm b/centreon-plugins/network/dell/6200/snmp/plugin.pm similarity index 90% rename from centreon-plugins/network/dell/6200/plugin.pm rename to centreon-plugins/network/dell/6200/snmp/plugin.pm index 198d0f68f..e321b9244 100644 --- a/centreon-plugins/network/dell/6200/plugin.pm +++ b/centreon-plugins/network/dell/6200/snmp/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::dell::6200::plugin; +package network::dell::6200::snmp::plugin; use strict; use warnings; @@ -32,10 +32,10 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( 'global-status' => 'centreon::common::dell::powerconnect3000::mode::globalstatus', - 'environment' => 'centreon::common::fastpath::mode::environment', + 'environment' => 'centreon::common::dell::fastpath::snmp::mode::environment', 'interfaces' => 'snmp_standard::mode::interfaces', - 'memory' => 'centreon::common::fastpath::mode::memory', - 'cpu' => 'centreon::common::fastpath::mode::cpu', + 'memory' => 'centreon::common::dell::fastpath::snmp::mode::memory', + 'cpu' => 'centreon::common::dell::fastpath::snmp::mode::cpu', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', ); diff --git a/centreon-plugins/network/dell/n4000/plugin.pm b/centreon-plugins/network/dell/n4000/snmp/plugin.pm similarity index 90% rename from centreon-plugins/network/dell/n4000/plugin.pm rename to centreon-plugins/network/dell/n4000/snmp/plugin.pm index e5b0e53b9..c0a0ad767 100644 --- a/centreon-plugins/network/dell/n4000/plugin.pm +++ b/centreon-plugins/network/dell/n4000/snmp/plugin.pm @@ -18,7 +18,7 @@ # limitations under the License. # -package network::dell::n4000::plugin; +package network::dell::n4000::snmp::plugin; use strict; use warnings; @@ -32,10 +32,10 @@ sub new { $self->{version} = '1.0'; %{$self->{modes}} = ( 'global-status' => 'centreon::common::dell::powerconnect3000::mode::globalstatus', - 'environment' => 'centreon::common::fastpath::mode::environment', + 'environment' => 'centreon::common::dell::fastpath::snmp::mode::environment', 'interfaces' => 'snmp_standard::mode::interfaces', - 'memory' => 'centreon::common::fastpath::mode::memory', - 'cpu' => 'centreon::common::fastpath::mode::cpu', + 'memory' => 'centreon::common::dell::fastpath::snmp::mode::memory', + 'cpu' => 'centreon::common::dell::fastpath::snmp::mode::cpu', 'list-interfaces' => 'snmp_standard::mode::listinterfaces', ); From 6299f38ab38ae9042690accc323544cdb4593d33 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 6 Dec 2017 13:49:14 +0100 Subject: [PATCH 42/45] enhance xtremio to manage cluster xms --- .../emc/xtremio/restapi/custom/xtremioapi.pm | 119 ++++++++++++++---- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm index 5ddc0815c..0fd5c04cf 100644 --- a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm +++ b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm @@ -23,16 +23,13 @@ package storage::emc::xtremio::restapi::custom::xtremioapi; use strict; use warnings; use centreon::plugins::http; +use centreon::plugins::statefile; use JSON; sub new { my ($class, %options) = @_; my $self = {}; bless $self, $class; - # $options{options} = options object - # $options{output} = output object - # $options{exit_value} = integer - # $options{noptions} = integer if (!defined($options{output})) { print "Class Custom: Need to specify 'output' argument.\n"; @@ -46,11 +43,12 @@ sub new { if (!defined($options{noptions})) { $options{options}->add_options(arguments => { - "hostname:s@" => { name => 'hostname', }, - "xtremio-username:s@" => { name => 'xtremio_username', }, - "xtremio-password:s@" => { name => 'xtremio_password', }, - "proxyurl:s@" => { name => 'proxyurl', }, - "timeout:s@" => { name => 'timeout', }, + "hostname:s@" => { name => 'hostname', }, + "xtremio-username:s@" => { name => 'xtremio_username', }, + "xtremio-password:s@" => { name => 'xtremio_password', }, + "proxyurl:s@" => { name => 'proxyurl', }, + "timeout:s@" => { name => 'timeout', }, + "reload-cache-time:s" => { name => 'reload_cache_time' }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -58,25 +56,21 @@ sub new { $self->{output} = $options{output}; $self->{mode} = $options{mode}; $self->{http} = centreon::plugins::http->new(output => $self->{output}); + $self->{statefile_cache_cluster} = centreon::plugins::statefile->new(%options); return $self; } -# Method to manage multiples sub set_options { my ($self, %options) = @_; - # options{options_result} $self->{option_results} = $options{option_results}; } -# Method to manage multiples sub set_defaults { my ($self, %options) = @_; - # options{default} - - # Manage default value + foreach (keys %{$options{default}}) { if ($_ eq $self->{mode}) { for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) { @@ -92,14 +86,13 @@ sub set_defaults { sub check_options { my ($self, %options) = @_; -# # return 1 = ok still hostname -# # return 0 = no hostname left $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; $self->{xtremio_username} = (defined($self->{option_results}->{xtremio_username})) ? shift(@{$self->{option_results}->{xtremio_username}}) : ''; $self->{xtremio_password} = (defined($self->{option_results}->{xtremio_password})) ? shift(@{$self->{option_results}->{xtremio_password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; $self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? shift(@{$self->{option_results}->{proxyurl}}) : undef; + $self->{reload_cache_time} = (defined($self->{option_results}->{reload_cache_time})) ? shift(@{$self->{option_results}->{reload_cache_time}}) : 180; if (!defined($self->{hostname})) { $self->{output}->add_option_msg(short_msg => "Need to specify hostname option."); @@ -113,6 +106,7 @@ sub check_options { if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { + $self->{statefile_cache_cluster}->check_options(option_results => $self->{option_results}); return 0; } return 1; @@ -136,6 +130,26 @@ sub settings { $self->{http}->set_options(%{$self->{option_results}}); } +sub cache_clusters { + my ($self, %options) = @_; + + my $has_cache_file = $self->{statefile_cache_cluster}->read(statefile => 'cache_xtremio_clusters_' . $self->{hostname} . '_' . $self->{port}); + my $timestamp_cache = $self->{statefile_cache_cluster}->get(name => 'last_timestamp'); + my $clusters = $self->{statefile_cache_cluster}->get(name => 'clusters'); + if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{reload_cache_time}) * 60))) { + $clusters = {}; + my $datas = { last_timestamp => time(), clusters => $clusters }; + my @items = $self->get_items(url => '/api/json/types/', + obj => 'clusters'); + foreach (@items) { + $clusters->{$_} = 1; + } + $self->{statefile_cache_cluster}->write(data => $datas); + } + + return $clusters; +} + sub get_items { my ($self, %options) = @_; @@ -157,28 +171,74 @@ sub get_items { my @items; foreach my $context (@{$decoded->{$options{obj}}}) { - push @items,$context->{name}; + push @items, $context->{name}; } return @items; } +sub get_details_data { + my ($self, %options) = @_; + + my $response = $self->{http}->request(url_path => $options{url}, + critical_status => '', warning_status => '', unknown_status => ''); + my $decoded; + eval { + $decoded = decode_json($response); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + $self->{output}->option_exit(); + } + + return $decoded; +} + + +sub get_details_lookup_clusters { + my ($self, %options) = @_; + + #Message if object not found: + #{ + # "message": "obj_not_found", + # "error_code": 400 + #} + # + my $clusters = $self->cache_clusters(); + foreach my $cluster_name (keys %$clusters) { + my $url = $options{url} . $options{append} . 'cluster-name=' . $cluster_name; + my $decoded = $self->get_details_data(url => $url); + return $decoded if (!defined($decoded->{error_code})); + } + + # object is not found. + $self->{output}->add_option_msg(short_msg => "xtremio api issue: cannot found object details"); + $self->{output}->option_exit(); +} + sub get_details { my ($self, %options) = @_; $self->settings(); + my $append = '?'; if ((defined($options{obj}) && $options{obj} ne '') && (defined($options{name}) && $options{name} ne '')) { - $options{url} .= $options{obj} . '/?name=' . $options{name} ; - } + $options{url} .= $options{obj} . '/?name=' . $options{name}; + $append = '&'; + } - my $response = $self->{http}->request(url_path => $options{url}); - my $decoded; - eval { - $decoded = decode_json($response); - }; - if ($@) { - $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + #Message when cluster id needed: + #{ + # "message": "cluster_id_is_required", + # "error_code": 400 + #} + # + my $decoded = $self->get_details_data(%options); + if (defined($decoded->{error_code}) && + ($decoded->{error_code} == 400 && $decoded->{message} eq 'cluster_id_is_required')) { + $decoded = $self->get_details_lookup_clusters(%options, append => $append); + } elsif (defined($decoded->{error_code})) { + $self->{output}->add_option_msg(short_msg => "xtremio api issue: $decoded->{message}"); $self->{output}->option_exit(); } @@ -222,6 +282,11 @@ Proxy URL if any Set HTTP timeout +=item B<--reload-cache-time> + +Time in seconds before reloading cache file (default: 180). +The cache is used when XMS manages multiple clusters. + =back =head1 DESCRIPTION From 9fd8d4b2fd115f139c8ecdbab2c89a878e479d77 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 6 Dec 2017 14:05:59 +0100 Subject: [PATCH 43/45] enhance xtermio --- .../storage/emc/xtremio/restapi/custom/xtremioapi.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm index 0fd5c04cf..c1389aec3 100644 --- a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm +++ b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm @@ -204,8 +204,10 @@ sub get_details_lookup_clusters { # "error_code": 400 #} # - my $clusters = $self->cache_clusters(); - foreach my $cluster_name (keys %$clusters) { + if (!defined($self->{cache_clusters})) { + $self->{cache_clusters} = $self->cache_clusters(); + } + foreach my $cluster_name (keys %{$self->{cache_clusters}}) { my $url = $options{url} . $options{append} . 'cluster-name=' . $cluster_name; my $decoded = $self->get_details_data(url => $url); return $decoded if (!defined($decoded->{error_code})); From 90ebe363bb572d06b6489c93bbc70a693dc493d4 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 6 Dec 2017 14:10:46 +0100 Subject: [PATCH 44/45] xtremio enhance fix --- .../storage/emc/xtremio/restapi/custom/xtremioapi.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm index c1389aec3..af3ba4ac0 100644 --- a/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm +++ b/centreon-plugins/storage/emc/xtremio/restapi/custom/xtremioapi.pm @@ -133,7 +133,7 @@ sub settings { sub cache_clusters { my ($self, %options) = @_; - my $has_cache_file = $self->{statefile_cache_cluster}->read(statefile => 'cache_xtremio_clusters_' . $self->{hostname} . '_' . $self->{port}); + my $has_cache_file = $self->{statefile_cache_cluster}->read(statefile => 'cache_xtremio_clusters_' . $self->{hostname}); my $timestamp_cache = $self->{statefile_cache_cluster}->get(name => 'last_timestamp'); my $clusters = $self->{statefile_cache_cluster}->get(name => 'clusters'); if ($has_cache_file == 0 || !defined($timestamp_cache) || ((time() - $timestamp_cache) > (($self->{reload_cache_time}) * 60))) { From e371751362b2e3c0404d2039f87837a58f33f726 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Wed, 6 Dec 2017 15:07:50 +0100 Subject: [PATCH 45/45] ref #312 --- .../fastpath/snmp/mode/components/fan.pm | 86 +++++++++++ .../fastpath/snmp/mode/components/psu.pm | 71 +++++++++ .../snmp/mode/components/temperature.pm | 86 +++++++++++ .../common/broadcom/fastpath/snmp/mode/cpu.pm | 123 ++++++++++++++++ .../broadcom/fastpath/snmp/mode/hardware.pm | 129 ++++++++++++++++ .../broadcom/fastpath/snmp/mode/memory.pm | 138 ++++++++++++++++++ .../network/ubiquiti/edge/snmp/plugin.pm | 52 +++++++ 7 files changed, 685 insertions(+) create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/fan.pm create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/psu.pm create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/temperature.pm create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/cpu.pm create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/hardware.pm create mode 100644 centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/memory.pm create mode 100644 centreon-plugins/network/ubiquiti/edge/snmp/plugin.pm diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/fan.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/fan.pm new file mode 100644 index 000000000..ab37053e9 --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/fan.pm @@ -0,0 +1,86 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::snmp::mode::components::fan; + +use strict; +use warnings; + +my %map_fan_status = ( + 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', + 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' +); + +my $mapping = { + boxServicesFanItemState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.6.1.3', map => \%map_fan_status }, + boxServicesFanSpeed => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.6.1.4' }, +}; +my $oid_boxServicesFansEntry = '.1.3.6.1.4.1.4413.1.1.43.1.6.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_boxServicesFansEntry, begin => $mapping->{boxServicesFanItemState}->{oid}, end => $mapping->{boxServicesFanSpeed}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesFansEntry}})) { + next if ($oid !~ /^$mapping->{boxServicesFanItemState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesFansEntry}, instance => $instance); + + next if ($self->check_filter(section => 'fan', instance => $instance)); + if ($result->{boxServicesFanItemState} =~ /notpresent/i) { + $self->absent_problem(section => 'fan', instance => $instance); + next; + } + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s, speed = %s]", + $instance, $result->{boxServicesFanItemState}, $instance, defined($result->{boxServicesFanSpeed}) ? $result->{boxServicesFanSpeed} : 'unknown')); + $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{boxServicesFanItemState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{boxServicesFanItemState})); + } + + next if (!defined($result->{boxServicesFanSpeed}) || $result->{boxServicesFanSpeed} !~ /[0-9]+/); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{boxServicesFanSpeed}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' is '%s' rpm", $instance, $result->{boxServicesFanSpeed})); + } + $self->{output}->perfdata_add(label => 'fan_' . $instance, unit => 'rpm', + value => $result->{boxServicesFanSpeed}, + warning => $warn, + critical => $crit, min => 0 + ); + } +} + +1; diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/psu.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/psu.pm new file mode 100644 index 000000000..6b8767ece --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/psu.pm @@ -0,0 +1,71 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::snmp::mode::components::psu; + +use strict; +use warnings; + +my %map_psu_status = ( + 1 => 'notpresent', 2 => 'operational', 3 => 'failed', 4 => 'powering', + 5 => 'nopower', 6 => 'notpowering', 7 => 'incompatible' +); + +my $mapping = { + boxServicesPowSupplyItemState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.7.1.3', map => \%map_psu_status }, +}; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $mapping->{boxServicesPowSupplyItemState}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}})) { + next if ($oid !~ /^$mapping->{boxServicesPowSupplyItemState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$mapping->{boxServicesPowSupplyItemState}->{oid}}, instance => $instance); + + next if ($self->check_filter(section => 'psu', instance => $instance)); + if ($result->{boxServicesPowSupplyItemState} =~ /notpresent/i) { + $self->absent_problem(section => 'psu', instance => $instance); + next; + } + + $self->{components}->{psu}->{total}++; + $self->{output}->output_add(long_msg => sprintf("power supply '%s' status is '%s' [instance = %s]", + $instance, $result->{boxServicesPowSupplyItemState}, $instance)); + $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{boxServicesPowSupplyItemState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Power supply '%s' status is '%s'", $instance, $result->{boxServicesPowSupplyItemState})); + } + } +} + +1; diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/temperature.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/temperature.pm new file mode 100644 index 000000000..bf85207ee --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/components/temperature.pm @@ -0,0 +1,86 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::snmp::mode::components::temperature; + +use strict; +use warnings; + +my %map_temp_status = ( + 0 => 'low', 1 => 'normal', 2 => 'warning', 3 => 'critical', + 4 => 'shutdown', 5 => 'notpresent', 6 => 'notoperational', +); + +my $mapping = { + boxServicesTempSensorState => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.8.1.4', map => \%map_temp_status }, + boxServicesTempSensorTemperature => { oid => '.1.3.6.1.4.1.4413.1.1.43.1.8.1.5' }, +}; +my $oid_boxServicesTempSensorsEntry = '.1.3.6.1.4.1.4413.1.1.43.1.8.1'; + +sub load { + my ($self) = @_; + + push @{$self->{request}}, { oid => $oid_boxServicesTempSensorsEntry, begin => $mapping->{boxServicesTempSensorState}->{oid}, end => $mapping->{boxServicesTempSensorTemperature}->{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')); + + my ($exit, $warn, $crit, $checked); + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_boxServicesTempSensorsEntry}})) { + next if ($oid !~ /^$mapping->{boxServicesTempSensorState}->{oid}\.(.*)$/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_boxServicesTempSensorsEntry}, instance => $instance); + + next if ($self->check_filter(section => 'temperature', instance => $instance)); + if ($result->{boxServicesTempSensorState} =~ /notpresent/i) { + $self->absent_problem(section => 'temperature', instance => $instance); + next; + } + + $self->{components}->{temperature}->{total}++; + $self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s, temperature = %s]", + $instance, $result->{boxServicesTempSensorState}, $instance, defined($result->{boxServicesTempSensorTemperature}) ? $result->{boxServicesTempSensorTemperature} : 'unknown')); + $exit = $self->get_severity(section => 'temperature', value => $result->{boxServicesTempSensorState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{boxServicesTempSensorState})); + } + + next if (!defined($result->{boxServicesTempSensorTemperature}) || $result->{boxServicesTempSensorTemperature} !~ /[0-9]+/); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{boxServicesTempSensorTemperature}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Temperature '%s' is '%s' rpm", $instance, $result->{boxServicesTempSensorTemperature})); + } + $self->{output}->perfdata_add(label => 'temp_' . $instance, unit => 'C', + value => $result->{boxServicesTempSensorTemperature}, + warning => $warn, + critical => $crit, + ); + } +} + +1; diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/cpu.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/cpu.pm new file mode 100644 index 000000000..bdcde39c0 --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/cpu.pm @@ -0,0 +1,123 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::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 => 'global', type => 0, cb_prefix_output => 'prefix_cpu_output' } + ]; + + $self->{maps_counters}->{global} = [ + { label => '5s', set => { + key_values => [ { name => 'usage_5s' } ], + output_template => '%.2f %% (5sec)', output_error_template => "%s (5sec)", + perfdatas => [ + { label => 'cpu_5s', value => 'usage_5s_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '1m', set => { + key_values => [ { name => 'usage_1m' } ], + output_template => '%.2f %% (1m)', output_error_template => "%s (1min)", + perfdatas => [ + { label => 'cpu_1m', value => 'usage_1m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => '5m', set => { + key_values => [ { name => 'usage_5m' } ], + output_template => '%.2f %% (5min)', output_error_template => "%s (5min)", + perfdatas => [ + { label => 'cpu_5m', value => 'usage_5m_absolute', template => '%.2f', + unit => '%', min => 0, max => 100 }, + ], + } + }, + ]; +} + +sub prefix_cpu_output { + my ($self, %options) = @_; + + return "CPU "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + # STRING: " 5 Secs ( 43.2625%) 60 Secs ( 13.9157%) 300 Secs ( 8.9274%)" + my $oid_agentSwitchCpuProcessTotalUtilization = '.1.3.6.1.4.1.4413.1.1.1.1.4.9.0'; + my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessTotalUtilization], nothing_quit => 1); + + $snmp_result->{$oid_agentSwitchCpuProcessTotalUtilization} =~ /\s*5\s*Secs\s*\(\s*(.*?)%\s*\)\s*60\s*Secs\s*\(\s*(.*?)%\s*\)\s*300\s*Secs\s*\(\s*(.*?)%\s*\)/i; + $self->{global} = { usage_5s => $1, usage_1m => $2, usage_5m => $3 }; +} + +1; + +__END__ + +=head1 MODE + +Check CPU usage. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='5m' + +=item B<--warning-*> + +Threshold warning. +Can be: '5s', '1m', '5m'. + +=item B<--critical-*> + +Threshold critical. +Can be: '5s', '1m', '5m'. + +=back + +=cut diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/hardware.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/hardware.pm new file mode 100644 index 000000000..6257ea940 --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/hardware.pm @@ -0,0 +1,129 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::snmp::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = '^(temperature|fan|psu)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(temperature|fan)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + default => [ + ['notPresent', 'OK'], + ['operational', 'OK'], + ['failed', 'CRITICAL'], + ['notpowering', 'WARNING'], + ['powering', 'OK'], + ['nopower', 'OK'], + ['incompatible', 'WARNING'], + ], + temperature => [ + ['low', 'OK'], + ['normal', 'OK'], + ['warning', 'WARNING'], + ['critical', 'CRITICAL'], + ['notpresent', 'OK'], + ['shutdown', 'OK'], + ['notoperational', 'WARNING'], + ], + }; + + $self->{components_path} = 'centreon::common::broadcom::fastpath::snmp::mode::components'; + $self->{components_module} = ['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); + bless $self, $class; + + $self->{version} = '1.0'; + $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: 'fan', 'psu', 'temperature'. + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=fan --filter=psu) +Can also exclude specific instance: --filter=fan,1.1 + +=item B<--absent-problem> + +Return an error if an entity is not 'present' (default is skipping) (comma seperated list) +Can be specific or global: --absent-problem=fan,1 + +=item B<--no-component> + +Return an error if no compenents are checked. +If total (with skipped) is 0. (Default: 'critical' returns). + +=item B<--threshold-overload> + +Set to overload default threshold values (syntax: section,[instance,]status,regexp) +It used before default thresholds (order stays). +Example: --threshold-overload='psu,CRITICAL,^(?!(operational)$)' + +=item B<--warning> + +Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --warning='temperature,.*,40' + +=item B<--critical> + +Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold) +Example: --critical='temperature,.*,50' + +=back + +=cut diff --git a/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/memory.pm b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/memory.pm new file mode 100644 index 000000000..3bee13503 --- /dev/null +++ b/centreon-plugins/centreon/common/broadcom/fastpath/snmp/mode/memory.pm @@ -0,0 +1,138 @@ +# +# Copyright 2017 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::common::broadcom::fastpath::snmp::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_usage_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add(label => 'used', unit => 'B', + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, 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->{label}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]); + return $exit; +} + +sub custom_usage_output { + my ($self, %options) = @_; + + my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total}); + my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used}); + my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free}); + + my $msg = sprintf("Memory Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", + $total_size_value . " " . $total_size_unit, + $total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used}, + $total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}); + return $msg; +} + +sub custom_usage_calc { + my ($self, %options) = @_; + + $self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'}; + $self->{result_values}->{prct_used} = $options{new_datas}->{$self->{instance} . '_prct_used'}; + + $self->{result_values}->{used} = int($self->{result_values}->{prct_used} * $self->{result_values}->{total} / 100); + $self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used}; + $self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used}; + + return 0; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'memory', type => 0 } + ]; + + $self->{maps_counters}->{memory} = [ + { label => 'usage', set => { + key_values => [ { name => 'prct_used' }, { name => 'total' } ], + closure_custom_calc => $self->can('custom_usage_calc'), + closure_custom_output => $self->can('custom_usage_output'), + closure_custom_perfdata => $self->can('custom_usage_perfdata'), + closure_custom_threshold_check => $self->can('custom_usage_threshold'), + } + }, + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => + { + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $oid_agentSwitchCpuProcessMemFree = '.1.3.6.1.4.1.4413.1.1.1.1.4.1.0'; # KB + my $oid_agentSwitchCpuProcessMemAvailable = '.1.3.6.1.4.1.4413.1.1.1.1.4.2.0'; # KB + my $snmp_result = $options{snmp}->get_leef(oids => [$oid_agentSwitchCpuProcessMemFree, $oid_agentSwitchCpuProcessMemAvailable], nothing_quit => 1); + + my $total = $snmp_result->{$oid_agentSwitchCpuProcessMemAvailable} * 1024; + $self->{memory} = { + prct_used => ($total - $snmp_result->{$oid_agentSwitchCpuProcessMemFree} * 1024) * 100 / $total, + total => $total, + }; +} + +1; + +__END__ + +=head1 MODE + +Check memory usage. + +=over 8 + +=item B<--warning-usage> + +Threshold warning (in percent). + +=item B<--critical-usage> + +Threshold critical (in percent). + +=back + +=cut diff --git a/centreon-plugins/network/ubiquiti/edge/snmp/plugin.pm b/centreon-plugins/network/ubiquiti/edge/snmp/plugin.pm new file mode 100644 index 000000000..c3cf26c72 --- /dev/null +++ b/centreon-plugins/network/ubiquiti/edge/snmp/plugin.pm @@ -0,0 +1,52 @@ +# +# Copyright 2017 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::ubiquiti::edge::snmp::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_snmp); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '1.0'; + %{$self->{modes}} = ( + 'cpu' => 'centreon::common::broadcom::fastpath::snmp::mode::cpu', + 'hardware' => 'centreon::common::broadcom::fastpath::snmp::mode::hardware', + 'interfaces' => 'snmp_standard::mode::interfaces', + 'list-interfaces' => 'snmp_standard::mode::listinterfaces', + 'memory' => 'centreon::common::broadcom::fastpath::snmp::mode::memory', + ); + + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Ubiquiti Edge Router in SNMP. + +=cut