#!/bin/ash
. /usr/local/bin/ipmi.env

DEBUG_LOG="/var/log/debug"
COMMAND=""
COMMAND_1=""
COMMAND_BANNER=""
POST_IPMI_COMMAND=""
WAIT_FOR_OUTPUT=""
CMD_OUTPUT=""
CMD_RESULT=""
VAR_1=0


#
# if this board is DS424-based, make sure we have enough power supplies to reboot
#
can_power_cycle()
{
local psu_count
local reboot_ok
local power_op

    power_op=${1}

    reboot_ok=0
    if [ "${op}" != "status" ] && [ -f /var/run/Vespa -o -f /var/run/Helix -o -f /var/run/Zuma ] && [ -f /var/run/DS424 ] ; then
        psu_count=$( ($IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU1_Present ; \
        $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU2_Present ; \
        $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU3_Present ; \
        $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU4_Present ) \
        | grep "\[Present\]" | wc -l ) 

        if [ ${psu_count} -lt 2 ] ; then
            echo "To perform a power ${power_op}, this chassis must have more than one power supply present"
            reboot_ok=1
        else
            psu_count=$( ($IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU1_Fault ; \
            $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU2_Fault ; \
            $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU3_Fault ; \
            $IPMITOOL -A NONE -H 127.0.0.1 sensor get PSU4_Fault ) \
            | grep "\[State Deasserted\]" | wc -l ) 
        
            if [ ${psu_count} -lt 2 ] && [ "${power_op}" != "off" ]; then
                echo "To perform a power ${power_op}, this chassis must have more than one power supply without a fault asserted"
                reboot_ok=1
            fi
        fi
    fi

    return ${reboot_ok}
}

ipmi_power_command()
# $1: power command
{

	case "$1" in
		on|cycle|status)
			echo "power ""$1" ;;
		off)
			# "/tmp/initiatedSystemPowerOff" is defined
			# as SEL_USER_INITIATED_SYSTEM_PWR_OFF_FILE 
			# in sel.h
			touch /tmp/initiatedSystemPowerOff
			echo "power ""$1" ;;
		diag)
			# "/tmp/initiatedSystemCore" is defined
			# as SEL_USER_INITIATED_SYSTEM_CORE_FILE 
			# in sel.h
			touch /tmp/initiatedSystemCore
			echo "power ""$1" ;;
		*) echo "" ;;	
	esac
}

ipmi_confirm_power_op()
{
local op
local confirm
local allow

    op="${1}"
    allow=1

    if [ -f /var/run/Vespa -o -f /var/run/Helix -o -f /var/run/Zuma ] && [ -f /var/run/DS424 ] ; then 
        case "${op}" in 
            on|cycle)
                if ! can_power_cycle "${op}" ; then
                    allow=0
                fi
            ;;
            off)
                if ! can_power_cycle "${op}" ; then
                    read -p "There are not enough power supplies in operation to restart the system, do you want to power off? Type YES to confirm "  confirm
                    if [ "${confirm}" != "YES" ] ; then 
                        echo "No action performed"
                        allow=0
                    fi
                fi
            ;;
        esac

        if [ "$allow" == "0" ] && [ -f /mnt/logs/var/RLM_debugmode ] ; then
            read -p "I see you're in debug mode, would you want to power ${op} in spite of the dire warnings? [y/n] " confirm
            if [ "${confirm}" == "y" ] ; then
                echo "OK, will do, but IPMI will still block the power ${op} operation"
                allow=1
            fi
        fi
     fi

    return ${allow}

}

check_sensor_monitor_status()
# $1: argument to monitor command
# $2: output from previous cmd
{
	#Check argument of "system sensor monitor" command
	if [ "$1" == "0" ]; then
		if [ $CMD_RESULT -eq 0 ]; then
			echo "echo -e WARNING: Disabling $OUTPUT_STR may lead to undesirable results.\nThe system $OUTPUT_STR has been disabled."
		else
			echo "echo Command executed with error $CMD_RESULT"
		fi
	elif [ "$1" == "1" ]; then
		if [ $CMD_RESULT -eq 0 ]; then
			echo "echo The system $OUTPUT_STR has been enabled."
		else
			echo "echo Command executed with error $CMD_RESULT"
		fi
	elif [ "$1" == "2" ]; then
		if [ $CMD_RESULT -eq 0 ]; then
			if [ "$2" == "00" ]; then 
				echo "echo The system $OUTPUT_STR is disabled."
			elif [ "$2" == "01" ]; then
				echo "echo The system $OUTPUT_STR is enabled."
			else 
				echo "echo Unexpected value $2."
			fi
		else
			echo "echo Command executed with error $CMD_RESULT"
		fi
	fi
}

