From 296f9c6afba9512c9210855cd885be197adf1773 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 13 Jan 2020 15:35:10 +0100 Subject: [PATCH] wip: cisco cces + enhance global instance --- centreon/plugins/templates/counter.pm | 52 ++-- centreon/plugins/values.pm | 2 +- network/cisco/cces/restapi/custom/api.pm | 284 ++++++++++++++++++ network/cisco/cces/restapi/mode/callsrt.pm | 236 +++++++++++++++ .../cisco/cces/restapi/mode/callssummary.pm | 206 +++++++++++++ network/cisco/cces/restapi/mode/components.pm | 166 ++++++++++ .../cisco/cces/restapi/mode/components/ad.pm | 68 +++++ .../cisco/cces/restapi/mode/components/aic.pm | 102 +++++++ .../cisco/cces/restapi/mode/components/aoc.pm | 108 +++++++ .../cces/restapi/mode/components/camera.pm | 60 ++++ .../cces/restapi/mode/components/software.pm | 66 ++++ .../cisco/cces/restapi/mode/components/st.pm | 66 ++++ .../restapi/mode/components/temperature.pm | 57 ++++ .../cisco/cces/restapi/mode/components/vic.pm | 69 +++++ .../cisco/cces/restapi/mode/components/vis.pm | 60 ++++ .../cisco/cces/restapi/mode/components/voc.pm | 60 ++++ .../cces/restapi/mode/components/webex.pm | 57 ++++ network/cisco/cces/restapi/plugin.pm | 56 ++++ storage/hp/p2000/xmlapi/mode/volumesstats.pm | 1 - 19 files changed, 1754 insertions(+), 22 deletions(-) create mode 100644 network/cisco/cces/restapi/custom/api.pm create mode 100644 network/cisco/cces/restapi/mode/callsrt.pm create mode 100644 network/cisco/cces/restapi/mode/callssummary.pm create mode 100644 network/cisco/cces/restapi/mode/components.pm create mode 100644 network/cisco/cces/restapi/mode/components/ad.pm create mode 100644 network/cisco/cces/restapi/mode/components/aic.pm create mode 100644 network/cisco/cces/restapi/mode/components/aoc.pm create mode 100644 network/cisco/cces/restapi/mode/components/camera.pm create mode 100644 network/cisco/cces/restapi/mode/components/software.pm create mode 100644 network/cisco/cces/restapi/mode/components/st.pm create mode 100644 network/cisco/cces/restapi/mode/components/temperature.pm create mode 100644 network/cisco/cces/restapi/mode/components/vic.pm create mode 100644 network/cisco/cces/restapi/mode/components/vis.pm create mode 100644 network/cisco/cces/restapi/mode/components/voc.pm create mode 100644 network/cisco/cces/restapi/mode/components/webex.pm create mode 100644 network/cisco/cces/restapi/plugin.pm diff --git a/centreon/plugins/templates/counter.pm b/centreon/plugins/templates/counter.pm index ec7b5cfed..e47e39f32 100644 --- a/centreon/plugins/templates/counter.pm +++ b/centreon/plugins/templates/counter.pm @@ -226,9 +226,9 @@ sub run_global { next if (defined($self->{option_results}->{filter_counters}) && $self->{option_results}->{filter_counters} ne '' && $_->{label} !~ /$self->{option_results}->{filter_counters}/); - + $obj->set(instance => defined($force_instance) ? $force_instance : $options{config}->{name}); - + my ($value_check) = $obj->execute(new_datas => $self->{new_datas}, values => $self->{$options{config}->{name}}); next if (defined($options{config}->{skipped_code}) && defined($options{config}->{skipped_code}->{$value_check})); @@ -252,39 +252,45 @@ sub run_global { $short_msg .= $short_msg_append . $output; $short_msg_append = $message_separator; } - + $obj->perfdata(extra_instance => $multiple_parent); } my ($prefix_output, $suffix_output); - $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}) + $prefix_output = $self->call_object_callback(method_name => $options{config}->{cb_prefix_output}, instance_value => $self->{$options{config}->{name}}) if (defined($options{config}->{cb_prefix_output})); $prefix_output = '' if (!defined($prefix_output)); - - $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}) + + $suffix_output = $self->call_object_callback(method_name => $options{config}->{cb_suffix_output}, instance_value => $self->{$options{config}->{name}}) if (defined($options{config}->{cb_suffix_output})); $suffix_output = '' if (!defined($suffix_output)); - + if ($called_multiple == 1 && $long_msg ne '') { $self->{output}->output_add(long_msg => $options{indent_long_output} . $prefix_output. $long_msg . $suffix_output); } - + my $exit = $self->{output}->get_most_critical(status => [ @exits ]); if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) { if ($called_multiple == 0) { - $self->{output}->output_add(severity => $exit, - short_msg => $prefix_output . $short_msg . $suffix_output); + $self->{output}->output_add( + severity => $exit, + short_msg => $prefix_output . $short_msg . $suffix_output + ); } else { - $self->run_multiple_prefix_output(severity => $exit, - short_msg => $prefix_output . $short_msg . $suffix_output); + $self->run_multiple_prefix_output( + severity => $exit, + short_msg => $prefix_output . $short_msg . $suffix_output + ); } } else { if ($long_msg ne '' && $multiple_parent == 0) { if ($called_multiple == 0) { $self->{output}->output_add(short_msg => $prefix_output . $long_msg . $suffix_output) ; } else { - $self->run_multiple_prefix_output(severity => 'ok', - short_msg => $prefix_output . $long_msg . $suffix_output); + $self->run_multiple_prefix_output( + severity => 'ok', + short_msg => $prefix_output . $long_msg . $suffix_output + ); } } } @@ -400,20 +406,26 @@ sub run_group { } if ($multiple == 1) { - $self->{output}->output_add(severity => 'OK', - short_msg => $options{config}->{message_multiple}); + $self->{output}->output_add( + severity => 'OK', + short_msg => $options{config}->{message_multiple} + ); } my $format_output = defined($options{config}->{format_output}) ? $options{config}->{format_output} : '%s problem(s) detected'; - + my ($global_exit, $total_problems) = ([], 0); foreach my $id (sort keys %{$self->{$options{config}->{name}}}) { $self->{most_critical_instance} = 'ok'; if (defined($options{config}->{cb_long_output})) { - $self->{output}->output_add(long_msg => $self->call_object_callback(method_name => $options{config}->{cb_long_output}, - instance_value => $self->{$options{config}->{name}}->{$id})); + $self->{output}->output_add( + long_msg => $self->call_object_callback( + method_name => $options{config}->{cb_long_output}, + instance_value => $self->{$options{config}->{name}}->{$id} + ) + ); } - + foreach my $group (@{$options{config}->{group}}) { $self->{$group->{name}} = $self->{$options{config}->{name}}->{$id}->{$group->{name}}; diff --git a/centreon/plugins/values.pm b/centreon/plugins/values.pm index 4e5ce501a..33d9c7826 100644 --- a/centreon/plugins/values.pm +++ b/centreon/plugins/values.pm @@ -141,7 +141,7 @@ sub output { if (defined($self->{closure_custom_output})) { return $self->{closure_custom_output}->($self); } - my $first = $self->{key_values}->[0]->{name}; + my $first = defined($self->{key_values}->[0]) ? $self->{key_values}->[0]->{name} : undef; my ($value, $unit) = (defined($first) ? $self->{result_values}->{$first . '_absolute'} : '', $self->{output_absolute_unit}); if (!defined($self->{output_use})) { diff --git a/network/cisco/cces/restapi/custom/api.pm b/network/cisco/cces/restapi/custom/api.pm new file mode 100644 index 000000000..9f6bf4aaa --- /dev/null +++ b/network/cisco/cces/restapi/custom/api.pm @@ -0,0 +1,284 @@ +# +# Copyright 2020 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::cisco::cces::restapi::custom::api; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::http; +use centreon::plugins::statefile; +use XML::Simple; +use Digest::MD5 qw(md5_hex); + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + 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'}, + 'proto:s' => { name => 'proto' }, + 'api-username:s' => { name => 'api_username' }, + 'api-password:s' => { name => 'api_password' }, + 'timeout:s' => { name => 'timeout', default => 30 }, + }); + } + + $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(%options); + $self->{cache} = centreon::plugins::statefile->new(%options); + + 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})) ? $self->{option_results}->{hostname} : undef; + $self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; + $self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; + $self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30; + $self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : undef; + $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : undef; + + if (!defined($self->{hostname}) || $self->{hostname} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); + $self->{output}->option_exit(); + } + if (!defined($self->{api_username}) || $self->{api_username} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --api-username option."); + $self->{output}->option_exit(); + } + if (!defined($self->{api_password}) || $self->{api_password} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --api-password option."); + $self->{output}->option_exit(); + } + + $self->{cache}->check_options(option_results => $self->{option_results}); + return 0; +} + +sub build_options_for_httplib { + my ($self, %options) = @_; + + $self->{option_results}->{hostname} = $self->{hostname}; + $self->{option_results}->{port} = $self->{port}; + $self->{option_results}->{proto} = $self->{proto}; + $self->{option_results}->{timeout} = $self->{timeout}; +} + +sub settings { + my ($self, %options) = @_; + + $self->build_options_for_httplib(); + $self->{http}->add_header(key => 'Content-Type', value => 'text/xml'); + $self->{http}->add_header(key => 'Accept', value => 'text/xml'); + $self->{http}->set_options(%{$self->{option_results}}); +} + +sub json_decode { + my ($self, %options) = @_; + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($options{content}); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +sub clean_session_cookie { + my ($self, %options) = @_; + + my $datas = { last_timestamp => time() }; + $options{statefile}->write(data => $datas); + $self->{session_cookie} = undef; + $self->{http}->add_header(key => 'Cookie', value => undef); +} + +sub authenticate { + my ($self, %options) = @_; + + my $has_cache_file = $options{statefile}->read(statefile => 'cces_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username})); + my $session_cookie = $options{statefile}->get(name => 'session_cookie'); + + if ($has_cache_file == 0 || !defined($session_cookie)) { + my $content = $self->{http}->request( + method => 'POST', + url_path => '/xmlapi/session/begin', + credentials => 1, basic => 1, + username => $self->{api_username}, + password => $self->{api_password}, + warning_status => '', unknown_status => '', critical_status => '', + curl_backend_options => { header => ['Content-Length: 0'] }, + ); + if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { + $self->{output}->add_option_msg(short_msg => "Login error [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); + $self->{output}->option_exit(); + } + + ($session_cookie) = $self->{http}->get_header(name => 'Set-Cookie'); + if (!defined($session_cookie)) { + $self->{output}->add_option_msg(short_msg => "Error retrieving cookie"); + $self->{output}->option_exit(); + } + + my $datas = { last_timestamp => time(), session_cookie => $session_cookie }; + $options{statefile}->write(data => $datas); + } + + $self->{session_cookie} = $session_cookie; + $self->{http}->add_header(key => 'Cookie', value => $self->{session_cookie}); +} + +sub request_api { + my ($self, %options) = @_; + + my $plop = do { + local $/ = undef; + if (!open my $fh, "<", '/tmp/plop.txt') { + $self->{output}->add_option_msg(short_msg => "Could not open file $self->{option_results}->{$_} : $!"); + $self->{output}->option_exit(); + } + <$fh>; + }; + eval { + $plop = XMLin($plop, ForceArray => $options{ForceArray}, KeyAttr => []); + }; + return $plop; + + $self->settings(); + if (!defined($self->{session_cookie})) { + $self->authenticate(statefile => $self->{cache}); + } + + my $content = $self->{http}->request( + %options, + warning_status => '', unknown_status => '', critical_status => '' + ); + + # Maybe there is an issue with the session_cookie. So we retry. + if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { + $self->clean_session_cookie(statefile => $self->{cache}); + $self->authenticate(statefile => $self->{cache}); + $content = $self->{http}->request( + %options, + warning_status => '', unknown_status => '', critical_status => '' + ); + } + + if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { + $self->{output}->add_option_msg(short_msg => 'api request error. use --debug.'); + $self->{output}->option_exit(); + } + + my $result; + eval { + $result = XMLin($content, ForceArray => $options{ForceArray}, KeyAttr => []); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); + $self->{output}->option_exit(); + } + + return $result; +} + +1; + +__END__ + +=head1 NAME + +CCES Rest API + +=head1 REST API OPTIONS + +=over 8 + +=item B<--hostname> + +Set hostname. + +=item B<--port> + +Set port (Default: '443'). + +=item B<--proto> + +Specify https if needed (Default: 'https'). + +=item B<--api-username> + +Set username. + +=item B<--api-password> + +Set password. + +=item B<--timeout> + +Threshold for HTTP timeout (Default: '30'). + +=back + +=cut diff --git a/network/cisco/cces/restapi/mode/callsrt.pm b/network/cisco/cces/restapi/mode/callsrt.pm new file mode 100644 index 000000000..5d9f65895 --- /dev/null +++ b/network/cisco/cces/restapi/mode/callsrt.pm @@ -0,0 +1,236 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::callsrt; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub custom_traffic_calc { + my ($self, %options) = @_; + + my $total_bytes = 0; + foreach (keys %{$options{new_datas}}) { + if (/\Q$self->{instance}\E_.*_bytes/) { + my $new_bytes = $options{new_datas}->{$_}; + next if (!defined($options{old_datas}->{$_})); + my $old_bytes = $options{old_datas}->{$_}; + my $bytes = $new_bytes - $old_bytes; + $bytes = $new_bytes if ($bytes < 0); + + $total_bytes += $bytes; + } + } + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{traffic_per_seconds} = ($total_bytes * 8) / $options{delta_time}; + return 0; +} + +sub custom_jitter_calc { + my ($self, %options) = @_; + + my $max_jitter = 0; + foreach (keys %{$options{new_datas}}) { + if (/\Q$self->{instance}\E_.*_maxjitter/) { + $max_jitter = $options{new_datas}->{$_} if ($options{new_datas}->{$_} > $max_jitter); + } + } + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{max_jitter} = $max_jitter; + return 0; +} + +sub custom_loss_calc { + my ($self, %options) = @_; + + my ($total_loss, $total_pkts) = (0, 0); + foreach (keys %{$options{new_datas}}) { + if (/\Q$self->{instance}\E_.*_loss/) { + my $new_loss = $options{new_datas}->{$_}; + next if (!defined($options{old_datas}->{$_})); + my $old_loss = $options{old_datas}->{$_}; + my $loss = $new_loss - $old_loss; + $loss = $new_loss if ($loss < 0); + + $total_loss += $loss; + } elsif (/\Q$self->{instance}\E_.*_packets/) { + my $new_pkts = $options{new_datas}->{$_}; + next if (!defined($options{old_datas}->{$_})); + my $old_pkts = $options{old_datas}->{$_}; + my $pkts = $new_pkts - $old_pkts; + $pkts = $new_pkts if ($pkts < 0); + + $total_pkts += $pkts; + } + } + + $self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'}; + $self->{result_values}->{packets_loss} = $total_loss; + $self->{result_values}->{packets_loss_prct} = 0; + $self->{result_values}->{packets} = $total_pkts; + if ($total_pkts > 0) { + $self->{result_values}->{packets_loss_prct} = ($total_loss * 100) / $total_pkts; + } + + return 0; +} + +sub custom_loss_output { + my ($self, %options) = @_; + + return sprintf( + "packets loss: %.2f%% (%s on %s)", + $self->{result_values}->{packets_loss_prct}, + $self->{result_values}->{packets_loss}, + $self->{result_values}->{packets} + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'channels', type => 1, cb_prefix_output => 'prefix_channels_output', message_multiple => 'All call channels are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{channels} = [ + { label => 'channels-traffic', nlabel => 'call.channels.traffic.bytes', set => { + key_values => [], + per_second => 1, manual_keys => 1, + closure_custom_calc => $self->can('custom_traffic_calc'), + output_template => 'traffic: %s %s/s', + output_change_bytes => 1, + output_use => 'traffic_per_seconds', threshold_use => 'traffic_per_seconds', + perfdatas => [ + { value => 'traffic_per_seconds', template => '%d', + unit => 'B/s', min => 0, label_extra_instance => 1, instance_use => 'display' }, + ], + } + }, + { label => 'channels-maxjitter', nlabel => 'call.channels.maxjitter.milliseconds', set => { + key_values => [], + manual_keys => 1, + closure_custom_calc => $self->can('custom_jitter_calc'), + output_template => 'max jitter: %s ms', + output_use => 'max_jitter', threshold_use => 'max_jitter', + perfdatas => [ + { value => 'max_jitter', template => '%d', + unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display' }, + ], + } + }, + { label => 'channels-packetloss', nlabel => 'call.channels.packetloss.count', set => { + key_values => [], + manual_keys => 1, + closure_custom_calc => $self->can('custom_loss_calc'), + closure_custom_output => $self->can('custom_loss_output'), + threshold_use => 'packets_loss', + perfdatas => [ + { value => 'packets_loss', template => '%d', + min => 0, label_extra_instance => 1, instance_use => 'display' }, + ], + } + }, + { label => 'channels-packetloss-prct', nlabel => 'call.channels.packetloss.percentage', display_ok => 0, set => { + key_values => [], + manual_keys => 1, + closure_custom_calc => $self->can('custom_loss_calc'), + closure_custom_output => $self->can('custom_loss_output'), + threshold_use => 'packets_loss_prct', + perfdatas => [ + { value => 'packets_loss_prct', template => '%d', + unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display' }, + ], + } + }, + ]; +} + +sub prefix_channels_output { + my ($self, %options) = @_; + + return "Channel '" . $options{instance_value}->{display} ."' "; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1, 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} = 'cces_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')); + + my $result = $options{custom}->request_api(url_path => '/status.xml', ForceArray => ['Call']); + foreach (('data~incoming', 'video~incoming~main', 'video~outgoing~main', + 'video~outgoing~presentation', 'video~incoming~presentation', + 'audio~incoming~main', 'audio~outgoing~main')) { + $self->{channels}->{$_} = { display => $_ }; + } + + return if (!defined($result->{MediaChannels}->{Call})); + + foreach my $call (@{$result->{MediaChannels}->{Call}}) { + foreach (@{$call->{Channel}}) { + my $instance = lc($_->{Type}) . '~' . lc($_->{Direction}); + $instance .= '~' . lc($_->{Audio}->{ChannelRole}) if (defined($_->{Audio})); + $instance .= '~' . lc($_->{Video}->{ChannelRole}) if (defined($_->{Video})); + + $self->{channels}->{$instance}->{$_->{item} . '_bytes'} = defined($_->{Netstat}->{Bytes}) ? $_->{Netstat}->{Bytes} : 0; + $self->{channels}->{$instance}->{$_->{item} . '_maxjitter'} = $_->{Netstat}->{MaxJitter} if (defined($_->{Netstat}->{MaxJitter})); + $self->{channels}->{$instance}->{$_->{item} . '_loss'} = defined($_->{Netstat}->{Loss}) ? $_->{Netstat}->{Loss} : 0; + $self->{channels}->{$instance}->{$_->{item} . '_packets'} = defined($_->{Netstat}->{Packets}) ? $_->{Netstat}->{Packets} : 0; + } + } +} + +1; + +__END__ + +=head1 MODE + +Check call channels in real-time. + +=over 8 + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'channels-traffic', 'channels-maxjitter' +'channels-packetloss', 'channels-packetloss-prct'. + +=back + +=cut diff --git a/network/cisco/cces/restapi/mode/callssummary.pm b/network/cisco/cces/restapi/mode/callssummary.pm new file mode 100644 index 000000000..a174e583b --- /dev/null +++ b/network/cisco/cces/restapi/mode/callssummary.pm @@ -0,0 +1,206 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::callssummary; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::statefile; +use Digest::MD5 qw(md5_hex); + +sub custom_loss_output { + my ($self, %options) = @_; + + return sprintf( + "packets loss: %.2f%% (%s on %s)", + $self->{result_values}->{loss_prct_absolute}, + $self->{result_values}->{loss_absolute}, + $self->{result_values}->{pkts_absolute} + ); +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return $options{instance_value}->{label} . ' '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, + { name => 'global_video_incoming', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, + { name => 'global_video_outgoing', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, + { name => 'global_audio_incoming', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, + { name => 'global_audio_outgoing', cb_prefix_output => 'prefix_global_output', type => 0, skipped_code => { -10 => 1 } }, + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total-finished', nlabel => 'calls.total.finished.count', set => { + key_values => [ { name => 'new_calls' } ], + output_template => 'total calls finished: %s', + output_change_bytes => 1, + perfdatas => [ + { value => 'new_calls_absolute', template => '%d', min => 0 }, + ], + } + } + ]; + + foreach my $type (('video', 'audio')) { + foreach my $direction (('incoming', 'outgoing')) { + $self->{maps_counters}->{'global_' . $type . '_' . $direction} = [ + { label => 'packetloss', nlabel => 'calls.' . $type . '.' . $direction . '.packetloss.count', set => { + key_values => [ { name => 'loss' }, { name => 'pkts' }, { name => 'loss_prct' } ], + closure_custom_output => $self->can('custom_loss_output'), + perfdatas => [ + { value => 'loss_absolute', template => '%d', min => 0 }, + ], + } + }, + { label => 'packetloss-prct', nlabel => 'calls.' . $type . '.' . $direction . '.packetloss.percentage', display_ok => 0, set => { + key_values => [ { name => 'loss_prct' }, { name => 'loss' }, { name => 'pkts' } ], + closure_custom_output => $self->can('custom_loss_output'), + perfdatas => [ + { value => 'loss_prct_absolute', template => '%d', unit => '%', min => 0, max => 100 }, + ], + } + }, + { label => 'maxjitter', nlabel => 'calls.' . $type . '.' . $direction . '.maxjitter.count', set => { + key_values => [ { name => 'maxjitter' } ], + output_template => 'max jitter: %s ms', + perfdatas => [ + { value => 'maxjitter_absolute', template => '%d', unit => 'ms', min => 0 }, + ], + } + }, + ]; + } + } +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $self->{version} = '1.0'; + $options{options}->add_options(arguments => { + }); + + centreon::plugins::misc::mymodule_load( + output => $self->{output}, + module => 'Date::Parse', + error_msg => "Cannot load module 'Date::Parse'." + ); + $self->{statefile_cache} = centreon::plugins::statefile->new(%options); + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->{statefile_cache}->check_options(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{statefile_cache}->read( + statefile => 'cces_' . $options{custom}->{hostname} . '_' . $self->{mode} . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) + ); + my $last_call_endtime = $self->{statefile_cache}->get(name => 'last_call_endtime'); + $last_call_endtime = 0 if (!defined($last_call_endtime)); + + my $result = $options{custom}->request_api( + method => 'POST', + url_path => '/putxml', + query_form_post => 'Full', + ForceArray => ['Entry'] + ); + + $self->{global} = { new_calls => 0 }; + $self->{global_video_incoming} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'video incoming' }; + $self->{global_video_outgoing} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'video outgoing' }; + $self->{global_audio_incoming} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'audio incoming' }; + $self->{global_audio_outgoing} = { loss => 0, pkts => 0, loss_prct => 0, maxjitter => 0, label => 'audio outgoing' }; + + return if (!defined($result->{CallHistoryGetResult}->{Entry})); + + my $save_last_time = 0; + foreach (@{$result->{CallHistoryGetResult}->{Entry}}) { + my $end_time = Date::Parse::str2time($_->{EndTimeUTC}); + if (!defined($end_time)) { + $self->{manager}->{output}->output_add( + severity => 'UNKNOWN', + short_msg => "can't parse date '" . $_->{EndTimeUTC} . "'" + ); + next; + } + $save_last_time = $end_time if ($save_last_time < $end_time); + next if ($end_time <= $last_call_endtime); + + $self->{global}->{new_calls}++; + foreach my $type (('Video', 'Audio')) { + foreach my $direction (('Incoming', 'Outgoing')) { + $self->{'global_' . lc($type) . '_' . lc($direction)}->{maxjitter} = $_->{$type}->{$direction}->{MaxJitter} + if ($self->{'global_' . lc($type) . '_' . lc($direction)}->{maxjitter} < $_->{$type}->{$direction}->{MaxJitter}); + if ($_->{$type}->{$direction}->{PacketLoss} =~ /^(\d+)\/(\d+)/) { + $self->{'global_' . lc($type) . '_' . lc($direction)}->{loss} += $1; + $self->{'global_' . lc($type) . '_' . lc($direction)}->{pkts} += $2; + } + } + } + } + + foreach my $type (('video', 'audio')) { + foreach my $direction (('incoming', 'outgoing')) { + $self->{'global_' . $type . '_' . $direction}->{loss_prct} = $self->{'global_' . $type . '_' . $direction}->{loss} * 100 / $self->{'global_' . $type . '_' . $direction}->{pkts} + if ($self->{'global_' . $type . '_' . $direction}->{pkts} > 0); + } + } + + $self->{statefile_cache}->write(data => { last_call_endtime => $save_last_time }); +} + +1; + +__END__ + +=head1 MODE + +Check call history. + +=over 8 + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'total-finished', 'packetloss' +'packetloss-prct', 'maxjitter'. + +=back + +=cut diff --git a/network/cisco/cces/restapi/mode/components.pm b/network/cisco/cces/restapi/mode/components.pm new file mode 100644 index 000000000..fd80f6907 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components.pm @@ -0,0 +1,166 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_overload_check_section_option} = + '^(?:ad|aic|aoc|camera|st|software|temperature|vic|vis|voc|webex)$'; + $self->{regexp_threshold_numeric_check_section_option} = '^(?:aiclatency|aocdelay)$'; + + $self->{cb_hook2} = 'execute_custom'; + + $self->{thresholds} = { + connection_status => [ + ['NotConnected', 'OK'], + ['Connected', 'OK'], + ['Unknown', 'UNKNOWN'], + ], + connected => [ + ['True', 'OK'], + ['False', 'WARNING'], + ['Unknown', 'UNKNOWN'], + ], + temperature => [ + ['Normal', 'OK'], + ['.*', 'CRITICAL'], + ], + software_status => [ + ['None', 'OK'], + ['InProgress', 'OK'], + ['InstallationFailed', 'CRITICAL'], + ['Failed', 'CRITICAL'], + ['Succeeded', 'OK'], + ], + software_urgency => [ + ['Low', 'OK'], + ['Medium', 'OK'], + ['Critical', 'CRITICAL'], + ], + signal_state => [ + ['OK', 'OK'], + ['Unsupported', 'WARNING'], + ['Unknown', 'UNKNOWN'], + ], + format_status => [ + ['Ok', 'OK'], + ['OutOfRange', 'WARNING'], + ['NotFound', 'OK'], + ['Error', 'CRITICAL'], + ['Interlaced', 'OK'], + ['Unknown', 'UNKNOWN'], + ], + webex => [ + ['Disabled', 'OK'], + ['Stopped', 'OK'], + ['Error', 'CRITICAL'], + ['Registered', 'OK'], + ['Registering', 'OK'], + ], + st_status => [ + ['Inactive', 'WARNING'], + ['Active', 'OK'], + ], + st_availability => [ + ['Unavailable', 'WARNING'], + ['Available', 'OK'], + ['Off', 'OK'], + ], + }; + + $self->{components_exec_load} = 0; + + $self->{components_path} = 'network::cisco::cces::restapi::mode::components'; + $self->{components_module} = [ + 'ad', 'aic', 'aoc', 'camera', 'st', 'software', 'temperature', 'vic', + 'vis', 'voc', 'webex' + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub execute_custom { + my ($self, %options) = @_; + + $self->{results} = $options{custom}->request_api( + url_path => '/status.xml', + ForceArray => ['Microphone', 'HDMI', 'Line', 'InternalSpeaker', 'Camera', 'Connector', 'Source'] + ); +} + +1; + +=head1 MODE + +Check components. + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'ad' (audio device), 'aic' (audio input connectors), 'aoc' (audio output connectors), +'camera', 'st' (speakerTrack), 'software', 'temperature', 'vic' (video input connectors), +'vis' (video input source), 'voc', (video output connectors), 'webex'. + +=item B<--filter> + +Exclude some parts (comma seperated list) +Can also exclude specific instance: --filter='aic,Microphone.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='ad.status,CRITICAL,NotConnected' + +=item B<--warning> + +Set warning threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) +Example: --warning='aiclatency,.*,20' + +=item B<--critical> + +Set critical threshold for 'temperature', 'fan', 'psu' (syntax: type,regexp,threshold) +Example: --critical='aiclatency,.*,50' + +=back + +=cut diff --git a/network/cisco/cces/restapi/mode/components/ad.pm b/network/cisco/cces/restapi/mode/components/ad.pm new file mode 100644 index 000000000..171ac4afc --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/ad.pm @@ -0,0 +1,68 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::ad; + +use strict; +use warnings; + +sub check_ad { + my ($self, %options) = @_; + + my $instance = $options{instance}; + next if ($self->check_filter(section => 'ad', instance => $instance)); + $self->{components}->{ad}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "audio device '%s' connection status is '%s' [instance: %s]", + $instance, $options{entry}->{ConnectionStatus}, $instance + ) + ); + + my $exit = $self->get_severity(label => 'connection_status', section => 'ad.status', value => $options{entry}->{ConnectionStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("audio device '%s' connection status is '%s'", $instance, $options{entry}->{ConnectionStatus}) + ); + } +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking audio devices'); + $self->{components}->{ad} = { name => 'audio devices', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'ad')); + + check_ad( + $self, + entry => $self->{results}->{Audio}->{Devices}->{HandsetUSB}, + instance => 'handsetUSB' + ); + check_ad( + $self, + entry => $self->{results}->{Audio}->{Devices}->{HeadsetUSB}, + instance => 'headsetUSB' + ); +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/aic.pm b/network/cisco/cces/restapi/mode/components/aic.pm new file mode 100644 index 000000000..36d1f6804 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/aic.pm @@ -0,0 +1,102 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::aic; + +use strict; +use warnings; + +sub check_aic { + my ($self, %options) = @_; + + foreach (@{$options{entry}->{ $options{element} }}) { + my $instance = $options{element} . ':' . $_->{item}; + + next if (!defined($_->{ConnectionStatus}) && !defined($_->{EcReferenceDelay})); + + next if ($self->check_filter(section => 'aic', instance => $instance)); + $self->{components}->{aic}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "audio input connector '%s' connection status is '%s' [instance: %s, latency: %s ms]", + $instance, + defined($_->{ConnectionStatus}) ? $_->{ConnectionStatus} : 'n/a', + $instance, + defined($_->{EcReferenceDelay}) ? $_->{EcReferenceDelay} : '-' + ) + ); + + if (defined($_->{ConnectionStatus})) { + my $exit = $self->get_severity(label => 'connection_status', section => 'aic.status', value => $_->{ConnectionStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("audio input connector '%s' connection status is '%s'", $instance, $_->{ConnectionStatus}) + ); + } + } + + if (defined($_->{EcReferenceDelay})) { + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'aiclatency', instance => $instance, value => $_->{EcReferenceDelay}); + + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "audio input connector '%s' latency is %s ms", + $instance, $_->{EcReferenceDelay} + ) + ); + } + $self->{output}->perfdata_add( + unit => 'ms', + nlabel => 'component.audio.input.connector.latency.milliseconds', + instances => [$options{element}, $_->{item}], + value => $_->{EcReferenceDelay}, + warning => $warn, + critical => $crit, + ); + } + } +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking audio input connectors'); + $self->{components}->{aic} = { name => 'audio input connectors', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'aic')); + + check_aic( + $self, + entry => $self->{results}->{Audio}->{Input}->{Connectors}, + element => 'Microphone', + instance => 'item' + ); + check_aic( + $self, + entry => $self->{results}->{Audio}->{Input}->{Connectors}, + element => 'HDMI', + instance => 'item' + ); +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/aoc.pm b/network/cisco/cces/restapi/mode/components/aoc.pm new file mode 100644 index 000000000..54d904391 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/aoc.pm @@ -0,0 +1,108 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::aoc; + +use strict; +use warnings; + +sub check_aoc { + my ($self, %options) = @_; + + foreach (@{$options{entry}->{ $options{element} }}) { + my $instance = $options{element} . ':' . $_->{item}; + + next if (!defined($_->{ConnectionStatus}) && !defined($_->{DelayMs})); + + next if ($self->check_filter(section => 'aoc', instance => $instance)); + $self->{components}->{aoc}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "audio output connector '%s' connection status is '%s' [instance: %s, delay: %s ms]", + $instance, + defined($_->{ConnectionStatus}) ? $_->{ConnectionStatus} : 'n/a', + $instance, + defined($_->{DelayMs}) ? $_->{DelayMs} : '-' + ) + ); + + if (defined($_->{ConnectionStatus})) { + my $exit = $self->get_severity(label => 'connection_status', section => 'aoc.status', value => $_->{ConnectionStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("audio output connector '%s' connection status is '%s'", $instance, $_->{ConnectionStatus}) + ); + } + } + + if (defined($_->{DelayMs})) { + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'aocdelay', instance => $instance, value => $_->{DelayMs}); + + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "audio output connector '%s' delay is %s ms", + $instance, $_->{EcReferenceDelay} + ) + ); + } + $self->{output}->perfdata_add( + unit => 'ms', + nlabel => 'component.audio.output.connector.delay.milliseconds', + instances => [$options{element}, $_->{item}], + value => $_->{DelayMs}, + warning => $warn, + critical => $crit, + ); + } + } +} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking audio output connectors'); + $self->{components}->{aoc} = { name => 'audio output connectors', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'aoc')); + + check_aoc( + $self, + entry => $self->{results}->{Audio}->{Output}->{Connectors}, + element => 'HDMI', + instance => 'item' + ); + check_aoc( + $self, + entry => $self->{results}->{Audio}->{Output}->{Connectors}, + element => 'InternalSpeaker', + instance => 'item' + ); + check_aoc( + $self, + entry => $self->{results}->{Audio}->{Output}->{Connectors}, + element => 'Line', + instance => 'item' + ); +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/camera.pm b/network/cisco/cces/restapi/mode/components/camera.pm new file mode 100644 index 000000000..03a61cfcd --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/camera.pm @@ -0,0 +1,60 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::camera; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking cameras'); + $self->{components}->{camera} = { name => 'cameras', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'camera')); + + return if (!defined($self->{results}->{Cameras}->{Camera})); + + foreach (@{$self->{results}->{Cameras}->{Camera}}) { + my $instance = $_->{item}; + + next if ($self->check_filter(section => 'camera', instance => $instance)); + $self->{components}->{camera}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "camera '%s' connection status is '%s' [instance: %s]", + $instance, + $_->{Connected}, + $instance, + ) + ); + + my $exit = $self->get_severity(label => 'connected', section => 'camera.status', value => $_->{Connected}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("camera '%s' connection status is '%s'", $instance, $_->{Connected}) + ); + } + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/software.pm b/network/cisco/cces/restapi/mode/components/software.pm new file mode 100644 index 000000000..efd8f6229 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/software.pm @@ -0,0 +1,66 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::software; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking software'); + $self->{components}->{software} = { name => 'software', total => 0, skip => 0 } ; + return if ($self->check_filter(section => 'software')); + + return if (!defined($self->{results}->{Provisioning}->{Software}->{UpgradeStatus})); + + my $instance = 'upgrade'; + return if ($self->check_filter(section => 'software', instance => $instance)); + $self->{components}->{software}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "software '%s' status is '%s' [instance: %s, urgency: %s]", + $instance, + $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}, + $instance, + $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency} + ) + ); + + my $exit = $self->get_severity(section => 'software_status', value => $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("software '%s' status is '%s'", $instance, $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Status}) + ); + } + + $exit = $self->get_severity(section => 'software_urgency', value => $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("software '%s' urgency is '%s'", $instance, $self->{results}->{Provisioning}->{Software}->{UpgradeStatus}->{Urgency}) + ); + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/st.pm b/network/cisco/cces/restapi/mode/components/st.pm new file mode 100644 index 000000000..6da741f57 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/st.pm @@ -0,0 +1,66 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::st; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking speaker track'); + $self->{components}->{st} = { name => 'speaker track', total => 0, skip => 0 } ; + return if ($self->check_filter(section => 'st')); + + return if (!defined($self->{results}->{Cameras}->{SpeakerTrack})); + + my $instance = 1; + return if ($self->check_filter(section => 'st', instance => $instance)); + $self->{components}->{st}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "speaker track '%s' status is '%s' [instance: %s, availability: %s]", + $instance, + $self->{results}->{Cameras}->{SpeakerTrack}->{Status}, + $instance, + $self->{results}->{Cameras}->{SpeakerTrack}->{Availability} + ) + ); + + my $exit = $self->get_severity(section => 'st_status', value => $self->{results}->{Cameras}->{SpeakerTrack}->{Status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("speaker track '%s' status is '%s'", $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Status}) + ); + } + + $exit = $self->get_severity(section => 'st_availability', value => $self->{results}->{Cameras}->{SpeakerTrack}->{Availability}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("speaker track '%s' availability is '%s'", $instance, $self->{results}->{Cameras}->{SpeakerTrack}->{Availability}) + ); + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/temperature.pm b/network/cisco/cces/restapi/mode/components/temperature.pm new file mode 100644 index 000000000..07437c329 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/temperature.pm @@ -0,0 +1,57 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::temperature; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking temperature'); + $self->{components}->{temperature} = { name => 'temperature', total => 0, skip => 0 } ; + return if ($self->check_filter(section => 'temperature')); + + return if (!defined($self->{results}->{SystemUnit}->{Hardware}->{Monitoring}->{Temperature})); + + my $instance = 1; + return if ($self->check_filter(section => 'temperature', instance => $instance)); + $self->{components}->{temperature}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "temperature '%s' status is '%s' [instance: %s]", + $instance, + $self->{results}->{SystemUnit}->{Hardware}->{Monitoring}->{Temperature}->{Status}, + $instance + ) + ); + + my $exit = $self->get_severity(section => 'temperature', value => $self->{results}->{SystemUnit}->{Hardware}->{Monitoring}->{Temperature}->{Status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("temperarture '%s' status is '%s'", $instance, $self->{results}->{SystemUnit}->{Hardware}->{Monitoring}->{Temperature}) + ); + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/vic.pm b/network/cisco/cces/restapi/mode/components/vic.pm new file mode 100644 index 000000000..63da03104 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/vic.pm @@ -0,0 +1,69 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::vic; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking video input connectors'); + $self->{components}->{vic} = { name => 'video input connectors', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'vic')); + + return if (!defined($self->{results}->{Video}->{Input}->{Connector})); + + foreach (@{$self->{results}->{Video}->{Input}->{Connector}}) { + my $instance = $_->{Type} . ':' . $_->{item}; + + next if ($self->check_filter(section => 'vic', instance => $instance)); + $self->{components}->{vic}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "video input connector '%s' connection status is '%s' [instance: %s, signal state: %s]", + $instance, + $_->{Connected}, + $instance, + $_->{SignalState} + ) + ); + + my $exit = $self->get_severity(label => 'connected', section => 'vic.status', value => $_->{Connected}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("video input connector '%s' connection status is '%s'", $instance, $_->{Connected}) + ); + } + + $exit = $self->get_severity(label => 'signal_state', section => 'vic.signal_state', value => $_->{SignalState}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("video input connector '%s' signal state is '%s'", $instance, $_->{SignalState}) + ); + } + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/vis.pm b/network/cisco/cces/restapi/mode/components/vis.pm new file mode 100644 index 000000000..86b91e31a --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/vis.pm @@ -0,0 +1,60 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::vis; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking video input sources'); + $self->{components}->{vis} = { name => 'video input sources', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'vis')); + + return if (!defined($self->{results}->{Video}->{Input}->{Source})); + + foreach (@{$self->{results}->{Video}->{Input}->{Source}}) { + my $instance = $_->{item}; + + next if ($self->check_filter(section => 'vis', instance => $instance)); + $self->{components}->{vis}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "video input source '%s' format status is '%s' [instance: %s]", + $instance, + $_->{FormatStatus}, + $instance + ) + ); + + my $exit = $self->get_severity(section => 'format_status', value => $_->{FormatStatus}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("video input source '%s' format status is '%s'", $instance, $_->{FormatStatus}) + ); + } + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/voc.pm b/network/cisco/cces/restapi/mode/components/voc.pm new file mode 100644 index 000000000..f8146ecce --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/voc.pm @@ -0,0 +1,60 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::voc; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking video output connectors'); + $self->{components}->{voc} = { name => 'video output connectors', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'voc')); + + return if (!defined($self->{results}->{Video}->{Output}->{Connector})); + + foreach (@{$self->{results}->{Video}->{Output}->{Connector}}) { + my $instance = $_->{Type} . ':' . $_->{item}; + + next if ($self->check_filter(section => 'voc', instance => $instance)); + $self->{components}->{vic}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "video output connector '%s' connection status is '%s' [instance: %s]", + $instance, + $_->{Connected}, + $instance + ) + ); + + my $exit = $self->get_severity(label => 'connected', section => 'voc.status', value => $_->{Connected}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("video output connector '%s' connection status is '%s'", $instance, $_->{Connected}) + ); + } + } +} + +1; diff --git a/network/cisco/cces/restapi/mode/components/webex.pm b/network/cisco/cces/restapi/mode/components/webex.pm new file mode 100644 index 000000000..6965229f5 --- /dev/null +++ b/network/cisco/cces/restapi/mode/components/webex.pm @@ -0,0 +1,57 @@ +# +# Copyright 2020 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::cisco::cces::restapi::mode::components::webex; + +use strict; +use warnings; + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking webex'); + $self->{components}->{webex} = { name => 'webex', total => 0, skip => 0 } ; + return if ($self->check_filter(section => 'webex')); + + return if (!defined($self->{results}->{Webex})); + + my $instance = 1; + return if ($self->check_filter(section => 'webex', instance => $instance)); + $self->{components}->{webex}->{total}++; + + $self->{output}->output_add( + long_msg => sprintf( + "webex '%s' status is '%s' [instance: %s]", + $instance, + $self->{results}->{Webex}->{Status}, + $instance + ) + ); + + my $exit = $self->get_severity(section => 'webex', value => $self->{results}->{Webex}->{Status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("webex '%s' status is '%s'", $instance, $self->{results}->{Webex}->{Status}) + ); + } +} + +1; diff --git a/network/cisco/cces/restapi/plugin.pm b/network/cisco/cces/restapi/plugin.pm new file mode 100644 index 000000000..965327d65 --- /dev/null +++ b/network/cisco/cces/restapi/plugin.pm @@ -0,0 +1,56 @@ +# +# Copyright 2020 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::cisco::cces::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}} = ( + 'components' => 'network::cisco::cces::restapi::mode::components', + 'calls-summary' => 'network::cisco::cces::restapi::mode::callssummary', + 'calls-rt' => 'network::cisco::cces::restapi::mode::callsrt', + ); + + $self->{custom_modes}{api} = 'network::cisco::cces::restapi::custom::api'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Cisco Collaboration Endpoint Software through HTTP/REST API. + +=over 8 + +=back + +=cut diff --git a/storage/hp/p2000/xmlapi/mode/volumesstats.pm b/storage/hp/p2000/xmlapi/mode/volumesstats.pm index bfe89fc1c..df1cb53b1 100644 --- a/storage/hp/p2000/xmlapi/mode/volumesstats.pm +++ b/storage/hp/p2000/xmlapi/mode/volumesstats.pm @@ -204,4 +204,3 @@ Allows to use regexp to filter volume name (with option --name). =back =cut -