From 45ce0c0b429ef39af4a6d6d9d88ee2222f44dec2 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 27 May 2020 17:37:50 +0200 Subject: [PATCH] Fix #1660 --- apps/pfsense/fauxapi/custom/api.pm | 238 +++++++++++++++++++++++ apps/pfsense/fauxapi/mode/backupfiles.pm | 125 ++++++++++++ apps/pfsense/fauxapi/mode/gateways.pm | 179 +++++++++++++++++ apps/pfsense/fauxapi/mode/rules.pm | 134 +++++++++++++ apps/pfsense/fauxapi/mode/system.pm | 136 +++++++++++++ apps/pfsense/fauxapi/plugin.pm | 52 +++++ 6 files changed, 864 insertions(+) create mode 100644 apps/pfsense/fauxapi/custom/api.pm create mode 100644 apps/pfsense/fauxapi/mode/backupfiles.pm create mode 100644 apps/pfsense/fauxapi/mode/gateways.pm create mode 100644 apps/pfsense/fauxapi/mode/rules.pm create mode 100644 apps/pfsense/fauxapi/mode/system.pm create mode 100644 apps/pfsense/fauxapi/plugin.pm diff --git a/apps/pfsense/fauxapi/custom/api.pm b/apps/pfsense/fauxapi/custom/api.pm new file mode 100644 index 000000000..0fcffae18 --- /dev/null +++ b/apps/pfsense/fauxapi/custom/api.pm @@ -0,0 +1,238 @@ +# +# 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 apps::pfsense::fauxapi::custom::api; + +use strict; +use warnings; +use centreon::plugins::http; +use POSIX; +use JSON::XS; +use Digest::SHA; + +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-key:s' => { name => 'api_key' }, + 'api-secret:s' => { name => 'api_secret' }, + '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 => 'REST API OPTIONS', once => 1); + + $self->{output} = $options{output}; + $self->{mode} = $options{mode}; + $self->{http} = centreon::plugins::http->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} : ''; + $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} : 10; + $self->{api_key} = (defined($self->{option_results}->{api_key})) ? $self->{option_results}->{api_key} : ''; + $self->{api_secret} = (defined($self->{option_results}->{api_secret})) ? $self->{option_results}->{api_secret} : ''; + $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 (!defined($self->{hostname}) || $self->{hostname} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --hostname option."); + $self->{output}->option_exit(); + } + if ($self->{api_key} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --api-key option."); + $self->{output}->option_exit(); + } + if ($self->{api_secret} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --api-secret option."); + $self->{output}->option_exit(); + } + + return 0; +} + +sub build_options_for_httplib { + my ($self, %options) = @_; + + $self->{option_results}->{hostname} = $self->{hostname}; + $self->{option_results}->{timeout} = $self->{timeout}; + $self->{option_results}->{port} = $self->{port}; + $self->{option_results}->{proto} = $self->{proto}; + $self->{option_results}->{timeout} = $self->{timeout}; +} + +sub build_fauxapi_header { + my ($self, %options) = @_; + + my $timestamp = POSIX::strftime('%Y%m%dZ%H%M%S', gmtime()); + my $nonce = sprintf('%08X', rand(0xFFFFFFFF)); + my $hash = Digest::SHA::sha256_hex($self->{api_key} . $timestamp . $nonce); + return sprintf( + '%s:%s:%s:%s', + $self->{api_key}, + $timestamp, + $nonce, + $hash + ); +} + +sub settings { + my ($self, %options) = @_; + + return if (defined($self->{settings_done})); + $self->build_options_for_httplib(); + $self->{http}->add_header(key => 'Accept', value => 'application/json'); + $self->{http}->add_header(key => 'Content-Type', value => 'application/json'); + $self->{http}->set_options(%{$self->{option_results}}); + $self->{settings_done} = 1; +} + +sub get_hostname { + my ($self, %options) = @_; + + return $self->{hostname}; +} + +sub get_port { + my ($self, %options) = @_; + + return $self->{port}; +} + +sub request_api { + my ($self, %options) = @_; + + $self->settings(); + my $content = $self->{http}->request( + url_path => '/fauxapi/v1/?action=' . $options{action}, + unknown_status => $self->{unknown_http_status}, + warning_status => $self->{warning_http_status}, + critical_status => $self->{critical_http_status}, + header => [ 'fauxapi-auth: ' . $self->build_fauxapi_header() ] + ); + + if (!defined($content) || $content eq '') { + $self->{output}->add_option_msg(short_msg => "API returns empty content [code: '" . $self->{http}->get_code() . "'] [message: '" . $self->{http}->get_message() . "']"); + $self->{output}->option_exit(); + } + + my $decoded; + eval { + $decoded = JSON::XS->new->utf8->decode($content); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)"); + $self->{output}->option_exit(); + } + + return $decoded; +} + +1; + +__END__ + +=head1 NAME + +pfsense FauxAPI + +=head1 REST API OPTIONS + +pfsense FauxAPI + +=over 8 + +=item B<--hostname> + +pfsense hostname. + +=item B<--port> + +Port used (Default: 443) + +=item B<--proto> + +Specify https if needed (Default: 'https') + +=item B<--api-key> + +API key. + +=item B<--api-secret> + +API secret. + +=item B<--timeout> + +Set timeout in seconds (Default: 10). + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/apps/pfsense/fauxapi/mode/backupfiles.pm b/apps/pfsense/fauxapi/mode/backupfiles.pm new file mode 100644 index 000000000..e18d4038d --- /dev/null +++ b/apps/pfsense/fauxapi/mode/backupfiles.pm @@ -0,0 +1,125 @@ +# +# 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 apps::pfsense::fauxapi::mode::backupfiles; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use POSIX; +use DateTime; + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total', nlabel => 'backups.total.count', set => { + key_values => [ { name => 'total' } ], + output_template => 'number of backups: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + }, + { label => 'time-last', nlabel => 'backups.time.last.seconds', set => { + key_values => [ { name => 'since' }, { name => 'readable_since' } ], + output_template => 'last backup time: %s', + output_use => 'readable_since', + perfdatas => [ + { template => '%s', min => 0, unit => 'ms' } + ] + } + } + ]; +} + +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 $results = $options{custom}->request_api(action => 'config_backup_list'); + + $self->{global} = { total => 0 }; + my $recent_time = 0; + if (defined($results->{data}->{backup_files})) { + foreach (@{$results->{data}->{backup_files}}) { + # 20200511Z094516 + return if ($_->{timestamp} !~ /^\s*(\d{4})(\d{2})(\d{2})Z(\d{2})(\d{2})(\d{2})/); + + my $dt = DateTime->new( + year => $1, + month => $2, + day => $3, + hour => $4, + minute => $5, + second => $6, + time_zone => 'GMT' + ); + my $time = $dt->epoch(); + $recent_time = $time if ($recent_time < $time); + + $self->{global}->{total}++; + } + } + + if ($recent_time > 0) { + $self->{global}->{since} = POSIX::strftime('%s', gmtime()) - $recent_time; + $self->{global}->{readable_since} = centreon::plugins::misc::change_seconds(value => $self->{global}->{since}); + } +} + +1; + +__END__ + +=head1 MODE + +Check backup files. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='total' + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'total', 'time-last'. + +=back + +=cut diff --git a/apps/pfsense/fauxapi/mode/gateways.pm b/apps/pfsense/fauxapi/mode/gateways.pm new file mode 100644 index 000000000..ca63d17d3 --- /dev/null +++ b/apps/pfsense/fauxapi/mode/gateways.pm @@ -0,0 +1,179 @@ +# +# 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 apps::pfsense::fauxapi::mode::gateways; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold); + +sub custom_status_output { + my ($self, %options) = @_; + + return sprintf('status: ' . $self->{result_values}->{status}); +} + +sub prefix_gateway_output { + my ($self, %options) = @_; + + return "Gateway '" . $options{instance_value}->{display} . "' packets "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'gateways', type => 1, cb_prefix_output => 'prefix_gateway_output', message_multiple => 'All gateways are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{gateways} = [ + { label => 'status', threshold => 0, set => { + key_values => [ { name => 'status' }, { name => 'display' } ], + closure_custom_output => $self->can('custom_status_output'), + closure_custom_perfdata => sub { return 0; }, + closure_custom_threshold_check => \&catalog_status_threshold + } + }, + { label => 'packets-delay', nlabel => 'gateway.packets.delay.milliseconds', set => { + key_values => [ { name => 'delay' }, { name => 'display' } ], + output_template => 'delay: %.2f ms', + perfdatas => [ + { template => '%.2f', min => 0, unit => 'ms', label_extra_instance => 1 } + ] + } + }, + { label => 'packets-loss', nlabel => 'gateway.packets.loss.percentage', set => { + key_values => [ { name => 'loss' }, { name => 'display' } ], + output_template => 'loss: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 } + ] + } + }, + { label => 'packets-stddev', nlabel => 'gateway.packets.stddev.milliseconds', set => { + key_values => [ { name => 'stddev' }, { name => 'display' } ], + output_template => 'stddev: %.2f ms', + perfdatas => [ + { template => '%.2f', min => 0, unit => 'ms', 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-name:s' => { name => 'filter_name' }, + 'unknown-status:s' => { name => 'unknown_status', default => '' }, + 'warning-status:s' => { name => 'warning_status', default => '' }, + 'critical-status:s' => { name => 'critical_status', default => '%{status} !~ /none/i' } + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::check_options(%options); + + $self->change_macros(macros => ['warning_status', 'critical_status', 'unknown_status']); +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->request_api(action => 'gateway_status'); + + $self->{gateways} = {}; + if (defined($results->{data}->{gateway_status})) { + foreach (values %{$results->{data}->{gateway_status}}) { + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $_->{name} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping gateway '" . $_->{name} . "': no matching filter.", debug => 1); + next; + } + + my $delay = $_->{delay} =~ /([0-9\.])+/ ? $1 : undef; + my $stddev = $_->{stddev} =~ /([0-9\.])+/ ? $1 : undef; + my $loss = $_->{loss} =~ /([0-9\.])+/ ? $1 : undef; + $self->{gateways}->{ $_->{name} } = { + display => $_->{name}, + status => $_->{status}, + delay => $delay, + stddev => $stddev, + loss => $loss + }; + } + } + + if (scalar(keys %{$self->{gateways}}) <= 0) { + $self->{output}->add_option_msg(short_msg => "no gateway found"); + $self->{output}->option_exit(); + } +} + +1; + +__END__ + +=head1 MODE + +Check gateways. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='status' + +=item B<--filter-name> + +Filter gateway name (can be a regexp). + +=item B<--unknown-status> + +Set unknon threshold for status (Default: ''). +Can used special variables like: %{status}, %{display} + +=item B<--warning-status> + +Set warning threshold for status (Default: ''). +Can used special variables like: %{status}, %{display} + +=item B<--critical-status> + +Set critical threshold for status (Default: '%{status} !~ /none/i'). +Can used special variables like: %{status}, %{display} + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'packets-delay' (ms), 'packets-loss' (%), 'packets-stddev' (ms). + +=back + +=cut diff --git a/apps/pfsense/fauxapi/mode/rules.pm b/apps/pfsense/fauxapi/mode/rules.pm new file mode 100644 index 000000000..eb762b8ec --- /dev/null +++ b/apps/pfsense/fauxapi/mode/rules.pm @@ -0,0 +1,134 @@ +# +# 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 apps::pfsense::fauxapi::mode::rules; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; +use Digest::MD5 qw(md5_hex); + +sub prefix_rule_output { + my ($self, %options) = @_; + + return "Rule '" . $options{instance_value}->{display} . "' "; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, skipped_code => { -10 => 1 } }, + { name => 'rules', type => 1, cb_prefix_output => 'prefix_rule_output', message_multiple => 'All rules are ok', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'total', nlabel => 'rules.total.count', set => { + key_values => [ { name => 'total' } ], + output_template => 'number of rules: %s', + perfdatas => [ + { template => '%s', min => 0 } + ] + } + } + ]; + + $self->{maps_counters}->{rules} = [ + { label => 'traffic', nlabel => 'rule.traffic.bitspersecond', set => { + key_values => [ { name => 'traffic', per_second => 1 }, { name => 'display' } ], + output_template => 'traffic: %s %s/s', + output_change_bytes => 2, + perfdatas => [ + { template => '%s', min => 0, unit => 'b/s', label_extra_instance => 1, instance_use => 'display' } + ] + } + } + ]; +} + +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-name:s' => { name => 'filter_name' } + }); + + return $self; +} + +sub manage_selection { + my ($self, %options) = @_; + + my $results = $options{custom}->request_api(action => 'rule_get'); + + $self->{global} = { total => 0 }; + $self->{rules} = {}; + if (defined($results->{data}->{rules})) { + foreach (@{$results->{data}->{rules}}) { + if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && + $_->{rule} !~ /$self->{option_results}->{filter_name}/) { + $self->{output}->output_add(long_msg => "skipping rule '" . $_->{name} . "': no matching filter.", debug => 1); + next; + } + + $self->{rules}->{ $_->{number} } = { + display => $_->{rule}, + traffic => $_->{bytes} * 8 + }; + + $self->{global}->{total}++; + } + } + + $self->{cache_name} = 'pfsense_fauxapi_' . $options{custom}->get_hostname() . '_' . $options{custom}->get_port() . '_' . $self->{mode} . '_' . + (defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all')) . '_' . + (defined($self->{option_results}->{filter_name}) ? md5_hex($self->{option_results}->{filter_name}) : md5_hex('all')); +} + +1; + +__END__ + +=head1 MODE + +Check rules. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='traffic' + +=item B<--filter-name> + +Filter rule name (can be a regexp). + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'traffic' (b/s). + +=back + +=cut diff --git a/apps/pfsense/fauxapi/mode/system.pm b/apps/pfsense/fauxapi/mode/system.pm new file mode 100644 index 000000000..60ed023ee --- /dev/null +++ b/apps/pfsense/fauxapi/mode/system.pm @@ -0,0 +1,136 @@ +# +# 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 apps::pfsense::fauxapi::mode::system; + +use base qw(centreon::plugins::templates::counter); + +use strict; +use warnings; + +sub custom_tcp_usage_output { + my ($self, %options) = @_; + + my $msg = sprintf( + 'tcp connections total: %s used: %s (%.2f%%) free: %s (%.2f%%)', + $self->{result_values}->{tcp_conn_total}, + $self->{result_values}->{tcp_conn_used}, $self->{result_values}->{tcp_conn_used_prct}, + $self->{result_values}->{tcp_conn_free}, $self->{result_values}->{tcp_conn_free_prct} + ); + return $msg; +} + +sub prefix_global_output { + my ($self, %options) = @_; + + return 'System '; +} + +sub set_counters { + my ($self, %options) = @_; + + $self->{maps_counters_type} = [ + { name => 'global', type => 0, cb_prefix_output => 'prefix_global_output', skipped_code => { -10 => 1 } } + ]; + + $self->{maps_counters}->{global} = [ + { label => 'connections-tcp-usage', nlabel => 'system.connections.tcp.usage.count', set => { + key_values => [ + { name => 'tcp_conn_used' }, { name => 'tcp_conn_total' }, + { name => 'tcp_conn_free' }, { name => 'tcp_conn_used_prct' }, + { name => 'tcp_conn_free_prct' } + ], + closure_custom_output => $self->can('custom_tcp_usage_output'), + perfdatas => [ + { template => '%s', min => 0, max => 'tcp_conn_total' } + ] + } + }, + { label => 'connections-tcp-usage-prct', nlabel => 'system.connections.tcp.usage.percentage', display_ok => 0, set => { + key_values => [ { name => 'tcp_conn_used_prct' } ], + output_template => 'tcp connections used: %.2f %%', + perfdatas => [ + { template => '%.2f', min => 0, max => 100, unit => '%' } + ] + } + }, + { label => 'temperature', nlabel => 'system.temperature.celsius', set => { + key_values => [ { name => 'temperature' } ], + output_template => 'temperature: %s C', + perfdatas => [ + { template => '%s', unit => 'C' } + ] + } + } + ]; +} + +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 $results = $options{custom}->request_api(action => 'system_stats'); + + $self->{global} = {}; + if (defined($results->{data}->{stats})) { + if ($results->{data}->{stats}->{pfstate} =~ /^(\d+)\/(\d+)/) { + $self->{global}->{tcp_conn_used} = $1; + $self->{global}->{tcp_conn_total} = $2; + $self->{global}->{tcp_conn_free} = $2 - $1; + $self->{global}->{tcp_conn_used_prct} = $1 * 100 / $2; + $self->{global}->{tcp_conn_free_prct} = 100 - $self->{global}->{tcp_conn_used_prct}; + } + $self->{global}->{temperature} = $results->{data}->{stats}->{temp}; + } +} + +1; + +__END__ + +=head1 MODE + +Check system. + +=over 8 + +=item B<--filter-counters> + +Only display some counters (regexp can be used). +Example: --filter-counters='temperature' + +=item B<--warning-*> B<--critical-*> + +Thresholds. +Can be: 'temperature' (C), 'connections-tcp-usage', 'connections-tcp-usage-prct' (%). + +=back + +=cut diff --git a/apps/pfsense/fauxapi/plugin.pm b/apps/pfsense/fauxapi/plugin.pm new file mode 100644 index 000000000..addc5a300 --- /dev/null +++ b/apps/pfsense/fauxapi/plugin.pm @@ -0,0 +1,52 @@ +# +# 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 apps::pfsense::fauxapi::plugin; + +use strict; +use warnings; +use base qw(centreon::plugins::script_custom); + +sub new { + my ( $class, %options ) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $self->{version} = '0.1'; + $self->{modes} = { + 'backup-files' => 'apps::pfsense::fauxapi::mode::backupfiles', + 'gateways' => 'apps::pfsense::fauxapi::mode::gateways', + 'system' => 'apps::pfsense::fauxapi::mode::system', + 'rules' => 'apps::pfsense::fauxapi::mode::rules' + }; + + $self->{custom_modes}{api} = 'apps::pfsense::fauxapi::custom::api'; + return $self; +} + +1; + +__END__ + +=head1 PLUGIN DESCRIPTION + +Check pfsense with FauxAPI. + +=cut