#!/usr/bin/perl # # # # # # #./new_raid_status.pl lsi 0 0 | rev | cut -d: -f2- | rev | cut -d: -f5- #159483946861 use strict; use Switch; use File::stat; my $tmp_file_status_raid = '/tmp/status_raid'; my $max_diff_old_file = 60; my $arcconf = `which arcconf 2>/dev/null` || '/usr/StorMan/arcconf'; my $three_ware = `which tw_cli 2>/dev/null` || '/sbin/tw_cli'; my $megacli = `which MegaCli 2>/dev/null` || `which megacli 2>/dev/null` || '/opt/MegaRAID/MegaCli/MegaCli64'; my $mpt = `which mpt-status 2>/dev/null` || '/usr/sbin/mpt-status'; my $mdadm = '/proc/mdstat'; main(shift, shift, shift, shift); sub main { my $vendor = shift; my $opt1 = shift; my $opt2 = shift; my $opt3 = shift; my $result = 'Unknown'; switch($vendor) { case 'adaptec' { $result = get_status_adaptec($opt1, $opt2, $opt3) } case '3ware' { $result = get_status_3ware($opt1, $opt2) } case 'lsi' { $result = get_status_lsi($opt1, $opt2, $opt3) } case 'mpt' { $result = get_status_mpt($opt1, $opt2) } case 'mdadm' { $result = get_status_mdadm($opt1) } else {} } $result=~s/\s+$//; $result=~s/\;$// if (index($result, ';')+1 == length($result)); print $result."\n"; } sub get_status_lsi($$$) { my $opt1 = shift; my $opt2 = shift; my $opt3 = shift; my $megapostopt = '-NoLog'; # additional options to call at the end of MegaCli arguments my ($adapters); my $hotsparecount = 0; my $pdbad = 0; my $pdcount = 0; my $mediaerrors = 0; my $mediaallow = 0; my $prederrors = 0; my $predallow = 0; my $othererrors = 0; my $otherallow = 0; my $result = ''; chomp($megacli); # Some sanity checks that you actually have something where you think MegaCli is (-e $megacli) or return "error: $megacli does not found"; # Getting list of all controllers open (ADPCOUNT, "$megacli -adpCount $megapostopt |") or return "error: Could not execute $megacli"; while () { if ( m/Controller Count:\s*(\d+)/ ) { $adapters = $1; last; } } close ADPCOUNT; my $adp_tmp = 0; my $ld_tmp = 0; if ($opt1=~/\d+/) { ($adapters > $opt1) or return "error: Count of founded adapters less than you want"; $adp_tmp = $opt1; $adapters = ++$opt1; } ADAPTER: for ( my $adp = $adp_tmp; $adp < $adapters; $adp++ ) { if ((defined($opt2) and $opt2 eq 'bbu') or (defined($opt1) and $opt1 eq 'bbu')) { open (BBUSTATUS, "$megacli -AdpBbuCmd -a$adp $megapostopt |") or return "error: Could not execute $megacli -AdpBbuCmd -a$adp $megapostopt"; my $bbu_state; while () { #Battery State : Operational if ( m/Battery\sState\s+\:\s*(.+)/ ) { $bbu_state = $1; last; } elsif ( m/Get\sBBU\sStatus\s(\S+)\./) { $bbu_state = $1; last; } } close BBUSTATUS; $result .= "$adp:$bbu_state; " unless defined $opt2; $result = $bbu_state if defined $opt2; next; } # Get count of logical drives from each controllers open (LDGETNUM, "$megacli -LdGetNum -a$adp $megapostopt |") or return "error: Could not execute $megacli -LdGetNum -a$adp $megapostopt"; my ($ldnum); while () { if ( m/Number of Virtual drives configured on adapter \d:\s*(\d+)/i ) { $ldnum = $1; last; } } close LDGETNUM; if ($opt1=~/\d+/ and $opt2=~/\d+/) { ($ldnum > $opt2) or return "error: Count of founded logical disks on this adapter less than you want"; $ld_tmp = $opt2; $ldnum = ++$opt2; } LDISK: for ( my $ld = $ld_tmp; $ld < $ldnum; $ld++ ) { # Getting info about each logical drive open (LDINFO, "$megacli -LdInfo -L$ld -a$adp $megapostopt |") or return "error: Could not execute $megacli -LdInfo -L$ld -a$adp $megapostopt"; my ($size, $unit, $raidlevel, $ldpdcount, $state, $spandepth); while () { if ( m/Size\s*:\s*((\d+\.?\d*)\s*(MB|GB|TB))/ ) { $size = $2; $unit = $3; if ( $unit eq 'MB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024) ); } if ( $unit eq 'GB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024) ); } if ( $unit eq 'TB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024 * 1024) ); } } elsif ( m/State\s*:\s*(\w+)/ ) { $state = $1; } elsif ( m/Number Of Drives\s*(per span\s*)?:\s*(\d+)/ ) { $ldpdcount = $2; } elsif ( m/Span Depth\s*:\s*(\d+)/ ) { $spandepth = $1; } elsif ( m/RAID Level\s*: Primary-(\d)/ ) { $raidlevel = $1; } } close LDINFO; # Report correct RAID-level and number of drives in case of Span configurations if ($ldpdcount && $spandepth > 1) { $ldpdcount = $ldpdcount * $spandepth; if ($raidlevel < 10) { $raidlevel = $raidlevel . "0"; } } $result .= "$adp:$ld:RAID-$raidlevel:$ldpdcount drives:$size:$state; "; } #LDISK close LDINFO; # Getting list of all phisical drives from each controller open (PDLIST, "$megacli -PdList -a$adp $megapostopt |") or return "error: Could not execute $megacli -PdList -a$adp $megapostopt "; my ($slotnumber,$fwstate); PDISKS: while () { if ( m/Slot Number\s*:\s*(\d+)/ ) { $slotnumber = $1; $pdcount++; } elsif ( m/(\w+) Error Count\s*:\s*(\d+)/ ) { if ( $1 eq 'Media') { $mediaerrors += $2; } else { $othererrors += $2; } } elsif ( m/Predictive Failure Count\s*:\s*(\d+)/ ) { $prederrors += $1; } elsif ( m/Firmware state\s*:\s*(\w+)/ ) { $fwstate = $1; if ( $fwstate eq 'Hotspare' ) { $hotsparecount++; } elsif ( $fwstate eq 'Online' ) { # Do nothing } elsif ( $fwstate eq 'Unconfigured' ) { # A drive not in anything, or a non drive device $pdcount--; } elsif ( $slotnumber != 255 ) { $pdbad++; } } } #PDISKS close PDLIST; } if (defined($opt1) and $opt1 eq 'hotspares') { return $hotsparecount; } if (defined($opt1) and $opt1 eq 'pdbad') { return $pdbad; } if (defined($opt1) and $opt1 eq 'drives') { return $pdcount; } unless (defined($opt1)) { # my $errorcount = $mediaerrors + $prederrors + $othererrors; } return $result || 'Unknown'; } sub get_status_adaptec($) { my $opt1 = shift; my $result_tmp; my $device_name; my $state; my $status_physical_device; my $segment_status; my $segment_id; my $size; my $unit; my $tmp_t; my $tmp_l; my $pdcount = 0; my $raidlevel; my $hotsparecount = 0; my $ldpdcount = 0; my $result = ''; chomp($arcconf); (-e $arcconf) or return "error: $arcconf does not found"; if (defined($opt1) and $opt1 eq 'bbu') { open (BBU, "$arcconf GETCONFIG 1 AL |") or return "error: Could not execute $arcconf GETCONFIG 1 AL"; my $tmp_bbu = 0; while () { if (m/Controller\sBattery\sInformation/) { $tmp_bbu = 1; } elsif (m/Status\s+\:\s+(.+)/ and $tmp_bbu == 1) { close BBU; return $1 || 'Unknown'; } } close BBU; return 'Unknown'; } open (PD, "$arcconf GETCONFIG 1 PD |") or return "error: Could not execute $arcconf GETCONFIG 1 PD"; while () { if (m/^\s+State\s+\:\s(.+)/) { $status_physical_device = $1; $pdcount++; if ( $status_physical_device eq 'Hot Spare' ) { $hotsparecount++; } elsif ( $status_physical_device eq 'Online' ) { # Do nothing } } elsif (m/\s+Reported\sChannel\,Device.+\:\s(\d+)\,(\d+).*/) { $result_tmp->{'physical'}->{$1}->{$2} = $status_physical_device; } elsif (m/\s+Reported\sLocation.+\:\sConnector\s(\d+)\,\sDevice\s(\d+).*/) { $result_tmp->{'physical'}->{$1}->{$2} = $status_physical_device; } } close PD; if (defined($opt1) and $opt1 eq 'hotspares') { return $hotsparecount; } if (defined($opt1) and $opt1 eq 'drives') { return $pdcount; } open (LD, "$arcconf GETCONFIG 1 LD |") or return "error: Could not execute $arcconf GETCONFIG 1 LD"; while () { if ( m/Size\s*:\s*((\d+\.?\d*)\s*(MB|GB|TB))/ ) { $size = $2; $unit = $3; if ( $unit eq 'MB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024) ); } if ( $unit eq 'GB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024) ); } if ( $unit eq 'TB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024 * 1024) ); } $result_tmp->{'logical'}->{$device_name}->{'size'} = $size; } elsif (m/RAID\slevel\s+\:\s(\d+)/) { $raidlevel = $1; $result_tmp->{'logical'}->{$device_name}->{'raidlevel'} = $raidlevel; } elsif (m/Logical\sdevice\snumber\s(\d+)/) { $device_name = $1; $result_tmp->{'logical'}->{$device_name}->{'ldpdcount'} = 0; } elsif (m/.*Logical\sdevice\sname.+\:\s(.+)/) { $device_name = $1; $result_tmp->{'logical'}->{$device_name}->{'ldpdcount'} = 0; } elsif (m/.*Status\sof\slogical\sdevice.+\:\s(.+)/) { $state = $1; $result_tmp->{'logical'}->{$device_name}->{'status'} = $state; } elsif (m/.*Segment\s(\d+).+\:\s(.+)\s\((\d+)\,(\d+)\).+/) { $segment_id = $1; $segment_status = $2; $tmp_t = $3; $tmp_l = $4; ++$result_tmp->{'logical'}->{$device_name}->{'ldpdcount'}; } elsif (m/.*Segment\s(\d+).+\:\s(.+)\s\(Controller\:\d+\,Connector\:(.+),Device\:(\d+)\).+/) { $segment_id = $1; $segment_status = $2; $tmp_t = $3; $tmp_l = $4; ++$result_tmp->{'logical'}->{$device_name}->{'ldpdcount'}; } } close (LD); foreach my $device_name (sort keys %{$result_tmp->{'logical'}}) { next if (defined($opt1) and $opt1 ne $device_name); my $raidlevel = $result_tmp->{'logical'}->{$device_name}->{'raidlevel'}; my $ldpcount = $result_tmp->{'logical'}->{$device_name}->{'ldpdcount'}; my $state = $result_tmp->{'logical'}->{$device_name}->{'status'}; $result .= "$device_name:RAID-$raidlevel:$ldpcount drives:$size:$state; "; } return $result || 'Unknown'; } sub get_status_mdadm($) { my $opt1 = shift; my $result = ''; my $pd_count = 0; my $result_tmp; (-e $mdadm) or return "error: $mdadm does not found"; open (MDADM, "< $mdadm") or return "error: Could not open $mdadm"; my ($device_name, $state, $raidlevel, $pdcount, $size, $units); while () { if (m/^(md\S*)\s\:\s(\S+)\s(\S+)\s.+/) { $device_name = $1; $state = $2; $raidlevel = $3; $raidlevel = 'RAID-'.$1 if ($raidlevel=~/raid(\d+)/); $result_tmp->{$device_name}{'state'} = ucfirst($state); $result_tmp->{$device_name}{'raidlevel'} = $raidlevel; $result_tmp->{$device_name}{'pdcount'} = $pdcount; } elsif (m/ \[_|_\]|U_|_U /) { $result_tmp->{$device_name}{'state'} = 'Degraded'; } elsif (m/\s(resync|recovery)\s/) { $result_tmp->{$device_name}{'state'} = ucfirst($1); } if (m/blocks\s.+\[(\d+)\//) { $pd_count = $pd_count + $1; $result_tmp->{$device_name}{'pdcount'} = $1; } } close MDADM; if (defined($opt1) and $opt1 eq 'drives') { return $pd_count; } open (DF, "/bin/df -BM |") or return "error: Could not execute /bin/df -BM"; while () { if (m/\/dev\/(md\S+)\s+(\d+)(\S)\s+/) { $device_name = $1; $size = $2; $units = $3; next unless (defined($result_tmp->{$device_name})); $size = sprintf( "%.0f", ($size * 1024 * 1024) ); $result_tmp->{$device_name}{'size'} = $size; } } close DF; foreach my $device_name (sort keys %{$result_tmp}){ my $state = $result_tmp->{$device_name}{'state'}; my $raidlevel = $result_tmp->{$device_name}{'raidlevel'}; my $pdcount = $result_tmp->{$device_name}{'pdcount'}; my $size = $result_tmp->{$device_name}{'size'} || 0; next if (defined($opt1) and $opt1 ne $device_name); $result .= "$device_name:$raidlevel:$pdcount drives:$size:$state; "; } return $result || 'Unknown'; } ## TSS MPT-STATUS HACK # if the id is not the default id=0, then we need to identify it and pass it back to get_status_mpt sub get_mpt_id { open (IDS, "$mpt -p | ") or return "error: Could not open $mpt "; while () { if (m/Found.*\ id\=(\d)/) { return $1; } if (m/Nothing\ Found/) { return "NA"; } } } ## /TSS MPT-STATUS HACK sub get_status_mpt($$) { my $opt1 = shift; my $opt2 = shift; my $result = ''; my $pd_count = 0; my $result_tmp; chomp($mpt); if (defined($opt1) and $opt1=~/\D+/ and $opt1 ne 'drives') { return "error: Incorrect adapter number"; } if (defined($opt2) and $opt2=~/\D+/) { return "error: Incorrect logical drive number"; } (-e $mpt) or return "error: $mpt does not found"; open (MPT, "$mpt -n | ") or return "error: Could not open $mpt "; while () { #TSS MPT-STATUS HACK if (m/You\ seem\ to\ have\ no\ SCSI\ disks/) { my $mpt_id = get_mpt_id; unless( $mpt_id == "NA" ) { # single drive in this case, return status will be unkown but it doesn't matter open (MPT, "$mpt -n -i $mpt_id | ") or return "error: Could not open $mpt "; } } ## /TSS MPT-STATUS HACK if (m/ioc\:(\d+)\svol\_id\:(\d+).+raidlevel\:(\S+)\snum_disks\:(\d+)\ssize\((.+)\)\:(\d+)\sstate\:\s(\S+)\s.+/) { my $pd = $1; my $ld = $2; next if (defined($opt1) and ($opt1 ne $pd or $opt1 eq 'drives')); next if (defined($opt2) and $opt2 ne $ld); my $pd_count = $4; my $size = $6; my $unit = $5; my $state = $7; my $raidlevel = $3; if ( $unit eq 'MB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024) ); } if ( $unit eq 'GB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024) ); } if ( $unit eq 'TB' ) { $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024 * 1024) ); } if (defined($opt1)) { $result .= "$ld:$raidlevel:$pd_count drives:$size:$state; "; } else { $result .= "$pd:$ld:$raidlevel:$pd_count drives:$size:$state; "; } } elsif( m/phys_id/) { $pd_count++; } } close MPT; return $pd_count if (defined($opt1) and $opt1 eq 'drives'); return $result || 'Unknown'; } sub get_status_3ware($$) { my $opt1 = shift; my $opt2 = shift; my $result = ''; my $result_tmp; chomp($three_ware); (-e $three_ware) or return "error: $three_ware does not found"; open (ADPCOUNT, "$three_ware info | ") or return "error: Could not open '$three_ware info'"; while () { if ( m/^(c\d+)\s+\S+\s+\d+\s+(\d+).+\s+(\S+).*$/ ) { $result_tmp->{$1}{'bbu'} = $3; $result_tmp->{$1}{'bbu'} = 'none' if ($3 eq '-'); $result_tmp->{$1}{'pdcount'} = $2; } } close ADPCOUNT; if (defined($opt1) and $opt1 ne 'bbu' and $opt1 ne 'drives') { unless (defined($result_tmp->{$opt1})) { return "error: Device is not founded"; } } if ((defined($opt2) and $opt2 eq 'bbu') or (defined($opt1) and $opt1 eq 'bbu')) { unless (defined($opt2)) { foreach my $adp (sort keys %{$result_tmp}) { my $bbu_state = $result_tmp->{$adp}{'bbu'}; $result .= "$adp:$bbu_state "; } return $result || 'Unknown'; } else { return $result_tmp->{$opt1}{'bbu'} || 'Unknown'; } } if ((defined($opt2) and $opt2 eq 'drives') or (defined($opt1) and $opt1 eq 'drives')) { unless (defined($opt2)) { foreach my $adp (sort keys %{$result_tmp}) { my $pd_count = $result_tmp->{$adp}{'pdcount'}; $result .= "$adp:$pd_count "; } return $result || 'Unknown'; } else { return $result_tmp->{$opt1}{'pdcount'} || 'Unknown'; } } ADAPTER: foreach my $adp (sort keys %{$result_tmp}) { next if (defined($opt1) and $opt1 ne $adp); open (LDISKS, "$three_ware info $adp | ") or return "error: Could not open '$three_ware info $adp'"; while () { if (m/^(u\d+)\s+(\S+)\s+(\S+).+\s(\d+\.?\d+)\s.+/) { my $ld = $1; my $raidlevel = $2; my $state = $3; my $size = $4; $size = sprintf( "%.0f", ($size * 1024 * 1024 * 1024) ); next if (defined($opt2) and $opt2 ne $ld); $result_tmp->{$adp}{'logical'}->{$ld}{'raidlevel'} = $raidlevel; $result_tmp->{$adp}{'logical'}->{$ld}{'state'} = $state; $result_tmp->{$adp}{'logical'}->{$ld}{'size'} = $size; $result_tmp->{$adp}{'logical'}->{$1}{'ldcount'} = 0; } elsif (m/p\d+\s+(\S+)\s+(u\d+).+/) { my $ld = $2; my $pd_state = $1; next if (defined($opt2) and $opt2 ne $ld); ++$result_tmp->{$adp}{'logical'}->{$ld}{'ldcount'}; if ($pd_state ne 'OK') { $result_tmp->{$adp}{'logical'}->{$ld}{'state'} = $pd_state; } } } close LDISKS; } foreach my $adp (sort keys %{$result_tmp}) { foreach my $ld (sort keys %{$result_tmp->{$adp}{'logical'}}) { my $raidlevel = $result_tmp->{$adp}{'logical'}->{$ld}{'raidlevel'}; my $state = $result_tmp->{$adp}{'logical'}->{$ld}{'state'}; my $ldcount = $result_tmp->{$adp}{'logical'}->{$ld}{'ldcount'}; my $size = $result_tmp->{$adp}{'logical'}->{$ld}{'size'}; $result .= "$adp:$ld:$raidlevel:$ldcount drives:$size:$state; "; } } return $result || 'Unknown'; }