+ Add Fujitsu eternus ds plugin (Need to be tested)

This commit is contained in:
garnier-quentin 2015-08-19 16:39:33 +02:00
parent 1ba7565739
commit 859b630c0e
7 changed files with 1929 additions and 0 deletions

View File

@ -0,0 +1,267 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::cpu;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::values;
my $maps_counters = {
cpu => {
'001_usage' => {
set => {
key_values => [ { name => 'usage' }, { name => 'display' } ],
output_template => 'Usage : %d %%',
perfdatas => [
{ label => 'cpu', value => 'usage_absolute', template => '%d',
unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => 'performance -type cm' },
"no-component:s" => { name => 'no_component' },
"filter-name:s" => { name => 'filter_name' },
});
$self->{no_components} = undef;
foreach my $key (('cpu')) {
foreach (keys %{$maps_counters->{$key}}) {
my ($id, $name) = split /_/;
if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) {
$options{options}->add_options(arguments => {
'warning-' . $name . ':s' => { name => 'warning-' . $name },
'critical-' . $name . ':s' => { name => 'critical-' . $name },
});
}
$maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(output => $self->{output}, perfdata => $self->{perfdata},
label => $name);
$maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}});
}
}
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
foreach my $key (('cpu')) {
foreach (keys %{$maps_counters->{$key}}) {
$maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results});
}
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection();
my $multiple = 1;
if (scalar(keys %{$self->{cpu}}) == 1) {
$multiple = 0;
}
if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK',
short_msg => 'All CPUs are ok');
}
foreach my $id (sort keys %{$self->{cpu}}) {
my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', '');
my @exits = ();
foreach (sort keys %{$maps_counters->{cpu}}) {
my $obj = $maps_counters->{cpu}->{$_}->{obj};
$obj->set(instance => $id);
my ($value_check) = $obj->execute(values => $self->{cpu}->{$id});
if ($value_check != 0) {
$long_msg .= $long_msg_append . $obj->output_error();
$long_msg_append = ', ';
next;
}
my $exit2 = $obj->threshold_check();
push @exits, $exit2;
my $output = $obj->output();
$long_msg .= $long_msg_append . $output;
$long_msg_append = ', ';
if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) {
$short_msg .= $short_msg_append . $output;
$short_msg_append = ', ';
}
$obj->perfdata(extra_instance => $multiple);
}
$self->{output}->output_add(long_msg => "CPU '$self->{cpu}->{$id}->{display}' $long_msg");
my $exit = $self->{output}->get_most_critical(status => [ @exits ]);
if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) {
$self->{output}->output_add(severity => $exit,
short_msg => "CPU '$self->{cpu}->{$id}->{display}' $short_msg"
);
}
if ($multiple == 0) {
$self->{output}->output_add(short_msg => "CPU '$self->{cpu}->{$id}->{display}' $long_msg");
}
}
$self->{output}->display();
$self->{output}->exit();
}
sub manage_selection {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#Location Busy Rate(%) Copy Residual Quantity(MB)
#--------------------- ------------ --------------------------
#CM#0 56 55191552
#CM#0 CPU Core#0 66 -
#CM#0 CPU Core#1 46 -
#CM#1 52 55191552
#CM#1 CPU Core#0 62 -
#CM#1 CPU Core#1 42 -
$self->{cpu} = {};
foreach (split /\n/, $stdout) {
next if ($_ !~ /^(.*?)\s+(\d+)\s+\S+$/);
my ($cpu_name, $cpu_value) = ($1, $2);
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$cpu_name !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "Skipping '" . $cpu_name . "': no matching filter name.");
next;
}
$self->{cpu}->{$cpu_name} = { display => $cpu_name, usage => $cpu_value };
}
if (defined($self->{option_results}->{no_component}) && scalar(keys %{$self->{cpu}}) <= 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
}
1;
__END__
=head1 MODE
Check CPUs usage.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'performance -type cm').
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=item B<--filter-name>
Filter by name (regexp can be used).
=item B<--warning-usage>
Threshold warning (in percent).
=item B<--critical-usage>
Threshold critical (in percent).
=back
=cut

View File

