enh aruba plugin
This commit is contained in:
parent
8ead9bcf08
commit
85a249d624
|
@ -209,7 +209,7 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check AP connections.
|
||||
Check AP connections (Deprecated).
|
||||
|
||||
=over 8
|
||||
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
#
|
||||
# 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 centreon::common::aruba::snmp::mode::apssidstatistics;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'ap', type => 3, cb_prefix_output => 'prefix_output_ap', cb_long_output => 'long_output',
|
||||
message_multiple => 'All AP BSSID are ok', indent_long_output => ' ',
|
||||
group => [
|
||||
{ name => 'essid', display_long => 1, cb_prefix_output => 'prefix_output_essid',
|
||||
message_multiple => 'All ESSID are ok', type => 1 },
|
||||
{ name => 'bssid', display_long => 1, cb_prefix_output => 'prefix_output_bssid',
|
||||
message_multiple => 'All BSSID are ok', type => 1 },
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{essid} = [
|
||||
{ label => 'stations-associated', nlabel => 'essid.stations.associated.count', set => {
|
||||
key_values => [ { name => 'wlanAPEssidNumAssociatedStations' }, { name => 'wlanAPESSID' } ],
|
||||
output_template => 'Associated Stations: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPEssidNumAssociatedStations_absolute', template => '%d',
|
||||
label_extra_instance => 1 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{bssid} = [
|
||||
{ label => 'stations-associated', nlabel => 'bssid.stations.associated.count', set => {
|
||||
key_values => [ { name => 'wlanAPBssidNumAssociatedStations' }, { name => 'wlanAPBSSID' },
|
||||
{ name => 'wlanAPESSID' } ],
|
||||
output_template => 'Associated Stations: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPBssidNumAssociatedStations_absolute', template => '%d',
|
||||
label_extra_instance => 1 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'channel-noise', nlabel => 'bssid.channel.noise.count', set => {
|
||||
key_values => [ { name => 'apChannelNoise' }, { name => 'wlanAPBSSID' },
|
||||
{ name => 'wlanAPESSID' } ],
|
||||
output_template => 'Channel Noise: %d',
|
||||
perfdatas => [
|
||||
{ value => 'apChannelNoise_absolute', template => '%d',
|
||||
label_extra_instance => 1 },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'signal-noise-ratio', nlabel => 'bssid.signal.noise.ratio.count', set => {
|
||||
key_values => [ { name => 'apSignalToNoiseRatio' }, { name => 'wlanAPBSSID' },
|
||||
{ name => 'wlanAPESSID' } ],
|
||||
output_template => 'Signal To Noise Ratio: %d',
|
||||
perfdatas => [
|
||||
{ value => 'apSignalToNoiseRatio_absolute', template => '%d',
|
||||
label_extra_instance => 1 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub prefix_output_ap {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "AP '" . $options{instance_value}->{wlanAPName} . "' [Mac: " . $options{instance_value}->{wlanAPMacAddress} . "] ";
|
||||
}
|
||||
|
||||
sub prefix_output_essid {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "ESSID '" . $options{instance_value}->{wlanAPESSID} . "' ";
|
||||
}
|
||||
|
||||
sub prefix_output_bssid {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "BSSID '" . $options{instance_value}->{wlanAPBSSID} . "' [ESSID: " .
|
||||
$options{instance_value}->{wlanAPESSID} . "][Protocol: " . $options{instance_value}->{wlanAPBssidPhyType} . "] ";
|
||||
}
|
||||
|
||||
sub long_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Checking AP '" . $options{instance_value}->{wlanAPName} . "' [Mac: " . $options{instance_value}->{wlanAPMacAddress} . "] ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
"filter-ap:s" => { name => 'filter_ap' },
|
||||
"filter-essid:s" => { name => 'filter_essid' },
|
||||
"filter-protocol:s" => { name => 'filter_protocol' },
|
||||
"filter-bssid:s" => { name => 'filter_bssid' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
my %map_type = (
|
||||
1 => '802.11a', 2 => '802.11b', 3 => '802.11g',
|
||||
4 => '802.11ag', 5 => 'wired'
|
||||
);
|
||||
|
||||
my $oid_wlsxSwitchAccessPointTable = '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1';
|
||||
|
||||
my $mapping_switch = {
|
||||
apChannelNoise => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.13' },
|
||||
apSignalToNoiseRatio => { oid => '.1.3.6.1.4.1.14823.2.2.1.1.3.3.1.14' },
|
||||
};
|
||||
|
||||
my $oid_wlsxWlanAPBssidTable = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1';
|
||||
|
||||
my $mapping_wlan = {
|
||||
wlanAPESSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.2' },
|
||||
wlanAPBssidPhyType => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.5', map => \%map_type },
|
||||
wlanAPBssidUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.9' },
|
||||
wlanAPBssidInactiveTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.10' },
|
||||
wlanAPBssidNumAssociatedStations => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.7.1.12' },
|
||||
};
|
||||
|
||||
my $oid_wlanAPName = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3';
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $snmp_result = $options{snmp}->get_multiple_table(
|
||||
oids => [
|
||||
{ oid => $oid_wlsxSwitchAccessPointTable,
|
||||
start => $mapping_switch->{apChannelNoise}->{oid},
|
||||
end => $mapping_switch->{apSignalToNoiseRatio}->{oid} },
|
||||
{ oid => $oid_wlsxWlanAPBssidTable,
|
||||
start => $mapping_wlan->{wlanAPESSID}->{oid},
|
||||
end => $mapping_wlan->{wlanAPBssidNumAssociatedStations}->{oid} },
|
||||
{ oid => $oid_wlanAPName },
|
||||
],
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
$self->{global}->{connected} = 0;
|
||||
$self->{ap} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result->{$oid_wlsxWlanAPBssidTable}}) {
|
||||
next if ($oid !~ /^$mapping_wlan->{wlanAPESSID}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping_wlan,
|
||||
results => $snmp_result->{$oid_wlsxWlanAPBssidTable},
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
my @digits = split /\./, $instance;
|
||||
$result->{wlanAPMacAddress} = join(':', unpack("(A2)*", unpack('H*', pack('C*', @digits[0..5]))));
|
||||
$result->{wlanAPBSSID} = join(':', unpack("(A2)*", unpack('H*', pack('C*', @digits[7..12]))));
|
||||
$result->{wlanAPName} = $snmp_result->{$oid_wlanAPName}->{$oid_wlanAPName . '.' . join('.', @digits[0..5])};
|
||||
$result->{apChannelNoise} = $snmp_result->{$oid_wlsxSwitchAccessPointTable}->{$mapping_switch->{apChannelNoise}->{oid} . '.' . join('.', @digits[7..12])};
|
||||
$result->{apSignalToNoiseRatio} = $snmp_result->{$oid_wlsxSwitchAccessPointTable}->{$mapping_switch->{apSignalToNoiseRatio}->{oid} . '.' . join('.', @digits[7..12])};
|
||||
|
||||
if (defined($self->{option_results}->{filter_ap}) && $self->{option_results}->{filter_ap} ne '' &&
|
||||
$result->{wlanAPName} !~ /$self->{option_results}->{filter_ap}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPName} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_essid}) && $self->{option_results}->{filter_essid} ne '' &&
|
||||
$result->{wlanAPESSID} !~ /$self->{option_results}->{filter_essid}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPESSID} . "': no matching filter essid.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_bssid}) && $self->{option_results}->{filter_bssid} ne '' &&
|
||||
$result->{wlanAPBSSID} !~ /$self->{option_results}->{filter_bssid}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPESSID} . "': no matching filter bssid.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_protocol}) && $self->{option_results}->{filter_protocol} ne '' &&
|
||||
$result->{wlanAPBssidPhyType} !~ /$self->{option_results}->{filter_protocol}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPBssidPhyType} . "': no matching filter protocol.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{ap}->{$result->{wlanAPName}}->{wlanAPName} = $result->{wlanAPName};
|
||||
$self->{ap}->{$result->{wlanAPName}}->{wlanAPMacAddress} = $result->{wlanAPMacAddress};
|
||||
$self->{ap}->{$result->{wlanAPName}}->{essid}->{$result->{wlanAPESSID}}->{wlanAPEssidNumAssociatedStations} += $result->{wlanAPBssidNumAssociatedStations};
|
||||
$self->{ap}->{$result->{wlanAPName}}->{essid}->{$result->{wlanAPESSID}}->{wlanAPESSID} = $result->{wlanAPESSID};
|
||||
$self->{ap}->{$result->{wlanAPName}}->{bssid}->{$result->{wlanAPBSSID}} = { %{$result} };
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{ap}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No AP found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check AP ESSID and BSSID statistics (WLSX-WLAN-MIB, WLSX-SWITCH-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'stations-associated' (ESSID and BSSID),
|
||||
'channel-noise', 'signal-noise-ratio' (BSSID).
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'stations-associated' (ESSID and BSSID),
|
||||
'channel-noise', 'signal-noise-ratio' (BSSID).
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter by 'ap', 'essid', 'protocol', 'bssid' (regexp can be used).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -0,0 +1,250 @@
|
|||
#
|
||||
# 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 centreon::common::aruba::snmp::mode::apstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s' [Ip: %s][Group: %s][Location: %s]",
|
||||
$self->{result_values}->{status},
|
||||
$self->{result_values}->{ip},
|
||||
$self->{result_values}->{group},
|
||||
$self->{result_values}->{location});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_wlanAPName'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_wlanAPStatus'};
|
||||
$self->{result_values}->{ip} = $options{new_datas}->{$self->{instance} . '_wlanAPIpAddress'};
|
||||
$self->{result_values}->{group} = $options{new_datas}->{$self->{instance} . '_wlanAPGroupName'};
|
||||
$self->{result_values}->{location} = $options{new_datas}->{$self->{instance} . '_wlanAPLocation'};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', type => 0, cb_init => 'skip_global' },
|
||||
{ name => 'ap', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All AP status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'connected-current', nlabel => 'accesspoints.connected.current.count', set => {
|
||||
key_values => [ { name => 'connected' } ],
|
||||
output_template => 'Total connected AP: %d',
|
||||
perfdatas => [
|
||||
{ value => 'connected_absolute', template => '%d', min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{ap} = [
|
||||
{ label => 'status', threshold => 0, set => {
|
||||
key_values => [ { name => 'wlanAPName' }, { name => 'wlanAPIpAddress' }, { name => 'wlanAPGroupName' },
|
||||
{ name => 'wlanAPLocation' }, { name => 'wlanAPStatus' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => \&catalog_status_threshold,
|
||||
}
|
||||
},
|
||||
{ label => 'uptime', nlabel => 'accesspoint.uptime.seconds', set => {
|
||||
key_values => [ { name => 'wlanAPUpTime' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Uptime: %ss',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPUpTime_absolute', template => '%s',
|
||||
unit => 's', label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'controller-bootstrap', nlabel => 'accesspoint.controller.bootstrap.count', set => {
|
||||
key_values => [ { name => 'wlanAPNumBootstraps' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Controller Bootstrap Count: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPNumBootstraps_absolute', template => '%d',
|
||||
label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'reboot', nlabel => 'accesspoint.reboot.count', set => {
|
||||
key_values => [ { name => 'wlanAPNumReboots' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Reboot Count: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPNumReboots_absolute', template => '%d',
|
||||
label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub skip_global {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
scalar(keys %{$self->{ap}}) > 1 ? return(0) : return(1);
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "AP '" . $options{instance_value}->{wlanAPName} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
"filter-ip:s" => { name => 'filter_ip' },
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-group:s" => { name => 'filter_group' },
|
||||
"filter-location:s" => { name => 'filter_location' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /up/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$self->change_macros(macros => ['warning_status', 'critical_status']);
|
||||
}
|
||||
|
||||
my %map_status = (
|
||||
1 => 'up', 2 => 'down'
|
||||
);
|
||||
|
||||
my $oid_wlsxWlanAPTable = '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1';
|
||||
|
||||
my $mapping = {
|
||||
wlanAPIpAddress => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.2' },
|
||||
wlanAPName => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.3' },
|
||||
wlanAPGroupName=> { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.4' },
|
||||
wlanAPUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.12' },
|
||||
wlanAPLocation => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.14' },
|
||||
wlanAPStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.20', map => \%map_status },
|
||||
wlanAPNumBootstraps => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.21' },
|
||||
wlanAPNumReboots => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.22' },
|
||||
};
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxWlanAPTable,
|
||||
start => $mapping->{wlanAPIpAddress}->{oid},
|
||||
end => $mapping->{wlanAPNumReboots}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
$self->{global}->{connected} = 0;
|
||||
$self->{ap} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{wlanAPIpAddress}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
if (defined($self->{option_results}->{filter_ip}) && $self->{option_results}->{filter_ip} ne '' &&
|
||||
$result->{wlanAPIpAddress} !~ /$self->{option_results}->{filter_ip}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPIpAddress} . "': no matching filter ip.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$result->{wlanAPName} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPName} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_group}) && $self->{option_results}->{filter_group} ne '' &&
|
||||
$result->{wlanAPGroupName} !~ /$self->{option_results}->{filter_group}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPGroupName} . "': no matching filter group.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_location}) && $self->{option_results}->{filter_location} ne '' &&
|
||||
$result->{wlanAPLocation} !~ /$self->{option_results}->{filter_location}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{wlanAPLocation} . "': no matching filter location.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{ap}->{$result->{wlanAPName}} = { %{$result}, wlanAPUpTime => $result->{wlanAPUpTime} / 100 };
|
||||
$self->{global}->{connected}++;
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{ap}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No AP found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check AP status (WLSX-WLAN-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{group}, %{location} (Default: '')
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{group}, %{location} (Default: '%{status} !~ /up/i')
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter by 'ip', 'name', 'group', 'location' (regexp can be used).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -150,12 +150,11 @@ sub new {
|
|||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"filter-ip-address:s" => { name => 'filter_ip_address' },
|
||||
"filter-bssid:s" => { name => 'filter_bssid' },
|
||||
"filter-essid:s" => { name => 'filter_essid' },
|
||||
});
|
||||
$options{options}->add_options(arguments => {
|
||||
"filter-ip-address:s" => { name => 'filter_ip_address' },
|
||||
"filter-bssid:s" => { name => 'filter_bssid' },
|
||||
"filter-essid:s" => { name => 'filter_essid' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
@ -176,11 +175,11 @@ my %map_role = (
|
|||
3 => 'standbymaster',
|
||||
);
|
||||
my $mapping = {
|
||||
nUserUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.5' },
|
||||
nUserAuthenticationMethod => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.6', map => \%map_auth_method },
|
||||
nUserUpTime => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.5' },
|
||||
nUserAuthenticationMethod => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.6', map => \%map_auth_method },
|
||||
};
|
||||
my $mapping2 = {
|
||||
nUserApBSSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.11' },
|
||||
nUserApBSSID => { oid => '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1.11' },
|
||||
};
|
||||
|
||||
my $oid_wlsxUserEntry = '.1.3.6.1.4.1.14823.2.2.1.4.1.2.1';
|
||||
|
@ -264,7 +263,7 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check total users connected.
|
||||
Check total users connected (Deprecated).
|
||||
|
||||
=over 8
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ my %map_fan_status = (
|
|||
2 => 'inactive',
|
||||
);
|
||||
|
||||
# In MIB 'aruba-systemext'
|
||||
my $mapping = {
|
||||
sysExtFanStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.17.1.2', map => \%map_fan_status },
|
||||
};
|
||||
|
@ -50,20 +49,28 @@ sub check {
|
|||
foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtFanEntry}})) {
|
||||
next if ($oid !~ /^$mapping->{sysExtFanStatus}->{oid}\.(.*)$/);
|
||||
my $instance = $1;
|
||||
my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtFanEntry}, instance => $instance);
|
||||
my $result = $self->{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $self->{results}->{$oid_wlsxSysExtFanEntry},
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
next if ($self->check_filter(section => 'fan', instance => $instance));
|
||||
$self->{components}->{fan}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("Fan '%s' status is %s [instance: %s].",
|
||||
$instance, $result->{sysExtFanStatus},
|
||||
$instance
|
||||
));
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf("Fan '%s' status is %s [instance: %s].",
|
||||
$instance, $result->{sysExtFanStatus},
|
||||
$instance
|
||||
));
|
||||
my $exit = $self->get_severity(section => 'fan', value => $result->{sysExtFanStatus});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Fan '%s' status is %s",
|
||||
$instance, $result->{sysExtFanStatus}));
|
||||
$self->{output}->output_add(
|
||||
severity => $exit,
|
||||
short_msg => sprintf("Fan '%s' status is %s",
|
||||
$instance,
|
||||
$result->{sysExtFanStatus}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ my %map_module_status = (
|
|||
2 => 'inactive',
|
||||
);
|
||||
|
||||
# In MIB 'aruba-systemext'
|
||||
my $mapping = {
|
||||
sysExtCardType => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.16.1.2', map => \%map_card_type },
|
||||
sysExtCardStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.16.1.12', map => \%map_module_status },
|
||||
|
@ -70,20 +69,29 @@ sub check {
|
|||
foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtCardEntry}})) {
|
||||
next if ($oid !~ /^$mapping->{sysExtCardStatus}->{oid}\.(.*)$/);
|
||||
my $instance = $1;
|
||||
my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtCardEntry}, instance => $instance);
|
||||
my $result = $self->{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $self->{results}->{$oid_wlsxSysExtCardEntry},
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
next if ($self->check_filter(section => 'module', instance => $instance));
|
||||
$self->{components}->{module}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("Module '%s/%s' status is %s [instance: %s].",
|
||||
$result->{sysExtCardType}, $instance, $result->{sysExtCardStatus},
|
||||
$instance
|
||||
));
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf("Module '%s/%s' status is %s [instance: %s].",
|
||||
$result->{sysExtCardType}, $instance, $result->{sysExtCardStatus},
|
||||
$instance
|
||||
));
|
||||
my $exit = $self->get_severity(section => 'module', value => $result->{sysExtCardStatus});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Module '%s/%s' status is %s",
|
||||
$result->{sysExtCardType}, $instance, $result->{sysExtCardStatus}));
|
||||
$self->{output}->output_add(
|
||||
severity => $exit,
|
||||
short_msg => sprintf("Module '%s/%s' status is %s",
|
||||
$result->{sysExtCardType},
|
||||
$instance,
|
||||
$result->{sysExtCardStatus})
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ my %map_psu_status = (
|
|||
2 => 'inactive',
|
||||
);
|
||||
|
||||
# In MIB 'aruba-systemext'
|
||||
my $mapping = {
|
||||
sysExtPowerSupplyStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.18.1.2', map => \%map_psu_status },
|
||||
};
|
||||
|
@ -50,20 +49,27 @@ sub check {
|
|||
foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_wlsxSysExtPowerSupplyEntry}})) {
|
||||
next if ($oid !~ /^$mapping->{sysExtPowerSupplyStatus}->{oid}\.(.*)$/);
|
||||
my $instance = $1;
|
||||
my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_wlsxSysExtPowerSupplyEntry}, instance => $instance);
|
||||
my $result = $self->{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $self->{results}->{$oid_wlsxSysExtPowerSupplyEntry},
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
next if ($self->check_filter(section => 'psu', instance => $instance));
|
||||
$self->{components}->{psu}->{total}++;
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("Power supply '%s' status is %s [instance: %s].",
|
||||
$instance, $result->{sysExtPowerSupplyStatus},
|
||||
$instance
|
||||
));
|
||||
$self->{output}->output_add(
|
||||
long_msg => sprintf("Power supply '%s' status is %s [instance: %s].",
|
||||
$instance, $result->{sysExtPowerSupplyStatus},
|
||||
$instance
|
||||
));
|
||||
my $exit = $self->get_severity(section => 'psu', value => $result->{sysExtPowerSupplyStatus});
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Power supply '%s' status is %s",
|
||||
$instance, $result->{sysExtPowerSupplyStatus}));
|
||||
$self->{output}->output_add(
|
||||
severity => $exit,
|
||||
short_msg => sprintf("Power supply '%s' status is %s",
|
||||
$instance, $result->{sysExtPowerSupplyStatus}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
#
|
||||
# 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 centreon::common::aruba::snmp::mode::controllerstatus;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s', Role is '%s' [Ip: %s][Version: %s][Location: %s]",
|
||||
$self->{result_values}->{status},
|
||||
$self->{result_values}->{role},
|
||||
$self->{result_values}->{ip},
|
||||
$self->{result_values}->{version},
|
||||
$self->{result_values}->{location});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchName'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchStatus'};
|
||||
$self->{result_values}->{role} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchRole'};
|
||||
$self->{result_values}->{ip} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchIPAddress'};
|
||||
$self->{result_values}->{version} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchSWVersion'};
|
||||
$self->{result_values}->{location} = $options{new_datas}->{$self->{instance} . '_sysExtSwitchLocation'};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'global', type => 0, cb_init => 'skip_global' },
|
||||
{ name => 'controllers', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All controllers status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{global} = [
|
||||
{ label => 'current', nlabel => 'controllers.current.count', set => {
|
||||
key_values => [ { name => 'current' } ],
|
||||
output_template => 'Total controllers: %d',
|
||||
perfdatas => [
|
||||
{ value => 'current_absolute', template => '%d', min => 0 },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{controllers} = [
|
||||
{ label => 'status', threshold => 0, set => {
|
||||
key_values => [ { name => 'sysExtSwitchIPAddress' }, { name => 'sysExtSwitchName' },
|
||||
{ name => 'sysExtSwitchLocation' }, { name => 'sysExtSwitchSWVersion' },
|
||||
{ name => 'sysExtSwitchRole' }, { name => 'sysExtSwitchStatus' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => \&catalog_status_threshold,
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub skip_global {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
scalar(keys %{$self->{controllers}}) > 1 ? return(0) : return(1);
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Controller '" . $options{instance_value}->{sysExtSwitchName} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-ip:s" => { name => 'filter_ip' },
|
||||
"filter-location:s" => { name => 'filter_location' },
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /active/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$self->change_macros(macros => ['warning_status', 'critical_status']);
|
||||
}
|
||||
|
||||
my %map_status = (
|
||||
1 => 'active', 2 => 'inactive'
|
||||
);
|
||||
my %map_role = (
|
||||
1 => 'master', 2 => 'local', 3 => 'backupmaster'
|
||||
);
|
||||
|
||||
my $oid_wlsxSysExtSwitchListTable = '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1';
|
||||
|
||||
my $mapping = {
|
||||
sysExtSwitchRole => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.2', map => \%map_role },
|
||||
sysExtSwitchLocation=> { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.3' },
|
||||
sysExtSwitchSWVersion => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.4' },
|
||||
sysExtSwitchStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.5', map => \%map_status },
|
||||
sysExtSwitchName => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.19.1.6' },
|
||||
};
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxSysExtSwitchListTable,
|
||||
start => $mapping->{sysExtSwitchRole}->{oid},
|
||||
end => $mapping->{sysExtSwitchName}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
$self->{global}->{current} = 0;
|
||||
$self->{controllers} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{sysExtSwitchRole}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
$result->{sysExtSwitchIPAddress} = $instance;
|
||||
|
||||
if (defined($self->{option_results}->{filter_ip}) && $self->{option_results}->{filter_ip} ne '' &&
|
||||
$result->{sysExtSwitchIPAddress} !~ /$self->{option_results}->{filter_ip}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchIPAddress} . "': no matching filter ip.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$result->{sysExtSwitchName} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchName} . "': no matching filter name.", debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_location}) && $self->{option_results}->{filter_location} ne '' &&
|
||||
$result->{sysExtSwitchLocation} !~ /$self->{option_results}->{filter_location}/) {
|
||||
$self->{output}->output_add(long_msg => "skipping '" . $result->{sysExtSwitchLocation} . "': no matching filter location.", debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$self->{controllers}->{$result->{sysExtSwitchName}} = { %{$result} };
|
||||
$self->{global}->{current}++;
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{controllers}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No controller found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check controller status (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{role}, %{location} (Default: '')
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{role}, %{location} (Default: '%{status} !~ /active/i')
|
||||
|
||||
=item B<--filter-*>
|
||||
|
||||
Filter by 'ip', 'name', 'location' (regexp can be used).
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -20,78 +20,84 @@
|
|||
|
||||
package centreon::common::aruba::snmp::mode::cpu;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'cpu', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All CPUs utilization are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{cpu} = [
|
||||
{ label => 'utilization', nlabel => 'cpu.utilization.percentage', set => {
|
||||
key_values => [ { name => 'sysExtProcessorLoad' }, { name => 'sysExtProcessorDescr' } ],
|
||||
output_template => 'Utilization %.2f%%',
|
||||
perfdatas => [
|
||||
{ label => 'utilization', value => 'sysExtProcessorLoad_absolute', template => '%.2f', min => 0, max => 100,
|
||||
unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "CPU '" . $options{instance_value}->{sysExtProcessorDescr} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"warning:s" => { name => 'warning', },
|
||||
"critical:s" => { name => 'critical', },
|
||||
});
|
||||
|
||||
$options{options}->add_options(arguments => {});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my $oid_wlsxSysExtProcessorEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1';
|
||||
|
||||
my $mapping = {
|
||||
sysExtProcessorDescr => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.2' },
|
||||
sysExtProcessorLoad => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.3' },
|
||||
};
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
|
||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
$self->{snmp} = $options{snmp};
|
||||
|
||||
my $oid_wlsxSysExtProcessorEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1';
|
||||
my $oid_sysExtProcessorDescr = '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.2';
|
||||
my $oid_sysExtProcessorLoad = '.1.3.6.1.4.1.14823.2.2.1.2.1.13.1.3';
|
||||
my $result = $self->{snmp}->get_table(oid => $oid_wlsxSysExtProcessorEntry, nothing_quit => 1);
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'All CPUs are ok.');
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxSysExtProcessorEntry,
|
||||
start => $mapping->{sysExtProcessorDescr}->{oid},
|
||||
end => $mapping->{sysExtProcessorLoad}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
foreach my $oid (keys %$result) {
|
||||
next if ($oid !~ /^$oid_sysExtProcessorLoad/);
|
||||
$oid =~ /\.([0-9]+)$/;
|
||||
$self->{cpu} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{sysExtProcessorDescr}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
my $load = $result->{$oid};
|
||||
my $descr = $result->{$oid_sysExtProcessorDescr . '.' . $instance};
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(value => $load,
|
||||
threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("CPU '%s': %.2f%% (1min)", $descr,
|
||||
$load));
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("CPU '%s': %.2f%% (1min)", $descr,
|
||||
$load));
|
||||
}
|
||||
|
||||
$self->{output}->perfdata_add(label => "cpu_" . $instance, unit => '%',
|
||||
value => $load,
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
|
||||
min => 0, max => 100);
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
$self->{cpu}->{$instance} = { %{$result} };
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{cpu}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot find CPU informations");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$self->{output}->display();
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -100,15 +106,15 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check cpu usage (over the last minute) (aruba-systemext).
|
||||
Check CPU usage (over the last minute) (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning>
|
||||
=item B<--warning-utilization>
|
||||
|
||||
Threshold warning in percent.
|
||||
|
||||
=item B<--critical>
|
||||
=item B<--critical-utilization>
|
||||
|
||||
Threshold critical in percent.
|
||||
|
||||
|
|
|
@ -63,9 +63,7 @@ sub new {
|
|||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_performance => 1, no_absent => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
});
|
||||
$options{options}->add_options(arguments => {});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
@ -76,7 +74,7 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check hardware (modules, fans, power supplies).
|
||||
Check hardware (modules, fans, power supplies) (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
#
|
||||
# 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 centreon::common::aruba::snmp::mode::license;
|
||||
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
|
||||
|
||||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = sprintf("Status is '%s' [Ip: %s][Group: %s][Location: %s]",
|
||||
$self->{result_values}->{status},
|
||||
$self->{result_values}->{ip},
|
||||
$self->{result_values}->{group},
|
||||
$self->{result_values}->{location});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_status_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{name} = $options{new_datas}->{$self->{instance} . '_wlanAPName'};
|
||||
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_wlanAPStatus'};
|
||||
$self->{result_values}->{ip} = $options{new_datas}->{$self->{instance} . '_wlanAPIpAddress'};
|
||||
$self->{result_values}->{group} = $options{new_datas}->{$self->{instance} . '_wlanAPGroupName'};
|
||||
$self->{result_values}->{location} = $options{new_datas}->{$self->{instance} . '_wlanAPLocation'};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'license', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All licenses status are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{license} = [
|
||||
{ label => 'status', set => {
|
||||
key_values => [ { name => 'wlanAPName' }, { name => 'wlanAPIpAddress' }, { name => 'wlanAPGroupName' },
|
||||
{ name => 'wlanAPLocation' }, { name => 'wlanAPStatus' } ],
|
||||
closure_custom_calc => $self->can('custom_status_calc'),
|
||||
closure_custom_output => $self->can('custom_status_output'),
|
||||
closure_custom_perfdata => sub { return 0; },
|
||||
closure_custom_threshold_check => \&catalog_status_threshold,
|
||||
}
|
||||
},
|
||||
{ label => 'uptime', nlabel => 'accesspoint.uptime.seconds', set => {
|
||||
key_values => [ { name => 'wlanAPUpTime' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Uptime: %ss',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPUpTime_absolute', template => '%s',
|
||||
unit => 's', label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'controller-bootstrap', nlabel => 'accesspoint.controller.bootstrap.count', set => {
|
||||
key_values => [ { name => 'wlanAPNumBootstraps' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Controller Bootstrap Count: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPNumBootstraps_absolute', template => '%d',
|
||||
label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
{ label => 'reboot', nlabel => 'accesspoint.reboot.count', set => {
|
||||
key_values => [ { name => 'wlanAPNumReboots' }, { name => 'wlanAPName' } ],
|
||||
output_template => 'Reboot Count: %d',
|
||||
perfdatas => [
|
||||
{ value => 'wlanAPNumReboots_absolute', template => '%d',
|
||||
label_extra_instance => 1, instance_use => 'wlanAPName_absolute' },
|
||||
],
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "License '" . $options{instance_value}->{sysExtLicenseKey} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments => {
|
||||
"warning-status:s" => { name => 'warning_status' },
|
||||
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /up/i' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::check_options(%options);
|
||||
|
||||
$self->change_macros(macros => ['warning_status', 'critical_status']);
|
||||
}
|
||||
|
||||
my %map_status = (
|
||||
1 => 'up', 2 => 'down'
|
||||
);
|
||||
|
||||
my $oid_wlsxSysExtSwitchLicenseTable = '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1';
|
||||
|
||||
my $mapping = {
|
||||
sysExtLicenseKey => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.2' },
|
||||
sysExtLicenseExpires => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.4' },
|
||||
sysExtLicenseService=> { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.20.1.6' },
|
||||
# wlanAPStatus => { oid => '.1.3.6.1.4.1.14823.2.2.1.5.2.1.4.1.20', map => \%map_status },
|
||||
};
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxSysExtSwitchLicenseTable,
|
||||
start => $mapping->{sysExtLicenseKey}->{oid},
|
||||
end => $mapping->{sysExtLicenseService}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
$self->{license} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{sysExtLicenseKey}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
$self->{license}->{$result->{sysExtLicenseKey}} = { %{$result} };
|
||||
}
|
||||
use Data::Dumper;
|
||||
print Dumper $self->{license};
|
||||
|
||||
if (scalar(keys %{$self->{license}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No license found.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 MODE
|
||||
|
||||
Check license (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning-*>
|
||||
|
||||
Threshold warning.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{group}, %{location} (Default: '')
|
||||
|
||||
=item B<--critical-*>
|
||||
|
||||
Threshold critical.
|
||||
Can be: 'connected-current' (global), 'uptime',
|
||||
'controller-bootstrap', 'reboot', 'status' (per AP).
|
||||
'status' can use special variables like: %{name},
|
||||
%{status}, %{ip}, %{group}, %{location} (Default: '%{status} !~ /up/i')
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
|
@ -20,102 +20,131 @@
|
|||
|
||||
package centreon::common::aruba::snmp::mode::memory;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub custom_usage_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->perfdata_add(
|
||||
instances => $self->{instance},
|
||||
label => 'usage', nlabel => 'memory.usage.bytes',
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_usage_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(
|
||||
value => $self->{result_values}->{prct_used},
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
|
||||
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free});
|
||||
|
||||
my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
|
||||
$total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_usage_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_sysExtMemorySize'} * 1024;
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_sysExtMemoryUsed'} * 1024;
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'memory', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All memory pools are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{memory} = [
|
||||
{ label => 'usage', set => {
|
||||
key_values => [ { name => 'sysExtMemoryUsed' }, { name => 'sysExtMemorySize' } ],
|
||||
closure_custom_calc => $self->can('custom_usage_calc'),
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Memory '" . $options{instance_value}->{display} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"warning:s" => { name => 'warning' },
|
||||
"critical:s" => { name => 'critical' },
|
||||
});
|
||||
$options{options}->add_options(arguments => {});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub check_options {
|
||||
my $oid_wlsxSysExtMemoryEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1';
|
||||
|
||||
my $mapping = {
|
||||
sysExtMemorySize => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.2' }, # in KB
|
||||
sysExtMemoryUsed => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.3' }, # in KB
|
||||
};
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
|
||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxSysExtMemoryEntry,
|
||||
start => $mapping->{sysExtMemorySize}->{oid},
|
||||
end => $mapping->{sysExtMemoryUsed}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
$self->{memory} = {};
|
||||
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{sysExtMemorySize}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
$self->{memory}->{$instance} = { %{$result}, display => $instance };
|
||||
}
|
||||
|
||||
if (scalar(keys %{$self->{memory}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot find memory informations");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
$self->{snmp} = $options{snmp};
|
||||
|
||||
my $oid_wlsxSysExtMemoryEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1';
|
||||
my $oid_sysExtMemoryUsed = '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.3'; # in KB
|
||||
my $oid_sysExtMemoryFree = '.1.3.6.1.4.1.14823.2.2.1.2.1.15.1.4'; # in KB
|
||||
my $result = $self->{snmp}->get_table(oid => $oid_wlsxSysExtMemoryEntry, nothing_quit => 1);
|
||||
my $mode = 0;
|
||||
|
||||
if (scalar(keys %$result) > 3) {
|
||||
# Not Only Control Processor memory
|
||||
$mode = 1;
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'All pool memories are ok.');
|
||||
}
|
||||
|
||||
foreach my $oid (keys %$result) {
|
||||
next if ($oid !~ /^$oid_sysExtMemoryFree/);
|
||||
$oid =~ /\.([0-9]+)$/;
|
||||
|
||||
my $memory_name = ($mode == 1) ? $1 : 'Control Processor';
|
||||
my $memory_used = $result->{$oid_sysExtMemoryUsed . '.' . $1} * 1024;
|
||||
my $memory_free =$result->{$oid_sysExtMemoryFree . '.' . $1} * 1024;
|
||||
|
||||
my $total_size = $memory_used + $memory_free;
|
||||
my $prct_used = $memory_used * 100 / $total_size;
|
||||
my $prct_free = 100 - $prct_used;
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
|
||||
my ($total_value, $total_unit) = $self->{perfdata}->change_bytes(value => $total_size);
|
||||
my ($used_value, $used_unit) = $self->{perfdata}->change_bytes(value => $memory_used);
|
||||
my ($free_value, $free_unit) = $self->{perfdata}->change_bytes(value => $memory_free);
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("Memory '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $memory_name,
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $prct_used,
|
||||
$free_value . " " . $free_unit, $prct_free));
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1) || $mode == 0) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Memory '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $memory_name,
|
||||
$total_value . " " . $total_unit,
|
||||
$used_value . " " . $used_unit, $prct_used,
|
||||
$free_value . " " . $free_unit, $prct_free));
|
||||
}
|
||||
|
||||
if ($mode == 1) {
|
||||
$self->{output}->perfdata_add(label => "used_" . $memory_name, unit => 'B',
|
||||
value => $memory_used,
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $total_size),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $total_size),
|
||||
min => 0, max => $total_size);
|
||||
} else {
|
||||
$self->{output}->perfdata_add(label => "used", unit => 'B',
|
||||
value => $memory_used,
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $total_size),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $total_size),
|
||||
min => 0, max => $total_size);
|
||||
}
|
||||
}
|
||||
|
||||
$self->{output}->display();
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -124,15 +153,15 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check memory usage (aruba-systemext).
|
||||
Check memory usage (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning>
|
||||
=item B<--warning-usage>
|
||||
|
||||
Threshold warning in percent.
|
||||
|
||||
=item B<--critical>
|
||||
=item B<--critical-usage>
|
||||
|
||||
Threshold critical in percent.
|
||||
|
||||
|
|
|
@ -20,118 +20,152 @@
|
|||
|
||||
package centreon::common::aruba::snmp::mode::storage;
|
||||
|
||||
use base qw(centreon::plugins::mode);
|
||||
use base qw(centreon::plugins::templates::counter);
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my %map_storage_type = (
|
||||
1 => 'ram',
|
||||
2 => 'flashMemory'
|
||||
);
|
||||
sub custom_usage_perfdata {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{output}->perfdata_add(
|
||||
instances => $self->{instance},
|
||||
label => 'usage', nlabel => 'storage.usage.bytes',
|
||||
unit => 'B',
|
||||
value => $self->{result_values}->{used},
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, total => $self->{result_values}->{total}, cast_int => 1),
|
||||
min => 0, max => $self->{result_values}->{total});
|
||||
}
|
||||
|
||||
sub custom_usage_threshold {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(
|
||||
value => $self->{result_values}->{prct_used},
|
||||
threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
|
||||
{ label => 'warning-' . $self->{label}, exit_litteral => 'warning' } ]);
|
||||
return $exit;
|
||||
}
|
||||
|
||||
sub custom_usage_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{total});
|
||||
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{used});
|
||||
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $self->{result_values}->{free});
|
||||
|
||||
my $msg = sprintf("Usage Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)",
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$total_used_value . " " . $total_used_unit, $self->{result_values}->{prct_used},
|
||||
$total_free_value . " " . $total_free_unit, $self->{result_values}->{prct_free});
|
||||
return $msg;
|
||||
}
|
||||
|
||||
sub custom_usage_calc {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_sysExtStorageSize'} * 1024 * 1024;
|
||||
$self->{result_values}->{used} = $options{new_datas}->{$self->{instance} . '_sysExtStorageUsed'} * 1024 * 1024;
|
||||
$self->{result_values}->{free} = $self->{result_values}->{total} - $self->{result_values}->{used};
|
||||
$self->{result_values}->{prct_free} = $self->{result_values}->{free} * 100 / $self->{result_values}->{total};
|
||||
$self->{result_values}->{prct_used} = $self->{result_values}->{used} * 100 / $self->{result_values}->{total};
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub set_counters {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'storage', type => 1, cb_prefix_output => 'prefix_output',
|
||||
message_multiple => 'All storages are ok' },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{storage} = [
|
||||
{ label => 'usage', set => {
|
||||
key_values => [ { name => 'sysExtStorageUsed' }, { name => 'sysExtStorageSize' },
|
||||
{ name => 'sysExtStorageName' } ],
|
||||
closure_custom_calc => $self->can('custom_usage_calc'),
|
||||
closure_custom_output => $self->can('custom_usage_output'),
|
||||
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
|
||||
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
|
||||
}
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
sub prefix_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Storage '" . $options{instance_value}->{sysExtStorageName} . "' ";
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, %options) = @_;
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
|
||||
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
|
||||
bless $self, $class;
|
||||
|
||||
$options{options}->add_options(arguments =>
|
||||
{
|
||||
"warning:s" => { name => 'warning' },
|
||||
"critical:s" => { name => 'critical' },
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-type:s" => { name => 'filter_type' },
|
||||
});
|
||||
$options{options}->add_options(arguments => {
|
||||
"filter-name:s" => { name => 'filter_name' },
|
||||
"filter-type:s" => { name => 'filter_type' },
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
my $oid_wlsxSysExtStorageEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1';
|
||||
|
||||
sub check_options {
|
||||
my %map_storage_type = (
|
||||
1 => 'ram', 2 => 'flashMemory'
|
||||
);
|
||||
|
||||
my $mapping = {
|
||||
sysExtStorageType => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.2', map => \%map_storage_type },
|
||||
sysExtStorageSize => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.3' }, # MB
|
||||
sysExtStorageUsed => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.4' }, # MB
|
||||
sysExtStorageName => { oid => '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.5' },
|
||||
};
|
||||
|
||||
sub manage_selection {
|
||||
my ($self, %options) = @_;
|
||||
$self->SUPER::init(%options);
|
||||
|
||||
if (($self->{perfdata}->threshold_validate(label => 'warning', value => $self->{option_results}->{warning})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong warning threshold '" . $self->{option_results}->{warning} . "'.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (($self->{perfdata}->threshold_validate(label => 'critical', value => $self->{option_results}->{critical})) == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, %options) = @_;
|
||||
$self->{snmp} = $options{snmp};
|
||||
my $snmp_result = $options{snmp}->get_table(
|
||||
oid => $oid_wlsxSysExtStorageEntry,
|
||||
start => $mapping->{sysExtStorageType}->{oid},
|
||||
end => $mapping->{sysExtStorageName}->{oid},
|
||||
nothing_quit => 1
|
||||
);
|
||||
|
||||
my $oid_wlsxSysExtStorageEntry = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1';
|
||||
my $oid_sysExtStorageType = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.2';
|
||||
my $oid_sysExtStorageName = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.5';
|
||||
my $oid_sysExtStorageSize = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.3'; # MB
|
||||
my $oid_sysExtStorageUsed = '.1.3.6.1.4.1.14823.2.2.1.2.1.14.1.4'; # MB
|
||||
$self->{storage} = {};
|
||||
|
||||
my $storage_num = 0;
|
||||
my $result = $self->{snmp}->get_table(oid => $oid_wlsxSysExtStorageEntry, nothing_quit => 1);
|
||||
|
||||
$self->{output}->output_add(severity => 'OK',
|
||||
short_msg => 'All storages are ok.');
|
||||
|
||||
foreach my $oid (keys %$result) {
|
||||
next if ($oid !~ /^$oid_sysExtStorageSize/);
|
||||
$oid =~ /\.([0-9]+)$/;
|
||||
foreach my $oid (keys %{$snmp_result}) {
|
||||
next if ($oid !~ /^$mapping->{sysExtStorageType}->{oid}\.(.*)/);
|
||||
my $instance = $1;
|
||||
|
||||
my $name = $result->{$oid_sysExtStorageName . '.' . $1};
|
||||
my $type = $result->{$oid_sysExtStorageType . '.' . $1};;
|
||||
my $total_used = $result->{$oid_sysExtStorageUsed . '.' . $1} * 1024 * 1024;
|
||||
my $total_size = $result->{$oid_sysExtStorageSize . '.' . $1} * 1024 * 1024;
|
||||
my $result = $options{snmp}->map_instance(
|
||||
mapping => $mapping,
|
||||
results => $snmp_result,
|
||||
instance => $instance
|
||||
);
|
||||
|
||||
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
|
||||
$name !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $name));
|
||||
$result->{sysExtStorageName} !~ /$self->{option_results}->{filter_name}/) {
|
||||
$self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $result->{sysExtStorageName}), debug => 1);
|
||||
next;
|
||||
}
|
||||
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
|
||||
$map_storage_type{$type} !~ /$self->{option_results}->{filter_type}/i) {
|
||||
$self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $name));
|
||||
$result->{sysExtStorageType} !~ /$self->{option_results}->{filter_type}/i) {
|
||||
$self->{output}->output_add(long_msg => sprintf("Skipping storage '%s'.", $result->{sysExtStorageType}), debug => 1);
|
||||
next;
|
||||
}
|
||||
|
||||
$storage_num++;
|
||||
my $total_free = $total_size - $total_used;
|
||||
my $prct_used = $total_used * 100 / $total_size;
|
||||
my $prct_free = 100 - $prct_used;
|
||||
|
||||
my $exit = $self->{perfdata}->threshold_check(value => $prct_used, threshold => [ { label => 'critical', exit_litteral => 'critical' }, { label => 'warning', exit_litteral => 'warning' } ]);
|
||||
my ($total_size_value, $total_size_unit) = $self->{perfdata}->change_bytes(value => $total_size);
|
||||
my ($total_used_value, $total_used_unit) = $self->{perfdata}->change_bytes(value => $total_used);
|
||||
my ($total_free_value, $total_free_unit) = $self->{perfdata}->change_bytes(value => $total_free);
|
||||
|
||||
$self->{output}->output_add(long_msg => sprintf("Storage '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name,
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$total_used_value . " " . $total_used_unit, $prct_used,
|
||||
$total_free_value . " " . $total_free_unit, $prct_free));
|
||||
if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) {
|
||||
$self->{output}->output_add(severity => $exit,
|
||||
short_msg => sprintf("Storage '%s' Total: %s Used: %s (%.2f%%) Free: %s (%.2f%%)", $name,
|
||||
$total_size_value . " " . $total_size_unit,
|
||||
$total_used_value . " " . $total_used_unit, $prct_used,
|
||||
$total_free_value . " " . $total_free_unit, $prct_free));
|
||||
}
|
||||
|
||||
$self->{output}->perfdata_add(label => 'used_' . $name, unit => 'B',
|
||||
value => $total_used,
|
||||
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning', total => $total_size, cast_int => 1),
|
||||
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical', total => $total_size, cast_int => 1),
|
||||
min => 0, max => $total_size);
|
||||
$self->{storage}->{$result->{sysExtStorageName}} = { %{$result} };
|
||||
}
|
||||
|
||||
if ($storage_num == 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No storage information found (maybe your filters)");
|
||||
|
||||
if (scalar(keys %{$self->{storage}}) <= 0) {
|
||||
$self->{output}->add_option_msg(short_msg => "No storage found");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$self->{output}->display();
|
||||
$self->{output}->exit();
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -140,15 +174,15 @@ __END__
|
|||
|
||||
=head1 MODE
|
||||
|
||||
Check storage device usage (aruba-systemext).
|
||||
Check storage device usage (WLSX-SYSTEMEXT-MIB).
|
||||
|
||||
=over 8
|
||||
|
||||
=item B<--warning>
|
||||
=item B<--warning-usage>
|
||||
|
||||
Threshold warning in percent.
|
||||
|
||||
=item B<--critical>
|
||||
=item B<--critical-usage>
|
||||
|
||||
Threshold critical in percent.
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold
|
|||
sub custom_status_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $msg = 'Status: ' . $self->{result_values}->{status};
|
||||
my $msg = "Status is '" . $self->{result_values}->{status} . "'";
|
||||
return $msg;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ sub set_counters {
|
|||
my ($self, %options) = @_;
|
||||
|
||||
$self->{maps_counters_type} = [
|
||||
{ name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output', message_multiple => 'All access points are ok', skipped_code => { -10 => 1 } },
|
||||
{ name => 'ap', type => 1, cb_prefix_output => 'prefix_ap_output',
|
||||
message_multiple => 'All access points are ok', skipped_code => { -10 => 1 } },
|
||||
];
|
||||
|
||||
$self->{maps_counters}->{ap} = [
|
||||
|
@ -63,7 +64,7 @@ sub set_counters {
|
|||
},
|
||||
{ label => 'clients', nlabel => 'clients.current.count', set => {
|
||||
key_values => [ { name => 'clients' }, { name => 'display' } ],
|
||||
output_template => 'Current Clients %s',
|
||||
output_template => 'Current Clients: %s',
|
||||
perfdatas => [
|
||||
{ label => 'clients', value => 'clients_absolute', template => '%s',
|
||||
min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
|
||||
|
@ -72,7 +73,7 @@ sub set_counters {
|
|||
},
|
||||
{ label => 'cpu', nlabel => 'cpu.utilization.percentage', set => {
|
||||
key_values => [ { name => 'cpu' }, { name => 'display' } ],
|
||||
output_template => 'Cpu %.2f %%',
|
||||
output_template => 'Cpu: %.2f%%',
|
||||
perfdatas => [
|
||||
{ label => 'cpu', value => 'cpu_absolute', template => '%.2f',
|
||||
min => 0, max => 100, unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' },
|
||||
|
@ -80,7 +81,8 @@ sub set_counters {
|
|||
}
|
||||
},
|
||||
{ label => 'mem-usage', nlabel => 'memory.usage.bytes', set => {
|
||||
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
|
||||
key_values => [ { name => 'used' }, { name => 'free' }, { name => 'prct_used' },
|
||||
{ name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
|
||||
closure_custom_output => $self->can('custom_memory_output'),
|
||||
perfdatas => [
|
||||
{ label => 'mem_used', value => 'used_absolute', template => '%d', min => 0, max => 'total_absolute',
|
||||
|
@ -89,7 +91,8 @@ sub set_counters {
|
|||
}
|
||||
},
|
||||
{ label => 'mem-usage-free', display_ok => 0, nlabel => 'memory.free.bytes', set => {
|
||||
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' }, { name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
|
||||
key_values => [ { name => 'free' }, { name => 'used' }, { name => 'prct_used' },
|
||||
{ name => 'prct_free' }, { name => 'total' }, { name => 'display' } ],
|
||||
closure_custom_output => $self->can('custom_memory_output'),
|
||||
perfdatas => [
|
||||
{ label => 'mem_free', value => 'free_absolute', template => '%d', min => 0, max => 'total_absolute',
|
||||
|
@ -99,7 +102,7 @@ sub set_counters {
|
|||
},
|
||||
{ label => 'mem-usage-prct', display_ok => 0, nlabel => 'memory.usage.percentage', set => {
|
||||
key_values => [ { name => 'prct_used' }, { name => 'display' } ],
|
||||
output_template => 'Memory Used : %.2f %%',
|
||||
output_template => 'Memory Used: %.2f %%',
|
||||
perfdatas => [
|
||||
{ label => 'mem_used_prct', value => 'prct_used_absolute', template => '%.2f', min => 0, max => 100,
|
||||
unit => '%', label_extra_instance => 1, instance_use => 'display_absolute' },
|
||||
|
@ -133,10 +136,12 @@ sub check_options {
|
|||
sub prefix_ap_output {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
return "Access point '" . $options{instance_value}->{display} . "' ";
|
||||
return "Access Point '" . $options{instance_value}->{display} . "' ";
|
||||
}
|
||||
|
||||
my $map_ap_status = { 1 => 'up', 2 => 'down' };
|
||||
my $map_ap_status = {
|
||||
1 => 'up', 2 => 'down'
|
||||
};
|
||||
|
||||
my $mapping = {
|
||||
aiAPName => { oid => '.1.3.6.1.4.1.14823.2.3.3.1.2.1.1.2' },
|
||||
|
@ -154,7 +159,8 @@ sub manage_selection {
|
|||
|
||||
my $snmp_result = $options{snmp}->get_multiple_table(
|
||||
oids => [
|
||||
{ oid => $oid_aiAccessPointEntry, start => $mapping->{aiAPName}->{oid} },
|
||||
{ oid => $oid_aiAccessPointEntry, start => $mapping->{aiAPName}->{oid},
|
||||
end => $mapping->{aiAPStatus}->{oid} },
|
||||
{ oid => $oid_aiClientAPIPAddress },
|
||||
],
|
||||
nothing_quit => 1
|
||||
|
|
|
@ -31,15 +31,19 @@ sub new {
|
|||
|
||||
$self->{version} = '1.0';
|
||||
%{$self->{modes}} = (
|
||||
'ap-connections' => 'centreon::common::aruba::snmp::mode::apconnections',
|
||||
'ap-users' => 'centreon::common::aruba::snmp::mode::apusers',
|
||||
'cpu' => 'centreon::common::aruba::snmp::mode::cpu',
|
||||
'hardware' => 'centreon::common::aruba::snmp::mode::hardware',
|
||||
'interfaces' => 'snmp_standard::mode::interfaces',
|
||||
'list-interfaces' => 'snmp_standard::mode::listinterfaces',
|
||||
'memory' => 'centreon::common::aruba::snmp::mode::memory',
|
||||
'storage' => 'centreon::common::aruba::snmp::mode::storage',
|
||||
);
|
||||
'ap-connections' => 'centreon::common::aruba::snmp::mode::apconnections', # Deprecated
|
||||
'ap-ssid-statistics' => 'centreon::common::aruba::snmp::mode::apssidstatistics',
|
||||
'ap-status' => 'centreon::common::aruba::snmp::mode::apstatus',
|
||||
'ap-users' => 'centreon::common::aruba::snmp::mode::apusers', # Deprecated
|
||||
'controller-status' => 'centreon::common::aruba::snmp::mode::controllerstatus',
|
||||
'cpu' => 'centreon::common::aruba::snmp::mode::cpu',
|
||||
'hardware' => 'centreon::common::aruba::snmp::mode::hardware',
|
||||
'interfaces' => 'snmp_standard::mode::interfaces',
|
||||
'list-interfaces' => 'snmp_standard::mode::listinterfaces',
|
||||
'license' => 'centreon::common::aruba::snmp::mode::license',
|
||||
'memory' => 'centreon::common::aruba::snmp::mode::memory',
|
||||
'storage' => 'centreon::common::aruba::snmp::mode::storage',
|
||||
);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue