#!/usr/bin/perl
use Data::Dumper qw(Dumper);
use Getopt::Long;
use warnings;
use strict;

my $alarms        = 0;
my $normal_output = "";
my $alarm_output  = "";

my $redundantPSU = "";
GetOptions  (
            'redundant-psu' => \$redundantPSU,       
            );

unless (-e "/dev/ipmi0" || -e "/dev/ipmi" || -d "/dev/ipmi") {
    my $modprobe_si  = `modprobe ipmi_si`;
    my $modprobe_dev = `modprobe ipmi_devintf`;
    unless (-e "/dev/ipmi0" || -e "/dev/ipmi" || -d "/dev/ipmi") {
        print "CRITICAL - Failed to load kernel modules\n";
        exit 2;
    }
}

my $retVal = eval {
    local $SIG{ALRM} = sub { die "sigalrm\n"; };
    alarm(30);

    my $system = `/usr/bin/ipmitool fru 2> /dev/null | egrep '(Product Serial|Product Name)'`;
    my @system_elements = split /[:|\n]/, $system;
    map { s/^\s//; s/\s+/ /g; s/\s$// } @system_elements;
    $system = "$system_elements[1] with serial $system_elements[3]";

    if ($system =~ m#PowerEdge#) { #dell
        my $psu_info = `ipmitool sdr type 'Power Supply'`;
        my @psu_info_lines = split /\n/, $psu_info;
        foreach my $line (@psu_info_lines) {
            my @psu_info_line_elements = split /[:|\n]/, $line;
            map { s/^\s//; s/\s+/ /g; s/\s$// } @psu_info_line_elements;
            my ($name, $something, $state, $something_other, $text_state) = @psu_info_line_elements;
            if ($state ne "ok" or $text_state =~ m#lost#i) {
                $alarms++;
                $alarm_output .= " PSU($name, $something, $state, $something_other, $text_state) ";
            }
        }
    }

    my $devices = `/usr/bin/ipmitool sdr list full 2> /dev/null`;
    foreach my $devices  (split /\n/, $devices) {
        my ($device, $reading, $status) = (split /\|/, $devices)[0, 1, 2];

        $device  =~ s/^\s+|\s+$//g;
        $reading =~ s/^\s+|\s+$//g;
        $status  =~ s/^\s+|\s+$//g;
 
        if ($status ne "ok" && $status ne "ns") {
            $alarm_output .= " $device";
            $alarms++;
        }

        # Collect power usage for performance data
        if ($device eq "Total Power" && $reading =~ /Watts/) {
            $normal_output .= "- $device $reading";
        }

        # Redundant PSU checking
        if ($redundantPSU) {
            if ( $device eq "PSU1 Power" ||
                 $device eq "PSU2 Power"
               ) {
                    if ($status ne "ok") {
                        $alarm_output .= " : $device missing";
                        $alarms++;
                    }
                }

            if ( $device eq "FAN1 PSU1" ||
                 $device eq "FAN2 PSU1" ||
                 $device eq "FAN1 PSU2" ||
                 $device eq "FAN2 PSU2"
               ) {
                    if ($status ne "ok") {
                        $alarm_output .= " : $device non spinning";
                        $alarms++;
                    }
                }

        }
    }

    if ($alarms == 0) {
        print "OK - $system $normal_output\n";
        exit 0;
    } else {
        print "CRITICAL - $system has failed components$alarm_output\n";
        exit 2;
    }

};

if ($@) {
    if ($@ =~ m#sigalrm#) {
        print "CRITICAL - plugin failed to collect IPMI data in a timely fashion\n";
        exit 2;
    } else {
        print "CRITICAL - some signal other than 'ARLM' stopped plugin execution: '$@'\n";
        exit 2;
    }
}