check_sensor_monitor_status_default()
# $1: output from previous cmd
{
	if [ $CMD_RESULT -eq 0 ]; then
		if [ "$1" == "00" ]; then 
			echo "echo The system $OUTPUT_STR is disabled."
		elif [ "$1" == "01" ]; then
			echo "echo The system $OUTPUT_STR is enabled."
		else 
			echo "echo Unexpected value $1."
		fi
	else
		echo "echo Command executed with error $CMD_RESULT"
	fi
}

get_sensor_id()
# $1: sensor name
{
	$IPMITOOL_EXEC sensor get $1 | grep "Sensor ID" | cut -d'(' -f2 | cut -d')' -f1
}

sensors_set_fan_command()
# $1: sensor name
# $2: % duty cycle
{
	if [ "$2" -ge 0 ] && [ "$2" -le 100 ]; then 
		SENSOR_ID=`get_sensor_id $1`
		
		case "$1" in 
			Sysfan1_F1_Speed | \
			Sysfan1_F2_Speed | \
			Sysfan2_F1_Speed | \
			Sysfan2_F2_Speed | \
			Sysfan3_F1_Speed | \
			Sysfan3_F2_Speed | \
			IOfan1_F1_Speed | \
			IOfan1_F2_Speed | \
			IOfan2_F1_Speed | \
			IOfan2_F2_Speed | \
			IOfan3_F1_Speed | \
			IOfan3_F2_Speed) create_oem_ipmi_command 0x71 $SENSOR_ID $2 ;;
			*) echo "" ;;
		esac
	else
		echo ""
	fi
}

ipmi_sensors_command()
# $1: sub commands
{
	if [ $# == 0 ]  
	then
		echo "sensor"
	else 
		case "$1" in
			get) echo "sensor get $2" ;;
				# $2: sensor name
			set-thresh)
				 # If the threshold is a negative val
				if echo $4 | grep -Eq  '-' ; then
					# If the threshold is a negative value, use '--' delimiter
					# so that ipmitool does not treat the value as an option
					echo "sensor thresh $2 $3 -- $4"
				else
					echo "sensor thresh $2 $3 $4"
				fi
				;;
				# $2 sensor name; $3: threshold; $4: setting
				# we are using ipmitool.  So if an invalid argument 
				# is entered, the ipmitool usage is displayed.
				# We can not use ch, wh, wl, cl for thresholds
				# as ipmitool will reject these.  Invalid sensor 
				# name is returned as not found.  No checking on 
				# setting.  This is a diag command.  So you need to 
				# know what you are doing.
			set-fan) 
				sensors_set_fan_command $2 $3
				;;

			monitor|thermal) 
				if [ "$1" == "monitor" ];
				then
					OEM_CMD=0x72
				else
					OEM_CMD=0x70
				fi

				if [ $# == 1 ]
				then
					# Request current status
					create_oem_ipmi_command $OEM_CMD 0x02
				elif [ $# == 2 ]
				then
					case "$2" in
						0|1|2)
							# $2: 0: disable; 1: enable ; 2: current status
							create_oem_ipmi_command $OEM_CMD $2
							;;
						*) echo "" ;;	
					esac
				fi
				;;
			*) echo "" ;;
		esac		
	fi
}

ipmi_reset_command()
# $1: reset type
{
	if [ $# == 0 ]
	then
		echo "chassis power reset" 
		return	
	fi
	case "$1" in
		prim) create_oem_ipmi_command 0x04 0x00 ;;
		back) create_oem_ipmi_command 0x04 0x01 ;;
		curr) echo "chassis power reset" ;;
		status) create_oem_ipmi_command 0x06 ;; # Need some work here
		*) echo "" ;;
	esac
}

ipmi_self_test()
{
	create_ipmi_raw_command 0x06 0x04
}

ipmi_i2c_read_write()
{
	create_ipmi_i2c_command $*
}