@ -0,0 +1,255 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::physicaldisk;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
my $thresholds = {
disk => [
['Available', 'OK'],
['Spare', 'OK'],
['Readying', 'OK'],
['Redundant Copy', 'OK'],
['Rebuild/Copyback', 'WARNING'],
['Available (Predictive Failure)', 'WARNING'],
['Present', 'WARNING'],
['Failed Usable', 'WARNING'],
['Formatting', 'WARNING'],
['Not Format', 'WARNING'],
['Not Supported', 'CRITICAL'],
['Not Available', 'CRITICAL'],
['Broken', 'CRITICAL'],
['Not Exist', 'CRITICAL'],
['Unknown', 'UNKNOWN'],
],
};
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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => 'disks -csv' },
"filter:s@" => { name => 'filter' },
"threshold-overload:s@" => { name => 'threshold_overload' },
"no-component:s" => { name => 'no_component' },
});
$self->{no_components} = undef;
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
$self->{filter} = [];
foreach my $val (@{$self->{option_results}->{filter}}) {
next if (!defined($val) || $val eq '');
my @values = split (/,/, $val);
push @{$self->{filter}}, { filter => $values[0], instance => $values[1] };
}
$self->{overload_th} = {};
foreach my $val (@{$self->{option_results}->{threshold_overload}}) {
if ($val !~ /^(.*?),(.*?),(.*)$/) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'.");
$self->{output}->option_exit();
}
my ($section, $status, $filter) = ($1, $2, $3);
if ($self->{output}->is_litteral_status(status => $status) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'.");
$self->{output}->option_exit();
}
$self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section}));
push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status};
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#[Location],[Status],[Size],[Type],[Speed],[Usage],[Health],[RAID Group],[Motor Status],[Rebuild/Copyback Progress],[Vendor ID],[Product ID],[Serial Number],[WWN],[Firmware Revision],[Total completed passes],[Progress with current pass],[Completed passes since last Power On]
#CE-Disk#0,Available,2.0TB,Unknown,-,System,0%,-,Active,-,FUJITSU,PRODUCT-00000001,SERIAL-000000001,0000000000000000,REV-0001,0Cycles,0%,0Cycles
#CE-Disk#1,Available,2.0TB,Unknown,-,System,0%,-,Active,-,FUJITSU,PRODUCT-00000001,SERIAL-000000002,0000000000000000,REV-0001,0Cycles,0%,0Cycles
#CE-Disk#2,Available,2.0TB,Unknown,-,System,0%,-,Active,-,FUJITSU,PRODUCT-00000001,SERIAL-000000003,0000000000000000,REV-0001,0Cycles,0%,0Cycles
#CE-Disk#3,Available,2.0TB,Unknown,-,System,0%,-,Active,-,FUJITSU,PRODUCT-00000001,SERIAL-000000004,0000000000000000,REV-0001,0Cycles,0%,0Cycles
my $total_components = 0;
while ($stdout =~ /^(.*?),(.*?),/msg) {
my ($disk_name, $disk_status) = ($1, $2);
next if ($disk_name =~ /\[.*?\]/);
next if ($self->check_filter(section => 'disk', instance => $disk_name));
$total_components++;
$self->{output}->output_add(long_msg => sprintf("Physical Disk '%s' status is '%s'", $disk_name, $disk_status));
my $exit = $self->get_severity(section => 'disk', value => $disk_status);
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $exit,
short_msg => sprintf("Physical Disk '%s' status is '%s'.", $disk_name, $disk_status));
}
}
$self->{output}->output_add(severity => 'OK',
short_msg => sprintf("All %d physical disks are ok.", $total_components));
if (defined($self->{option_results}->{no_component}) && $total_components == 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
$self->{output}->display();
$self->{output}->exit();
}
sub check_filter {
my ($self, %options) = @_;
foreach (@{$self->{filter}}) {
if ($options{section} =~ /$_->{filter}/) {
if (!defined($options{instance}) && !defined($_->{instance})) {
$self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section."));
return 1;
} elsif (defined($options{instance}) && $options{instance} =~ /$_->{instance}/) {
$self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance."));
return 1;
}
}
}
return 0;
}
sub get_severity {
my ($self, %options) = @_;
my $status = 'UNKNOWN'; # default
if (defined($self->{overload_th}->{$options{section}})) {
foreach (@{$self->{overload_th}->{$options{section}}}) {
if ($options{value} =~ /$_->{filter}/i) {
$status = $_->{status};
return $status;
}
}
}
foreach (@{$thresholds->{$options{section}}}) {
if ($options{value} =~ /$$_[0]/i) {
$status = $$_[1];
return $status;
}
}
return $status;
}
1;
__END__
=head1 MODE
Check Physical disks.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'disks -csv').
=item B<--filter>
Exclude some parts (comma seperated list)
Can also exclude specific instance: --filter=disk,CE-Disk#0
=item B<--threshold-overload>
Set to overload default threshold values (syntax: section,status,regexp)
It used before default thresholds (order stays).
Example: --threshold-overload='disk,CRITICAL,^(?!(Available|Spare)$)'
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=back
=cut

View File

