#!/usr/bin/perl
use Getopt::Long;

# misc variables
my (@output, @checks, $file, %found, %requested);
my $megacli = '/usr/local/sbin/megacli';

# parameters
my @checks = @ARGV;

# check @checks and extract values
process_checks(@checks);

# check command works properly
check_command($megacli . ' -PDList -aALL');



# gather data
foreach (`$megacli -PDList -aALL`)
{
    # Adapter #0
    if ( /^\s*Adapter\s+#(\d+)\s*$/ ) { $c = $1; $e = -1; $s = -1; $state = ''; }

    # Enclosure Device ID: 32
    # Slot Number: 7
    # Firmware state: Hotspare
    # Media Type: Hard Disk Device
    if ( /^\s*Enclosure Device ID:\s+(\d+)\s*$/ ) { $e = $1; }
    if ( /^\s*Enclosure Device ID:\s+N\/A$/ ) { $e = 'na'; }
    if ( /^\s*Slot Number:\s+(\d+)\s*$/ ) { $s = $1; }
    if ( /^\s*Firmware state:\s+(.+)\s*$/  ) { $state = $1; }
    if ( /^\s*Media Type:\s+(Hard Disk|Solid State) Device\s*$/ && $e != -1 && $s != -1 ) { $found{$c}{'enclosures'}{$e}{'slots'}{$s} = $state; }
}

foreach (`$megacli -LDinfo -LAll -aAll`)
{
    # Adapter 0 -- Virtual Drive Information:
    if ( /^\s*Adapter\s+(\d+) --/ ) { $c = $1; $vd = -1; }

    # Virtual Disk: 0 (Target Id: 0)
    # State: Optimal
    if ( /^\s*Virtual Disk:\s+(\d+)\s+/ ) { $vd = $1; }
    if ( /^\s*State:\s+(.+)\s*$/ && $vd != -1 ) { $found{$c}{'vd'}{$vd} = $1; }
}



# check found against requested
foreach $c (keys(%found))
{
    foreach $vd (keys(%{$found{$c}{'vd'}}))
    {
        # check Virtual Disk has a valid status
        if ( $found{$c}{'vd'}{$vd} ne 'Optimal' ) { print STDERR 'Virtual Disk #' . $vd . ' is in status: ' . $found{$c}{'vd'}{$vd} . "\n"; failraid(); }
    }

    foreach $e (keys(%{$found{$c}{'enclosures'}}))
    {
        foreach $s (keys(%{$found{$c}{'enclosures'}{$e}{'slots'}}))
        {
            # check slot was requested
            if ( ! exists $requested{$c}{'enclosures'}{$e}{'slots'}{$s} )
            {
                print STDERR 'Controller #' . $c. ', Enclosure #' . $e . ', Slot #' . $s . ' exists but was not requested ( add \'c' . $c . ':e' . $e . ':s' . $s . '\' )' . "\n"; failraid(); 
            }

            # check slot has a valid state
            if ( $found{$c}{'enclosures'}{$e}{'slots'}{$s} !~ /(Online|Hotspare)/ )
            {
                print STDERR 'Controller #' . $c. ', Enclosure #' . $e . ', Slot #' . $s . ' has status ' . $found{$c}{'enclosures'}{$e}{'slots'}{$s} . "\n";
                failraid();
            }
        }
    }
}

# check requested against found
foreach $c (keys(%requested))
{
    foreach $e (keys(%{$requested{$c}{'enclosures'}}))
    {
        foreach $s (keys(%{$requested{$c}{'enclosures'}{$e}{'slots'}}))
        {
            if ( ! exists $found{$c}{'enclosures'}{$e}{'slots'}{$s} )
            {
                print STDERR 'Controller #' . $c. ', Enclosure #' . $e . ', Slot #' . $s . ' was requested but was not found ( delete \'c' . $c . ':e' . $e . ':s' . $s . '\' )' . "\n";
                failraid();
            }
        }
    }
}


# if we are here, all is ok
okraid();






sub check_command
{
    my ($cmd) = @_;

    # check if the command is valid
    if ( system($cmd . ' > /dev/null') != 0 )
    {
        print STDERR $cmd . ' has failed' . "\n";
        failraid();
    }
}


sub process_checks
{
    my $p;
    foreach (@_)
    {
        if ( /^c(\d+):e(na|\d+):s(\d+)$/ ) { $requested{$1}{'enclosures'}{$2}{'slots'}{$3} = 0; }
        else
        {
            print STDERR 'Invalid syntax for parameter (' . $_ . '), examples of valid values: "c0:e1:s1" "c1:e2:s7" "c0:e1:s4" "c0:ena:s0"' . "\n";
            failraid();
        }
    }
}


sub okraid
{
    print 'RAIDOK';
    exit(0);
}

sub failraid
{
    print 'FAIL';
    exit(0);
}
