From 0e2fd28b6308e9abc5381f7746ca78aafffb5287 Mon Sep 17 00:00:00 2001 From: qgarnier Date: Tue, 4 Jan 2022 14:37:24 +0100 Subject: [PATCH] enh(synology/snmp): mode hardware - add disk bad sectors (#3374) --- storage/synology/snmp/mode/components/disk.pm | 63 ++++++++++++++----- storage/synology/snmp/mode/hardware.pm | 18 +++++- 2 files changed, 61 insertions(+), 20 deletions(-) diff --git a/storage/synology/snmp/mode/components/disk.pm b/storage/synology/snmp/mode/components/disk.pm index 4c0410b9a..bcb4263dd 100644 --- a/storage/synology/snmp/mode/components/disk.pm +++ b/storage/synology/snmp/mode/components/disk.pm @@ -32,49 +32,78 @@ my $map_disk_status = { }; my $mapping = { - synoDiskdiskName => { oid => '.1.3.6.1.4.1.6574.2.1.1.2' }, - synoDiskdiskStatus => { oid => '.1.3.6.1.4.1.6574.2.1.1.5', map => $map_disk_status } + status => { oid => '.1.3.6.1.4.1.6574.2.1.1.5', map => $map_disk_status }, # synoDiskdiskStatus + badSectors => { oid => '.1.3.6.1.4.1.6574.2.1.1.9' } # diskBadSector }; -my $oid_synoDisk = '.1.3.6.1.4.1.6574.2.1.1'; +my $oid_diskName = '.1.3.6.1.4.1.6574.2.1.1.2'; # synoDiskdiskName sub load { my ($self) = @_; - push @{$self->{request}}, { - oid => $oid_synoDisk, - start => $mapping->{synoDiskdiskName}->{oid}, - end => $mapping->{synoDiskdiskStatus}->{oid} - }; + push @{$self->{request}}, { oid => $oid_diskName }; } sub check { my ($self) = @_; $self->{output}->output_add(long_msg => "Checking disk"); - $self->{components}->{disk} = {name => 'disk', total => 0, skip => 0}; + $self->{components}->{disk} = { name => 'disk', total => 0, skip => 0 }; return if ($self->check_filter(section => 'disk')); - foreach my $oid ($self->{snmp}->oid_lex_sort(keys %{$self->{results}->{$oid_synoDisk}})) { - next if ($oid !~ /^$mapping->{synoDiskdiskStatus}->{oid}\.(\d+)/); - my $instance = $1; - my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $self->{results}->{$oid_synoDisk}, instance => $instance); + my $instances = []; + foreach (keys %{$self->{results}->{$oid_diskName}}) { + push @$instances, $1 if (/^$oid_diskName\.(.*)$/); + } + return if (scalar(@$instances) <= 0); + + $self->{snmp}->load( + oids => [map($_->{oid}, values(%$mapping))], + instances => $instances + ); + my $results = $self->{snmp}->get_leef(); + + foreach my $oid ($self->{snmp}->oid_lex_sort(keys %$results)) { + next if ($oid !~ /^$mapping->{status}->{oid}\.(\d+)/); + my $instance = $1; + my $result = $self->{snmp}->map_instance(mapping => $mapping, results => $results, instance => $instance); + + my $name = $self->{results}->{$oid_diskName}->{$oid_diskName . '.' . $instance}; next if ($self->check_filter(section => 'disk', instance => $instance)); $self->{components}->{disk}->{total}++; $self->{output}->output_add( long_msg => sprintf( - "disk '%s' status is %s [instance: %s]", - $result->{synoDiskdiskName}, $result->{synoDiskdiskStatus}, $instance + "disk '%s' status is %s [instance: %s%s]", + $name, $result->{status}, $instance, + defined($result->{badSectors}) ? ', bad sectors: ' . $result->{badSectors} : '' ) ); - my $exit = $self->get_severity(section => 'disk', value => $result->{synoDiskdiskStatus}); + my $exit = $self->get_severity(section => 'disk', value => $result->{status}); if (!$self->{output}->is_status(value => $exit, compare => 'ok', litteral => 1)) { $self->{output}->output_add( severity => $exit, - short_msg => sprintf("Disk '%s' status is %s", $result->{synoDiskdiskName}, $result->{synoDiskdiskStatus}) + short_msg => sprintf("Disk '%s' status is %s", $name, $result->{status}) ); } + + next if (!defined($result->{badSectors})); + + my ($exit2, $warn, $crit, $checked) = $self->get_severity_numeric(section => 'disk.badsectors', instance => $instance, value => $result->{badSectors}); + if (!$self->{output}->is_status(value => $exit2, compare => 'ok', litteral => 1)) { + $self->{output}->output_add( + severity => $exit2, + short_msg => sprintf("Disk '%s' has %s bad sector(s)", $name, $result->{badSectors}) + ); + } + $self->{output}->perfdata_add( + nlabel => 'hardware.disk.bad_sectors.count', + instances => $name, + value => $result->{badSectors}, + warning => $warn, + critical => $crit, + min => 0 + ); } } diff --git a/storage/synology/snmp/mode/hardware.pm b/storage/synology/snmp/mode/hardware.pm index 8ed44abde..141a4099e 100644 --- a/storage/synology/snmp/mode/hardware.pm +++ b/storage/synology/snmp/mode/hardware.pm @@ -28,6 +28,8 @@ use warnings; sub set_system { my ($self, %options) = @_; + $self->{regexp_threshold_numeric_check_section_option} = '^(?:disk.badsectors)$'; + $self->{cb_hook2} = 'snmp_execute'; $self->{thresholds} = { @@ -69,7 +71,7 @@ sub set_system { }; $self->{components_path} = 'storage::synology::snmp::mode::components'; - $self->{components_module} = ['psu', 'fan', 'disk', 'raid', 'system']; + $self->{components_module} = ['disk', 'fan', 'psu', 'raid', 'system']; $self->{request_leef} = []; } @@ -88,7 +90,7 @@ sub snmp_execute { sub new { my ($class, %options) = @_; - my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, no_performance => 1); + my $self = $class->SUPER::new(package => __PACKAGE__, %options, no_absent => 1, force_new_perfdata => 1); bless $self, $class; $options{options}->add_options(arguments => {}); @@ -102,7 +104,7 @@ __END__ =head1 MODE -Check hardware (SYNOLOGY-SYSTEM-MIB, SYNOLOGY-RAID-MIB) (Fans, Power Supplies, Disk status, Raid status, System status). +Check hardware. =over 8 @@ -127,6 +129,16 @@ Set to overload default threshold values (syntax: section,[instance,]status,rege It used before default thresholds (order stays). Example: --threshold-overload='psu,CRITICAL,^(?!(on)$)' +=item B<--warning> + +Set warning threshold for 'disk.badsectors' (syntax: type,regexp,threshold) +Example: --warning='disk.badsectors,.*,30' + +=item B<--critical> + +Set critical threshold for 'disk.badsectors' (syntax: type,regexp,threshold) +Example: --critical='disk.badsectors,.*,50' + =back =cut