add hp eva plugin
This commit is contained in:
parent
302d1ad8cc
commit
7f07d9b416
|
@ -0,0 +1,211 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::custom::api;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::misc;
|
||||
use XML::Simple;
|
||||
|
||||
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 =>
|
||||
{
|
||||
"manager-hostname:s" => { name => 'manager_hostname' },
|
||||
"manager-username:s" => { name => 'manager_username' },
|
||||
"manager-password:s" => { name => 'manager_password' },
|
||||
"manager-system:s" => { name => 'manager_system' },
|
||||
"timeout:s" => { name => 'timeout', default => 50 },
|
||||
"sudo" => { name => 'sudo' },
|
||||
"command:s" => { name => 'command', default => 'sssu_linux_x64' },
|
||||
"command-path:s" => { name => 'command_path' },
|
||||
"command-options:s" => { name => 'command_options', default => '' },
|
||||
});
|
||||
}
|
||||
$options{options}->add_help(package => __PACKAGE__, sections => 'SSU CLI OPTIONS', once => 1);
|
||||
|
||||
$self->{output} = $options{output};
|
||||
$self->{mode} = $options{mode};
|
||||
|
||||
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) = @_;
|
||||
|
||||
if (!defined($self->{option_results}->{manager_hostname}) || $self->{option_results}->{manager_hostname} eq '') {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to set manager-hostname option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{manager_username}) || $self->{option_results}->{manager_username} eq '') {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to set manager-username option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{manager_password})) {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to set manager-password option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($self->{option_results}->{manager_system}) || $self->{option_results}->{manager_system} eq '') {
|
||||
$self->{output}->add_option_msg(short_msg => "Need to set manager-system option.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub ssu_build_options {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne '');
|
||||
$self->{option_results}->{command_options} =
|
||||
"'select manager \"$self->{option_results}->{manager_hostname}\" USERNAME=$self->{option_results}->{manager_username} PASSWORD=$self->{option_results}->{manager_password}' 'select system $self->{option_results}->{manager_system}'";
|
||||
foreach my $cmd (keys %{$options{commands}}) {
|
||||
$self->{option_results}->{command_options} .= " '$cmd'";
|
||||
}
|
||||
}
|
||||
|
||||
sub ssu_execute {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->ssu_build_options(%options);
|
||||
my ($response) = centreon::plugins::misc::execute(output => $self->{output},
|
||||
options => $self->{option_results},
|
||||
sudo => $self->{option_results}->{sudo},
|
||||
command => $self->{option_results}->{command},
|
||||
command_path => $self->{option_results}->{command_path},
|
||||
command_options => $self->{option_results}->{command_options});
|
||||
my $xml_root = '<root>';
|
||||
while ($response =~ /(<object>.*?<\/object>)/msig) {
|
||||
$xml_root .= $1;
|
||||
}
|
||||
$xml_root .= '</root>';
|
||||
|
||||
my $xml_result;
|
||||
eval {
|
||||
$xml_result = XMLin($xml_root,
|
||||
ForceArray => ['object', 'diskslot', 'powersupply', 'sensor', 'fan', 'deviceport',
|
||||
'module', 'vdcoutput', 'source'],
|
||||
KeyAttr => [], SuppressEmpty => '');
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot decode xml response: $@");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$self->{output}->output_add(long_msg => $response, debug => 1);
|
||||
return $xml_result;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
SSU CLI
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
ssu cli
|
||||
|
||||
=head1 SSU CLI OPTIONS
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--manager-hostname>
|
||||
|
||||
Manager hostname to query.
|
||||
|
||||
=item B<--manager-username>
|
||||
|
||||
Manager username.
|
||||
|
||||
=item B<--manager-password>
|
||||
|
||||
Manager password.
|
||||
|
||||
=item B<--manager-system>
|
||||
|
||||
Manager system.
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Set timeout (Default: 50).
|
||||
|
||||
=item B<--sudo>
|
||||
|
||||
Use 'sudo' to execute the command.
|
||||
|
||||
=item B<--command>
|
||||
|
||||
Command to get information (Default: 'sssu_linux_x64').
|
||||
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: none).
|
||||
|
||||
=back
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<custom>.
|
||||
|
||||
=cut
|
|
@ -0,0 +1,66 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::battery;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls controller full xml'} = 1;
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking cache batteries");
|
||||
$self->{components}->{battery} = {name => 'cache battery', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'battery'));
|
||||
|
||||
# <object>
|
||||
# <objecttype>controller</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Controller Enclosure 7\Controller B</objectname>
|
||||
# <cachebattery>
|
||||
# <operationalstate>good</operationalstate>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'controller');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
my $instance = $object->{objectname};
|
||||
|
||||
next if ($self->check_filter(section => 'battery', instance => $instance));
|
||||
|
||||
$self->{components}->{battery}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("cache battery '%s' status is '%s' [instance = %s]",
|
||||
$instance, $object->{cachebattery}->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'battery', value => $object->{cachebattery}->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Cache battery '%s' status is '%s'", $instance, $object->{cachebattery}->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::disk;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls disk full xml'} = 1;
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking disks");
|
||||
$self->{components}->{disk} = {name => 'disks', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'disk'));
|
||||
|
||||
# <object>
|
||||
# <objecttype>disk</objecttype>
|
||||
# <objectname>\Disk Groups\Ungrouped Disks\Disk 133</objectname>
|
||||
# <operationalstate>good</operationalstate>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'disk');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
my $instance = $object->{objectname};
|
||||
|
||||
next if ($self->check_filter(section => 'disk', instance => $instance));
|
||||
|
||||
$self->{components}->{disk}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("disk '%s' status is '%s' [instance = %s]",
|
||||
$instance, $object->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'disk', value => $object->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Disk '%s' status is '%s'", $instance, $object->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::diskgrp;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls disk_group full xml'} = 1;
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking disk groups");
|
||||
$self->{components}->{diskgrp} = {name => 'disk groups', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'diskgrp'));
|
||||
|
||||
# <object>
|
||||
# <objecttype>diskgroupfolder</objecttype>
|
||||
# <objectname>\Disk Groups\XXX</objectname>
|
||||
# <operationalstate>good</operationalstate>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'diskgroupfolder');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
my $instance = $object->{objectname};
|
||||
|
||||
next if ($self->check_filter(section => 'diskgrp', instance => $instance));
|
||||
|
||||
$self->{components}->{diskgrp}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("disk group '%s' status is '%s' [instance = %s]",
|
||||
$instance, $object->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'diskgrp', value => $object->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Disk group '%s' status is '%s'", $instance, $object->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,135 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::fan;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls diskshelf full xml'} = 1;
|
||||
$self->{ssu_commands}->{'ls controller full xml'} = 1;
|
||||
}
|
||||
|
||||
sub fan_ctrl {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>controller</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Controller Enclosure 7\Controller B</objectname>
|
||||
# <fans>
|
||||
# <fan>
|
||||
# <fanname>fan0</fanname>
|
||||
# <status>normal</status>
|
||||
# <speed>2240</speed>
|
||||
# </fan>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'controller');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{fans}->{fan}}) {
|
||||
my $instance = $object->{objectname} . '/' . $result->{fanname};
|
||||
|
||||
next if ($self->check_filter(section => 'fan', instance => $instance));
|
||||
next if ($result->{status} =~ /notinstalled/i &&
|
||||
$self->absent_problem(section => 'fan', instance => $instance));
|
||||
|
||||
$self->{components}->{fan}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s] [value = %s]",
|
||||
$instance, $result->{status}, $instance,
|
||||
$result->{speed}));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{status});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{status}));
|
||||
}
|
||||
|
||||
next if ($result->{speed} !~ /[0-9]/);
|
||||
my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'fan', instance => $instance, value => $result->{speed});
|
||||
if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit2,
|
||||
short_msg => sprintf("Fan '%s' is %s rpm", $instance, $result->{speed}));
|
||||
}
|
||||
$self->{output}->perfdata_add(label => 'fan_' . $instance, unit => 'rpm',
|
||||
value => $result->{speed},
|
||||
warning => $warn,
|
||||
critical => $crit,
|
||||
min => 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub fan_diskshelf {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>diskshelf</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Disk Enclosure 3</objectname>
|
||||
# <cooling>
|
||||
# <fans>
|
||||
# <fan>
|
||||
# <name>fan1</name>
|
||||
# <operationalstate>good</operationalstate>
|
||||
# <failprediction>No</failprediction>
|
||||
# <speed>speed_1_lowest</speed>
|
||||
# </fan>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'diskshelf');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{cooling}->{fans}->{fan}}) {
|
||||
my $instance = $object->{objectname} . '/' . $result->{name};
|
||||
|
||||
next if ($self->check_filter(section => 'fan', instance => $instance));
|
||||
next if ($result->{operationalstate} =~ /notinstalled/i &&
|
||||
$self->absent_problem(section => 'fan', instance => $instance));
|
||||
|
||||
$self->{components}->{fan}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("fan '%s' status is '%s' [instance = %s]",
|
||||
$instance, $result->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'fan', value => $result->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Fan '%s' status is '%s'", $instance, $result->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking fans");
|
||||
$self->{components}->{fan} = {name => 'fans', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'fan'));
|
||||
|
||||
fan_ctrl($self);
|
||||
fan_diskshelf($self);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,72 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::iomodule;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls diskshelf full xml'} = 1;
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking IO modules");
|
||||
$self->{components}->{iomodule} = {name => 'io modules', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'iomodule'));
|
||||
|
||||
# <object>
|
||||
# <objecttype>diskshelf</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Disk Enclosure 3</objectname>
|
||||
# <iocomm>
|
||||
# <iomodules>
|
||||
# <module>
|
||||
# <name>modulea</name>
|
||||
# <operationalstate>good</operationalstate>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'diskshelf');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{iocomm}->{iomodules}->{module}}) {
|
||||
next if ($result->{name} eq '');
|
||||
my $instance = $object->{objectname} . '/' . $result->{name};
|
||||
|
||||
next if ($self->check_filter(section => 'iomodule', instance => $instance));
|
||||
|
||||
$self->{components}->{iomodule}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("IO module '%s' status is '%s' [instance = %s]",
|
||||
$instance, $object->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'iomodule', value => $object->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("IO module '%s' status is '%s'", $instance, $object->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,146 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::psu;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls diskshelf full xml'} = 1;
|
||||
$self->{ssu_commands}->{'ls controller full xml'} = 1;
|
||||
}
|
||||
|
||||
sub psu_ctrl {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>controller</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Controller Enclosure 7\Controller B</objectname>
|
||||
# <powersources>
|
||||
# <powerlevel>12.32</powerlevel>
|
||||
# <source>
|
||||
# <type>powersupply0</type>
|
||||
# <state>good</state>
|
||||
# </source>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'controller');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{powersources}->{source}}) {
|
||||
next if ($result->{type} eq '');
|
||||
my $instance = $object->{objectname} . '/' . $result->{type};
|
||||
|
||||
next if ($self->check_filter(section => 'psu', instance => $instance));
|
||||
next if ($result->{state} =~ /notinstalled/i &&
|
||||
$self->absent_problem(section => 'psu', instance => $instance));
|
||||
|
||||
$self->{components}->{psu}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("power supply '%s' status is '%s' [instance = %s]",
|
||||
$instance, $result->{state}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{state});
|
||||
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'", $instance, $result->{state}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub psu_diskshelf {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>diskshelf</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Disk Enclosure 3</objectname>
|
||||
# <powersupplies>
|
||||
# <powersupply>
|
||||
# <name>powersupply1</name>
|
||||
# <operationalstate>good</operationalstate>
|
||||
# <failurepredicted>No</failurepredicted>
|
||||
# <vdcoutputs>
|
||||
# <vdcoutput>
|
||||
# <type>vdc5output</type>
|
||||
# <voltage>5.5</voltage>
|
||||
# <current>6.7</current>
|
||||
# </vdcoutput>
|
||||
# <vdcoutput>
|
||||
# <type>vdc12output</type>
|
||||
# <voltage>12.5</voltage>
|
||||
# <current>4.1</current>
|
||||
# </vdcoutput>
|
||||
# </vdcoutputs>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'diskshelf');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{powersupplies}->{powersupply}}) {
|
||||
my $instance = $object->{objectname} . '/' . $result->{name};
|
||||
|
||||
next if ($self->check_filter(section => 'psu', instance => $instance));
|
||||
next if ($result->{operationalstate} =~ /notinstalled/i &&
|
||||
$self->absent_problem(section => 'psu', instance => $instance));
|
||||
|
||||
$self->{components}->{psu}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("power suuply '%s' status is '%s' [instance = %s]",
|
||||
$instance, $result->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'psu', value => $result->{operationalstate});
|
||||
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'", $instance, $result->{operationalstate}));
|
||||
}
|
||||
|
||||
foreach my $voltage (@{$result->{vdcoutputs}->{vdcoutput}}) {
|
||||
next if ($voltage->{current} !~ /[0-9]/);
|
||||
my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'psu', instance => $instance . '/' . $voltage->{type}, value => $voltage->{current});
|
||||
if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit2,
|
||||
short_msg => sprintf("Power supply '%s' is %s V", $instance, $voltage->{current}));
|
||||
}
|
||||
$self->{output}->perfdata_add(label => 'voltage_' . $instance . '/' . $voltage->{type}, unit => 'V',
|
||||
value => $voltage->{current},
|
||||
warning => $warn,
|
||||
critical => $crit,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking power supplies");
|
||||
$self->{components}->{psu} = {name => 'psus', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'psu'));
|
||||
|
||||
psu_ctrl($self);
|
||||
psu_diskshelf($self);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,65 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::system;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls system full xml'} = 1;
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking systems");
|
||||
$self->{components}->{system} = {name => 'systems', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'system'));
|
||||
|
||||
# <object>
|
||||
# <objecttype>storagecell</objecttype>
|
||||
# <objectname>Backup_Wintel</objectname>
|
||||
# <operationalstate>attention</operationalstate>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'storagecell');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
my $instance = $object->{objectname};
|
||||
|
||||
next if ($self->check_filter(section => 'system', instance => $instance));
|
||||
|
||||
$self->{components}->{system}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("system '%s' status is '%s' [instance = %s]",
|
||||
$instance, $object->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'system', value => $object->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("System '%s' status is '%s'", $instance, $object->{operationalstate}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,141 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::components::temperature;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub load {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{ssu_commands}->{'ls diskshelf full xml'} = 1;
|
||||
$self->{ssu_commands}->{'ls controller full xml'} = 1;
|
||||
}
|
||||
|
||||
sub temp_ctrl {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>controller</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Controller Enclosure 7\Controller B</objectname>
|
||||
# <sensors>
|
||||
# <sensor>
|
||||
# <name>i2csensor1</name>
|
||||
# <tempc>28</tempc>
|
||||
# <tempf>82</tempf>
|
||||
# </sensor>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'controller');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{sensors}->{sensor}}) {
|
||||
next if ($result->{name} eq '');
|
||||
my $instance = $object->{objectname} . '/' . $result->{name};
|
||||
|
||||
next if ($self->check_filter(section => 'temperature', instance => $instance));
|
||||
|
||||
$self->{components}->{temperature}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("temperature '%s' is %s C [instance = %s]",
|
||||
$instance, $result->{tempc}, $instance,
|
||||
));
|
||||
|
||||
next if ($result->{tempc} !~ /[0-9]/);
|
||||
my ($exit, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{tempc});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Temperature '%s' is %s C", $instance, $result->{tempc}));
|
||||
}
|
||||
$self->{output}->perfdata_add(label => 'temperature_' . $instance, unit => 'C',
|
||||
value => $result->{tempc},
|
||||
warning => $warn,
|
||||
critical => $crit,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub temp_diskshelf {
|
||||
my ($self) = @_;
|
||||
|
||||
# <object>
|
||||
# <objecttype>diskshelf</objecttype>
|
||||
# <objectname>\Hardware\Rack 1\Disk Enclosure 3</objectname>
|
||||
# <cooling>
|
||||
# <sensors>
|
||||
# <sensor>
|
||||
# <name>ps1</name>
|
||||
# <tempf>91.4</tempf>
|
||||
# <tempc>33.0</tempc>
|
||||
# <operationalstate>good</operationalstate>
|
||||
# <tempalarmstatus>no_alarm</tempalarmstatus>
|
||||
# </sensor>
|
||||
foreach my $object (@{$self->{xml_result}->{object}}) {
|
||||
next if ($object->{objecttype} ne 'diskshelf');
|
||||
|
||||
$object->{objectname} =~ s/\\/\//g;
|
||||
foreach my $result (@{$object->{cooling}->{sensors}->{sensor}}) {
|
||||
next if ($result->{name} eq '');
|
||||
my $instance = $object->{objectname} . '/' . $result->{name};
|
||||
|
||||
next if ($self->check_filter(section => 'temperature', instance => $instance));
|
||||
next if ($result->{operationalstate} =~ /notinstalled/i &&
|
||||
$self->absent_problem(section => 'temperature', instance => $instance));
|
||||
|
||||
$self->{components}->{temperature}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("temperature '%s' status is '%s' [instance = %s]",
|
||||
$instance, $result->{operationalstate}, $instance,
|
||||
));
|
||||
|
||||
my $exit = $self->get_severity(label => 'default', section => 'temperature', value => $result->{operationalstate});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Temperature '%s' status is '%s'", $instance, $result->{operationalstate}));
|
||||
}
|
||||
|
||||
next if ($result->{tempc} !~ /[0-9]/);
|
||||
my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'temperature', instance => $instance, value => $result->{tempc});
|
||||
if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit2,
|
||||
short_msg => sprintf("Temperature '%s' is %s C", $instance, $result->{tempc}));
|
||||
}
|
||||
$self->{output}->perfdata_add(label => 'temperature_' . $instance, unit => 'C',
|
||||
value => $result->{tempc},
|
||||
warning => $warn,
|
||||
critical => $crit,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub check {
|
||||
my ($self) = @_;
|
||||
|
||||
$self->{output}->output_add(long_msg => "Checking temperatures");
|
||||
$self->{components}->{temperature} = {name => 'temperatures', total => 0, skip => 0};
|
||||
return if ($self->check_filter(section => 'temperature'));
|
||||
|
||||
temp_ctrl($self);
|
||||
temp_diskshelf($self);
|
||||
}
|
||||
|
||||
1;
|
|
@ -0,0 +1,120 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::mode::hardware;
|
||||
|
||||
use base qw(centreon::plugins::templates::hardware);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_system {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{regexp_threshold_overload_check_section_option} =
|
||||
'^(fan|temperature|system|disk|diskgrp|psu|battery|iomodule)$';
|
||||
$self->{regexp_threshold_numeric_check_section_option} = '^(fan|temperature|psu)$';
|
||||
|
||||
$self->{cb_hook2} = 'api_execute';
|
||||
|
||||
$self->{thresholds} = {
|
||||
default => [
|
||||
['^good$', 'OK'],
|
||||
['notinstalled', 'OK'],
|
||||
['^normal$', 'OK'],
|
||||
['unsupported', 'OK'],
|
||||
['attention', 'WARNING'],
|
||||
['.*', 'CRITICAL'],
|
||||
],
|
||||
};
|
||||
|
||||
$self->{components_path} = 'storage::hp::eva::cli::mode::components';
|
||||
$self->{components_module} = ['fan', 'temperature', 'system', 'disk', 'diskgrp', 'psu', 'battery', 'iomodule'];
|
||||
}
|
||||
|
||||
sub api_execute {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{xml_result} = $options{custom}->ssu_execute(commands => $self->{ssu_commands});
|
||||
}
|
||||
|
||||
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 =>
|
||||
{
|
||||
});
|
||||
|
||||
$self->{ssu_commands} = {};
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check hardware.
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--component>
|
||||
|
||||
Which component to check (Default: '.*').
|
||||
Can be: 'fan'.
|
||||
|
||||
=item B<--filter>
|
||||
|
||||
Exclude some parts (comma seperated list) (Example: --filter=temperature --filter=fan)
|
||||
Can also exclude specific instance: --filter="fan,Fan Block 1"
|
||||
|
||||
=item B<--absent-problem>
|
||||
|
||||
Return an error if an entity is not 'present' (default is skipping)
|
||||
Can be specific or global: --absent-problem="fan,Fan Block 1"
|
||||
|
||||
=item B<--no-component>
|
||||
|
||||
Return an error if no compenents are checked.
|
||||
If total (with skipped) is 0. (Default: 'critical' returns).
|
||||
|
||||
=item B<--threshold-overload>
|
||||
|
||||
Set to overload default threshold values (syntax: section,[instance,]status,regexp)
|
||||
It used before default thresholds (order stays).
|
||||
Example: --threshold-overload='fan,OK,degraded'
|
||||
|
||||
=item B<--warning>
|
||||
|
||||
Set warning threshold for 'temperature', 'fan' (syntax: type,regexp,threshold)
|
||||
Example: --warning='temperature,.*,30'
|
||||
|
||||
=item B<--critical>
|
||||
|
||||
Set critical threshold for 'temperature', 'fan' (syntax: type,regexp,threshold)
|
||||
Example: --critical='temperature,.*,50'
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# Copyright 2017 Centreon (http://www.centreon.com/)
|
||||
#
|
||||
# Centreon is a full-fledged industry-strength solution that meets
|
||||
# the needs in IT infrastructure and application monitoring for
|
||||
# service performance.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
package storage::hp::eva::cli::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} = '0.1';
|
||||
%{$self->{modes}} = (
|
||||
'hardware' => 'storage::hp::eva::cli::mode::hardware',
|
||||
);
|
||||
$self->{custom_modes}{api} = 'storage::hp::eva::cli::custom::api';
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Check HP EVA Storage.
|
||||
|
||||
=over 8
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
Loading…
Reference in New Issue