diff --git a/centreon/plugins/snmp.pm b/centreon/plugins/snmp.pm index fdb89ee86..3b4dd6d82 100644 --- a/centreon/plugins/snmp.pm +++ b/centreon/plugins/snmp.pm @@ -43,28 +43,30 @@ sub new { $options{output}->option_exit(); } - $options{options}->add_options(arguments => { - "hostname|host:s" => { name => 'host' }, - "snmp-community:s" => { name => 'snmp_community', default => 'public' }, - "snmp-version:s" => { name => 'snmp_version', default => 1 }, - "snmp-port:s" => { name => 'snmp_port', default => 161 }, - "snmp-timeout:s" => { name => 'snmp_timeout', default => 1 }, - "snmp-retries:s" => { name => 'snmp_retries', default => 5 }, - "maxrepetitions:s" => { name => 'maxrepetitions', default => 50 }, - "subsetleef:s" => { name => 'subsetleef', default => 50 }, - "subsettable:s" => { name => 'subsettable', default => 100 }, - "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' }, - "authprotocol:s" => { name => 'snmp_auth_protocol' }, - "privpassphrase:s" => { name => 'snmp_priv_passphrase' }, - "privprotocol:s" => { name => 'snmp_priv_protocol' }, - "contextname:s" => { name => 'snmp_context_name' }, - "contextengineid:s" => { name => 'snmp_context_engine_id' }, - "securityengineid:s" => { name => 'snmp_security_engine_id' }, - "snmp-errors-exit:s" => { name => 'snmp_errors_exit', default => 'unknown' }, - }); + if (!defined($options{noptions})) { + $options{options}->add_options(arguments => { + "hostname|host:s" => { name => 'host' }, + "snmp-community:s" => { name => 'snmp_community', default => 'public' }, + "snmp-version:s" => { name => 'snmp_version', default => 1 }, + "snmp-port:s" => { name => 'snmp_port', default => 161 }, + "snmp-timeout:s" => { name => 'snmp_timeout', default => 1 }, + "snmp-retries:s" => { name => 'snmp_retries', default => 5 }, + "maxrepetitions:s" => { name => 'maxrepetitions', default => 50 }, + "subsetleef:s" => { name => 'subsetleef', default => 50 }, + "subsettable:s" => { name => 'subsettable', default => 100 }, + "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' }, + "authprotocol:s" => { name => 'snmp_auth_protocol' }, + "privpassphrase:s" => { name => 'snmp_priv_passphrase' }, + "privprotocol:s" => { name => 'snmp_priv_protocol' }, + "contextname:s" => { name => 'snmp_context_name' }, + "contextengineid:s" => { name => 'snmp_context_engine_id' }, + "securityengineid:s" => { name => 'snmp_security_engine_id' }, + "snmp-errors-exit:s" => { name => 'snmp_errors_exit', default => 'unknown' }, + }); + } $options{options}->add_help(package => __PACKAGE__, sections => 'SNMP OPTIONS'); ##### diff --git a/os/linux/local/mode/discoverysnmp.pm b/os/linux/local/mode/discoverysnmp.pm new file mode 100644 index 000000000..54fbdd91e --- /dev/null +++ b/os/linux/local/mode/discoverysnmp.pm @@ -0,0 +1,177 @@ +# +# Copyright 2019 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 os::linux::local::mode::discoverysnmp; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use centreon::plugins::snmp; +use NetAddr::IP; +use JSON::XS; + +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 => { + "subnet:s" => { name => 'subnet' }, + "snmp-port:s" => { name => 'snmp_port' }, + "snmp-version:s@" => { name => 'snmp_version' }, + "snmp-community:s@" => { name => 'snmp_community' }, + "snmp-timeout:s" => { name => 'snmp_timeout', default => 1 }, + "prettify" => { name => 'prettify' }, + }); + + $self->{snmp} = centreon::plugins::snmp->new(%options, noptions => 1); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); + + if (!defined($self->{option_results}->{subnet}) || + $self->{option_results}->{subnet} !~ /(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)/) { + $self->{output}->add_option_msg(short_msg => "Need to specify --subnet option (/)."); + $self->{output}->option_exit(); + } + if (!defined($self->{option_results}->{snmp_port}) || $self->{option_results}->{snmp_port} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --snmp-port option."); + $self->{output}->option_exit(); + } + if (!defined($self->{option_results}->{snmp_community}) || $self->{option_results}->{snmp_community} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --snmp-community option."); + $self->{output}->option_exit(); + } + if (!defined($self->{option_results}->{snmp_version}) || $self->{option_results}->{snmp_version} eq '') { + $self->{output}->add_option_msg(short_msg => "Need to specify --snmp-version option."); + $self->{output}->option_exit(); + } + if (!defined($self->{option_results}->{snmp_timeout}) || $self->{option_results}->{snmp_timeout} !~ /(\d+)/) { + $self->{output}->add_option_msg(short_msg => "Need to specify --snmp-timeout option."); + $self->{output}->option_exit(); + } + + $self->{snmp}->set_snmp_connect_params(Timeout => $self->{option_results}->{snmp_timeout} * (10**6)); + $self->{snmp}->set_snmp_connect_params(Retries => 0); + $self->{snmp}->set_snmp_params(subsetleef => 1); + $self->{snmp}->set_snmp_params(snmp_autoreduce => 0); + $self->{snmp}->set_snmp_params(snmp_errors_exit => 'unknown'); +} + +sub define_type { + my ($self, %options) = @_; + + return "linux" if ($options{desc} =~ /linux/i); + return "windows" if ($options{desc} =~ /windows/i); + return "unknown"; +} + +sub snmp_request { + my ($self, %options) = @_; + + $self->{snmp}->set_snmp_connect_params(DestHost => $options{ip}); + $self->{snmp}->set_snmp_connect_params(Community => $options{community}); + $self->{snmp}->set_snmp_connect_params(Version => $options{version}); + $self->{snmp}->set_snmp_connect_params(RemotePort => $options{port}); + $self->{snmp}->connect(); + return $self->{snmp}->get_leef(oids => [ $self->{oid_sysDescr}, $self->{oid_sysName} ], + nothing_quit => 0, dont_quit => 1); +} + +sub run { + my ($self, %options) = @_; + + $self->{oid_sysDescr} = ".1.3.6.1.2.1.1.1.0"; + $self->{oid_sysName} = ".1.3.6.1.2.1.1.5.0"; + + my @disco_data; + my $disco_stats; + + my $last_version; + my $last_community; + my $subnet = NetAddr::IP->new($self->{option_results}->{subnet}); + + $disco_stats->{start_time} = time(); + + foreach my $ip (@{$subnet->splitref($subnet->bits())}) { + my $result; + foreach my $community (@{$self->{option_results}->{snmp_community}}) { + foreach my $version (@{$self->{option_results}->{snmp_version}}) { + $result = $self->snmp_request(ip => $ip->addr, community => $community, version => $version, + port => $self->{option_results}->{snmp_port}); + $last_version = $version; + $last_community = $community; + last if (defined($result)); + } + } + next if (!defined($result) || $result eq ''); + + my %host; + $host{type} = $self->define_type(desc => $result->{$self->{oid_sysDescr}}); + $host{desc} = $result->{$self->{oid_sysDescr}}; + $host{ip} = $ip->addr; + $host{hostname} = $result->{$self->{oid_sysName}}; + $host{snmp_version} = $last_version; + $host{snmp_community} = $last_community; + $host{snmp_port} = $self->{option_results}->{snmp_port}; + push @disco_data, \%host; + } + + $disco_stats->{end_time} = time(); + $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; + $disco_stats->{discovered_items} = @disco_data; + $disco_stats->{results} = \@disco_data; + + my $encoded_data; + eval { + if (defined($self->{option_results}->{prettify})) { + $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); + } else { + $encoded_data = JSON::XS->new->utf8->encode($disco_stats); + } + }; + if ($@) { + $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; + } + + $self->{output}->output_add(short_msg => $encoded_data); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +Resources discovery. + +=over 8 + +=back + +=cut diff --git a/os/linux/local/plugin.pm b/os/linux/local/plugin.pm index 6298fd7f4..7fdb99f7e 100644 --- a/os/linux/local/plugin.pm +++ b/os/linux/local/plugin.pm @@ -36,6 +36,7 @@ sub new { 'cmd-return' => 'os::linux::local::mode::cmdreturn', 'connections' => 'os::linux::local::mode::connections', 'directlvm-usage' => 'os::linux::local::mode::directlvmusage', + 'discovery-snmp' => 'os::linux::local::mode::discoverysnmp', 'diskio' => 'os::linux::local::mode::diskio', 'files-size' => 'os::linux::local::mode::filessize', 'files-date' => 'os::linux::local::mode::filesdate',