#
# Main Loop
#
case "$1" in
	power) 
		if [ $# == 3 ] && [ "$3" != "-f" ]; then
		        echo "Invalid option: $3"
		        echo "Usage: system $1 $2 [-f]'"
		        exit 1
		fi

        if ipmi_confirm_power_op "${2}"; then
            exit 1
        fi

		bbsp_code=`cat /sys/class/hwmon/bbsp`
        	if [ \( "$3" != "-f" \) -a \( "$bbsp_code" == "21" -o "$bbsp_code" == "22" \) ]; then
			echo "Command disabled while BIOS is updating"
			exit 1
		else
			if [ \( "$2" == "diag" \)  -a \( "$bbsp_code" != "2f" \) -a  \( "$3" != "-f" \) ]; then
			echo "Command disabled while ONTAP is not running"
			exit 1
			fi
			COMMAND=`ipmi_power_command $2` 
			if [ $2 != "status" ]
			then
				POST_IPMI_COMMAND_0=" "
				VAR_1=1
			else
				POST_IPMI_COMMAND_0="sed s/Chassis/Host/g"
			fi
		fi
		;;
	sensors) 
		COMMAND=`ipmi_sensors_command $2 $3 $4 $5`
		if [ $# == 1 ]
		then
			COMMAND_BANNER_0="Sensor Name      | Current    | Unit       | Status     | LCR       | LNC       | UNC       | UCR"
			COMMAND_BANNER_1="-----------------+------------+------------+------------+-----------+-----------+-----------+-----------"
			POST_IPMI_COMMAND_0="cut -s -d| -f1-4,6-9"
		else
			case "$2" in
				monitor|thermal)
					WAIT_FOR_OUTPUT="1"
					#Note that we have post IPMI command to run
					POST_IPMI_COMMAND_0=" "

					if [ $2 == monitor ]; then
						OUTPUT_STR="sensors monitoring"
					else
						OUTPUT_STR="thermal management"
					fi
					;;
				*)
					POST_IPMI_COMMAND_0=""
					;;
			esac
		fi
		;;
	reset) 
		if [ $# == 3 ] && [ "$3" != "-f" ]; then
		        echo "Invalid option - $3"
		        echo "Usage: system $1 $2 [-f]'"
		        exit 1
		fi

		bbsp_code=`cat /sys/class/hwmon/bbsp`
        	if [ \( "$3" != "-f" \) -a \( "$bbsp_code" == "21" -o "$bbsp_code" == "22" \) ]; then
			echo "Command disabled while BIOS is updating"
			exit 1
		else
			COMMAND=`ipmi_reset_command $2` 
			if [ $2 != "status" ]
			then
				POST_IPMI_COMMAND_0=" "
				VAR_1=1
			fi
		fi
		;;
	selftest) 
		COMMAND=`ipmi_self_test` 
		COMMAND_1="/usr/local/bin/decode_selftest.sh"
		;;

	i2c) 
		COMMAND=`ipmi_i2c_read_write $*` 
		;;
	oem)
		shift
		$OEM_IPMI_EXEC $*
		exit 0
		;;
	sim)
		if [ "$2" == "start" ]; then
			touch /tmp/sim_sensors_start
			echo "Sensor simulation starting, check /tmp/sim_sensors_log.txt to ensure simulation started correctly"
		elif [ "$2" == "stop" ]; then
			rm /tmp/sim_sensors_start
			echo "Sensor simulation stopped"
		else
			echo "Please enter option start or stop"
		fi
		exit 0
		;;
	*) 
		echo "unknown command"
		;;
esac

if [ "$COMMAND" == "" ]
then
	echo "invalid argument" 
	exit 1
fi

# Print banner for the output
if [ "$COMMAND_BANNER_0" != "" ] 
then
	echo "$COMMAND_BANNER_0"
fi

if [ "$COMMAND_BANNER_1" != "" ] 
then
	echo "$COMMAND_BANNER_1"
fi

#Now execute the command
if [ "$POST_IPMI_COMMAND_0" != "" ]
then 
	if [ VAR_1 == 1 ]
	then
		POST_IPMI_COMMAND_0=`echo > /dev/null`
	fi
	if [ "$POST_IPMI_COMMAND_1" != "" ]
	then
		$IPMITOOL_EXEC $COMMAND | $POST_IPMI_COMMAND_0 | $POST_IPMI_COMMAND_1
	else
		#sensors and sensors monitor cmds
		if [ "$WAIT_FOR_OUTPUT" != "" ]; then
			CMD_OUTPUT=`$IPMITOOL_EXEC $COMMAND` 
			CMD_RESULT=$?
			if [ "$3" != "" ]; then
				POST_IPMI_COMMAND_0=`check_sensor_monitor_status $3 $CMD_OUTPUT`
			else
				POST_IPMI_COMMAND_0=`check_sensor_monitor_status_default $CMD_OUTPUT`
			fi
			$POST_IPMI_COMMAND_0
		else
			$IPMITOOL_EXEC $COMMAND | $POST_IPMI_COMMAND_0
		fi
	fi
else
	if [ "$COMMAND_1" == "" ]
	then
		$IPMITOOL_EXEC $COMMAND
	else
		VAR=`$IPMITOOL_EXEC $COMMAND`
		$COMMAND_1 $VAR
	fi
fi                 
