433 lines
17 KiB
Perl
433 lines
17 KiB
Perl
#
|
|
# Copyright 2020 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 snmp_standard::mode::listinterfaces;
|
|
|
|
use base qw(centreon::plugins::mode);
|
|
|
|
use strict;
|
|
use warnings;
|
|
use snmp_standard::mode::resources::types qw($map_iftype);
|
|
|
|
my $oid_speed32 = '.1.3.6.1.2.1.2.2.1.5'; # in b/s
|
|
my $oid_speed64 = '.1.3.6.1.2.1.31.1.1.1.15';
|
|
|
|
sub set_oids_status {
|
|
my ($self, %options) = @_;
|
|
|
|
$self->{oid_adminstatus} = '.1.3.6.1.2.1.2.2.1.7';
|
|
$self->{oid_adminstatus_mapping} = {
|
|
1 => 'up', 2 => 'down', 3 => 'testing', 4 => 'unknown', 5 => 'dormant', 6 => 'notPresent', 7 => 'lowerLayerDown'
|
|
};
|
|
$self->{oid_opstatus} = '.1.3.6.1.2.1.2.2.1.8';
|
|
$self->{oid_opstatus_mapping} = {
|
|
1 => 'up', 2 => 'down', 3 => 'testing', 4 => 'unknown', 5 => 'dormant', 6 => 'notPresent', 7 => 'lowerLayerDown'
|
|
};
|
|
$self->{oid_mac_address} = '.1.3.6.1.2.1.2.2.1.6';
|
|
$self->{oid_iftype} = '.1.3.6.1.2.1.2.2.1.3';
|
|
}
|
|
|
|
sub check_oids_label {
|
|
my ($self, %options) = @_;
|
|
|
|
foreach (('oid_filter', 'oid_display')) {
|
|
$self->{option_results}->{$_} = lc($self->{option_results}->{$_}) if (defined($self->{option_results}->{$_}));
|
|
if (!defined($self->{oids_label}->{$self->{option_results}->{$_}})) {
|
|
my $label = $_;
|
|
$label =~ s/_/-/g;
|
|
$self->{output}->add_option_msg(short_msg => "Unsupported oid in --" . $label . " option.");
|
|
$self->{output}->option_exit();
|
|
}
|
|
}
|
|
}
|
|
|
|
sub set_oids_label {
|
|
my ($self, %options) = @_;
|
|
|
|
$self->{oids_label} = {
|
|
'ifdesc' => '.1.3.6.1.2.1.2.2.1.2',
|
|
'ifalias' => '.1.3.6.1.2.1.31.1.1.1.18',
|
|
'ifname' => '.1.3.6.1.2.1.31.1.1.1.1'
|
|
};
|
|
}
|
|
|
|
sub default_oid_filter_name {
|
|
my ($self, %options) = @_;
|
|
|
|
return 'ifname';
|
|
}
|
|
|
|
sub default_oid_display_name {
|
|
my ($self, %options) = @_;
|
|
|
|
return 'ifname';
|
|
}
|
|
|
|
sub is_admin_status_down {
|
|
my ($self, %options) = @_;
|
|
|
|
if (defined($self->{option_results}->{use_adminstatus}) && defined($options{admin_status}) &&
|
|
$self->{oid_adminstatus_mapping}->{$options{admin_status}} ne 'up') {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub new {
|
|
my ($class, %options) = @_;
|
|
my $self = $class->SUPER::new(package => defined($options{package}) ? $options{package} : __PACKAGE__, %options);
|
|
bless $self, $class;
|
|
|
|
$self->{no_speed} = defined($options{no_speed}) && $options{no_speed} =~ /^[01]$/ ? $options{no_speed} : 0;
|
|
$options{options}->add_options(arguments => {
|
|
'name' => { name => 'use_name' },
|
|
'interface:s' => { name => 'interface' },
|
|
'speed:s' => { name => 'speed' },
|
|
'filter-status:s' => { name => 'filter_status' },
|
|
'skip-speed0' => { name => 'skip_speed0' },
|
|
'use-adminstatus' => { name => 'use_adminstatus' },
|
|
'oid-filter:s' => { name => 'oid_filter', default => $self->default_oid_filter_name() },
|
|
'oid-display:s' => { name => 'oid_display', default => $self->default_oid_display_name() },
|
|
'display-transform-src:s' => { name => 'display_transform_src' },
|
|
'display-transform-dst:s' => { name => 'display_transform_dst' },
|
|
'add-extra-oid:s@' => { name => 'add_extra_oid' },
|
|
'add-mac-address' => { name => 'add_mac_address' }
|
|
});
|
|
|
|
$self->{interface_id_selected} = [];
|
|
|
|
return $self;
|
|
}
|
|
|
|
sub check_options {
|
|
my ($self, %options) = @_;
|
|
$self->SUPER::init(%options);
|
|
|
|
$self->set_oids_label();
|
|
$self->check_oids_label();
|
|
$self->set_oids_status();
|
|
|
|
$self->{extra_oids} = {};
|
|
foreach (@{$self->{option_results}->{add_extra_oid}}) {
|
|
next if ($_ eq '');
|
|
my ($name, $oid, $matching) = split /,/;
|
|
$matching = '%{instance}$' if (!defined($matching));
|
|
if (!defined($oid) || $oid !~ /^(\.\d+){1,}$/ || $name eq '') {
|
|
$self->{output}->add_option_msg(short_msg => "Wrong syntax for add-extra-oid '" . $_ . "' option.");
|
|
$self->{output}->option_exit();
|
|
}
|
|
$self->{extra_oids}->{$name} = { oid => $oid, matching => $matching };
|
|
}
|
|
}
|
|
|
|
sub run {
|
|
my ($self, %options) = @_;
|
|
$self->{snmp} = $options{snmp};
|
|
|
|
$self->manage_selection();
|
|
my $result = $self->get_additional_information();
|
|
foreach (sort @{$self->{interface_id_selected}}) {
|
|
my $display_value = $self->get_display_value(id => $_);
|
|
|
|
my $interface_speed = 0;
|
|
if ($self->{no_speed} == 0) {
|
|
$interface_speed = (defined($result->{$oid_speed64 . "." . $_}) && $result->{$oid_speed64 . "." . $_} ne '' && $result->{$oid_speed64 . "." . $_} != 0) ?
|
|
($result->{$oid_speed64 . "." . $_}) :
|
|
(defined($result->{$oid_speed32 . "." . $_}) && $result->{$oid_speed32 . "." . $_} ne '' && $result->{$oid_speed32 . "." . $_} != 0 ?
|
|
(sprintf("%g", $result->{$oid_speed32 . "." . $_} / 1000 / 1000)) : '');
|
|
}
|
|
if (defined($self->{option_results}->{speed}) && $self->{option_results}->{speed} ne '') {
|
|
$interface_speed = $self->{option_results}->{speed};
|
|
}
|
|
|
|
if (defined($self->{option_results}->{skip_speed0}) && $interface_speed == 0) {
|
|
$self->{output}->output_add(long_msg => "skipping interface '" . $display_value . "': interface speed is 0 and option --skip-speed0 is set");
|
|
next;
|
|
}
|
|
if (defined($self->{option_results}->{filter_status}) && defined($result->{$self->{oid_opstatus} . "." . $_}) &&
|
|
$self->{oid_opstatus_mapping}->{$result->{$self->{oid_opstatus} . "." . $_}} !~ /$self->{option_results}->{filter_status}/i) {
|
|
$self->{output}->output_add(long_msg => "skipping interface '" . $display_value . "': no matching filter status");
|
|
next;
|
|
}
|
|
if ($self->is_admin_status_down(admin_status => $result->{$self->{oid_adminstatus} . "." . $_})) {
|
|
$self->{output}->output_add(long_msg => "skipping interface '" . $display_value . "': adminstatus is not 'up' and option --use-adminstatus is set");
|
|
next;
|
|
}
|
|
|
|
my $extra_values = $self->get_extra_values_by_instance(result => $result, instance => $_);
|
|
my $extra_display = '';
|
|
foreach my $name (keys %{$extra_values}) {
|
|
$extra_display .= '[' . $name . ' = ' . $extra_values->{$name} . ']';
|
|
}
|
|
if (defined($self->{oid_iftype})) {
|
|
$extra_display .= '[type = ' . $map_iftype->{ $result->{ $self->{oid_iftype} . '.' . $_ } } . ']';
|
|
}
|
|
|
|
$self->{output}->output_add(
|
|
long_msg => sprintf(
|
|
"'%s' [speed = %s][status = %s][id = %s]%s",
|
|
$display_value,
|
|
$interface_speed,
|
|
(defined($result->{$self->{oid_opstatus} . "." . $_}) ? $self->{oid_opstatus_mapping}->{$result->{$self->{oid_opstatus} . "." . $_}} : ''),
|
|
$_,
|
|
$extra_display
|
|
)
|
|
);
|
|
}
|
|
|
|
$self->{output}->output_add(
|
|
severity => 'OK',
|
|
short_msg => 'List interfaces:'
|
|
);
|
|
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
|
|
$self->{output}->exit();
|
|
}
|
|
|
|
sub get_additional_information {
|
|
my ($self, %options) = @_;
|
|
|
|
my $oids = [];
|
|
push @$oids, $self->{oid_adminstatus} if (defined($self->{oid_adminstatus}));
|
|
push @$oids, $self->{oid_opstatus} if (defined($self->{oid_opstatus}));
|
|
push @$oids, $self->{oid_mac_address} if (defined($self->{option_results}->{add_mac_address}));
|
|
push @$oids, $self->{oid_iftype} if (defined($self->{oid_iftype}));
|
|
push @$oids, $oid_speed32 if ($self->{no_speed} == 0);
|
|
push @$oids, $oid_speed64 if (!$self->{snmp}->is_snmpv1() && $self->{no_speed} == 0);
|
|
|
|
$self->{snmp}->load(oids => $oids, instances => $self->{interface_id_selected});
|
|
return $self->{snmp}->get_leef();
|
|
}
|
|
|
|
sub get_display_value {
|
|
my ($self, %options) = @_;
|
|
my $value = $self->{datas}->{$self->{option_results}->{oid_display} . "_" . $options{id}};
|
|
|
|
if (defined($self->{option_results}->{display_transform_src})) {
|
|
$self->{option_results}->{display_transform_dst} = '' if (!defined($self->{option_results}->{display_transform_dst}));
|
|
eval "\$value =~ s{$self->{option_results}->{display_transform_src}}{$self->{option_results}->{display_transform_dst}}";
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
sub manage_selection {
|
|
my ($self, %options) = @_;
|
|
|
|
my $oids = [{ oid => $self->{oids_label}->{$self->{option_results}->{oid_filter}} }];
|
|
if ($self->{option_results}->{oid_filter} ne $self->{option_results}->{oid_display}) {
|
|
push @$oids, { oid => $self->{oids_label}->{$self->{option_results}->{oid_display}} };
|
|
}
|
|
if (scalar(keys %{$self->{extra_oids}}) > 0) {
|
|
foreach (keys %{$self->{extra_oids}}) {
|
|
push @$oids, { oid => $self->{extra_oids}->{$_}->{oid} };
|
|
}
|
|
}
|
|
|
|
$self->{datas} = {};
|
|
$self->{results} = $self->{snmp}->get_multiple_table(oids => $oids);
|
|
$self->{datas}->{all_ids} = [];
|
|
foreach my $key ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oids_label}->{$self->{option_results}->{oid_filter}} }})) {
|
|
next if ($key !~ /^$self->{oids_label}->{$self->{option_results}->{oid_filter}}\.(.*)$/);
|
|
$self->{datas}->{$self->{option_results}->{oid_filter} . "_" . $1} = $self->{output}->to_utf8($self->{results}->{$self->{oids_label}->{ $self->{option_results}->{oid_filter}} }->{$key});
|
|
push @{$self->{datas}->{all_ids}}, $1;
|
|
}
|
|
|
|
if (scalar(@{$self->{datas}->{all_ids}}) <= 0) {
|
|
$self->{output}->add_option_msg(short_msg => "Can't get interfaces...");
|
|
$self->{output}->option_exit();
|
|
}
|
|
|
|
if ($self->{option_results}->{oid_filter} ne $self->{option_results}->{oid_display}) {
|
|
foreach my $key ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{ $self->{oids_label}->{$self->{option_results}->{oid_display}} }})) {
|
|
next if ($key !~ /^$self->{oids_label}->{$self->{option_results}->{oid_display}}\.(.*)$/);
|
|
$self->{datas}->{$self->{option_results}->{oid_display} . "_" . $1} = $self->{output}->to_utf8($self->{results}->{$self->{oids_label}->{ $self->{option_results}->{oid_display}} }->{$key});
|
|
}
|
|
}
|
|
|
|
if (!defined($self->{option_results}->{use_name}) && defined($self->{option_results}->{interface})) {
|
|
foreach (@{$self->{datas}->{all_ids}}) {
|
|
if ($self->{option_results}->{interface} =~ /(^|\s|,)$_(\s*,|$)/) {
|
|
push @{$self->{interface_id_selected}}, $_;
|
|
}
|
|
}
|
|
} else {
|
|
foreach (@{$self->{datas}->{all_ids}}) {
|
|
my $filter_name = $self->{datas}->{$self->{option_results}->{oid_filter} . "_" . $_};
|
|
next if (!defined($filter_name));
|
|
|
|
if (!defined($self->{option_results}->{interface})) {
|
|
push @{$self->{interface_id_selected}}, $_;
|
|
next;
|
|
}
|
|
if ($filter_name =~ /$self->{option_results}->{interface}/) {
|
|
push @{$self->{interface_id_selected}}, $_;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (scalar(@{$self->{interface_id_selected}}) <= 0 && !defined($options{disco})) {
|
|
$self->{output}->add_option_msg(short_msg => 'No entry found');
|
|
$self->{output}->option_exit();
|
|
}
|
|
}
|
|
|
|
sub get_extra_values_by_instance {
|
|
my ($self, %options) = @_;
|
|
|
|
my $extra_values = {};
|
|
foreach my $name (keys %{$self->{extra_oids}}) {
|
|
my $matching = $self->{extra_oids}->{$name}->{matching};
|
|
$matching =~ s/%\{instance\}/$options{instance}/g;
|
|
next if (!defined($self->{results}->{ $self->{extra_oids}->{$name}->{oid} }));
|
|
|
|
my $append = '';
|
|
foreach (keys %{$self->{results}->{ $self->{extra_oids}->{$name}->{oid} }}) {
|
|
if (/^$self->{extra_oids}->{$name}->{oid}\.$matching/) {
|
|
$extra_values->{$name} = '' if (!defined($extra_values->{$name}));
|
|
$extra_values->{$name} .= $append . $self->{results}->{$self->{extra_oids}->{$name}->{oid}}->{$_};
|
|
$append = ',';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (defined($self->{option_results}->{add_mac_address})) {
|
|
my $macaddress = defined($options{result}->{$self->{oid_mac_address} . "." . $_}) ? unpack('H*', $options{result}->{$self->{oid_mac_address} . "." . $_}) : '';
|
|
$macaddress =~ s/(..)(?=.)/$1:/g;
|
|
$extra_values->{macaddress} = $macaddress;
|
|
}
|
|
|
|
return $extra_values;
|
|
}
|
|
|
|
sub disco_format {
|
|
my ($self, %options) = @_;
|
|
|
|
my $names = ['name', 'total', 'status', 'interfaceid'];
|
|
if (scalar(keys %{$self->{extra_oids}}) > 0) {
|
|
push @$names, keys %{$self->{extra_oids}};
|
|
}
|
|
if (defined($self->{option_results}->{add_mac_address})) {
|
|
push @$names, 'macaddress';
|
|
}
|
|
push @$names, 'type' if (defined($self->{oid_iftype}));
|
|
|
|
$self->{output}->add_disco_format(elements => $names);
|
|
}
|
|
|
|
sub disco_show {
|
|
my ($self, %options) = @_;
|
|
$self->{snmp} = $options{snmp};
|
|
|
|
$self->manage_selection(disco => 1);
|
|
return if (scalar(@{$self->{interface_id_selected}}) == 0);
|
|
my $result = $self->get_additional_information();
|
|
foreach (sort @{$self->{interface_id_selected}}) {
|
|
my $display_value = $self->get_display_value(id => $_);
|
|
|
|
my $interface_speed = 0;
|
|
if ($self->{no_speed} == 0) {
|
|
$interface_speed = (defined($result->{$oid_speed64 . "." . $_}) && $result->{$oid_speed64 . "." . $_} ne '' && $result->{$oid_speed64 . "." . $_} != 0) ?
|
|
($result->{$oid_speed64 . "." . $_}) :
|
|
(defined($result->{$oid_speed32 . "." . $_}) && $result->{$oid_speed32 . "." . $_} ne '' && $result->{$oid_speed32 . "." . $_} != 0 ?
|
|
(sprintf("%g", $result->{$oid_speed32 . "." . $_} / 1000 / 1000)) : '');
|
|
}
|
|
if (defined($self->{option_results}->{speed}) && $self->{option_results}->{speed} ne '') {
|
|
$interface_speed = $self->{option_results}->{speed};
|
|
}
|
|
next if (defined($self->{option_results}->{skip_speed0}) && $interface_speed == 0);
|
|
next if (defined($self->{option_results}->{filter_status}) && defined($result->{$self->{oid_opstatus} . "." . $_}) &&
|
|
$self->{oid_opstatus_mapping}->{$result->{$self->{oid_opstatus} . "." . $_}} !~ /$self->{option_results}->{filter_status}/i);
|
|
next if ($self->is_admin_status_down(admin_status => $result->{$self->{oid_adminstatus} . "." . $_}));
|
|
|
|
my $extra_values = $self->get_extra_values_by_instance(result => $result, instance => $_);
|
|
if (defined($self->{oid_iftype})) {
|
|
$extra_values->{type} = $map_iftype->{ $result->{ $self->{oid_iftype} . '.' . $_ } };
|
|
}
|
|
$self->{output}->add_disco_entry(
|
|
name => $display_value,
|
|
total => $interface_speed,
|
|
status => defined($result->{$self->{oid_opstatus} . "." . $_}) ? $self->{oid_opstatus_mapping}->{$result->{$self->{oid_opstatus} . "." . $_}} : '',
|
|
interfaceid => $_,
|
|
%$extra_values
|
|
);
|
|
}
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=head1 MODE
|
|
|
|
=over 8
|
|
|
|
=item B<--interface>
|
|
|
|
Set the interface (number expected) ex: 1,2,... (empty means 'check all interface').
|
|
|
|
=item B<--name>
|
|
|
|
Allows to use interface name with option --interface instead of interface oid index (Can be a regexp)
|
|
|
|
=item B<--speed>
|
|
|
|
Set interface speed (in Mb).
|
|
|
|
=item B<--skip-speed0>
|
|
|
|
Don't display interface with speed 0.
|
|
|
|
=item B<--filter-status>
|
|
|
|
Display interfaces matching the filter (example: 'up').
|
|
|
|
=item B<--use-adminstatus>
|
|
|
|
Display interfaces with AdminStatus 'up'.
|
|
|
|
=item B<--oid-filter>
|
|
|
|
Choose OID used to filter interface (default: ifName) (values: ifDesc, ifAlias, ifName).
|
|
|
|
=item B<--oid-display>
|
|
|
|
Choose OID used to display interface (default: ifName) (values: ifDesc, ifAlias, ifName).
|
|
|
|
=item B<--display-transform-src>
|
|
|
|
Regexp src to transform display value. (security risk!!!)
|
|
|
|
=item B<--display-transform-dst>
|
|
|
|
Regexp dst to transform display value. (security risk!!!)
|
|
|
|
=item B<--add-extra-oid>
|
|
|
|
Display an OID.
|
|
Example: --add-extra-oid='alias,.1.3.6.1.2.1.31.1.1.1.18'
|
|
or --add-extra-oid='vlan,.1.3.6.1.2.1.31.19,%{instance}\..*'
|
|
|
|
=item B<--add-mac-address>
|
|
|
|
Display interface mac address.
|
|
|
|
=back
|
|
|
|
=cut
|