(plugin) apps::backup::rubrik::restapi - mode jobs add cache and limit (#4566)

This commit is contained in:
qgarnier 2023-07-19 16:36:08 +02:00 committed by GitHub
parent 7251cad3ab
commit f99ad76662
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 208 additions and 33 deletions

View File

@ -55,13 +55,15 @@ sub new {
'unknown-http-status:s' => { name => 'unknown_http_status' },
'warning-http-status:s' => { name => 'warning_http_status' },
'critical-http-status:s' => { name => 'critical_http_status' },
'token:s' => { name => 'token' }
'token:s' => { name => 'token' },
'cache-use' => { name => 'cache_use' }
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
$self->{output} = $options{output};
$self->{http} = centreon::plugins::http->new(%options);
$self->{http} = centreon::plugins::http->new(%options, default_backend => 'curl');
$self->{cache_connect} = centreon::plugins::statefile->new(%options);
$self->{cache} = centreon::plugins::statefile->new(%options);
return $self;
@ -91,12 +93,14 @@ sub check_options {
$self->{critical_http_status} = (defined($self->{option_results}->{critical_http_status})) ? $self->{option_results}->{critical_http_status} : '';
$self->{token} = $self->{option_results}->{token};
$self->{cache}->check_options(option_results => $self->{option_results});
if (!defined($self->{option_results}->{hostname}) || $self->{option_results}->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.');
$self->{output}->option_exit();
}
if (defined($self->{token})) {
$self->{cache}->check_options(option_results => $self->{option_results});
$self->{cache_connect}->check_options(option_results => $self->{option_results});
return 0 if ($self->{token} ne '');
}
@ -105,7 +109,7 @@ sub check_options {
$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});
$self->{cache_connect}->check_options(option_results => $self->{option_results});
return 0;
}
@ -140,9 +144,9 @@ sub get_connection_info {
sub get_token {
my ($self, %options) = @_;
my $has_cache_file = $self->{cache}->read(statefile => 'rubrik_api_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{api_username}));
my $token = $self->{cache}->get(name => 'token');
my $md5_secret_cache = $self->{cache}->get(name => 'md5_secret');
my $has_cache_file = $self->{cache_connect}->read(statefile => 'rubrik_api_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{api_username}));
my $token = $self->{cache_connect}->get(name => 'token');
my $md5_secret_cache = $self->{cache_connect}->get(name => 'md5_secret');
my $md5_secret = md5_hex($self->{api_username} . $self->{api_password});
if ($has_cache_file == 0 ||
@ -177,7 +181,7 @@ sub get_token {
token => $decoded->{token},
md5_secret => $md5_secret
};
$self->{cache}->write(data => $datas);
$self->{cache_connect}->write(data => $datas);
}
return $token;
@ -186,9 +190,9 @@ sub get_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 $has_cache_file = $self->{cache_connect}->read(statefile => 'rubrik_api_' . md5_hex($self->{option_results}->{hostname} . '_' . $self->{service_account}));
my $token = $self->{cache_connect}->get(name => 'token');
my $md5_secret_cache = $self->{cache_connect}->get(name => 'md5_secret');
my $md5_secret = md5_hex($self->{service_account} . $self->{secret});
if ($has_cache_file == 0 ||
@ -235,7 +239,7 @@ sub get_service_account_token {
token => $decoded->{token},
md5_secret => $md5_secret
};
$self->{cache}->write(data => $datas);
$self->{cache_connect}->write(data => $datas);
}
return $token;
@ -245,7 +249,7 @@ sub clean_token {
my ($self, %options) = @_;
my $datas = { updated => time() };
$self->{cache}->write(data => $datas);
$self->{cache_connect}->write(data => $datas);
}
sub credentials {
@ -374,6 +378,54 @@ sub request_api {
return $result;
}
sub write_cache_file {
my ($self, %options) = @_;
$self->{cache}->read(statefile => 'cache_rubrik_' . $options{statefile} . '_' . md5_hex($self->get_connection_info()));
$self->{cache}->write(data => {
update_time => time(),
response => $options{response}
});
}
sub get_cache_file_response {
my ($self, %options) = @_;
$self->{cache}->read(statefile => 'cache_rubrik_' . $options{statefile} . '_' . md5_hex($self->get_connection_info()));
my $response = $self->{cache}->get(name => 'response');
if (!defined($response)) {
$self->{output}->add_option_msg(short_msg => 'Cache file missing');
$self->{output}->option_exit();
}
return $response;
}
sub cache_jobs_monitoring {
my ($self, %options) = @_;
my $datas = $self->get_jobs_monitoring(disable_cache => 1, limit => $options{limit});
$self->write_cache_file(
statefile => 'jobs_monitoring',
response => $datas
);
return $datas;
}
sub get_jobs_monitoring {
my ($self, %options) = @_;
return $self->get_cache_file_response(statefile => 'jobs_monitoring')
if (defined($self->{option_results}->{cache_use}) && !defined($options{disable_cache}));
return $self->request_api(
endpoint => '/api/v1/job_monitoring',
label => 'jobMonitoringInfoList',
get_param => ['limit=' . $options{limit}]
);
}
1;
__END__
@ -428,6 +480,10 @@ Use token authentication. If option is empty, token is created.
Set timeout in seconds (Default: 30).
=item B<--cache-use>
Use the cache file (created with cache mode).
=back
=head1 DESCRIPTION

View File

@ -0,0 +1,76 @@
#
# 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::backup::rubrik::restapi::mode::cache;
use base qw(centreon::plugins::templates::counter);
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 => {
'limit:s' => { name => 'limit' }
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
if (!defined($self->{option_results}->{limit}) || $self->{option_results}->{limit} !~ /\d+/) {
$self->{option_results}->{limit} = 500;
}
}
sub manage_selection {
my ($self, %options) = @_;
$options{custom}->cache_jobs_monitoring(limit => $self->{option_results}->{limit});
$self->{output}->output_add(
severity => 'OK',
short_msg => 'Cache files created successfully'
);
}
1;
__END__
=head1 MODE
Create cache files (job mode could use it with --cache-use option).
=over 8
=item B<--limit>
Define the number of entries to retrieve for the pagination (default: 500).
=back
=cut

View File

@ -39,7 +39,7 @@ sub custom_last_exec_perfdata {
$self->{output}->perfdata_add(
nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} },
instances => $self->{result_values}->{name},
instances => [$self->{result_values}->{jobName}, $self->{result_values}->{jobType}],
unit => $self->{instance_mode}->{option_results}->{unit},
value => $self->{result_values}->{lastExecSeconds} >= 0 ? floor($self->{result_values}->{lastExecSeconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }) : $self->{result_values}->{lastExecSeconds},
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
@ -66,7 +66,7 @@ sub custom_duration_perfdata {
$self->{output}->perfdata_add(
nlabel => $self->{nlabel} . '.' . $unitdiv_long->{ $self->{instance_mode}->{option_results}->{unit} },
instances => $self->{result_values}->{name},
instances => [$self->{result_values}->{jobName}, $self->{result_values}->{jobType}],
unit => $self->{instance_mode}->{option_results}->{unit},
value => floor($self->{result_values}->{durationSeconds} / $unitdiv->{ $self->{instance_mode}->{option_results}->{unit} }),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
@ -151,18 +151,29 @@ sub set_counters {
$self->{maps_counters}->{failed} = [
{ label => 'job-executions-failed-prct', nlabel => 'job.executions.failed.percentage', set => {
key_values => [ { name => 'failedPrct' } ],
key_values => [ { name => 'failedPrct' }, { name => 'jobName' }, { name => 'jobType' } ],
output_template => 'number of failed executions: %.2f %%',
perfdatas => [
{ template => '%.2f', unit => '%', min => 0, max => 100, label_extra_instance => 1 }
]
closure_custom_perfdata => sub {
my ($self, %options) = @_;
$self->{output}->perfdata_add(
nlabel => $self->{nlabel},
unit => '%',
instances => [$self->{result_values}->{jobName}, $self->{result_values}->{jobType}],
value => sprintf('%.2f', $self->{result_values}->{failedPrct}),
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
);
}
}
}
];
$self->{maps_counters}->{timers} = [
{ label => 'job-execution-last', nlabel => 'job.execution.last', set => {
key_values => [ { name => 'lastExecSeconds' }, { name => 'lastExecHuman' }, { name => 'name' } ],
key_values => [ { name => 'lastExecSeconds' }, { name => 'lastExecHuman' }, { name => 'jobName' }, { name => 'jobType' } ],
output_template => 'last execution %s',
output_use => 'lastExecHuman',
closure_custom_perfdata => $self->can('custom_last_exec_perfdata'),
@ -170,7 +181,7 @@ sub set_counters {
}
},
{ label => 'job-running-duration', nlabel => 'job.running.duration', set => {
key_values => [ { name => 'durationSeconds' }, { name => 'durationHuman' }, { name => 'name' } ],
key_values => [ { name => 'durationSeconds' }, { name => 'durationHuman' }, { name => 'jobName' }, { name => 'jobType' } ],
output_template => 'running duration %s',
output_use => 'durationHuman',
closure_custom_perfdata => $self->can('custom_duration_perfdata'),
@ -206,7 +217,8 @@ sub new {
'filter-job-name:s' => { name => 'filter_job_name' },
'filter-job-type:s' => { name => 'filter_job_type' },
'filter-location-name:s' => { name => 'filter_location_name' },
'unit:s' => { name => 'unit', default => 's' }
'unit:s' => { name => 'unit', default => 's' },
'limit:s' => { name => 'limit' }
});
$self->{cache_exec} = centreon::plugins::statefile->new(%options);
@ -222,19 +234,21 @@ sub check_options {
$self->{option_results}->{unit} = 's';
}
if (!defined($self->{option_results}->{limit}) || $self->{option_results}->{limit} !~ /\d+/) {
$self->{option_results}->{limit} = 500;
}
$self->{cache_exec}->check_options(option_results => $self->{option_results}, default_format => 'json');
}
sub manage_selection {
my ($self, %options) = @_;
my $jobs_exec = $options{custom}->request_api(
endpoint => '/api/v1/job_monitoring',
label => 'jobMonitoringInfoList'
);
my $jobs_exec = $options{custom}->get_jobs_monitoring(limit => $self->{option_results}->{limit});
$self->{cache_exec}->read(statefile => 'rubrik_' . $self->{mode} . '_' .
$self->{cache_exec}->read(statefile => 'rubrik_' . $self->{mode} . '_' .
Digest::MD5::md5_hex(
$options{custom}->get_connection_info() . '_' .
(defined($self->{option_results}->{filter_job_id}) ? $self->{option_results}->{filter_job_id} : '') . '_' .
(defined($self->{option_results}->{filter_job_name}) ? $self->{option_results}->{filter_job_name} : '') . '_' .
(defined($self->{option_results}->{filter_job_type}) ? $self->{option_results}->{filter_job_type} : '')
@ -256,10 +270,12 @@ sub manage_selection {
next if (defined($self->{option_results}->{filter_location_name}) && $self->{option_results}->{filter_location_name} ne '' &&
$job_exec->{locationName} !~ /$self->{option_results}->{filter_location_name}/);
$job_exec->{jobType} = lc($job_exec->{jobType});
if (!defined($self->{jobs}->{ $job_exec->{objectId} })) {
$self->{jobs}->{ $job_exec->{objectId} } = {
name => $job_exec->{objectName},
jobType => lc($job_exec->{jobType}),
jobType => $job_exec->{jobType},
timers => {},
executions => {}
};
@ -284,6 +300,8 @@ sub manage_selection {
}
$self->{jobs}->{ $job_exec->{objectId} }->{failed} = {
jobName => $job_exec->{objectName},
jobType => $job_exec->{jobType},
failedPrct => $total > 0 ? $failed * 100 / $total : 0
};
@ -296,16 +314,21 @@ sub manage_selection {
$last_exec->{startTime} =~ /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)/;
my $dt = DateTime->new(year => $1, month => $2, day => $3, hour => $4, minute => $5, second => $6);
$last_exec_times->{ $job_exec->{objectId} } = $dt->epoch();
$last_exec_times->{ $job_exec->{objectId} } = {
jobName => $job_exec->{objectName},
jobType => $job_exec->{jobType},
epoch => $dt->epoch()
};
}
$self->{jobs}->{ $job_exec->{objectId} }->{timers} = {
name => $job_exec->{objectName},
lastExecSeconds => defined($last_exec_times->{ $job_exec->{objectId} }) ? $ctime - $last_exec_times->{ $job_exec->{objectId} } : -1,
jobName => $job_exec->{objectName},
jobType => $job_exec->{jobType},
lastExecSeconds => defined($last_exec_times->{ $job_exec->{objectId} }) ? $ctime - $last_exec_times->{ $job_exec->{objectId} }->{epoch} : -1,
lastExecHuman => 'never'
};
if (defined($last_exec_times->{ $job_exec->{objectId} })) {
$self->{jobs}->{ $job_exec->{objectId} }->{timers}->{lastExecHuman} = centreon::plugins::misc::change_seconds(value => $ctime - $last_exec_times->{ $job_exec->{objectId} });
$self->{jobs}->{ $job_exec->{objectId} }->{timers}->{lastExecHuman} = centreon::plugins::misc::change_seconds(value => $ctime - $last_exec_times->{ $job_exec->{objectId} }->{epoch});
}
if (defined($older_running_exec)) {
@ -317,6 +340,21 @@ sub manage_selection {
}
}
foreach my $objectId (keys %$last_exec_times) {
next if (defined($self->{jobs}->{$objectId}));
$self->{jobs}->{$objectId} = {
name => $last_exec_times->{$objectId}->{jobName},
jobType => $last_exec_times->{$objectId}->{jobType},
timers => {
jobName => $last_exec_times->{$objectId}->{jobName},
jobType => $last_exec_times->{$objectId}->{jobType},
lastExecSeconds => $ctime - $last_exec_times->{$objectId}->{epoch},
lastExecHuman => centreon::plugins::misc::change_seconds(value => $ctime - $last_exec_times->{$objectId}->{epoch})
}
};
}
$self->{cache_exec}->write(data => {
jobs => $last_exec_times
});
@ -353,6 +391,10 @@ Filter jobs by location name.
Select the unit for last execution time threshold. May be 's' for seconds, 'm' for minutes,
'h' for hours, 'd' for days, 'w' for weeks. Default is seconds.
=item B<--limit>
Define the number of entries to retrieve for the pagination (default: 500).
=item B<--unknown-execution-status>
Set unknown threshold for last job execution status.
@ -365,7 +407,7 @@ You can use the following variables: %{status}, %{jobName}
=item B<--critical-execution-status>
Set critical threshold for last job execution status (Default: %{status} =~ /Failure/i).
Set critical threshold for last job execution status (default: %{status} =~ /Failure/i).
You can use the following variables: %{status}, %{jobName}
=item B<--warning-*> B<--critical-*>

View File

@ -30,6 +30,7 @@ sub new {
bless $self, $class;
$self->{modes} = {
'cache' => 'apps::backup::rubrik::restapi::mode::cache',
'cluster' => 'apps::backup::rubrik::restapi::mode::cluster',
'compliance' => 'apps::backup::rubrik::restapi::mode::compliance',
'disks' => 'apps::backup::rubrik::restapi::mode::disks',