Skip to content

Commit 8c912cd

Browse files
scresto31rmorandell-pgumomercier
authored
feat(network::huawei::standard::snmp): extend Huawei Network Device by GPON ONT module monitoring (#6112)
Refs:CTOR-1842 Co-authored-by: rmorandell_pgum <roman.morandell@pgum.eu> Co-authored-by: omercier <32134301+omercier@users.noreply.github.com>
1 parent 0120956 commit 8c912cd

13 files changed

Lines changed: 1391 additions & 11 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#
2+
# Copyright 2026-Present Centreon (http://www.centreon.com/)
3+
#
4+
# Centreon is a full-fledged industry-strength solution that meets
5+
# the needs in IT infrastructure and application monitoring for
6+
# service performance.
7+
#
8+
# Licensed under the Apache License, Version 2.0 (the "License");
9+
# you may not use this file except in compliance with the License.
10+
# You may obtain a copy of the License at
11+
#
12+
# http://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing, software
15+
# distributed under the License is distributed on an "AS IS" BASIS,
16+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
# See the License for the specific language governing permissions and
18+
# limitations under the License.
19+
#
20+
21+
package centreon::common::huawei::standard::snmp::functions;
22+
23+
use strict;
24+
use warnings;
25+
26+
use Exporter 'import';
27+
28+
our @EXPORT_OK = qw/get_serial_string/;
29+
30+
sub get_serial_string($) {
31+
# Get the raw OCTET STRING value for the serial number.
32+
# It may contain both ASCII and binary data.
33+
my ($raw_bytes) = @_;
34+
35+
# Extract the first 4 bytes and interpret them as ASCII characters.
36+
# Example: '52 43 4D 47' => 'RCMG'
37+
my $ascii_part = substr($raw_bytes, 0, 4);
38+
39+
# Extract the last 4 bytes, convert them to an uppercase hex string.
40+
# Example: '1A 98 0E 53' => '1A980E53'
41+
my $hex_part = uc(unpack("H*", substr($raw_bytes, 4, 4)));
42+
43+
# Format the final output string, combining name, serial number, and state.
44+
# The serial number is shown as: [first 4 bytes as ASCII][last 4 bytes as HEX].
45+
# Example: RCMG1A980E53
46+
return "$ascii_part$hex_part";
47+
}
48+
49+
1;
50+
51+
__END__
52+
53+
=head1 DESCRIPTION
54+
55+
Huawei SNMP common functions.
56+
57+
=cut

src/centreon/plugins/misc.pm

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -931,20 +931,27 @@ sub sort_ips($$) {
931931
}
932932

933933
# function to assess if a string has to be excluded given an include regexp and an exclude regexp
934-
sub is_excluded($;$;$) {
935-
my ($string, $include_regexp, $exclude_regexp) = @_;
934+
sub is_excluded($;$;$;%) {
935+
my ($string, $include_regexp, $exclude_regexp, %options) = @_;
936936
return 1 unless defined $string;
937937

938938
if (defined $exclude_regexp) {
939939
$exclude_regexp = [ $exclude_regexp ] unless ref $exclude_regexp eq 'ARRAY';
940-
return 1 if grep { defined && $_ ne '' && $string =~ /$_/ } @$exclude_regexp;
940+
if (grep { defined && $_ ne '' && $string =~ /$_/ } @$exclude_regexp) {
941+
$options{output}->output_add(long_msg => "skipping '$string': excluded by a filter.", debug => 1)
942+
if %options && $options{output};
943+
return 1
944+
}
941945
}
942946
return 0 unless defined $include_regexp;
943947
$include_regexp = [ $include_regexp ] unless ref $include_regexp eq 'ARRAY';
944948
return 0 unless @{$include_regexp};
945949

946950
return 0 if grep { (not defined) || $_ eq '' || $string =~ /$_/ } @$include_regexp;
947951

952+
$options{output}->output_add(long_msg => "skipping '$string': not included by any filter.", debug => 1)
953+
if %options && $options{output};
954+
948955
return 1;
949956
}
950957

@@ -1589,7 +1596,7 @@ Returns a sorted array.
15891596
15901597
=head2 is_excluded
15911598
1592-
my $excluded = is_excluded($string, $include_regexp, $exclude_regexp);
1599+
my $excluded = is_excluded($string, $include_regexp, $exclude_regexp, %options);
15931600
15941601
Determines whether a string should be excluded based on include and exclude regular expressions.
15951602
@@ -1601,6 +1608,8 @@ Determines whether a string should be excluded based on include and exclude regu
16011608
16021609
=item * C<$exclude_regexp> - A regular expression to exclude the string. If defined and matches the string, the function returns 1 (excluded).
16031610
1611+
=item * C<%options> - An optional hash that allows defining the output module in order to log when the string is excluded.
1612+
16041613
=back
16051614
16061615
Returns 1 if the string is excluded, 0 if it is included.
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
#
2+
# Copyright 2026-Present Centreon (http://www.centreon.com/)
3+
#
4+
# Centreon is a full-fledged industry-strength solution that meets
5+
# the needs in IT infrastructure and application monitoring for
6+
# service performance.
7+
#
8+
# Licensed under the Apache License, Version 2.0 (the "License");
9+
# you may not use this file except in compliance with the License.
10+
# You may obtain a copy of the License at
11+
#
12+
# http://www.apache.org/licenses/LICENSE-2.0
13+
#
14+
# Unless required by applicable law or agreed to in writing, software
15+
# distributed under the License is distributed on an "AS IS" BASIS,
16+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
# See the License for the specific language governing permissions and
18+
# limitations under the License.
19+
#
20+
21+
package network::huawei::standard::snmp::mode::gponontethernetport;
22+
23+
use base qw(centreon::plugins::templates::counter);
24+
25+
use strict;
26+
use warnings;
27+
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold_ng);
28+
use centreon::plugins::constants qw/:counters :values/;
29+
use centreon::plugins::misc qw/is_excluded/;
30+
use centreon::common::huawei::standard::snmp::functions qw/get_serial_string/;
31+
32+
sub prefix_module_output {
33+
my ($self, %options) = @_;
34+
35+
return sprintf("ONT '%s' - %s(%s) ethernet port %d (%s) ",
36+
$options{instance_value}->{display},
37+
$options{instance_value}->{serial},
38+
$options{instance_value}->{serial_hex},
39+
$options{instance_value}->{port_id},
40+
$options{instance_value}->{speed}
41+
);
42+
}
43+
44+
sub set_counters {
45+
my ($self, %options) = @_;
46+
47+
$self->{maps_counters_type} = [
48+
{
49+
name => 'ethernet_ports',
50+
type => COUNTER_TYPE_INSTANCE,
51+
cb_prefix_output => 'prefix_module_output',
52+
message_multiple => 'All ONT ethernet port are ok',
53+
skipped_code => { NO_VALUE() => 1 }
54+
}
55+
];
56+
57+
$self->{maps_counters}->{ethernet_ports} = [
58+
{
59+
label => 'status',
60+
type => COUNTER_KIND_TEXT,
61+
critical_default => '%{online_state} ne "linkup" || %{speed} eq "invalid"',
62+
set =>
63+
{
64+
key_values => [
65+
{ name => 'online_state' },
66+
{ name => 'display' },
67+
{ name => 'speed' }
68+
],
69+
closure_custom_perfdata => sub {return 0;},
70+
closure_custom_threshold_check => \&catalog_status_threshold_ng
71+
}
72+
}
73+
];
74+
}
75+
76+
sub new {
77+
my ($class, %options) = @_;
78+
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
79+
bless $self, $class;
80+
81+
$options{options}->add_options(arguments => {
82+
'include-serial:s' => { name => 'include_serial', default => '' },
83+
'exclude-serial:s' => { name => 'exclude_serial', default => '' }
84+
});
85+
86+
return $self;
87+
}
88+
89+
my $mapping_online_status = {
90+
1 => 'linkup',
91+
2 => 'linkdown',
92+
-1 => 'invalid'
93+
};
94+
95+
my $mapping_speed = {
96+
1 => 'speed10M',
97+
2 => 'speed100M',
98+
3 => 'speed1000M',
99+
4 => 'autoneg',
100+
5 => 'autospeed10M',
101+
6 => 'autospeed100M',
102+
7 => 'autospeed1000M',
103+
8 => 'speed10G',
104+
9 => 'autospeed10G',
105+
10 => 'speed2500M',
106+
11 => 'autospeed2500M',
107+
12 => 'speed5000M',
108+
13 => 'autospeed5000M',
109+
14 => 'speed25000M',
110+
15 => 'autospeed25000M',
111+
16 => 'speed40000M',
112+
17 => 'autospeed40000M',
113+
-1 => 'invalid'
114+
};
115+
116+
sub manage_selection {
117+
my ($self, %options) = @_;
118+
119+
my $mapping = {
120+
serial => { oid => '.1.3.6.1.4.1.2011.6.128.1.1.2.43.1.3' },# hwGponDeviceOntSn
121+
name => { oid => '.1.3.6.1.4.1.2011.6.128.1.1.2.43.1.9' }# hwGponDeviceOntDespt
122+
};
123+
124+
my $snmp_result = $options{snmp}->get_multiple_table(
125+
oids => [ { oid => $mapping->{serial}->{oid} }, { oid => $mapping->{name}->{oid} } ],
126+
return_type => 1,
127+
nothing_quit => 1
128+
);
129+
130+
my %ont = ();
131+
132+
foreach my $oid (keys %{$snmp_result}) {
133+
next if ($oid !~ /^$mapping->{name}->{oid}\.(.*)$/);
134+
my $instance = $1;
135+
136+
my $result = $options{snmp}->map_instance(mapping => $mapping, results => $snmp_result, instance => $instance);
137+
my $serial = get_serial_string($result->{serial}) // '';
138+
139+
next if is_excluded($serial, $self->{option_results}->{include_serial}, $self->{option_results}->{exclude_serial}, output => $self->{output});
140+
141+
$ont{$instance} = {
142+
name => $result->{name},
143+
serial => $serial,
144+
serial_hex => uc(unpack("H*", $result->{serial})),
145+
};
146+
}
147+
148+
149+
$self->{output}->option_exit(short_msg => 'no ethernet_ports associated')
150+
unless keys %ont;
151+
152+
$mapping = {
153+
online_state => { oid => '.1.3.6.1.4.1.2011.6.128.1.1.2.62.1.22', map => $mapping_online_status },
154+
speed => { oid => '.1.3.6.1.4.1.2011.6.128.1.1.2.62.1.4', map => $mapping_speed }
155+
};
156+
157+
$snmp_result = $options{snmp}->get_multiple_table(
158+
oids => [ { oid => $mapping->{online_state}->{oid} }, { oid => $mapping->{speed}->{oid} } ],
159+
return_type => 1,
160+
nothing_quit => 1
161+
);
162+
163+
foreach my $oid (keys %{$snmp_result}) {
164+
next if ($oid !~ /^$mapping->{online_state}->{oid}\.(.*)$/);
165+
my $ont_instance = $1;
166+
my ($ont_index, $port_id) = $ont_instance =~ /^(.*)\.([^.]+)$/;
167+
168+
if (defined($ont{$ont_index})) {
169+
my $result = $options{snmp}->map_instance(
170+
mapping => $mapping,
171+
results => $snmp_result,
172+
instance => $ont_instance
173+
);
174+
175+
my $port_instance = $ont_index . '-' . $port_id;
176+
177+
$self->{ethernet_ports}->{$port_instance} = {
178+
online_state => $result->{online_state},
179+
speed => $result->{speed},
180+
port_id => $port_id,
181+
instance => $port_instance,
182+
display => $ont{$ont_index}->{name},
183+
serial => $ont{$ont_index}->{serial},
184+
serial_hex => $ont{$ont_index}->{serial_hex},
185+
};
186+
}
187+
}
188+
}
189+
190+
1;
191+
192+
__END__
193+
194+
=head1 MODE
195+
196+
Shows the status of a ONT module ETH port for GPON
197+
198+
=over 8
199+
200+
=item B<--include-serial>
201+
202+
Filter ONT by serial (can be a regexp).
203+
204+
=item B<--exclude-serial>
205+
206+
Exclude ONT by serial (can be a regexp).
207+
208+
=item B<--warning-status>
209+
210+
Define the conditions to match for the status to be WARNING.
211+
You can use the following variables: C<%{online_state}>, C<%{display}>, C<%(speed)>.
212+
C<%(online_state)> can have one of these values: C<linkup>, C<linkdown>, C<invalid>.
213+
C<%(speed)> can have one of these values: C<speed10M>, C<speed100M>, C<speed1000M>, C<autoneg>, C<autospeed10M>,
214+
C<autospeed100M>, C<autospeed1000M>, C<speed10G>, C<autospeed10G>, C<speed2500M>, C<autospeed2500M>, C<speed5000M>,
215+
C<autospeed5000M>, C<speed25000M>, C<autospeed25000M>, C<speed40000M>, C<autospeed40000M>, C<invalid>
216+
217+
=item B<--critical-status>
218+
219+
Define the conditions to match for the status to be CRITICAL. (default: C<'%{online_state} ne "linkup" || %{speed} eq "invalid"'>).
220+
You can use the following variables: C<%{online_state}>, C<%{display}>, C<%(speed)>.
221+
C<%(online_state)> can have one of these values: C<linkup>, C<linkdown>, C<invalid>.
222+
C<%(speed)> can have one of these values: C<speed10M>, C<speed100M>, C<speed1000M>, C<autoneg>, C<autospeed10M>,
223+
C<autospeed100M>, C<autospeed1000M>, C<speed10G>, C<autospeed10G>, C<speed2500M>, C<autospeed2500M>, C<speed5000M>,
224+
C<autospeed5000M>, C<speed25000M>, C<autospeed25000M>, C<speed40000M>, C<autospeed40000M>, C<invalid>
225+
226+
=back
227+
228+
=cut

0 commit comments

Comments
 (0)