#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html

# This script is used by UpdatexCATNodeStatus event response to handle the node
# status changes from the condition NodeReachability and NodeReachability_H

BEGIN
{
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
}

use strict;
use Getopt::Std;
use POSIX qw(strftime);

my $respname  = $ENV{ERRM_ER_NAME};
my $cond_name = $ENV{ERRM_COND_NAME};
my $batch     = 0;
if (exists($ENV{ERRM_COND_BATCH})) { $batch = $ENV{ERRM_COND_BATCH}; }
my $currtime;

if (!$batch) {
    my $node;
    my $status;
    if ($cond_name eq "NodeReachability") {
        $node   = $ENV{ERRM_RSRC_NAME};
        $status = $ENV{ERRM_VALUE};
    } elsif ($cond_name eq "NodeReachability_H") {

        # Parse the ERRM_VALUE attribute, which will contain the
        # LastEvent structured data variable from the Condition class
        # The fields in this structured data variable are documented below where we parse them out.
        my $event = $ENV{ERRM_VALUE};
        $event =~ s/^\[(.*)\]$/$1/; # SD variables have square brackets around them

        # This parse the LastEvent
        my (                        # split the SD into the following fields:
            $Occurred,              # One if the condition has been triggered
            $ErrNum,  # Non-zero if there was in error in the event registration
            $ErrMsg,  # The string msg related to ErrNum
            $EventFlags,  # Bit mask giving some additional info about the event
            $EventTime,   # Time of event expressed in seconds since 1/1/1970
            $EventTimeMicros,    # Number of microseconds past EventTime
            $ResourceHandle, # Binary address of the RMC resource that caused the condition to be triggered
            $NodeName, # The node on which the event occurred.  For conditions that use the management domain scope (4),
                       # this will be the leaf node.  For conditions that use the local scope (e.g. NodeReachability),
                       # this will be the FMS.
            $NumAttrs, # Number of attr values from the resource returned in this event
            $NumAttrsInExpr, # How many of the above were attributes in the event expression
            $IndexForAttrs, # The starting index of the array of values.  Until new fixed fields are added
                            # to LastEvent, this will be the element right after this one.
            $AttrArray      # This list of attribute names, types, and values
        ) = split(/,/, $event, 12);

        my @attrArray = split(/,/, $AttrArray); # Note: parsing this way does not support SDs or SD Arrays that may be in this list

        my $j = 0;                              # index into attrArray
        for (my $i = 0 ; $i < $NumAttrs ; $i++) {
            my $attrName = $attrArray[ $j++ ];
            my $attrType = $attrArray[ $j++ ]; # Types <= 8 are "simple" types. Types > 8 are SDs and arrays.
            my $attrValue = $attrArray[ $j++ ];
            if ($attrName eq '"Name"')   { $node   = $attrValue; }
            if ($attrName eq '"Status"') { $status = $attrValue; }
        }
    } else {
`logger -t xcat -p local4.err  "[mon]: updatexcatnodestatus: This script does not handle condition $cond_name"`;
        exit 1;
    }
    my $status_string;
    if   ($status == 1) { $status_string = "alive"; }
    else                { $status_string = "unreachable"; }

    if (!$currtime) {
        my (
            $sec, $min, $hour, $mday, $mon,
            $year, $wday, $yday, $isdst
          )
          = localtime(time);
        $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
            $mon + 1, $mday, $year + 1900,
            $hour, $min, $sec);
    }
    my $result = `$::XCATROOT/sbin/chtab node=$node nodelist.status=$status_string nodelist.statustime="$currtime" 2>&1`;
    my $code = $?;
    if ($code) {
`logger -t xcat -p local4.err "[mon]: Error saving node status ($node,$status_string) to xCAT:$result"`;
        exit $code;
    }
} else {    #batch event
    if ($cond_name ne "NodeReachability_Batch") {
`logger -t xcat -p local4.err  "[mon]: updatexcatnodestatus: This script does not handle condition $cond_name"`;
        exit 1;
    }
    if ($ENV{ERRM_COND_BATCH_NUM} > 0) {

        #check if event detail file exist
        if (!exists($ENV{ERRM_EVENT_DETAIL_FILE})) {
            xCAT::MsgUtils->message('S', "logeventtoxcat: no event detail file specified in the response $respname for condition $cond_name.\n");
            exit(1);
        }

        my $filename = $ENV{ERRM_EVENT_DETAIL_FILE};
        if (!-f $filename) {
            xCAT::MsgUtils->message('S', "logeventtoxcat: cannot find event detail file $filename in response $respname for condition $cond_name.\n");
            exit(1);
        }

        open(FILE1, "<$filename");
        readline(FILE1);    #skip first 2 lines
        readline(FILE1);
        my $line1      = readline(FILE1);
        my @aTemp      = split(/=/, $line1);
        my $num_events = $aTemp[1];
        close(FILE1);

        my $count;
        my @active    = ();
        my @inactive  = ();
        my %new_value = ();
        for ($count = 1 ; $count <= $num_events ; $count++) {
            my $content = `sed -n "/Event $count:/,/ERRM_COND_BATCH/ p" $filename`;

            my @content_array = split(/\n/, $content);
            pop(@content_array);      #get rid of last line
            shift(@content_array);    #get rid of firt line

            my %content_hash = ();
            foreach (@content_array) {
                /([^\=]+)\=(.*)/;
                $content_hash{$1} = $2;
            }

            my $node;
            my $status;
            my $status_string;
            $node   = $content_hash{ERRM_RSRC_NAME};
            $status = $content_hash{ERRM_VALUE};

            if   ($status == 1) { $new_value{$node} = 1; }
            else                { $new_value{$node} = 0; }
        }    #end for
        foreach my $node (keys %new_value) {
            if   ($new_value{$node} == 1) { push(@active,   $node); }
            else                          { push(@inactive, $node); }
        }    #end foreach

        if (@active > 0) {
            if (!$currtime) {
                my (
                    $sec, $min, $hour, $mday, $mon,
                    $year, $wday, $yday, $isdst
                  )
                  = localtime(time);
                $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
                    $mon + 1, $mday, $year + 1900,
                    $hour, $min, $sec);
            }
            my $node_string = join(',', @active);
            my $result = `XCATBYPASS=Y $::XCATROOT/bin/nodech $node_string nodelist.status=active nodelist.statustime="$currtime" 2>&1`;
            my $code = $?;
            if ($code) {
`logger -t xcat -p local4.warning "[mon]: Error saving node status ($node_string,active) to xCAT:$result"`;
            }
        }
        if (@inactive > 0) {
            if (!$currtime) {
                my (
                    $sec, $min, $hour, $mday, $mon,
                    $year, $wday, $yday, $isdst
                  )
                  = localtime(time);
                $currtime = sprintf("%02d-%02d-%04d %02d:%02d:%02d",
                    $mon + 1, $mday, $year + 1900,
                    $hour, $min, $sec);
            }
            my $node_string = join(',', @inactive);
            my $result = `XCATBYPASS=Y $::XCATROOT/bin/nodech $node_string nodelist.status=inactive nodelist.statustime="$currtime" 2>&1`;

            my $code = $?;
            if ($code) {
`logger -t xcat -p local4.warning  "[mon]: Error saving node status ($node_string,inactive) to xCAT:$result"`;
            }
        }
    }
}
exit 0


