diff --git a/centreon-plugins/network/stormshield/api/custom/api.pm b/centreon-plugins/network/stormshield/api/custom/api.pm new file mode 100644 index 000000000..e64163158 --- /dev/null +++ b/centreon-plugins/network/stormshield/api/custom/api.pm @@ -0,0 +1,410 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::custom::api; + +use strict; +use warnings; +use centreon::plugins::http; +use centreon::plugins::statefile; +use Digest::MD5 qw(md5_hex); +use MIME::Base64; +use XML::LibXML::Simple; +use URI::Encode; + +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 => { + 'api-username:s' => { name => 'api_username' }, + 'api-password:s' => { name => 'api_password' }, + 'hostname:s' => { name => 'hostname' }, + 'port:s' => { name => 'port' }, + 'proto:s' => { name => 'proto' }, + 'timeout:s' => { name => 'timeout' }, + 'unknown-http-status:s' => { name => 'unknown_http_status' }, + 'warning-http-status:s' => { name => 'warning_http_status' }, + 'critical-http-status:s' => { name => 'critical_http_status' } + }); + } + $options{options}->add_help(package => __PACKAGE__, sections => 'API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{http} = centreon::plugins::http->new(%options, default_backend => 'curl'); + $self->{cache} = centreon::plugins::statefile->new(%options); + + return $self; +} + +sub set_options { + my ($self, %options) = @_; + + $self->{option_results} = $options{option_results}; +} + +sub set_defaults {} + +sub check_options { + my ($self, %options) = @_; + + $self->{option_results}->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : ''; + $self->{option_results}->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443; + $self->{option_results}->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https'; + $self->{option_results}->{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} : ''; + $self->{api_password} = (defined($self->{option_results}->{api_password})) ? $self->{option_results}->{api_password} : ''; + $self->{unknown_http_status} = (defined($self->{option_results}->{unknown_http_status})) ? $self->{option_results}->{unknown_http_status} : '%{http_code} < 200 or %{http_code} >= 300'; + $self->{warning_http_status} = (defined($self->{option_results}->{warning_http_status})) ? $self->{option_results}->{warning_http_status} : ''; + $self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : ''; + + if ($self->{option_results}->{hostname} eq '') { + $self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.'); + $self->{output}->option_exit(); + } + if ($self->{api_username} eq '') { + $self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.'); + $self->{output}->option_exit(); + } + if ($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 settings { + my ($self, %options) = @_; + + return if (defined($self->{settings_done})); + $self->{http}->set_options(%{$self->{option_results}}); + $self->{http}->add_header(key => 'Accept', value => '*/*'); + $self->{settings_done} = 1; +} + +sub get_connection_info { + my ($self, %options) = @_; + + return $self->{option_results}->{hostname} . ':' . $self->{option_results}->{port}; +} + +sub decode_xml { + my ($self, %options) = @_; + + my $decoded; + eval { + $SIG{__WARN__} = sub {}; + $decoded = XMLin($options{content}, KeyAttr => [], ForceArray => ['serverd', 'section', 'key', 'line']); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +my $map_api_code = { + SSL_SERVERD_OK => 100, + SSL_SERVERD_REQUEST_ERROR => 200, + SSL_SERVERD_UNKNOWN_COMMAND => 201, + SSL_SERVERD_ERROR_COMMAND => 202, + SSL_SERVERD_INVALID_SESSION => 203, + SSL_SERVERD_EXPIRED_SESSION => 204, + SSL_SERVERD_AUTH_ERROR => 205, + SSL_SERVERD_PENDING_TRANSFER => 206, + SSL_SERVERD_PENDING_UPLOAD => 207, + SSL_SERVERD_OVERHEAT => 500, + SSL_SERVERD_UNREACHABLE => 501, + SSL_SERVERD_DISCONNECTED => 502, + SSL_SERVERD_INTERNAL_ERROR => 900 +}; +my $map_api_msg = { + $map_api_code->{SSL_SERVERD_REQUEST_ERROR} => "request error", + $map_api_code->{SSL_SERVERD_UNKNOWN_COMMAND} => "unknown command", + $map_api_code->{SSL_SERVERD_ERROR_COMMAND} => "command error", + $map_api_code->{SSL_SERVERD_INVALID_SESSION} => "invalid session", + $map_api_code->{SSL_SERVERD_EXPIRED_SESSION} => "expired session", + $map_api_code->{SSL_SERVERD_AUTH_ERROR} => "authentication error", + $map_api_code->{SSL_SERVERD_PENDING_TRANSFER} => "pending transfer", + $map_api_code->{SSL_SERVERD_PENDING_UPLOAD} => "upload pending", + $map_api_code->{SSL_SERVERD_OVERHEAT} => "server overheat", + $map_api_code->{SSL_SERVERD_UNREACHABLE} => "server unreachable", + $map_api_code->{SSL_SERVERD_DISCONNECTED} => "server disconnected", + $map_api_code->{SSL_SERVERD_INTERNAL_ERROR} => "internal error" +}; + +sub get_session_id { + my ($self, %options) = @_; + + my $has_cache_file = $self->{cache}->read(statefile => 'stormshield_' . md5_hex($self->get_connection_info() . '_' . $self->{api_username})); + my $session_id = $self->{cache}->get(name => 'session_id'); + my $cookie = $self->{cache}->get(name => 'cookie'); + my $md5_secret_cache = $self->{cache}->get(name => 'md5_secret'); + my $md5_secret = md5_hex($self->{api_username} . $self->{api_password}); + + if ($has_cache_file == 0 || + !defined($session_id) || + (defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret) + ) { + my $json_request = { + username => $self->{api_username}, + password => $self->{api_password}, + grant_type => 'password' + }; + + $self->settings(); + my ($content) = $self->{http}->request( + method => 'POST', + url_path => '/auth/admin.html', + post_param => [ + 'uid=' . MIME::Base64::encode_base64($self->{api_username}, ''), + 'pswd=' . MIME::Base64::encode_base64($self->{api_password}, ''), + 'app=sslclient' + ], + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status} + ); + + my $decoded = $self->decode_xml(content => $content); + if ($decoded->{msg} ne 'AUTH_SUCCESS') { + $self->{output}->add_option_msg(short_msg => 'Authentication failed: ' . $decoded->{msg}); + $self->{output}->option_exit(); + } + + my (@cookies) = $self->{http}->get_first_header(name => 'Set-Cookie'); + $cookie = ''; + foreach (@cookies) { + $cookie = $1 if (/(NETASQ_sslclient=.+?);/); + } + + if (!defined($cookie) || $cookie eq '') { + $self->{output}->add_option_msg(short_msg => 'Cannot get cookie'); + $self->{output}->option_exit(); + } + + ($content) = $self->{http}->request( + method => 'POST', + url_path => '/api/auth/login', + post_param => [ + 'app=sslclient', + 'id=0' + ], + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status}, + header => ['Cookie: ' . $cookie] + ); + + $decoded = $self->decode_xml(content => $content); + if ($decoded->{code} != $map_api_code->{SSL_SERVERD_OK}) { + $self->{output}->add_option_msg(short_msg => "Can't get serverd session: " . $map_api_msg->{ $decoded->{code} }); + $self->{output}->option_exit(); + } + if (!defined($decoded->{sessionid})) { + $self->{output}->add_option_msg(short_msg => "Can't get serverd session"); + $self->{output}->option_exit(); + } + + $session_id = $decoded->{sessionid}; + + my $datas = { + updated => time(), + cookie => $cookie, + session_id => $session_id, + md5_secret => $md5_secret + }; + $self->{cache}->write(data => $datas); + } + + return ($cookie, $session_id); +} + +sub clean_session_id { + my ($self, %options) = @_; + + my $datas = { updated => time() }; + $self->{cache}->write(data => $datas); +} + +sub request_api_internal { + my ($self, %options) = @_; + + $self->settings(); + my ($cookie, $session_id) = $self->get_session_id(); + + my $uri = URI::Encode->new({encode_reserved => 1}); + + # stormshield doesnt like the space separator + + my ($content) = $self->{http}->request( + url_path => '/api/command?sessionid=' . $session_id . '&cmd=' . $uri->encode($options{command}), + header => ['Cookie: ' . $cookie], + unknown_status => $options{unknown_status}, + warning_status => $options{warning_status}, + critical_status => $options{critical_status} + ); + + return $content; +} + +sub request { + my ($self, %options) = @_; + + my $content = $self->request_api_internal( + command => $options{command}, + unknown_status => '', + warning_status => '', + critical_status => '' + ); + + # Maybe token is invalid. so we retry + if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) { + $self->clean_session_id(); + $content = $self->request_api_internal( + command => $options{command}, + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status} + ); + } + + my $decoded = $self->decode_xml(content => $content); + if ($decoded->{code} == $map_api_code->{SSL_SERVERD_INVALID_SESSION} || + $decoded->{code} == $map_api_code->{SSL_SERVERD_EXPIRED_SESSION} || + $decoded->{code} == $map_api_code->{SSL_SERVERD_DISCONNECTED}) { + $self->clean_session_id(); + $content = $self->request_api_internal( + command => $options{command}, + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status} + ); + $decoded = $self->decode_xml(content => $content); + } + + if ($decoded->{code} != $map_api_code->{SSL_SERVERD_OK}) { + $self->{output}->add_option_msg(short_msg => "Command error: " . $map_api_msg->{ $decoded->{code} }); + $self->{output}->option_exit(); + } + + return $self->parse_format(xml => $decoded); +} + +sub parse_format { + my ($self, %options) = @_; + + my $code = scalar(@{$options{xml}->{serverd}}) > 1 ? $options{xml}->{serverd}->[1]->{ret} : $options{xml}->{serverd}->[0]->{ret}; + if ($code != $map_api_code->{SSL_SERVERD_OK}) { + $self->{output}->add_option_msg(short_msg => "Command error: " . $map_api_msg->{ $code }); + $self->{output}->option_exit(); + } + if ($options{xml}->{serverd}->[0]->{data}->{format} eq 'section') { + my $result = {}; + foreach my $section (@{$options{xml}->{serverd}->[0]->{data}->{section}}) { + $result->{ $section->{title} } = {}; + foreach my $entry (@{$section->{key}}) { + $result->{ $section->{title} }->{ $entry->{name} } = $entry->{value}; + } + } + + return $result; + } + + if ($options{xml}->{serverd}->[0]->{data}->{format} eq 'section_line') { + my $result = {}; + foreach my $section (@{$options{xml}->{serverd}->[0]->{data}->{section}}) { + $result->{ $section->{title} } = []; + foreach my $line (@{$section->{line}}) { + my $entry = {}; + foreach (@{$line->{key}}) { + $entry->{ $_->{name} } = $_->{value}; + } + + push @{$result->{ $section->{title} }}, $entry; + } + } + + return $result; + } + + $self->{output}->add_option_msg(short_msg => "Unsupported command response: " . $options{xml}->{serverd}->[0]->{data}->{format}); + $self->{output}->option_exit(); +} + +1; + +__END__ + +=head1 NAME + +Stormshield API + +=head1 API OPTIONS + +Stormshield API + +=over 8 + +=item B<--hostname> + +Set hostname. + +=item B<--port> + +Port used (Default: 443) + +=item B<--proto> + +Specify https if needed (Default: 'https') + +=item B<--api-username> + +API username. + +=item B<--api-password> + +API password. + +=item B<--timeout> + +Set timeout in seconds (Default: 30). + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/components/disk.pm b/centreon-plugins/network/stormshield/api/mode/components/disk.pm new file mode 100644 index 000000000..7437184ac --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/components/disk.pm @@ -0,0 +1,65 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::components::disk; + +use strict; +use warnings; + +sub load {} + +sub check { + my ($self) = @_; + + $self->{output}->output_add(long_msg => 'checking disks'); + $self->{components}->{disk} = { name => 'disks', total => 0, skip => 0 }; + return if ($self->check_filter(section => 'disk')); + + foreach my $label (keys %{$self->{results}}) { + next if ($label !~ /SMART_(\S+)$/i); + my $instance = $1; + + next if ($self->check_filter(section => 'disk', instance => $instance)); + + $self->{results}->{$label}->{DiskHealth} = lc($self->{results}->{$label}->{DiskHealth}); + + $self->{components}->{disk}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "disk '%s' status is %s [instance: %s]", + $instance, + $self->{results}->{$label}->{DiskHealth}, + $instance + ) + ); + + my $exit = $self->get_severity(section => 'disk', value => $self->{results}->{$label}->{DiskHealth}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Disk '%s' status is %s", $instance, $self->{results}->{$label}->{DiskHealth} + ) + ); + } + } +} + +1; diff --git a/centreon-plugins/network/stormshield/api/mode/components/fan.pm b/centreon-plugins/network/stormshield/api/mode/components/fan.pm new file mode 100644 index 000000000..876323cd1 --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/components/fan.pm @@ -0,0 +1,73 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::components::fan; + +use strict; +use warnings; + +sub load {} + +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 $label (keys %{$self->{results}}) { + next if ($label !~ /FANS_fan_(\d+)/i); + my $instance = 'fan' . $1; + my $num = $1; + next if ($self->check_filter(section => 'fan', instance => $instance)); + + next if ($self->{results}->{$label}->{Status} !~ /\d+/); + + $self->{components}->{fan}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "fan '%s' speed is %s rpm [instance: %s]", + $num, $self->{results}->{$label}->{Status}, $instance + ) + ); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $self->{results}->{$label}->{Status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Fan '%s' speed is '%s' rpm", $num, $self->{results}->{$label}->{Status} + ) + ); + } + $self->{output}->perfdata_add( + nlabel => 'hardware.fan.speed.rpm', + unit => 'rpm', + instances => $instance, + value => $self->{results}->{$label}->{Status}, + warning => $warn, + critical => $crit, + min => 0 + ); + } +} + +1; diff --git a/centreon-plugins/network/stormshield/api/mode/components/psu.pm b/centreon-plugins/network/stormshield/api/mode/components/psu.pm new file mode 100644 index 000000000..5ce5afb0e --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/components/psu.pm @@ -0,0 +1,90 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::components::psu; + +use strict; +use warnings; + +sub load {} + +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 $label (keys %{$self->{results}}) { + next if ($label !~ /POWERSUPPLY_POWER(\d+)/i); + my $instance = 'psu' . $1; + my $num = $1; + + next if ($self->check_filter(section => 'psu', instance => $instance)); + + $self->{results}->{$label}->{status} = lc($self->{results}->{$label}->{status}); + + $self->{components}->{psu}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "power supply '%s' status is %s [instance: %s, fan: %s rpm]", + $num, + $self->{results}->{$label}->{status}, + $instance, + $self->{results}->{$label}->{fan_speed} + ) + ); + + $exit = $self->get_severity(section => 'psu', value => $self->{results}->{$label}->{status}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Power supply '%s' status is %s", $instance, $self->{results}->{$label}->{status} + ) + ); + } + + next if ($self->{results}->{$label}->{status} ne 'ok'); + + ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $self->{results}->{$label}->{fan_speed}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Power supply '%s' speed is '%s' rpm", $num, $self->{results}->{$label}->{fan_speed} + ) + ); + } + + $self->{output}->perfdata_add( + nlabel => 'hardware.fan.speed.rpm', + unit => 'rpm', + instances => $instance, + value => $self->{results}->{$label}->{fan_speed}, + warning => $warn, + critical => $crit, + min => 0 + ); + } +} + +1; diff --git a/centreon-plugins/network/stormshield/api/mode/components/temperature.pm b/centreon-plugins/network/stormshield/api/mode/components/temperature.pm new file mode 100644 index 000000000..f84555929 --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/components/temperature.pm @@ -0,0 +1,84 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::components::temperature; + +use strict; +use warnings; + +sub load {} + +sub check_temperature { + my ($self, %options) = @_; + + return if ($self->check_filter(section => 'temperature', instance => $options{instance})); + + $self->{components}->{temperature}->{total}++; + $self->{output}->output_add( + long_msg => sprintf( + "temperature '%s' is %s celsius [instance: %s]", + $options{instance}, $options{value}, $options{instance} + ) + ); + + my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $options{instance}, value => $options{value}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf( + "Temperature '%s' is %s celsius", $options{instance}, $options{value} + ) + ); + } + + $self->{output}->perfdata_add( + nlabel => 'hardware.temperature.celsius', + unit => 'C', + instances => $options{instance}, + value => $options{value}, + warning => $warn, + critical => $crit + ); +} + +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')); + + check_temperature($self, instance => 'system', value => $self->{results}->{STAT_Result}->{temperature}); + my $num = 1; + foreach (split(/,/, $self->{results}->{STAT_Result}->{CPUthermal})) { + check_temperature($self, instance => 'cpu' . $num, value => $_); + $num++; + } + foreach my $label (keys %{$self->{results}}) { + if ($label =~ /POWERSUPPLY_POWER(\d+)/i && $self->{results}->{$label}->{powered} == 1) { + check_temperature($self, instance => 'psu' . $1, value => sprintf('%.2f', $self->{results}->{$label}->{temperature})); + } + if ($label =~ /SMART_(\S+)$/i) { + check_temperature($self, instance => 'disk_' . $1, value => $self->{results}->{$label}->{Temperature_Celsius}); + } + } +} + +1; diff --git a/centreon-plugins/network/stormshield/api/mode/cpu.pm b/centreon-plugins/network/stormshield/api/mode/cpu.pm new file mode 100644 index 000000000..d2da221ad --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/cpu.pm @@ -0,0 +1,124 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::cpu; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_cpu_core_output { + my ($self, %options) = @_; + + return "CPU '" . $options{instance} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'cpu_avg', type => 0 }, + { name => 'cpu_core', type => 1, cb_prefix_output => 'prefix_cpu_core_output' } + ]; + + $self->{maps_counters}->{cpu_avg} = [ + { label => 'average', nlabel => 'cpu.utilization.percentage', set => { + key_values => [ { name => 'average' } ], + output_template => 'CPU(s) average usage is: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + } + ]; + + $self->{maps_counters}->{cpu_core} = [ + { label => 'core', nlabel => 'core.cpu.utilization.percentage', set => { + key_values => [ { name => 'used' } ], + output_template => 'usage: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-core:s' => { name => 'filter_core' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $system = $options{custom}->request(command => 'monitor system'); + + my $cpu = 0; + + $self->{cpu_core} = {}; + foreach my $label (%{$system->{STAT_Result}}) { + next if ($label !~ /CPU(\d+)/); + my $num = $1; + + next if (defined($self->{option_results}->{filter_core}) && $self->{option_results}->{filter_core} ne '' && + $num !~ /$self->{option_results}->{filter_core}/); + my @values = split(/,/, $system->{STAT_Result}->{$label}); + my $used = $values[0] + $values[1] + $values[2]; + $self->{cpu_core}->{$num} = { used => $used }; + $cpu += $used; + } + + my $num_core = scalar(keys %{$self->{cpu_core}}); + $self->{cpu_avg} = { + average => $num_core > 0 ? $cpu / $num_core : '' + }; +} + +1; + +__END__ + +=head1 MODE + +Check cpu usage. + +=over 8 + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'core', 'average'. + +=item B<--filter-core> + +Core cpu to monitor (can be a regexp). + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/ha.pm b/centreon-plugins/network/stormshield/api/mode/ha.pm new file mode 100644 index 000000000..f44bc4593 --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/ha.pm @@ -0,0 +1,276 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::ha; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_link_status_output { + my ($self, %options) = @_; + + return sprintf( + 'link status: %s', + $self->{result_values}->{linkStatus} + ); +} + +sub custom_member_state_output { + my ($self, %options) = @_; + + return sprintf( + 'state: %s [mode: %s]', + $self->{result_values}->{state}, + $self->{result_values}->{mode} + ); +} + +sub custom_member_config_output { + my ($self, %options) = @_; + + return sprintf( + 'config sync: %s', + $self->{result_values}->{isConfigSync} + ); +} + +sub member_long_output { + my ($self, %options) = @_; + + return "checking member '" . $options{instance_value}->{name} . "'"; +} + +sub prefix_member_output { + my ($self, %options) = @_; + + return "member '" . $options{instance_value}->{name} . "' "; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'Members '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } }, + { name => 'members', type => 3, cb_prefix_output => 'prefix_member_output', cb_long_output => 'member_long_output', indent_long_output => ' ', message_multiple => 'All stack members are ok', + group => [ + { name => 'status', type => 0, skipped_code => { -10 => 1 } }, + { name => 'config', type => 0, skipped_code => { -10 => 1 } }, + { name => 'quality', type => 0, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'members-detected', nlabel => 'members.detected.count', display_ok => 0, set => { + key_values => [ { name => 'detected' } ], + output_template => 'members detected: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + ]; + + foreach ('none', 'starting', 'waiting_peer', 'running', 'ready', 'reboot', 'down', 'initializing') { + my $label = $_; + $label =~ s/_/-/; + push @{$self->{maps_counters}->{global}}, { + label => 'members-' . $label, nlabel => 'members.' . $_ . '.count', display_ok => 0, set => { + key_values => [ { name => 'state_' . $_ } ], + output_template => $_ . ': %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + } + + $self->{maps_counters}->{status} = [ + { label => 'member-state', type => 2, set => { + key_values => [ { name => 'state' }, { name => 'mode' }, { name => 'name' } ], + closure_custom_output => $self->can('custom_member_state_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { + label => 'member-link-status', + type => 2, + unknown_default => '%{linkStatus} =~ /unknown/i', + critical_default => '%{linkStatus} =~ /failed|failing/i', + set => { + key_values => [ { name => 'linkStatus' }, { name => 'name' } ], + closure_custom_output => $self->can('custom_link_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{config} = [ + { label => 'member-config', type => 2, warning_default => '%{isConfigSync} eq "no"', set => { + key_values => [ { name => 'isConfigSync' }, { name => 'name' } ], + closure_custom_output => $self->can('custom_member_config_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; + + $self->{maps_counters}->{quality} = [ + { label => 'member-quality', nlabel => 'member.quality.percentage', set => { + key_values => [ { name => 'current' } ], + output_template => 'quality: %.2f%%', + perfdatas => [ + { template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $ha = $options{custom}->request(command => 'ha info'); + + $self->{global} = { detected => 0 }; + foreach ('none', 'starting', 'waiting_peer', 'running', 'ready', 'reboot', 'down', 'initializing') { + $self->{global}->{'state_' . $_ } = 0; + } + + $self->{members} = {}; + foreach my $name (keys %$ha) { + my $values = {}; + foreach my $entry (@{$ha->{$name}}) { + foreach my $key (keys %$entry) { + $values->{$key} = $entry->{$key}; + } + } + + next if ($values->{Reply} == 0); + + $values->{State} = lc($values->{State}); + $values->{State} =~ s/ /_/g; + + $self->{global}->{detected}++; + $self->{global}->{'state_' . $values->{State} }++; + + $self->{members}->{$name} = { + name => $name, + status => { + name => $name, + mode => lc($values->{Mode}), + state => $values->{State}, + linkStatus => lc($values->{Link}) + }, + config => { + name => $name, + isConfigSync => $values->{IsConfigSync} =~ /1|true/i ? 'yes' : 'no' + }, + quality => { current => $values->{Quality} } + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check high availability. + +=over 8 + +=item B<--unknown-member-state> + +Set unknown threshold for status. +Can used special variables like: %{state}, %{name} + +=item B<--warning-member-state> + +Set warning threshold for status. +Can used special variables like: %{state}, %{name} + +=item B<--critical-member-state> + +Set critical threshold for status. +Can used special variables like: %{state}, %{name} + +=item B<--unknown-member-link-status> + +Set unknown threshold for status (Default: '%{linkStatus} =~ /unknown/i'). +Can used special variables like: %{linkStatus}, %{name} + +=item B<--warning-member-link-status> + +Set warning threshold for status. +Can used special variables like: %{linkStatus}, %{name} + +=item B<--critical-member-link-status> + +Set critical threshold for status (Default: '%{linkStatus} =~ /failed|failing/i'). +Can used special variables like: %{linkStatus}, %{name} + +=item B<--unknown-member-config> + +Set unknown threshold for status. +Can used special variables like: %{isConfigSync}, %{name} + +=item B<--warning-member-config> + +Set warning threshold for status (Default: '%{isConfigSync} eq "no"'). +Can used special variables like: %{isConfigSync}, %{name} + +=item B<--critical-member-config> + +Set critical threshold for status. +Can used special variables like: %{isConfigSync}, %{name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'member-quality', 'members-detected', 'members-none', +'members-starting', 'members-waiting-peer', 'members-running', +'members-ready', 'members-reboot', 'members-down', 'members-initializing'. + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/hardware.pm b/centreon-plugins/network/stormshield/api/mode/hardware.pm new file mode 100644 index 000000000..c80c34c1a --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/hardware.pm @@ -0,0 +1,111 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::hardware; + +use base qw(centreon::plugins::templates::hardware); + +use strict; +use warnings; + +sub set_system { + my ($self, %options) = @_; + + $self->{regexp_threshold_numeric_check_section_option} = '^(?:fan|temperature)$'; + + $self->{cb_hook2} = 'snmp_execute'; + + $self->{thresholds} = { + psu => [ + ['OK', 'OK'], + ['DUMMY', 'OK'], + ['FAILED', 'CRITICAL'], + ['NOTFOUND', 'OK'] + ], + disk => [ + ['passed', 'OK'], + ['failed', 'CRITICAL'] + ] + }; + + $self->{components_path} = 'network::stormshield::api::mode::components'; + $self->{components_module} = ['disk', 'fan', 'psu', 'temperature']; +} + +sub snmp_execute { + my ($self, %options) = @_; + + $self->{results} = $options{custom}->request(command => 'monitor system'); +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +1; + +__END__ + +=head1 MODE + +Check hardware. + +=over 8 + +=item B<--component> + +Which component to check (Default: '.*'). +Can be: 'disk', 'fan', 'psu', 'temperature'. + +=item B<--filter> + +Exclude some parts (comma seperated list) (Example: --filter=fan) +Can also exclude specific instance: --filter=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='disk,WARNING,missing' + +=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/stormshield/api/mode/health.pm b/centreon-plugins/network/stormshield/api/mode/health.pm new file mode 100644 index 000000000..70e1cf2ee --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/health.pm @@ -0,0 +1,153 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::health; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); + +sub custom_service_status_output { + my ($self, %options) = @_; + + return sprintf( + "health: %s", + $self->{result_values}->{health} + ); +} + +sub firewall_long_output { + my ($self, %options) = @_; + + return "checking firewall '" . $options{instance_value}->{display} . "'"; +} + +sub prefix_firewall_output { + my ($self, %options) = @_; + + return "firewall '" . $options{instance_value}->{display} . "' "; +} + +sub prefix_service_output { + my ($self, %options) = @_; + + return "service '" . $options{instance_value}->{service} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'firewalls', type => 3, cb_prefix_output => 'prefix_firewall_output', cb_long_output => 'firewall_long_output', + indent_long_output => ' ', message_multiple => 'All firewalls are ok', + group => [ + { name => 'services', display_long => 1, cb_prefix_output => 'prefix_service_output', message_multiple => 'all services are ok', type => 1, skipped_code => { -10 => 1 } } + ] + } + ]; + + $self->{maps_counters}->{services} = [ + { + label => 'service-status', + type => 2, + warning_default => '%{health} =~ /minor/i', + critical_default => '%{health} =~ /major/i', + set => { + key_values => [ { name => 'health' }, { name => 'service' } ], + closure_custom_output => $self->can('custom_service_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-serial:s' => { name => 'filter_serial' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $health = $options{custom}->request(command => 'monitor health'); + + $self->{firewalls} = {}; + foreach my $label (keys %$health) { + next if ($label eq 'MAIN'); + + next if (defined($self->{option_results}->{filter_serial}) && $self->{option_results}->{filter_serial} ne '' && + $label !~ /$self->{option_results}->{filter_serial}/); + + $self->{firewalls}->{$label} = { + display => $label, + services => {} + }; + + foreach my $service (keys %{$health->{$label}}) { + $self->{firewalls}->{$label}->{services}->{$service} = { + service => $service, + health => $health->{$label}->{$service} + }; + } + } +} + +1; + +__END__ + +=head1 MODE + +Check health. + +=over 8 + +=item B<--filter-serial> + +Filter by firewalls by serial (can be a regexp). + +=item B<--unknown-service-status> + +Set unknown threshold for status. +Can used special variables like: %{health}, %{service} + +=item B<--warning-service-status> + +Set warning threshold for status (Default: '%{health} =~ /minor/i'). +Can used special variables like: %{health}, %{service} + +=item B<--critical-service-status> + +Set critical threshold for status (Default: '%{health} =~ /major/i'). +Can used special variables like: %{health}, %{service} + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/interfaces.pm b/centreon-plugins/network/stormshield/api/mode/interfaces.pm new file mode 100644 index 000000000..000f869dd --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/interfaces.pm @@ -0,0 +1,461 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::interfaces; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng); +use Digest::MD5 qw(md5_hex); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf( + 'status: %s (%s)', + $self->{result_values}->{plugged}, + $self->{result_values}->{state} + ); +} + +sub custom_traffic_perfdata { + my ($self, %options) = @_; + + my ($warning, $critical); + if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'percent_delta' && defined($self->{result_values}->{speed})) { + $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1); + $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, total => $self->{result_values}->{speed}, cast_int => 1); + } elsif ($self->{instance_mode}->{option_results}->{units_traffic} =~ /bps|counter/) { + $warning = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}); + $critical = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}); + } + + if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'counter') { + my $nlabel = $self->{nlabel}; + $nlabel =~ s/bitspersecond/bits/; + $self->{output}->perfdata_add( + nlabel => $nlabel, + unit => 'b', + instances => [$self->{result_values}->{user_name}, $self->{result_values}->{real_name}], + value => $self->{result_values}->{traffic_counter}, + warning => $warning, + critical => $critical, + min => 0 + ); + } else { + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + instances => [$self->{result_values}->{user_name}, $self->{result_values}->{real_name}], + value => sprintf('%.2f', $self->{result_values}->{traffic_per_seconds}), + warning => $warning, + critical => $critical, + min => 0, + max => $self->{result_values}->{speed} + ); + } +} + +sub custom_traffic_threshold { + my ($self, %options) = @_; + + my $exit = 'ok'; + if ($self->{instance_mode}->{option_results}->{units_traffic} eq 'percent_delta' && defined($self->{result_values}->{speed})) { + $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'bps') { + $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_per_seconds}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + } elsif ($self->{instance_mode}->{option_results}->{units_traffic} eq 'counter') { + $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{traffic_counter}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + } + return $exit; +} + +sub custom_traffic_output { + my ($self, %options) = @_; + + my ($traffic_value, $traffic_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{traffic_per_seconds}, network => 1); + return sprintf( + 'traffic %s: %s/s (%s)', + $self->{result_values}->{label}, $traffic_value . $traffic_unit, + defined($self->{result_values}->{traffic_prct}) ? sprintf('%.2f%%', $self->{result_values}->{traffic_prct}) : '-' + ); +} + +sub custom_traffic_calc { + my ($self, %options) = @_; + + $self->{result_values}->{traffic_per_seconds} = ($options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} } - $options{old_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} }) / $options{delta_time}; + $self->{result_values}->{traffic_per_seconds} = sprintf('%d', $self->{result_values}->{traffic_per_seconds}); + + if (defined($options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}}) && + $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}} ne '' && + $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}} > 0) { + $self->{result_values}->{traffic_prct} = $self->{result_values}->{traffic_per_seconds} * 100 / $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}}; + $self->{result_values}->{speed} = $options{new_datas}->{$self->{instance} . '_speed_' . $options{extra_options}->{label_ref}}; + } + + $self->{result_values}->{label} = $options{extra_options}->{label_ref}; + $self->{result_values}->{user_name} = $options{new_datas}->{ $self->{instance} . '_user_name' }; + $self->{result_values}->{real_name} = $options{new_datas}->{ $self->{instance} . '_real_name' }; + return 0; +} + +############## +# Errors +sub custom_errors_perfdata { + my ($self, %options) = @_; + + if ($self->{instance_mode}->{option_results}->{units_errors} =~ /percent/) { + my $nlabel = $self->{nlabel}; + $nlabel =~ s/count$/percentage/; + + $self->{output}->perfdata_add( + nlabel => $nlabel, + unit => '%', + instances => [$self->{result_values}->{user_name}, $self->{result_values}->{real_name}], + value => sprintf('%.2f', $self->{result_values}->{prct}), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0, + max => 100 + ); + } else { + $self->{output}->perfdata_add( + nlabel => $self->{nlabel}, + instances => [$self->{result_values}->{user_name}, $self->{result_values}->{real_name}], + value => $self->{result_values}->{used}, + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0, + max => $self->{result_values}->{total} + ); + } +} + +sub custom_errors_threshold { + my ($self, %options) = @_; + + my $exit = 'ok'; + if ($self->{instance_mode}->{option_results}->{units_errors} =~ /percent/) { + $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + } else { + $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{used}, threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, { label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' } ]); + } + return $exit; +} + +sub custom_errors_output { + my ($self, %options) = @_; + + return sprintf( + 'packets %s: %.2f%% (%s on %s)', + $self->{result_values}->{label}, + $self->{result_values}->{prct}, + $self->{result_values}->{used}, + $self->{result_values}->{total} + ); +} + +sub custom_errors_calc { + my ($self, %options) = @_; + + my $errors = $options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} }; + my $errors_diff = $options{new_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} } - $options{old_datas}->{ $self->{instance} . '_' . $options{extra_options}->{label_ref} }; + my $total = $options{new_datas}->{$self->{instance} . '_total_packets'}; + my $total_diff = $options{new_datas}->{$self->{instance} . '_total_packets'} - $options{old_datas}->{$self->{instance} . '_total_packets'}; + + $self->{result_values}->{prct} = 0; + $self->{result_values}->{used} = $errors_diff; + $self->{result_values}->{total} = $total_diff; + if ($self->{instance_mode}->{option_results}->{units_errors} eq 'percent_delta') { + $self->{result_values}->{prct} = $errors_diff * 100 / $total_diff if ($total_diff > 0); + } elsif ($self->{instance_mode}->{option_results}->{units_errors} eq 'percent') { + $self->{result_values}->{prct} = $errors * 100 / $total if ($total > 0); + $self->{result_values}->{used} = $errors; + $self->{result_values}->{total} = $total; + } elsif ($self->{instance_mode}->{option_results}->{units_errors} eq 'delta') { + $self->{result_values}->{prct} = $errors_diff * 100 / $total_diff if ($total_diff > 0); + $self->{result_values}->{used} = $errors_diff; + } else { + $self->{result_values}->{prct} = $errors * 100 / $total if ($total > 0); + $self->{result_values}->{used} = $errors; + $self->{result_values}->{total} = $total; + } + + $self->{result_values}->{label} = $options{extra_options}->{label_ref}; + $self->{result_values}->{user_name} = $options{new_datas}->{ $self->{instance} . '_user_name' }; + $self->{result_values}->{real_name} = $options{new_datas}->{ $self->{instance} . '_real_name' }; + return 0; +} + +sub prefix_interface_output { + my ($self, %options) = @_; + + return sprintf( + "Interface '%s' [%s] ", + $options{instance_value}->{real_name}, + $options{instance_value}->{user_name} + ); +} + +sub skip_counters { + my ($self, %options) = @_; + + return (defined($self->{option_results}->{$options{filter}})) ? 0 : 1; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'interfaces', type => 1, cb_prefix_output => 'prefix_interface_output', message_multiple => 'All interfaces are ok', cb_init_counters => 'skip_counters', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{interfaces} = [ + { + label => 'status', + type => 2, + filter => 'add_status', + critical_default => "%{state} eq 'enabled' and %{plugged} eq 'unplugged'", set => { + key_values => [ { name => 'state' }, { name => 'plugged' }, { name => 'real_name' }, { name => 'user_name' } ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold_ng + } + }, + { label => 'in-traffic', filter => 'add_traffic', nlabel => 'interface.traffic.in.bitspersecond', set => { + key_values => [ { name => 'in', diff => 1 }, { name => 'speed_in' }, { name => 'real_name' }, { name => 'user_name' } ], + closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'in' }, + closure_custom_output => $self->can('custom_traffic_output'), output_error_template => 'traffic in: %s', + closure_custom_perfdata => $self->can('custom_traffic_perfdata'), + closure_custom_threshold_check => $self->can('custom_traffic_threshold') + } + }, + { label => 'out-traffic', filter => 'add_traffic', nlabel => 'interface.traffic.out.bitspersecond', set => { + key_values => [ { name => 'out', diff => 1 }, { name => 'speed_out' }, { name => 'real_name' }, { name => 'user_name' } ], + closure_custom_calc => $self->can('custom_traffic_calc'), closure_custom_calc_extra_options => { label_ref => 'out' }, + closure_custom_output => $self->can('custom_traffic_output'), output_error_template => 'traffic out: %s', + closure_custom_perfdata => $self->can('custom_traffic_perfdata'), + closure_custom_threshold_check => $self->can('custom_traffic_threshold') + } + }, + { label => 'packets-accepted', filter => 'add_errors', nlabel => 'interface.packets.accepted.count', set => { + key_values => [ { name => 'accepted', diff => 1 }, { name => 'total_packets', diff => 1 }, , { name => 'real_name' }, { name => 'user_name' } ], + closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref => 'accepted' }, + closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets blocked: %s', + closure_custom_perfdata => $self->can('custom_errors_perfdata'), + closure_custom_threshold_check => $self->can('custom_errors_threshold') + } + }, + { label => 'packets-blocked', filter => 'add_errors', nlabel => 'interface.packets.blocked.count', set => { + key_values => [ { name => 'blocked', diff => 1 }, { name => 'total_packets', diff => 1 }, , { name => 'real_name' }, { name => 'user_name' } ], + closure_custom_calc => $self->can('custom_errors_calc'), closure_custom_calc_extra_options => { label_ref => 'blocked' }, + closure_custom_output => $self->can('custom_errors_output'), output_error_template => 'packets blocked: %s', + closure_custom_perfdata => $self->can('custom_errors_perfdata'), + closure_custom_threshold_check => $self->can('custom_errors_threshold') + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, statefile => 1, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'filter-user-name:s' => { name => 'filter_user_name' }, + 'filter-real-name:s' => { name => 'filter_real_name' }, + 'add-status' => { name => 'add_status' }, + 'add-traffic' => { name => 'add_traffic' }, + 'add-errors' => { name => 'add_errors' }, + 'units-traffic:s' => { name => 'units_traffic', default => 'percent_delta' }, + 'speed:s' => { name => 'speed' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + # If no options, we set add-status + if (!defined($self->{option_results}->{add_traffic}) && + !defined($self->{option_results}->{add_errors}) && + !defined($self->{option_results}->{add_status})) { + $self->{option_results}->{add_status} = 1; + } + + if (defined($self->{option_results}->{speed}) && $self->{option_results}->{speed} ne '') { + if ($self->{option_results}->{speed} !~ /^[0-9]+(\.[0-9]+){0,1}$/) { + $self->{output}->add_option_msg(short_msg => "Speed must be a positive number '" . $self->{option_results}->{speed} . "' (can be a float also)."); + $self->{output}->option_exit(); + } else { + $self->{option_results}->{speed} *= 1000000; + } + } + + if (defined($self->{option_results}->{add_traffic})) { + $self->{option_results}->{units_traffic} = 'percent_delta' + if (!defined($self->{option_results}->{units_traffic}) || + $self->{option_results}->{units_traffic} eq '' || + $self->{option_results}->{units_traffic} eq '%'); + if ($self->{option_results}->{units_traffic} !~ /^(?:percent|percent_delta|bps|counter)$/) { + $self->{output}->add_option_msg(short_msg => 'Wrong option --units-traffic.'); + $self->{output}->option_exit(); + } + } + + if (defined($self->{option_results}->{add_errors})) { + $self->{option_results}->{units_errors} = 'percent_delta' + if (!defined($self->{option_results}->{units_errors}) || + $self->{option_results}->{units_errors} eq '' || + $self->{option_results}->{units_errors} eq '%'); + if ($self->{option_results}->{units_errors} !~ /^(?:percent|percent_delta|delta|counter)$/) { + $self->{output}->add_option_msg(short_msg => 'Wrong option --units-errors.'); + $self->{output}->option_exit(); + } + } + + $self->{checking} = ''; + foreach ('add_status', 'add_errors', 'add_traffic') { + if (defined($self->{option_results}->{$_})) { + $self->{checking} .= $_; + } + } +} + +my $map_state = { 0 => 'disabled', 1 => 'enabled' }; +my $map_plugged = { 0 => 'unplugged', 1 => 'plugged' }; + +sub manage_selection { + my ($self, %options) = @_; + + my $interfaces = $options{custom}->request(command => 'monitor interface'); + + $self->{interfaces} = {}; + foreach my $interface (@{$interfaces->{Result}}) { + my ($user_name, $real_name) = split(/,/, $interface->{name}); + next if (defined($self->{option_results}->{filter_user_name}) && $self->{option_results}->{filter_user_name} ne '' && + $user_name !~ /$self->{option_results}->{filter_user_name}/); + next if (defined($self->{option_results}->{filter_real_name}) && $self->{option_results}->{filter_real_name} ne '' && + $real_name !~ /$self->{option_results}->{filter_real_name}/); + + my ($traffic_out) = split(/,/, $interface->{byte_out}); + my ($traffic_in) = split(/,/, $interface->{byte}); + + my ($accepted, $blocked) = split(/,/, $interface->{packet}); + + $self->{interfaces}->{$real_name} = { + real_name => $real_name, + user_name => $user_name, + state => $map_state->{ $interface->{state} }, + plugged => $map_plugged->{ $interface->{plugged} }, + speed_in => defined($self->{option_results}->{speed}) ? $self->{option_results}->{speed} : '', + speed_out => defined($self->{option_results}->{speed}) ? $self->{option_results}->{speed} : '', + in => $traffic_in, + out => $traffic_out, + accepted => $accepted, + blocked => $blocked, + total_packets => $accepted + $blocked + }; + } + + if (scalar(keys %{$self->{interfaces}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "No interface found."); + $self->{output}->option_exit(); + } + + $self->{cache_name} = 'stormshield_' . $options{custom}->get_connection_info() . '_' . $self->{mode} . '_' . + md5_hex( + (defined($self->{option_results}->{filter_counters}) ? $self->{option_results}->{filter_counters} : '') . '_' . + (defined($self->{option_results}->{filter_real_name}) ? $self->{option_results}->{filter_real_name} : '') . '_' . + (defined($self->{option_results}->{filter_user_name}) ? $self->{option_results}->{filter_user_name} : '') . '_' . + $self->{checking} + ); +} + +1; + +__END__ + +=head1 MODE + +Check interfaces. + +=over 8 + +=item B<--filter-real-name> + +Filter interfaces by real name (regexp can be used). + +=item B<--filter-user-name> + +Filter interfaces by user name (regexp can be used). + +=item B<--add-status> + +Check interface status. + +=item B<--add-traffic> + +Check interface traffic. + +=item B<--add-errors> + +Check interface errors. + +=item B<--units-traffic> + +Units of thresholds for the traffic (Default: 'percent_delta') ('percent_delta', 'bps', 'counter'). + +=item B<--units-traffic> + +Units of thresholds for the traffic (Default: 'percent_delta') ('percent_delta', 'bps', 'counter'). + +=item B<--unknown-status> + +Set unknown threshold for status. +Can used special variables like: %{state}, %{plugged}, %{user_name}, %{real_name} + +=item B<--warning-status> + +Set warning threshold for status. +Can used special variables like: %{state}, %{plugged}, %{user_name}, %{real_name} + +=item B<--critical-status> + +Set critical threshold for status (Default: "%{state} eq 'enabled' and %{plugged} eq 'unplugged'") +Can used special variables like: %{state}, %{plugged}, %{user_name}, %{real_name} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'in-traffic', 'out-traffic', 'packets-accepted', 'packets-blocked', + +=item B<--speed> + +Set interface speed (in Mb). + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/listinterfaces.pm b/centreon-plugins/network/stormshield/api/mode/listinterfaces.pm new file mode 100644 index 000000000..e20df766d --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/listinterfaces.pm @@ -0,0 +1,112 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::listinterfaces; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +my @labels = ('user_name', 'real_name', 'state', 'plugged'); +my $map_state = { 0 => 'disabled', 1 => 'enabled' }; +my $map_plugged = { 0 => 'unplugged', 1 => 'plugged' }; + +sub manage_selection { + my ($self, %options) = @_; + + my $interfaces = $options{custom}->request(command => 'monitor interface'); + + my $results = {}; + foreach (@{$interfaces->{Result}}) { + my ($user_name, $real_name) = split(/,/, $_->{name}); + $results->{$real_name} = { + real_name => $real_name, + user_name => $user_name, + state => $map_state->{ $_->{state} }, + plugged => $map_state->{ $_->{plugged} } + }; + } + + return $results; +} + +sub run { + my ($self, %options) = @_; + + my $results = $self->manage_selection(custom => $options{custom}); + foreach my $instance (sort keys %$results) { + $self->{output}->output_add(long_msg => + join('', map("[$_: " . $results->{$instance}->{$_} . ']', @labels)) + ); + } + + $self->{output}->output_add( + severity => 'OK', + short_msg => 'List interfaces:' + ); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1); + $self->{output}->exit(); +} + +sub disco_format { + my ($self, %options) = @_; + + $self->{output}->add_disco_format(elements => [@labels]); +} + +sub disco_show { + my ($self, %options) = @_; + + my $results = $self->manage_selection(custom => $options{custom}); + foreach (sort keys %$results) { + $self->{output}->add_disco_entry( + %{$results->{$_}} + ); + } +} +1; + +__END__ + +=head1 MODE + +List interfaces. + +=over 8 + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/memory.pm b/centreon-plugins/network/stormshield/api/mode/memory.pm new file mode 100644 index 000000000..b52dd2cc3 --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/memory.pm @@ -0,0 +1,161 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::memory; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub prefix_memory_output { + my ($self, %options) = @_; + + return 'Memory usage '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_memory_output', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'host', nlabel => 'memory.protected_host.percentage', set => { + key_values => [ { name => 'host' } ], + output_template => 'protected host: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'frag', nlabel => 'memory.fragmented.percentage', set => { + key_values => [ { name => 'frag' } ], + output_template => 'fragmented: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'conn', nlabel => 'memory.connections.percentage', set => { + key_values => [ { name => 'conn' } ], + output_template => 'connections: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'icmp', nlabel => 'memory.icmp.percentage', set => { + key_values => [ { name => 'icmp' } ], + output_template => 'icmp: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'dtrack', nlabel => 'memory.data_tracking.percentage', set => { + key_values => [ { name => 'dtrack' } ], + output_template => 'data tracking: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'dyn', nlabel => 'memory.dynamic.percentage', set => { + key_values => [ { name => 'dyn' } ], + output_template => 'dynamic: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'etherstate', nlabel => 'memory.ether_state.percentage', set => { + key_values => [ { name => 'ether_state' } ], + output_template => 'ether state: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $system = $options{custom}->request(command => 'monitor system'); + + # host,frag,icmp,conn,dtrack,dyn + # host,frag,icmp,conn,ether_state,dtrack,dyn + + my @values = split(/,/, $system->{STAT_Result}->{mem}); + my $fields = scalar(@values); + if ($fields == 7) { + $self->{global} = { + host => $values[0], + frag => $values[1], + icmp => $values[2], + conn => $values[3], + ether_state => $values[4], + dtrack => $values[5], + dyn => $values[6] + }; + } elsif ($fields == 6) { + $self->{global} = { + host => $values[0], + frag => $values[1], + icmp => $values[2], + conn => $values[3], + dtrack => $values[4], + dyn => $values[5] + }; + } +} + +1; + +__END__ + +=head1 MODE + +Check memory. + +=over 8 + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'host', 'frag', 'conn', 'icmp', +'dtrack', 'dyn', 'etherstate'. + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/mode/uptime.pm b/centreon-plugins/network/stormshield/api/mode/uptime.pm new file mode 100644 index 000000000..a350b19ac --- /dev/null +++ b/centreon-plugins/network/stormshield/api/mode/uptime.pm @@ -0,0 +1,157 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::mode::uptime; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use DateTime; +use POSIX; +use centreon::plugins::misc; + +my $unitdiv = { s => 1, w => 604800, d => 86400, h => 3600, m => 60 }; +my $unitdiv_long = { s => 'seconds', w => 'weeks', d => 'days', h => 'hours', m => 'minutes' }; + +sub custom_uptime_output { + my ($self, %options) = @_; + + return sprintf( + 'uptime is: %s', + centreon::plugins::misc::change_seconds(value => $self->{result_values}->{uptime}, start => 'd') + ); +} + +sub custom_uptime_perfdata { + my ($self, %options) = @_; + + $self->{output}->perfdata_add( + nlabel => 'system.uptime.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} }, + unit => $self->{instance_mode}->{option_results}->{unit}, + value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), + warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}), + critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}), + min => 0 + ); +} + +sub custom_uptime_threshold { + my ($self, %options) = @_; + + return $self->{perfdata}->threshold_check( + value => floor($self->{result_values}->{uptime} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }), + threshold => [ + { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' }, + { label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }, + { label => 'unknown-'. $self->{thlabel}, exit_litteral => 'unknown' } + ] + ); +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0 } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'uptime', set => { + key_values => [ { name => 'uptime' } ], + closure_custom_output => $self->can('custom_uptime_output'), + closure_custom_perfdata => $self->can('custom_uptime_perfdata'), + closure_custom_threshold_check => $self->can('custom_uptime_threshold') + } + } + ]; +} + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1); + bless $self, $class; + + $options{options}->add_options(arguments => { + 'add-system-info' => { name => 'add_system_info' }, + 'unit:s' => { name => 'unit', default => 's' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + if ($self->{option_results}->{unit} eq '' || !defined($unitdiv->{$self->{option_results}->{unit}})) { + $self->{option_results}->{unit} = 's'; + } +} + +sub manage_selection { + my ($self, %options) = @_; + + my $system = $options{custom}->request(command => 'monitor system'); + + my ($day, $hour, $min, $sec) = split(/:/, $system->{STAT_Result}->{uptime}); + + $self->{global} = { + uptime => ($day * 86400) + ($hour * 3600) + ($min * 60) + $sec + }; + + if (defined($self->{option_results}->{add_system_info})) { + $system = $options{custom}->request(command => 'globaladmin getinfos'); + $self->{output}->output_add(short_msg => sprintf( + 'product: %s, firmware: %s', + $system->{Information}->{ProductModel}, + $system->{Information}->{Firmware} + ) + ); + } +} + +1; + +__END__ + +=head1 MODE + +Check uptime. + +=over 8 + +=item B<--add-system-info> + +Display product and firmware informations + +=item B<--unit> + +Select the unit for performance data and thresholds. May be 's' for seconds, 'm' for minutes, +'h' for hours, 'd' for days, 'w' for weeks. Default is seconds + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'uptime'. + +=back + +=cut diff --git a/centreon-plugins/network/stormshield/api/plugin.pm b/centreon-plugins/network/stormshield/api/plugin.pm new file mode 100644 index 000000000..ad59befdb --- /dev/null +++ b/centreon-plugins/network/stormshield/api/plugin.pm @@ -0,0 +1,55 @@ +# +# Copyright 2022 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package network::stormshield::api::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->{modes} = { + 'cpu' => 'network::stormshield::api::mode::cpu', + 'ha' => 'network::stormshield::api::mode::ha', + 'hardware' => 'network::stormshield::api::mode::hardware', + 'health' => 'network::stormshield::api::mode::health', + 'interfaces' => 'network::stormshield::api::mode::interfaces', + 'list-interfaces' => 'network::stormshield::api::mode::listinterfaces', + 'memory' => 'network::stormshield::api::mode::memory', + 'uptime' => 'network::stormshield::api::mode::uptime' + }; + + $self->{custom_modes}->{api} = 'network::stormshield::api::custom::api'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check Stormshield through SSL API. + +=cut diff --git a/centreon-plugins/network/stormshield/snmp/mode/components/psu.pm b/centreon-plugins/network/stormshield/snmp/mode/components/psu.pm index 7d6239657..989a14038 100644 --- a/centreon-plugins/network/stormshield/snmp/mode/components/psu.pm +++ b/centreon-plugins/network/stormshield/snmp/mode/components/psu.pm @@ -40,7 +40,7 @@ sub check { $self->{output}->output_add(long_msg => 'checking power supplies'); $self->{components}->{psu} = { name => 'psu', total => 0, skip => 0 }; - return if ($self->check_filter(section => 'disk')); + return if ($self->check_filter(section => 'psu')); foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $oid_psuEntry }})) { next if ($oid !~ /^$mapping->{status}->{oid}\.(.*)$/);