From 0cfae8f77ee8efcf7fc0ff6086699ef09540ee81 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 30 Dec 2018 12:36:40 +0100 Subject: [PATCH 1/4] + WIP snmp-autoreduce option --- centreon/plugins/snmp.pm | 83 +++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 9 deletions(-) diff --git a/centreon/plugins/snmp.pm b/centreon/plugins/snmp.pm index 27683b76c..a95cddff3 100644 --- a/centreon/plugins/snmp.pm +++ b/centreon/plugins/snmp.pm @@ -53,6 +53,7 @@ sub new { "maxrepetitions:s" => { name => 'maxrepetitions', default => 50 }, "subsetleef:s" => { name => 'subsetleef', default => 50 }, "subsettable:s" => { name => 'subsettable', default => 100 }, + "snmp-autoreduce" => { name => 'snmp_autoreduce' }, "snmp-force-getnext" => { name => 'snmp_force_getnext' }, "snmp-username:s" => { name => 'snmp_security_name' }, "authpassphrase:s" => { name => 'snmp_auth_passphrase' }, @@ -138,6 +139,54 @@ sub load { push @{$self->{oids_loaded}}, @{$options{oids}}; } +sub autoreduce_table { + my ($self, %options) = @_; + + return 1 if (defined($self->{snmp_force_getnext}) || $self->is_snmpv1()); + if ($self->{snmp_params}->{Retries} > 1) { + $self->{snmp_params}->{Retries} = 1; + $self->connect(); + } + return 1 if (${$options{repeat_count}} == 1); + ${$options{repeat_count}} = int(${$options{repeat_count}} / 2); + + return 0; +} + +sub autoreduce_leef { + my ($self, %options) = @_; + + if ($self->{snmp_params}->{Retries} > 1) { + $self->{snmp_params}->{Retries} = 1; + $self->connect(); + } + + return 1 if ($self->{subsetleef} == 1); + $self->{subsetleef} = int($self->{subsetleef} / 2); + + my $array_ref = []; + my $subset_current = 0; + my $subset_construct = []; + foreach ([@{$options{current}}, @{$self->{array_ref_ar}}]) { + foreach my $entry (@$_) { + push @$subset_construct, [$entry->[0], $entry->[1]]; + $subset_current++; + if ($subset_current == $self->{subsetleef}) { + push @$array_ref, \@$subset_construct; + $subset_construct = []; + $subset_current = 0; + } + } + } + + if ($subset_current) { + push @$array_ref, \@$subset_construct; + } + + $self->{array_ref_ar} = $array_ref; + return 0; +} + sub get_leef { my ($self, %options) = @_; # $options{dont_quit} = integer @@ -165,7 +214,7 @@ sub get_leef { } my $results = {}; - my @array_ref_ar = (); + $self->{array_ref_ar} = []; my $subset_current = 0; my $subset_construct = []; foreach my $oid (@{$options{oids}}) { @@ -177,13 +226,13 @@ sub get_leef { push @$subset_construct, [$oid, $instance]; $subset_current++; if ($subset_current == $self->{subsetleef}) { - push @array_ref_ar, \@$subset_construct; + push @{$self->{array_ref_ar}}, \@$subset_construct; $subset_construct = []; $subset_current = 0; } } if ($subset_current) { - push @array_ref_ar, \@$subset_construct; + push @{$self->{array_ref_ar}}, \@$subset_construct; } ############################ @@ -232,20 +281,23 @@ sub get_leef { ############################ my $total = 0; - foreach (@array_ref_ar) { - my $vb = new SNMP::VarList(@{$_}); + while (my $entry = shift(@{$self->{array_ref_ar}})) { + my $vb = new SNMP::VarList(@{$entry}); $self->{session}->get($vb); if ($self->{session}->{ErrorNum}) { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. + # -24 Timeout if ($self->{session}->{ErrorNum} == 2) { # We are at the end with snmpv1. We next. next; } - - my $msg = 'SNMP GET Request : ' . $self->{session}->{ErrorStr}; - + + if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == -24)) { + next if ($self->autoreduce_leef(current => $entry) == 0); + } + my $msg = 'SNMP GET Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); @@ -503,6 +555,7 @@ sub get_table { $last_oid =~ /(.*)\.(\d+)([\.\s]*)$/; my $vb = new SNMP::VarList([$1, $2]); + print "===" . $repeat_count . "===\n"; if ($self->is_snmpv1() || defined($self->{snmp_force_getnext})) { $self->{session}->getnext($vb); } else { @@ -514,10 +567,15 @@ sub get_table { # 0 noError Pas d'erreurs. # 1 tooBig Reponse de taille trop grande. # 2 noSuchName Variable inexistante. + # -24 Timeout if ($self->{session}->{ErrorNum} == 2) { # We are at the end with snmpv1. We quit. last; } + if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == -24)) { + next if ($self->autoreduce_table(repeat_count => \$repeat_count) == 0); + } + my $msg = 'SNMP Table Request : ' . $self->{session}->{ErrorStr}; if ($dont_quit == 0) { @@ -650,15 +708,18 @@ sub check_options { $self->{subsetleef} = (defined($options{option_results}->{subsetleef}) && $options{option_results}->{subsetleef} =~ /^[0-9]+$/) ? $options{option_results}->{subsetleef} : 50; $self->{subsettable} = (defined($options{option_results}->{subsettable}) && $options{option_results}->{subsettable} =~ /^[0-9]+$/) ? $options{option_results}->{subsettable} : 100; $self->{snmp_errors_exit} = $options{option_results}->{snmp_errors_exit}; + $self->{snmp_autoreduce} = defined($options{option_results}->{snmp_autoreduce}) ? 1 : 0; %{$self->{snmp_params}} = (DestHost => $options{option_results}->{host}, Community => $options{option_results}->{snmp_community}, Version => $options{option_results}->{snmp_version}, - RemotePort => $options{option_results}->{snmp_port}); + RemotePort => $options{option_results}->{snmp_port}, + Retries => 5); if (defined($options{option_results}->{snmp_timeout}) && $options{option_results}->{snmp_timeout} =~ /^[0-9]+$/) { $self->{snmp_params}->{Timeout} = $options{option_results}->{snmp_timeout} * (10**6); } + if (defined($options{option_results}->{snmp_retries}) && $options{option_results}->{snmp_retries} =~ /^[0-9]+$/) { $self->{snmp_params}->{Retries} = $options{option_results}->{snmp_retries}; } @@ -855,6 +916,10 @@ Max repetitions value (default: 50) (only for SNMP v2 and v3). How many oid values per SNMP request (default: 50) (for get_leef method. Be cautious whe you set it. Prefer to let the default value). +=item B<--snmp-autoreduce> + +Auto reduce SNMP request size in case of SNMP errors. + =item B<--snmp-force-getnext> Use snmp getnext function (even in snmp v2c and v3). From 2eca4ebc5f5c7e5cc5784493ad98dd9939fb529e Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Sun, 30 Dec 2018 13:20:23 +0100 Subject: [PATCH 2/4] + add snmp-autoreduce option --- centreon/plugins/snmp.pm | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/centreon/plugins/snmp.pm b/centreon/plugins/snmp.pm index a95cddff3..f265c57fc 100644 --- a/centreon/plugins/snmp.pm +++ b/centreon/plugins/snmp.pm @@ -147,9 +147,23 @@ sub autoreduce_table { $self->{snmp_params}->{Retries} = 1; $self->connect(); } + return 1 if (${$options{repeat_count}} == 1); ${$options{repeat_count}} = int(${$options{repeat_count}} / 2); + return 0; +} + +sub autoreduce_multiple_table { + my ($self, %options) = @_; + if ($self->{snmp_params}->{Retries} > 1) { + $self->{snmp_params}->{Retries} = 1; + $self->connect(); + } + return 1 if (${$options{repeat_count}} == 1); + + ${$options{repeat_count}} = int(${$options{repeat_count}} / 2); + $self->{subsettable} = int($self->{subsettable} / 2); return 0; } @@ -429,8 +443,11 @@ sub get_multiple_table { next; } + if ($self->{snmp_autoreduce} == 1 && ($self->{session}->{ErrorNum} == 1 || $self->{session}->{ErrorNum} == -24)) { + next if ($self->autoreduce_multiple_table(repeat_count => \$repeat_count) == 0); + } + my $msg = 'SNMP Table Request : ' . $self->{session}->{ErrorStr}; - if ($dont_quit == 0) { $self->{output}->add_option_msg(short_msg => $msg); $self->{output}->option_exit(exit_litteral => $self->{snmp_errors_exit}); @@ -555,7 +572,6 @@ sub get_table { $last_oid =~ /(.*)\.(\d+)([\.\s]*)$/; my $vb = new SNMP::VarList([$1, $2]); - print "===" . $repeat_count . "===\n"; if ($self->is_snmpv1() || defined($self->{snmp_force_getnext})) { $self->{session}->getnext($vb); } else { From eca755940cc5711de4132afe5c03bc058208297b Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Mon, 31 Dec 2018 18:10:15 +0100 Subject: [PATCH 3/4] + Fix issue with leef --- centreon/plugins/snmp.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/centreon/plugins/snmp.pm b/centreon/plugins/snmp.pm index abe342aa0..e78a3b401 100644 --- a/centreon/plugins/snmp.pm +++ b/centreon/plugins/snmp.pm @@ -181,8 +181,8 @@ sub autoreduce_leef { my $array_ref = []; my $subset_current = 0; my $subset_construct = []; - foreach ([@{$options{current}}, @{$self->{array_ref_ar}}]) { - foreach my $entry (@$_) { + foreach ([@{$options{current}}], @{$self->{array_ref_ar}}) { + foreach my $entry (@$_) {; push @$subset_construct, [$entry->[0], $entry->[1]]; $subset_current++; if ($subset_current == $self->{subsetleef}) { @@ -197,7 +197,7 @@ sub autoreduce_leef { push @$array_ref, \@$subset_construct; } - $self->{array_ref_ar} = $array_ref; + $self->{array_ref_ar} = \@$array_ref; return 0; } From a26677f999926f3fbafdf17f59fc35df3807fa96 Mon Sep 17 00:00:00 2001 From: garnier-quentin Date: Tue, 1 Jan 2019 12:17:32 +0100 Subject: [PATCH 4/4] + Add snmp autoreduce divisor --- centreon/plugins/snmp.pm | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/centreon/plugins/snmp.pm b/centreon/plugins/snmp.pm index e78a3b401..9c6cb180e 100644 --- a/centreon/plugins/snmp.pm +++ b/centreon/plugins/snmp.pm @@ -53,7 +53,7 @@ sub new { "maxrepetitions:s" => { name => 'maxrepetitions', default => 50 }, "subsetleef:s" => { name => 'subsetleef', default => 50 }, "subsettable:s" => { name => 'subsettable', default => 100 }, - "snmp-autoreduce" => { name => 'snmp_autoreduce' }, + "snmp-autoreduce:s" => { name => 'snmp_autoreduce' }, "snmp-force-getnext" => { name => 'snmp_force_getnext' }, "snmp-username:s" => { name => 'snmp_security_name' }, "authpassphrase:s" => { name => 'snmp_auth_passphrase' }, @@ -149,7 +149,8 @@ sub autoreduce_table { } return 1 if (${$options{repeat_count}} == 1); - ${$options{repeat_count}} = int(${$options{repeat_count}} / 2); + ${$options{repeat_count}} = int(${$options{repeat_count}} / $self->{snmp_autoreduce_divisor}); + ${$options{repeat_count}} = 1 if (${$options{repeat_count}} < 1); return 0; } @@ -162,8 +163,9 @@ sub autoreduce_multiple_table { } return 1 if (${$options{repeat_count}} == 1); - ${$options{repeat_count}} = int(${$options{repeat_count}} / 2); - $self->{subsettable} = int($self->{subsettable} / 2); + ${$options{repeat_count}} = int(${$options{repeat_count}} / $self->{snmp_autoreduce_divisor}); + $self->{subsettable} = int($self->{subsettable} / $self->{snmp_autoreduce_divisor}); + ${$options{repeat_count}} = 1 if (${$options{repeat_count}} < 1); return 0; } @@ -176,7 +178,8 @@ sub autoreduce_leef { } return 1 if ($self->{subsetleef} == 1); - $self->{subsetleef} = int($self->{subsetleef} / 2); + $self->{subsetleef} = int($self->{subsetleef} / $self->{snmp_autoreduce_divisor}); + $self->{subsetleef} = 1 if ($self->{subsetleef} < 1); my $array_ref = []; my $subset_current = 0; @@ -726,7 +729,11 @@ sub check_options { $self->{subsetleef} = (defined($options{option_results}->{subsetleef}) && $options{option_results}->{subsetleef} =~ /^[0-9]+$/) ? $options{option_results}->{subsetleef} : 50; $self->{subsettable} = (defined($options{option_results}->{subsettable}) && $options{option_results}->{subsettable} =~ /^[0-9]+$/) ? $options{option_results}->{subsettable} : 100; $self->{snmp_errors_exit} = $options{option_results}->{snmp_errors_exit}; - $self->{snmp_autoreduce} = defined($options{option_results}->{snmp_autoreduce}) ? 1 : 0; + $self->{snmp_autoreduce_divisor} = 2; + if (defined($options{option_results}->{snmp_autoreduce})) { + $self->{snmp_autoreduce} = 1; + $self->{snmp_autoreduce_divisor} = $1 if ($options{option_results}->{snmp_autoreduce} =~ /(\d+(\.\d+)?)/ && $1 > 1); + } %{$self->{snmp_params}} = (DestHost => $options{option_results}->{host}, Community => $options{option_results}->{snmp_community}, @@ -936,7 +943,7 @@ How many oid values per SNMP request (default: 50) (for get_leef method. Be caut =item B<--snmp-autoreduce> -Auto reduce SNMP request size in case of SNMP errors. +Auto reduce SNMP request size in case of SNMP errors (By default, the divisor is 2). =item B<--snmp-force-getnext>