From 88e21a496a81729ee0e681d99ecee86408baba50 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Tue, 8 Dec 2020 09:58:19 +0100 Subject: [PATCH] Fix #2339 --- .../p2000/xmlapi/{custom.pm => custom/api.pm} | 122 +++++++++--------- .../hp/p2000/xmlapi/mode/components/disk.pm | 15 ++- .../p2000/xmlapi/mode/components/enclosure.pm | 19 ++- .../hp/p2000/xmlapi/mode/components/fru.pm | 26 +++- .../hp/p2000/xmlapi/mode/components/sensor.pm | 2 +- .../hp/p2000/xmlapi/mode/components/vdisk.pm | 19 ++- .../storage/hp/p2000/xmlapi/mode/health.pm | 8 +- .../storage/hp/p2000/xmlapi/plugin.pm | 8 +- 8 files changed, 125 insertions(+), 94 deletions(-) rename centreon-plugins/storage/hp/p2000/xmlapi/{custom.pm => custom/api.pm} (76%) diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/custom.pm b/centreon-plugins/storage/hp/p2000/xmlapi/custom/api.pm similarity index 76% rename from centreon-plugins/storage/hp/p2000/xmlapi/custom.pm rename to centreon-plugins/storage/hp/p2000/xmlapi/custom/api.pm index 2fa0b050c..d67a85ad9 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/custom.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/custom/api.pm @@ -18,13 +18,13 @@ # limitations under the License. # -package storage::hp::p2000::xmlapi::custom; +package storage::hp::p2000::xmlapi::custom::api; use strict; use warnings; use centreon::plugins::http; -use XML::XPath; use Digest::MD5 qw(md5_hex); +use XML::LibXML::Simple; sub new { my ($class, %options) = @_; @@ -116,38 +116,34 @@ sub build_options_for_httplib { sub check_login { my ($self, %options) = @_; - my ($xpath, $nodeset); - + + my $xml; eval { - $xpath = XML::XPath->new(xml => $options{content}); - $nodeset = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='return-code']"); + $SIG{__WARN__} = sub {}; + $xml = XMLin($options{content}, ForceArray => [], KeyAttr => []); }; if ($@) { $self->{output}->add_option_msg(short_msg => "Cannot parse login response: $@"); $self->{output}->option_exit(); } - - if (scalar($nodeset->get_nodelist) == 0) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'Cannot find login response.'); - $self->{output}->display(); - $self->{output}->exit(); + + if (!defined($xml->{OBJECT}) || !defined($xml->{OBJECT}->{PROPERTY})) { + $self->{output}->add_option_msg(short_msg => 'Cannot find login response'); + $self->{output}->option_exit(); } - - foreach my $node ($nodeset->get_nodelist()) { - if ($node->string_value != 1) { - $self->{output}->output_add(severity => 'UNKNOWN', - short_msg => 'Login authentification failed (return-code: ' . $node->string_value . ').'); - $self->{output}->display(); - $self->{output}->exit(); - } + + my ($session_id, $return_code); + foreach (@{$xml->{OBJECT}->{PROPERTY}}) { + $return_code = $_->{content} if ($_->{name} eq 'return-code'); + $session_id = $_->{content} if ($_->{name} eq 'response'); } - - $nodeset = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='response']"); - my @nodes = $nodeset->get_nodelist(); - my $node = shift(@nodes); - - $self->{session_id} = $node->string_value; + + if ($return_code != 1) { + $self->{output}->add_option_msg(short_msg => 'Login authentification failed (return-code: ' . $return_code . ').'); + $self->{output}->option_exit(); + } + + $self->{session_id} = $session_id; $self->{logon} = 1; } @@ -175,12 +171,12 @@ sub get_infos { $self->login(); my $cmd = $options{cmd}; $cmd =~ s/ /\//g; - + my ($unknown_status, $warning_status, $critical_status) = ($self->{unknown_http_status}, $self->{warning_http_status}, $self->{critical_http_status}); if (defined($options{no_quit}) && $options{no_quit} == 1) { ($unknown_status, $warning_status, $critical_status) = ('', '', ''); } - my $response = $self->{http}->request( + my ($response) = $self->{http}->request( url_path => $self->{url_path} . $cmd, header => [ 'Cookie: wbisessionkey=' . $self->{session_id} . '; wbiusername=' . $self->{username}, @@ -188,19 +184,20 @@ sub get_infos { ], unknown_status => $unknown_status, warning_status => $warning_status, - critical_status => $critical_status, + critical_status => $critical_status ); + my $xml; eval { - $xpath = XML::XPath->new(xml => $response); - $nodeset = $xpath->find("//OBJECT[\@basetype='" . $options{base_type} . "']"); + $SIG{__WARN__} = sub {}; + $xml = XMLin($response, ForceArray => ['OBJECT'], KeyAttr => []); }; if ($@) { return ({}, 0) if (defined($options{no_quit}) && $options{no_quit} == 1); $self->{output}->add_option_msg(short_msg => "Cannot parse 'cmd' response: $@"); $self->{output}->option_exit(); } - + # Check if there is an error # #Error @@ -209,38 +206,44 @@ sub get_infos { #-10028 # # - if (my $nodestatus = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='return-code']")) { - my @nodes = $nodestatus->get_nodelist(); - my $node = shift @nodes; - my $return_code = $node->string_value; - if ($return_code != 0) { - $nodestatus = $xpath->find("//OBJECT[\@basetype='status']//PROPERTY[\@name='response']"); - @nodes = $nodestatus->get_nodelist(); - $node = shift @nodes; - return ({}, 0, $node->string_value) if (defined($options{no_quit}) && $options{no_quit} == 1); - $self->{output}->add_option_msg(short_msg => $node->string_value); - $self->{output}->option_exit(); - } - } - my $results = {}; - foreach my $node ($nodeset->get_nodelist()) { - my $properties = {}; + $results = [] if (!defined($options{key})); + foreach my $obj (@{$xml->{OBJECT}}) { + if ($obj->{basetype} eq 'status') { + my ($return_code, $response) = (-1, 'n/a'); + foreach my $prop (@{$obj->{PROPERTY}}) { + $return_code = $prop->{content} if ($prop->{name} eq 'return-code'); + $response = $prop->{content} if ($prop->{name} eq 'response'); + } - foreach my $prop_node ($node->getChildNodes()) { - my $prop_name = $prop_node->getAttribute('name'); - - if (defined($prop_name) && ($prop_name eq $options{key} || - $prop_name =~ /$options{properties_name}/)) { - $properties->{$prop_name} = $prop_node->string_value; + if ($return_code != 0) { + return ({}, 0) if (defined($options{no_quit}) && $options{no_quit} == 1); + $self->{output}->add_option_msg(short_msg => $response); + $self->{output}->option_exit(); } } - - if (defined($properties->{$options{key}})) { - $results->{$properties->{$options{key}}} = $properties; + + if ($obj->{basetype} eq $options{base_type}) { + my $properties = {}; + foreach (keys %$obj) { + $properties->{$_} = $obj->{$_} if (/$options{properties_name}/); + } + foreach my $prop (@{$obj->{PROPERTY}}) { + if (defined($prop->{name}) && + ((defined($options{key}) && $prop->{name} eq $options{key}) || $prop->{name} =~ /$options{properties_name}/)) { + $properties->{ $prop->{name} } = $prop->{content}; + } + } + + if (defined($options{key})) { + $results->{ $properties->{ $options{key} } } = $properties + if (defined($properties->{ $options{key} })); + } else { + push @$results, $properties; + } } } - + return ($results, 1); } @@ -254,7 +257,7 @@ sub login { $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); - + # Login First my $md5_hash = md5_hex($self->{username} . '_' . $self->{password}); my $response = $self->{http}->request( @@ -263,6 +266,7 @@ sub login { warning_status => $self->{warning_http_status}, critical_status => $self->{critical_http_status}, ); + $self->check_login(content => $response); } diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/disk.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/disk.pm index 791215ff2..90ffea760 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/disk.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/disk.pm @@ -52,13 +52,18 @@ sub check { my $state = $health{$results->{$disk_id}->{'health-numeric'}}; - $self->{output}->output_add(long_msg => sprintf("disk '%s' status is %s [instance: %s]", - $disk_id, $state, $disk_id) - ); + $self->{output}->output_add( + long_msg => sprintf( + "disk '%s' status is %s [instance: %s]", + $disk_id, $state, $disk_id + ) + ); my $exit = $self->get_severity(label => 'default', section => 'disk', value => $state); 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'", $disk_id, $state)); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Disk '%s' status is '%s'", $disk_id, $state) + ); } } } diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/enclosure.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/enclosure.pm index bdf6e9acd..61c5430c9 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/enclosure.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/enclosure.pm @@ -48,16 +48,21 @@ sub check { foreach my $enc_id (keys %$results) { next if ($self->check_filter(section => 'enclosure', instance => $enc_id)); $self->{components}->{enclosure}->{total}++; - + my $state = $health{$results->{$enc_id}->{'health-numeric'}}; - - $self->{output}->output_add(long_msg => sprintf("enclosure '%s' status is %s [instance: %s] [reason: %s]", - $enc_id, $state, $enc_id, $results->{$enc_id}->{'health-reason'}) - ); + + $self->{output}->output_add( + long_msg => sprintf( + "enclosure '%s' status is %s [instance: %s] [reason: %s]", + $enc_id, $state, $enc_id, $results->{$enc_id}->{'health-reason'} + ) + ); my $exit = $self->get_severity(label => 'default', section => 'enclosure', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Enclosure '%s' status is '%s'", $enc_id, $state)); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Enclosure '%s' status is '%s'", $enc_id, $state) + ); } } } diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/fru.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/fru.pm index 29404f901..bcfbd55ae 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/fru.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/fru.pm @@ -30,20 +30,32 @@ sub check { $self->{components}->{fru} = {name => 'frus', total => 0, skip => 0}; return if ($self->check_filter(section => 'fru')); - my ($results) = $self->{custom}->get_infos( + my ($entries) = $self->{custom}->get_infos( cmd => 'show frus', base_type => 'enclosure-fru', - key => 'fru-location', - properties_name => '^(fru-status|fru-location)$', + properties_name => '^fru-status|fru-location|oid$', no_quit => 1, ); - foreach my $part_number (keys %$results) { - my $instance = $results->{$part_number}->{'fru-location'}; - + + my ($results, $duplicated) = ({}, {}); + foreach (@$entries) { + my $name = $_->{'fru-location'}; + $name = $_->{'fru-location'} . ':' . $_->{oid} if (defined($duplicated->{$name})); + if (defined($results->{$name})) { + $duplicated->{$name} = 1; + my $instance = $results->{$name}->{'fru-location'} . ':' . $results->{$name}->{oid}; + $results->{$instance} = $results->{$name}; + delete $results->{$name}; + $name = $_->{'fru-location'} . ':' . $_->{oid}; + } + $results->{$name} = $_; + } + + foreach my $instance (keys %$results) { next if ($self->check_filter(section => 'fru', instance => $instance)); $self->{components}->{fru}->{total}++; - my $state = $results->{$part_number}->{'fru-status'}; + my $state = $results->{$instance}->{'fru-status'}; $self->{output}->output_add( long_msg => sprintf( diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/sensor.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/sensor.pm index 702b4e004..decefcfe4 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/sensor.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/sensor.pm @@ -48,7 +48,7 @@ sub check { cmd => 'show sensor-status', base_type => 'sensors', key => 'sensor-name', - properties_name => '^(value|sensor-type|status)$' + properties_name => '^(?:value|sensor-type|status)$' ); # diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/vdisk.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/vdisk.pm index 2343efa09..ad654c7ed 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/vdisk.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/components/vdisk.pm @@ -40,13 +40,18 @@ sub check_vdisk { my $state = $health{$options{results}->{$vdisk_id}->{'health-numeric'}}; - $self->{output}->output_add(long_msg => sprintf("vdisk '%s' status is %s [instance: %s]", - $vdisk_id, $state, $vdisk_id) - ); + $self->{output}->output_add( + long_msg => sprintf( + "vdisk '%s' status is %s [instance: %s]", + $vdisk_id, $state, $vdisk_id + ) + ); my $exit = $self->get_severity(label => 'default', section => 'vdisk', value => $state); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { - $self->{output}->output_add(severity => $exit, - short_msg => sprintf("Vdisk '%s' status is '%s'", $vdisk_id, $state)); + $self->{output}->output_add( + severity => $exit, + short_msg => sprintf("Vdisk '%s' status is '%s'", $vdisk_id, $state) + ); } } } @@ -63,7 +68,7 @@ sub check { base_type => 'virtual-disks', key => 'name', properties_name => '^health-numeric$', - no_quit => 1, + no_quit => 1 ); if ($code == 0) { ($results) = $self->{custom}->get_infos( @@ -71,7 +76,7 @@ sub check { base_type => 'disk-groups', key => 'name', properties_name => '^health-numeric$', - no_quit => 1, + no_quit => 1 ); } diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/mode/health.pm b/centreon-plugins/storage/hp/p2000/xmlapi/mode/health.pm index 784e2c540..850483206 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/mode/health.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/mode/health.pm @@ -39,19 +39,19 @@ sub set_system { ['ok', 'OK'], ['degraded', 'WARNING'], ['failed|fault', 'CRITICAL'], - ['unknown|not available', 'UNKNOWN'], + ['unknown|not available', 'UNKNOWN'] ], fru => [ ['ok', 'OK'], ['absent', 'WARNING'], ['fault', 'CRITICAL'], - ['not available', 'UNKNOWN'], + ['not available', 'UNKNOWN'] ], sensor => [ ['ok', 'OK'], ['warning|not installed|unavailable', 'WARNING'], ['error|unrecoverable', 'CRITICAL'], - ['unknown|unsupported', 'UNKNOWN'], + ['unknown|unsupported', 'UNKNOWN'] ], }; @@ -70,7 +70,7 @@ sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1); bless $self, $class; - + $options{options}->add_options(arguments => { }); diff --git a/centreon-plugins/storage/hp/p2000/xmlapi/plugin.pm b/centreon-plugins/storage/hp/p2000/xmlapi/plugin.pm index fbe1f20f2..857986b5b 100644 --- a/centreon-plugins/storage/hp/p2000/xmlapi/plugin.pm +++ b/centreon-plugins/storage/hp/p2000/xmlapi/plugin.pm @@ -31,13 +31,13 @@ sub new { bless $self, $class; $self->{version} = '0.1'; - %{$self->{modes}} = ( + $self->{modes} = { 'health' => 'storage::hp::p2000::xmlapi::mode::health', 'list-volumes' => 'storage::hp::p2000::xmlapi::mode::listvolumes', 'vdisks' => 'storage::hp::p2000::xmlapi::mode::vdisks', - 'volume-stats' => 'storage::hp::p2000::xmlapi::mode::volumesstats', - ); - $self->{custom_modes}{p2000xml} = 'storage::hp::p2000::xmlapi::custom'; + 'volume-stats' => 'storage::hp::p2000::xmlapi::mode::volumesstats' + }; + $self->{custom_modes}->{p2000xml} = 'storage::hp::p2000::xmlapi::custom::api'; return $self; }