From 1d922005b36a9984f9d9fcf16046385831503ed1 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Wed, 26 Aug 2015 14:05:27 +0200 Subject: [PATCH] + working on vplex --- storage/emc/vplex/restapi/custom/vplexapi.pm | 87 +++++----- storage/emc/vplex/restapi/mode/fans.pm | 160 ++++++++++++++----- 2 files changed, 170 insertions(+), 77 deletions(-) diff --git a/storage/emc/vplex/restapi/custom/vplexapi.pm b/storage/emc/vplex/restapi/custom/vplexapi.pm index c8b7c9472..04f194024 100644 --- a/storage/emc/vplex/restapi/custom/vplexapi.pm +++ b/storage/emc/vplex/restapi/custom/vplexapi.pm @@ -46,10 +46,11 @@ sub new { if (!defined($options{noptions})) { $options{options}->add_options(arguments => { - "hostname:s@" => { name => 'hostname', }, - "proxyurl:s@" => { name => 'proxyurl', }, - "timeout:s@" => { name => 'timeout', }, - "header:s@" => { name => 'header', }, + "hostname:s@" => { name => 'hostname', }, + "vplex-username:s@" => { name => 'vplex_username', }, + "vplex-password:s@" => { name => 'vplex_password', }, + "proxyurl:s@" => { name => 'proxyurl', }, + "timeout:s@" => { name => 'timeout', }, }); } $options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1); @@ -95,9 +96,9 @@ sub check_options { # # return 0 = no hostname left $self->{hostname} = (defined($self->{option_results}->{hostname})) ? shift(@{$self->{option_results}->{hostname}}) : undef; + $self->{vplex_username} = (defined($self->{option_results}->{vplex_username})) ? shift(@{$self->{option_results}->{vplex_username}}) : ''; + $self->{vplex_password} = (defined($self->{option_results}->{vplex_password})) ? shift(@{$self->{option_results}->{vplex_password}}) : ''; $self->{timeout} = (defined($self->{option_results}->{timeout})) ? shift(@{$self->{option_results}->{timeout}}) : 10; - $self->{port} = (defined($self->{option_results}->{port})) ? shift(@{$self->{option_results}->{port}}) : 443; - $self->{proto} = (defined($self->{option_results}->{proto})) ? shift(@{$self->{option_results}->{proto}}) : 'https'; $self->{proxyurl} = (defined($self->{option_results}->{proxyurl})) ? shift(@{$self->{option_results}->{proxyurl}}) : undef; if (!defined($self->{hostname})) { @@ -105,15 +106,6 @@ sub check_options { $self->{output}->option_exit(); } - if (defined($self->{option_results}->{header})) { - $self->{headers} = {}; - foreach (@{$self->{option_results}->{header}}) { - if (/^(.*?):(.*)/) { - $self->{headers}->{$1} = $2; - } - } - } - if (!defined($self->{hostname}) || scalar(@{$self->{option_results}->{hostname}}) == 0) { return 0; @@ -129,40 +121,53 @@ sub build_options_for_httplib { $self->{option_results}->{port} = 443; $self->{option_results}->{proto} = 'https'; $self->{option_results}->{proxyurl} = $self->{proxyurl}; - $self->{option_results}->{url_path} = $self->{url_path}; - + $self->{option_results}->{headers} = { Username => $self->{vplex_username}, Password => $self->{vplex_password} }; } -sub connect { +sub settings { my ($self, %options) = @_; $self->build_options_for_httplib(); $self->{http}->set_options(%{$self->{option_results}}); - } sub get_items { my ($self, %options) = @_; - my $url = $options{url}; - my $obj = $options{obj}; - my $engine = $options{engine}; + $self->settings(); - my @items; - if ($engine) { - $url .= $engine.'/'.$obj.'/'; - } elsif (defined $obj) { - $url .= '/'.$obj; + if (defined($options{engine}) && $options{engine} ne '') { + $options{url} .= 'engine-' . $options{engine}; + } else { + $options{url} .= '*'; + } + $options{url} = '/' . $options{obj} . '/*'; + + my $response = $self->{http}->request(url_path => $options{url}); + my $decoded; + eval { + $decoded = decode_json($response); }; - - my $response = $self->{http}->request(url_path => $url); - my $decoded = decode_json($response); - - foreach my $child (@{ $decoded->{response}->{context}->[0]->{children} } ) { - push @items, $child->{name}; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode json response"); + $self->{output}->option_exit(); + } + + my $items = {}; + foreach my $context (@{$decoded->{response}->{context}}) { + $context->{parent} =~ /\engines\/(.*?)\//; + my $engine_name = $1; + $items->{$engine_name} = {} if (!defined($items->{$engine_name})); + + my $attributes = {}; + foreach my $attribute (@{$context->{attributes}}) { + $attributes->{$attribute->{name}} = $attribute->{value}; + } + + $items->{$engine_name}->{$attributes->{name}} = $attributes; } - return @items; + return $items; } sub get_param { @@ -230,7 +235,15 @@ Vplex Rest API custom mode =item B<--hostname> -Vplex Hostname. +Vplex hostname. + +=item B<--vplex-username> + +Vplex username. + +=item B<--vplex-password> + +Vplex password. =item B<--proxyurl> @@ -240,10 +253,6 @@ Proxy URL if any Set HTTP timeout -=item B<--header> - -Set HTTPS Headers (specify multiple time e.g ) - =back =head1 DESCRIPTION diff --git a/storage/emc/vplex/restapi/mode/fans.pm b/storage/emc/vplex/restapi/mode/fans.pm index 8463771a8..eb7d4917a 100644 --- a/storage/emc/vplex/restapi/mode/fans.pm +++ b/storage/emc/vplex/restapi/mode/fans.pm @@ -25,6 +25,17 @@ use base qw(centreon::plugins::mode); use strict; use warnings; +my $thresholds = { + fan_opstatus => [ + ['online', 'OK'], + ['.*', 'CRITICAL'], + ], + fan => [ + ['false', 'OK'], + ['.*', 'CRITICAL'], + ], +}; + sub new { my ($class, %options) = @_; my $self = $class->SUPER::new(package => __PACKAGE__, %options); @@ -33,8 +44,9 @@ sub new { $self->{version} = '1.1'; $options{options}->add_options(arguments => { - "engine:s" => { name => 'engine' }, - "filter-name:s" => { name => 'filter_name' }, + "engine:s" => { name => 'engine' }, + "filter:s@" => { name => 'filter' }, + "threshold-overload:s@" => { name => 'threshold_overload' }, }); return $self; @@ -43,57 +55,122 @@ sub new { sub check_options { my ($self, %options) = @_; $self->SUPER::init(%options); + + $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}}) { + next if (!defined($val) || $val eq ''); + my @values = split (/,/, $val); + if (scalar(@values) < 3) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload option '" . $val . "'."); + $self->{output}->option_exit(); + } + my ($section, $instance, $status, $filter); + if (scalar(@values) == 3) { + ($section, $status, $filter) = @values; + $instance = '.*'; + } else { + ($section, $instance, $status, $filter) = @values; + } + if ($section !~ /^fan|fan_opstatus$/) { + $self->{output}->add_option_msg(short_msg => "Wrong threshold-overload section '" . $val . "'."); + $self->{output}->option_exit(); + } + 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, instance => $instance }; + } } sub run { my ($self, %options) = @_; my $vplex = $options{custom}; - my $urlbase = '/vplex/engines/engine-'; - + my $urlbase = '/vplex/engines/'; $self->{output}->output_add(severity => 'OK', short_msg => 'All Fans are OK'); - $vplex->connect(); - my @items = $vplex->get_items(url => $urlbase, + my $items = $vplex->get_items(url => $urlbase, engine => $self->{option_results}->{engine}, obj => 'fans'); + foreach my $engine_name (sort keys %{$items}) { + foreach my $fan_name (sort keys %{$items->{$engine_name}}) { + my $instance = $engine_name . '_' . $fan_name; - foreach my $item (@items) { + next if ($self->check_filter(section => 'fan', instance => $instance)); + + $self->{output}->output_add(long_msg => sprintf("Fan '%s' state is '%s' and speed-threshold-raised is '%s'", + $instance, + $items->{$engine_name}->{$fan_name}->{'operational-status'}, + $items->{$engine_name}->{$fan_name}->{'speed-threshold-exceeded'})); - if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' && - $item !~ /$self->{option_results}->{filter_name}/) { - $self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $item)); - next; + my $exit = $self->get_severity(section => 'fan_opstatus', value => $items->{$engine_name}->{$fan_name}->{'operational-status'}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' operational status is %s", + $instance, $items->{$engine_name}->{$fan_name}->{'operational-status'})); + } + $exit = $self->get_severity(section => 'fan', value => $items->{$engine_name}->{$fan_name}->{'speed-threshold-exceeded'}); + if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { + $self->{output}->output_add(severity => $exit, + short_msg => sprintf("Fan '%s' is over speed threshold (%s)", + $instance, $items->{$engine_name}->{$fan_name}->{'speed-threshold-exceeded'})); + } } - - my $details = $vplex->get_infos(url => $urlbase, - obj => 'fans', - engine => $self->{option_results}->{engine}, - item => $item); - - $self->{output}->output_add(long_msg => sprintf("FAN '%s' state is '%s' and speed-threshold-raised is '%s'", - $details->{context}->[0]->{attributes}->[0]->{value}, - $details->{context}->[0]->{attributes}->[1]->{value}, - $details->{context}->[0]->{attributes}->[2]->{value})); - - if ($details->{context}->[0]->{attributes}->[1]->{value} ne 'online') { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("FAN '%s' state is '%s'", - $details->{context}->[0]->{attributes}->[0]->{value}, - $details->{context}->[0]->{attributes}->[1]->{value})); - } elsif ($details->{context}->[0]->{attributes}->[2]->{value} ne 'false') { - $self->{output}->output_add(severity => 'CRITICAL', - short_msg => sprintf("FAN '%s' is over speed threshold (%s)", - $details->{context}->[0]->{attributes}->[0]->{value}, - $details->{context}->[0]->{attributes}->[2]->{value})); - } - } - $self->{output}->display(); - $self->{output}->exit(); + $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; + } + } + } + my $label = defined($options{label}) ? $options{label} : $options{section}; + foreach (@{$thresholds->{$label}}) { + if ($options{value} =~ /$$_[0]/i) { + $status = $$_[1]; + return $status; + } + } + + return $status; } 1; @@ -110,9 +187,16 @@ Check Fan state for VPlex Specify the engine number to be checked (1-1 or 2-1 usually) -=item B<--filter-name> +=item B<--filter> -Filter by name - can be a regexp +Filter some parts (comma seperated list) +Can also exclude specific instance: --filter=fan,engine-1-1_fan-psa0-intake + +=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,CRITICAL,^(?!(false)$)' =back