add netapp restapi plugin
This commit is contained in:
parent
e0414e65bc
commit
1f4b834066
|
@ -0,0 +1,263 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::custom::restapi;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::http;
|
||||
use JSON::XS;
|
||||
use URI::Encode;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = {};
|
||||
bless $self, $class;
|
||||
|
||||
if (!defined($options{output})) {
|
||||
print "Class Custom: Need to specify 'output' argument.\n";
|
||||
exit 3;
|
||||
}
|
||||
if (!defined($options{options})) {
|
||||
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
|
||||
$options{output}->option_exit();
|
||||
}
|
||||
|
||||
if (!defined($options{noptions})) {
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"hostname:s@" => { name => 'hostname' },
|
||||
"url-path:s@" => { name => 'url_path' },
|
||||
"port:s@" => { name => 'port' },
|
||||
"proto:s@" => { name => 'proto' },
|
||||
"username:s@" => { name => 'username' },
|
||||
"password:s@" => { name => 'password' },
|
||||
"proxyurl:s@" => { name => 'proxyurl' },
|
||||
"timeout:s@" => { name => 'timeout' },
|
||||
"ssl:s@" => { name => 'ssl' },
|
||||
});
|
||||
}
|
||||
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
|
||||
|
||||
$self->{output} = $options{output};
|
||||
$self->{mode} = $options{mode};
|
||||
$self->{http} = centreon::plugins::http->new(output => $self->{output});
|
||||
|
||||
return $self;
|
||||
|
||||
}
|
||||
|
||||
sub set_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{option_results} = $options{option_results};
|
||||
}
|
||||
|
||||
sub set_defaults {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach (keys %{$options{default}}) {
|
||||
if ($_ eq $self->{mode}) {
|
||||
for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) {
|
||||
foreach my $opt (keys %{$options{default}->{$_}[$i]}) {
|
||||
if (!defined($self->{option_results}->{$opt}[$i])) {
|
||||
$self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef;
|
||||
$self->{url_path} = (defined($self->{option_results}->{url_path})) ? shift(@{$self->{option_results}->{url_path}}) : '/api/4.0/ontap';
|
||||
$self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 8443;
|
||||
$self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'https';
|
||||
$self->{username} = (defined($self->{option_results}->{username})) ? shift(@{$self->{option_results}->{username}}) : '';
|
||||
$self->{password} = (defined($self->{option_results}->{password})) ? shift(@{$self->{option_results}->{password}}) : '';
|
||||
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10;
|
||||
$self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? shift(@{$self->{option_results}->{proxyurl}}) : undef;
|
||||
$self->{ssl} = (defined($self->{option_results}->{ssl})) ? shift(@{$self->{option_results}->{ssl}}) : 'tlsv1';
|
||||
|
||||
if (!defined($self->{hostname})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to specify hostname option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
if (!defined($self->{hostname}) ||
|
||||
scalar(@{$self->{option_results}->{hostname}}) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub build_options_for_httplib {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{option_results}->{hostname} = $self->{hostname};
|
||||
$self->{option_results}->{timeout} = $self->{timeout};
|
||||
$self->{option_results}->{port} = $self->{port};
|
||||
$self->{option_results}->{proto} = $self->{proto};
|
||||
$self->{option_results}->{proxyurl} = $self->{proxyurl};
|
||||
$self->{option_results}->{credentials} = 1;
|
||||
$self->{option_results}->{username} = $self->{username};
|
||||
$self->{option_results}->{password} = $self->{password};
|
||||
$self->{option_results}->{ssl} = $self->{ssl};
|
||||
$self->{option_results}->{warning_status} = '';
|
||||
$self->{option_results}->{critical_status} = '';
|
||||
}
|
||||
|
||||
sub settings {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->build_options_for_httplib();
|
||||
$self->{http}->set_options(%{$self->{option_results}});
|
||||
}
|
||||
|
||||
sub get_connection_info {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return $self->{hostname} . ":" . $self->{port};
|
||||
}
|
||||
|
||||
sub get_objects {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my %objects;
|
||||
my $objects = $self->get(%options);
|
||||
foreach my $object (@{$objects}) {
|
||||
$objects{$object->{$options{key}}} = $object->{$options{name}};
|
||||
}
|
||||
|
||||
return \%objects;
|
||||
}
|
||||
|
||||
sub get_next {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $encoded_tag = '';
|
||||
if (defined($options{nextTag})) {
|
||||
my $uri = URI::Encode->new({encode_reserved => 1});
|
||||
$encoded_tag = "nextTag=" . $uri->encode($options{nextTag});
|
||||
}
|
||||
|
||||
my $url_path = $self->{url_path} . $options{path};
|
||||
$url_path .= '?' . $options{uri} if (defined($options{args}));
|
||||
$url_path .= '?' . $encoded_tag if (defined($options{nextTag}) && !defined($options{args}));
|
||||
$url_path .= '&' . $encoded_tag if (defined($options{nextTag}) && defined($options{args}));
|
||||
|
||||
my $response = $self->{http}->request(url_path => $url_path);
|
||||
|
||||
my $content;
|
||||
eval {
|
||||
$content = JSON::XS->new->utf8->decode($response);
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
if (defined($content->{errmsg})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot get data: " . $content->{errmsg});
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
sub get {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->settings();
|
||||
|
||||
my @result;
|
||||
while(my $content = $self->get_next(%options)) {
|
||||
push @result, @{$content->{result}->{records}};
|
||||
|
||||
last if (!defined($content->{result}->{nextTag}));
|
||||
$options{nextTag} = $content->{result}->{nextTag};
|
||||
}
|
||||
|
||||
return \@result;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
NetApp OnCommand REST API
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
NetApp OnCommand Rest API custom mode
|
||||
|
||||
=head1 REST API OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--hostname>
|
||||
|
||||
NetApp hostname.
|
||||
|
||||
=item B<--url-path>
|
||||
|
||||
OnCommand API url path (Default: '/api/4.0/ontap')
|
||||
|
||||
=item B<--port>
|
||||
|
||||
OnCommand API port (Default: 8443)
|
||||
|
||||
=item B<--proto>
|
||||
|
||||
Specify https if needed (Default: 'https')
|
||||
|
||||
=item B<--username>
|
||||
|
||||
OnCommand API username.
|
||||
|
||||
=item B<--password>
|
||||
|
||||
OnCommand API password.
|
||||
|
||||
=item B<--proxyurl>
|
||||
|
||||
Proxy URL if any
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Set HTTP timeout
|
||||
|
||||
=item B<--ssl>
|
||||
|
||||
SSL version (Default: tlsv1)
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<custom>.
|
||||
|
||||
=cut
|
|
@ -0,0 +1,210 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::aggregateraidstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Raid status is '%s' [type: %s] [size: %s]",
|
||||
$self->{result_values}->{status}, $self->{result_values}->{type}, $self->{result_values}->{size});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_raid_status'};
|
||||
$self->{result_values}->{type} = $options{new_datas}->{$self->{instance} . '_raid_type'};
|
||||
$self->{result_values}->{size} = $options{new_datas}->{$self->{instance} . '_raid_size'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Aggregate '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'aggregates', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All aggregates raid status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{aggregates} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'raid_status' }, { name => 'raid_type' }, { name => 'raid_size' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /normal/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
my $nodes;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '') {
|
||||
$nodes = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/aggregates');
|
||||
|
||||
foreach my $aggregate (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$aggregate->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($nodes->{$aggregate->{node_key}}) && $nodes->{$aggregate->{node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter node '" . $nodes->{$aggregate->{node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$aggregate->{cluster_key}}) && $clusters->{$aggregate->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter cluster '" . $clusters->{$aggregate->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{aggregates}->{$aggregate->{key}} = {
|
||||
name => $aggregate->{name},
|
||||
raid_status => $aggregate->{raid_status},
|
||||
raid_type => $aggregate->{raid_type},
|
||||
raid_size => $aggregate->{raid_size},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{aggregates}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp aggregates raid status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter volume.
|
||||
Can be: 'name', 'node', 'cluster' (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{status}, %{type}, %{size}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{status} !~ /normal/i').
|
||||
Can used special variables like: %{status}, %{type}, %{size}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,208 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::aggregatestatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("State is '%s', Mirror status is '%s'",
|
||||
$self->{result_values}->{state}, $self->{result_values}->{mirror_status});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'};
|
||||
$self->{result_values}->{mirror_status} = $options{new_datas}->{$self->{instance} . '_mirror_status'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Aggregate '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'aggregates', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All aggregates status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{aggregates} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'state' }, { name => 'mirror_status' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{state} !~ /online/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
my $nodes;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '') {
|
||||
$nodes = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/aggregates');
|
||||
|
||||
foreach my $aggregate (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$aggregate->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($nodes->{$aggregate->{node_key}}) && $nodes->{$aggregate->{node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter node '" . $nodes->{$aggregate->{node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$aggregate->{cluster_key}}) && $clusters->{$aggregate->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter cluster '" . $clusters->{$aggregate->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{aggregates}->{$aggregate->{key}} = {
|
||||
name => $aggregate->{name},
|
||||
state => $aggregate->{state},
|
||||
mirror_status => $aggregate->{mirror_status},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{aggregates}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp aggregates status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter aggregate.
|
||||
Can be: 'name', 'node', 'cluster' (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}, %{mirror_status}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{state} !~ /online/i').
|
||||
Can used special variables like: %{state}, %{mirror_status}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,315 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::aggregateusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_usage_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'used' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_usage_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
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 ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
|
||||
my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_usage_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size_total'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_size_used'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_snapshot_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'snapshot' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_snapshot_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_snapshot_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
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 ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
|
||||
my $msg = sprintf("Snapshot Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_snapshot_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_snapshot_size_total'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_snapshot_size_used'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Aggregate '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'aggregates', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All aggregates usage are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{aggregates} = [
|
||||
{ label => 'usage', set => {
|
||||
key_values => [ { name => 'size_used' }, { name => 'size_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_usage_calc'),
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'snapshot', set => {
|
||||
key_values => [ { name => 'snapshot_size_used' }, { name => 'snapshot_size_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_snapshot_calc'),
|
||||
closure_custom_output => $self->can('custom_snapshot_output'),
|
||||
closure_custom_perfdata => $self->can('custom_snapshot_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_snapshot_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
"filter-state:s" => { name => 'filter_state' },
|
||||
"filter-type:s" => { name => 'filter_type' },
|
||||
"units:s" => { name => 'units', default => '%' },
|
||||
"free" => { name => 'free' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
my $nodes;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '') {
|
||||
$nodes = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/aggregates');
|
||||
|
||||
foreach my $aggregate (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$aggregate->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' &&
|
||||
$aggregate->{state} !~ /$self->{option_results}->{filter_state}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter state : '" . $aggregate->{state} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
|
||||
$aggregate->{aggregate_type} !~ /$self->{option_results}->{filter_type}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter type : '" . $aggregate->{vol_type} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($nodes->{$aggregate->{node_key}}) && $nodes->{$aggregate->{node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter node '" . $nodes->{$aggregate->{node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$aggregate->{cluster_key}}) && $clusters->{$aggregate->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter cluster '" . $clusters->{$aggregate->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{aggregates}->{$aggregate->{key}} = {
|
||||
name => $aggregate->{name},
|
||||
size_total => $aggregate->{size_total},
|
||||
size_used => $aggregate->{size_used},
|
||||
snapshot_size_total => $aggregate->{snapshot_size_total},
|
||||
snapshot_size_used => $aggregate->{snapshot_size_used},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{aggregates}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp aggregates usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter volume.
|
||||
Can be: 'name', 'node', 'cluster', 'state', 'type' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'usage', 'snapshot'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'usage', 'snapshot'.
|
||||
|
||||
=item B<--units>
|
||||
|
||||
Units of thresholds (Default: '%') ('%', 'B').
|
||||
|
||||
=item B<--free>
|
||||
|
||||
Thresholds are on free space left.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,149 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::clusterio;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Cluster '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'clusters', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All clusters IOs are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{clusters} = [
|
||||
{ label => 'total-throughput', set => {
|
||||
key_values => [ { name => 'total_throughput' }, { name => 'name' } ],
|
||||
output_template => 'Total throughput: %.2f %s/s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{ label => 'total_throughput', value => 'total_throughput_absolute', template => '%.2f',
|
||||
min => 0, unit => 'B/s', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'total-ops', set => {
|
||||
key_values => [ { name => 'total_ops' }, { name => 'name' } ],
|
||||
output_template => 'Total IOPS: %.2f ops/s',
|
||||
perfdatas => [
|
||||
{ label => 'total_ops', value => 'total_ops_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my %names_hash;
|
||||
my $names = $options{custom}->get(path => '/clusters');
|
||||
foreach my $cluster (@{$names}) {
|
||||
$names_hash{$cluster->{key}} = {
|
||||
name => $cluster->{name},
|
||||
};
|
||||
}
|
||||
|
||||
my $args = '';
|
||||
my $append = '';
|
||||
foreach my $metric ('total_ops', 'total_throughput') {
|
||||
$args .= $append . 'name=' . $metric;
|
||||
$append = '&';
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/clusters/metrics', args => $args);
|
||||
|
||||
foreach my $cluster (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
defined($names_hash{$cluster->{resource_key}}) && $names_hash{$cluster->{resource_key}}->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$cluster->{resource_key}}->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
foreach my $metric (@{$cluster->{metrics}}) {
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{name} = $names_hash{$cluster->{resource_key}}->{name};
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{total_ops} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'total_ops');
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{total_throughput} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'total_throughput');
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{clusters}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp clusters IOs.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'total-throughput', 'total-ops'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'total-throughput', 'total-ops'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,186 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::clusterstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s'", $self->{result_values}->{status});
|
||||
$msg .= sprintf(", Metro Cluster is '%s' [mode: %s]",
|
||||
$self->{result_values}->{metro_cluster_configuration_state},
|
||||
$self->{result_values}->{metro_cluster_mode}) if ($self->{result_values}->{metro_cluster_configuration_state} !~ /-/);
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
|
||||
$self->{result_values}->{metro_cluster_mode} = $options{new_datas}->{$self->{instance} . '_metro_cluster_mode'};
|
||||
$self->{result_values}->{metro_cluster_configuration_state} = $options{new_datas}->{$self->{instance} . '_metro_cluster_configuration_state'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Cluster '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'clusters', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All clusters status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{clusters} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'status' }, { name => 'metro_cluster_mode' }, { name => 'metro_cluster_configuration_state' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /ok/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/clusters');
|
||||
|
||||
foreach my $cluster (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$cluster->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $cluster->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{clusters}->{$cluster->{key}} = {
|
||||
name => $cluster->{name},
|
||||
status => $cluster->{status},
|
||||
metro_cluster_mode => defined($cluster->{metro_cluster_mode}) ? $cluster->{metro_cluster_mode} : "-",
|
||||
metro_cluster_configuration_state => defined($cluster->{metro_cluster_configuration_state}) ? $cluster->{metro_cluster_configuration_state} : "-",
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{clusters}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp clusters status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{status}, %{metro_cluster_mode}, %{metro_cluster_configuration_state}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{status} !~ /ok/i').
|
||||
Can used special variables like: %{status}, %{metro_cluster_mode}, %{metro_cluster_configuration_state}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,148 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::clusterusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Cluster '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'clusters', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All clusters usage are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{clusters} = [
|
||||
{ label => 'max-node-utilization', set => {
|
||||
key_values => [ { name => 'max_node_utilization' }, { name => 'name' } ],
|
||||
output_template => 'Node utilization: %.2f %%',
|
||||
perfdatas => [
|
||||
{ label => 'max_node_utilization', value => 'max_node_utilization_absolute', template => '%.2f',
|
||||
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'max-aggregate-utilization', set => {
|
||||
key_values => [ { name => 'max_aggregate_utilization' }, { name => 'name' } ],
|
||||
output_template => 'Aggregate utilization: %.2f %%',
|
||||
perfdatas => [
|
||||
{ label => 'max_aggregate_utilization', value => 'max_aggregate_utilization_absolute', template => '%.2f',
|
||||
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my %names_hash;
|
||||
my $names = $options{custom}->get(path => '/clusters');
|
||||
foreach my $cluster (@{$names}) {
|
||||
$names_hash{$cluster->{key}} = {
|
||||
name => $cluster->{name},
|
||||
};
|
||||
}
|
||||
|
||||
my $args = '';
|
||||
my $append = '';
|
||||
foreach my $metric ('max_node_utilization', 'max_aggregate_utilization') {
|
||||
$args .= $append . 'name=' . $metric;
|
||||
$append = '&';
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/clusters/metrics', args => $args);
|
||||
|
||||
foreach my $cluster (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
defined($names_hash{$cluster->{resource_key}}) && $names_hash{$cluster->{resource_key}}->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$cluster->{resource_key}}->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
foreach my $metric (@{$cluster->{metrics}}) {
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{name} = $names_hash{$cluster->{resource_key}}->{name};
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{max_node_utilization} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'max_node_utilization');
|
||||
$self->{clusters}->{$cluster->{resource_key}}->{max_aggregate_utilization} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'max_aggregate_utilization');
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{clusters}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp clusters usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'max-node-utilization', 'max-aggregate-utilization'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'max-node-utilization', 'max-aggregate-utilization'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,147 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::diskfailed;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'disks', type => 0},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{disks} = [
|
||||
{ label => 'failed', set => {
|
||||
key_values => [ { name => 'failed' } ],
|
||||
output_template => 'Failed disks: %d',
|
||||
perfdatas => [
|
||||
{ label => 'failed', value => 'failed_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'pre-failed', set => {
|
||||
key_values => [ { name => 'pre_failed' } ],
|
||||
output_template => 'Pre-failed disks: %d',
|
||||
perfdatas => [
|
||||
{ label => 'pre_failed', value => 'pre_failed_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
my $nodes;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '') {
|
||||
$nodes = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/disks');
|
||||
|
||||
$self->{disks}->{failed} = 0;
|
||||
$self->{disks}->{pre_failed} = 0;
|
||||
|
||||
foreach my $disk (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($nodes->{$disk->{owner_node_key}}) && $nodes->{$disk->{owner_node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $disk->{name} . "': no matching filter node '" . $nodes->{$disk->{owner_node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$disk->{cluster_key}}) && $clusters->{$disk->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $disk->{name} . "': no matching filter cluster '" . $clusters->{$disk->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if ($disk->{is_failed}) {
|
||||
$self->{disks}->{failed}++;
|
||||
$self->{output}->output_add(long_msg => "Disk '" . $disk->{name} . "' from cluster '" . $clusters->{$disk->{cluster_key}} . "' is in 'failed' state (reason: '" . $disk->{failed_reason} . "') [shelf: " . $disk->{shelf} . "] [serial_number: " . $disk->{serial_number} . "] [model: " . $disk->{model} . "]");
|
||||
}
|
||||
if ($disk->{is_prefailed}) {
|
||||
$self->{disks}->{pre_failed}++;
|
||||
$self->{output}->output_add(long_msg => "Disk '" . $disk->{name} . "' from cluster '" . $clusters->{$disk->{cluster_key}} . "' is in 'pre-failed' state [shelf: " . $disk->{shelf} . "] [serial_number: " . $disk->{serial_number} . "] [model: " . $disk->{model} . "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp failed disks.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter disk.
|
||||
Can be: 'node', 'cluster' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'failed', 'pre-failed'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'failed', 'pre-failed'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,161 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::diskspare;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'disks', type => 0},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{disks} = [
|
||||
{ label => 'spare', set => {
|
||||
key_values => [ { name => 'spare' } ],
|
||||
output_template => 'Spare disks: %d',
|
||||
perfdatas => [
|
||||
{ label => 'spare', value => 'spare_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'zeroed', set => {
|
||||
key_values => [ { name => 'zeroed' } ],
|
||||
output_template => 'Zeroed disks: %d',
|
||||
perfdatas => [
|
||||
{ label => 'zeroed', value => 'zeroed_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'not-zeroed', set => {
|
||||
key_values => [ { name => 'not_zeroed' } ],
|
||||
output_template => 'Not zeroed disks: %d',
|
||||
perfdatas => [
|
||||
{ label => 'not_zeroed', value => 'not_zeroed_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
my $nodes;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '') {
|
||||
$nodes = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/disks');
|
||||
|
||||
$self->{disks}->{spare} = 0;
|
||||
$self->{disks}->{zeroed} = 0;
|
||||
$self->{disks}->{not_zeroed} = 0;
|
||||
|
||||
foreach my $disk (@{$result}) {
|
||||
next if ($disk->{container_type} !~ /spare/i);
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($nodes->{$disk->{owner_node_key}}) && $nodes->{$disk->{owner_node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $disk->{name} . "': no matching filter node '" . $nodes->{$disk->{owner_node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$disk->{cluster_key}}) && $clusters->{$disk->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $disk->{name} . "': no matching filter cluster '" . $clusters->{$disk->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{disks}->{spare}++;
|
||||
$self->{disks}->{zeroed}++ if ($disk->{is_zeroed});
|
||||
if (!$disk->{is_zeroed}) {
|
||||
$self->{disks}->{not_zeroed}++;
|
||||
|
||||
my $long_msg = "Spare disk '" . $disk->{name} . "' is not in 'zeroed' state [shelf: " . $disk->{shelf} . "]";
|
||||
$long_msg .= " [node: " . $nodes->{$disk->{owner_node_key}} . "]" if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '');
|
||||
$long_msg .= " [cluster: " . $clusters->{$disk->{cluster_key}} . "]" if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '');
|
||||
$self->{output}->output_add(long_msg => $long_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp spare disks.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter disk.
|
||||
Can be: 'node', 'cluster' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'spare', 'zeroed', 'not-zeroed'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'spare', 'zeroed', 'not-zeroed'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,191 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::fcportstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s', State is '%s' [adapter: %s] [switch port: %s] [fabric established: %s]",
|
||||
$self->{result_values}->{status}, $self->{result_values}->{state},
|
||||
$self->{result_values}->{adapter}, $self->{result_values}->{switch_port},
|
||||
$self->{result_values}->{fabric_established});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_wwpn'};
|
||||
$self->{result_values}->{adapter} = $options{new_datas}->{$self->{instance} . '_adapter'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
|
||||
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'};
|
||||
$self->{result_values}->{switch_port} = $options{new_datas}->{$self->{instance} . '_switch_port'};
|
||||
$self->{result_values}->{fabric_established} = ($options{new_datas}->{$self->{instance} . '_fabric_established'}) ? "true" : "false";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "FC port '" . $options{instance_value}->{wwpn} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'fcports', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All FC ports status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{fcports} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'wwpn' }, { name => 'status' }, { name => 'state' }, { name => 'switch_port' }, { name => 'fabric_established' }, { name => 'adapter' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /online/i || %{state} !~ /online/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/fc-ports');
|
||||
|
||||
foreach my $fcport (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$fcport->{wwpn} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $fcport->{wwpn} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{fcports}->{$fcport->{key}} = {
|
||||
wwpn => $fcport->{wwpn},
|
||||
adapter => $fcport->{adapter},
|
||||
status => $fcport->{status},
|
||||
state => $fcport->{state},
|
||||
switch_port => $fcport->{switch_port},
|
||||
fabric_established => $fcport->{fabric_established},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{fcports}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp FC ports status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter qtree.
|
||||
Can be: 'name', 'volume' (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}, %{state}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{status} !~ /online/i || %{state} !~ /online/i').
|
||||
Can used special variables like: %{status}, %{state}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,154 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listaggregates;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-node:s" => { name => 'filter_node' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{clusters} = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
|
||||
$self->{nodes} = $options{custom}->get_objects(path => '/nodes', key => 'key', name => 'name');
|
||||
|
||||
my $result = $options{custom}->get(path => '/aggregates');
|
||||
|
||||
foreach my $aggregate (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$aggregate->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_node}) && $self->{option_results}->{filter_node} ne '' &&
|
||||
defined($self->{nodes}->{$aggregate->{node_key}}) && $self->{nodes}->{$aggregate->{node_key}} !~ /$self->{option_results}->{filter_node}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter node '" . $self->{nodes}->{$aggregate->{node_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($self->{clusters}->{$aggregate->{cluster_key}}) && $self->{clusters}->{$aggregate->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $aggregate->{name} . "': no matching filter cluster '" . $self->{clusters}->{$aggregate->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{aggregates}->{$aggregate->{key}} = {
|
||||
name => $aggregate->{name},
|
||||
state => $aggregate->{state},
|
||||
mirror_status => $aggregate->{mirror_status},
|
||||
raid_type => $aggregate->{raid_type},
|
||||
aggregate_type => $aggregate->{aggregate_type},
|
||||
snaplock_type => $aggregate->{snaplock_type},
|
||||
cluster => $self->{clusters}->{$aggregate->{cluster_key}},
|
||||
node => $self->{nodes}->{$aggregate->{node_key}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $aggregate (sort keys %{$self->{aggregates}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[name = %s] [state = %s] [mirror_status = %s] [raid_type = %s] [aggregate_type = %s] [snaplock_type = %s] [cluster = %s] [node = %s]",
|
||||
$self->{aggregates}->{$aggregate}->{name},
|
||||
$self->{aggregates}->{$aggregate}->{state},
|
||||
$self->{aggregates}->{$aggregate}->{mirror_status},
|
||||
$self->{aggregates}->{$aggregate}->{raid_type},
|
||||
$self->{aggregates}->{$aggregate}->{aggregate_type},
|
||||
$self->{aggregates}->{$aggregate}->{snaplock_type},
|
||||
$self->{aggregates}->{$aggregate}->{cluster},
|
||||
$self->{aggregates}->{$aggregate}->{node}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List aggregates:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['name', 'state', 'mirror_status',
|
||||
'raid_type', 'aggregate_type', 'snaplock_type']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $aggregate (sort keys %{$self->{aggregates}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
name => $self->{aggregates}->{$aggregate}->{name},
|
||||
state => $self->{aggregates}->{$aggregate}->{state},
|
||||
mirror_status => $self->{aggregates}->{$aggregate}->{mirror_status},
|
||||
raid_type => $self->{aggregates}->{$aggregate}->{raid_type},
|
||||
aggregate_type => $self->{aggregates}->{$aggregate}->{aggregate_type},
|
||||
snaplock_type => $self->{aggregates}->{$aggregate}->{snaplock_type},
|
||||
cluster => $self->{aggregates}->{$aggregate}->{cluster},
|
||||
node => $self->{aggregates}->{$aggregate}->{node},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List aggregates.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter aggregates.
|
||||
Can be: 'name', 'node', 'cluster' (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,123 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listclusters;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/clusters');
|
||||
|
||||
foreach my $cluster (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$cluster->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $cluster->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{clusters}->{$cluster->{key}} = {
|
||||
name => $cluster->{name},
|
||||
status => $cluster->{status},
|
||||
metro_cluster_mode => defined($cluster->{metro_cluster_mode}) ? $cluster->{metro_cluster_mode} : "-",
|
||||
metro_cluster_configuration_state => defined($cluster->{metro_cluster_configuration_state}) ? $cluster->{metro_cluster_configuration_state} : "-",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $cluster (sort keys %{$self->{clusters}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[name = %s] [status = %s] [metro_cluster_mode = %s] [metro_cluster_configuration_state = %s]",
|
||||
$self->{clusters}->{$cluster}->{name},
|
||||
$self->{clusters}->{$cluster}->{status},
|
||||
$self->{clusters}->{$cluster}->{metro_cluster_mode},
|
||||
$self->{clusters}->{$cluster}->{metro_cluster_configuration_state}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List clusters:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['name', 'status', 'metro_cluster_mode',
|
||||
'metro_cluster_configuration_state']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $cluster (sort keys %{$self->{clusters}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
name => $self->{clusters}->{$cluster}->{name},
|
||||
status => $self->{clusters}->{$cluster}->{status},
|
||||
metro_cluster_mode => $self->{clusters}->{$cluster}->{metro_cluster_mode},
|
||||
metro_cluster_configuration_state => $self->{clusters}->{$cluster}->{metro_cluster_configuration_state},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List clusters.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,125 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listfcports;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/fc-ports');
|
||||
|
||||
foreach my $fcport (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$fcport->{wwpn} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $fcport->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{fcports}->{$fcport->{key}} = {
|
||||
wwpn => $fcport->{wwpn},
|
||||
adapter => $fcport->{adapter},
|
||||
status => $fcport->{status},
|
||||
state => $fcport->{state},
|
||||
switch_port => $fcport->{switch_port},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $fcport (sort keys %{$self->{fcports}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[wwpn = %s] [adapter = %s] [status = %s] [state = %s] [switch_port = %s]",
|
||||
$self->{fcports}->{$fcport}->{wwpn},
|
||||
$self->{fcports}->{$fcport}->{adapter},
|
||||
$self->{fcports}->{$fcport}->{status},
|
||||
$self->{fcports}->{$fcport}->{state},
|
||||
$self->{fcports}->{$fcport}->{switch_port}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List FC ports:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['wwpn', 'adapter', 'status', 'state', 'switch_port']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $fcport (sort keys %{$self->{fcports}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
wwpn => $self->{fcports}->{$fcport}->{wwpn},
|
||||
adapter => $self->{fcports}->{$fcport}->{adapter},
|
||||
status => $self->{fcports}->{$fcport}->{status},
|
||||
state => $self->{fcports}->{$fcport}->{state},
|
||||
switch_port => $self->{fcports}->{$fcport}->{switch_port},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List FC ports.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter FC ports name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,129 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listluns;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/luns');
|
||||
|
||||
foreach my $lun (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$lun->{path} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $lun->{path} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{luns}->{$lun->{key}} = {
|
||||
path => $lun->{path},
|
||||
is_online => $lun->{is_online},
|
||||
is_mapped => $lun->{is_mapped},
|
||||
lun_class => $lun->{lun_class},
|
||||
alignment => $lun->{alignment},
|
||||
multi_protocol_type => $lun->{multi_protocol_type},
|
||||
size => $lun->{size},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $lun (sort keys %{$self->{luns}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[path = %s] [is_online = %s] [is_mapped = %s] [lun_class = %s] [alignment = %s] [multi_protocol_type = %s] [size = %s]",
|
||||
$self->{luns}->{$lun}->{path}, $self->{luns}->{$lun}->{is_online},
|
||||
$self->{luns}->{$lun}->{is_mapped}, $self->{luns}->{$lun}->{lun_class},
|
||||
$self->{luns}->{$lun}->{alignment}, $self->{luns}->{$lun}->{multi_protocol_type},
|
||||
$self->{luns}->{$lun}->{size}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List luns:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['path', 'is_online', 'is_mapped', 'lun_class', 'alignment',
|
||||
'multi_protocol_type', 'size']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $lun (sort keys %{$self->{luns}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
path => $self->{luns}->{$lun}->{path},
|
||||
is_online => $self->{luns}->{$lun}->{is_online},
|
||||
is_mapped => $self->{luns}->{$lun}->{is_mapped},
|
||||
lun_class => $self->{luns}->{$lun}->{lun_class},
|
||||
alignment => $self->{luns}->{$lun}->{alignment},
|
||||
multi_protocol_type => $self->{luns}->{$lun}->{multi_protocol_type},
|
||||
size => $self->{luns}->{$lun}->{size},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List LUNs.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter lun name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,123 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listnodes;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/nodes');
|
||||
|
||||
foreach my $node (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$node->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{nodes}->{$node->{key}} = {
|
||||
name => $node->{name},
|
||||
is_node_healthy => $node->{is_node_healthy},
|
||||
current_mode => $node->{current_mode},
|
||||
failover_state => $node->{failover_state},
|
||||
is_failover_enabled => $node->{is_failover_enabled},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $node (sort keys %{$self->{nodes}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[name = %s] [status = %s] [current_mode = %s] [failover_state = %s] [failover = %s]",
|
||||
$self->{nodes}->{$node}->{name}, ($self->{nodes}->{$node}->{is_node_healthy}) ? "healthy" : "not healthy",
|
||||
$self->{nodes}->{$node}->{current_mode}, $self->{nodes}->{$node}->{failover_state},
|
||||
($self->{nodes}->{$node}->{is_failover_enabled}) ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List nodes:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['name', 'status', 'current_mode', 'failover_state', 'failover']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $node (sort keys %{$self->{nodes}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
name => $self->{nodes}->{$node}->{name},
|
||||
status => ($self->{nodes}->{$node}->{is_node_healthy}) ? "healthy" : "not healthy",
|
||||
current_mode => $self->{nodes}->{$node}->{current_mode},
|
||||
failover_state => $self->{nodes}->{$node}->{failover_state},
|
||||
failover => ($self->{nodes}->{$node}->{is_failover_enabled}) ? "enabled" : "disabled",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List nodes.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter node name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,123 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listsnapmirrors;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/snap-mirrors');
|
||||
|
||||
foreach my $snapmirror (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$snapmirror->{source_location} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $snapmirror->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{snapmirrors}->{$snapmirror->{key}} = {
|
||||
source_location => $snapmirror->{source_location},
|
||||
destination_location => $snapmirror->{destination_location},
|
||||
mirror_state => $snapmirror->{mirror_state},
|
||||
is_healthy => $snapmirror->{is_healthy},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $snapmirror (sort keys %{$self->{snapmirrors}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[source_location = %s] [destination_location = %s] [mirror_state = %s] [is_healthy = %s]",
|
||||
$self->{snapmirrors}->{$snapmirror}->{source_location},
|
||||
$self->{snapmirrors}->{$snapmirror}->{destination_location},
|
||||
$self->{snapmirrors}->{$snapmirror}->{mirror_state},
|
||||
$self->{snapmirrors}->{$snapmirror}->{is_healthy}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List snap mirrors:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['source_location', 'destination_location', 'mirror_state',
|
||||
'is_healthy']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $snapmirror (sort keys %{$self->{snapmirrors}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
source_location => $self->{snapmirrors}->{$snapmirror}->{source_location},
|
||||
destination_location => $self->{snapmirrors}->{$snapmirror}->{destination_location},
|
||||
mirror_state => $self->{snapmirrors}->{$snapmirror}->{mirror_state},
|
||||
is_healthy => $self->{snapmirrors}->{$snapmirror}->{is_healthy},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List snap mirrors.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,126 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::listvolumes;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/volumes');
|
||||
|
||||
foreach my $volume (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$volume->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{volumes}->{$volume->{key}} = {
|
||||
name => $volume->{name},
|
||||
state => $volume->{state},
|
||||
vol_type => $volume->{vol_type},
|
||||
style => $volume->{style},
|
||||
is_replica_volume => $volume->{is_replica_volume},
|
||||
size_total => $volume->{size_total},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $volume (sort keys %{$self->{volumes}}) {
|
||||
$self->{output}->output_add(long_msg => sprintf("[name = %s] [state = %s] [vol_type = %s] [style = %s] [is_replica_volume = %s] [size_total = %s]",
|
||||
$self->{volumes}->{$volume}->{name}, $self->{volumes}->{$volume}->{state},
|
||||
$self->{volumes}->{$volume}->{vol_type}, $self->{volumes}->{$volume}->{style},
|
||||
$self->{volumes}->{$volume}->{is_replica_volume}, $self->{volumes}->{$volume}->{size_total}));
|
||||
}
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'List volumes:');
|
||||
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
sub disco_format {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->add_disco_format(elements => ['name', 'state', 'vol_type', 'style',
|
||||
'is_replica_volume', 'size_total']);
|
||||
}
|
||||
|
||||
sub disco_show {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->manage_selection(%options);
|
||||
foreach my $volume (sort keys %{$self->{volumes}}) {
|
||||
$self->{output}->add_disco_entry(
|
||||
name => $self->{volumes}->{$volume}->{name},
|
||||
state => $self->{volumes}->{$volume}->{state},
|
||||
vol_type => $self->{volumes}->{$volume}->{vol_type},
|
||||
style => $self->{volumes}->{$volume}->{style},
|
||||
is_replica_volume => $self->{volumes}->{$volume}->{is_replica_volume},
|
||||
size_total => $self->{volumes}->{$volume}->{size_total},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
List volumes.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter volume name (can be a regexp).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,170 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::lunalignment;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'luns', type => 0},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{luns} = [
|
||||
{ label => 'aligned', set => {
|
||||
key_values => [ { name => 'aligned' } ],
|
||||
output_template => 'Luns aligned: %d',
|
||||
perfdatas => [
|
||||
{ label => 'aligned', value => 'aligned_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'misaligned', set => {
|
||||
key_values => [ { name => 'misaligned' } ],
|
||||
output_template => 'Luns misaligned: %d',
|
||||
perfdatas => [
|
||||
{ label => 'misaligned', value => 'misaligned_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'possibly-misaligned', set => {
|
||||
key_values => [ { name => 'possibly_misaligned' } ],
|
||||
output_template => 'Luns possibly misaligned: %d',
|
||||
perfdatas => [
|
||||
{ label => 'possibly_misaligned', value => 'possibly_misaligned_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'indeterminate', set => {
|
||||
key_values => [ { name => 'indeterminate' } ],
|
||||
output_template => 'Luns indeterminate: %d',
|
||||
perfdatas => [
|
||||
{ label => 'indeterminate', value => 'indeterminate_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'partial-writes', set => {
|
||||
key_values => [ { name => 'partial_writes' } ],
|
||||
output_template => 'Luns partial writes: %d',
|
||||
perfdatas => [
|
||||
{ label => 'partial_writes', value => 'partial_writes_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'not-mapped', set => {
|
||||
key_values => [ { name => 'not_mapped' } ],
|
||||
output_template => 'Luns not mapped: %d',
|
||||
perfdatas => [
|
||||
{ label => 'not_mapped', value => 'not_mapped_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-volume:s" => { name => 'filter_volume' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/luns');
|
||||
|
||||
$self->{luns}->{aligned} = 0;
|
||||
$self->{luns}->{misaligned} = 0;
|
||||
$self->{luns}->{possibly_misaligned} = 0;
|
||||
$self->{luns}->{indeterminate} = 0;
|
||||
$self->{luns}->{partial_writes} = 0;
|
||||
$self->{luns}->{not_mapped} = 0;
|
||||
|
||||
foreach my $lun (@{$result}) {
|
||||
my $volume = $2 if ($lun->{path} =~ /^\/(\S+)\/(\S+)\/(\S+)\s*/);
|
||||
|
||||
if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '' &&
|
||||
defined($volume) && $volume !~ /$self->{option_results}->{filter_volume}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $lun->{path} . "': no matching filter volume '" . $volume . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{luns}->{$lun->{alignment}}++;
|
||||
|
||||
if ($lun->{alignment} ne "aligned" && $lun->{alignment} ne "indeterminate") {
|
||||
my $long_msg = "Lun '" . $lun->{path} . "' is '" . $lun->{alignment} . "'";
|
||||
$long_msg .= " [volume: " . $volume . "]" if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '');
|
||||
$self->{output}->output_add(long_msg => $long_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp luns alignment.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter lun.
|
||||
Can be: 'volume' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
'aligned', 'misaligned', 'possibly-misaligned', 'indeterminate', 'partial-writes', 'not-mapped'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
'aligned', 'misaligned', 'possibly-misaligned', 'indeterminate', 'partial-writes', 'not-mapped'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,159 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::lunonline;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'luns', type => 0},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{luns} = [
|
||||
{ label => 'online', set => {
|
||||
key_values => [ { name => 'online' } ],
|
||||
output_template => 'Luns online: %d',
|
||||
perfdatas => [
|
||||
{ label => 'online', value => 'online_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'not-online', set => {
|
||||
key_values => [ { name => 'not_online' } ],
|
||||
output_template => 'Luns not online: %d',
|
||||
perfdatas => [
|
||||
{ label => 'not_online', value => 'not_online_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'mapped', set => {
|
||||
key_values => [ { name => 'mapped' } ],
|
||||
output_template => 'Luns mapped: %d',
|
||||
perfdatas => [
|
||||
{ label => 'mapped', value => 'mapped_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'not-mapped', set => {
|
||||
key_values => [ { name => 'not_mapped' } ],
|
||||
output_template => 'Luns not mapped: %d',
|
||||
perfdatas => [
|
||||
{ label => 'not_mapped', value => 'not_mapped_absolute', template => '%d',
|
||||
min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-volume:s" => { name => 'filter_volume' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/luns');
|
||||
|
||||
$self->{luns}->{online} = 0;
|
||||
$self->{luns}->{not_online} = 0;
|
||||
$self->{luns}->{mapped} = 0;
|
||||
$self->{luns}->{not_mapped} = 0;
|
||||
|
||||
foreach my $lun (@{$result}) {
|
||||
my $volume = $2 if ($lun->{path} =~ /^\/(\S+)\/(\S+)\/(\S+)\s*/);
|
||||
|
||||
if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '' &&
|
||||
defined($volume) && $volume !~ /$self->{option_results}->{filter_volume}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $lun->{path} . "': no matching filter volume '" . $volume . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{luns}->{online}++ if ($lun->{is_online});
|
||||
$self->{luns}->{mapped}++ if ($lun->{is_mapped});
|
||||
if (!$lun->{is_online}) {
|
||||
$self->{luns}->{not_online}++;
|
||||
|
||||
my $long_msg = "Lun '" . $lun->{path} . "' is 'not online'";
|
||||
$long_msg .= " [volume: " . $volume . "]" if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '');
|
||||
$self->{output}->output_add(long_msg => $long_msg);
|
||||
}
|
||||
if (!$lun->{is_mapped}) {
|
||||
$self->{luns}->{not_mapped}++;
|
||||
|
||||
my $long_msg = "Lun '" . $lun->{path} . "' is 'not mapped'";
|
||||
$long_msg .= " [volume: " . $volume . "]" if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '');
|
||||
$self->{output}->output_add(long_msg => $long_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp luns status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter lun.
|
||||
Can be: 'volume' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'online', 'not-online', 'mapped', 'not-mapped'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'online', 'not-online', 'mapped', 'not-mapped'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,199 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::lunusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_usage_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'used' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_usage_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
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 ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
|
||||
my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_usage_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_path'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_size_used'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Lun '" . $options{instance_value}->{path} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'luns', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All luns usage are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{luns} = [
|
||||
{ label => 'usage', set => {
|
||||
key_values => [ { name => 'size_used' }, { name => 'size' }, { name => 'path' } ],
|
||||
closure_custom_calc => $self->can('custom_usage_calc'),
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"units:s" => { name => 'units', default => '%' },
|
||||
"free" => { name => 'free' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/luns');
|
||||
|
||||
foreach my $lun (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$lun->{path} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $lun->{path} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{luns}->{$lun->{key}} = {
|
||||
path => $lun->{path},
|
||||
size => $lun->{size},
|
||||
size_used => $lun->{size_used},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{luns}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp luns usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter lun name (can be a regexp).
|
||||
|
||||
=item B<--warning-usage>
|
||||
|
||||
Threshold warning.
|
||||
|
||||
=item B<--critical-usage>
|
||||
|
||||
Threshold critical.
|
||||
|
||||
=item B<--units>
|
||||
|
||||
Units of thresholds (Default: '%') ('%', 'B').
|
||||
|
||||
=item B<--free>
|
||||
|
||||
Thresholds are on free space left.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,204 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::nodefailoverstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Failover state is '%s', Interconnect is '%s' [current mode: %s] [take_over_possible: %s]",
|
||||
$self->{result_values}->{state},
|
||||
$self->{result_values}->{interconnect},
|
||||
$self->{result_values}->{current_mode},
|
||||
$self->{result_values}->{take_over_possible});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_failover_state'};
|
||||
$self->{result_values}->{interconnect} = ($options{new_datas}->{$self->{instance} . '_is_interconnect_up'}) ? "up" : "down";
|
||||
$self->{result_values}->{current_mode} = $options{new_datas}->{$self->{instance} . '_current_mode'};
|
||||
$self->{result_values}->{take_over_possible} = ($options{new_datas}->{$self->{instance} . '_is_take_over_possible'}) ? "true" : "false";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Node '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'nodes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All nodes status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{nodes} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'failover_state' }, { name => 'current_mode' }, { name => 'is_interconnect_up' },
|
||||
{ name => 'is_take_over_possible' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{state} !~ /connected/i || %{interconnect} !~ /up/i'},
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/nodes');
|
||||
|
||||
foreach my $node (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$node->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$node->{cluster_key}}) && $clusters->{$node->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter cluster '" . $clusters->{$node->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{nodes}->{$node->{key}} = {
|
||||
name => $node->{name},
|
||||
failover_state => $node->{failover_state},
|
||||
current_mode => $node->{current_mode},
|
||||
is_interconnect_up => $node->{is_interconnect_up},
|
||||
is_take_over_possible => $node->{is_take_over_possible},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{nodes}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp nodes status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter node.
|
||||
Can be: 'name', 'clusters' (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}, %{interconnect}, %{current_mode}, %{take_over_possible}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{state} !~ /connected/i || %{interconnect} !~ /up/i').
|
||||
Can used special variables like: %{state}, %{interconnect}, %{current_mode}, %{take_over_possible}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,233 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::nodehardwarestatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s', Battery status is '%s', Temperature is '%s'",
|
||||
$self->{result_values}->{status},
|
||||
$self->{result_values}->{battery_status},
|
||||
$self->{result_values}->{temperature});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{status} = ($options{new_datas}->{$self->{instance} . '_is_node_healthy'}) ? "healthy" : "not healthy";
|
||||
$self->{result_values}->{temperature} = ($options{new_datas}->{$self->{instance} . '_is_over_temperature'}) ? "critical" : "ok";
|
||||
$self->{result_values}->{battery_status} = $options{new_datas}->{$self->{instance} . '_nvram_battery_status'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Node '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'nodes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All nodes status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{nodes} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'is_node_healthy' }, { name => 'is_over_temperature' },
|
||||
{ name => 'nvram_battery_status' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'failed-fans', set => {
|
||||
key_values => [ { name => 'failed_fan_count' }, { name => 'name' } ],
|
||||
output_template => '%d failed fan(s)',
|
||||
perfdatas => [
|
||||
{ label => 'failed_fans', value => 'failed_fan_count_absolute', template => '%d',
|
||||
min => 0, label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'failed-psu', set => {
|
||||
key_values => [ { name => 'failed_power_supply_count' }, { name => 'name' } ],
|
||||
output_template => '%d failed psu',
|
||||
perfdatas => [
|
||||
{ label => 'failed_psu', value => 'failed_power_supply_count_absolute', template => '%d',
|
||||
min => 0, label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-cluster:s" => { name => 'filter_cluster' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} =~ /not healthy/i || ' .
|
||||
'%{temperature} !~ /ok/i || %{battery_status} !~ /battery_ok|battery_fully_charge|battery_over_charged/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $clusters;
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '') {
|
||||
$clusters = $options{custom}->get_objects(path => '/clusters', key => 'key', name => 'name');
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/nodes');
|
||||
|
||||
foreach my $node (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$node->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_cluster}) && $self->{option_results}->{filter_cluster} ne '' &&
|
||||
defined($clusters->{$node->{cluster_key}}) && $clusters->{$node->{cluster_key}} !~ /$self->{option_results}->{filter_cluster}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $node->{name} . "': no matching filter cluster '" . $clusters->{$node->{cluster_key}} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{nodes}->{$node->{key}} = {
|
||||
name => $node->{name},
|
||||
is_node_healthy => $node->{is_node_healthy},
|
||||
is_over_temperature => $node->{is_over_temperature},
|
||||
nvram_battery_status => $node->{nvram_battery_status},
|
||||
failed_fan_count => $node->{failed_fan_count},
|
||||
failed_power_supply_count => $node->{failed_power_supply_count},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{nodes}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp nodes hardware status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter node.
|
||||
Can be: 'name', 'clusters' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'failed-fans', 'psu'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'failed-fans', 'psu'.
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{status}, %{temperature}, %{battery_status}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{status} =~ /not healthy/i || %{temperature} !~ /ok/i ||
|
||||
%{battery_status} !~ /battery_ok|battery_fully_charge|battery_over_charged/i').
|
||||
Can used special variables like: %{status}, %{temperature}, %{battery_status}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,196 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::qtreestatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s' [path: %s] [volume: %s]",
|
||||
$self->{result_values}->{status},
|
||||
$self->{result_values}->{qtree_path},
|
||||
$self->{result_values}->{volume});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
|
||||
$self->{result_values}->{qtree_path} = $options{new_datas}->{$self->{instance} . '_qtree_path'};
|
||||
$self->{result_values}->{volume} = $options{new_datas}->{$self->{instance} . '_volume'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Qtree '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'qtrees', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All Qtrees status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{qtrees} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'status' }, { name => 'qtree_path' }, { name => 'volume' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-volume:s" => { name => 'filter_volume' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/qtrees');
|
||||
|
||||
foreach my $qtree (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$qtree->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $qtree->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
my $volume = $2 if ($qtree->{qtree_path} =~ /^\/(\S+)\/(\S+)\/(\S+)\s*/);
|
||||
|
||||
if (defined($self->{option_results}->{filter_volume}) && $self->{option_results}->{filter_volume} ne '' &&
|
||||
defined($volume) && $volume !~ /$self->{option_results}->{filter_volume}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $qtree->{name} . "': no matching filter volume '" . $volume . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{qtrees}->{$qtree->{key}} = {
|
||||
name => $qtree->{name},
|
||||
status => $qtree->{status},
|
||||
qtree_path => $qtree->{qtree_path},
|
||||
volume => $volume,
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{qtrees}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp Qtrees status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter qtree.
|
||||
Can be: 'name', 'volume' (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '').
|
||||
Can used special variables like: %{status}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,181 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::snapmirrorstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("State is '%s', Update is '%s'", $self->{result_values}->{state}, $self->{result_values}->{update});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{source_location} = $options{new_datas}->{$self->{instance} . '_source_location'};
|
||||
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_mirror_state'};
|
||||
$self->{result_values}->{update} = $options{new_datas}->{$self->{instance} . '_is_healthy'} ? "healthy" : "not healthy";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Snap mirror '" . $options{instance_value}->{source_location} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'snapmirrors', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All snap mirrors status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{snapmirrors} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'source_location' }, { name => 'mirror_state' }, { name => 'is_healthy' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{state} !~ /snapmirrored/i || %{update} =~ /not healthy/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/snap-mirrors');
|
||||
|
||||
foreach my $snapmirror (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$snapmirror->{source_location} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $snapmirror->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{snapmirrors}->{$snapmirror->{key}} = {
|
||||
source_location => $snapmirror->{source_location},
|
||||
mirror_state => $snapmirror->{mirror_state},
|
||||
is_healthy => $snapmirror->{is_healthy},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{snapmirrors}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp snap mirrors status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}, %{update}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{state} !~ /snapmirrored/i || %{update} =~ /not healthy/i').
|
||||
Can used special variables like: %{state}, %{update}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,144 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::snapmirrorusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Snap mirror '" . $options{instance_value}->{source_location} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'snapmirrors', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All snap mirrors usage are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{snapmirrors} = [
|
||||
{ label => 'last-transfer-duration', set => {
|
||||
key_values => [ { name => 'last_transfer_duration' }, { name => 'source_location' } ],
|
||||
output_template => 'Last transfer duration: %.2f s',
|
||||
perfdatas => [
|
||||
{ label => 'last_transfer_duration', value => 'last_transfer_duration_absolute', template => '%.2f',
|
||||
min => 0, unit => 's', label_extra_instance => 1, instance_use => 'source_location_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'last-transfer-size', set => {
|
||||
key_values => [ { name => 'last_transfer_size' }, { name => 'source_location' } ],
|
||||
output_template => 'Last transfer size: %s %s',
|
||||
output_change_bytes => 1,
|
||||
perfdatas => [
|
||||
{ label => 'last_transfer_size', value => 'last_transfer_size_absolute', template => '%d',
|
||||
min => 0, unit => 'B', label_extra_instance => 1, instance_use => 'source_location_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'lag-time', set => {
|
||||
key_values => [ { name => 'lag_time' }, { name => 'source_location' } ],
|
||||
output_template => 'Lag time: %.2f s',
|
||||
perfdatas => [
|
||||
{ label => 'lag_time', value => 'lag_time_absolute', template => '%.2f',
|
||||
min => 0, unit => 's', label_extra_instance => 1, instance_use => 'source_location_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/snap-mirrors');
|
||||
|
||||
foreach my $snapmirror (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$snapmirror->{source_location} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $snapmirror->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{snapmirrors}->{$snapmirror->{key}} = {
|
||||
source_location => $snapmirror->{source_location},
|
||||
last_transfer_duration => $snapmirror->{last_transfer_duration},
|
||||
last_transfer_size => $snapmirror->{last_transfer_size},
|
||||
lag_time => $snapmirror->{lag_time},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{snapmirrors}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp snap mirrors usage.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter snapmirror name (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'last-transfer-duration', 'last-transfer-size', 'lag-time'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'last-transfer-duration', 'last-transfer-size', 'lag-time'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,225 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::volumeio;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Volume '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'volumes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All volumes IOs are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{volumes} = [
|
||||
{ label => 'read-iops', set => {
|
||||
key_values => [ { name => 'read_ops' }, { name => 'name' } ],
|
||||
output_template => 'Read IOPS: %.2f ops/s',
|
||||
perfdatas => [
|
||||
{ label => 'read_iops', value => 'read_ops_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'write-iops', set => {
|
||||
key_values => [ { name => 'write_ops' }, { name => 'name' } ],
|
||||
output_template => 'Write IOPS: %.2f ops/s',
|
||||
perfdatas => [
|
||||
{ label => 'write_iops', value => 'write_ops_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'other-iops', set => {
|
||||
key_values => [ { name => 'other_ops' }, { name => 'name' } ],
|
||||
output_template => 'Other IOPS: %.2f ops/s',
|
||||
perfdatas => [
|
||||
{ label => 'other_iops', value => 'other_ops_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ops/s', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'avg-latency', set => {
|
||||
key_values => [ { name => 'avg_latency' }, { name => 'name' } ],
|
||||
output_template => 'Average latency: %.2f ms',
|
||||
perfdatas => [
|
||||
{ label => 'avg_latency', value => 'avg_latency_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'read-latency', set => {
|
||||
key_values => [ { name => 'read_latency' }, { name => 'name' } ],
|
||||
output_template => 'Read latency: %.2f ms',
|
||||
perfdatas => [
|
||||
{ label => 'read_latency', value => 'read_latency_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'write-latency', set => {
|
||||
key_values => [ { name => 'write_latency' }, { name => 'name' } ],
|
||||
output_template => 'Write latency: %.2f ms',
|
||||
perfdatas => [
|
||||
{ label => 'write_latency', value => 'write_latency_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'other-latency', set => {
|
||||
key_values => [ { name => 'other_latency' }, { name => 'name' } ],
|
||||
output_template => 'Other latency: %.2f ms',
|
||||
perfdatas => [
|
||||
{ label => 'other_latency', value => 'other_latency_absolute', template => '%.2f',
|
||||
min => 0, unit => 'ms', label_extra_instance => 1, instance_use => 'name_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-state:s" => { name => 'filter_state' },
|
||||
"filter-style:s" => { name => 'filter_style' },
|
||||
"filter-type:s" => { name => 'filter_type' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my %names_hash;
|
||||
my $names = $options{custom}->get(path => '/volumes');
|
||||
foreach my $volume (@{$names}) {
|
||||
$names_hash{$volume->{key}} = {
|
||||
name => $volume->{name},
|
||||
state => $volume->{state},
|
||||
style => $volume->{style},
|
||||
vol_type => $volume->{vol_type},
|
||||
};
|
||||
}
|
||||
|
||||
my $args = '';
|
||||
my $append = '';
|
||||
foreach my $metric ('read_ops', 'write_ops', 'other_ops', 'avg_latency', 'read_latency', 'write_latency', 'other_latency') {
|
||||
$args .= $append . 'name=' . $metric;
|
||||
$append = '&';
|
||||
}
|
||||
|
||||
my $result = $options{custom}->get(path => '/volumes/metrics', args => $args);
|
||||
|
||||
foreach my $volume (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
defined($names_hash{$volume->{resource_key}}) && $names_hash{$volume->{resource_key}}->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$volume->{resource_key}}->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' &&
|
||||
defined($names_hash{$volume->{resource_key}}) && $names_hash{$volume->{resource_key}}->{state} !~ /$self->{option_results}->{filter_state}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$volume->{resource_key}}->{name} . "': no matching filter state : '" . $names_hash{$volume->{resource_key}}->{state} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_style}) && $self->{option_results}->{filter_style} ne '' &&
|
||||
defined($names_hash{$volume->{resource_key}}) && $names_hash{$volume->{resource_key}}->{style} !~ /$self->{option_results}->{filter_style}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$volume->{resource_key}}->{name} . "': no matching filter style : '" . $names_hash{$volume->{resource_key}}->{style} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
|
||||
defined($names_hash{$volume->{resource_key}}) && $names_hash{$volume->{resource_key}}->{vol_type} !~ /$self->{option_results}->{filter_type}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $names_hash{$volume->{resource_key}}->{name} . "': no matching filter type : '" . $names_hash{$volume->{resource_key}}->{vol_type} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
foreach my $metric (@{$volume->{metrics}}) {
|
||||
$self->{volumes}->{$volume->{resource_key}}->{name} = $names_hash{$volume->{resource_key}}->{name};
|
||||
$self->{volumes}->{$volume->{resource_key}}->{read_ops} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'read_ops');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{write_ops} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'write_ops');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{other_ops} = ${$metric->{samples}}[0]->{value} if ($metric->{name} eq 'other_ops');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{avg_latency} = ${$metric->{samples}}[0]->{value} / 1000 if ($metric->{name} eq 'avg_latency');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{read_latency} = ${$metric->{samples}}[0]->{value} / 1000 if ($metric->{name} eq 'read_latency');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{write_latency} = ${$metric->{samples}}[0]->{value} / 1000 if ($metric->{name} eq 'write_latency');
|
||||
$self->{volumes}->{$volume->{resource_key}}->{other_latency} = ${$metric->{samples}}[0]->{value} / 1000 if ($metric->{name} eq 'other_latency');
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{volumes}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp volumes IOs.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter volume.
|
||||
Can be: 'name', 'state', 'style', 'type' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'read-iops', 'write-iops', 'other-iops',
|
||||
'avg-latency', 'read-latency', 'write-latency', 'other-latency'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'read-iops', 'write-iops', 'other-iops',
|
||||
'avg-latency', 'read-latency', 'write-latency', 'other-latency'.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,180 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::volumestatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_status_threshold {
|
||||
my ($self, %options) = @_;
|
||||
my $status = 'ok';
|
||||
my $message;
|
||||
|
||||
eval {
|
||||
local $SIG{__WARN__} = sub { $message = $_[0]; };
|
||||
local $SIG{__DIE__} = sub { $message = $_[0]; };
|
||||
|
||||
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{critical_status}") {
|
||||
$status = 'critical';
|
||||
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
|
||||
eval "$instance_mode->{option_results}->{warning_status}") {
|
||||
$status = 'warning';
|
||||
}
|
||||
};
|
||||
if (defined($message)) {
|
||||
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("State is '%s'",
|
||||
$self->{result_values}->{state}, $self->{result_values}->{mirror_status});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{state} = $options{new_datas}->{$self->{instance} . '_state'};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Volume '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'volumes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All volumes status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{volumes} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'state' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => $self->can('custom_status_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{state} !~ /online/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub change_macros {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
foreach ('warning_status', 'critical_status') {
|
||||
if (defined($self->{option_results}->{$_})) {
|
||||
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
$self->change_macros();
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/volumes');
|
||||
|
||||
foreach my $volume (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$volume->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{volumes}->{$volume->{key}} = {
|
||||
name => $volume->{name},
|
||||
state => $volume->{state},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{volumes}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp volumes status.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-name>
|
||||
|
||||
Filter volume name (can be a regexp).
|
||||
|
||||
=item B<--warning-status>
|
||||
|
||||
Set warning threshold for status (Default: '').
|
||||
Can used special variables like: %{state}
|
||||
|
||||
=item B<--critical-status>
|
||||
|
||||
Set critical threshold for status (Default: '%{state} !~ /online/i').
|
||||
Can used special variables like: %{state}
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,487 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::restapi::mode::volumeusage;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $instance_mode;
|
||||
|
||||
sub custom_usage_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'used' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_usage_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
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 ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
|
||||
my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_usage_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size_total'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_size_used'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_inode_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'inodes' . $extra_label,
|
||||
unit => '%',
|
||||
value => sprintf("%.2f", $self->{result_values}->{prct_used}),
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}),
|
||||
min => 0, max => 100);
|
||||
}
|
||||
|
||||
sub custom_inode_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(value => $self->{result_values}->{prct_used},
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_inode_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Inodes Used: %.2f%%", $self->{result_values}->{prct_used});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_inode_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_inode_files_used'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_inode_files_total'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
} else {
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_snapshot_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'snapshot' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_snapshot_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_snapshot_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
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});
|
||||
|
||||
my $msg = sprintf("Snapshot Used: %s (%.2f%%) Free: %s (%.2f%%) Reserved: %s",
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used},
|
||||
$free_value . " " . $free_unit, $self->{result_values}->{prct_free},
|
||||
$reserved_value . " " . $reserved_unit);
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_snapshot_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{free} = $options{new_datas}->{$self->{instance} . '_size_available_for_snapshot'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_size_used_by_snapshots'};
|
||||
$self->{result_values}->{reserved} = $options{new_datas}->{$self->{instance} . '_snapshot_reserve_size'};
|
||||
|
||||
$self->{result_values}->{total} = $self->{result_values}->{used} + $self->{result_values}->{free};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_compression_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'compresssaved' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_compression_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_compression_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
|
||||
|
||||
my $msg = sprintf("Compression Space Saved: %s (%.2f%%)",
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_compression_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size_total'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_compression_space_saved'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub custom_deduplication_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $extra_label = '';
|
||||
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
|
||||
|
||||
$self->{output}->perfdata_add(label => 'dedupsaved' . $extra_label,
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_deduplicationn_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($exit, $threshold_value);
|
||||
$threshold_value = $self->{result_values}->{used};
|
||||
$threshold_value = $self->{result_values}->{free} if (defined($instance_mode->{option_results}->{free}));
|
||||
if ($instance_mode->{option_results}->{units} eq '%') {
|
||||
$threshold_value = $self->{result_values}->{prct_used};
|
||||
$threshold_value = $self->{result_values}->{prct_free} if (defined($instance_mode->{option_results}->{free}));
|
||||
}
|
||||
$exit = $self->{perfdata}->threshold_check(value => $threshold_value,
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_deduplication_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
|
||||
|
||||
my $msg = sprintf("Deduplication Space Saved: %s (%.2f%%)",
|
||||
$used_value . " " . $used_unit, $self->{result_values}->{prct_used});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_deduplication_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_name'};
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_size_total'};
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_deduplication_space_saved'};
|
||||
|
||||
if ($self->{result_values}->{total} != 0) {
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_free} = 100 - $self->{result_values}->{prct_used};
|
||||
} else {
|
||||
$self->{result_values}->{free} = '0';
|
||||
$self->{result_values}->{prct_used} = '0';
|
||||
$self->{result_values}->{prct_free} = '0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Volume '" . $options{instance_value}->{name} . "' ";
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'volumes', type => 1, cb_prefix_output => 'prefix_output', message_multiple => 'All volumes usage are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{volumes} = [
|
||||
{ label => 'usage', set => {
|
||||
key_values => [ { name => 'size_used' }, { name => 'size_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_usage_calc'),
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'inodes', set => {
|
||||
key_values => [ { name => 'inode_files_used' }, { name => 'inode_files_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_inode_calc'),
|
||||
closure_custom_output => $self->can('custom_inode_output'),
|
||||
closure_custom_perfdata => $self->can('custom_inode_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_inode_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'snapshot', set => {
|
||||
key_values => [ { name => 'size_available_for_snapshot' }, { name => 'size_used_by_snapshots' }, { name => 'snapshot_reserve_size' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_snapshot_calc'),
|
||||
closure_custom_output => $self->can('custom_snapshot_output'),
|
||||
closure_custom_perfdata => $self->can('custom_snapshot_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_snapshot_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'compresssaved', set => {
|
||||
key_values => [ { name => 'compression_space_saved' }, { name => 'size_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_compression_calc'),
|
||||
closure_custom_output => $self->can('custom_compression_output'),
|
||||
closure_custom_perfdata => $self->can('custom_compression_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_compression_threshold'),
|
||||
}
|
||||
},
|
||||
{ label => 'dedupsaved', set => {
|
||||
key_values => [ { name => 'deduplication_space_saved' }, { name => 'size_total' }, { name => 'name' } ],
|
||||
closure_custom_calc => $self->can('custom_deduplication_calc'),
|
||||
closure_custom_output => $self->can('custom_deduplication_output'),
|
||||
closure_custom_perfdata => $self->can('custom_deduplication_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_deduplication_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$self->{version} = '1.0';
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-state:s" => { name => 'filter_state' },
|
||||
"filter-style:s" => { name => 'filter_style' },
|
||||
"filter-type:s" => { name => 'filter_type' },
|
||||
"units:s" => { name => 'units', default => '%' },
|
||||
"free" => { name => 'free' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$instance_mode = $self;
|
||||
}
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $result = $options{custom}->get(path => '/volumes');
|
||||
|
||||
foreach my $volume (@{$result}) {
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$volume->{name} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_state}) && $self->{option_results}->{filter_state} ne '' &&
|
||||
$volume->{state} !~ /$self->{option_results}->{filter_state}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter state : '" . $volume->{state} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_style}) && $self->{option_results}->{filter_style} ne '' &&
|
||||
$volume->{style} !~ /$self->{option_results}->{filter_style}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter style : '" . $volume->{style} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
|
||||
$volume->{vol_type} !~ /$self->{option_results}->{filter_type}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $volume->{name} . "': no matching filter type : '" . $volume->{vol_type} . "'", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{volumes}->{$volume->{key}} = {
|
||||
name => $volume->{name},
|
||||
size_total => $volume->{size_total},
|
||||
size_used => $volume->{size_used},
|
||||
compression_space_saved => $volume->{compression_space_saved},
|
||||
deduplication_space_saved => $volume->{deduplication_space_saved},
|
||||
size_available_for_snapshot => $volume->{size_available_for_snapshot},
|
||||
size_used_by_snapshots => $volume->{size_used_by_snapshots},
|
||||
snapshot_reserve_size => $volume->{snapshot_reserve_size},
|
||||
inode_files_used => $volume->{inode_files_used},
|
||||
inode_files_total => $volume->{inode_files_total},
|
||||
}
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{volumes}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No entry found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check NetApp volumes usage (space, inodes, snapshot, compression and deduplication)
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter volume.
|
||||
Can be: 'name', 'state', 'style', 'type' (can be a regexp).
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'usage', 'inodes', 'snapshot', 'compresssaved', 'dedupsaved'.
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'usage', 'inodes', 'snapshot', 'compresssaved', 'dedupsaved'.
|
||||
|
||||
=item B<--units>
|
||||
|
||||
Units of thresholds (Default: '%') ('%', 'B').
|
||||
|
||||
=item B<--free>
|
||||
|
||||
Thresholds are on free space left.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,74 @@
|
|||
#
|
||||
# Copyright 2018 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::netapp::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->{version} = '1.0';
|
||||
%{$self->{modes}} = (
|
||||
'aggregate-raid-status' => 'storage::netapp::restapi::mode::aggregateraidstatus',
|
||||
'aggregate-status' => 'storage::netapp::restapi::mode::aggregatestatus',
|
||||
'aggregate-usage' => 'storage::netapp::restapi::mode::aggregateusage',
|
||||
'cluster-io' => 'storage::netapp::restapi::mode::clusterio',
|
||||
'cluster-status' => 'storage::netapp::restapi::mode::clusterstatus',
|
||||
'cluster-usage' => 'storage::netapp::restapi::mode::clusterusage',
|
||||
'disk-failed' => 'storage::netapp::restapi::mode::diskfailed',
|
||||
'disk-spare' => 'storage::netapp::restapi::mode::diskspare',
|
||||
'fc-port-status' => 'storage::netapp::restapi::mode::fcportstatus',
|
||||
'list-aggregates' => 'storage::netapp::restapi::mode::listaggregates',
|
||||
'list-clusters' => 'storage::netapp::restapi::mode::listclusters',
|
||||
'list-fc-ports' => 'storage::netapp::restapi::mode::listfcports',
|
||||
'list-luns' => 'storage::netapp::restapi::mode::listluns',
|
||||
'list-nodes' => 'storage::netapp::restapi::mode::listnodes',
|
||||
'list-snapmirrors' => 'storage::netapp::restapi::mode::listsnapmirrors',
|
||||
'list-volumes' => 'storage::netapp::restapi::mode::listvolumes',
|
||||
'lun-alignment' => 'storage::netapp::restapi::mode::lunalignment',
|
||||
'lun-online' => 'storage::netapp::restapi::mode::lunonline',
|
||||
'lun-usage' => 'storage::netapp::restapi::mode::lunusage',
|
||||
'node-failover-status' => 'storage::netapp::restapi::mode::nodefailoverstatus',
|
||||
'node-hardware-status' => 'storage::netapp::restapi::mode::nodehardwarestatus',
|
||||
'qtree-status' => 'storage::netapp::restapi::mode::qtreestatus',
|
||||
'snapmirror-status' => 'storage::netapp::restapi::mode::snapmirrorstatus',
|
||||
'snapmirror-usage' => 'storage::netapp::restapi::mode::snapmirrorusage',
|
||||
'volume-io' => 'storage::netapp::restapi::mode::volumeio',
|
||||
'volume-status' => 'storage::netapp::restapi::mode::volumestatus',
|
||||
'volume-usage' => 'storage::netapp::restapi::mode::volumeusage',
|
||||
);
|
||||
$self->{custom_modes}{api} = 'storage::netapp::restapi::custom::restapi';
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Check NetApp with OnCommand API.
|
||||
|
||||
=cut
|
Loading…
Reference in New Issue