@ -0,0 +1,300 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::portstats;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::values;
my $maps_counters = {
port => {
'000_read-iops' => {
set => {
key_values => [ { name => 'read_iops' }, { name => 'display' } ],
output_template => 'Read IOPS : %d',
perfdatas => [
{ label => 'read_iops', value => 'read_iops_absolute', template => '%d',
unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'001_write-iops' => {
set => {
key_values => [ { name => 'write_iops' }, { name => 'display' } ],
output_template => 'Write IOPS : %d',
perfdatas => [
{ label => 'write_iops', value => 'write_iops_absolute', template => '%d',
unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'002_read-traffic' => {
set => {
key_values => [ { name => 'read_traffic' }, { name => 'display' } ],
output_template => 'Read Traffic : %s %s/s', output_change_bytes => 2,
perfdatas => [
{ label => 'read_traffic', value => 'read_traffic_absolute', template => '%d',
unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'003_write-traffic' => {
set => {
key_values => [ { name => 'write_traffic' }, { name => 'display' } ],
output_template => 'Write Traffic : %s %s/s', output_change_bytes => 2,
perfdatas => [
{ label => 'write_traffic', value => 'write_traffic_absolute', template => '%d',
unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display_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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => 'performance -type port' },
"no-component:s" => { name => 'no_component' },
"filter-name:s" => { name => 'filter_name' },
});
$self->{no_components} = undef;
foreach my $key (('port')) {
foreach (keys %{$maps_counters->{$key}}) {
my ($id, $name) = split /_/;
if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) {
$options{options}->add_options(arguments => {
'warning-' . $name . ':s' => { name => 'warning-' . $name },
'critical-' . $name . ':s' => { name => 'critical-' . $name },
});
}
$maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(output => $self->{output}, perfdata => $self->{perfdata},
label => $name);
$maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}});
}
}
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
foreach my $key (('port')) {
foreach (keys %{$maps_counters->{$key}}) {
$maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results});
}
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection();
my $multiple = 1;
if (scalar(keys %{$self->{port}}) == 1) {
$multiple = 0;
}
if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK',
short_msg => 'All Ports are ok');
}
foreach my $id (sort keys %{$self->{port}}) {
my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', '');
my @exits = ();
foreach (sort keys %{$maps_counters->{port}}) {
my $obj = $maps_counters->{port}->{$_}->{obj};
$obj->set(instance => $id);
my ($value_check) = $obj->execute(values => $self->{port}->{$id});
if ($value_check != 0) {
$long_msg .= $long_msg_append . $obj->output_error();
$long_msg_append = ', ';
next;
}
my $exit2 = $obj->threshold_check();
push @exits, $exit2;
my $output = $obj->output();
$long_msg .= $long_msg_append . $output;
$long_msg_append = ', ';
if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) {
$short_msg .= $short_msg_append . $output;
$short_msg_append = ', ';
}
$obj->perfdata(extra_instance => $multiple);
}
$self->{output}->output_add(long_msg => "Port '$self->{port}->{$id}->{display}' $long_msg");
my $exit = $self->{output}->get_most_critical(status => [ @exits ]);
if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) {
$self->{output}->output_add(severity => $exit,
short_msg => "Port '$self->{port}->{$id}->{display}' $short_msg"
);
}
if ($multiple == 0) {
$self->{output}->output_add(short_msg => "Port '$self->{port}->{$id}->{display}' $long_msg");
}
}
$self->{output}->display();
$self->{output}->exit();
}
sub manage_selection {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#Location IOPS(IOPS) Throughput(MB/s)
# Read / Write Read / Write
#------------------- ----------- ------------ ----------- -----------
#CM#0 CA#0 Port#0 6621 5192 589 379
#CM#1 CA#1 Port#1 7791 6608 613 292
$self->{port} = {};
foreach (split /\n/, $stdout) {
next if ($_ !~ /^(.*?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/);
my ($port_name, $port_read_iops, $port_write_iops, $port_read_traffic, $port_write_traffic) = ($1, $2, $3, $4, $5);
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$port_name !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "Skipping '" . $port_name . "': no matching filter name.");
next;
}
$self->{port}->{$port_name} = { display => $port_name,
read_iops => $port_read_iops, write_iops => $port_write_iops,
read_traffic => $port_read_traffic * 1000 * 1000 * 8,
write_traffic => $port_write_traffic * 1000 * 1000 * 8
};
}
if (defined($self->{option_results}->{no_component}) && scalar(keys %{$self->{port}}) <= 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
}
1;
__END__
=head1 MODE
Check Port statistics.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'performance -type port').
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=item B<--filter-name>
Filter by name (regexp can be used).
=item B<--warning-*>
Threshold warning.
Can be: 'read-iops', 'write-iops', 'read-traffic', 'write-traffic'.
=item B<--critical-*>
Threshold critical.
Can be: 'read-iops', 'write-iops', 'read-traffic', 'write-traffic'.
=back
=cut

View File

@ -0,0 +1,288 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::psu;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::misc;
my $thresholds = {
psu => [
['Normal', 'OK'],
['Warning', 'WARNING'],
['Maintenance', 'WARNING'],
['Check1', 'WARNING'],
['Undefined', 'WARNING'],
['Normal (Inside unused parts)', 'WARNING'],
['Error', 'CRITICAL'],
['Unknown', 'UNKNOWN'],
],
};
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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => 'enclosure-status -type all' },
"filter:s@" => { name => 'filter' },
"threshold-overload:s@" => { name => 'threshold_overload' },
"no-component:s" => { name => 'no_component' },
});
$self->{no_components} = undef;
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
$self->{filter} = [];
foreach my $val (@{$self->{option_results}->{filter}}) {
next if (!defined($val) || $val eq '');
my @values = split (/,/, $val);
push @{$self->{filter}}, { filter => $values[0], instance => $values[1] };
}
$self->{overload_th} = {};
foreach my $val (@{$self->{option_results}->{threshold_overload}}) {
if ($val !~ /^(.*?),(.*?),(.*)$/) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'.");
$self->{output}->option_exit();
}
my ($section, $status, $filter) = ($1, $2, $3);
if ($self->{output}->is_litteral_status(status => $status) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'.");
$self->{output}->option_exit();
}
$self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section}));
push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status};
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#Controller Enclosure #0 Information
#...
#Controller Enclosure #0 Status
# Controller Module Status/Status Code
# CM#0 [Normal / 0xE001]
# CM#1 [Normal / 0xE001]
# PCIe Flash Module Status/Status Code
# CM#0 PFM#0 [Undefined / 0x6000]
# CM#0 PFM#1 [Undefined / 0x6000]
# CM#1 PFM#0 [Undefined / 0x6000]
# CM#1 PFM#1 [Undefined / 0x6000]
# Power Supply Unit Status/Status Code
# PSU#0 [Normal / 0xE001]
# PSU#1 [Normal / 0xE001]
#
#Controller Enclosure #1 Information
#..
#Controller Module Status/Status Code
# CM#0 [Normal / 0xE001]
# CM#1 [Normal / 0xE001]
# PCIe Flash Module Status/Status Code
# CM#0 PFM#0 [Undefined / 0x6000]
# CM#0 PFM#1 [Undefined / 0x6000]
# CM#1 PFM#0 [Undefined / 0x6000]
# CM#1 PFM#1 [Undefined / 0x6000]
# Power Supply Unit Status/Status Code
# PSU#0 [Normal / 0xE001]
# PSU#1 [Normal / 0xE001]
#
#Frontend Enclosure Information
#...
#Frontend Enclosure Status
# Front End Router Status/Status Code
# Power Supply Unit Status/Status Code
# PSU#0 [Normal / 0xE001]
# PSU#1 [Normal / 0xE001]
my $total_components = 0;
while ($stdout =~ /^(Controller|Frontend)\s+Enclosure\s+(#\d+\s+|)Status(.*?)(\n\n|\Z)/msg) {
my ($type, $num, $content) = ($1, $2, $3);
my $prefix = 'fe';
if ($type =~ /^C/) {
$prefix = 'ce' . centreon::plugins::misc::trim($num);
}
while ($content =~ /PSU#(\d+)\s+\[\s*(\S+)/msig) {
my ($psu_number, $psu_status) = ($1, $2);
my $psu_name = $prefix . '_' . $psu_number;
next if ($self->check_filter(section => 'psu', instance => $psu_name));
$total_components++;
$self->{output}->output_add(long_msg => sprintf("Power Supply '%s' status is '%s'", $psu_name, $psu_status));
my $exit = $self->get_severity(section => 'psu', value => $psu_status);
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
$self->{output}->output_add(severity => $exit,
short_msg => sprintf("Power Supply '%s' status is '%s'.", $psu_name, $psu_status));
}
}
}
$self->{output}->output_add(severity => 'OK',
short_msg => sprintf("All %d power supplies are ok.", $total_components));
if (defined($self->{option_results}->{no_component}) && $total_components == 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
$self->{output}->display();
$self->{output}->exit();
}
sub check_filter {
my ($self, %options) = @_;
foreach (@{$self->{filter}}) {
if ($options{section} =~ /$_->{filter}/) {
if (!defined($options{instance}) && !defined($_->{instance})) {
$self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section."));
return 1;
} elsif (defined($options{instance}) && $options{instance} =~ /$_->{instance}/) {
$self->{output}->output_add(long_msg => sprintf("Skipping $options{section} section $options{instance} instance."));
return 1;
}
}
}
return 0;
}
sub get_severity {
my ($self, %options) = @_;
my $status = 'UNKNOWN'; # default
if (defined($self->{overload_th}->{$options{section}})) {
foreach (@{$self->{overload_th}->{$options{section}}}) {
if ($options{value} =~ /$_->{filter}/i) {
$status = $_->{status};
return $status;
}
}
}
foreach (@{$thresholds->{$options{section}}}) {
if ($options{value} =~ /$$_[0]/i) {
$status = $$_[1];
return $status;
}
}
return $status;
}
1;
__END__
=head1 MODE
Check power supplies.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'enclosure-status -type all').
=item B<--filter>
Exclude some parts (comma seperated list)
Can also exclude specific instance: --filter=psu,ce#0_0
=item B<--threshold-overload>
Set to overload default threshold values (syntax: section,status,regexp)
It used before default thresholds (order stays).
Example: --threshold-overload='psu,CRITICAL,^(?!(Normal)$)'
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=back
=cut

