Release 20230215 #4225 from centreon/release-20230215

This commit is contained in:
Kevin Duret 2023-02-15 17:45:21 +01:00 committed by GitHub
commit 952518e62a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 3745 additions and 704 deletions

View File

@ -1,4 +1,4 @@
FROM docker-proxy.centreon.com/almalinux:8.5
FROM docker-proxy.centreon.com/almalinux:8
RUN <<EOF

View File

@ -0,0 +1,13 @@
FROM docker-proxy.centreon.com/almalinux:9
RUN <<EOF
dnf -y install git gettext rpm-build dos2unix python3 epel-release
dnf -y install perl-App-cpanminus perl-JSON
cpanm App::FatPacker
cpanm File::Copy::Recursive
dnf clean all
EOF
WORKDIR /src

View File

@ -4,11 +4,11 @@ Upstream-Contact: Centreon <contact@centreon.com>
Source: https://www.centreon.com
Files: *
Copyright: 2021 Centreon
Copyright: 2023 Centreon
License: Apache-2.0
Files: debian/*
Copyright: 2021 Centreon
Copyright: 2023 Centreon
License: Apache-2.0
License: Apache-2.0

View File

@ -4,7 +4,7 @@ Release: @RELEASE@%{?dist}
Source0: %{name}-%{version}.tar.gz
Summary: @SUMMARY@
Group: Development/Libraries
License: ASL 2.0
License: Apache-2.0
URL: https://www.centreon.com/
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)

View File

@ -19,11 +19,11 @@ on:
jobs:
create-and-push-docker:
runs-on: [self-hosted, common]
runs-on: ubuntu-22.04
strategy:
matrix:
distrib: [centos7, alma8, bullseye]
distrib: [centos7, alma8, alma9, bullseye]
include:
- project: plugins
steps:

View File

@ -36,7 +36,7 @@ jobs:
runs-on: [self-hosted, common]
strategy:
matrix:
distrib: [el7, el8]
distrib: [el7, el8, el9]
steps:
- name: Checkout sources

View File

@ -59,6 +59,9 @@ jobs:
- package_extension: rpm
image: packaging-plugins-alma8
distrib: el8
- package_extension: rpm
image: packaging-plugins-alma9
distrib: el9
- package_extension: deb
image: packaging-plugins-bullseye
distrib: bullseye

View File

@ -1,3 +1,11 @@
2023-01-18 Quentin Garnier <qgarnier@centreon.com>
* Plugin added: Talend TMC API
* Plugin added: Sensor APC SNMP
* Plugin added: Vectra SNMP
* Plugin added: Stormshield API
* Mode added: [netapp/ontap/restapi] 'quotas'
* Break: pure storage refactoring
2022-11-15 Quentin Garnier <qgarnier@centreon.com>
* Plugin added: Thales Mistral VS9 Rest API
* Plugin added: PICOS SNMP

View File

@ -1,5 +1,3 @@
{
"dependencies": [
"libjson-perl"
]
"dependencies": []
}

View File

@ -3,7 +3,7 @@
"pkg_summary": "Centreon Plugin",
"plugin_name": "centreon_jenkins.pl",
"files": [
"centreon/plugins/script_simple.pm",
"centreon/plugins/script_custom.pm",
"apps/jenkins/"
]
}

View File

@ -1,5 +1,3 @@
{
"dependencies": [
"perl(JSON)"
]
"dependencies": []
}

View File

@ -0,0 +1,5 @@
{
"dependencies": [
"libjmx4perl-perl"
]
}

View File

@ -0,0 +1,10 @@
{
"pkg_name": "centreon-plugin-Applications-Oracle-Ucp-Jmx",
"pkg_summary": "Centreon Plugin",
"plugin_name": "centreon_oracle_ucp_jmx.pl",
"files": [
"centreon/plugins/script_custom.pm",
"centreon/common/protocols/jmx/",
"apps/oracle/ucp/jmx/"
]
}

View File

@ -0,0 +1,5 @@
{
"dependencies": [
"perl(JMX::Jmx4Perl)"
]
}

View File

@ -0,0 +1,5 @@
{
"dependencies": [
"libsnmp-perl"
]
}

View File

@ -0,0 +1,10 @@
{
"pkg_name": "centreon-plugin-Hardware-Storage-Wd-Nas-Snmp",
"pkg_summary": "Centreon Plugin",
"plugin_name": "centreon_wd_nas_snmp.pl",
"files": [
"centreon/plugins/script_snmp.pm",
"centreon/plugins/snmp.pm",
"storage/wd/nas/snmp/"
]
}

View File

@ -0,0 +1,5 @@
{
"dependencies": [
"perl(SNMP)"
]
}

View File

@ -7,6 +7,7 @@
"centreon/plugins/wsman.pm",
"os/windows/wsman/",
"centreon/common/powershell/functions.pm",
"centreon/common/powershell/windows/pendingreboot.pm"
"centreon/common/powershell/windows/pendingreboot.pm",
"centreon/common/powershell/windows/updates.pm"
]
}

View File

@ -45,6 +45,9 @@ sub new {
$options{options}->add_options(arguments => {
'api-username:s' => { name => 'api_username' },
'api-password:s' => { name => 'api_password' },
'service-account:s' => { name => 'service_account' },
'secret:s' => { name => 'secret' },
'organization-id:s' => { name => 'organization_id' },
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' },
'proto:s' => { name => 'proto' },
@ -80,6 +83,9 @@ sub check_options {
$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->{service_account} = (defined($self->{option_results}->{service_account})) ? $self->{option_results}->{service_account} : '';
$self->{secret} = (defined($self->{option_results}->{secret})) ? $self->{option_results}->{secret} : '';
$self->{organization_id} = (defined($self->{option_results}->{organization_id})) ? $self->{option_results}->{organization_id} : '';
$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} : '';
@ -94,6 +100,15 @@ sub check_options {
return 0 if ($self->{token} ne '');
}
if ($self->{service_account} ne '') {
if ($self->{secret} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --secret option.');
$self->{output}->option_exit();
}
$self->{cache}->check_options(option_results => $self->{option_results});
return 0;
}
if ($self->{api_username} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.');
$self->{output}->option_exit();
@ -141,7 +156,68 @@ sub get_token {
credentials => 1,
basic => 1,
username => $self->{api_username},
password => $self->{api_password}
password => $self->{api_password},
unknown_status => $self->{unknown_http_status},
warning_status => $self->{warning_http_status},
critical_status => $self->{critical_http_status}
);
my $decoded;
eval {
$decoded = JSON::XS->new->utf8->decode($content);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode json response");
$self->{output}->option_exit();
}
$token = $decoded->{token};
my $datas = {
updated => time(),
token => $decoded->{token},
md5_secret => $md5_secret
};
$self->{cache}->write(data => $datas);
}
return $token;
}
sub get_service_account_token {
my ($self, %options) = @_;
my $has_cache_file = $self->{cache}->read(statefile => 'rubrik_api_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{service_account}));
my $token = $self->{cache}->get(name => 'token');
my $md5_secret_cache = $self->{cache}->get(name => 'md5_secret');
my $md5_secret = md5_hex($self->{service_account} . $self->{secret});
if ($has_cache_file == 0 ||
!defined($token) ||
(defined($md5_secret_cache) && $md5_secret_cache ne $md5_secret)
) {
my $json_request = {
serviceAccountId => $self->{service_account},
secret => $self->{secret}
};
$json_request->{organizationId} = $self->{organization_id} if ($self->{organization_id} ne '');
my $encoded;
eval {
$encoded = encode_json($json_request);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => 'cannot encode json request');
$self->{output}->option_exit();
}
$self->settings();
my $content = $self->{http}->request(
method => 'POST',
url_path => '/api/v1/service_account/session',
query_form_post => $encoded,
unknown_status => $self->{unknown_http_status},
warning_status => $self->{warning_http_status},
critical_status => $self->{critical_http_status}
);
my $decoded;
@ -181,7 +257,15 @@ sub credentials {
}
my $creds = {};
if (defined($self->{token})) {
if ($self->{service_account} ne '') {
$token = $self->get_service_account_token();
$creds = {
header => ['Authorization: Bearer ' . $token],
unknown_status => '',
warning_status => '',
critical_status => ''
};
} elsif (defined($self->{token})) {
$creds = {
header => ['Authorization: Bearer ' . $token],
unknown_status => '',
@ -273,6 +357,18 @@ Port used (Default: 443)
Specify https if needed (Default: 'https')
=item B<--service-account>
Service account ID (with --secret and --organization-id options).
=item B<--secret>
Service account secret (with --service-account and --organization-id options).
=item B<--organization-id>
Organization ID (with --service-account and --secret options).
=item B<--api-username>
API username.

View File

@ -0,0 +1,118 @@
#
# Copyright 2023 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::ceph::restapi::mode::storage;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
sub custom_space_usage_output {
my ($self, %options) = @_;
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_space});
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space});
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free_space});
return sprintf(
'raw storage space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)',
$total_size_value . " " . $total_size_unit,
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used_space},
$total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free_space}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }
];
$self->{maps_counters}->{global} = [
{ label => 'space-usage', nlabel => 'storage.raw.space.usage.bytes', set => {
key_values => [ { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-free', nlabel => 'storage.raw.space.free.bytes', display_ok => 0, set => {
key_values => [ { name => 'free_space' }, { name => 'used_space' }, { name => 'prct_used_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total_space', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'space-usage-prct', nlabel => 'storage.raw.space.usage.percentage', display_ok => 0, set => {
key_values => [ { name => 'prct_used_space' }, { name => 'used_space' }, { name => 'free_space' }, { name => 'prct_free_space' }, { name => 'total_space' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
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 => {});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $health = $options{custom}->request_api(endpoint => '/api/health/minimal');
$self->{global} = {
total_space => $health->{df}->{stats}->{total_bytes},
used_space => $health->{df}->{stats}->{total_used_raw_bytes},
free_space => $health->{df}->{stats}->{total_bytes} - $health->{df}->{stats}->{total_used_raw_bytes},
prct_used_space => $health->{df}->{stats}->{total_used_raw_bytes} * 100 / $health->{df}->{stats}->{total_bytes},
prct_free_space => ($health->{df}->{stats}->{total_bytes} - $health->{df}->{stats}->{total_used_raw_bytes}) * 100 / $health->{df}->{stats}->{total_bytes}
};
}
1;
__END__
=head1 MODE
Check raw storage.
=over 8
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'space-usage', 'space-usage-free', 'space-usage-prct'.
=back
=cut

View File

@ -33,7 +33,8 @@ sub new {
'health' => 'apps::ceph::restapi::mode::health',
'list-pools' => 'apps::ceph::restapi::mode::listpools',
'osd' => 'apps::ceph::restapi::mode::osd',
'pools' => 'apps::ceph::restapi::mode::pools'
'pools' => 'apps::ceph::restapi::mode::pools',
'storage' => 'apps::ceph::restapi::mode::storage'
};
$self->{custom_modes}->{api} = 'apps::ceph::restapi::custom::api';

View File

@ -0,0 +1,204 @@
#
# Copyright 2023 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::jenkins::custom::api;
use strict;
use warnings;
use centreon::plugins::http;
use JSON::XS;
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 => {
'username:s' => { name => 'username' },
'password:s' => { name => '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 => 'REST API OPTIONS', once => 1);
$self->{output} = $options{output};
$self->{http} = centreon::plugins::http->new(%options, default_backend => 'curl');
return $self;
}
sub set_options {
my ($self, %options) = @_;
$self->{option_results} = $options{option_results};
}
sub set_defaults {}
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->{username} = (defined($self->{option_results}->{username})) ? $self->{option_results}->{username} : '';
$self->{password} = (defined($self->{option_results}->{password})) ? $self->{option_results}->{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->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --hostname option.");
$self->{output}->option_exit();
}
if ($self->{username} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --username option.");
$self->{output}->option_exit();
}
if ($self->{password} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --password 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};
$self->{option_results}->{credentials} = 1;
$self->{option_results}->{basic} = 1;
$self->{option_results}->{username} = $self->{username};
$self->{option_results}->{password} = $self->{password};
}
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 request_api {
my ($self, %options) = @_;
$self->settings();
my ($content) = $self->{http}->request(
url_path => $options{endpoint},
get_param => $options{get_param},
unknown_status => $self->{unknown_http_status},
warning_status => $self->{warning_http_status},
critical_status => $self->{critical_http_status}
);
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
Jenkins Rest API
=head1 REST API OPTIONS
Jenkins Rest API
=over 8
=item B<--hostname>
Hostname.
=item B<--port>
Port used (Default: 443)
=item B<--proto>
Specify https if needed (Default: 'https')
=item B<--username>
API username.
=item B<--password>
API password.
=item B<--timeout>
Set timeout in seconds (Default: 10).
=back
=head1 DESCRIPTION
B<custom>.
=cut

View File

@ -0,0 +1,134 @@
#
# Copyright 2023 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::jenkins::mode::jobs;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
sub prefix_job_output {
my ($self, %options) = @_;
return "Job '" . $options{instance} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'jobs', type => 1, cb_prefix_output => 'prefix_job_output', message_multiple => 'All jobs are ok' }
];
$self->{maps_counters}->{jobs} = [
{ label => 'score', nlabel => 'job.score.percentage', set => {
key_values => [ { name => 'score' } ],
output_template => 'score: %.2f %%',
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }
]
}
},
{ label => 'violations', nlabel => 'job.violations.count', set => {
key_values => [ { name => 'violations' } ],
output_template => 'violations: %s',
perfdatas => [
{ template => '%s', min => 0, 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-job-name:s' => { name => 'filter_job_name' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $jobs = $options{custom}->request_api(
endpoint => '/api/json',
get_param => [
'tree=jobs[name,buildable,healthReport[description,score],jobs[name,buildable,healthReport[description,score]]]'
]
);
$self->{jobs} = {};
foreach my $job (@{$jobs->{jobs}}) {
my $name = $job->{name};
next if (defined($self->{option_results}->{filter_job_name}) && $self->{option_results}->{filter_job_name} ne '' &&
$name !~ /$self->{option_results}->{filter_job_name}/);
if (defined($job->{healthReport}->[0]->{score})) {
$self->{jobs}->{$name} = { score => $job->{healthReport}->[0]->{score}, violations => 0 };
if ($job->{healthReport}->[0]->{description} =~ /^.+?([0-9]+)/ ) {
$self->{jobs}->{$name}->{violations} = $1;
}
}
next if (!defined($job->{jobs}));
foreach my $subjob (@{$job->{jobs}}) {
my $subname = $name . '/' . $subjob->{name};
next if (defined($self->{option_results}->{filter_job_name}) && $self->{option_results}->{filter_job_name} ne '' &&
$subname !~ /$self->{option_results}->{filter_job_name}/);
if (defined($subjob->{healthReport}->[0]->{score})) {
$self->{jobs}->{$subname} = { score => $subjob->{healthReport}->[0]->{score}, violations => 0 };
if ($subjob->{healthReport}->[0]->{description} =~ /^.+?([0-9]+)/ ) {
$self->{jobs}->{$subname}->{violations} = $1;
}
}
}
}
}
1;
__END__
=head1 MODE
Check jobs.
=over 8
=item B<--filter-job-name>
Filter jobs by name (can be a regexp).
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'score', 'violations'.
=back
=cut

View File

@ -1,197 +0,0 @@
#
# Copyright 2023 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::jenkins::mode::jobstate;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::http;
use centreon::plugins::statefile;
use JSON;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$options{options}->add_options(arguments => {
"hostname:s" => { name => 'hostname' },
"port:s" => { name => 'port' },
"proto:s" => { name => 'proto' },
"urlpath:s" => { name => 'url_path' },
"timeout:s" => { name => 'timeout' },
"credentials" => { name => 'credentials' },
"basic" => { name => 'basic' },
"username:s" => { name => 'username' },
"password:s" => { name => 'password' },
"jobname:s" => { name => 'jobname' },
"warning:s" => { name => 'warning' },
"critical:s" => { name => 'critical' },
"checkstyle" => { name => 'checkstyle' },
});
$self->{http} = centreon::plugins::http->new(%options);
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
$self->{output}->option_exit();
}
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{jobname})) {
$self->{output}->add_option_msg(short_msg => "Please set the jobname option");
$self->{output}->option_exit();
}
$self->{option_results}->{url_path} = $self->{option_results}->{url_path} . "/job/" . $self->{option_results}->{jobname} . "/api/json";
$self->{http}->set_options(%{$self->{option_results}});
}
sub run {
my ($self, %options) = @_;
my $jsoncontent = $self->{http}->request();
my $json = JSON->new;
my $webcontent;
eval {
$webcontent = $json->decode($jsoncontent);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode json response");
$self->{output}->option_exit();
}
my $description_tendency = $webcontent->{healthReport}->[0]->{description};
my $score_tendency = $webcontent->{healthReport}->[0]->{score};
my ($description_violations, $number_violations);
my $exit1 = $self->{perfdata}->threshold_check(value => $score_tendency, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
$self->{output}->output_add(severity => $exit1,
short_msg => sprintf("%s", $description_tendency));
$self->{output}->perfdata_add(label => 'score_tendency',
value => sprintf("%d", $score_tendency),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0,
);
if (defined($self->{option_results}->{checkstyle})) {
if (defined($webcontent->{healthReport}->[1]->{description})) {
my $description_violations;
my $number_violations;
$description_violations = $webcontent->{healthReport}->[1]->{description};
if ( $description_violations =~ /^.+?([0-9]+)$/ ) {
$number_violations = $1;
}
$self->{output}->add_option_msg(short_msg => sprintf("%s", $description_violations));
$self->{output}->perfdata_add(label => 'number_violations',
value => sprintf("%d", $number_violations),
min => 0,
);
}
}
$self->{output}->display();
$self->{output}->exit();
}
1;
__END__
=head1 MODE
Check Jenkins specific job tendency (score) and checkstyle violation
=over 8
=item B<--hostname>
IP Addr/FQDN of the Jenkins host
=item B<--port>
Port used by Jenkins API
=item B<--proto>
Specify https if needed (Default: 'http')
=item B<--urlpath>
Set path to get Jenkins information
=item B<--credentials>
Required to use username/password authentication method
=item B<--basic>
Specify this option if you access API over basic authentication and don't want a '401 UNAUTHORIZED' error to be logged on your webserver.
Specify this option if you access API over hidden basic authentication or you'll get a '404 NOT FOUND' error.
(Use with --credentials)
=item B<--username>
Specify username for API authentification
=item B<--password>
Specify password for API authentification
=item B<--timeout>
Threshold for HTTP timeout (Default: 5)
=item B<--warning>
Warning Threshold for tendency score
=item B<--critical>
Critical Threshold for tendency score
=item B<--checkstyle>
Add checkstyle's violation output and perfdata
=back
=cut

View File

@ -0,0 +1,116 @@
#
# Copyright 2023 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::jenkins::mode::listjobs;
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);
}
sub manage_selection {
my ($self, %options) = @_;
my $jobs = $options{custom}->request_api(
endpoint => '/api/json',
get_param => [
'tree=jobs[name,buildable,jobs[name,buildable]]'
]
);
my $results = [];
foreach my $job (@{$jobs->{jobs}}) {
push @$results, { name => $job->{name} };
foreach my $subjob (@{$job->{jobs}}) {
push @$results, { name => $job->{name} . '/' . $subjob->{name} };
}
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $jobs = $self->manage_selection(%options);
foreach (@$jobs) {
$self->{output}->output_add(
long_msg => sprintf(
'[name: %s]',
$_->{name}
)
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List jobs:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['name']);
}
sub disco_show {
my ($self, %options) = @_;
my $jobs = $self->manage_selection(%options);
foreach (@$jobs) {
$self->{output}->add_disco_entry(
%$_
);
}
}
1;
__END__
=head1 MODE
List jobs.
=over 8
=back
=cut

View File

@ -22,18 +22,19 @@ package apps::jenkins::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_simple);
use base qw(centreon::plugins::script_custom);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
%{$self->{modes}} = (
'job-state' => 'apps::jenkins::mode::jobstate',
);
$self->{modes} = {
'jobs' => 'apps::jenkins::mode::jobs',
'list-jobs' => 'apps::jenkins::mode::listjobs'
};
$self->{custom_modes}->{api} = 'apps::jenkins::custom::api';
return $self;
}

View File

@ -0,0 +1,258 @@
#
# Copyright 2023 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::oracle::ucp::jmx::mode::connectionpools;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
sub custom_usage_perfdata {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->{result_values}->{poolName},
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} > 0 ? $self->{result_values}->{total} : undef
);
}
sub custom_usage_free_perfdata {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
instances => $self->{result_values}->{poolName},
value => $self->{result_values}->{free},
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_usage_prct_perfdata {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
unit => '%',
instances => $self->{result_values}->{poolName},
value => sprintf('%.2f', $self->{result_values}->{prct_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 => 100
);
}
sub custom_usage_threshold {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{used}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' },
]
);
}
sub custom_usage_free_threshold {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{free}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }
]
);
}
sub custom_usage_prct_threshold {
my ($self, %options) = @_;
return $self->{perfdata}->threshold_check(
value => $self->{result_values}->{prct_used}, threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }
]
);
}
sub custom_usage_output {
my ($self, %options) = @_;
my $msg;
if ($self->{result_values}->{total} <= 0) {
$msg = sprintf("used: %s (unlimited)", $self->{result_values}->{used});
} else {
$msg = sprintf(
"total: %s used: %s (%.2f%%) free: %s (%.2f%%)",
$self->{result_values}->{total},
$self->{result_values}->{used}, $self->{result_values}->{prct_used},
$self->{result_values}->{free}, $self->{result_values}->{prct_free}
);
}
return $msg;
}
sub custom_usage_calc {
my ($self, %options) = @_;
$self->{result_values}->{poolName} = $options{new_datas}->{$self->{instance} . '_poolName'};
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'};
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'};
if ($self->{result_values}->{total} == 0) {
return -10 if ($options{extra_options}->{label} ne 'usage');
return 0;
}
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
return 0;
}
sub prefix_pool_output {
my ($self, %options) = @_;
return sprintf(
"Connection pool '%s' ",
$options{instance_value}->{poolName}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'pools', type => 1, cb_prefix_output => 'prefix_pool_output', message_multiple => 'All connection pools are ok', skipped_code => { -10 => 1 } }
];
$self->{maps_counters}->{pools} = [
{ label => 'usage', nlabel => 'connection_pool.usage.count', set => {
key_values => [
{ name => 'poolName' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'usage' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
closure_custom_perfdata => $self->can('custom_usage_perfdata')
}
},
{ label => 'usage-free', nlabel => 'connection_pool.free.count', display_ok => 0, set => {
key_values => [
{ name => 'poolName' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'free' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => $self->can('custom_usage_free_threshold'),
closure_custom_perfdata => $self->can('custom_usage_free_perfdata')
}
},
{ label => 'usage-prct', nlabel => 'connection_pool.usage.percentage', display_ok => 0, set => {
key_values => [
{ name => 'poolName' }, { name => 'used' }, { name => 'total' }
],
closure_custom_calc_extra_options => { label => 'prct' },
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_threshold_check => $self->can('custom_usage_prct_threshold'),
closure_custom_perfdata => $self->can('custom_usage_prct_perfdata')
}
}
];
}
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-pool-name:s' => { name => 'filter_pool_name' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $request = [
{ mbean => "oracle.ucp.admin.UniversalConnectionPoolMBean:name=UniversalConnectionPoolManager*,poolName=*", attributes =>
[ { name => 'remainingPoolCapacityCount' }, { name => 'totalConnectionsCount' }, { name => 'maxPoolSize' } ] }
];
my $result = $options{custom}->get_attributes(request => $request, nothing_quit => 1);
$self->{pools} = {};
foreach my $key (keys %$result) {
$key =~ /(?:[:,])poolName=(.*?)(?:,|$)/;
my $poolName = $1;
next if (defined($self->{option_results}->{filter_pool_name}) && $self->{option_results}->{filter_pool_name} ne '' &&
$poolName !~ /$self->{option_results}->{filter_pool_name}/);
$self->{pools}->{$poolName} = {
poolName => $poolName,
used => $result->{$key}->{totalConnectionsCount},
total => defined($result->{$key}->{maxPoolSize}) ? $result->{$key}->{maxPoolSize} : 0
};
}
if (scalar(keys %{$self->{pools}}) <= 0) {
$self->{output}->add_option_msg(short_msg => 'No connection pools found');
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check connection pools.
=over 8
=item B<--filter-pool-name>
Filter connection pools by name (can be a regexp).
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'usage', 'usage-free', 'usage-prct'.
=back
=cut

View File

@ -0,0 +1,121 @@
#
# Copyright 2023 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::oracle::ucp::jmx::mode::listconnectionpools;
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);
}
sub manage_selection {
my ($self, %options) = @_;
my $mbeans = $options{custom}->get_attributes(
request => [
{
mbean => "oracle.ucp.admin.UniversalConnectionPoolMBean:name=UniversalConnectionPoolManager*,poolName=*",
attributes => [ { name => 'totalConnectionsCount' } ]
}
]
);
my $results = {};
foreach my $mbean (keys %$mbeans) {
$mbean =~ /(?:[:,])poolName=(.*?)(?:,|$)/;
my $poolName = $1;
$mbean =~ /(?:[:,])name=(.*?)(?:,|$)/;
my $name = $1;
$results->{$name} = {
name => $name,
poolName => $poolName
};
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $results = $self->manage_selection(%options);
foreach my $instance (sort keys %$results) {
$self->{output}->output_add(
long_msg =>
'[name = ' . $results->{$instance}->{name} . "]" .
" [poolName = '" . $results->{$instance}->{poolName} . "']"
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List connection pools:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['name', 'poolName']);
}
sub disco_show {
my ($self, %options) = @_;
my $results = $self->manage_selection(%options);
foreach my $instance (sort keys %$results) {
$self->{output}->add_disco_entry(
%{$results->{$instance}}
);
}
}
1;
__END__
=head1 MODE
List connection pools.
=over 8
=back
=cut

View File

@ -0,0 +1,49 @@
#
# Copyright 2023 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::oracle::ucp::jmx::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_custom);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{modes} = {
'connection-pools' => 'apps::oracle::ucp::jmx::mode::connectionpools',
'list-connection-pools' => 'apps::oracle::ucp::jmx::mode::listconnectionpools'
};
$self->{custom_modes}->{jolokia} = 'centreon::common::protocols::jmx::custom::jolokia';
return $self;
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check Oracle Universal Connection Pool in JMX. Need Jolokia agent.
=cut

View File

@ -67,26 +67,36 @@ sub run {
$valueRuntime = $result->{$oid_pfsenseRuntime};
if ($valueStatus == 1) {
my $exit_code = $self->{perfdata}->threshold_check(value => $valueRuntime,
threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
$self->{output}->perfdata_add(label => 'runtime', unit => 's',
value => floor($valueRuntime / 100),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0);
$self->{output}->output_add(severity => $exit_code,
short_msg => sprintf("PfSense running since : %s",
centreon::plugins::misc::change_seconds(value => floor($valueRuntime / 100))));
my $exit_code = $self->{perfdata}->threshold_check(
value => $valueRuntime,
threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]
);
$self->{output}->perfdata_add(
label => 'runtime', unit => 's',
value => floor($valueRuntime / 100),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0
);
$self->{output}->output_add(
severity => $exit_code,
short_msg => sprintf(
"PfSense running since : %s",
centreon::plugins::misc::change_seconds(value => floor($valueRuntime / 100))
)
);
} else {
$self->{output}->perfdata_add(label => 'runtime', unit => 's',
value => 0,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0);
$self->{output}->output_add(severity => 'critical',
short_msg => 'PfSense not running');
$self->{output}->perfdata_add(
label => 'runtime', unit => 's',
value => 0,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
min => 0
);
$self->{output}->output_add(
severity => 'critical',
short_msg => 'PfSense not running'
);
}
$self->{output}->display();
$self->{output}->exit();

View File

@ -0,0 +1,132 @@
#
# Copyright 2023 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::snmp::mode::statetable;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use Digest::MD5 qw(md5_hex);
sub prefix_global_output {
my ($self, %options) = @_;
return 'Number of state table ';
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, cb_prefix_output => 'prefix_global_output' }
];
$self->{maps_counters}->{global} = [
{ label => 'entries', nlabel => 'state_table.entries.count', set => {
key_values => [ { name => 'count' } ],
output_template => 'entries: %s',
perfdatas => [
{ template => '%s', min => 0 }
]
}
},
{ label => 'searches', nlabel => 'state_table.search.count', set => {
key_values => [ { name => 'searches', diff => 1 } ],
output_template => 'searches: %s',
perfdatas => [
{ template => '%s', min => 0 }
]
}
},
{ label => 'entries-inserted', nlabel => 'state_table.entries.inserted.count', set => {
key_values => [ { name => 'inserted', diff => 1 } ],
output_template => 'entries inserted: %s',
perfdatas => [
{ template => '%s', min => 0 }
]
}
},
{ label => 'entries-removed', nlabel => 'state_table.entries.removed.count', set => {
key_values => [ { name => 'removed', diff => 1 } ],
output_template => 'entries removed: %s',
perfdatas => [
{ template => '%s', min => 0 }
]
}
}
];
}
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 => {
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
if ($options{snmp}->is_snmpv1()) {
$self->{output}->add_option_msg(short_msg => "Can't check SNMP 64 bits counters with SNMPv1.");
$self->{output}->option_exit();
}
my $mapping = {
count => { oid => '.1.3.6.1.4.1.12325.1.200.1.3.1' }, # pfStateTableCount
searches => { oid => '.1.3.6.1.4.1.12325.1.200.1.3.2' }, # pfStateTableSearches
inserted => { oid => '.1.3.6.1.4.1.12325.1.200.1.3.3' }, # pfStateTableInserts
removed => { oid => '.1.3.6.1.4.1.12325.1.200.1.3.4' } # pfStateTableRemovals
};
my $snmp_result = $options{snmp}->get_leef(oids => [ map($_->{oid} . '.0', values(%$mapping)) ], nothing_quit => 1);
$self->{global} = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => 0);
$self->{cache_name} = 'pfsense_' . $self->{mode} . '_' . $options{snmp}->get_hostname() . '_' . $options{snmp}->get_port() . '_' .
(defined($self->{option_results}->{filter_counters}) ? md5_hex($self->{option_results}->{filter_counters}) : md5_hex('all'));
}
1;
__END__
=head1 MODE
Check state table.
=over 8
=item B<--filter-counters>
Only display some counters (regexp can be used).
Example: --filter-counters='count'
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'entries', 'searches', 'entries-inserted', 'entries-removed'.
=back
=cut

View File

@ -29,12 +29,12 @@ sub new {
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
$self->{modes} = {
'list-pfinterfaces' => 'apps::pfsense::snmp::mode::listpfinterfaces',
'packet-stats' => 'apps::pfsense::snmp::mode::packetstats',
'pfinterfaces' => 'apps::pfsense::snmp::mode::pfinterfaces',
'runtime' => 'apps::pfsense::snmp::mode::runtime'
'runtime' => 'apps::pfsense::snmp::mode::runtime',
'state-table' => 'apps::pfsense::snmp::mode::statetable'
};
return $self;

View File

@ -118,11 +118,12 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'max-depth:s' => { name => 'max_depth', default => 0 },
'timezone:s' => { name => 'timezone' },
'unit:s' => { name => 'unit', default => 's' }
'filter-file:s' => { name => 'filter_file' }
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'max-depth:s' => { name => 'max_depth', default => 0 },
'timezone:s' => { name => 'timezone' },
'unit:s' => { name => 'unit', default => 's' }
});
return $self;
@ -190,6 +191,9 @@ sub check_directory {
my $name = $dir . '/' . $file->[1];
next if (defined($self->{option_results}->{filter_file}) && $self->{option_results}->{filter_file} ne '' &&
$name !~ /$self->{option_results}->{filter_file}/);
if ($file->[0] == SMBC_DIR) {
if (defined($self->{option_results}->{max_depth}) && $level + 1 <= $self->{option_results}->{max_depth}) {
push @$list, { name => $name, level => $level + 1 };
@ -263,7 +267,7 @@ Check files.
=item B<--directory>
Check directory (Multiple option)
Check directory (Multiple option).
=item B<--max-depth>
@ -271,7 +275,11 @@ Don't check fewer levels (Default: '0'. Means current dir only). Used for direct
=item B<--file>
Check file (Multiple option)
Check file (Multiple option).
=item B<--filter-file>
Filter files (can be a regexp. Directory in the name).
=item B<--timezone>

View File

@ -144,7 +144,7 @@ Count files in a directory (can be recursive).
=item B<--directory>
Check files in the directory (Multiple option)
Check files in the directory (Multiple option).
=item B<--max-depth>

View File

@ -89,10 +89,11 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'timezone:s' => { name => 'timezone' },
'unit:s' => { name => 'unit', default => 's' }
'filter-file:s' => { name => 'filter_file' },
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'timezone:s' => { name => 'timezone' },
'unit:s' => { name => 'unit', default => 's' }
});
return $self;
@ -155,6 +156,9 @@ sub manage_selection {
my $name = $dir . '/' . $file->[1];
next if (defined($self->{option_results}->{filter_file}) && $self->{option_results}->{filter_file} ne '' &&
$name !~ /$self->{option_results}->{filter_file}/);
$rv = $options{custom}->stat_file(file => $name);
if ($rv->{code} != 0) {
$self->{output}->add_option_msg(short_msg => "cannot stat file '" . $name . "': " . $rv->{message});
@ -206,6 +210,10 @@ Check files in the directory (no recursive) (Multiple option)
Check file (Multiple option)
=item B<--filter-file>
Filter files (can be a regexp. Directory in the name).
=item B<--timezone>
Set the timezone of display date.

View File

@ -58,9 +58,10 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'max-depth:s' => { name => 'max_depth', default => 0 }
'filter-file:s' => { name => 'filter_file' },
'directory:s@' => { name => 'directory' },
'file:s@' => { name => 'file' },
'max-depth:s' => { name => 'max_depth', default => 0 }
});
return $self;
@ -120,6 +121,9 @@ sub check_directory {
my $name = $dir . '/' . $file->[1];
next if (defined($self->{option_results}->{filter_file}) && $self->{option_results}->{filter_file} ne '' &&
$name !~ /$self->{option_results}->{filter_file}/);
if ($file->[0] == SMBC_DIR) {
if (defined($self->{option_results}->{max_depth}) && $level + 1 <= $self->{option_results}->{max_depth}) {
push @$list, { name => $name, level => $level + 1 };
@ -175,6 +179,10 @@ Can get sub directory size with --max-depth option.
Check file (Multiple option)
=item B<--filter-file>
Filter files (can be a regexp. Directory in the name).
=item B<--max-depth>
Don't check fewer levels (Default: '0'. Means current dir only).

View File

@ -33,6 +33,7 @@ sub new {
$options{options}->add_options(arguments => {
'command:s' => { name => 'command' },
'arg:s@' => { name => 'arg' },
'extra-args' => { name => 'extra_args' },
'sanitize-message:s' => { name => 'sanitize_message' }
});
@ -70,9 +71,12 @@ sub sanitize_message {
sub run {
my ($self, %options) = @_;
my @arg = defined($self->{option_results}->{arg}) ? @{$self->{option_results}->{arg}} : ();
push @arg, @{$self->{option_extras}} if ($self->{option_results}->{extra_args});
my $result = $options{custom}->request(
command => $self->{option_results}->{command},
arg => $self->{option_results}->{arg}
arg => \@arg
);
$self->{output}->output_add(
@ -112,6 +116,13 @@ In nrpe use following command to get server version: --command='_NRPE_CHECK'
Set arguments (Multiple option. Example: --arg='arg1' --arg='arg2').
=item B<--extra-args>
Use extra arguments from command line (all values placed after a double-dash '--')
as additional "--arg" options for the NRPE command.
Example: --arg='arg1' --extra-args -- 'arg2' 'arg3' 'arg4'
=item B<--sanitize-message>
Sanitize message by removing heading code and

View File

@ -0,0 +1,207 @@
#
# Copyright 2023 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::protocols::x509::custom::opensslcli;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::ssh;
use centreon::plugins::misc;
use Net::SSLeay 1.42;
use DateTime;
use Socket;
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 => {
'ssh-hostname:s' => { name => 'ssh_hostname' },
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' }
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'OPENSSL CLI OPTIONS', once => 1);
$self->{output} = $options{output};
$self->{ssh} = centreon::plugins::ssh->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->{sslhost} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : '';
$self->{port} = (defined($self->{option_results}->{port})) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : '';
$self->{ssh_hostname} = defined($self->{option_results}->{ssh_hostname}) && $self->{option_results}->{ssh_hostname} ne '' ? $self->{option_results}->{ssh_hostname} : '';
if ($self->{sslhost} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.');
$self->{output}->option_exit();
}
if ($self->{port} eq '') {
$self->{output}->add_option_msg(short_msg => "Please set --port option");
$self->{output}->option_exit();
}
if ($self->{ssh_hostname} ne '') {
$self->{option_results}->{hostname} = $self->{ssh_hostname};
$self->{ssh}->check_options(option_results => $self->{option_results});
}
return 0;
}
sub pem_type {
my ($self, %options) = @_;
my $bio_cert = Net::SSLeay::BIO_new(Net::SSLeay::BIO_s_mem());
if (!$bio_cert) {
$self->{output}->add_option_msg(short_msg => "Cannot init Net::SSLeay: $!");
$self->{output}->option_exit();
}
if (Net::SSLeay::BIO_write($bio_cert, $options{cert}) < 0) {
Net::SSLeay::BIO_free($bio_cert);
$self->{output}->add_option_msg(short_msg => "Cannot write certificate: $!");
$self->{output}->option_exit();
}
my $x509 = Net::SSLeay::PEM_read_bio_X509($bio_cert);
Net::SSLeay::BIO_free($bio_cert);
if (!$x509) {
$self->{output}->add_option_msg(short_msg => "Cannot read certificate: $!");
$self->{output}->option_exit();
}
my $cert_infos = {};
$cert_infos->{issuer} = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_issuer_name($x509));
$cert_infos->{expiration_date} = Net::SSLeay::P_ASN1_TIME_get_isotime(Net::SSLeay::X509_get_notAfter($x509));
my $subject = Net::SSLeay::X509_NAME_oneline(Net::SSLeay::X509_get_subject_name($x509));
if ($subject =~ /CN=(.*?)(?:\/(?:C|ST|L|O)=|\Z)/) {
$cert_infos->{subject} = $1;
}
my @subject_alt_names = Net::SSLeay::X509_get_subjectAltNames($x509);
my $append = '';
$cert_infos->{alt_subjects} = '';
for (my $i = 0; $i < $#subject_alt_names; $i += 2) {
my ($type, $name) = ($subject_alt_names[$i], $subject_alt_names[$i + 1]);
if ($type == &Net::SSLeay::GEN_IPADD) {
$name = Socket::inet_ntop(length($name) > 4 ? Socket::AF_INET6 : Socket::AF_INET, $name);
}
$cert_infos->{alt_subjects} .= $append . $name;
$append = ', ';
}
$cert_infos->{expiration_date} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/; # 2033-05-16T20:39:37Z
my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6);
$cert_infos->{expiration} = $dt->epoch();
return $cert_infos;
}
sub get_certificate_informations {
my ($self, %options) = @_;
my $timeout = 30;
my ($stdout, $exit_code);
if ($self->{ssh_hostname} ne '') {
($stdout, $exit_code) = $self->{ssh}->execute(
hostname => $self->{ssh_hostname},
command => 'openssl',
command_options => "s_client -connect '" . $self->{sslhost} . ':' . $self->{port} . "'",
timeout => $timeout,
no_quit => 1
);
} else {
($stdout, $exit_code) = centreon::plugins::misc::execute(
output => $self->{output},
sudo => $self->{option_results}->{sudo},
options => { timeout => $timeout },
command => 'openssl',
command_options => "s_client -connect '" . $self->{sslhost} . ':' . $self->{port} . "'",
no_quit => 1
);
}
$self->{output}->output_add(long_msg => "command response: $stdout", debug => 1);
if ($stdout !~ /^(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----)/ms) {
$self->{output}->add_option_msg(short_msg => "cannot find the server certificate");
$self->{output}->option_exit();
}
my $cert = $1;
my $cert_infos = $self->pem_type(cert => $cert);
return $cert_infos;
}
1;
__END__
=head1 NAME
openssl connections
=head1 OPENSSL CLI OPTIONS
openssl connection
=over 8
=item B<--hostname>
IP Addr/FQDN of the host.
=item B<--port>
Port used by host.
=back
=head1 DESCRIPTION
B<custom>.
=cut

View File

@ -37,6 +37,7 @@ sub new {
$self->{custom_modes}->{tcp} = 'apps::protocols::x509::custom::tcp';
$self->{custom_modes}->{https} = 'apps::protocols::x509::custom::https';
$self->{custom_modes}->{file} = 'apps::protocols::x509::custom::file';
$self->{custom_modes}->{opensslcli} = 'apps::protocols::x509::custom::opensslcli';
return $self;
}

View File

@ -181,7 +181,7 @@ sub clean_token {
my ($self, %options) = @_;
my $datas = { updated => time() };
$self->{cache}->write(data => $datas);
$self->{cache_connect}->write(data => $datas);
}
sub request_api {

View File

@ -0,0 +1,136 @@
#
# Copyright 2023 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::common::airespace::snmp::mode::listaps;
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);
}
sub manage_selection {
my ($self, %options) = @_;
# Collecting all the relevant informations user may needs when using discovery function for AP in Cisco WLC controllers.
# They had been select with https://oidref.com/1.3.6.1.4.1.14179.2.2.1.1.3 as support.
my $mapping = {
name => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.3' }, # bsnAPName
location => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.4' }, # bsnAPLocation
model => { oid => '.1.3.6.1.4.1.14179.2.2.1.1.16' } # bsnAPModel
};
# parent oid for all the mapping usage
my $oid_bsnAPEntry = '.1.3.6.1.4.1.14179.2.2.1.1';
my $snmp_result = $options{snmp}->get_table(
oid => $oid_bsnAPEntry,
start => $mapping->{name}->{oid}, # First oid of the mapping => here : 3
end => $mapping->{model}->{oid} # Last oid of the mapping => here : 16
);
my $results = {};
# Iterate for all oids catch in snmp result above
foreach my $oid (keys %$snmp_result) {
next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/);
my $oid_path = $1;
my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $oid_path);
$results->{$oid_path} = {
name => $result->{name},
location => $result->{location},
model => $result->{model}
};
}
return $results;
}
sub run {
my ($self, %options) = @_;
my $results = $self->manage_selection(snmp => $options{snmp});
foreach my $oid_path (sort keys %$results) {
$self->{output}->output_add(
long_msg => sprintf(
'[oid_path: %s] [name: %s] [location: %s] [model: %s]',
$oid_path,
$results->{$oid_path}->{name},
$results->{$oid_path}->{location},
$results->{$oid_path}->{model}
)
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List aps'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['name','location','model']);
}
sub disco_show {
my ($self, %options) = @_;
my $results = $self->manage_selection(snmp => $options{snmp});
foreach my $oid_path (sort keys %$results) {
$self->{output}->add_disco_entry(
name => $results->{$oid_path}->{name},
location => $results->{$oid_path}->{location},
model => $results->{$oid_path}->{model}
);
}
}
1;
__END__
=head1 MODE
List wireless name.
=over 8
=back
=cut

View File

@ -24,16 +24,25 @@ use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
use Time::Local;
sub custom_status_output {
my ($self, %options) = @_;
my $msg = sprintf("Status is '%s', Expires in '%s' [%s]",
$self->{result_values}->{flag},
$self->{result_values}->{expires_human},
$self->{result_values}->{expires_date});
my $msg = "status is '" . $self->{result_values}->{flag} . "'";
if ($self->{result_values}->{expires_date} =~ /never/i) {
$msg .= ', never expires';
} elsif ($self->{result_values}->{expires_date} =~ /expired/i) {
$msg .= ', expired';
} else {
$msg .= sprintf(
"expires in %s [%s]",
$self->{result_values}->{expires_human},
$self->{result_values}->{expires_date}
);
}
return $msg;
}
@ -45,36 +54,21 @@ sub custom_status_calc {
$self->{result_values}->{service} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseService'};
$self->{result_values}->{expires} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseExpires'};
$self->{result_values}->{expires_date} = $options{new_datas}->{$self->{instance} . '_sysExtLicenseExpires'};
$self->{result_values}->{expires_human} = 'Never';
if ($self->{result_values}->{expires} !~ /Never/) {
$self->{result_values}->{expires_human} = 'never';
if ($self->{result_values}->{expires_date} =~ /Expired/) {
$self->{result_values}->{expires_human} = 'expired';
$self->{result_values}->{expires} = 0;
}
if ($self->{result_values}->{expires_date} !~ /Never|Expired/) {
my ($year, $mon, $mday, $hour, $min, $sec) = split(/[\s\-:]+/, $self->{result_values}->{expires});
$self->{result_values}->{expires} = timelocal($sec, $min, $hour, $mday, $mon - 1, $year) - time();
$self->{result_values}->{expires_human} = centreon::plugins::misc::change_seconds(value => $self->{result_values}->{expires});
$self->{result_values}->{expires_human} = $self->{result_values}->{expires} = 0 if ($self->{result_values}->{expires} < 0);
}
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'license', type => 1, cb_prefix_output => 'prefix_output',
message_multiple => 'All licenses status are ok' },
];
$self->{maps_counters}->{license} = [
{ label => 'status', threshold => 0, set => {
key_values => [ { name => 'sysExtLicenseKey' }, { name => 'sysExtLicenseFlags' },
{ name => 'sysExtLicenseService' }, { name => 'sysExtLicenseExpires' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold,
}
},
];
return 0;
}
sub prefix_output {
@ -83,27 +77,39 @@ sub prefix_output {
return "License '" . $options{instance_value}->{sysExtLicenseService} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'license', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All licenses status are ok' }
];
$self->{maps_counters}->{license} = [
{ label => 'status', type => 2, critical_default => '%{flag} !~ /enabled/i || (%{expires} ne "Never" && %{expires} < 86400)', set => {
key_values => [
{ name => 'sysExtLicenseKey' }, { name => 'sysExtLicenseFlags' },
{ name => 'sysExtLicenseService' }, { name => 'sysExtLicenseExpires' }
],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&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 => {
"warning-status:s" => { name => 'warning_status' },
"critical-status:s" => { name => 'critical_status',
default => '%{flag} !~ /enabled/i || (%{expires} ne "Never" && %{expires} < 86400)' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
my %map_flags = (
'E' => 'enabled', 'A' => 'auto-generated', 'R' => 'reboot-required'
);
@ -115,7 +121,7 @@ my $mapping = {
sysExtLicenseInstalled => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.3' },
sysExtLicenseExpires => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.4' },
sysExtLicenseFlags => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.5', map => \%map_flags },
sysExtLicenseService => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.6' },
sysExtLicenseService => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.6' }
};
sub manage_selection {
@ -133,7 +139,6 @@ sub manage_selection {
}
$self->{license} = {};
foreach my $oid (keys %{$snmp_result}) {
next if ($oid !~ /^$mapping->{sysExtLicenseKey}->{oid}\.(.*)/);
my $instance = $1;
@ -146,7 +151,7 @@ sub manage_selection {
$self->{license}->{$result->{sysExtLicenseService}} = { %{$result} };
}
if (scalar(keys %{$self->{license}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No license found.");
$self->{output}->option_exit();

View File

@ -219,7 +219,10 @@ sub manage_selection {
}
my $local;
if (length($result->{localAddr}) == 4) {
# it can be empty
if (length($result->{localAddr}) == 0) {
$local = '-';
} elsif (length($result->{localAddr}) == 4) {
$local = Socket::inet_ntop(Socket::AF_INET, $result->{localAddr}) . ':' . $result->{localPort};
} else {
$local = '[' . Socket::inet_ntop(Socket::AF_INET6, $result->{localAddr}) . ']:' . $result->{localPort};

View File

@ -117,9 +117,9 @@ sub check_options {
command => $self->{option_results}->{naviseccli_command},
command_path => $self->{option_results}->{naviseccli_path}
);
$self->{option_results}->{navicli_command} = 'naviseccli'
$self->{option_results}->{naviseccli_command} = 'naviseccli'
if (!defined($self->{option_results}->{naviseccli_command}) || $self->{option_results}->{naviseccli_command} eq '');
$self->{option_results}->{navicli_path} = '/opt/Navisphere/bin'
$self->{option_results}->{naviseccli_path} = '/opt/Navisphere/bin'
if (!defined($self->{option_results}->{naviseccli_path}) || $self->{option_results}->{naviseccli_path} eq '');
if (defined($self->{option_results}->{ssh_address}) && $self->{option_results}->{ssh_address} ne '') {

View File

@ -0,0 +1,84 @@
#
# Copyright 2023 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::common::redfish::restapi::mode::components::drive;
use strict;
use warnings;
sub check {
my ($self) = @_;
$self->{output}->output_add(long_msg => 'checking drives');
$self->{components}->{drive} = { name => 'drives', total => 0, skip => 0 };
return if ($self->check_filter(section => 'drive'));
$self->get_storages() if (!defined($self->{storages}));
foreach my $storage (@{$self->{storages}}) {
$storage->{'@odata.id'} =~ /Systems\/(\d+)\//;
my $system_id = $1;
my $system_name = 'system:' . $1;
my $storage_name = $storage->{Id};
foreach (@{$storage->{Drives}}) {
my $drive = $self->get_drive(drive => $_);
my $instance = $system_id . '.' . $storage->{Id} . '.' . $drive->{Id};
$drive->{Status}->{Health} = defined($drive->{Status}->{Health}) ? $drive->{Status}->{Health} : 'n/a';
$drive->{Status}->{State} = defined($drive->{Status}->{State}) ? $drive->{Status}->{State} : 'n/a';
next if ($self->check_filter(section => 'drive', instance => $instance));
$self->{components}->{drive}->{total}++;
$self->{output}->output_add(
long_msg => sprintf(
"drive '%s/%s/%s' status is '%s' [instance: %s, state: %s, location: %s]",
$system_name,
$storage_name,
$drive->{Id},
$drive->{Status}->{Health},
$instance,
$drive->{Status}->{State},
$drive->{PhysicalLocation}->{PartLocation}->{ServiceLabel}
)
);
my $exit = $self->get_severity(label => 'state', section => 'drive.state', value => $drive->{Status}->{State});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Drive '%s/%s/%s' state is '%s'", $system_name, $storage_name, $drive->{Id}, $drive->{Status}->{State})
);
}
$exit = $self->get_severity(label => 'status', section => 'drive.status', value => $drive->{Status}->{Health});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Drive '%s/%s/%s' status is '%s'", $system_name, $storage_name, $drive->{Id}, $drive->{Status}->{Health})
);
}
}
}
}
1;

View File

@ -0,0 +1,78 @@
#
# Copyright 2023 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::common::redfish::restapi::mode::components::sc;
use strict;
use warnings;
sub check {
my ($self) = @_;
$self->{output}->output_add(long_msg => 'checking storage controllers');
$self->{components}->{sc} = { name => 'sc', total => 0, skip => 0 };
return if ($self->check_filter(section => 'sc'));
$self->get_storages() if (!defined($self->{storages}));
foreach my $storage (@{$self->{storages}}) {
$storage->{'@odata.id'} =~ /Systems\/(\d+)\//;
my $system_id = $1;
my $system_name = 'system:' . $1;
my $storage_name = $storage->{Id};
foreach my $sc (@{$storage->{StorageControllers}}) {
my $instance .= $system_id . '.' . $storage->{Id} . '.' . $sc->{MemberId};
my $sc_name = $sc->{MemberId};
$sc->{Status}->{Health} = defined($sc->{Status}->{Health}) ? $sc->{Status}->{Health} : 'n/a';
$sc->{Status}->{State} = defined($sc->{Status}->{State}) ? $sc->{Status}->{State} : 'n/a';
next if ($self->check_filter(section => 'sc', instance => $instance));
$self->{components}->{sc}->{total}++;
$self->{output}->output_add(
long_msg => sprintf(
"storage controller '%s/%s/%s' status is '%s' [instance: %s, state: %s]",
$system_name, $storage_name, $sc_name, $sc->{Status}->{Health}, $instance, $sc->{Status}->{State}
)
);
my $exit = $self->get_severity(label => 'state', section => 'sc.state', value => $sc->{Status}->{State});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Storage controller '%s/%s/%s' state is '%s'", $system_name, $storage_name, $sc_name, $sc->{Status}->{State})
);
}
$exit = $self->get_severity(label => 'status', section => 'sc.status', value => $sc->{Status}->{Health});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Storage controller '%s/%s/%s' status is '%s'", $system_name, $storage_name, $sc_name, $sc->{Status}->{Health})
);
}
}
}
}
1;

View File

@ -0,0 +1,73 @@
#
# Copyright 2023 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::common::redfish::restapi::mode::components::storage;
use strict;
use warnings;
sub check {
my ($self) = @_;
$self->{output}->output_add(long_msg => 'checking storages');
$self->{components}->{storage} = { name => 'storages', total => 0, skip => 0 };
return if ($self->check_filter(section => 'storage'));
$self->get_storages() if (!defined($self->{storages}));
foreach my $storage (@{$self->{storages}}) {
$storage->{'@odata.id'} =~ /Systems\/(\d+)\//;
my $system_id = $1;
my $system_name = 'system:' . $1;
my $storage_name = $storage->{Id};
my $instance = $system_id . '.' . $storage->{Id};
$storage->{Status}->{Health} = defined($storage->{Status}->{HealthRollup}) ? $storage->{Status}->{HealthRollup} : 'n/a';
$storage->{Status}->{State} = defined($storage->{Status}->{State}) ? $storage->{Status}->{State} : 'n/a';
next if ($self->check_filter(section => 'storage', instance => $instance));
$self->{components}->{storage}->{total}++;
$self->{output}->output_add(
long_msg => sprintf(
"storage '%s/%s' status is '%s' [instance: %s, state: %s]",
$system_name, $storage_name, $storage->{Status}->{HealthRollup}, $instance, $storage->{Status}->{State}
)
);
my $exit = $self->get_severity(label => 'state', section => 'storage.state', value => $storage->{Status}->{State});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Storage '%s/%s' state is '%s'", $system_name, $storage_name, $storage->{Status}->{State})
);
}
$exit = $self->get_severity(label => 'status', section => 'storage.status', value => $storage->{Status}->{HealthRollup});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Storage '%s/%s' status is '%s'", $system_name, $storage_name, $storage->{Status}->{HealthRollup})
);
}
}
}
1;

View File

@ -0,0 +1,78 @@
#
# Copyright 2023 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package centreon::common::redfish::restapi::mode::components::volume;
use strict;
use warnings;
sub check {
my ($self) = @_;
$self->{output}->output_add(long_msg => 'checking volumes');
$self->{components}->{volume} = { name => 'volumes', total => 0, skip => 0 };
return if ($self->check_filter(section => 'volume'));
$self->get_storages() if (!defined($self->{storages}));
foreach my $storage (@{$self->{storages}}) {
$storage->{'@odata.id'} =~ /Systems\/(\d+)\//;
my $system_id = $1;
my $system_name = 'system:' . $1;
my $storage_name = $storage->{Id};
my $volumes = $self->get_volumes(storage => $storage);
foreach my $volume (@$volumes) {
my $instance = $system_id . '.' . $storage->{Id} . '.' . $volume->{Id};
$volume->{Status}->{Health} = defined($volume->{Status}->{Health}) ? $volume->{Status}->{Health} : 'n/a';
$volume->{Status}->{State} = defined($volume->{Status}->{State}) ? $volume->{Status}->{State} : 'n/a';
next if ($self->check_filter(section => 'volume', instance => $instance));
$self->{components}->{volume}->{total}++;
$self->{output}->output_add(
long_msg => sprintf(
"volume '%s/%s/%s' status is '%s' [instance: %s, state: %s]",
$system_name, $storage_name, $volume->{Id}, $volume->{Status}->{Health}, $instance, $volume->{Status}->{State}
)
);
my $exit = $self->get_severity(label => 'state', section => 'volume.state', value => $volume->{Status}->{State});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Volume '%s/%s/%s' state is '%s'", $system_name, $storage_name, $volume->{Id}, $volume->{Status}->{State})
);
}
$exit = $self->get_severity(label => 'status', section => 'volume.status', value => $volume->{Status}->{Health});
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit,
short_msg => sprintf("Volume '%s/%s/%s' status is '%s'", $system_name, $storage_name, $volume->{Id}, $volume->{Status}->{Health})
);
}
}
}
}
1;

View File

@ -51,7 +51,7 @@ sub set_system {
$self->{components_exec_load} = 0;
$self->{components_path} = 'centreon::common::redfish::restapi::mode::components';
$self->{components_module} = ['chassis', 'device', 'fan', 'psu', 'temperature'];
$self->{components_module} = ['chassis', 'device', 'drive', 'fan', 'psu', 'sc', 'storage', 'temperature', 'volume'];
}
sub new {
@ -106,6 +106,43 @@ sub get_chassis {
}
}
sub get_drive {
my ($self, %options) = @_;
return {} if (!defined($options{drive}->{'@odata.id'}));
return $self->{custom}->request_api(url_path => $options{drive}->{'@odata.id'});
}
sub get_volumes {
my ($self, %options) = @_;
return [] if (!defined($options{storage}->{Volumes}->{'@odata.id'}));
my $volumes = $self->{custom}->request_api(url_path => $options{storage}->{Volumes}->{'@odata.id'});
my $result = [];
foreach my $volume (@{$volumes->{Members}}) {
my $volume_detailed = $self->{custom}->request_api(url_path => $volume->{'@odata.id'});
push @$result, $volume_detailed;
}
return $result;
}
sub get_storages {
my ($self, %options) = @_;
$self->{storages} = [];
my $systems = $self->{custom}->request_api(url_path => '/redfish/v1/Systems');
foreach my $system (@{$systems->{Members}}) {
my $storages = $self->{custom}->request_api(url_path => $system->{'@odata.id'} . '/Storage/');
foreach my $storage (@{$storages->{Members}}) {
my $storage_detailed = $self->{custom}->request_api(url_path => $storage->{'@odata.id'});
push @{$self->{storages}}, $storage_detailed;
}
}
}
sub execute_custom {
my ($self, %options) = @_;
@ -123,7 +160,7 @@ Check hardware.
=item B<--component>
Which component to check (Default: '.*').
Can be: 'chassis', 'device', 'fan', 'psu', 'temperature'.
Can be: 'chassis', 'device', 'drive', 'fan', 'psu', 'sc', 'storage', 'temperature', 'volume'.
=item B<--filter>

View File

@ -62,6 +62,15 @@ sub GetOptions {
if (defined($ARGV[$i]) && $ARGV[$i] =~ /^--(.*?)(?:=|$)((?s).*)/) {
my ($option, $value) = ($1, $2);
# The special argument "--" forces an end of option-scanning.
# All arguments placed after are stored in a list with the special option key '_double_dash_'.
if ($option eq '' && $value eq '') {
my @values = splice @ARGV, $i + 1, $num_args - $i - 1;
push @{${$opts{'_double_dash_'}}}, @values;
splice @ARGV, $i, 1;
last;
}
# find type of option
if ($search_str !~ /,((?:[^,]*?\|){0,}$option(?:\|.*?){0,}(:.*?){0,1}),/) {
warn "Unknown option: $option" if ($warn_message == 1);

View File

@ -136,8 +136,15 @@ sub check_options {
my ($self, %options) = @_;
$self->{data_source} = (defined($self->{option_results}->{data_source})) ? shift(@{$self->{option_results}->{data_source}}) : undef;
$self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : undef;
$self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : undef;
$self->{username} = undef;
if (defined($self->{option_results}->{username})) {
$self->{username} = ref($self->{option_results}->{username}) eq 'ARRAY' ? shift(@{$self->{option_results}->{username}}) : $self->{option_results}->{username};
}
$self->{password} = undef;
if (defined($self->{option_results}->{password})) {
$self->{password} = ref($self->{option_results}->{password}) eq 'ARRAY' ? shift(@{$self->{option_results}->{password}}) : $self->{option_results}->{password};
}
$self->{connect_options} = (defined($self->{option_results}->{connect_options})) ? shift(@{$self->{option_results}->{connect_options}}) : undef;
$self->{connect_query} = (defined($self->{option_results}->{connect_query})) ? shift(@{$self->{option_results}->{connect_query}}) : undef;
$self->{env} = (defined($self->{option_results}->{env})) ? shift(@{$self->{option_results}->{env}}) : undef;

View File

@ -32,6 +32,7 @@ sub new {
$self->{perfdata} = centreon::plugins::perfdata->new(output => $options{output});
%{$self->{option_results}} = ();
@{$self->{option_extras}} = @{$options{options}->{extra_arguments}};
$self->{output} = $options{output};
$self->{output}->use_new_perfdata(value => 1)
if (defined($options{force_new_perfdata}) && $options{force_new_perfdata} == 1);

View File

@ -37,6 +37,7 @@ sub new {
$self->{options} = {};
@{$self->{pod_package}} = ();
$self->{pod_packages_once} = {};
$self->{extra_arguments} = [];
if ($alternative == 0) {
require Getopt::Long;
@ -145,6 +146,9 @@ sub parse_options {
};
}
# Store all arguments placed after the special argument "--" in the 'extra_arguments' list
$self->{options}->{'_double_dash_'} = \$self->{extra_arguments};
GetOptions(
%{$self->{options}}
);

View File

@ -223,7 +223,7 @@ sub do_map {
while ($map =~ /\%\{(.*?)\}/g) {
my $sub = '';
$sub = $self->{lookup_values}->{$1} if (defined($self->{lookup_values}->{$1}));
$map =~ s/\%\{$1\}/$sub/g
$map =~ s/\%\{$1\}/$sub/g;
}
$option =~ s/-/_/g;
$options{option_results}->{$option} = $map;

View File

@ -113,7 +113,7 @@ sub check_options {
}
}
$self->{statefile_format} = 'dumper';
$self->{statefile_format} = 'json';
if (defined($options{option_results}->{statefile_format}) && $options{option_results}->{statefile_format} ne '' &&
$options{option_results}->{statefile_format} =~ /^(?:dumper|json|storable)$/) {
$self->{statefile_format} = $options{option_results}->{statefile_format};

View File

@ -28,9 +28,8 @@ use warnings;
sub custom_usage_perfdata {
my ($self, %options) = @_;
my $label = 'capacity-usage';
my $value_perf = $self->{result_values}->{used_space};
my %total_options = ();
if ($self->{instance_mode}->{option_results}->{units} eq '%') {
$total_options{total} = $self->{result_values}->{total_capacity};
@ -38,12 +37,12 @@ sub custom_usage_perfdata {
}
$self->{output}->perfdata_add(
label => $label, unit => 'B',
nlabel => 'fileshare.capacity.usage.bytes',
nlabel => 'fileshare.capacity.usage.bytes',
unit => 'B',
value => $value_perf,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}, %total_options),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}, %total_options),
min => 0, max => $self->{result_values}->{total_capacity},
min => 0, max => $self->{result_values}->{total_capacity}
);
}
@ -55,9 +54,13 @@ sub custom_usage_threshold {
if ($self->{instance_mode}->{option_results}->{units} eq '%') {
$threshold_value = $self->{result_values}->{prct_used};
}
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
threshold => [ { label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' } ]);
$exit = $self->{perfdata}->threshold_check(
value => $threshold_value,
threshold => [
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{thlabel}, exit_litteral => 'warning' }
]
);
return $exit;
}
@ -66,11 +69,13 @@ sub custom_usage_output {
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total_capacity} );
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used_space} );
my $msg = sprintf("Fileshare '%s' from storage account '%s' used capacity: %s (%.2f%%), total size %s",
$self->{result_values}->{fileshare},
$self->{result_values}->{storageaccount},
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
$total_size_value . " " . $total_size_unit);
my $msg = sprintf(
"Fileshare '%s' from storage account '%s' used capacity: %s (%.2f%%), total size %s",
$self->{result_values}->{fileshare},
$self->{result_values}->{storageaccount},
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
$total_size_value . " " . $total_size_unit
);
return $msg;
}
@ -89,7 +94,7 @@ sub custom_usage_calc {
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'fileshare', type => 0 }
];
@ -100,7 +105,7 @@ sub set_counters {
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
closure_custom_threshold_check => $self->can('custom_usage_threshold')
}
}
]
@ -111,13 +116,12 @@ sub new {
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments =>
{
"resource-group:s" => { name => 'resource_group' },
"storage-account:s" => { name => 'storage_account' },
"units:s" => { name => 'units', default => '%' },
"fileshare:s" => { name => 'fileshare' }
});
$options{options}->add_options(arguments => {
'resource-group:s' => { name => 'resource_group' },
'storage-account:s' => { name => 'storage_account' },
'units:s' => { name => 'units', default => '%' },
'fileshare:s' => { name => 'fileshare' }
});
return $self;
}
@ -140,21 +144,22 @@ sub check_options {
$self->{output}->add_option_msg(short_msg => "Need to specify --fileshare <name>");
$self->{output}->option_exit();
}
}
sub manage_selection {
my ($self, %options) = @_;
my $results;
$results = $options{custom}->azure_get_file_share_stats(resource_group => $self->{option_results}->{resource_group}, storage_account => $self->{option_results}->{storage_account},
fileshare => $self->{option_results}->{fileshare}, api_version => $self->{api_version});
$results = $options{custom}->azure_get_file_share_stats(
resource_group => $self->{option_results}->{resource_group}, storage_account => $self->{option_results}->{storage_account},
fileshare => $self->{option_results}->{fileshare}, api_version => $self->{api_version}
);
$self->{fileshare} = {
storage_account => $self->{option_results}->{storage_account},
fileshare => $self->{option_results}->{fileshare},
total_capacity => $results->{properties}->{shareQuota},
used_space => $results->{properties}->{shareUsageBytes} * 1024 ** 3
used_space => $results->{properties}->{shareUsageBytes}
};
if (scalar(keys %{$self->{fileshare}}) <= 0) {

View File

@ -280,7 +280,7 @@ sub convert_iso8601_to_epoch {
nanosecond => $7
);
my $epoch_time = $dt->epoch;
my $epoch_time = $dt->epoch();
return $epoch_time;
}
@ -327,8 +327,13 @@ sub azure_get_subscription_cost_management {
$encoded_form_post = JSON::XS->new->utf8->encode($options{body_post});
};
$self->{http}->add_header(key => 'Content-Type', value => 'application/json');
my $response = $self->request_api(method => 'POST', full_url => $full_url, query_form_post => $encoded_form_post, hostname => '');
my $response = $self->request_api(
method => 'POST',
full_url => $full_url,
query_form_post => $encoded_form_post,
hostname => '',
header => ['Content-Type: application/json']
);
return $response->{properties}->{rows};
}
@ -562,23 +567,23 @@ sub azure_list_vms {
my $full_response = [];
my $full_url = $self->azure_list_vms_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
}
sub azure_list_file_shares_set_url {
my ($self, %options) = @_;
my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourceGroups/" . $options{resource_group} . "/providers/Microsoft.Storage/storageAccounts/"
. $options{storage_account} . "/fileServices/default/shares?api-version=" . $options{api_version};
my $url = $self->{management_endpoint} . "/subscriptions/" . $self->{subscription} . "/resourceGroups/" . $options{resource_group} . "/providers/Microsoft.Storage/storageAccounts/" .
$options{storage_account} . "/fileServices/default/shares?api-version=" . $options{api_version};
return $url;
}
@ -766,13 +771,13 @@ sub azure_list_sqlservers {
my $full_response = [];
my $full_url = $self->azure_list_sqlservers_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -992,13 +997,13 @@ sub azure_list_nics {
my $full_response = [];
my $full_url = $self->azure_list_nics_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1020,13 +1025,13 @@ sub azure_list_nsgs {
my $full_response = [];
my $full_url = $self->azure_list_nsgs_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1048,13 +1053,13 @@ sub azure_list_publicips {
my $full_response = [];
my $full_url = $self->azure_list_publicips_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1076,13 +1081,13 @@ sub azure_list_route_tables {
my $full_response = [];
my $full_url = $self->azure_list_route_tables_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1104,13 +1109,13 @@ sub azure_list_snapshots {
my $full_response = [];
my $full_url = $self->azure_list_snapshots_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1132,13 +1137,13 @@ sub azure_list_sqlvms {
my $full_response = [];
my $full_url = $self->azure_list_sqlvms_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;
@ -1160,13 +1165,13 @@ sub azure_list_sqlelasticpools {
my $full_response = [];
my $full_url = $self->azure_list_sqlelasticpools_set_url(%options);
while (1) {
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
my $response = $self->request_api(method => 'GET', full_url => $full_url, hostname => '');
foreach (@{$response->{value}}) {
push @$full_response, $_;
}
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
last if (!defined($response->{nextLink}));
$full_url = $response->{nextLink};
}
return $full_response;

View File

@ -49,7 +49,8 @@ sub new {
'token:s' => { name => 'token' },
'timeout:s' => { name => 'timeout' },
'limit:s' => { name => 'limit' },
'config-file:s' => { name => 'config_file' }
'config-file:s' => { name => 'config_file' },
'namespace:s' => { name => 'namespace' }
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
@ -71,18 +72,20 @@ sub set_defaults {}
sub check_options {
my ($self, %options) = @_;
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef;
$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} =~ /(\d+)/ ? $1 : 10;
$self->{token} = (defined($self->{option_results}->{token})) ? $self->{option_results}->{token} : '';
$self->{limit} = (defined($self->{option_results}->{limit})) && $self->{option_results}->{limit} =~ /(\d+)/ ? $1 : 100;
if (!defined($self->{hostname}) || $self->{hostname} eq '') {
$self->{namespace} = defined($self->{option_results}->{namespace}) && $self->{option_results}->{namespace} ne '' ?
$self->{option_results}->{namespace} : '';
if ($self->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --hostname option.");
$self->{output}->option_exit();
}
if (!defined($self->{token}) || $self->{token} eq '') {
if ($self->{token} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --token option.");
$self->{output}->option_exit();
}
@ -116,10 +119,13 @@ sub settings {
sub request_api {
my ($self, %options) = @_;
$self->settings;
$self->settings();
$self->{output}->output_add(long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} .
':' . $self->{port} . $options{url_path} . "'", debug => 1);
$self->{output}->output_add(
long_msg => "URL: '" . $self->{proto} . '://' . $self->{hostname} .
':' . $self->{port} . $options{url_path} . "'",
debug => 1
);
my $response = $self->{http}->request(%options);
@ -153,7 +159,7 @@ sub request_api {
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $response");
$self->{output}->option_exit();
}
return $decoded;
}
@ -163,7 +169,7 @@ sub request_api_paginate {
my @items;
my @get_param = ( 'limit=' . $self->{limit} );
push @get_param, @{$options{get_param}} if (defined($options{get_param}));
while (1) {
my $response = $self->request_api(
method => $options{method},
@ -183,105 +189,141 @@ sub request_api_paginate {
sub kubernetes_list_cronjobs {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/batch/v1beta1/cronjobs');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/batch/v1beta1/namespaces/' . $self->{namespace} . '/cronjobs' : '/apis/batch/v1beta1/cronjobs'
);
return $response;
}
sub kubernetes_list_daemonsets {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/daemonsets');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/apps/v1/namespaces/' . $self->{namespace} . '/daemonsets' : '/apis/apps/v1/daemonsets'
);
return $response;
}
sub kubernetes_list_deployments {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/deployments');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/apps/v1/namespaces/' . $self->{namespace} . '/deployments' : '/apis/apps/v1/deployments'
);
return $response;
}
sub kubernetes_list_events {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/events');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/api/v1/namespaces/' . $self->{namespace} . '/events' : '/api/v1/events'
);
return $response;
}
sub kubernetes_list_ingresses {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/extensions/v1beta1/ingresses');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/extensions/v1beta1/namespaces/' . $self->{namespace} . '/ingresses' : '/apis/extensions/v1beta1/ingresses'
);
return $response;
}
sub kubernetes_list_namespaces {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/namespaces');
return $response;
}
sub kubernetes_list_nodes {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/nodes');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => '/api/v1/nodes'
);
return $response;
}
sub kubernetes_list_rcs {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/replicationcontrollers');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/api/v1/namespaces/' . $self->{namespace} . '/replicationcontrollers' : '/api/v1/replicationcontrollers'
);
return $response;
}
sub kubernetes_list_replicasets {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/replicasets');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/apps/v1/namespaces/' . $self->{namespace} . '/replicasets' : '/apis/apps/v1/replicasets'
);
return $response;
}
sub kubernetes_list_services {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/v1/services');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/api/v1/namespaces/' . $self->{namespace} . '/services' : '/api/v1/services'
);
return $response;
}
sub kubernetes_list_statefulsets {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/apis/apps/v1/statefulsets');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/apis/apps/v1/namespaces/' . $self->{namespace} . '/statefulsets' : '/apis/apps/v1/statefulsets'
);
return $response;
}
sub kubernetes_list_pods {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/pods');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => $self->{namespace} ne '' ? '/api/v1/namespaces/' . $self->{namespace} . '/pods' : '/api/v1/pods'
);
return $response;
}
sub kubernetes_list_pvs {
my ($self, %options) = @_;
my $response = $self->request_api_paginate(method => 'GET', url_path => '/api/v1/persistentvolumes');
my $response = $self->request_api_paginate(
method => 'GET',
url_path => '/api/v1/persistentvolumes'
);
return $response;
}
@ -325,6 +367,10 @@ Number of responses to return for each list calls.
See https://kubernetes.io/docs/reference/kubernetes-api/common-parameters/common-parameters/#limit
=item B<--namespace>
Set namespace to get informations.
=back
=head1 DESCRIPTION

View File

@ -48,6 +48,7 @@ sub new {
'timeout:s' => { name => 'timeout', default => 10 },
'config-file:s' => { name => 'config_file', default => '~/.kube/config' },
'context:s' => { name => 'context' },
'namespace:s' => { name => 'namespace' },
'sudo' => { name => 'sudo' },
'command:s' => { name => 'command', default => '' },
'command-path:s' => { name => 'command_path' },
@ -76,6 +77,8 @@ sub check_options {
$self->{config_file} = (defined($self->{option_results}->{config_file})) ? $self->{option_results}->{config_file} : '';
$self->{context} = (defined($self->{option_results}->{context})) ? $self->{option_results}->{context} : '';
$self->{timeout} = (defined($self->{option_results}->{timeout})) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10;
$self->{namespace_option} = defined($self->{option_results}->{namespace}) && $self->{option_results}->{namespace} ne '' ?
"--namespace='$self->{option_results}->{namespace}'" : '--all-namespaces';
if (!defined($self->{config_file}) || $self->{config_file} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --config-file option.");
@ -155,7 +158,7 @@ sub execute {
sub kubernetes_list_cronjobs {
my ($self, %options) = @_;
my $cmd = "get cronjobs --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get cronjobs $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -167,7 +170,7 @@ sub kubernetes_list_cronjobs {
sub kubernetes_list_daemonsets {
my ($self, %options) = @_;
my $cmd = "get daemonsets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get daemonsets $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -179,7 +182,7 @@ sub kubernetes_list_daemonsets {
sub kubernetes_list_deployments {
my ($self, %options) = @_;
my $cmd = "get deployments --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get deployments $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -191,7 +194,7 @@ sub kubernetes_list_deployments {
sub kubernetes_list_events {
my ($self, %options) = @_;
my $cmd = "get events --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get events $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -203,7 +206,7 @@ sub kubernetes_list_events {
sub kubernetes_list_ingresses {
my ($self, %options) = @_;
my $cmd = "get ingresses --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get ingresses $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -227,7 +230,7 @@ sub kubernetes_list_namespaces {
sub kubernetes_list_nodes {
my ($self, %options) = @_;
my $cmd = "get nodes --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get nodes $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -239,7 +242,7 @@ sub kubernetes_list_nodes {
sub kubernetes_list_rcs {
my ($self, %options) = @_;
my $cmd = "get replicationcontroller --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get replicationcontroller $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -251,7 +254,7 @@ sub kubernetes_list_rcs {
sub kubernetes_list_replicasets {
my ($self, %options) = @_;
my $cmd = "get replicasets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get replicasets $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -263,7 +266,7 @@ sub kubernetes_list_replicasets {
sub kubernetes_list_services {
my ($self, %options) = @_;
my $cmd = "get services --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get services $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -275,7 +278,7 @@ sub kubernetes_list_services {
sub kubernetes_list_statefulsets {
my ($self, %options) = @_;
my $cmd = "get statefulsets --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get statefulsets $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -287,7 +290,7 @@ sub kubernetes_list_statefulsets {
sub kubernetes_list_pods {
my ($self, %options) = @_;
my $cmd = "get pods --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get pods $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -299,7 +302,7 @@ sub kubernetes_list_pods {
sub kubernetes_list_pvs {
my ($self, %options) = @_;
my $cmd = "get pv --all-namespaces --output='json' --kubeconfig='" . $self->{config_file} . "'"
my $cmd = "get pv $self->{namespace_option} --output='json' --kubeconfig='" . $self->{config_file} . "'"
. " --request-timeout='" . $self->{timeout} . "'";
$cmd .= " --context='" . $self->{context} . "'" if (defined($self->{context}) && $self->{context} ne '');
@ -335,6 +338,10 @@ Kubernetes configuration file path (Default: '~/.kube/config').
Context to use in configuration file.
=item B<--namespace>
Set namespace to get informations.
=item B<--timeout>
Set timeout in seconds (Default: 10).

View File

@ -100,20 +100,20 @@ sub set_counters {
$self->{maps_counters}->{global} = [
{ label => 'warning', nlabel => 'events.type.warning.count', set => {
key_values => [ { name => 'warning' } ],
output_template => 'Warning : %d',
output_template => 'warning: %d',
perfdatas => [
{ label => 'warning_events', template => '%d', min => 0 }
{ template => '%d', min => 0 }
]
}
},
{ label => 'normal', nlabel => 'events.type.normal.count', set => {
key_values => [ { name => 'normal' } ],
output_template => 'Normal : %d',
output_template => 'normal: %d',
perfdatas => [
{ label => 'normal_events', template => '%d', min => 0 }
{ template => '%d', min => 0 }
]
}
},
}
];
$self->{maps_counters}->{events} = [
@ -140,31 +140,22 @@ 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-type:s" => { name => 'filter_type' },
"filter-namespace:s" => { name => 'filter_namespace' },
'filter-type:s' => { name => 'filter_type' },
'filter-namespace:s' => { name => 'filter_namespace' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection {
my ($self, %options) = @_;
$self->{events} = {};
my $results = $options{custom}->kubernetes_list_events();
$self->{global} = { normal => 0, warning => 0 };
$self->{events} = {};
foreach my $event (@{$results}) {
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
$event->{type} !~ /$self->{option_results}->{filter_type}/) {
@ -178,7 +169,7 @@ sub manage_selection {
}
$self->{global}->{lc($event->{type})}++;
$self->{events}->{$event->{metadata}->{uid}} = {
name => $event->{metadata}->{name},
namespace => $event->{metadata}->{namespace},

View File

@ -90,7 +90,8 @@ sub set_counters {
{ label => 'status', type => 2, set => {
key_values => [
{ name => 'active' }, { name => 'last_schedule_time' }, { name => 'name' },
{ name => 'namespace' } ],
{ name => 'namespace' }
],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => $self->can('custom_status_perfdata'),

View File

@ -18,7 +18,7 @@
# limitations under the License.
#
package cloud::kubernetes::mode::discoverynodes;
package cloud::kubernetes::mode::discovery;
use base qw(centreon::plugins::mode);
@ -31,7 +31,8 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
"prettify" => { name => 'prettify' },
'resource-type:s' => { name => 'resource_type' },
'prettify' => { name => 'prettify' }
});
return $self;
@ -40,6 +41,60 @@ sub new {
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if ($self->{option_results}->{resource_type} !~ /^node|namespace$/) {
$self->{output}->add_option_msg(short_msg => 'unknown resource type');
$self->{output}->option_exit();
}
}
sub discovery_node {
my ($self, %options) = @_;
my $nodes = $options{custom}->kubernetes_list_nodes();
my $disco_data = [];
foreach my $node (@$nodes) {
my %entry;
$entry{name} = $node->{metadata}->{name};
$entry{uid} = $node->{metadata}->{uid};
$entry{os_image} = $node->{status}->{nodeInfo}->{osImage};
$entry{kubelet_version} = $node->{status}->{nodeInfo}->{kubeletVersion};
if (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/control-plane'})) {
$entry{node_role} = "control-plane";
} elsif (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/master'})) {
$entry{node_role} = "master";
} else {
$entry{node_role} = "worker";
}
foreach my $address (@{$node->{status}->{addresses}}) {
$entry{internal_ip} = $address->{address} if ($address->{type} eq "InternalIP");
$entry{external_ip} = $address->{address} if ($address->{type} eq "ExternalIP");
$entry{hostname} = $address->{address} if ($address->{type} eq "Hostname");
}
push @$disco_data, \%entry;
}
return $disco_data;
}
sub discovery_namespace {
my ($self, %options) = @_;
my $namespaces = $options{custom}->kubernetes_list_namespaces();
my $disco_data = [];
foreach my $namespace (@$namespaces) {
my %entry;
$entry{name} = $namespace->{metadata}->{name};
$entry{uid} = $namespace->{metadata}->{uid};
push @$disco_data, \%entry;
}
return $disco_data;
}
sub run {
@ -50,35 +105,21 @@ sub run {
$disco_stats->{start_time} = time();
my $nodes = $options{custom}->kubernetes_list_nodes();
foreach my $node (@{$nodes}) {
my %node;
$node{name} = $node->{metadata}->{name};
$node{uid} = $node->{metadata}->{uid};
$node{os_image} = $node->{status}->{nodeInfo}->{osImage};
$node{kubelet_version} = $node->{status}->{nodeInfo}->{kubeletVersion};
if (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/control-plane'})) {
$node{node_role} = "control-plane";
} elsif (defined($node->{metadata}->{labels}->{'node-role.kubernetes.io/master'})) {
$node{node_role} = "master";
} else {
$node{node_role} = "worker";
}
foreach my $address (@{$node->{status}->{addresses}}) {
$node{internal_ip} = $address->{address} if ($address->{type} eq "InternalIP");
$node{external_ip} = $address->{address} if ($address->{type} eq "ExternalIP");
$node{hostname} = $address->{address} if ($address->{type} eq "Hostname");
}
push @disco_data, \%node;
my $results = [];
if ($self->{option_results}->{resource_type} eq 'node') {
$results = $self->discovery_node(
custom => $options{custom}
);
} elsif ($self->{option_results}->{resource_type} eq 'namespace') {
$results = $self->discovery_namespace(
custom => $options{custom}
);
}
$disco_stats->{end_time} = time();
$disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time};
$disco_stats->{discovered_items} = @disco_data;
$disco_stats->{results} = \@disco_data;
$disco_stats->{discovered_items} = scalar(@$results);
$disco_stats->{results} = $results;
my $encoded_data;
eval {
@ -91,7 +132,7 @@ sub run {
if ($@) {
$encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}';
}
$self->{output}->output_add(short_msg => $encoded_data);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1);
$self->{output}->exit();
@ -107,6 +148,10 @@ Nodes discovery.
=over 8
=item B<--resource-type>
Choose the type of resources to discover (Can be: 'node', 'namespace').
=item B<--prettify>
Prettify JSON output.

View File

@ -31,8 +31,8 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
"filter-name:s" => { name => 'filter_name' },
"filter-namespace:s" => { name => 'filter_namespace' },
'filter-name:s' => { name => 'filter_name' },
'filter-namespace:s' => { name => 'filter_namespace' }
});
return $self;
@ -63,7 +63,7 @@ sub manage_selection {
$self->{deployments}->{$deployment->{metadata}->{uid}} = {
uid => $deployment->{metadata}->{uid},
name => $deployment->{metadata}->{name},
namespace => $deployment->{metadata}->{namespace},
namespace => $deployment->{metadata}->{namespace}
}
}
}
@ -73,14 +73,20 @@ sub run {
$self->manage_selection(%options);
foreach my $deployment (sort keys %{$self->{deployments}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{deployments}->{$deployment}->{uid},
$self->{deployments}->{$deployment}->{name},
$self->{deployments}->{$deployment}->{namespace}));
$self->{output}->output_add(
long_msg => sprintf(
'[uid: %s] [name: %s] [namespace: %s]',
$self->{deployments}->{$deployment}->{uid},
$self->{deployments}->{$deployment}->{name},
$self->{deployments}->{$deployment}->{namespace}
)
);
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List deployments:');
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List deployments:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
@ -99,7 +105,7 @@ sub disco_show {
$self->{output}->add_disco_entry(
uid => $self->{deployments}->{$deployment}->{uid},
name => $self->{deployments}->{$deployment}->{name},
namespace => $self->{deployments}->{$deployment}->{namespace},
namespace => $self->{deployments}->{$deployment}->{namespace}
);
}
}

View File

@ -73,14 +73,20 @@ sub run {
$self->manage_selection(%options);
foreach my $ingress (sort keys %{$self->{ingresses}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{ingresses}->{$ingress}->{uid},
$self->{ingresses}->{$ingress}->{name},
$self->{ingresses}->{$ingress}->{namespace}));
$self->{output}->output_add(
long_msg => sprintf(
'[uid: %s] [name: %s] [namespace: %s]',
$self->{ingresses}->{$ingress}->{uid},
$self->{ingresses}->{$ingress}->{name},
$self->{ingresses}->{$ingress}->{namespace}
)
);
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List ingresses:');
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List ingresses:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
@ -99,7 +105,7 @@ sub disco_show {
$self->{output}->add_disco_entry(
uid => $self->{ingresses}->{$ingress}->{uid},
name => $self->{ingresses}->{$ingress}->{name},
namespace => $self->{ingresses}->{$ingress}->{namespace},
namespace => $self->{ingresses}->{$ingress}->{namespace}
);
}
}

View File

@ -54,9 +54,9 @@ sub manage_selection {
next;
}
$self->{namespaces}->{$namespace->{metadata}->{uid}} = {
$self->{namespaces}->{ $namespace->{metadata}->{uid} } = {
uid => $namespace->{metadata}->{uid},
name => $namespace->{metadata}->{name},
name => $namespace->{metadata}->{name}
}
}
}
@ -66,13 +66,19 @@ sub run {
$self->manage_selection(%options);
foreach my $namespace (sort keys %{$self->{namespaces}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]",
$self->{namespaces}->{$namespace}->{uid},
$self->{namespaces}->{$namespace}->{name}));
$self->{output}->output_add(
long_msg => sprintf(
'[uid: %s] [name: %s]',
$self->{namespaces}->{$namespace}->{uid},
$self->{namespaces}->{$namespace}->{name}
)
);
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List namespaces:');
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List namespaces:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
@ -90,7 +96,7 @@ sub disco_show {
foreach my $namespace (sort keys %{$self->{namespaces}}) {
$self->{output}->add_disco_entry(
uid => $self->{namespaces}->{$namespace}->{uid},
name => $self->{namespaces}->{$namespace}->{name},
name => $self->{namespaces}->{$namespace}->{name}
);
}
}

View File

@ -29,13 +29,12 @@ sub new {
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
%{$self->{modes}} = (
$self->{modes} = {
'cluster-events' => 'cloud::kubernetes::mode::clusterevents',
'cronjob-status' => 'cloud::kubernetes::mode::cronjobstatus',
'daemonset-status' => 'cloud::kubernetes::mode::daemonsetstatus',
'deployment-status' => 'cloud::kubernetes::mode::deploymentstatus',
'discovery-nodes' => 'cloud::kubernetes::mode::discoverynodes',
'discovery' => 'cloud::kubernetes::mode::discovery',
'list-cronjobs' => 'cloud::kubernetes::mode::listcronjobs',
'list-daemonsets' => 'cloud::kubernetes::mode::listdaemonsets',
'list-deployments' => 'cloud::kubernetes::mode::listdeployments',
@ -54,11 +53,11 @@ sub new {
'pod-status' => 'cloud::kubernetes::mode::podstatus',
'replicaset-status' => 'cloud::kubernetes::mode::replicasetstatus',
'replicationcontroller-status' => 'cloud::kubernetes::mode::replicationcontrollerstatus',
'statefulset-status' => 'cloud::kubernetes::mode::statefulsetstatus',
);
'statefulset-status' => 'cloud::kubernetes::mode::statefulsetstatus'
};
$self->{custom_modes}{api} = 'cloud::kubernetes::custom::api';
$self->{custom_modes}{kubectl} = 'cloud::kubernetes::custom::kubectl';
$self->{custom_modes}->{api} = 'cloud::kubernetes::custom::api';
$self->{custom_modes}->{kubectl} = 'cloud::kubernetes::custom::kubectl';
return $self;
}

View File

@ -0,0 +1,18 @@
# Centren Collection modes
Centreon developed a method to scrap monitoring indicators, and Its called **Collection**.
This kind of mode is handy if you are in one of the following situations:
* You can't find an existing plugin to monitor what you want or fulfill your particular need.
* You need to gather data from a in-house, black box, or third-party application and transform it to be easier to analyze.
* Writing (or asking for) a dedicated plugin appears overkill because you simply want to monitor values and apply thresholds over them.
You can find more information on [The Watch](https://thewatch.centreon.com/data-collection-6/centreon-plugins-discover-collection-modes-131), the Centreon User Community.
Currently, Collection modes are available for:
* SNMP (check the [tutorial](https://thewatch.centreon.com/product-how-to-21/snmp-collection-tutorial-132))
* SQL (check the [tutorial](https://thewatch.centreon.com/product-how-to-21/sql-collection-tutorial-134))
Feel free to share here the file that you have developed.
* SNMP
* [moxa-iologik-collection.json](snmp/moxa-iologik-collection.json): to monitor the DI channel status (OID [diStatus](http://www.circitor.fr/Mibs/Html/M/MOXA-IO-E2210-MIB.php#DiEntry) .1.3.6.1.4.1.8691.10.2210.10.1.1.4 of MOXA ioLogik device

View File

@ -0,0 +1,46 @@
{
"mapping": {
"diStatus": {
"0": "Off",
"1": "On"
}
},
"constants": {
"criticalStatus": "Off"
},
"snmp": {
"tables": [
{
"name": "diEntry",
"oid": ".1.3.6.1.4.1.8691.10.2210.10.1.1",
"used_instance": "\\.(\\d+)$",
"entries": [
{ "name": "diIndex", "oid": ".1.3.6.1.4.1.8691.10.2210.10.1.1.1"},
{ "name": "diStatus", "oid": ".1.3.6.1.4.1.8691.10.2210.10.1.1.4" , "map": "diStatus"}
]
}
]
},
"selection_loop": [
{
"name": "DI Channel identification",
"source": "%(snmp.tables.diEntry)",
"expand_tables": {
"diEntry": "%(snmp.tables.diEntry.[%(diEntry.instance)])"
},
"critical": "%(diEntry.diStatus) =~ /%(constants.criticalStatus)/",
"formatting": {
"printf_msg": "Device '%s' status is '%s'",
"printf_var": [
"%(diEntry.diIndex)",
"%(diEntry.diStatus)"
],
"display_ok": true
}
}
],
"formatting": {
"custom_message_global": "All DI Channels are OK",
"separator": "-"
}
}

View File

@ -77,18 +77,18 @@ sub run {
my $new_datas = {};
$new_datas->{last_timestamp} = time();
my $result = $options{sql}->fetchall_arrayref();
$self->{output}->output_add(
severity => 'OK',
short_msg => "All databases hitratio are ok"
);
foreach my $row (@{$result}) {
$new_datas->{$$row[2] . '_blks_hit'} = $row->[0];
$new_datas->{$$row[2] . '_blks_read'} = $row->[1];
$new_datas->{$row->[2] . '_blks_hit'} = $row->[0];
$new_datas->{$row->[2] . '_blks_read'} = $row->[1];
if (defined($self->{option_results}->{exclude}) && $row->[2] !~ /$self->{option_results}->{exclude}/) {
$self->{output}->output_add(long_msg => "Skipping database '" . $$row[2] . '"');
$self->{output}->output_add(long_msg => "Skipping database '" . $row->[2] . '"');
next;
}
@ -96,16 +96,16 @@ sub run {
my $old_blks_read = $self->{statefile_cache}->get(name => $row->[2] . '_blks_read');
next if (!defined($old_blks_hit) || !defined($old_blks_read));
$old_blks_hit = 0 if ($$row[0] <= $old_blks_hit);
$old_blks_read = 0 if ($$row[1] <= $old_blks_read);
$old_blks_hit = 0 if ($row->[0] < $old_blks_hit);
$old_blks_read = 0 if ($row->[1] < $old_blks_read);
$database_check++;
my %prcts = ();
my $total_read_requests = $new_datas->{$$row[2] . '_blks_hit'} - $old_blks_hit;
my $total_read_disk = $new_datas->{$$row[2] . '_blks_read'} - $old_blks_read;
my $total_read_requests = $new_datas->{$row->[2] . '_blks_hit'} - $old_blks_hit;
my $total_read_disk = $new_datas->{$row->[2] . '_blks_read'} - $old_blks_read;
$prcts{hitratio_now} = (($total_read_requests + $total_read_disk) == 0) ? 100 : $total_read_requests * 100 / ($total_read_requests + $total_read_disk);
$prcts{hitratio} = (($new_datas->{$$row[2] . '_blks_hit'} + + $new_datas->{$$row[2] . '_blks_read'}) == 0) ? 100 : $new_datas->{$$row[2] . '_blks_hit'} * 100 / ($new_datas->{$$row[2] . '_blks_hit'} + $new_datas->{$$row[2] . '_blks_read'});
$prcts{hitratio} = (($new_datas->{$row->[2] . '_blks_hit'} + + $new_datas->{$row->[2] . '_blks_read'}) == 0) ? 100 : $new_datas->{$row->[2] . '_blks_hit'} * 100 / ($new_datas->{$$row[2] . '_blks_hit'} + $new_datas->{$row->[2] . '_blks_read'});
my $exit_code = $self->{perfdata}->threshold_check(value => $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now' )}, threshold => [ { label => 'critical', 'exit_litteral' => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
$self->{output}->output_add(
long_msg => sprintf(
@ -113,7 +113,7 @@ sub run {
$row->[2], $prcts{'hitratio' . ((defined($self->{option_results}->{lookback})) ? '' : '_now')}
)
);
if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit_code,
@ -139,7 +139,7 @@ sub run {
min => 0, max => 100
);
}
$self->{statefile_cache}->write(data => $new_datas);
if (!defined($old_timestamp)) {
$self->{output}->output_add(

View File

@ -93,25 +93,24 @@ sub run {
);
my $dbquery = {};
while ((my $row = $options{sql}->fetchrow_hashref())) {
if (defined($self->{option_results}->{exclude}) && $row->{datname} !~ /$self->{option_results}->{exclude}/) {
next;
}
next if (defined($self->{option_results}->{exclude}) && $self->{option_results}->{exclude} ne '' && $row->{datname} =~ /$self->{option_results}->{exclude}/);
if (!defined($dbquery->{$row->{datname}})) {
$dbquery->{ $row->{datname} } = { total => 0, code => {} };
}
next if (!defined($row->{datid}) || $row->{datid} eq ''); # No joint
if (defined($self->{option_results}->{exclude_user}) && $row->{usename} !~ /$self->{option_results}->{exclude_user}/) {
next;
}
next if (defined($self->{option_results}->{exclude_user}) && $self->{option_results}->{exclude_user} ne '' && $row->{usename} =~ /$self->{option_results}->{exclude_user}/);
my $exit_code = $self->{perfdata}->threshold_check(value => $row->{seconds}, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
if (!$self->{output}->is_status(value => $exit_code, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
long_msg => sprintf(
"Request from client '%s' too long (%d sec) on database '%s': %s",
$row->{client_addr}, $row->{seconds}, $row->{datname}, $row->{current_query}
"Request from client '%s' too long (%s sec) on database '%s': %s",
defined($row->{client_addr}) ? $row->{client_addr} : 'unknown',
defined($row->{seconds}) ? $row->{seconds} : '-',
defined($row->{datname}) ? $row->{datname} : '-',
defined($row->{current_query}) ? $row->{current_query} : '-'
)
);
$dbquery->{ $row->{datname} }->{total}++;

View File

@ -67,52 +67,66 @@ my %map_state = (
22 => 'i1OpenFault', 23 => 'i1ShortFault',
24 => 'i2OpenFault', 25 => 'i2ShortFault', 26 => 'fault',
27 => 'warning', 28 => 'critical',
29 => 'selfTest',
29 => 'selfTest'
);
$mapping = {
external_label => {
Label => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.4' } # externalSensorName
},
external => {
Unit => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.16', map => \%map_units }, # externalSensorUnits
Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.17' }, # externalSensorDecimalDigits
LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.31' }, # externalSensorLowerCriticalThreshold
LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.32' }, # externalSensorLowerWarningThreshold
UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.33' }, # externalSensorUpperCriticalThreshold
UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.34' }, # externalSensorUpperWarningThreshold
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.6.3.1.35' }, # externalSensorEnabledThresholds
State => { oid => '.1.3.6.1.4.1.13742.6.5.5.3.1.3', map => \%map_state }, # measurementsExternalSensorState
Value => { oid => '.1.3.6.1.4.1.13742.6.5.5.3.1.4' } # measurementsExternalSensorValue
},
inlet_label => {
Label => { oid => '.1.3.6.1.4.1.13742.6.3.3.3.1.2' }, # inletLabel
Label => { oid => '.1.3.6.1.4.1.13742.6.3.3.3.1.2' } # inletLabel
},
inlet => {
Unit => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.6', map => \%map_units }, # inletSensorUnits
Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.7' }, # inletSensorDecimalDigits
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.25' }, # inletSensorEnabledThresholds
LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.21' }, # inletSensorLowerCriticalThreshold
LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.22' }, # inletSensorLowerWarningThreshold
UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.23' }, # inletSensorUpperCriticalThreshold
UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.24' }, # inletSensorUpperWarningThreshold
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.3.4.1.25' }, # inletSensorEnabledThresholds
State => { oid => '.1.3.6.1.4.1.13742.6.5.2.3.1.3', map => \%map_state }, # measurementsInletSensorState
Value => { oid => '.1.3.6.1.4.1.13742.6.5.2.3.1.4' }, # measurementsInletSensorValue
Value => { oid => '.1.3.6.1.4.1.13742.6.5.2.3.1.4' } # measurementsInletSensorValue
},
outlet_label => {
Label => { oid => '.1.3.6.1.4.1.13742.6.3.5.3.1.2' }, # outletLabel
Label => { oid => '.1.3.6.1.4.1.13742.6.3.5.3.1.2' } # outletLabel
},
outlet => {
Unit => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.6', map => \%map_units }, # outletSensorUnits
Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.7' }, # outletSensorDecimalDigits
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.25' }, # outletSensorEnabledThresholds
LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.21' }, # outletSensorLowerCriticalThreshold
LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.22' }, # outletSensorLowerWarningThreshold
UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.23' }, # outletSensorUpperCriticalThreshold
UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.24' }, # outletSensorUpperWarningThreshold
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.5.4.1.25' }, # outletSensorEnabledThresholds
State => { oid => '.1.3.6.1.4.1.13742.6.5.4.3.1.3', map => \%map_state }, # measurementsOutletSensorState
Value => { oid => '.1.3.6.1.4.1.13742.6.5.4.3.1.4' }, # measurementsOutletSensorValue
Value => { oid => '.1.3.6.1.4.1.13742.6.5.4.3.1.4' } # measurementsOutletSensorValue
},
ocprot_label => {
Label => { oid => '.1.3.6.1.4.1.13742.6.3.4.3.1.2' }, # overCurrentProtectorLabel
Label => { oid => '.1.3.6.1.4.1.13742.6.3.4.3.1.2' } # overCurrentProtectorLabel
},
ocprot => {
Unit => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.6', map => \%map_units }, # overCurrentProtectorSensorUnits
Decimal => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.7' }, # overCurrentProtectorSensorDecimalDigits
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.25' }, # overCurrentProtectorSensorEnabledThresholds
LowerCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.21' }, # overCurrentProtectorSensorLowerCriticalThreshold
LowerWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.22' }, # overCurrentProtectorSensorLowerWarningThreshold
UpperCriticalThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.23' }, # overCurrentProtectorSensorUpperCriticalThreshold
UpperWarningThreshold => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.24' }, # overCurrentProtectorSensorUpperWarningThreshold
EnabledThresholds => { oid => '.1.3.6.1.4.1.13742.6.3.4.4.1.25' }, # overCurrentProtectorSensorEnabledThresholds
State => { oid => '.1.3.6.1.4.1.13742.6.5.3.3.1.3', map => \%map_state }, # measurementsOverCurrentProtectorSensorState
Value => { oid => '.1.3.6.1.4.1.13742.6.5.3.3.1.4' }, # measurementsOverCurrentProtectorSensorValue
},
Value => { oid => '.1.3.6.1.4.1.13742.6.5.3.3.1.4' } # measurementsOverCurrentProtectorSensorValue
}
};
%raritan_type = (
@ -130,7 +144,7 @@ $mapping = {
inletPhaseSyncAngle => 38, inletPhaseSync => 39, operatingState => 40,
activeInlet => 41, illuminance => 42, doorContact => 43,
tamperDetection => 44, motionDetection => 45, i1smpsStatus => 46,
i2smpsStatus => 47, switchStatus => 48,
i2smpsStatus => 47, switchStatus => 48
);
%map_type = (
@ -187,55 +201,55 @@ $thresholds = {
['belowLowerCritical', 'CRITICAL'],
['belowLowerWarning', 'WARNING'],
['aboveUpperWarning', 'WARNING'],
['aboveUpperCritical', 'CRITICAL'],
['aboveUpperCritical', 'CRITICAL']
],
onoff => [
['unavailable', 'UNKNOWN'],
['on', 'OK'],
['off', 'OK'],
['off', 'OK']
],
contact => [
['unavailable', 'UNKNOWN'],
['open', 'OK'],
['closed', 'OK'],
['closed', 'OK']
],
alarm => [
['unavailable', 'UNKNOWN'],
['normal', 'OK'],
['alarmed', 'CRITICAL'],
['selfTest', 'OK'],
['fail', 'CRITICAL'],
['fail', 'CRITICAL']
],
fault => [
['unavailable', 'UNKNOWN'],
['ok', 'OK'],
['fault', 'CRITICAL'],
['fault', 'CRITICAL']
],
powerQuality => [
['unavailable', 'UNKNOWN'],
['normal', 'OK'],
['warning', 'WARNING'],
['critical', 'CRITICAL'],
['critical', 'CRITICAL']
],
inletPhaseSync => [
['unavailable', 'UNKNOWN'],
['inSync', 'OK'],
['outOfSync', 'CRITICAL'],
['outOfSync', 'CRITICAL']
],
operatingState => [
['unavailable', 'UNKNOWN'],
['normal', 'OK'],
['standby', 'OK'],
['off', 'CRITICAL'],
['off', 'CRITICAL']
],
activeInlet => [
['unavailable', 'UNKNOWN'],
['one', 'OK'],
['two', 'OK'],
['none', 'WARNING'],
['none', 'WARNING']
],
motionDetection => [
['unavailable', 'UNKNOWN'],
['unavailable', 'UNKNOWN']
],
switchStatus => [
['unavailable', 'UNKNOWN'],
@ -243,8 +257,8 @@ $thresholds = {
['i1OpenFault', 'WARNING'],
['i1ShortFault', 'WARNING'],
['i2OpenFault', 'WARNING'],
['i2ShortFault', 'WARNING'],
],
['i2ShortFault', 'WARNING']
]
};
1;

View File

@ -42,22 +42,38 @@ sub load {
sub check {
my ($self, %options) = @_;
foreach my $component (sort keys %raritan_type) {
my $long_msg = 0;
next if ($component !~ /$options{component}/);
$self->{components}->{$component} = {name => $component, total => 0, skip => 0};
$self->{components}->{$component} = { name => $component, total => 0, skip => 0 };
next if ($self->check_filter(section => $component));
my $instance_type = $raritan_type{$component};
my $value_type = $map_type{$instance_type};
foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}})) {
next if ($oid !~ /^$mapping->{$options{type}}->{State}->{oid}\.(\d+)\.(\d+)\.$instance_type$/);
my $instance = $1 . '.' . $2 . '.' . $instance_type;
my $result = $self->{snmp}->map_instance(mapping => $mapping->{$options{type}}, results => $self->{results}, instance => $instance);
my $result2 = $self->{snmp}->map_instance(mapping => $mapping->{$options{type} . '_label'}, results => $self->{results}, instance => $1 . '.' . $2);
$instance = defined($result2->{Label}) && $result2->{Label} ne '' ? $result2->{Label} : $1 . '.' . $2;
my ($pduId, $fullSensorId, $result);
if ($options{type} eq 'external') {
next if ($oid !~ /^$mapping->{ $options{type} }->{State}->{oid}\./);
$oid =~ /^$mapping->{ $options{type} }->{State}->{oid}\.(\d+)\.(\d+)$/;
$pduId = $1;
$fullSensorId = $1 . '.' . $2;
next if ($self->{externalSensorType}->{$fullSensorId} != $instance_type);
$result = $self->{snmp}->map_instance(mapping => $mapping->{$options{type}}, results => $self->{results}, instance => $fullSensorId);
} else {
next if ($oid !~ /^$mapping->{ $options{type} }->{State}->{oid}\.(\d+)\.(\d+)\.$instance_type$/);
$pduId = $1;
$fullSensorId = $1 . '.' . $2;
my $fullInstanceId = $1 . '.' . $2 . '.' . $instance_type;
$result = $self->{snmp}->map_instance(mapping => $mapping->{$options{type}}, results => $self->{results}, instance => $fullInstanceId);
}
my $pduName = $self->{pduNames}->{$pduId};
my $result2 = $self->{snmp}->map_instance(mapping => $mapping->{$options{type} . '_label'}, results => $self->{results}, instance => $fullSensorId);
my $instance = defined($result2->{Label}) && $result2->{Label} ne '' ? $result2->{Label} : $fullSensorId;
next if ($self->check_filter(section => $component, instance => $instance));
@ -74,9 +90,15 @@ sub check {
}
$self->{output}->output_add(
long_msg => sprintf(
"'%s' %s state is '%s' [instance: %s, value: %s, unit: %s, label: %s]",
$instance, $component, $result->{State},
$instance, $value, $result->{Unit}->{unit}, $result2->{Label}
"'%s' %s state is '%s' [instance: %s, value: %s, unit: %s, label: %s, pdu: %s]",
$instance,
$component,
$result->{State},
$instance,
$value,
$result->{Unit}->{unit},
$result2->{Label},
$pduName
)
);
my $exit = $self->get_severity(
@ -93,55 +115,56 @@ sub check {
);
}
if ($value =~ /[0-9]/) {
next if ($value =~ /^0$/ && $result->{Unit}->{unit} eq '');
my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => $component, instance => $instance, value => $value);
if ($checked == 0) {
$result->{EnabledThresholds} = oct("0b". unpack('b*', $result->{EnabledThresholds}));
my $warn_th;
$warn_th = ($result->{LowerWarningThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 1)));
if (($result->{EnabledThresholds} & (1 << 2))) {
if (defined($warn_th)) {
$warn_th .= ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal}));
} else {
$warn_th = '~:' . ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal}));
}
}
my $crit_th;
$crit_th = ($result->{LowerCriticalThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 0)));
if (($result->{EnabledThresholds} & (1 << 3))) {
if (defined($crit_th)) {
$crit_th .= ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal}));
} else {
$crit_th = '~:' . ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal}));
}
}
$self->{perfdata}->threshold_validate(label => 'warning-' . $component . '-instance-' . $instance, value => $warn_th);
$self->{perfdata}->threshold_validate(label => 'critical-' . $component . '-instance-' . $instance, value => $crit_th);
$warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $component . '-instance-' . $instance);
$crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $component . '-instance-' . $instance);
}
if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit2,
short_msg => sprintf(
"'%s' %s value is %s %s",
$instance, $component, $value, $result->{Unit}->{unit}
)
);
}
next if ($value !~ /[0-9]/);
next if ($value =~ /^0$/ && $result->{Unit}->{unit} eq '');
my $nunit = (defined($result->{Unit}->{nunit}) ? $result->{Unit}->{nunit} : lc($result->{Unit}->{unit}));
my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => $component, instance => $instance, value => $value);
if ($checked == 0) {
$result->{EnabledThresholds} = oct('0b'. unpack('b*', $result->{EnabledThresholds}));
my $warn_th;
$warn_th = ($result->{LowerWarningThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 1)));
if (($result->{EnabledThresholds} & (1 << 2))) {
if (defined($warn_th)) {
$warn_th .= ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal}));
} else {
$warn_th = '~:' . ($result->{UpperWarningThreshold} * 10 ** -int($result->{Decimal}));
}
}
my $crit_th;
$crit_th = ($result->{LowerCriticalThreshold} * 10 ** -int($result->{Decimal})) . ':' if (($result->{EnabledThresholds} & (1 << 0)));
if (($result->{EnabledThresholds} & (1 << 3))) {
if (defined($crit_th)) {
$crit_th .= ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal}));
} else {
$crit_th = '~:' . ($result->{UpperCriticalThreshold} * 10 ** -int($result->{Decimal}));
}
}
$self->{perfdata}->threshold_validate(label => 'warning-' . $component . '-instance-' . $instance, value => $warn_th);
$self->{perfdata}->threshold_validate(label => 'critical-' . $component . '-instance-' . $instance, value => $crit_th);
$warn = $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $component . '-instance-' . $instance);
$crit = $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $component . '-instance-' . $instance);
}
$self->{output}->perfdata_add(
label => $component, unit => $result->{Unit}->{unit},
nlabel => 'hardware.sensor.' . $options{type} . '.' . lc($component) . '.' . $nunit,
instances => $instance,
value => $value,
warning => $warn,
critical => $crit
if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(
severity => $exit2,
short_msg => sprintf(
"'%s' %s value is %s %s",
$instance, $component, $value, $result->{Unit}->{unit}
)
);
}
my $nunit = (defined($result->{Unit}->{nunit}) ? $result->{Unit}->{nunit} : lc($result->{Unit}->{unit}));
$self->{output}->perfdata_add(
nlabel => 'hardware.sensor.' . $options{type} . '.' . lc($component) . '.' . $nunit,
unit => $result->{Unit}->{unit},
instances => [$pduName, $instance],
value => $value,
warning => $warn,
critical => $crit
);
}
}
}

View File

@ -0,0 +1,147 @@
#
# Copyright 2023 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 hardware::pdu::raritan::snmp::mode::externalsensors;
use base qw(centreon::plugins::templates::hardware);
use strict;
use warnings;
use hardware::pdu::raritan::snmp::mode::components::resources qw($thresholds %raritan_type);
sub set_system {
my ($self, %options) = @_;
$self->{cb_threshold_numeric_check_section_option} = 'check_numeric_section_option';
$self->{cb_hook2} = 'snmp_execute';
$self->{thresholds} = $thresholds;
$self->{components_path} = 'hardware::pdu::raritan::snmp::mode::components';
}
sub snmp_execute {
my ($self, %options) = @_;
$self->{snmp} = $options{snmp};
$self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1);
my $oid_pduName = '.1.3.6.1.4.1.13742.6.3.2.2.1.13';
my $snmp_result = $self->{snmp}->get_table(oid => $oid_pduName, return_type => 1);
$self->{pduNames} = {};
foreach (keys %$snmp_result) {
/\.(\d+)$/;
$self->{pduNames}->{$1} = $snmp_result->{$_};
}
my $oid_externalSensorType = '.1.3.6.1.4.1.13742.6.3.6.3.1.2';
$snmp_result = $self->{snmp}->get_table(oid => $oid_externalSensorType, return_type => 1);
$self->{externalSensorType} = {};
foreach (keys %$snmp_result) {
/\.(\d+\.\d+)$/;
$self->{externalSensorType}->{$1} = $snmp_result->{$_};
}
}
sub check_numeric_section_option {
my ($self, %options) = @_;
if (!defined($raritan_type{$options{section}})) {
$self->{output}->add_option_msg(short_msg => "Wrong $options{option_name} option '" . $options{option_value} . "'.");
$self->{output}->option_exit();
}
}
sub load_components {
my ($self, %options) = @_;
my $mod_name = $self->{components_path} . "::sensor";
centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'."
);
my $func = $mod_name->can('load');
$func->($self, type => 'external');
$self->{loaded} = 1;
}
sub exec_components {
my ($self, %options) = @_;
my $mod_name = $self->{components_path} . "::sensor";
my $func = $mod_name->can('check');
$func->($self, component => $self->{option_results}->{component}, type => 'external');
}
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 external sensors.
=over 8
=item B<--component>
Which component to check (Default: '.*').
=item B<--filter>
Exclude some parts (comma seperated list) (Example: --filter=airPressure --filter=rmsVoltage)
Can also exclude specific instance: --filter=rmsVoltage,I1
=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='powerQuality,CRITICAL,^(?!(normal)$)'
=item B<--warning>
Set warning threshold for temperatures (syntax: type,instance,threshold)
Example: --warning='powerQuality,.*,30'
=item B<--critical>
Set critical threshold for temperatures (syntax: type,instance,threshold)
Example: --critical='powerQuality,.*,40'
=back
=cut

View File

@ -43,6 +43,14 @@ sub snmp_execute {
$self->{snmp} = $options{snmp};
$self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1);
my $oid_pduName = '.1.3.6.1.4.1.13742.6.3.2.2.1.13';
my $snmp_result = $self->{snmp}->get_table(oid => $oid_pduName, return_type => 1);
$self->{pduNames} = {};
foreach (keys %$snmp_result) {
/\.(\d+)$/;
$self->{pduNames}->{$1} = $snmp_result->{$_};
}
}
sub check_numeric_section_option {
@ -58,8 +66,10 @@ sub load_components {
my ($self, %options) = @_;
my $mod_name = $self->{components_path} . "::sensor";
centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'.");
centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'."
);
my $func = $mod_name->can('load');
$func->($self, type => 'inlet');
@ -76,12 +86,10 @@ sub exec_components {
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1);
my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments =>
{
});
$options{options}->add_options(arguments => {});
return $self;
}
@ -128,4 +136,4 @@ Example: --critical='powerQuality,.*,40'
=back
=cut
=cut

View File

@ -43,6 +43,14 @@ sub snmp_execute {
$self->{snmp} = $options{snmp};
$self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1);
my $oid_pduName = '.1.3.6.1.4.1.13742.6.3.2.2.1.13';
my $snmp_result = $self->{snmp}->get_table(oid => $oid_pduName, return_type => 1);
$self->{pduNames} = {};
foreach (keys %$snmp_result) {
/\.(\d+)$/;
$self->{pduNames}->{$1} = $snmp_result->{$_};
}
}
sub check_numeric_section_option {
@ -58,8 +66,10 @@ sub load_components {
my ($self, %options) = @_;
my $mod_name = $self->{components_path} . "::sensor";
centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'.");
centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'."
);
my $func = $mod_name->can('load');
$func->($self, type => 'ocprot');
@ -76,11 +86,10 @@ sub exec_components {
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1);
my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
});
$options{options}->add_options(arguments => {});
return $self;
}

View File

@ -43,6 +43,14 @@ sub snmp_execute {
$self->{snmp} = $options{snmp};
$self->{results} = $self->{snmp}->get_multiple_table(oids => $self->{request}, return_type => 1);
my $oid_pduName = '.1.3.6.1.4.1.13742.6.3.2.2.1.13';
my $snmp_result = $self->{snmp}->get_table(oid => $oid_pduName, return_type => 1);
$self->{pduNames} = {};
foreach (keys %$snmp_result) {
/\.(\d+)$/;
$self->{pduNames}->{$1} = $snmp_result->{$_};
}
}
sub check_numeric_section_option {
@ -58,8 +66,10 @@ sub load_components {
my ($self, %options) = @_;
my $mod_name = $self->{components_path} . "::sensor";
centreon::plugins::misc::mymodule_load(output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'.");
centreon::plugins::misc::mymodule_load(
output => $self->{output}, module => $mod_name,
error_msg => "Cannot load module '$mod_name'."
);
my $func = $mod_name->can('load');
$func->($self, type => 'outlet');
@ -76,11 +86,10 @@ sub exec_components {
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
});
$options{options}->add_options(arguments => {});
return $self;
}

View File

@ -29,12 +29,12 @@ sub new {
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
%{$self->{modes}} = (
$self->{modes} = {
'external-sensors' => 'hardware::pdu::raritan::snmp::mode::externalsensors',
'inlet-sensors' => 'hardware::pdu::raritan::snmp::mode::inletsensors',
'outlet-sensors' => 'hardware::pdu::raritan::snmp::mode::outletsensors',
'ocprot-sensors' => 'hardware::pdu::raritan::snmp::mode::ocprotsensors',
);
'ocprot-sensors' => 'hardware::pdu::raritan::snmp::mode::ocprotsensors'
};
return $self;
}

View File

@ -43,6 +43,7 @@ sub new {
$options{options}->add_options(arguments => {
'api-username:s' => { name => 'api_username' },
'api-password:s' => { name => 'api_password' },
'api-version:s' => { name => 'api_version' },
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' },
'proto:s' => { name => 'proto' },
@ -77,6 +78,7 @@ sub check_options {
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 50;
$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->{api_version} = defined($self->{option_results}->{api_version}) && $self->{option_results}->{api_version} ne '' ? $self->{option_results}->{api_version} : '2';
$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} : '';
@ -138,7 +140,7 @@ sub request {
$self->settings();
my $content = $self->{http}->request(
url_path => $options{endpoint},
url_path => '/rest/vxm/v' . $self->{api_version} . $options{endpoint},
unknown_status => $self->{unknown_http_status},
warning_status => $self->{warning_http_status},
critical_status => $self->{critical_http_status}
@ -195,6 +197,10 @@ API username.
API password.
=item B<--api-version>
API version (Default: 2).
=item B<--timeout>
Set timeout in seconds (Default: 50).

View File

@ -128,7 +128,7 @@ sub new {
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request(endpoint => '/rest/vxm/v1/chassis');
my $results = $options{custom}->request(endpoint => '/chassis');
$self->{global} = { num_chassis => 0, unhealthy => 0 };
$self->{chassis} = {};

View File

@ -55,7 +55,7 @@ sub check_options {
sub discovery_host {
my ($self, %options) = @_;
my $hosts = $options{custom}->request(endpoint => '/rest/vxm/v1/hosts');
my $hosts = $options{custom}->request(endpoint => '/hosts');
my $disco_data = [];
foreach my $host (@$hosts) {

View File

@ -165,7 +165,7 @@ sub new {
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request(endpoint => '/rest/vxm/v1/hosts');
my $results = $options{custom}->request(endpoint => '/hosts');
$self->{global} = { num_hosts => 0, unhealthy => 0 };
$self->{hosts} = {};

View File

@ -209,6 +209,7 @@ sub request_api {
$self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)");
$self->{output}->option_exit();
}
if ($self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) {
$self->{output}->add_option_msg(short_msg => 'api request error: ' . (defined($decoded->{type}) ? $decoded->{type} : 'unknown'));
$self->{output}->option_exit();

View File

@ -39,6 +39,7 @@ sub new {
'discovery' => 'centreon::common::airespace::snmp::mode::discovery',
'hardware' => 'centreon::common::airespace::snmp::mode::hardware',
'interfaces' => 'snmp_standard::mode::interfaces',
'list-aps' => 'centreon::common::airespace::snmp::mode::listaps',
'list-groups' => 'centreon::common::airespace::snmp::mode::listgroups',
'list-interfaces' => 'snmp_standard::mode::listinterfaces',
'list-radius-acc-servers' => 'centreon::common::airespace::snmp::mode::listradiusaccservers',
@ -59,4 +60,4 @@ __END__
Check Cisco Wireless Lan Controller in SNMP.
=cut
=cut

View File

@ -37,10 +37,10 @@ sub set_counters {
key_values => [ { name => 'total' } ],
output_template => 'Total CPU Usage : %.2f %%',
perfdatas => [
{ label => 'cpu_total', value => 'total', template => '%.2f', min => 0, max => 100, unit => '%' },
],
{ label => 'cpu_total', template => '%.2f', min => 0, max => 100, unit => '%' }
]
}
},
}
];
$self->{maps_counters}->{cpu} = [
@ -48,47 +48,47 @@ sub set_counters {
key_values => [ { name => 'extremeCpuMonitorSystemUtilization5secs' }, { name => 'num' }, ],
output_template => '5 seconds : %.2f %%',
perfdatas => [
{ label => 'cpu_5secs', value => 'extremeCpuMonitorSystemUtilization5secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' },
],
{ label => 'cpu_5secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }
]
}
},
{ label => '10secs', set => {
key_values => [ { name => 'extremeCpuMonitorSystemUtilization10secs' }, { name => 'num' }, ],
output_template => '10 seconds : %.2f %%',
perfdatas => [
{ label => 'cpu_10secs', value => 'extremeCpuMonitorSystemUtilization10secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' },
],
{ label => 'cpu_10secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }
]
}
},
{ label => '30secs', set => {
key_values => [ { name => 'extremeCpuMonitorSystemUtilization30secs' }, { name => 'num' }, ],
output_template => '30 seconds : %.2f %%',
perfdatas => [
{ label => 'cpu_30secs', value => 'extremeCpuMonitorSystemUtilization30secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' },
],
{ label => 'cpu_30secs', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }
]
}
},
{ label => '1min', set => {
key_values => [ { name => 'extremeCpuMonitorSystemUtilization1min' }, { name => 'num' }, ],
output_template => '1 minute : %.2f %%',
perfdatas => [
{ label => 'cpu_1min', value => 'extremeCpuMonitorSystemUtilization1min', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' },
],
{ label => 'cpu_1min', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }
]
}
},
{ label => '5min', set => {
key_values => [ { name => 'extremeCpuMonitorSystemUtilization5mins' }, { name => 'num' }, ],
output_template => '5 minutes : %.2f %%',
perfdatas => [
{ label => 'cpu_5min', value => 'extremeCpuMonitorSystemUtilization5mins', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' },
],
{ label => 'cpu_5min', template => '%.2f',
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'num' }
]
}
},
}
];
}
@ -141,11 +141,11 @@ sub manage_selection {
next if ($oid !~ /^$mapping->{extremeCpuMonitorSystemUtilization1min}->{oid}\.(.*)$/);
my $instance = $1;
my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result->{$oid_extremeCpuMonitorSystemEntry}, instance => $instance);
foreach (keys %{$mapping}) {
$result->{$_} = undef if (defined($result->{$_}) && $result->{$_} =~ /n\/a/i);
}
$self->{cpu}->{$instance} = { num => $instance, %$result };
}
@ -170,12 +170,12 @@ Example: --filter-counters='^(1min|5min)$'
=item B<--warning-*>
Threshold warning.
Can be: 'total', '5sec', '10sec', '30sec, '1min', '5min'.
Can be: 'total', '5secs', '10secs', '30secs', '1min', '5min'.
=item B<--critical-*>
Threshold critical.
Can be: 'total', '5sec', '10sec', '30sec, '1min', '5min'.
Can be: 'total', '5secs', '10secs', '30secs', '1min', '5min'.
=back

View File

@ -52,7 +52,7 @@ sub set_counters {
];
$self->{maps_counters}->{memory} = [
{ label => 'usage', display_ok => 0, nlabel => 'memory.usage.bytes', set => {
{ label => 'usage', nlabel => 'memory.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
@ -60,7 +60,7 @@ sub set_counters {
]
}
},
{ label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => {
{ label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', display_ok => 0, set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
@ -68,9 +68,9 @@ sub set_counters {
]
}
},
{ label => 'usage-prct', nlabel => 'memory.usage.percentage', set => {
key_values => [ { name => 'prct_used' }, { name => 'display' } ],
output_template => 'used: %.2f %%',
{ label => 'usage-prct', nlabel => 'memory.usage.percentage', display_ok => 0, set => {
key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1 }
]
@ -113,13 +113,13 @@ sub check_khi {
my $instance = $1;
my $result = $options{snmp}->map_instance(mapping => $mapping_khi, results => $snmp_result, instance => $instance);
my $total = $result->{rcKhiSlotMemUsed} * 1024 + $result->{rcKhiSlotMemFree} * 1024;
my $total = ($result->{rcKhiSlotMemUsed} * 1024) + ($result->{rcKhiSlotMemFree} * 1024);
$self->{memory}->{'slot_' . $1} = {
display => 'slot_' . $1,
used => $result->{rcKhiSlotMemUsed} * 1024,
free => $result->{rcKhiSlotMemFree} * 1024,
prct_used => $result->{rcKhiSlotMemUsed} * 1024 / $total,
prct_free => $result->{rcKhiSlotMemFree} * 1024 / $total,
prct_used => ($result->{rcKhiSlotMemUsed} * 1024 * 100 / $total),
prct_free => ($result->{rcKhiSlotMemFree} * 1024 * 100 / $total),
total => $total
};
}

View File

@ -237,8 +237,7 @@ Example: --filter-counters='tunnels-total'
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'tunnels-total', 'tunnels-traffic-in', 'tunnels-traffic-out',
'tunnel-traffic-in', 'tunnel-traffic-out'.
Can be: 'tunnels-total', 'tunnel-traffic-in', 'tunnel-traffic-out'.
=back

View File

@ -133,7 +133,7 @@ sub get_port {
return $self->{port};
}
sub get_metrics_by_clusters {
sub get_performance_metrics_by_clusters {
my ($self, %options) = @_;
my $clusters = $self->request_api(endpoint => '/api/rest/cluster');
@ -160,6 +160,33 @@ sub get_metrics_by_clusters {
return $results;
}
sub get_space_metrics_by_appliance {
my ($self, %options) = @_;
my $appliances = $self->request_api(endpoint => '/api/rest/appliance');
my $results = {};
foreach (@$appliances) {
my $post_json = JSON::XS->new->utf8->encode(
{
entity => 'space_metrics_by_appliance',
entity_id => $_->{id},
interval => 'Five_Mins'
}
);
my $perfs = $self->request_api(
method => 'POST',
endpoint => '/api/rest/metrics/generate',
headers => ['Content-Type: application/json'],
query_form_post => $post_json
);
$results->{ $_->{id} } = $perfs;
}
return $results;
}
sub request_api {
my ($self, %options) = @_;

View File

@ -170,7 +170,7 @@ sub new {
sub manage_selection {
my ($self, %options) = @_;
my $clusters = $options{custom}->get_metrics_by_clusters();
my $clusters = $options{custom}->get_performance_metrics_by_clusters();
$self->{global} = { detected => 0 };
$self->{clusters} = {};

View File

@ -0,0 +1,136 @@
#
# Copyright 2023 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 storage::dell::powerstore::restapi::mode::memory;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
sub custom_usage_output {
my ($self, %options) = @_;
return sprintf(
'memory total: %s %s used: %s %s (%.2f%%) free: %s %s (%.2f%%)',
$self->{perfdata}->change_bytes(value => $self->{result_values}->{total}),
$self->{perfdata}->change_bytes(value => $self->{result_values}->{used}),
$self->{result_values}->{prct_used},
$self->{perfdata}->change_bytes(value => $self->{result_values}->{free}),
$self->{result_values}->{prct_free}
);
}
sub prefix_appliance_output {
my ($self, %options) = @_;
return "Appliance '" . $options{instance} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'memory', type => 1, cb_prefix_output => 'prefix_appliance_output', message_multiple => 'All appliances memory usage are ok' },
];
$self->{maps_counters}->{memory} = [
{ label => 'usage', nlabel => 'memory.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1 }
]
}
},
{ label => 'usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => {
key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' } ],
closure_custom_output => $self->can('custom_usage_output'),
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-appliance-id:s' => { name => 'filter_appliance_id' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $appliances = $options{custom}->get_space_metrics_by_appliance();
$self->{memory} = {};
foreach my $appliance_id (keys %$appliances) {
next if (defined($self->{option_results}->{filter_appliance_id}) && $self->{option_results}->{filter_appliance_id} ne '' &&
$appliance_id !~ /$self->{option_results}->{filter_appliance_id}/);
my $free = $appliances->{$appliance_id}->{last_physical_total} - $appliances->{$appliance_id}->{last_physical_used};
$self->{memory}->{ $appliance_id } = {
total => $appliances->{$appliance_id}->{last_physical_total},
used => $appliances->{$appliance_id}->{last_physical_used},
free => $free,
prct_used => $appliances->{$appliance_id}->{last_physical_used} * 100 / $appliances->{$appliance_id}->{last_physical_total},
prct_free => $free * 100 / $appliances->{$appliance_id}->{last_physical_total}
};
}
}
1;
__END__
=head1 MODE
Check appliances memory usage.
=over 8
=item B<--filter-appliance-id>
Filter appliance ID.
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'usage' (B), 'usage-free' (B), 'usage-prct' (%).
=back
=cut

View File

@ -32,7 +32,8 @@ sub new {
$self->{modes} = {
'alerts' => 'storage::dell::powerstore::restapi::mode::alerts',
'clusters' => 'storage::dell::powerstore::restapi::mode::clusters',
'hardware' => 'storage::dell::powerstore::restapi::mode::hardware'
'hardware' => 'storage::dell::powerstore::restapi::mode::hardware',
'memory' => 'storage::dell::powerstore::restapi::mode::memory'
};
$self->{custom_modes}->{api} = 'storage::dell::powerstore::restapi::custom::api';

View File

@ -278,14 +278,14 @@ sub manage_selection {
$qtree !~ /$self->{option_results}->{filter_qtree}/);
next if ($volume ne '' && defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '' &&
$volume !~ /$self->{option_results}->{filter_volume}/);
next if ($vserver ne '' &&defined($self->{option_results}->{filter_vserver}) && $self->{option_results}->{filter_vserver} ne '' &&
next if ($vserver ne '' && defined($self->{option_results}->{filter_vserver}) && $self->{option_results}->{filter_vserver} ne '' &&
$vserver !~ /$self->{option_results}->{filter_vserver}/);
my $path = $vserver . $volume . $qtree;
$self->{duplicated}->{$path} = 0 if (!defined($self->{duplicated}->{$path}));
$self->{duplicated}->{$path}++;
$self->{quotas}->{$index} = {
$self->{quotas}->{$path . $index} = {
index => $index,
qtree => $qtree,
volume => $volume,

View File

@ -0,0 +1,221 @@
#
# Copyright 2023 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 storage::wd::nas::snmp::mode::hardware;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
sub prefix_fan_output {
my ($self, %options) = @_;
return "fan '" . $options{instance} . "' ";
}
sub prefix_drive_output {
my ($self, %options) = @_;
return "drive '" . $options{instance} . "' ";
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0 },
{ name => 'fans', type => 1, cb_prefix_output => 'prefix_fan_output', skipped_code => { -10 => 1 } },
{ name => 'drives', type => 1, cb_prefix_output => 'prefix_drive_output', skipped_code => { -10 => 1 } }
];
$self->{maps_counters}->{global} = [
{ label => 'system-temperature', nlabel => 'hardware.temperature.celsius', set => {
key_values => [ { name => 'temperature' } ],
output_template => 'system temperature: %s C',
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
unit => 'C',
instances => 'system',
value => $self->{result_values}->{temperature},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel})
);
}
}
}
];
$self->{maps_counters}->{fans} = [
{ label => 'fan-status', type => 2, critical_default => '%{status} ne "running"', set => {
key_values => [ { name => 'status' } ],
output_template => 'status: %s',
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold_ng
}
}
];
$self->{maps_counters}->{drives} = [
{ label => 'drive-temperature', nlabel => 'hardware.temperature.celsius', set => {
key_values => [ { name => 'temperature' }, { name => 'serial' } ],
output_template => 'temperature: %s C',
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
unit => 'C',
instances => 'drive:' . $self->{result_values}->{serial},
value => $self->{result_values}->{temperature},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel})
);
}
}
}
];
}
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 $nas = {
ex2 => {
system => {
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.7' },
fanStatus => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.8' }
},
drive => {
serial => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.10.1.4' },
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.10.1.5' }
},
driveTable => '.1.3.6.1.4.1.5127.1.1.1.2.1.10.1'
},
ex2ultra => {
system => {
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.7' },
fanStatus => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.8' }
},
drive => {
serial => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.10.1.4' },
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.10.1.5' }
},
driveTable => '.1.3.6.1.4.1.5127.1.1.1.8.1.10.1'
},
pr2100 => {
system => {
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.7' },
fanStatus => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.8' }
},
drive => {
serial => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.10.1.4' },
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.10.1.5' }
},
driveTable => '.1.3.6.1.4.1.5127.1.1.1.9.1.10.1'
},
pr4100 => {
system => {
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.7' },
fanStatus => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.8' }
},
drive => {
serial => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.10.1.4' },
temperature => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.10.1.5' }
},
driveTable => '.1.3.6.1.4.1.5127.1.1.1.10.1.10.1'
}
};
my $snmp_result = $options{snmp}->get_leef(
oids => [ map({ $nas->{$_}->{system}->{temperature}->{oid} . '.0', $nas->{$_}->{system}->{fanStatus}->{oid} . '.0' } keys(%$nas)) ],
nothing_quit => 1
);
$self->{global} = {};
$self->{fans} = {};
$self->{drives} = {};
foreach my $type (keys %$nas) {
next if (!defined($snmp_result->{ $nas->{$type}->{system}->{temperature}->{oid} . '.0' }));
my $result = $options{snmp}->map_instance(mapping => $nas->{$type}->{system}, results => $snmp_result, instance => 0);
$self->{global}->{temperature} = $1 if ($result->{temperature} =~ /Centigrade:(\d+)/i);
while ($result->{fanStatus} =~ /fan(\d+):\s*(\S+)/g) {
$self->{fans}->{$1} = { status => $2 };
}
$snmp_result = $options{snmp}->get_table(
oid => $nas->{$type}->{driveTable},
start => $nas->{$type}->{drive}->{serial}->{oid},
end => $nas->{$type}->{drive}->{temperature}->{oid}
);
foreach (keys %$snmp_result) {
next if (! /^$nas->{$type}->{drive}->{serial}->{oid}\.(\d+)$/);
$result = $options{snmp}->map_instance(mapping => $nas->{$type}->{drive}, results => $snmp_result, instance => $1);
$self->{drives}->{ $result->{serial} } = { serial => $result->{serial} };
$self->{drives}->{ $result->{serial} }->{temperature} = $1 if ($result->{temperature} =~ /Centigrade:(\d+)/i);
}
}
}
1;
__END__
=head1 MODE
Check hardware.
=over 8
=item B<--warning-fan-status>
Set warning threshold for status (Default : '%{status} ne "running"').
Can used special variables like: %{status}
=item B<--critical-fan-status>
Set critical threshold for status.
Can used special variables like: %{status}
=item B<--warning-*> B<--critical-*>
Thresholds. Can be:
'system-temperature', 'drive-temperature'.
=back
=cut

View File

@ -0,0 +1,151 @@
#
# Copyright 2023 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 storage::wd::nas::snmp::mode::listvolumes;
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);
}
sub manage_selection {
my ($self, %options) = @_;
my $nas = {
ex2 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1.2' },
type => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1.3' }
}
},
ex2ultra => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1.2' },
type => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1.3' }
}
},
pr2100 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1.2' },
type => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1.3' }
}
},
pr4100 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1.2' },
type => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1.3' }
}
}
};
my $snmp_result = $options{snmp}->get_multiple_table(
oids => [
{ oid => $nas->{ex2}->{volumeTable} },
{ oid => $nas->{ex2ultra}->{volumeTable} },
{ oid => $nas->{pr2100}->{volumeTable} },
{ oid => $nas->{pr4100}->{volumeTable} }
]
);
my $volumes = {};
foreach my $type (keys %$nas) {
next if (scalar(keys %{$snmp_result->{ $nas->{$type}->{volumeTable} }}) <= 0);
foreach (keys %{$snmp_result->{ $nas->{$type}->{volumeTable} }}) {
next if (! /^$nas->{$type}->{volume}->{name}->{oid}\.(\d+)$/);
$volumes->{$1} = $options{snmp}->map_instance(mapping => $nas->{$type}->{volume}, results => $snmp_result->{ $nas->{$type}->{volumeTable} }, instance => $1);
}
}
return $volumes;
}
sub run {
my ($self, %options) = @_;
my $volumes = $self->manage_selection(%options);
foreach (sort keys %$volumes) {
$self->{output}->output_add(
long_msg => sprintf(
'[name: %s] [type: %s]',
$volumes->{$_}->{name},
$volumes->{$_}->{type}
)
);
}
$self->{output}->output_add(
severity => 'OK',
short_msg => 'List volumes:'
);
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['name', 'type']);
}
sub disco_show {
my ($self, %options) = @_;
my $volumes = $self->manage_selection(%options);
foreach (sort keys %$volumes) {
$self->{output}->add_disco_entry(
%{$volumes->{$_}}
);
}
}
1;
__END__
=head1 MODE
List volumes.
=over 8
=back
=cut

View File

@ -0,0 +1,197 @@
#
# Copyright 2023 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 storage::wd::nas::snmp::mode::volumes;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::misc;
sub custom_space_usage_output {
my ($self, %options) = @_;
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free});
return sprintf(
"space usage total: %s used: %s (%.2f%%) free: %s (%.2f%%)",
$total_size_value . " " . $total_size_unit,
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
$total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free}
);
}
sub prefix_volume_output {
my ($self, %options) = @_;
return sprintf(
"volume '%s' ",
$options{instance_value}->{name}
);
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'volumes', type => 1, cb_prefix_output => 'prefix_volume_output', message_multiple => 'All volumes are ok' }
];
$self->{maps_counters}->{volumes} = [
{ label => 'space-usage', nlabel => 'volume.space.usage.bytes', set => {
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'name' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'name' }
]
}
},
{ label => 'space-usage-free', display_ok => 0, nlabel => 'volume.space.free.bytes', set => {
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'name' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
perfdatas => [
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'name' }
]
}
},
{ label => 'space-usage-prct', display_ok => 0, nlabel => 'volume.space.usage.percentage', set => {
key_values => [ { name => 'prct_used' }, { name => 'used' }, { name => 'free' }, { name => 'prct_free' }, { name => 'total' }, { name => 'name' } ],
closure_custom_output => $self->can('custom_space_usage_output'),
perfdatas => [
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'name' }
]
}
}
];
}
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' }
});
return $self;
}
sub manage_selection {
my ($self, %options) = @_;
my $nas = {
ex2 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1.2' },
total => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1.5' },
free => { oid => '.1.3.6.1.4.1.5127.1.1.1.2.1.9.1.6' }
}
},
ex2ultra => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1.2' },
total => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1.5' },
free => { oid => '.1.3.6.1.4.1.5127.1.1.1.8.1.9.1.6' }
}
},
pr2100 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1.2' },
total => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1.5' },
free => { oid => '.1.3.6.1.4.1.5127.1.1.1.9.1.9.1.6' }
}
},
pr4100 => {
volumeTable => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1',
volume => {
name => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1.2' },
total => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1.5' },
free => { oid => '.1.3.6.1.4.1.5127.1.1.1.10.1.9.1.6' }
}
}
};
my $snmp_result = $options{snmp}->get_multiple_table(
oids => [
{ oid => $nas->{ex2}->{volumeTable} },
{ oid => $nas->{ex2ultra}->{volumeTable} },
{ oid => $nas->{pr2100}->{volumeTable} },
{ oid => $nas->{pr4100}->{volumeTable} }
],
nothing_quit => 1
);
$self->{volumes} = {};
foreach my $type (keys %$nas) {
next if (scalar(keys %{$snmp_result->{ $nas->{$type}->{volumeTable} }}) <= 0);
foreach (keys %{$snmp_result->{ $nas->{$type}->{volumeTable} }}) {
next if (! /^$nas->{$type}->{volume}->{name}->{oid}\.(\d+)$/);
my $result = $options{snmp}->map_instance(mapping => $nas->{$type}->{volume}, results => $snmp_result->{ $nas->{$type}->{volumeTable} }, instance => $1);
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$result->{name} !~ /$self->{option_results}->{filter_name}/);
$result->{total} =~ /^([0-9\.]+)\s*(\S+)/;
$result->{total} = centreon::plugins::misc::convert_bytes(value => $1, unit => $2 . 'B');
$result->{free} =~ /^([0-9\.]+)\s*(\S+)/;
$result->{free} = centreon::plugins::misc::convert_bytes(value => $1, unit => $2 . 'B');
$self->{volumes}->{ $result->{name} } = {
name => $result->{name},
total => $result->{total},
free => $result->{free},
used => $result->{total} - $result->{free},
prct_used => ($result->{total} - $result->{free}) * 100 / $result->{total},
prct_free => $result->{free} * 100 / $result->{total}
};
}
}
}
1;
__END__
=head1 MODE
Check volumes.
=over 8
=item B<--filter-name>
Filter volumes by name (can be a regexp).
=item B<--warning-*> B<--critical-*>
Thresholds.
Can be: 'space-usage-prct', 'space-usage', 'space-usage-free'.
=back
=cut

View File

@ -0,0 +1,49 @@
#
# Copyright 2023 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 storage::wd::nas::snmp::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_snmp);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{modes} = {
'hardware' => 'storage::wd::nas::snmp::mode::hardware',
'list-volumes' => 'storage::wd::nas::snmp::mode::listvolumes',
'volumes' => 'storage::wd::nas::snmp::mode::volumes'
};
return $self;
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check WD (Western Digital) NAS in SNMP.
=cut