mirror of
https://github.com/librenms/librenms-agent.git
synced 2024-05-09 09:54:52 +00:00
Merge pull request #226 from VVelox/smart-update
SMART monitoring update adding RAID support
This commit is contained in:
+99
-82
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env perl
|
||||
#Copyright (c) 2017, Zane C. Bowers-Hadley
|
||||
#Copyright (c) 2019, Zane C. Bowers-Hadley
|
||||
#All rights reserved.
|
||||
#
|
||||
#Redistribution and use in source and binary forms, with or without modification,
|
||||
@@ -38,14 +38,17 @@ will be /etc/snmp/smart.config. Alternatively you can also specific a config via
|
||||
|
||||
Anything starting with a # is comment. The format for variables is $variable=$value. Empty
|
||||
lines are ignored. Spaces and tabes at either the start or end of a line are ignored. Any
|
||||
line with out a = or # are treated as a disk.
|
||||
line with out a matched variable or # are treated as a disk.
|
||||
|
||||
#This is a comment
|
||||
cache=/var/cache/smart
|
||||
smartctl=/usr/local/sbin/smartctl
|
||||
useSN=0
|
||||
ada0
|
||||
ada1
|
||||
da5 /dev/da5 -d sat
|
||||
twl0,0 /dev/twl0 -d 3ware,0
|
||||
twl0,1 /dev/twl0 -d 3ware,1
|
||||
twl0,2 /dev/twl0 -d 3ware,2
|
||||
|
||||
The variables are as below.
|
||||
|
||||
@@ -54,8 +57,13 @@ The variables are as below.
|
||||
useSN = If set to 1, it will use the disks SN for reporting instead of the device name.
|
||||
1 is the default. 0 will use the device name.
|
||||
|
||||
A disk line is can be as simple as just a disk name under /dev/. Such as in the config above
|
||||
The line "ada0" would resolve to "/dev/ada0" and would be called with no special argument. If
|
||||
a line has a space in it, everything before the space is treated as the disk name and is what
|
||||
used for reporting and everything after that is used as the argument to be passed to smartctl.
|
||||
|
||||
If you want to guess at the configuration, call it with -g and it will print out what it thinks
|
||||
it should be.
|
||||
it should be.
|
||||
|
||||
=cut
|
||||
|
||||
@@ -73,10 +81,9 @@ my $useSN=1;
|
||||
|
||||
$Getopt::Std::STANDARD_HELP_VERSION = 1;
|
||||
sub main::VERSION_MESSAGE {
|
||||
print "SMART SNMP extend 0.0.0\n";
|
||||
print "SMART SNMP extend 0.1.0\n";
|
||||
};
|
||||
|
||||
|
||||
sub main::HELP_MESSAGE {
|
||||
print "\n".
|
||||
"-u Update '".$cache."'\n".
|
||||
@@ -108,75 +115,70 @@ if ( defined( $opts{g} ) ){
|
||||
$cache='cache='.$cache."\n";
|
||||
}
|
||||
|
||||
my %found_disks;
|
||||
|
||||
#check for drives named /dev/sd*
|
||||
my @matches=glob('/dev/sd*');
|
||||
@matches=grep(!/[0-9]/, @matches);
|
||||
my $matches_int=0;
|
||||
while ( defined( $matches[$matches_int] ) ){
|
||||
my $device=$matches[$matches_int];
|
||||
system( $smartctl.' -A '.$device.' > /dev/null' );
|
||||
if ( $? == 0 ){
|
||||
$device =~ s/\/dev\///;
|
||||
$found_disks{$device}=1;
|
||||
}
|
||||
|
||||
$matches_int++;
|
||||
}
|
||||
|
||||
#check for drives named /dev/ada*
|
||||
@matches=glob('/dev/ada*');
|
||||
@matches=grep(!/[ps]/, @matches);
|
||||
$matches_int=0;
|
||||
while ( defined( $matches[$matches_int] ) ){
|
||||
my $device=$matches[$matches_int];
|
||||
system( $smartctl.' -A '.$device.' > /dev/null' );
|
||||
if ( $? == 0 ){
|
||||
$device =~ s/\/dev\///;
|
||||
$found_disks{$device}=1;
|
||||
}
|
||||
|
||||
$matches_int++;
|
||||
}
|
||||
|
||||
#check for drives named /dev/da*
|
||||
@matches=glob('/dev/da*');
|
||||
@matches=grep(!/[ps]/, @matches);
|
||||
$matches_int=0;
|
||||
while ( defined( $matches[$matches_int] ) ){
|
||||
my $device=$matches[$matches_int];
|
||||
system( $smartctl.' -A '.$device.' > /dev/null' );
|
||||
if ( $? == 0 ){
|
||||
$device =~ s/\/dev\///;
|
||||
$found_disks{$device}=1;
|
||||
}
|
||||
|
||||
$matches_int++;
|
||||
}
|
||||
# used for checking if a disk has been found more than once
|
||||
my %found_disks_names;
|
||||
my @argumentsA;
|
||||
|
||||
#have smartctl scan and see if it finds anythings not get found
|
||||
my $scan_output=`$smartctl --scan-open`;
|
||||
my @scan_outputA=split(/\n/, $scan_output);
|
||||
|
||||
# remove non-SMART devices sometimes returned
|
||||
@scan_outputA=grep(!/ses[0-9]/, @scan_outputA); # not a disk, but may or may not have SMART attributes
|
||||
@scan_outputA=grep(!/pass[0-9]/, @scan_outputA); # very likely a duplicate and a disk under another name
|
||||
$matches_int=0;
|
||||
while ( defined( $scan_outputA[$matches_int] ) ){
|
||||
my $device=$scan_outputA[$matches_int];
|
||||
$device =~ s/ .*//;
|
||||
system( $smartctl.' -A '.$device.' > /dev/null' );
|
||||
if ( $? == 0 ){
|
||||
$device =~ s/\/dev\///;
|
||||
$found_disks{$device}=1;
|
||||
}
|
||||
|
||||
$matches_int++;
|
||||
@scan_outputA=grep(!/cd[0-9]/, @scan_outputA); # CD drive
|
||||
if ( $^O eq 'freebsd' ){
|
||||
@scan_outputA=grep(!/sa[0-9]/, @scan_outputA); # tape drive
|
||||
@scan_outputA=grep(!/ctl[0-9]/, @scan_outputA); # CAM target layer
|
||||
}elsif( $^O eq 'linux' ){
|
||||
@scan_outputA=grep(!/st[0-9]/, @scan_outputA); # SCSI tape drive
|
||||
@scan_outputA=grep(!/ht[0-9]/, @scan_outputA); # ATA tape drive
|
||||
}
|
||||
|
||||
|
||||
# make the first pass, figuring out what all we have and trimming comments
|
||||
foreach my $arguments ( @scan_outputA ){
|
||||
my $name = $arguments;
|
||||
|
||||
$arguments =~ s/ \#.*//; # trim the comment out of the argument
|
||||
$name =~ s/ .*//;
|
||||
$name =~ s/\/dev\///;
|
||||
if (defined( $found_disks_names{$name} )){
|
||||
$found_disks_names{$name}++;
|
||||
}else{
|
||||
$found_disks_names{$name}=0;
|
||||
}
|
||||
|
||||
push( @argumentsA, $arguments );
|
||||
|
||||
}
|
||||
|
||||
# second pass, putting the lines together
|
||||
my %current_disk;
|
||||
my $drive_lines='';
|
||||
foreach my $arguments ( @argumentsA ){
|
||||
my $name = $arguments;
|
||||
$name =~ s/ .*//;
|
||||
$name =~ s/\/dev\///;
|
||||
|
||||
if ( $found_disks_names{$name} == 0 ){
|
||||
# If no other devices, just name it after the base device.
|
||||
$drive_lines=$drive_lines.$name." ".$arguments."\n";
|
||||
}else{
|
||||
# if more than one, start at zero and increment, apennding comma number to the base device name
|
||||
if (defined( $current_disk{$name} )){
|
||||
$current_disk{$name}++;
|
||||
}else{
|
||||
$current_disk{$name}=0;
|
||||
}
|
||||
$drive_lines=$drive_lines.$name.",".$current_disk{$name}." ".$arguments."\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print "useSN=0\n".'smartctl='.$smartctl."\n".
|
||||
$cache.
|
||||
join( "\n", keys(%found_disks) )."\n";
|
||||
|
||||
$cache.
|
||||
$drive_lines;
|
||||
|
||||
exit 0;
|
||||
}
|
||||
|
||||
@@ -200,27 +202,32 @@ my @configA=split(/\n/, $config_file);
|
||||
my $configA_int=0;
|
||||
while ( defined( $configA[$configA_int] ) ){
|
||||
my $line=$configA[$configA_int];
|
||||
chomp($line);
|
||||
$line=~s/^[\t\s]+//;
|
||||
$line=~s/[\t\s]+$//;
|
||||
|
||||
my ( $var, $val )=split(/=/, $line, 2);
|
||||
|
||||
my $matched;
|
||||
if ( $var eq 'cache' ){
|
||||
$cache=$val;
|
||||
$matched=1;
|
||||
}
|
||||
|
||||
|
||||
if ( $var eq 'smartctl' ){
|
||||
$smartctl=$val;
|
||||
$matched=1;
|
||||
}
|
||||
|
||||
if ( $var eq 'useSN' ){
|
||||
$useSN=$val;
|
||||
$matched=1;
|
||||
}
|
||||
|
||||
|
||||
if ( !defined( $val ) ){
|
||||
push(@disks, $var);
|
||||
push(@disks, $line);
|
||||
}
|
||||
|
||||
|
||||
$configA_int++;
|
||||
}
|
||||
|
||||
@@ -244,11 +251,22 @@ if ( ! defined( $opts{u} ) ){
|
||||
}
|
||||
|
||||
my $toReturn='';
|
||||
my $int=0;
|
||||
while ( defined($disks[$int]) ) {
|
||||
my $disk=$disks[$int];
|
||||
foreach my $line ( @disks ){
|
||||
my $disk;
|
||||
my $name;
|
||||
if ( $line =~ /\ / ){
|
||||
($name, $disk)=split(/\ /, $line, 2);
|
||||
}else{
|
||||
$disk=$line;
|
||||
$name=$line;
|
||||
}
|
||||
my $disk_sn=$disk;
|
||||
my $output=`$smartctl -A /dev/$disk`;
|
||||
my $output;
|
||||
if ( $disk =~ /\// ){
|
||||
$output=`$smartctl -A $disk`;
|
||||
}else{
|
||||
$output=`$smartctl -A /dev/$disk`;
|
||||
}
|
||||
|
||||
my %IDs=( '5'=>'null',
|
||||
'10'=>'null',
|
||||
@@ -267,7 +285,7 @@ while ( defined($disks[$int]) ) {
|
||||
'231'=>'null',
|
||||
'233'=>'null',
|
||||
);
|
||||
|
||||
|
||||
my @outputA=split( /\n/, $output );
|
||||
my $outputAint=0;
|
||||
while ( defined($outputA[$outputAint]) ) {
|
||||
@@ -281,7 +299,7 @@ while ( defined($disks[$int]) ) {
|
||||
my $id=$lineA[0];
|
||||
|
||||
# single int raw values
|
||||
if (
|
||||
if (
|
||||
( $id == 5 ) ||
|
||||
( $id == 10 ) ||
|
||||
( $id == 173 ) ||
|
||||
@@ -319,8 +337,8 @@ while ( defined($disks[$int]) ) {
|
||||
) {
|
||||
my ( $temp )=split(/\ /, $raw);
|
||||
$IDs{$id}=$temp;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$outputAint++;
|
||||
@@ -337,9 +355,9 @@ while ( defined($disks[$int]) ) {
|
||||
my $short=scalar grep(/Short/, @outputA);
|
||||
my $conveyance=scalar grep(/Conveyance/, @outputA);
|
||||
my $selective=scalar grep(/Selective/, @outputA);
|
||||
|
||||
|
||||
# get the drive serial number, if needed
|
||||
my $disk_id=$disk;
|
||||
my $disk_id=$name;
|
||||
if ( $useSN ){
|
||||
while (`$smartctl -i /dev/$disk` =~ /Serial Number:(.*)/g) {
|
||||
$disk_id = $1;
|
||||
@@ -351,7 +369,6 @@ while ( defined($disks[$int]) ) {
|
||||
.','.$IDs{'190'} .','.$IDs{'194'}.','.$IDs{'196'}.','.$IDs{'197'}.','.$IDs{'198'}.','.$IDs{'199'}.','.$IDs{'231'}.','.$IDs{'233'}.','.
|
||||
$completed.','.$interrupted.','.$read_failure.','.$unknown_failure.','.$extended.','.$short.','.$conveyance.','.$selective."\n";
|
||||
|
||||
$int++;
|
||||
}
|
||||
|
||||
if ( ! $noWrite ){
|
||||
|
||||
Reference in New Issue
Block a user