#!/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