View File

@ -0,0 +1,398 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::raidgroups;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::values;
my $thresholds = {
rg => [
['Available', 'OK'],
['Spare in Use', 'WARNING'],
],
};
my $instance_mode;
my $maps_counters = {
rg => {
'000_status' => {
set => { threshold => 0,
key_values => [ { name => 'status' } ],
closure_custom_calc => \&custom_status_calc,
output_template => 'Status : %s', output_error_template => 'Status : %s',
output_use => 'status',
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&custom_threshold_output,
}
},
'001_usage' => {
set => {
key_values => [ { name => 'display' }, { name => 'total' }, { name => 'used' } ],
closure_custom_calc => \&custom_usage_calc,
closure_custom_output => \&custom_usage_output,
closure_custom_perfdata => \&custom_usage_perfdata,
closure_custom_threshold_check => \&custom_usage_threshold,
},
},
}
};
sub custom_threshold_output {
my ($self, %options) = @_;
return $instance_mode->get_severity(section => 'rg', value => $self->{result_values}->{status});
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
return 0;
}
sub custom_usage_perfdata {
my ($self, %options) = @_;
my $extra_label = '';
if (!defined($options{extra_instance}) || $options{extra_instance} != 0) {
$extra_label .= '_' . $self->{result_values}->{display};
}
$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 = $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_usage_output {
my ($self, %options) = @_;
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free});
my $msg = sprintf("Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
$total_size_value . " " . $total_size_unit,
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
$total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free});
return $msg;
}
sub custom_usage_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_total'};
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_used'};
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
$self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total};
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
return 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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => 'raid-groups -csv' },
"threshold-overload:s@" => { name => 'threshold_overload' },
"no-component:s" => { name => 'no_component' },
"filter-name:s" => { name => 'filter_name' },
"filter-level:s" => { name => 'filter_level' },
});
$self->{no_components} = undef;
foreach my $key (('rg')) {
foreach (keys %{$maps_counters->{$key}}) {
my ($id, $name) = split /_/;
if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) {
$options{options}->add_options(arguments => {
'warning-' . $name . ':s' => { name => 'warning-' . $name },
'critical-' . $name . ':s' => { name => 'critical-' . $name },
});
}
$maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(output => $self->{output}, perfdata => $self->{perfdata},
label => $name);
$maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}});
}
}
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
foreach my $key (('rg')) {
foreach (keys %{$maps_counters->{$key}}) {
$maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results});
}
}
$instance_mode = $self;
$self->{overload_th} = {};
foreach my $val (@{$self->{option_results}->{threshold_overload}}) {
if ($val !~ /^(.*?),(.*?),(.*)$/) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'.");
$self->{output}->option_exit();
}
my ($section, $status, $filter) = ($1, $2, $3);
if ($self->{output}->is_litteral_status(status => $status) == 0) {
$self->{output}->add_option_msg(short_msg => "Wrong threshold-overload status '" . $val . "'.");
$self->{output}->option_exit();
}
$self->{overload_th}->{$section} = [] if (!defined($self->{overload_th}->{$section}));
push @{$self->{overload_th}->{$section}}, {filter => $filter, status => $status};
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection();
my $multiple = 1;
if (scalar(keys %{$self->{rg}}) == 1) {
$multiple = 0;
}
if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK',
short_msg => 'All Raid Groups are ok');
}
foreach my $id (sort keys %{$self->{rg}}) {
my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', '');
my @exits = ();
foreach (sort keys %{$maps_counters->{rg}}) {
my $obj = $maps_counters->{rg}->{$_}->{obj};
$obj->set(instance => $id);
my ($value_check) = $obj->execute(values => $self->{rg}->{$id});
if ($value_check != 0) {
$long_msg .= $long_msg_append . $obj->output_error();
$long_msg_append = ', ';
next;
}
my $exit2 = $obj->threshold_check();
push @exits, $exit2;
my $output = $obj->output();
$long_msg .= $long_msg_append . $output;
$long_msg_append = ', ';
if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) {
$short_msg .= $short_msg_append . $output;
$short_msg_append = ', ';
}
$obj->perfdata(extra_instance => $multiple);
}
$self->{output}->output_add(long_msg => "Raid Group '$self->{rg}->{$id}->{display}' $long_msg");
my $exit = $self->{output}->get_most_critical(status => [ @exits ]);
if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) {
$self->{output}->output_add(severity => $exit,
short_msg => "Raid Group '$self->{rg}->{$id}->{display}' $short_msg"
);
}
if ($multiple == 0) {
$self->{output}->output_add(short_msg => "Raid Group '$self->{rg}->{$id}->{display}' $long_msg");
}
}
$self->{output}->display();
$self->{output}->exit();
}
sub manage_selection {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#[RAID Group No.],[RAID Group Name],[RAID Level],[Assigned CM],[Status],[Total Capacity(MB)],[Free Capacity(MB)]
#1,RAIDGROUP001,RAID1+0,CM#0,Spare in Use,134656,132535
#2,RAIDGROUP002,RAID5,CM#1,Available,134656,132532
#3,RAIDGROUP003,RAID5,CM#1,SED Locked,134656,132532
$self->{rg} = {};
while ($stdout =~ /^(.*?),(.*?),(.*?),.*?,(.*?),(.*?),(.*?)$/msg) {
my ($raid_num, $raid_name, $raid_level, $raid_status, $raid_total, $raid_free) = ($1, $2, $3, $4, $5, $6);
next if ($raid_num =~ /\[.*?\]/);
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$raid_name !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "Skipping '" . $raid_name . "': no matching filter name.");
next;
}
if (defined($self->{option_results}->{filter_level}) && $self->{option_results}->{filter_level} ne '' &&
$raid_level !~ /$self->{option_results}->{filter_level}/) {
$self->{output}->output_add(long_msg => "Skipping '" . $raid_name . "': no matching filter level.");
next;
}
$self->{rg}->{$raid_num} = { status => $raid_status, total => $raid_total * 1024 * 1024,
used => ($raid_total * 1024 * 1024) - ($raid_free * 1024 * 1024),
display => $raid_name };
}
if (defined($self->{option_results}->{no_component}) && scalar(keys %{$self->{rg}}) <= 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
}
sub get_severity {
my ($self, %options) = @_;
my $status = 'UNKNOWN'; # default
if (defined($self->{overload_th}->{$options{section}})) {
foreach (@{$self->{overload_th}->{$options{section}}}) {
if ($options{value} =~ /$_->{filter}/i) {
$status = $_->{status};
return $status;
}
}
}
foreach (@{$thresholds->{$options{section}}}) {
if ($options{value} =~ /$$_[0]/i) {
$status = $$_[1];
return $status;
}
}
return $status;
}
1;
__END__
=head1 MODE
Check raid groups.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'raid-groups -csv').
=item B<--threshold-overload>
Set to overload default threshold values (syntax: section,status,regexp)
It used before default thresholds (order stays).
Example: --threshold-overload='rg,CRITICAL,^(?!(Available|Spare)$)'
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=item B<--filter-name>
Filter by name (regexp can be used).
=item B<--filter-level>
Filter by raid level (regexp can be used).
=item B<--warning-usage>
Threshold warning (in percent).
=item B<--critical-usage>
Threshold critical (in percent).
=back
=cut

