mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-30 17:15:11 +02:00
CTOR-880: New Pack(storage::hp::alletra::restapi) (#5653)
Co-authored-by: Roman Morandell <46994680+rmorandell-pgum@users.noreply.github.com>
This commit is contained in:
parent
e04e5519b5
commit
4565304d18
@ -0,0 +1,4 @@
|
||||
{
|
||||
"dependencies": [
|
||||
]
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"pkg_name": "centreon-plugin-Hardware-Storage-Hpe-Alletra-Restapi",
|
||||
"pkg_summary": "Centreon Plugin",
|
||||
"plugin_name": "centreon_hpe_alletra_restapi.pl",
|
||||
"files": [
|
||||
"centreon/plugins/script_custom.pm",
|
||||
"storage/hp/alletra/restapi/"
|
||||
]
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"dependencies": [
|
||||
]
|
||||
}
|
267
src/storage/hp/alletra/restapi/custom/api.pm
Normal file
267
src/storage/hp/alletra/restapi/custom/api.pm
Normal file
@ -0,0 +1,267 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::custom::api;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::http;
|
||||
use centreon::plugins::statefile;
|
||||
use JSON::XS;
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
if (!defined($options{output})) {
|
||||
print "Class Custom: Need to specify 'output' argument.\n";
|
||||
exit 3;
|
||||
}
|
||||
if (!defined($options{options})) {
|
||||
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
|
||||
$options{output}->option_exit();
|
||||
}
|
||||
|
||||
if (!defined($options{noptions})) {
|
||||
$options{options}->add_options(arguments => {
|
||||
'api-username:s' =>
|
||||
{ name => 'api_username' },
|
||||
'api-password:s' =>
|
||||
{ name => 'api_password' },
|
||||
'hostname:s' =>
|
||||
{ name => 'hostname' },
|
||||
'port:s' =>
|
||||
{ name => 'port', default => 443 },
|
||||
'proto:s' =>
|
||||
{ name => 'proto', default => 'https' },
|
||||
'timeout:s' =>
|
||||
{ name => 'timeout', default => 30 },
|
||||
'unknown-http-status:s' =>
|
||||
{ name => 'unknown_http_status', default => '%{http_code} < 200 or %{http_code} >= 300' },
|
||||
'warning-http-status:s' =>
|
||||
{ name => 'warning_http_status' },
|
||||
'critical-http-status:s' =>
|
||||
{ name => 'critical_http_status' }
|
||||
});
|
||||
}
|
||||
$options{options}->add_help(package => __PACKAGE__, sections => 'HPE Alletra API OPTIONS', once => 1);
|
||||
|
||||
$self->{output} = $options{output};
|
||||
$self->{http} = centreon::plugins::http->new(%options, default_backend => 'curl');
|
||||
$self->{cache} = centreon::plugins::statefile->new(%options);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub set_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{option_results} = $options{option_results};
|
||||
}
|
||||
|
||||
sub set_defaults {}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
if (centreon::plugins::misc::is_empty($self->{option_results}->{hostname})) {
|
||||
$self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.');
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (centreon::plugins::misc::is_empty($self->{option_results}->{api_username})) {
|
||||
$self->{output}->add_option_msg(short_msg => 'Need to specify --api-username option.');
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (centreon::plugins::misc::is_empty($self->{option_results}->{api_password})) {
|
||||
$self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.');
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
$self->{http}->set_options(%{$self->{option_results}});
|
||||
$self->{http}->add_header(key => 'Accept', value => 'application/json');
|
||||
|
||||
$self->{cache}->check_options(option_results => $self->{option_results});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub get_connection_info {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return $self->{option_results}->{hostname} . ':' . $self->{option_results}->{port};
|
||||
}
|
||||
|
||||
sub get_token {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{cache}->read(statefile =>
|
||||
'hpe_alletra_' . md5_hex($self->get_connection_info() . '_' . $self->{option_results}->{api_username}));
|
||||
my $auth_key = $self->{cache}->get(name => 'auth_key');
|
||||
|
||||
if (! $auth_key) {
|
||||
my $json_request = {
|
||||
user => $self->{option_results}->{api_username},
|
||||
password => $self->{option_results}->{api_password}
|
||||
};
|
||||
my $encoded;
|
||||
eval {
|
||||
$encoded = encode_json($json_request);
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg =>
|
||||
'An error occurred while encoding the credentials to a JSON string.');
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
my $content = $self->{http}->request(
|
||||
method => 'POST',
|
||||
url_path => '/api/v1/credentials',
|
||||
query_form_post => $encoded,
|
||||
unknown_status => $self->{option_results}->{unknown_http_status},
|
||||
warning_status => $self->{option_results}->{warning_http_status},
|
||||
critical_status => $self->{option_results}->{critical_http_status},
|
||||
header => [ 'Content-Type: application/json' ]
|
||||
);
|
||||
|
||||
my $decoded;
|
||||
eval {
|
||||
$decoded = JSON::XS->new->utf8->decode($content);
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg => "An error occurred while decoding the response ('$content').");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$auth_key = $decoded->{key};
|
||||
my $data = {
|
||||
updated => time(),
|
||||
auth_key => $auth_key
|
||||
};
|
||||
$self->{cache}->write(data => $data);
|
||||
}
|
||||
|
||||
return $auth_key;
|
||||
}
|
||||
|
||||
sub clean_token {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $data = { updated => time() };
|
||||
$self->{cache}->write(data => $data);
|
||||
}
|
||||
|
||||
sub request_api {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $get_param = [];
|
||||
if (defined($options{get_param})) {
|
||||
$get_param = $options{get_param};
|
||||
}
|
||||
|
||||
my $token = $self->get_token();
|
||||
my ($content) = $self->{http}->request(
|
||||
url_path => $options{endpoint},
|
||||
get_param => $get_param,
|
||||
header => [ 'X-HP3PAR-WSAPI-SessionKey: ' . $token ],
|
||||
unknown_status => '',
|
||||
warning_status => '',
|
||||
critical_status => ''
|
||||
);
|
||||
|
||||
# Maybe token is invalid. so we retry
|
||||
if (!defined($self->{token}) && $self->{http}->get_code() < 200 || $self->{http}->get_code() >= 300) {
|
||||
$self->clean_token();
|
||||
$token = $self->get_token();
|
||||
|
||||
$content = $self->{http}->request(
|
||||
url_path => $options{endpoint},
|
||||
get_param => $get_param,
|
||||
header => [ 'X-HP3PAR-WSAPI-SessionKey: ' . $token ],
|
||||
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->allow_nonref(1)->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
|
||||
|
||||
HPE Alletra REST API
|
||||
|
||||
=head1 HPE Alletra API OPTIONS
|
||||
|
||||
HPE Alletra REST API
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--hostname>
|
||||
|
||||
Address of the server that hosts the API.
|
||||
|
||||
=item B<--port>
|
||||
|
||||
Define the TCP port to use to reach the API (default: 443).
|
||||
|
||||
=item B<--proto>
|
||||
|
||||
Define the protocol to reach the API (default: 'https').
|
||||
|
||||
=item B<--api-username>
|
||||
|
||||
Define the username for authentication.
|
||||
|
||||
=item B<--api-password>
|
||||
|
||||
Define the password associated with the username.
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Define the timeout in seconds for HTTP requests (default: 30).
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<custom>.
|
||||
|
||||
=cut
|
494
src/storage/hp/alletra/restapi/mode/capacity.pm
Normal file
494
src/storage/hp/alletra/restapi/mode/capacity.pm
Normal file
@ -0,0 +1,494 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::capacity;
|
||||
|
||||
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});
|
||||
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 storage_long_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return sprintf(
|
||||
"checking storage '%s'",
|
||||
$options{instance_value}->{type}
|
||||
);
|
||||
}
|
||||
|
||||
sub prefix_storage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return sprintf(
|
||||
"storage '%s' ",
|
||||
$options{instance_value}->{type}
|
||||
);
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{
|
||||
name => 'storages',
|
||||
type => 3,
|
||||
cb_prefix_output => 'prefix_storage_output',
|
||||
cb_long_output => 'storage_long_output',
|
||||
indent_long_output => ' ',
|
||||
message_multiple => 'All storage capacities are ok',
|
||||
group =>
|
||||
[
|
||||
{ name => 'space', type => 0 },
|
||||
{ name => 'provisioning', type => 0 },
|
||||
{ name => 'efficiency', type => 0, skipped_code => { -10 => 1 } }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{space} = [
|
||||
{
|
||||
label => 'space-usage', nlabel => 'storage.space.usage.bytes', set => {
|
||||
key_values =>
|
||||
[
|
||||
{ name => 'used' },
|
||||
{ name => 'free' },
|
||||
{ name => 'prct_used' },
|
||||
{ name => 'prct_free' },
|
||||
{ name => 'total' }
|
||||
],
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'space-usage-free', nlabel => 'storage.space.free.bytes', display_ok => 0, set => {
|
||||
key_values =>
|
||||
[
|
||||
{ name => 'free' },
|
||||
{ name => 'used' },
|
||||
{ name => 'prct_used' },
|
||||
{ name => 'prct_free' },
|
||||
{ name => 'total' }
|
||||
],
|
||||
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
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'space-usage-prct', nlabel => 'storage.space.usage.percentage', display_ok => 0, set => {
|
||||
key_values =>
|
||||
[
|
||||
{ name => 'prct_used' },
|
||||
{ name => 'used' },
|
||||
{ name => 'free' },
|
||||
{ name => 'prct_free' },
|
||||
{ name => 'total' }
|
||||
],
|
||||
closure_custom_output => $self->can('custom_space_usage_output'),
|
||||
perfdatas =>
|
||||
[
|
||||
{
|
||||
template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'space-unavailable', nlabel => 'storage.space.unavailable.bytes', set => {
|
||||
key_values =>
|
||||
[
|
||||
{ name => 'unavailable' }
|
||||
],
|
||||
output_template => 'unavailable: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'space-failed', nlabel => 'storage.space.failed.bytes', set => {
|
||||
key_values => [ { name => 'failed' } ],
|
||||
output_template => 'failed: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{provisioning} = [
|
||||
{
|
||||
label => 'provisioning-virtual-size', nlabel => 'storage.provisioning.virtualsize.bytes', set => {
|
||||
key_values => [ { name => 'virtual_size' } ],
|
||||
output_template => 'provisioning virtual size: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'provisioning-used', nlabel => 'storage.provisioning.used.bytes', set => {
|
||||
key_values => [ { name => 'used' } ],
|
||||
output_template => 'provisioning used: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'provisioning-allocated', nlabel => 'storage.provisioning.allocated.bytes', set => {
|
||||
key_values => [ { name => 'allocated' } ],
|
||||
output_template => 'provisioning allocated: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'provisioning-free', nlabel => 'storage.provisioning.free.bytes', set => {
|
||||
key_values => [ { name => 'free' } ],
|
||||
output_template => 'provisioning free: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%s', unit => 'B', min => 0, label_extra_instance => 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{efficiency} = [
|
||||
{
|
||||
label => 'compaction', nlabel => 'storage.space.compaction.ratio.count', set => {
|
||||
key_values => [ { name => 'compaction' } ],
|
||||
output_template => 'compaction: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, label_extra_instance => 1 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'deduplication', nlabel => 'storage.space.deduplication.ratio.count', set => {
|
||||
key_values => [ { name => 'deduplication' } ],
|
||||
output_template => 'deduplication: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, label_extra_instance => 1 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'compression', nlabel => 'storage.space.compression.ratio.count', set => {
|
||||
key_values => [ { name => 'compression' } ],
|
||||
output_template => 'compression: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, label_extra_instance => 1 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'data-reduction', nlabel => 'storage.space.data_reduction.ratio.count', set => {
|
||||
key_values => [ { name => 'data_reduction' } ],
|
||||
output_template => 'data reduction: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, label_extra_instance => 1 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'overprovisioning', nlabel => 'storage.space.overprovisioning.ratio.count', set => {
|
||||
key_values => [ { name => 'overprovisioning' } ],
|
||||
output_template => 'overprovisioning: %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-type:s' => { name => 'filter_type' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(
|
||||
endpoint => '/api/v1/capacity'
|
||||
);
|
||||
|
||||
for my $type (keys %{$response}) {
|
||||
next if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne ''
|
||||
&& $type !~ /$self->{option_results}->{filter_type}/);
|
||||
|
||||
my $total = $response->{$type}->{totalMiB} * 1024 * 1024;
|
||||
my $free = $response->{$type}->{freeMiB} * 1024 * 1024;
|
||||
my $unavailable = $response->{$type}->{unavailableCapacityMiB} * 1024 * 1024;
|
||||
my $failed = $response->{$type}->{failedCapacityMiB} * 1024 * 1024;
|
||||
|
||||
$self->{storages}->{$type} = {
|
||||
type => $type,
|
||||
space => {
|
||||
total => $total,
|
||||
free => $free,
|
||||
used => $total - $free,
|
||||
unavailable => $unavailable,
|
||||
prct_used => $total > 0 ? ($total - $free) * 100 / $total : 0,
|
||||
prct_free => $total > 0 ? $free * 100 / $total : 0,
|
||||
failed => $failed
|
||||
},
|
||||
provisioning => {
|
||||
virtual_size => $response->{$type}->{overProvisionedVirtualSizeMiB} * 1024 * 1024,
|
||||
used => $response->{$type}->{overProvisionedUsedMiB} * 1024 * 1024,
|
||||
allocated => $response->{$type}->{overProvisionedAllocatedMiB} * 1024 * 1024,
|
||||
free => $response->{$type}->{overProvisionedFreeMiB} * 1024 * 1024,
|
||||
}
|
||||
};
|
||||
|
||||
my $shortcut = $response->{$type}->{allocated}->{volumes}->{capacityEfficiency};
|
||||
|
||||
$self->{storages}->{$type}->{efficiency}->{compaction} = $shortcut->{compaction} if defined($shortcut->{compaction});
|
||||
$self->{storages}->{$type}->{efficiency}->{deduplication} = $shortcut->{deduplication} if defined($shortcut->{deduplication});
|
||||
$self->{storages}->{$type}->{efficiency}->{compression} = $shortcut->{compression} if defined($shortcut->{compression});
|
||||
$self->{storages}->{$type}->{efficiency}->{data_reduction} = $shortcut->{dataReduction} if defined($shortcut->{dataReduction});
|
||||
$self->{storages}->{$type}->{efficiency}->{overprovisioning} = $shortcut->{overProvisioning} if defined($shortcut->{overProvisioning});
|
||||
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{storages}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Couldn't get capacity information");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check storage capacity per storage type.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : compaction deduplication compression data-reduction overprovisioning provisioning-virtual-size provisioning-used provisioning-allocated provisioning-free space-usage space-usage-free space-usage-prct space-unavailable space-failed
|
||||
Example: --filter-counters='^compaction$'
|
||||
|
||||
=item B<--filter-type>
|
||||
|
||||
Filter storage by type (regular expression).
|
||||
The known types are: C<allCapacity>, C<FCCapacity>, C<SSDCapacity> and C<NLCapacity>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for space oriented metrics
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-space-failed>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-space-failed>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-space-unavailable>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-space-unavailable>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-space-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-space-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-space-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-space-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-space-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=item B<--critical-space-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for provisioning metrics
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-provisioning-allocated>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-provisioning-allocated>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-provisioning-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-provisioning-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-provisioning-used>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-provisioning-used>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-provisioning-virtual-size>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-provisioning-virtual-size>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for storage optimization metrics
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-compaction>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-compaction>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-compression>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-compression>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-data-reduction>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-data-reduction>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-deduplication>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-deduplication>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-overprovisioning>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-overprovisioning>
|
||||
|
||||
Threshold.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
342
src/storage/hp/alletra/restapi/mode/diskstatus.pm
Normal file
342
src/storage/hp/alletra/restapi/mode/diskstatus.pm
Normal file
@ -0,0 +1,342 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::diskstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %map_state = (
|
||||
1 => 'normal',
|
||||
2 => 'degraded',
|
||||
3 => 'new',
|
||||
4 => 'failed',
|
||||
99 => 'unknown'
|
||||
);
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return sprintf(
|
||||
"Disk #%s (%s/%s, serial: %s) located %s is %s",
|
||||
$self->{result_values}->{id},
|
||||
$self->{result_values}->{manufacturer},
|
||||
$self->{result_values}->{model},
|
||||
$self->{result_values}->{serial},
|
||||
$self->{result_values}->{position},
|
||||
$self->{result_values}->{status}
|
||||
);
|
||||
}
|
||||
|
||||
sub prefix_global_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return 'Disks ';
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 },
|
||||
{ name => 'disks', type => 1, message_multiple => 'All disks are ok' }
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'disks-total', nlabel => 'disks.total.count', set => {
|
||||
key_values => [ { name => 'total' } ],
|
||||
output_template => 'total: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'disks-normal', nlabel => 'disks.normal.count', set => {
|
||||
key_values => [ { name => 'normal' }, { name => 'total' } ],
|
||||
output_template => 'normal: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'disks-degraded', nlabel => 'disks.degraded.count', set => {
|
||||
key_values => [ { name => 'degraded' }, { name => 'total' } ],
|
||||
output_template => 'degraded: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'disks-new', nlabel => 'disks.new.count', set => {
|
||||
key_values => [ { name => 'new' }, { name => 'total' } ],
|
||||
output_template => 'new: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'disks-failed', nlabel => 'disks.failed.count', set => {
|
||||
key_values => [ { name => 'failed' }, { name => 'total' } ],
|
||||
output_template => 'failed: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'disks-unknown', nlabel => 'disks.unknown.count', set => {
|
||||
key_values => [ { name => 'unknown' }, { name => 'total' } ],
|
||||
output_template => 'unknown: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
$self->{maps_counters}->{disks} = [
|
||||
{
|
||||
label => 'status',
|
||||
type => 2,
|
||||
warning_default => '%{status} =~ /^(new|degraded|unknown)$/',
|
||||
critical_default => '%{status} =~ /failed/',
|
||||
unknown_default => '%{status} =~ /NOT_DOCUMENTED$/',
|
||||
set => {
|
||||
key_values => [ { name => 'status' }, { name => 'id' }, { name => 'manufacturer' }, { name => 'model' }, { name => 'serial' }, { name => 'position' } ],
|
||||
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 => {
|
||||
'filter-id:s' => { name => 'filter_id' },
|
||||
'filter-manufacturer:s' => { name => 'filter_manufacturer' },
|
||||
'filter-model:s' => { name => 'filter_model' },
|
||||
'filter-position:s' => { name => 'filter_position' },
|
||||
'filter-serial:s' => { name => 'filter_serial' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $api_response = $options{custom}->request_api(
|
||||
endpoint => '/api/v1/disks'
|
||||
);
|
||||
|
||||
my $disks = $api_response->{members};
|
||||
|
||||
$self->{global} = {
|
||||
total => 0,
|
||||
normal => 0,
|
||||
degraded => 0,
|
||||
new => 0,
|
||||
failed => 0,
|
||||
unknown => 0
|
||||
};
|
||||
|
||||
for my $disk (@{$disks}) {
|
||||
my $disk_intro = "disk #" . $disk->{id} . " (" . $disk->{manufacturer} . "/" . $disk->{model}
|
||||
. ", serial: " . $disk->{serialNumber} . ") located '" . $disk->{position};
|
||||
# skip if filtered by id
|
||||
if (defined($self->{option_results}->{filter_id})
|
||||
and $self->{option_results}->{filter_id} ne ''
|
||||
and $disk->{id} !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the id does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by manufacturer
|
||||
if (defined($self->{option_results}->{filter_manufacturer})
|
||||
and $self->{option_results}->{filter_manufacturer} ne ''
|
||||
and $disk->{manufacturer} !~ /$self->{option_results}->{filter_manufacturer}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the manufacturer does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by model
|
||||
if (defined($self->{option_results}->{filter_model})
|
||||
and $self->{option_results}->{filter_model} ne ''
|
||||
and $disk->{model} !~ /$self->{option_results}->{filter_model}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the model does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by position
|
||||
if (defined($self->{option_results}->{filter_position})
|
||||
and $self->{option_results}->{filter_position} ne ''
|
||||
and $disk->{position} !~ /$self->{option_results}->{filter_position}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the position does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by serial
|
||||
if (defined($self->{option_results}->{filter_serial})
|
||||
and $self->{option_results}->{filter_serial} ne ''
|
||||
and $disk->{serialNumber} !~ /$self->{option_results}->{filter_serial}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the serial does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
my $state = defined($map_state{$disk->{state}}) ? $map_state{$disk->{state}} : 'NOT_DOCUMENTED';
|
||||
|
||||
# increment adequate global counters
|
||||
$self->{global}->{total} = $self->{global}->{total} + 1;
|
||||
$self->{global}->{$state} = $self->{global}->{$state} + 1;
|
||||
|
||||
# add the instance
|
||||
$self->{disks}->{ $disk->{id} } = {
|
||||
status => $state,
|
||||
position => $disk->{position},
|
||||
id => $disk->{id},
|
||||
manufacturer => $disk->{manufacturer},
|
||||
model => $disk->{model},
|
||||
serial => $disk->{serialNumber}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Monitor the states of the physical disks.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : disks-total disks-normal disks-degraded disks-new disks-failed disks-unknown status
|
||||
Example: --filter-counters='^disks-total$'
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Define which disks should be monitored based on their IDs.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-manufacturer>
|
||||
|
||||
Define which volumes should be monitored based on the disk manufacturer.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-model>
|
||||
|
||||
Define which volumes should be monitored based on the disk model.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-serial>
|
||||
|
||||
Define which volumes should be monitored based on the disk serial number.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-position>
|
||||
|
||||
Define which volumes should be monitored based on the disk position.
|
||||
The position is composed of 3 integers, separated by colons:
|
||||
- Cage number where the physical disk is in.
|
||||
- Magazine number where the physical disk is in.
|
||||
- For DC4 cages, disk position within the magazine. For non-DC4 cages, 0.
|
||||
Example: 7:5:0
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Define the condition to match for the returned status to be WARNING.
|
||||
Default: '%{status} =~ /^(new|degraded|unknown)$/'
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Define the condition to match for the returned status to be CRITICAL.
|
||||
Default: '%{status} =~ /failed/'
|
||||
|
||||
=item B<--unknown-status>
|
||||
|
||||
Define the condition to match for the returned status to be UNKNOWN.
|
||||
Default: '%{status} =~ /NOT_DOCUMENTED$/'
|
||||
|
||||
=item B<--warning-disks-degraded>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-degraded>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-disks-failed>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-failed>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-disks-new>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-new>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-disks-normal>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-normal>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-disks-total>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-total>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-disks-unknown>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-disks-unknown>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Threshold.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
360
src/storage/hp/alletra/restapi/mode/diskusage.pm
Normal file
360
src/storage/hp/alletra/restapi/mode/diskusage.pm
Normal file
@ -0,0 +1,360 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::diskusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub custom_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(
|
||||
"Used: %s of %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_used_value . " " . $total_used_unit,
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$self->{result_values}->{prct_used},
|
||||
$total_free_value . " " . $total_free_unit,
|
||||
$self->{result_values}->{prct_free}
|
||||
);
|
||||
}
|
||||
|
||||
sub custom_global_total_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($used_human, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
|
||||
my ($total_human, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
my $msg = "Total Used: $used_human $used_unit / $total_human $total_unit" ;
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_global_total_free_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($free_human, $free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free});
|
||||
my $msg = "Total Free: $free_human $free_unit" ;
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', type => 0 },
|
||||
{ name => 'disk', type => 1, cb_prefix_output => 'prefix_disk_output', message_multiple => 'All disks are ok' },
|
||||
];
|
||||
$self->{maps_counters}->{global} = [
|
||||
{
|
||||
label => 'total-usage',
|
||||
nlabel => 'disks.total.space.usage.bytes',
|
||||
set => {
|
||||
key_values => [ { name => 'used' }, { name => 'total' } ],
|
||||
closure_custom_output => $self->can('custom_global_total_usage_output'),
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'total-usage-prct',
|
||||
nlabel => 'disks.total.space.usage.percent',
|
||||
set => {
|
||||
key_values => [ { name => 'used_prct' }],
|
||||
output_template => 'Total percentage used: %.2f %%',
|
||||
perfdatas => [
|
||||
{ template => '%s', uom => '%', min => 0, max => 100 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'total-free',
|
||||
nlabel => 'disks.total.space.free.bytes',
|
||||
set => {
|
||||
key_values => [ { name => 'free' }, { name => 'total' } ],
|
||||
closure_custom_output => $self->can('custom_global_total_free_output'),
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
$self->{maps_counters}->{disk} = [
|
||||
{ label => 'usage', nlabel => 'disk.space.usage.bytes', set => {
|
||||
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'id' }, { name => 'position' }, { name => 'manufacturer' }, { name => 'model' }, { name => 'serial' } ],
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'id' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'usage-free', display_ok => 0, nlabel => 'disk.space.free.bytes', set => {
|
||||
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'id' }, { name => 'position' }, { name => 'manufacturer' }, { name => 'model' }, { name => 'serial' } ],
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
perfdatas => [
|
||||
{ template => '%d', min => 0, max => 'total', unit => 'B', cast_int => 1, label_extra_instance => 1, instance_use => 'id' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'usage-prct', display_ok => 0, nlabel => 'disk.space.usage.percentage', set => {
|
||||
key_values => [ { name => 'prct_used' }, { name => 'id' }, { name => 'position' }, { name => 'manufacturer' }, { name => 'model' }, { name => 'serial' } ],
|
||||
output_template => 'Used : %.2f %%',
|
||||
perfdatas => [
|
||||
{ template => '%.2f', min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'id' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
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-id:s' => { name => 'filter_id' },
|
||||
'filter-manufacturer:s' => { name => 'filter_manufacturer' },
|
||||
'filter-model:s' => { name => 'filter_model' },
|
||||
'filter-serial:s' => { name => 'filter_serial' },
|
||||
'filter-position:s' => { name => 'filter_position' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub prefix_disk_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
#return "Disk '" . $options{instance_value}->{display} . "' ";
|
||||
return sprintf(
|
||||
"Disk #%s (%s/%s, serial: %s) located %s has ",
|
||||
$options{instance_value}->{id},
|
||||
$options{instance_value}->{manufacturer},
|
||||
$options{instance_value}->{model},
|
||||
$options{instance_value}->{serial},
|
||||
$options{instance_value}->{position}
|
||||
);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(
|
||||
endpoint => '/api/v1/disks'
|
||||
);
|
||||
my $disks = $response->{members};
|
||||
|
||||
$self->{global} = {
|
||||
total => 0,
|
||||
free => 0,
|
||||
used => 0,
|
||||
used_prct => 0
|
||||
};
|
||||
$self->{disk} = {};
|
||||
|
||||
for my $disk (@{$disks}) {
|
||||
|
||||
my $disk_intro = "disk #" . $disk->{id} . " (" . $disk->{manufacturer} . "/" . $disk->{model}
|
||||
. ", serial: " . $disk->{serialNumber} . ") located '" . $disk->{position};
|
||||
|
||||
# skip if filtered by id
|
||||
if (defined($self->{option_results}->{filter_id})
|
||||
and $self->{option_results}->{filter_id} ne ''
|
||||
and $disk->{id} !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the id does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by manufacturer
|
||||
if (defined($self->{option_results}->{filter_manufacturer})
|
||||
and $self->{option_results}->{filter_manufacturer} ne ''
|
||||
and $disk->{manufacturer} !~ /$self->{option_results}->{filter_manufacturer}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the manufacturer does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by model
|
||||
if (defined($self->{option_results}->{filter_model})
|
||||
and $self->{option_results}->{filter_model} ne ''
|
||||
and $disk->{model} !~ /$self->{option_results}->{filter_model}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the model does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by position
|
||||
if (defined($self->{option_results}->{filter_position})
|
||||
and $self->{option_results}->{filter_position} ne ''
|
||||
and $disk->{position} !~ /$self->{option_results}->{filter_position}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the position does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
# skip if filtered by serial
|
||||
if (defined($self->{option_results}->{filter_serial})
|
||||
and $self->{option_results}->{filter_serial} ne ''
|
||||
and $disk->{serialNumber} !~ /$self->{option_results}->{filter_serial}/) {
|
||||
$self->{output}->output_add(long_msg => "Skipping $disk_intro because the serial does not match the filter.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
my $total = $disk->{totalSizeMiB} * 1024 * 1024;
|
||||
my $free = $disk->{freeSizeMiB} * 1024 * 1024;
|
||||
my $used = $total - $free;
|
||||
|
||||
$self->{global}->{total} = $self->{global}->{total} + $total;
|
||||
$self->{global}->{free} = $self->{global}->{free} + $free;
|
||||
$self->{global}->{used} = $self->{global}->{used} + $used;
|
||||
|
||||
$self->{disk}->{$disk->{id}} = {
|
||||
id => $disk->{id},
|
||||
total => $total,
|
||||
used => $used,
|
||||
free => $free,
|
||||
prct_used => $used * 100 / $total,
|
||||
prct_free => $free * 100 / $total,
|
||||
manufacturer => $disk->{manufacturer},
|
||||
model => $disk->{model},
|
||||
serial => $disk->{serialNumber},
|
||||
position => $disk->{position}
|
||||
};
|
||||
}
|
||||
|
||||
$self->{global}->{used_prct} = $self->{global}->{used} * 100 / $self->{global}->{total} if ($self->{global}->{total} > 0);
|
||||
|
||||
if (scalar(keys %{$self->{disk}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No disk found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check disk usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : usage usage-free usage-prct total-usage total-usage-prct total-free
|
||||
Example: --filter-counters='^usage-free$'
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Define which disks should be monitored based on their IDs.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-manufacturer>
|
||||
|
||||
Define which volumes should be monitored based on the disk manufacturer.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-model>
|
||||
|
||||
Define which volumes should be monitored based on the disk model.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-serial>
|
||||
|
||||
Define which volumes should be monitored based on the disk serial number.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-position>
|
||||
|
||||
Define which volumes should be monitored based on the disk position.
|
||||
The position is composed of 3 integers, separated by colons:
|
||||
Cage number where the physical disk is in.
|
||||
- Magazine number where the physical disk is in.
|
||||
- For DC4 cages, disk position within the magazine. For non-DC4 cages, 0.
|
||||
Example: 7:5:0
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for individual disks
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=item B<--critical-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for global statistics
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-total-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-total-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-total-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-total-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-total-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=item B<--critical-total-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
240
src/storage/hp/alletra/restapi/mode/licenses.pm
Normal file
240
src/storage/hp/alletra/restapi/mode/licenses.pm
Normal file
@ -0,0 +1,240 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::licenses;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub custom_license_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $message;
|
||||
if ($self->{result_values}->{expiration_human} eq 'never') {
|
||||
$message = $self->{result_values}->{name} . ' has permanent license.';
|
||||
} elsif ($self->{result_values}->{expires_seconds} == 0) {
|
||||
$message = sprintf(
|
||||
"%s license has expired.",
|
||||
$self->{result_values}->{name}
|
||||
);
|
||||
} else {
|
||||
$message = sprintf(
|
||||
"%s license expires in %s.",
|
||||
$self->{result_values}->{name},
|
||||
centreon::plugins::misc::change_seconds(value => $self->{result_values}->{expires_seconds})
|
||||
);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
sub custom_license_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return if $self->{result_values}->{expiration_human} eq 'never';
|
||||
|
||||
$self->{output}->perfdata_add(
|
||||
nlabel => $self->{nlabel},
|
||||
unit => 's',
|
||||
instances => $self->{result_values}->{name},
|
||||
value => $self->{result_values}->{expires_seconds},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{thlabel}),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{thlabel}),
|
||||
min => 0
|
||||
);
|
||||
}
|
||||
|
||||
sub custom_license_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return 'ok' if (!defined($self->{result_values}->{expires_seconds}));
|
||||
return $self->{perfdata}->threshold_check(
|
||||
value => $self->{result_values}->{expires_seconds},
|
||||
threshold => [
|
||||
{ label => 'critical-' . $self->{thlabel}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{thlabel}, exit_litteral => 'warning' }
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
sub prefix_license_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "License '" . $options{instance_value}->{name} . "' expires: " . $options{instance_value}->{expiration_human} . ". ";
|
||||
}
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', type => 0 },
|
||||
{ name => 'license_expiration', type => 1, cb_prefix_output => 'prefix_license_output', message_multiple => 'All licenses are ok'}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{
|
||||
label => 'total',
|
||||
nlabel => 'licenses.total.count',
|
||||
critical_default => '1:',
|
||||
set => {
|
||||
key_values => [ { name => 'total' } ],
|
||||
output_template => 'Number of licenses: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'expired',
|
||||
nlabel => 'licenses.expired.count',
|
||||
critical_default => ':0',
|
||||
set => {
|
||||
key_values => [ { name => 'expired' }, { name => 'total' } ],
|
||||
output_template => 'Number of expired licenses: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
$self->{maps_counters}->{license_expiration} = [
|
||||
{ label => 'license-expiration', nlabel => 'license.expiration.seconds', set => {
|
||||
key_values => [ { name => 'name' }, { name => 'expires_seconds' }, { name => 'expiration_status' }, { name => 'expiration_human' }],
|
||||
closure_custom_output => $self->can('custom_license_output'),
|
||||
closure_custom_perfdata => $self->can('custom_license_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_license_threshold')
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
'filter-name:s' => { name => 'filter_name' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(
|
||||
endpoint => '/api/v1/system'
|
||||
);
|
||||
my $licenses = $response->{licenseInfo}->{licenses};
|
||||
|
||||
my ($total_licenses, $expired_licenses) = (0, 0);
|
||||
for my $license_item (@{$licenses}) {
|
||||
# skip if filter does not match
|
||||
next if (defined($self->{option_results}->{filter_name})
|
||||
and $self->{option_results}->{filter_name} ne ''
|
||||
and $license_item->{name} !~ /$self->{option_results}->{filter_name}/);
|
||||
|
||||
$total_licenses = $total_licenses + 1;
|
||||
$self->{license_expiration}->{$license_item->{name}} = {
|
||||
name => $license_item->{name},
|
||||
expiration_human => defined($license_item->{expiryTime8601}) ? $license_item->{expiryTime8601} : 'never',
|
||||
expires_seconds => 0,
|
||||
};
|
||||
|
||||
my $license_status = 'valid';
|
||||
if (defined($license_item->{expiryTimeSec})) {
|
||||
if ($license_item->{expiryTimeSec} > time()) {
|
||||
$self->{license_expiration}->{$license_item->{name}}->{expires_seconds} = $license_item->{expiryTimeSec} - time();
|
||||
} else {
|
||||
$license_status = 'expired';
|
||||
$expired_licenses = $expired_licenses + 1;
|
||||
}
|
||||
}
|
||||
$self->{license_expiration}->{$license_item->{name}}->{expiration_status} = $license_status;
|
||||
}
|
||||
$self->{global} = {
|
||||
total => $total_licenses,
|
||||
expired => $expired_licenses
|
||||
};
|
||||
|
||||
if (scalar(keys %{$self->{license_expiration}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Couldn't get information about licenses");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check storage capacities.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : license-expiration total expired
|
||||
Example: --filter-counters='^total$'
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter licenses by name (regular expression).
|
||||
|
||||
=item B<--warning-expired>
|
||||
|
||||
Threshold.
|
||||
Applies to the number of expired licenses.
|
||||
|
||||
=item B<--critical-expired>
|
||||
|
||||
Threshold.
|
||||
Default: C<:0>
|
||||
Applies to the number of expired licenses.
|
||||
|
||||
=item B<--warning-license-expiration>
|
||||
|
||||
Threshold in seconds.
|
||||
Applies to the remaining time in seconds until the licenses expire.
|
||||
|
||||
=item B<--critical-license-expiration>
|
||||
|
||||
Threshold in seconds.
|
||||
Applies to the remaining time in seconds until the licenses expire.
|
||||
|
||||
=item B<--warning-total>
|
||||
|
||||
Threshold.
|
||||
Applies to the total number of licenses.
|
||||
|
||||
|
||||
=item B<--critical-total>
|
||||
|
||||
Threshold.
|
||||
Default: C<1:>
|
||||
Applies to the total number of licenses.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
188
src/storage/hp/alletra/restapi/mode/listdisks.pm
Normal file
188
src/storage/hp/alletra/restapi/mode/listdisks.pm
Normal file
@ -0,0 +1,188 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::listdisks;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
'filter-id:s' => { name => 'filter_id' },
|
||||
'filter-protocol:s' => { name => 'filter_protocol' },
|
||||
'filter-type:s' => { name => 'filter_type' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
}
|
||||
|
||||
my %connection_type = (
|
||||
1 => 'FC',
|
||||
2 => 'SATA',
|
||||
4 => 'NVMe',
|
||||
99 => 'unknown'
|
||||
);
|
||||
|
||||
my %media_type = (
|
||||
1 => 'Magnetic',
|
||||
2 => 'SLC',
|
||||
3 => 'MLC',
|
||||
4 => 'cMLC',
|
||||
5 => '3DX',
|
||||
99 => 'unknown'
|
||||
);
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(endpoint => '/api/v1/disks');
|
||||
my $disks = $response->{members};
|
||||
|
||||
$self->{disks} = [];
|
||||
|
||||
for my $disk (@{$disks}) {
|
||||
$disk->{type} = $media_type{$disk->{type}};
|
||||
$disk->{protocol} = $connection_type{$disk->{protocol}};
|
||||
|
||||
# skip if filtered by protocol
|
||||
if (defined($self->{option_results}->{filter_protocol})
|
||||
and $self->{option_results}->{filter_protocol} ne '' and $disk->{protocol} !~ /$self->{option_results}->{filter_protocol}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $disk->{protocol} because the protocol does not match the protocol filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
# skip if filtered by type
|
||||
if (defined($self->{option_results}->{filter_type})
|
||||
and $self->{option_results}->{filter_type} ne '' and $disk->{type} !~ /$self->{option_results}->{filter_type}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $disk->{type} because the type does not match the type filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
# skip if filtered by id
|
||||
if (defined($self->{option_results}->{filter_id})
|
||||
and $self->{option_results}->{filter_id} ne '' and $disk->{id} !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $disk->{id} because the id does not match the id filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
push @{$self->{disks}}, {
|
||||
id => $disk->{id},
|
||||
position => $disk->{position},
|
||||
size => $disk->{totalSizeMiB},
|
||||
manufacturer => $disk->{manufacturer},
|
||||
model => $disk->{model},
|
||||
serial => $disk->{serialNumber},
|
||||
protocol => $disk->{protocol},
|
||||
type => $disk->{type}
|
||||
};
|
||||
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf(
|
||||
"[id: %s][position: %s][size: %s][manufacturer: %s][model: %s][serial: %s][protocol: %s][type: %s]",
|
||||
$disk->{id},
|
||||
$disk->{position},
|
||||
$disk->{totalSizeMiB},
|
||||
$disk->{manufacturer},
|
||||
$disk->{model},
|
||||
$disk->{serialNumber},
|
||||
$disk->{protocol},
|
||||
$disk->{type}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!defined($options{disco_show})) {
|
||||
$self->{output}->output_add(severity => 'OK', short_msg => 'Disks:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
}
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements =>
|
||||
[ 'id', 'position', 'size', 'manufacturer', 'model', 'serial', 'protocol', 'type' ]);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$options{disco_show} = 1;
|
||||
$self->run(%options);
|
||||
|
||||
for my $disk (@{$self->{disks}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
id => $disk->{id},
|
||||
position => $disk->{position},
|
||||
size => $disk->{size},
|
||||
manufacturer => $disk->{manufacturer},
|
||||
model => $disk->{model},
|
||||
serial => $disk->{serial},
|
||||
protocol => $disk->{protocol},
|
||||
type => $disk->{type}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List physical disks using the HPE Alletra REST API.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Display disks matching the id filter.
|
||||
|
||||
=item B<--filter-protocol>
|
||||
|
||||
Display disks matching the protocol filter.
|
||||
|
||||
=item B<--filter-type>
|
||||
|
||||
Display disks matching the media type filter.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
148
src/storage/hp/alletra/restapi/mode/listvolumes.pm
Normal file
148
src/storage/hp/alletra/restapi/mode/listvolumes.pm
Normal file
@ -0,0 +1,148 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::listvolumes;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
'filter-id:s' => { name => 'filter_id' },
|
||||
'filter-name:s' => { name => 'filter_name' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
}
|
||||
|
||||
my %map_state = (
|
||||
1 => 'normal',
|
||||
2 => 'degraded',
|
||||
3 => 'failed',
|
||||
99 => 'unknown'
|
||||
);
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(endpoint => '/api/v1/volumes');
|
||||
my $volumes = $response->{members};
|
||||
|
||||
$self->{volumes} = [];
|
||||
|
||||
for my $volume (@{$volumes}) {
|
||||
# skip if filtered by name
|
||||
if (defined($self->{option_results}->{filter_name})
|
||||
and $self->{option_results}->{filter_name} ne '' and $volume->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $volume->{name} because the name does not match the name filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
# skip if filtered by name
|
||||
if (defined($self->{option_results}->{filter_id})
|
||||
and $self->{option_results}->{filter_id} ne '' and $volume->{id} !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $volume->{name} because the id does not match the id filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
push @{$self->{volumes}}, {
|
||||
id => $volume->{id},
|
||||
name => $volume->{name},
|
||||
size => $volume->{sizeMiB},
|
||||
state => defined($map_state{$volume->{state}}) ? $map_state{$volume->{state}} : 'NOT_DOCUMENTED'
|
||||
};
|
||||
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf(
|
||||
"[id: %s][name: %s][size: %s][state: %s]",
|
||||
$volume->{id},
|
||||
$volume->{name},
|
||||
$volume->{sizeMiB},
|
||||
$volume->{state}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!defined($options{disco_show})) {
|
||||
$self->{output}->output_add(severity => 'OK', short_msg => 'Volumes:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
}
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => [ 'id', 'name', 'size', 'state' ]);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$options{disco_show} = 1;
|
||||
$self->run(%options);
|
||||
|
||||
for my $disk (@{$self->{volumes}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
id => $disk->{id},
|
||||
name => $disk->{name},
|
||||
size => $disk->{size},
|
||||
state => $disk->{state}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List physical volumes using the HPE Alletra REST API.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Display volumes matching the name filter.
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Display volumes matching the id filter.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
304
src/storage/hp/alletra/restapi/mode/volumestatus.pm
Normal file
304
src/storage/hp/alletra/restapi/mode/volumestatus.pm
Normal file
@ -0,0 +1,304 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::volumestatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %map_state = (
|
||||
1 => 'normal',
|
||||
2 => 'degraded',
|
||||
4 => 'failed',
|
||||
99 => 'unknown'
|
||||
);
|
||||
|
||||
my %compression_state = (
|
||||
1 => 'YES',
|
||||
2 => 'NO',
|
||||
3 => 'OFF',
|
||||
4 => 'NA',
|
||||
5 => 'V1',
|
||||
6 => 'v2'
|
||||
);
|
||||
|
||||
my %provisioning_type = (
|
||||
1 => 'FULL',
|
||||
2 => 'TPVV',
|
||||
3 => 'SNP',
|
||||
4 => 'PEER',
|
||||
5 => 'UNKNOWN',
|
||||
6 => 'TDVV',
|
||||
7 => 'DDS'
|
||||
);
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return sprintf(
|
||||
"Volume #%s (%s) uuid: %s (readonly: %s, compression: %s, provisioning: %s)",
|
||||
$self->{result_values}->{id},
|
||||
$self->{result_values}->{name},
|
||||
$self->{result_values}->{uuid},
|
||||
$self->{result_values}->{readonly},
|
||||
$self->{result_values}->{compression_state},
|
||||
$self->{result_values}->{provisioning_type}
|
||||
);
|
||||
}
|
||||
|
||||
sub prefix_global_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return 'Volumes ';
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', cb_prefix_output => 'prefix_global_output', type => 0 },
|
||||
{ name => 'volumes', type => 1, message_multiple => 'All volumes are ok' }
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'volumes-total', nlabel => 'volumes.total.count', set => {
|
||||
key_values => [ { name => 'total' } ],
|
||||
output_template => 'total: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'volumes-normal', nlabel => 'volumes.normal.count', set => {
|
||||
key_values => [ { name => 'normal' }, { name => 'total' } ],
|
||||
output_template => 'normal: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'volumes-degraded', nlabel => 'volumes.degraded.count', set => {
|
||||
key_values => [ { name => 'degraded' }, { name => 'total' } ],
|
||||
output_template => 'degraded: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'volumes-failed', nlabel => 'volumes.failed.count', set => {
|
||||
key_values => [ { name => 'failed' }, { name => 'total' } ],
|
||||
output_template => 'failed: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label => 'volumes-unknown', nlabel => 'volumes.unknown.count', set => {
|
||||
key_values => [ { name => 'unknown' }, { name => 'total' } ],
|
||||
output_template => 'unknown: %s',
|
||||
perfdatas => [
|
||||
{ template => '%s', min => 0, max => 'total' }
|
||||
]
|
||||
}
|
||||
}
|
||||
];
|
||||
$self->{maps_counters}->{volumes} = [
|
||||
{
|
||||
label => 'status',
|
||||
type => 2,
|
||||
warning_default => '%{status} =~ /^(degraded|unknown)$/',
|
||||
critical_default => '%{status} =~ /failed/',
|
||||
unknown_default => '%{status} =~ /NOT_DOCUMENTED$/',
|
||||
set => {
|
||||
key_values => [
|
||||
{ name => 'status' },
|
||||
{ name => 'id' },
|
||||
{ name => 'name' },
|
||||
{ name => 'uuid' },
|
||||
{ name => 'compression_state' },
|
||||
{ name => 'provisioning_type' },
|
||||
{ name => 'readonly' }
|
||||
],
|
||||
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 => {
|
||||
'filter-id:s' => { name => 'filter_id' },
|
||||
'filter-name:s' => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $api_response = $options{custom}->request_api(
|
||||
endpoint => '/api/v1/volumes'
|
||||
);
|
||||
|
||||
my $volumes = $api_response->{members};
|
||||
|
||||
$self->{global} = {
|
||||
total => 0,
|
||||
normal => 0,
|
||||
degraded => 0,
|
||||
failed => 0,
|
||||
unknown => 0
|
||||
};
|
||||
|
||||
for my $volume (@{$volumes}) {
|
||||
# skip if filtered by name
|
||||
if (defined($self->{option_results}->{filter_name})
|
||||
and $self->{option_results}->{filter_name} ne '' and $volume->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $volume->{name} because the name does not match the name filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
# skip if filtered by name
|
||||
if (defined($self->{option_results}->{filter_id})
|
||||
and $self->{option_results}->{filter_id} ne '' and $volume->{id} !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg => "Skipping $volume->{name} because the id does not match the id filter.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
my $state = defined($map_state{$volume->{state}}) ? $map_state{$volume->{state}} : 'NOT_DOCUMENTED';
|
||||
|
||||
# increment adequate global counters
|
||||
$self->{global}->{total} = $self->{global}->{total} + 1;
|
||||
$self->{global}->{$state} = $self->{global}->{$state} + 1;
|
||||
|
||||
# add the instance
|
||||
$self->{volumes}->{ $volume->{id} } = {
|
||||
status => $state,
|
||||
name => $volume->{name},
|
||||
id => $volume->{id},
|
||||
uuid => $volume->{uuid},
|
||||
compression_state => defined($compression_state{$volume->{compressionState}}) ?
|
||||
$compression_state{$volume->{compressionState}} : 'NOT_DOCUMENTED',
|
||||
provisioning_type => defined($provisioning_type{$volume->{provisioningType}}) ?
|
||||
$provisioning_type{$volume->{provisioningType}} : 'NOT_DOCUMENTED',
|
||||
readonly => $volume->{readOnly}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Monitor the states of the volumes.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : volumes-total volumes-normal volumes-degraded volumes-failed volumes-unknown status
|
||||
Example: --filter-counters='^volumes-total$'
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Define which volumes should be monitored based on their IDs.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Define which volumes should be monitored based on the volume name.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Define the condition to match for the returned status to be WARNING.
|
||||
Default: '%{status} =~ /^(degraded|unknown)$/'
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Define the condition to match for the returned status to be CRITICAL.
|
||||
Default: '%{status} =~ /failed/'
|
||||
|
||||
=item B<--unknown-status>
|
||||
|
||||
Define the condition to match for the returned status to be UNKNOWN.
|
||||
Default: '%{status} =~ /NOT_DOCUMENTED$/'
|
||||
|
||||
=item B<--warning-volumes-degraded>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-volumes-degraded>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-volumes-failed>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-volumes-failed>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-volumes-normal>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-volumes-normal>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-volumes-total>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-volumes-total>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--warning-volumes-unknown>
|
||||
|
||||
Threshold.
|
||||
|
||||
=item B<--critical-volumes-unknown>
|
||||
|
||||
Threshold.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
282
src/storage/hp/alletra/restapi/mode/volumeusage.pm
Normal file
282
src/storage/hp/alletra/restapi/mode/volumeusage.pm
Normal file
@ -0,0 +1,282 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::mode::volumeusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(
|
||||
value => $self->{result_values}->{total}
|
||||
);
|
||||
my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(
|
||||
value => $self->{result_values}->{used}
|
||||
);
|
||||
my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(
|
||||
value => $self->{result_values}->{free}
|
||||
);
|
||||
my ($reserved_value, $reserved_unit) = $self->{perfdata}->change_bytes(
|
||||
value => $self->{result_values}->{reserved}
|
||||
);
|
||||
|
||||
return sprintf(
|
||||
"Total: %s Reserved: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$reserved_value . " " . $reserved_unit,
|
||||
$used_value . " " . $used_unit,
|
||||
$self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit,
|
||||
$self->{result_values}->{prct_free},
|
||||
);
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{
|
||||
name => 'volume',
|
||||
type => 1,
|
||||
cb_prefix_output => 'prefix_volume_output',
|
||||
message_multiple => 'All volumes are ok'
|
||||
},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{volume} = [
|
||||
{
|
||||
label => 'usage',
|
||||
nlabel => 'volume.space.usage.bytes',
|
||||
set => {
|
||||
key_values =>
|
||||
[
|
||||
{ name => 'used' },
|
||||
{ name => 'free' },
|
||||
{ name => 'prct_used' },
|
||||
{ name => 'prct_free' },
|
||||
{ name => 'total' },
|
||||
{ name => 'reserved' },
|
||||
{ name => 'name' },
|
||||
{ name => 'id' }
|
||||
],
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
perfdatas => [
|
||||
{
|
||||
template => '%d',
|
||||
min => 0,
|
||||
max => 'total',
|
||||
unit => 'B',
|
||||
cast_int => 1,
|
||||
label_extra_instance => 1,
|
||||
instance_use => 'name'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => '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 => 'reserved' },
|
||||
{ name => 'name' },
|
||||
{ name => 'id' }
|
||||
],
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
perfdatas =>
|
||||
[
|
||||
{
|
||||
template => '%d',
|
||||
min => 0,
|
||||
max => 'total',
|
||||
unit => 'B',
|
||||
cast_int => 1,
|
||||
label_extra_instance => 1,
|
||||
instance_use => 'name'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
label => 'usage-prct',
|
||||
display_ok => 0,
|
||||
nlabel => 'volume.space.usage.percentage',
|
||||
set => {
|
||||
key_values => [ { name => 'prct_used' }, { name => 'name' }, { name => 'id' } ],
|
||||
output_template => 'Used : %.2f %%',
|
||||
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-id:s' => { name => 'filter_id' },
|
||||
'filter-name:s' => { name => 'filter_name' }
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub prefix_volume_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Volume '" . $options{instance_value}->{name} . "' (#" . $options{instance_value}->{id} . ") ";
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $response = $options{custom}->request_api(endpoint => '/api/v1/volumes');
|
||||
my $volumes = $response->{members};
|
||||
$self->{volume} = {};
|
||||
|
||||
for my $volume (@{$volumes}) {
|
||||
my $name = $volume->{name};
|
||||
my $id = $volume->{id};
|
||||
|
||||
if (defined($self->{option_results}->{filter_name}) and $self->{option_results}->{filter_name} ne '' and
|
||||
$name !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg =>
|
||||
"Skipping volume named '" . $name . "': not matching filter /" . $self->{option_results}->{filter_name} . "/.",
|
||||
debug =>
|
||||
1
|
||||
);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_id}) and $self->{option_results}->{filter_id} ne '' and
|
||||
$id !~ /$self->{option_results}->{filter_id}/) {
|
||||
$self->{output}->output_add(
|
||||
long_msg =>
|
||||
"Skipping volume #" . $id . ": not matching filter /" . $self->{option_results}->{filter_id} . "/.",
|
||||
debug => 1
|
||||
);
|
||||
next;
|
||||
}
|
||||
|
||||
my $total = $volume->{sizeMiB} * 1024 * 1024;
|
||||
my $reserved = $volume->{totalReservedMiB} * 1024 * 1024;
|
||||
my $used = $volume->{totalUsedMiB} * 1024 * 1024;
|
||||
my $free = ($total - $used) >= 0 ? ($total - $used) : 0;
|
||||
|
||||
$self->{volume}->{$name} = {
|
||||
id => $id,
|
||||
name => $name,
|
||||
total => $total,
|
||||
reserved => $reserved,
|
||||
used => $used,
|
||||
free => $free,
|
||||
prct_used => $used * 100 / $total,
|
||||
prct_free => $free * 100 / $total
|
||||
};
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{volume}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No volume found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check volume usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-counters>
|
||||
|
||||
Define which counters (filtered by regular expression) should be monitored.
|
||||
Can be : usage usage-free usage-prct
|
||||
Example: --filter-counters='^usage$'
|
||||
|
||||
=item B<--filter-id>
|
||||
|
||||
Define which volumes should be monitored based on their IDs.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Define which volumes should be monitored based on the volume names.
|
||||
This option will be treated as a regular expression.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Thresholds for volume usage metrics
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-usage>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--critical-usage-free>
|
||||
|
||||
Threshold in bytes.
|
||||
|
||||
=item B<--warning-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=item B<--critical-usage-prct>
|
||||
|
||||
Threshold in percentage.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
55
src/storage/hp/alletra/restapi/plugin.pm
Normal file
55
src/storage/hp/alletra/restapi/plugin.pm
Normal file
@ -0,0 +1,55 @@
|
||||
#
|
||||
# Copyright 2025 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::hp::alletra::restapi::plugin;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(centreon::plugins::script_custom);
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{modes} = {
|
||||
'capacity' => 'storage::hp::alletra::restapi::mode::capacity',
|
||||
'disk-status' => 'storage::hp::alletra::restapi::mode::diskstatus',
|
||||
'disk-usage' => 'storage::hp::alletra::restapi::mode::diskusage',
|
||||
'licenses' => 'storage::hp::alletra::restapi::mode::licenses',
|
||||
'list-disks' => 'storage::hp::alletra::restapi::mode::listdisks',
|
||||
'list-volumes' => 'storage::hp::alletra::restapi::mode::listvolumes',
|
||||
'volume-usage' => 'storage::hp::alletra::restapi::mode::volumeusage',
|
||||
'volume-status' => 'storage::hp::alletra::restapi::mode::volumestatus'
|
||||
};
|
||||
|
||||
$self->{custom_modes}->{api} = 'storage::hp::alletra::restapi::custom::api';
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Monitor HPE Alletra storage controller.
|
||||
|
||||
=cut
|
@ -13,6 +13,7 @@ ACS
|
||||
ADSL
|
||||
Alcatel
|
||||
allCapacity
|
||||
Alletra
|
||||
allsteps
|
||||
Ansible
|
||||
--api-filter-orgs
|
||||
|
50
tests/storage/hp/alletra/restapi/hpe-alletra-capacity.robot
Normal file
50
tests/storage/hp/alletra/restapi/hpe-alletra-capacity.robot
Normal file
@ -0,0 +1,50 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Capacity
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode capacity
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
Capacity ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} OK: All storage capacities are ok | 'FCCapacity#storage.space.usage.bytes'=0B;;;0;0 'FCCapacity#storage.space.free.bytes'=0B;;;0;0 'FCCapacity#storage.space.usage.percentage'=0.00%;;;0;100 'FCCapacity#storage.space.unavailable.bytes'=0B;;;0; 'FCCapacity#storage.space.failed.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.virtualsize.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.used.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.allocated.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.free.bytes'=0B;;;0; 'FCCapacity#storage.space.compaction.ratio.count'=0;;;0; 'FCCapacity#storage.space.deduplication.ratio.count'=0;;;0; 'FCCapacity#storage.space.data_reduction.ratio.count'=0;;;0; 'FCCapacity#storage.space.overprovisioning.ratio.count'=0;;;0; 'NLCapacity#storage.space.usage.bytes'=0B;;;0;0 'NLCapacity#storage.space.free.bytes'=0B;;;0;0 'NLCapacity#storage.space.usage.percentage'=0.00%;;;0;100 'NLCapacity#storage.space.unavailable.bytes'=0B;;;0; 'NLCapacity#storage.space.failed.bytes'=0B;;;0; 'NLCapacity#storage.provisioning.virtualsize.bytes'=0B;;;0; 'NLCapacity#storage.provisioning.used.bytes'=0B;;;0; 'NLCapacity#storage.provisioning.allocated.bytes'=0B;;;0; 'NLCapacity#storage.provisioning.free.bytes'=0B;;;0; 'NLCapacity#storage.space.compaction.ratio.count'=0;;;0; 'NLCapacity#storage.space.deduplication.ratio.count'=0;;;0; 'NLCapacity#storage.space.data_reduction.ratio.count'=0;;;0; 'NLCapacity#storage.space.overprovisioning.ratio.count'=0;;;0; 'SSDCapacity#storage.space.usage.bytes'=123327838420992B;;;0;184305636605952 'SSDCapacity#storage.space.free.bytes'=60977798184960B;;;0;184305636605952 'SSDCapacity#storage.space.usage.percentage'=66.91%;;;0;100 'SSDCapacity#storage.space.unavailable.bytes'=0B;;;0; 'SSDCapacity#storage.space.failed.bytes'=0B;;;0; 'SSDCapacity#storage.provisioning.virtualsize.bytes'=145453502955520B;;;0; 'SSDCapacity#storage.provisioning.used.bytes'=98247842463744B;;;0; 'SSDCapacity#storage.provisioning.allocated.bytes'=8490068213760B;;;0; 'SSDCapacity#storage.provisioning.free.bytes'=60977798184960B;;;0; 'SSDCapacity#storage.space.compaction.ratio.count'=2.84;;;0; 'SSDCapacity#storage.space.deduplication.ratio.count'=1.17;;;0; 'SSDCapacity#storage.space.compression.ratio.count'=1;;;0; 'SSDCapacity#storage.space.data_reduction.ratio.count'=1.58;;;0; 'SSDCapacity#storage.space.overprovisioning.ratio.count'=0.87;;;0; 'allCapacity#storage.space.usage.bytes'=123327838420992B;;;0;184305636605952 'allCapacity#storage.space.free.bytes'=60977798184960B;;;0;184305636605952 'allCapacity#storage.space.usage.percentage'=66.91%;;;0;100 'allCapacity#storage.space.unavailable.bytes'=0B;;;0; 'allCapacity#storage.space.failed.bytes'=0B;;;0; 'allCapacity#storage.provisioning.virtualsize.bytes'=145453502955520B;;;0; 'allCapacity#storage.provisioning.used.bytes'=98247842463744B;;;0; 'allCapacity#storage.provisioning.allocated.bytes'=8490068213760B;;;0; 'allCapacity#storage.provisioning.free.bytes'=60977798184960B;;;0; 'allCapacity#storage.space.compaction.ratio.count'=2.84;;;0; 'allCapacity#storage.space.deduplication.ratio.count'=1.17;;;0; 'allCapacity#storage.space.compression.ratio.count'=1;;;0; 'allCapacity#storage.space.data_reduction.ratio.count'=1.58;;;0; 'allCapacity#storage.space.overprovisioning.ratio.count'=0.87;;;0;
|
||||
... 2 --filter-type=FCCapacity OK: storage 'FCCapacity' space usage total: 0.00 B used: 0.00 B (0.00%) free: 0.00 B (0.00%), unavailable: 0.00 B, failed: 0.00 B - provisioning virtual size: 0.00 B, provisioning used: 0.00 B, provisioning allocated: 0.00 B, provisioning free: 0.00 B - compaction: 0, deduplication: 0, data reduction: 0, overprovisioning: 0 | 'FCCapacity#storage.space.usage.bytes'=0B;;;0;0 'FCCapacity#storage.space.free.bytes'=0B;;;0;0 'FCCapacity#storage.space.usage.percentage'=0.00%;;;0;100 'FCCapacity#storage.space.unavailable.bytes'=0B;;;0; 'FCCapacity#storage.space.failed.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.virtualsize.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.used.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.allocated.bytes'=0B;;;0; 'FCCapacity#storage.provisioning.free.bytes'=0B;;;0; 'FCCapacity#storage.space.compaction.ratio.count'=0;;;0; 'FCCapacity#storage.space.deduplication.ratio.count'=0;;;0; 'FCCapacity#storage.space.data_reduction.ratio.count'=0;;;0; 'FCCapacity#storage.space.overprovisioning.ratio.count'=0;;;0;
|
||||
... 3 --filter-type=SSDCapacity --critical-compression=:0 --filter-counters=compression CRITICAL: storage 'SSDCapacity' compression: 1 | 'SSDCapacity#storage.space.compression.ratio.count'=1;;0:0;0;
|
||||
... 4 --filter-type=SSDCapacity --filter-counters=space-usage --warning-space-usage=:160 WARNING: storage 'SSDCapacity' space usage total: 167.62 TB used: 112.17 TB (66.91%) free: 55.46 TB (33.09%) | 'SSDCapacity#storage.space.usage.bytes'=123327838420992B;0:160;;0;184305636605952 'SSDCapacity#storage.space.free.bytes'=60977798184960B;;;0;184305636605952 'SSDCapacity#storage.space.usage.percentage'=66.91%;;;0;100
|
||||
... 5 --filter-type=SSDCapacity --filter-counters=space-usage --critical-space-usage-free=:55 CRITICAL: storage 'SSDCapacity' space usage total: 167.62 TB used: 112.17 TB (66.91%) free: 55.46 TB (33.09%) | 'SSDCapacity#storage.space.usage.bytes'=123327838420992B;;;0;184305636605952 'SSDCapacity#storage.space.free.bytes'=60977798184960B;;0:55;0;184305636605952 'SSDCapacity#storage.space.usage.percentage'=66.91%;;;0;100
|
||||
... 6 --filter-type=SSDCapacity --filter-counters=space-usage --critical-space-usage-prct=:60 CRITICAL: storage 'SSDCapacity' space usage total: 167.62 TB used: 112.17 TB (66.91%) free: 55.46 TB (33.09%) | 'SSDCapacity#storage.space.usage.bytes'=123327838420992B;;;0;184305636605952 'SSDCapacity#storage.space.free.bytes'=60977798184960B;;;0;184305636605952 'SSDCapacity#storage.space.usage.percentage'=66.91%;;0:60;0;100
|
||||
... 7 --filter-type=SSDCapacity --filter-counters=space-unavailable --critical-space-unavailable=1:10 CRITICAL: storage 'SSDCapacity' unavailable: 0.00 B | 'SSDCapacity#storage.space.unavailable.bytes'=0B;;1:10;0;
|
||||
... 8 --filter-type=SSDCapacity --filter-counters=space-failed --critical-space-failed=1:10 CRITICAL: storage 'SSDCapacity' failed: 0.00 B | 'SSDCapacity#storage.space.failed.bytes'=0B;;1:10;0;
|
||||
... 9 --filter-type=SSDCapacity --filter-counters=provisioning-virtual-size OK: storage 'SSDCapacity' provisioning virtual size: 132.29 TB | 'SSDCapacity#storage.provisioning.virtualsize.bytes'=145453502955520B;;;0;
|
||||
... 10 --filter-type=SSDCapacity --filter-counters=provisioning-used OK: storage 'SSDCapacity' provisioning used: 89.36 TB | 'SSDCapacity#storage.provisioning.used.bytes'=98247842463744B;;;0;
|
||||
... 11 --filter-type=SSDCapacity --filter-counters=provisioning-allocated --critical-provisioning-allocated=:1 CRITICAL: storage 'SSDCapacity' provisioning allocated: 7.72 TB | 'SSDCapacity#storage.provisioning.allocated.bytes'=8490068213760B;;0:1;0;
|
||||
... 12 --filter-type=SSDCapacity --filter-counters=provisioning-free --warning-provisioning-free=:1 WARNING: storage 'SSDCapacity' provisioning free: 55.46 TB | 'SSDCapacity#storage.provisioning.free.bytes'=60977798184960B;0:1;;0;
|
||||
... 13 --filter-type=SSDCapacity --filter-counters=compaction --warning-compaction=:1 WARNING: storage 'SSDCapacity' compaction: 2.84 | 'SSDCapacity#storage.space.compaction.ratio.count'=2.84;0:1;;0;
|
||||
... 14 --filter-type=SSDCapacity --filter-counters=deduplication --warning-deduplication=:1 WARNING: storage 'SSDCapacity' deduplication: 1.17 | 'SSDCapacity#storage.space.deduplication.ratio.count'=1.17;0:1;;0;
|
||||
... 15 --filter-type=SSDCapacity --filter-counters=data-reduction --critical-data-reduction=3: CRITICAL: storage 'SSDCapacity' data reduction: 1.58 | 'SSDCapacity#storage.space.data_reduction.ratio.count'=1.58;;3:;0;
|
||||
... 16 --filter-type=SSDCapacity --filter-counters=overprovisioning OK: storage 'SSDCapacity' overprovisioning: 0.87 | 'SSDCapacity#storage.space.overprovisioning.ratio.count'=0.87;;;0;
|
@ -0,0 +1,45 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Disk Status
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode disk-status
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
DiskStatus ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} CRITICAL: Disk #1 (XXXX/XXXX, serial: XXXX) located 1:2 is failed WARNING: Disk #2 (XXX/XXX, serial: XXX) located 1:3 is degraded | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;;;0;3 'disks.new.count'=0;;;0;3 'disks.failed.count'=1;;;0;3 'disks.unknown.count'=0;;;0;3
|
||||
... 2 --filter-id='^0$' OK: Disks total: 1, normal: 1, degraded: 0, new: 0, failed: 0, unknown: 0 - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 is normal | 'disks.total.count'=1;;;0; 'disks.normal.count'=1;;;0;1 'disks.degraded.count'=0;;;0;1 'disks.new.count'=0;;;0;1 'disks.failed.count'=0;;;0;1 'disks.unknown.count'=0;;;0;1
|
||||
... 3 --filter-manufacturer='X1$' OK: Disks total: 1, normal: 1, degraded: 0, new: 0, failed: 0, unknown: 0 - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 is normal | 'disks.total.count'=1;;;0; 'disks.normal.count'=1;;;0;1 'disks.degraded.count'=0;;;0;1 'disks.new.count'=0;;;0;1 'disks.failed.count'=0;;;0;1 'disks.unknown.count'=0;;;0;1
|
||||
... 4 --filter-model='X1$' OK: Disks total: 1, normal: 1, degraded: 0, new: 0, failed: 0, unknown: 0 - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 is normal | 'disks.total.count'=1;;;0; 'disks.normal.count'=1;;;0;1 'disks.degraded.count'=0;;;0;1 'disks.new.count'=0;;;0;1 'disks.failed.count'=0;;;0;1 'disks.unknown.count'=0;;;0;1
|
||||
... 5 --filter-serial='X2$' CRITICAL: Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 is failed | 'disks.total.count'=1;;;0; 'disks.normal.count'=0;;;0;1 'disks.degraded.count'=0;;;0;1 'disks.new.count'=0;;;0;1 'disks.failed.count'=1;;;0;1 'disks.unknown.count'=0;;;0;1
|
||||
... 6 --filter-position=1:3 WARNING: Disk #2 (XXX3/XXX3, serial: XXX3) located 1:3 is degraded | 'disks.total.count'=1;;;0; 'disks.normal.count'=0;;;0;1 'disks.degraded.count'=1;;;0;1 'disks.new.count'=0;;;0;1 'disks.failed.count'=0;;;0;1 'disks.unknown.count'=0;;;0;1
|
||||
... 7 --warning-disks-new=1: --critical-status='' --warning-status='' WARNING: Disks new: 0 | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;;;0;3 'disks.new.count'=0;1:;;0;3 'disks.failed.count'=1;;;0;3 'disks.unknown.count'=0;;;0;3
|
||||
... 8 --warning-disks-degraded=:0 --critical-status='' --warning-status='' WARNING: Disks degraded: 1 | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;0:0;;0;3 'disks.new.count'=0;;;0;3 'disks.failed.count'=1;;;0;3 'disks.unknown.count'=0;;;0;3
|
||||
... 9 --critical-status='' --warning-status='' --warning-disks-new=@0:0 WARNING: Disks new: 0 | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;;;0;3 'disks.new.count'=0;@0:0;;0;3 'disks.failed.count'=1;;;0;3 'disks.unknown.count'=0;;;0;3
|
||||
... 10 --critical-status='' --warning-status='' --critical-disks-failed=:0 CRITICAL: Disks failed: 1 | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;;;0;3 'disks.new.count'=0;;;0;3 'disks.failed.count'=1;;0:0;0;3 'disks.unknown.count'=0;;;0;3
|
||||
... 11 --critical-status='' --warning-status='' --critical-disks-unknown=@0:0 CRITICAL: Disks unknown: 0 | 'disks.total.count'=3;;;0; 'disks.normal.count'=1;;;0;3 'disks.degraded.count'=1;;;0;3 'disks.new.count'=0;;;0;3 'disks.failed.count'=1;;;0;3 'disks.unknown.count'=0;@0:0;;0;3
|
46
tests/storage/hp/alletra/restapi/hpe-alletra-diskusage.robot
Normal file
46
tests/storage/hp/alletra/restapi/hpe-alletra-diskusage.robot
Normal file
@ -0,0 +1,46 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Disk Usage
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode disk-usage
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
DiskUsage ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} OK: Total Used: 28.04 TB / 41.91 TB, Total percentage used: 66.91 %, Total Free: 13.87 TB - All disks are ok | 'disks.total.space.usage.bytes'=30830348992512;;;0;46076409151488 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=15246060158976;;;0;46076409151488 '0#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.usage.percentage'=66.91%;;;0;100 '1#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.usage.percentage'=66.91%;;;0;100 '2#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '2#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '2#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 2 --filter-id='^0$' OK: Total Used: 9.35 TB / 13.97 TB, Total percentage used: 66.91 %, Total Free: 4.62 TB - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | 'disks.total.space.usage.bytes'=10276782997504;;;0;15358803050496 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=5082020052992;;;0;15358803050496 '0#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 3 --filter-manufacturer='X1$' OK: Total Used: 9.35 TB / 13.97 TB, Total percentage used: 66.91 %, Total Free: 4.62 TB - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | 'disks.total.space.usage.bytes'=10276782997504;;;0;15358803050496 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=5082020052992;;;0;15358803050496 '0#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 4 --filter-model='X1$' OK: Total Used: 9.35 TB / 13.97 TB, Total percentage used: 66.91 %, Total Free: 4.62 TB - Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | 'disks.total.space.usage.bytes'=10276782997504;;;0;15358803050496 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=5082020052992;;;0;15358803050496 '0#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '0#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 5 --filter-serial='X2$' OK: Total Used: 9.35 TB / 13.97 TB, Total percentage used: 66.91 %, Total Free: 4.62 TB - Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | 'disks.total.space.usage.bytes'=10276782997504;;;0;15358803050496 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=5082020052992;;;0;15358803050496 '1#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 6 --filter-position=1:2 OK: Total Used: 9.35 TB / 13.97 TB, Total percentage used: 66.91 %, Total Free: 4.62 TB - Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | 'disks.total.space.usage.bytes'=10276782997504;;;0;15358803050496 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 'disks.total.space.free.bytes'=5082020052992;;;0;15358803050496 '1#disk.space.usage.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.free.bytes'=10276782997504B;;;0;15358803050496 '1#disk.space.usage.percentage'=66.91%;;;0;100
|
||||
... 7 --filter-counters='^usage$' --critical-usage=:10 CRITICAL: Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) - Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) - Disk #2 (XXX3/XXX3, serial: XXX3) located 1:3 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | '0#disk.space.usage.bytes'=10276782997504B;;0:10;0;15358803050496 '1#disk.space.usage.bytes'=10276782997504B;;0:10;0;15358803050496 '2#disk.space.usage.bytes'=10276782997504B;;0:10;0;15358803050496
|
||||
... 8 --filter-counters='usage-free' --critical-usage-free=:10 CRITICAL: Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) - Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) - Disk #2 (XXX3/XXX3, serial: XXX3) located 1:3 has Used: 9.35 TB of 13.97 TB (66.91%) Free: 4.62 TB (33.09%) | '0#disk.space.free.bytes'=10276782997504B;;0:10;0;15358803050496 '1#disk.space.free.bytes'=10276782997504B;;0:10;0;15358803050496 '2#disk.space.free.bytes'=10276782997504B;;0:10;0;15358803050496
|
||||
... 9 --filter-counters='usage-prct' --warning-usage-prct=:10 WARNING: Disk #0 (XXXX1/XXXXXX1, serial: XXXXX1) located 1:1 has Used : 66.91 % - Disk #1 (XXXX2/XXXX2, serial: XXXX2) located 1:2 has Used : 66.91 % - Disk #2 (XXX3/XXX3, serial: XXX3) located 1:3 has Used : 66.91 % | 'disks.total.space.usage.percent'=66.9113534675615;;;0;100 '0#disk.space.usage.percentage'=66.91%;0:10;;0;100 '1#disk.space.usage.percentage'=66.91%;0:10;;0;100 '2#disk.space.usage.percentage'=66.91%;0:10;;0;100
|
||||
... 10 --filter-counters='total-free' --warning-total-free=:10 WARNING: Total Free: 13.87 TB | 'disks.total.space.free.bytes'=15246060158976;0:10;;0;46076409151488
|
||||
... 11 --filter-counters='total-usage' --warning-total-usage=:10 WARNING: Total Used: 28.04 TB / 41.91 TB | 'disks.total.space.usage.bytes'=30830348992512;0:10;;0;46076409151488 'disks.total.space.usage.percent'=66.9113534675615;;;0;100
|
||||
... 12 --filter-counters='total-usage-prct' --critical-total-usage-prct=:60 CRITICAL: Total percentage used: 66.91 % | 'disks.total.space.usage.percent'=66.9113534675615;;0:60;0;100
|
39
tests/storage/hp/alletra/restapi/hpe-alletra-licenses.robot
Normal file
39
tests/storage/hp/alletra/restapi/hpe-alletra-licenses.robot
Normal file
@ -0,0 +1,39 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Licenses
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode licenses
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
Licenses ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} CRITICAL: Number of expired licenses: 1 | 'licenses.total.count'=9;;0:;0; 'licenses.expired.count'=1;;0:0;0;1 'LICENSE 2#license.expiration.seconds'=0s;;;0; 'LICENSE 3#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 5#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 6#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 8#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 9#license.expiration.seconds'=(\\\\d+)s;;;0;
|
||||
... 2 --filter-counters=license-expiration OK: All licenses are ok | 'LICENSE 2#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 3#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 5#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 6#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 8#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 9#license.expiration.seconds'=(\\\\d+)s;;;0;
|
||||
... 3 --warning-total=10: --critical-expired='' WARNING: Number of licenses: 9 | 'licenses.total.count'=9;10:;;0; 'licenses.expired.count'=0;;;0;9 'LICENSE 2#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 3#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 5#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 6#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 8#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 9#license.expiration.seconds'=(\\\\d+)s;;;0;
|
||||
... 4 --critical-expired='' --warning-expired=':0' WARNING: Number of expired licenses: 1 | 'licenses.total.count'=9;;0:;0; 'licenses.expired.count'=1;0:0;;0;1 'LICENSE 2#license.expiration.seconds'=0s;;;0; 'LICENSE 3#license.expiration.seconds'(\\\\d+)s;;;0; 'LICENSE 5#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 6#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 8#license.expiration.seconds'=(\\\\d+)s;;;0; 'LICENSE 9#license.expiration.seconds'=(\\\\d+)s;;;0;
|
||||
... 5 --critical-expired='' --warning-license-expiration='1:' WARNING: License 'LICENSE 1' expires: never. LICENSE 1 has permanent license. - License 'LICENSE 2' expires: 2020-04-20T02:00:00+02:00. LICENSE 2 license has expired. - License 'LICENSE 4' expires: never. LICENSE 4 has permanent license. - License 'LICENSE 7' expires: never. LICENSE 7 has permanent license. | 'licenses.total.count'=9;;1:;0; 'licenses.expired.count'=1;;;0;9 'LICENSE 2#license.expiration.seconds'=0s;1:;;0; 'LICENSE 3#license.expiration.seconds'=(\\\\d+)s;1:;;0; 'LICENSE 5#license.expiration.seconds'=(\\\\d+)s;1:;;0; 'LICENSE 6#license.expiration.seconds'=(\\\\d+)s;1:;;0; 'LICENSE 8#license.expiration.seconds'=(\\\\d+)s;1:;;0; 'LICENSE 9#license.expiration.seconds'=(\\\\d+)s;1:;;0;
|
38
tests/storage/hp/alletra/restapi/hpe-alletra-listdisks.robot
Normal file
38
tests/storage/hp/alletra/restapi/hpe-alletra-listdisks.robot
Normal file
@ -0,0 +1,38 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode List Disks
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode list-disks
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
ListDisks ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} ^Disks: (\\\\n\\\\[id:.*\\\\]){3}\\\\Z
|
||||
... 2 --filter-type=SLC ^Disks: (\\\\n\\\\[id:.*\\\\]){1}\\\\Z
|
||||
... 3 --filter-id=1 ^Disks: (\\\\n\\\\[id:.*\\\\]){1}\\\\Z
|
||||
... 4 --filter-protocol=SATA ^Disks: (\\\\n\\\\[id:.*\\\\]){1}\\\\Z
|
@ -0,0 +1,37 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode List Volumes
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode list-volumes
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
ListVolumes ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Regexp ${command} ${expected_regexp}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_regexp --
|
||||
... 1 ${EMPTY} ^Volumes: (\\\\n\\\\[id:.*\\\\]){3}\\\\Z
|
||||
... 2 --filter-name='^test$' ^Volumes: (\\\\n\\\\[id:.*\\\\]){1}\\\\Z
|
||||
... 3 --filter-id=1 ^Volumes: (\\\\n\\\\[id:.*\\\\]){1}\\\\Z
|
@ -0,0 +1,42 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Volume Status
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode volume-status
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
VolumeStatus ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Strings ${command} ${expected_string}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_string --
|
||||
... 1 ${EMPTY} CRITICAL: Volume #2 (mtest) uuid: AEZDSSFDDSD (readonly: 0, compression: NA, provisioning: FULL) WARNING: Volume #1 (stest) uuid: SFFDSDDSDSD (readonly: 0, compression: NA, provisioning: FULL) | 'volumes.total.count'=3;;;0; 'volumes.normal.count'=1;;;0;3 'volumes.degraded.count'=1;;;0;3 'volumes.failed.count'=1;;;0;3 'volumes.unknown.count'=0;;;0;3
|
||||
... 2 --critical-status='' --warning-status='' --warning-volumes-total=4: --filter-counters=volumes-total WARNING: Volumes total: 3 | 'volumes.total.count'=3;4:;;0;
|
||||
... 3 --mode=volume-status --critical-status='' --warning-status='' --warning-volumes-normal=:0 --filter-counters=volumes-normal WARNING: Volumes normal: 1 | 'volumes.normal.count'=1;0:0;;0;3
|
||||
... 4 --critical-status='' --warning-status='' --warning-volumes-degraded=:0 --filter-counters=volumes-degraded WARNING: Volumes degraded: 1 | 'volumes.degraded.count'=1;0:0;;0;3
|
||||
... 5 --critical-status='' --warning-status='' --warning-volumes-failed=:0 --filter-counters=volumes-failed WARNING: Volumes failed: 1 | 'volumes.failed.count'=1;0:0;;0;3
|
||||
... 6 --critical-status='' --warning-status='' --critical-volumes-unknown=@0:0 --filter-counters=volumes-unknown CRITICAL: Volumes unknown: 0 | 'volumes.unknown.count'=0;;@0:0;0;3
|
||||
... 7 --filter-name=mtest CRITICAL: Volume #2 (mtest) uuid: AEZDSSFDDSD (readonly: 0, compression: NA, provisioning: FULL) | 'volumes.total.count'=1;;;0; 'volumes.normal.count'=0;;;0;1 'volumes.degraded.count'=0;;;0;1 'volumes.failed.count'=1;;;0;1 'volumes.unknown.count'=0;;;0;1
|
||||
... 8 --filter-id=0 OK: Volumes total: 1, normal: 1, degraded: 0, failed: 0, unknown: 0 - Volume #0 (test) uuid: ZAZZAZZA (readonly: 0, compression: NA, provisioning: FULL) | 'volumes.total.count'=1;;;0; 'volumes.normal.count'=1;;;0;1 'volumes.degraded.count'=0;;;0;1 'volumes.failed.count'=0;;;0;1 'volumes.unknown.count'=0;;;0;1
|
@ -0,0 +1,40 @@
|
||||
*** Settings ***
|
||||
Documentation HPE Alletra Storage REST API Mode Volume Usage
|
||||
|
||||
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
|
||||
|
||||
Suite Setup Start Mockoon ${MOCKOON_JSON}
|
||||
Suite Teardown Stop Mockoon
|
||||
Test Timeout 120s
|
||||
|
||||
|
||||
*** Variables ***
|
||||
${MOCKOON_JSON} ${CURDIR}${/}hpe-alletra.mockoon.json
|
||||
${HOSTNAME} 127.0.0.1
|
||||
${APIPORT} 3000
|
||||
${CMD} ${CENTREON_PLUGINS}
|
||||
... --plugin=storage::hp::alletra::restapi::plugin
|
||||
... --mode volume-usage
|
||||
... --hostname=${HOSTNAME}
|
||||
... --api-username=xx
|
||||
... --api-password=xx
|
||||
... --proto=http
|
||||
... --port=${APIPORT}
|
||||
|
||||
*** Test Cases ***
|
||||
VolumeUsage ${tc}
|
||||
[Tags] storage api hpe hp
|
||||
${command} Catenate
|
||||
... ${CMD}
|
||||
... ${extra_options}
|
||||
|
||||
Ctn Run Command And Check Result As Strings ${command} ${expected_string}
|
||||
|
||||
|
||||
Examples: tc extraoptions expected_string --
|
||||
... 1 ${EMPTY} OK: All volumes are ok | 'mtest#volume.space.usage.bytes'=549755813888B;;;0;549755813888 'mtest#volume.space.free.bytes'=0B;;;0;549755813888 'mtest#volume.space.usage.percentage'=100.00%;;;0;100 'stest#volume.space.usage.bytes'=23991418880B;;;0;128849018880 'stest#volume.space.free.bytes'=104857600000B;;;0;128849018880 'stest#volume.space.usage.percentage'=18.62%;;;0;100 'test#volume.space.usage.bytes'=10737418240B;;;0;10737418240 'test#volume.space.free.bytes'=0B;;;0;10737418240 'test#volume.space.usage.percentage'=100.00%;;;0;100
|
||||
... 2 --filter-id=1 OK: Volume 'stest' (#1) Total: 120.00 GB Reserved: 120.00 GB Used: 22.34 GB (18.62%) Free: 97.66 GB (81.38%) | 'stest#volume.space.usage.bytes'=23991418880B;;;0;128849018880 'stest#volume.space.free.bytes'=104857600000B;;;0;128849018880 'stest#volume.space.usage.percentage'=18.62%;;;0;100
|
||||
... 3 --filter-name=mtest OK: Volume 'mtest' (#2) Total: 512.00 GB Reserved: 512.00 GB Used: 512.00 GB (100.00%) Free: 0.00 B (0.00%) | 'mtest#volume.space.usage.bytes'=549755813888B;;;0;549755813888 'mtest#volume.space.free.bytes'=0B;;;0;549755813888 'mtest#volume.space.usage.percentage'=100.00%;;;0;100
|
||||
... 4 --filter-counters=usage-prct --critical-usage-prct=90 CRITICAL: Volume 'mtest' (#2) Used : 100.00 % - Volume 'test' (#0) Used : 100.00 % | 'mtest#volume.space.usage.percentage'=100.00%;;0:90;0;100 'stest#volume.space.usage.percentage'=18.62%;;0:90;0;100 'test#volume.space.usage.percentage'=100.00%;;0:90;0;100
|
||||
... 5 --filter-counters=usage-free --critical-usage-free=:10 CRITICAL: Volume 'stest' (#1) Total: 120.00 GB Reserved: 120.00 GB Used: 22.34 GB (18.62%) Free: 97.66 GB (81.38%) | 'mtest#volume.space.free.bytes'=0B;;0:10;0;549755813888 'stest#volume.space.free.bytes'=104857600000B;;0:10;0;128849018880 'test#volume.space.free.bytes'=0B;;0:10;0;10737418240
|
||||
... 6 --filter-counters='^usage$' --warning-usage=:10 WARNING: Volume 'mtest' (#2) Total: 512.00 GB Reserved: 512.00 GB Used: 512.00 GB (100.00%) Free: 0.00 B (0.00%) - Volume 'stest' (#1) Total: 120.00 GB Reserved: 120.00 GB Used: 22.34 GB (18.62%) Free: 97.66 GB (81.38%) - Volume 'test' (#0) Total: 10.00 GB Reserved: 10.00 GB Used: 10.00 GB (100.00%) Free: 0.00 B (0.00%) | 'mtest#volume.space.usage.bytes'=549755813888B;0:10;;0;549755813888 'stest#volume.space.usage.bytes'=23991418880B;0:10;;0;128849018880 'test#volume.space.usage.bytes'=10737418240B;0:10;;0;10737418240
|
259
tests/storage/hp/alletra/restapi/hpe-alletra.mockoon.json
Normal file
259
tests/storage/hp/alletra/restapi/hpe-alletra.mockoon.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user