View File

@ -0,0 +1,367 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::mode::volumestats;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
use centreon::plugins::values;
my $maps_counters = {
vol => {
'000_read-iops' => {
set => {
key_values => [ { name => 'read_iops' }, { name => 'display' } ],
output_template => 'Read IOPS : %d',
perfdatas => [
{ label => 'read_iops', value => 'read_iops_absolute', template => '%d',
unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'001_write-iops' => {
set => {
key_values => [ { name => 'write_iops' }, { name => 'display' } ],
output_template => 'Write IOPS : %d',
perfdatas => [
{ label => 'write_iops', value => 'write_iops_absolute', template => '%d',
unit => 'iops', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'002_read-traffic' => {
set => {
key_values => [ { name => 'read_traffic' }, { name => 'display' } ],
output_template => 'Read Traffic : %s %s/s', output_change_bytes => 2,
perfdatas => [
{ label => 'read_traffic', value => 'read_traffic_absolute', template => '%d',
unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'003_write-traffic' => {
set => {
key_values => [ { name => 'write_traffic' }, { name => 'display' } ],
output_template => 'Write Traffic : %s %s/s', output_change_bytes => 2,
perfdatas => [
{ label => 'write_traffic', value => 'write_traffic_absolute', template => '%d',
unit => 'b/s', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'004_read-response-time' => {
set => {
key_values => [ { name => 'read_response_time' }, { name => 'display' } ],
output_template => 'Read Response Time : %d ms',
perfdatas => [
{ label => 'read_response_time', value => 'read_response_time_absolute', template => '%d',
unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'005_write-response-time' => {
set => {
key_values => [ { name => 'write_response_time' }, { name => 'display' } ],
output_template => 'Write Response Time : %d ms',
perfdatas => [
{ label => 'write_response_time', value => 'write_response_time_absolute', template => '%d',
unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'006_read-processing-time' => {
set => {
key_values => [ { name => 'read_processing_time' }, { name => 'display' } ],
output_template => 'Read Processing Time : %d ms',
perfdatas => [
{ label => 'read_processing_time', value => 'read_processing_time_absolute', template => '%d',
unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'007_write-processing-time' => {
set => {
key_values => [ { name => 'write_processing_time' }, { name => 'display' } ],
output_template => 'Write Processing Time : %d ms',
perfdatas => [
{ label => 'write_processing_time', value => 'write_processing_time_absolute', template => '%d',
unit => 'ms', min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'008_read-cache-hit-rate' => {
set => {
key_values => [ { name => 'read_cache_hit_rate' }, { name => 'display' } ],
output_template => 'Read Cache Hit Rate : %d %%',
perfdatas => [
{ label => 'read_cache_hit_rate', value => 'read_cache_hit_rate_absolute', template => '%d',
unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_absolute' },
],
},
},
'009_write-cache-hit-rate' => {
set => {
key_values => [ { name => 'write_cache_hit_rate' }, { name => 'display' } ],
output_template => 'Write Cache Hit Rate : %d %%',
perfdatas => [
{ label => 'write_cache_hit_rate', value => 'write_cache_hit_rate_absolute', template => '%d',
unit => '%', min => 0, max => 100, label_extra_instance => 1, instance_use => 'display_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 =>
{
"hostname:s" => { name => 'hostname' },
"ssh-option:s@" => { name => 'ssh_option' },
"ssh-path:s" => { name => 'ssh_path' },
"ssh-command:s" => { name => 'ssh_command', default => 'ssh' },
"timeout:s" => { name => 'timeout', default => 30 },
"command:s" => { name => 'command', default => 'show' },
"command-path:s" => { name => 'command_path' },
"command-options:s" => { name => 'command_options', default => ' performance -type host-io' },
"no-component:s" => { name => 'no_component' },
"filter-name:s" => { name => 'filter_name' },
});
$self->{no_components} = undef;
foreach my $key (('vol')) {
foreach (keys %{$maps_counters->{$key}}) {
my ($id, $name) = split /_/;
if (!defined($maps_counters->{$key}->{$_}->{threshold}) || $maps_counters->{$key}->{$_}->{threshold} != 0) {
$options{options}->add_options(arguments => {
'warning-' . $name . ':s' => { name => 'warning-' . $name },
'critical-' . $name . ':s' => { name => 'critical-' . $name },
});
}
$maps_counters->{$key}->{$_}->{obj} = centreon::plugins::values->new(output => $self->{output}, perfdata => $self->{perfdata},
label => $name);
$maps_counters->{$key}->{$_}->{obj}->set(%{$maps_counters->{$key}->{$_}->{set}});
}
}
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
if (defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '') {
$self->{option_results}->{remote} = 1;
}
foreach my $key (('vol')) {
foreach (keys %{$maps_counters->{$key}}) {
$maps_counters->{$key}->{$_}->{obj}->init(option_results => $self->{option_results});
}
}
if (defined($self->{option_results}->{no_component})) {
if ($self->{option_results}->{no_component} ne '') {
$self->{no_components} = $self->{option_results}->{no_component};
} else {
$self->{no_components} = 'critical';
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection();
my $multiple = 1;
if (scalar(keys %{$self->{vol}}) == 1) {
$multiple = 0;
}
if ($multiple == 1) {
$self->{output}->output_add(severity => 'OK',
short_msg => 'All Volumes are ok');
}
foreach my $id (sort keys %{$self->{vol}}) {
my ($short_msg, $short_msg_append, $long_msg, $long_msg_append) = ('', '', '', '');
my @exits = ();
foreach (sort keys %{$maps_counters->{vol}}) {
my $obj = $maps_counters->{vol}->{$_}->{obj};
$obj->set(instance => $id);
my ($value_check) = $obj->execute(values => $self->{vol}->{$id});
if ($value_check != 0) {
$long_msg .= $long_msg_append . $obj->output_error();
$long_msg_append = ', ';
next;
}
my $exit2 = $obj->threshold_check();
push @exits, $exit2;
my $output = $obj->output();
$long_msg .= $long_msg_append . $output;
$long_msg_append = ', ';
if (!$self->{output}->is_status(litteral => 1, value => $exit2, compare => 'ok')) {
$short_msg .= $short_msg_append . $output;
$short_msg_append = ', ';
}
$obj->perfdata(extra_instance => $multiple);
}
$self->{output}->output_add(long_msg => "Volume '$self->{vol}->{$id}->{display}' $long_msg");
my $exit = $self->{output}->get_most_critical(status => [ @exits ]);
if (!$self->{output}->is_status(litteral => 1, value => $exit, compare => 'ok')) {
$self->{output}->output_add(severity => $exit,
short_msg => "Volume '$self->{vol}->{$id}->{display}' $short_msg"
);
}
if ($multiple == 0) {
$self->{output}->output_add(short_msg => "Volume '$self->{vol}->{$id}->{display}' $long_msg");
}
}
$self->{output}->display();
$self->{output}->exit();
}
sub manage_selection {
my ($self, %options) = @_;
my $stdout = centreon::plugins::misc::execute(output => $self->{output},
options => $self->{option_results},
command => $self->{option_results}->{command},
command_path => $self->{option_results}->{command_path},
command_options => $self->{option_results}->{command_options});
#Volume IOPS(IOPS) Throughput(MB/s) Response Time(msec.) Processing Time(msec.) Cache Hit Rate(%)
#No. Name Read / Write Read / Write Read / Write Read / Write Read / Write / Prefetch
#----- -------------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
# 1 VOL001 6621 5192 589 379 17055 12056 10025 10010 41 37 36
# 2 VOL002 7791 6608 613 292 12148 11045 10005 10007 41 37 36
$self->{vol} = {};
foreach (split /\n/, $stdout) {
next if ($_ !~ /^\s*(\d+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/);
my @matches = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$matches[1] !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "Skipping '" . $matches[1] . "': no matching filter name.");
next;
}
$self->{vol}->{$matches[0]} = { display => $matches[1],
read_iops => $matches[2], write_iops => $matches[3],
read_traffic => $matches[4] * 1000 * 1000 * 8,
write_traffic => $matches[5] * 1000 * 1000 * 8,
read_response_time => $matches[6], write_response_time => $matches[7],
read_processing_time => $matches[8], write_processing_time => $matches[9],
read_cache_hit_rate => $matches[10], write_cache_hit_rate => $matches[11],
};
}
if (defined($self->{option_results}->{no_component}) && scalar(keys %{$self->{vol}}) <= 0) {
$self->{output}->output_add(severity => $self->{no_components},
short_msg => 'No components are checked.');
}
}
1;
__END__
=head1 MODE
Check Volume statistics.
=over 8
=item B<--hostname>
Hostname to query.
=item B<--ssh-option>
Specify multiple options like the user (example: --ssh-option='-l=centreon-engine' --ssh-option='-p=52').
=item B<--ssh-path>
Specify ssh command path (default: none)
=item B<--ssh-command>
Specify ssh command (default: 'ssh'). Useful to use 'plink'.
=item B<--timeout>
Timeout in seconds for the command (Default: 30).
=item B<--command>
Command to get information (Default: 'show').
Can be changed if you have output in a file.
=item B<--command-path>
Command path (Default: none).
=item B<--command-options>
Command options (Default: 'performance -type host-io').
=item B<--no-component>
Return an error if no compenents are checked.
If total (with skipped) is 0. (Default: 'critical' returns).
=item B<--filter-name>
Filter by name (regexp can be used).
=item B<--warning-*>
Threshold warning.
Can be: 'read-iops', 'write-iops', 'read-traffic', 'write-traffic',
'read-response-time', 'write-response-time', 'read-processing-time', 'write-processing-time',
'read-cache-hit-rate', 'write-cache-hit-rate'.
=item B<--critical-*>
Threshold critical.
Can be: 'read-iops', 'write-iops', 'read-traffic', 'write-traffic',
'read-response-time', 'write-response-time', 'read-processing-time', 'write-processing-time',
'read-cache-hit-rate', 'write-cache-hit-rate'.
=back
=cut

View File

@ -0,0 +1,54 @@
#
# Copyright 2015 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::fujitsu::eternus::dx::ssh::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_simple);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
# $options->{options} = options object
$self->{version} = '1.0';
%{$self->{modes}} = (
'physicaldisk' => 'storage::fujitsu::eternus::dx::ssh::mode::physicaldisk',
'psu' => 'storage::fujitsu::eternus::dx::ssh::mode::psu',
'raid-groups' => 'storage::fujitsu::eternus::dx::ssh::mode::raidgroups',
'volume-stats' => 'storage::fujitsu::eternus::dx::ssh::mode::volumestats',
'cpu' => 'storage::fujitsu::eternus::dx::ssh::mode::cpu',
'port-stats' => 'storage::fujitsu::eternus::dx::ssh::mode::portstats',
);
return $self;
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check Fujitsu Eternnus DX storage in SSH.
=cut