#!/usr/bin/bash
# Copyright (c) 2016 NEC Corporation.
# All rights reserved.
#
# Description:
# wrapper scipt to execute VE program, it is also responsible to converts the
# ve node number to special file path and socket file path, and executes the
# actual ve_exec binary without creating a child process.
# Below are the command line options for wrapper script.

# 1. "-N node" and "--node=<node>" optional argument with default value is "0"
# 2. "-c core" and "--core=<core>" optional argument with value of core on which
#    VE task is to be executed.
#    Note:
#    If “-c” option is not specified, or "-1" is provided by user then VEOS chooses
#    the appropriate core to run the VE task and by default all CPU’s of that node
#    is allowed for that VE process.
# 3. "-V" and "--version" optional argument to display binary version info.
# 4. "-h" and "--help" optional argument to display the help information of
#	wrapper.
# 5. "--traceme" for internal use only
# 6. "--cpunodebind" optional argument specify NUMA node ID on which VE program
#        to be executed.
# 7. "--localmembind" optional argument set memory policy to MPOL_BIND.


#update PATH_VE_EXEC with the path of ve_exec of your system.

PATH_VE_EXEC="/opt/nec/ve/libexec/ve_exec"

export VE_EXEC_PATH=$PATH_VE_EXEC

if [ -z "$VE_LD_ORIGIN_PATH" ]
then
	export VE_LD_ORIGIN_PATH=`pwd`
fi

if [[(! -v VE3_LD_LIBRARY_EXCLUDE_PATH)]]; then
	export VE3_LD_LIBRARY_EXCLUDE_PATH="/opt/nec/ve/lib"
else
	flag=`echo $VE3_LD_LIBRARY_EXCLUDE_PATH|awk '{print match($0,"/opt/nec/ve/lib")}'`;
	if [ $flag -le 0 ];then
		export VE3_LD_LIBRARY_EXCLUDE_PATH="/opt/nec/ve/lib:$VE3_LD_LIBRARY_EXCLUDE_PATH"
	fi
fi

flag_traceme=0

VE_NODE=0
VE_CORE=-1
ve_core_given=0
NUMA_NODE_ID=-1
flag_membind=0
node_given=0
numa_node_id_given=0
flag_show_limit=0
flag_show_usage=0
regex='^[0-9]+$';

ld_show_aux_flag=0
if [ -n "$LD_SHOW_AUXV" ]; then
ld_show_aux_flag=1
unset LD_SHOW_AUXV
fi

#declare and initialize variables for VE_LIMIT_OPT parsing
declare -A resource_limit_option=(
		[c]="core file size          (blocks, -c)"
		[d]="data seg size           (kbytes, -d)"
		[i]="pending signals                 (-i)"
		[m]="max memory size         (kbytes, -m)"
		[s]="stack size              (kbytes, -s)"
		[t]="cpu time               (seconds, -t)"
		[v]="virtual memory          (kbytes, -v)"
		)
declare -A resource_limit_values=() ;
declare -A resource_limit_valid_arg=() ;
for option in "${!resource_limit_option[@]}";
do
	let hard$option=-1 ;
	let soft$option=-1 ;
	resource_limit_valid_arg[hard$option]=1 ;
	resource_limit_valid_arg[soft$option]=1 ;
	resource_limit_values[hard$option]=$(ulimit "-H$option") ;
	resource_limit_values[soft$option]=$(ulimit "-S$option") ;
done;

if [ ! -x "$PATH_VE_EXEC" ] ; then
	echo "ERROR: acutal ve_exec is not found in path: ${PATH_VE_EXEC}"
	exit 1
fi

normal_help_message() {
echo "Usage: ${0} [options] binary [arguments]
Options:
  -V, --version                 output version information and exit
  -h, --help                    display this help and exit
  -N node, --node=<node>        where node is the VE Node number
                                on which VE program belongs
  -c core, --core=<core>        where core is the VE core number on
                                which VE program to be executed
  --show-limit                  display the applicable soft and hard
                                resource limits of VE process supported by
                                VE_LIMIT_OPT environment variable
  --                            end of options (requires if binary name
                                starts with ‘-’)
ENVIRONMENT VARIABLE
  VE_NODE_NUMBER                provide the VE node number
  If -N option is specified, this environment variable is ignored.
  VE_ATOMIC_IO                  value 1 enables atomic I/O
  VE_ACC_IO                     value 1 enables accelerated I/O"
}

partitioning_help_message() {
echo "Usage: ${0} [options] binary [arguments]
Options:
  -V, --version                 output version information and exit
  -h, --help                    display this help and exit
  -N node, --node=<node>        where node is the VE Node number
                                on which VE program belongs
  -c core, --core=<core>        where core is the VE core number on
                                which VE program to be executed
                                Can't specify both '-c' and '--cpunodebind'
  --cpunodebind=<NUMA node ID>  specify NUMA node ID on which VE program
                                to be executed
  --localmembind                memory policy is set to MPOL_BIND
  --show-limit                  display the applicable soft and hard
                                resource limits of VE process supported by
                                VE_LIMIT_OPT environment variable
  --                            end of options (requires if binary name
                                starts with ‘-’)
ENVIRONMENT VARIABLE
  VE_NODE_NUMBER                provide the VE node number
  If -N option is specified, this environment variable is ignored.
  VE_NUMA_OPT                   provide NUMA node ID and memory policy
  If NUMA node ID or memory policy are specified as command line argument,
  then the values passed in this environment variable will be ignored.
  VE_ATOMIC_IO                  value 1 enables atomic I/O
  VE_ACC_IO                     value 1 enables accelerated I/O"
}

ve_limit_opt_usage()
{
	if [[ $flag_show_usage != 1 ]]; then
		printf "Error: invalid input in VE_LIMIT_OPT $1\n" "$2"
		if [[ $flag_show_limit == 0 ]]; then
			exit 1
		fi
		flag_show_usage=1
	fi
}
function check_limit_overflow()
{
max_val1=18014398509481983    #maximum allowed value for resources (-c, -d, -v, -s and -m).
max_val2=18446744073709551615 #maximum allowed value for resources (-i, -t).
input=$2;
limit_opt=$1
input=$(printf "%u" $(($input)))
resource_limit_values[$limit_opt]=$input
if [[ "$limit_opt" != "hardi" && "$limit_opt" != "softi"
	&& "$limit_opt" != "hardt" && "$limit_opt" != "softt" ]]; then
	if [[ $input -gt $max_val1 ]]; then
		error_string="(error: limit out of range)"
	fi
else
	if [[ ${resource_limit_values[$limit_opt]} == $max_val2 ]]; then
		resource_limit_values[$limit_opt]="unlimited";
	elif [[ "$limit_opt" == "hardt" || "$limit_opt" == "softt" ]]; then
		if [[ ${resource_limit_values[$limit_opt]} == 0 ]]; then
			resource_limit_values[$limit_opt]=1;
		fi
	fi
fi
}
ve_limit_validate_display()
{
for option in "${!resource_limit_option[@]}";
do
	error_string=""
	optarg_hard=${resource_limit_values[hard$option]}
	optarg_soft=${resource_limit_values[soft$option]}
	if [[ $flag_show_limit == 1 ]]; then
		if [[ ${optarg_soft} =~ $regex ]]; then
			check_limit_overflow "soft$option"  $optarg_soft
		fi
		if [[ ${optarg_hard} =~ $regex ]]; then
			check_limit_overflow "hard$option"  $optarg_hard
		fi
		if [[ ${optarg_soft} =~ $regex
			&& ${optarg_hard} =~ $regex
			&& ${resource_limit_values[soft$option]} -gt ${resource_limit_values[hard$option]} ]]; then
				error_string="(error: invalid limits)"
		elif [[ ${optarg_soft} ==  "unlimited"
			&& ${optarg_hard} != "unlimited" ]]; then
				error_string="(error: invalid limits)"
		fi
	fi
	if [[ ! ${optarg_hard} =~ $regex && "$optarg_hard" != "unlimited" ]]; then
		resource_limit_valid_arg[hard$option]=0
		error_string="($optarg_hard: invalid number)"
	fi
	if [[ ! ${optarg_soft} =~ $regex && "$optarg_soft" != "unlimited" ]]; then
		resource_limit_valid_arg[soft$option]=0
		error_string="($optarg_soft: invalid number)"
	fi
	if [[ $flag_show_limit == 1 ]]; then
		:
		printf "%s " "${resource_limit_option[$option]}"
		printf "%-20s %-20s %s\n" "${resource_limit_values[soft$option]}" "${resource_limit_values[hard$option]}" "$error_string"
	elif [[ ${resource_limit_valid_arg[hard$option]} != 1
		|| ${resource_limit_valid_arg[soft$option]} != 1
		|| $error_string != "" ]]; then
			ve_limit_opt_usage
			exit 1
	fi
done
}

ve_limit_opt_parse()
{
#check if VE_STACK_LIMIT environment variable is defined and give it precedence
#over 'ulimit' value of resource limits
if [ ! -z "$VE_STACK_LIMIT" ]; then
	if [[ ${VE_STACK_LIMIT} =~ $regex || $VE_STACK_LIMIT == "unlimited" ]]; then
		resource_limit_values[softs]=$VE_STACK_LIMIT ;
		resource_limit_values[hards]=$VE_STACK_LIMIT ;
	fi
fi

#make VE_LIMIT_OPT environment variable input parsable by getopt
VE_LIMIT_OPT=$(echo $VE_LIMIT_OPT)
TEMP_VE_LIMIT_OPT=$VE_LIMIT_OPT
IFS=" " read  -a ve_limit_opt <<< "$VE_LIMIT_OPT"

SHORT_OPTS="m:s:d:c:v:i:t:"
LONG_OPTS="hardm:,softm:,hards:,softs:,hardd:,softd:,hardv:,softv:,hardc:,softc:,hardi:,softi:,hardt:,softt:,"
TEMP=`getopt -q --options $SHORT_OPTS --longoptions $LONG_OPTS -- "${ve_limit_opt[@]}"`
if [ $? -ne 0 ]; then
	ve_limit_opt_usage;
fi
TEMP="${TEMP:1}"
eval set -- "$TEMP"
unset TEMP

short_option_array=$(echo $SHORT_OPTS | sed "s/:/ /g");
long_option_array=$(echo $LONG_OPTS | sed "s/:,/ /g");
long_option_array=$(echo $long_option_array | sed 's/[^ ]* */-&/g');
# extract options and their arguments into variables
while true ; do

	# Check if the options and arguments are space separated or not
	for i in $(echo "$short_option_array $long_option_array")
	do
		if [[ "$1" == "-$i" ]]; then
			if [[ ! "$TEMP_VE_LIMIT_OPT" =~ "$1 $2" ]]; then
				ve_limit_opt_usage
				flag_missing_space=1
				break
			fi
		fi
	done
	if [[ "$flag_missing_space" == 1 ]]; then
		shift 2
		flag_missing_space=0
		continue
	fi

	case "$1" in
		-c)	case "$2" in
				*) if [[ $hardc == -1 ]]; then
					hardc=$2 ;
					resource_limit_values[hardc]=$2 ;
				   fi
				   if [[ $softc == -1 ]]; then
					softc=$2 ;
					resource_limit_values[softc]=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardc)case "$2" in
				*) if [[ $hardc == -1 ]]; then
					hardc=$2 ;
					resource_limit_values[hardc]=$2 ;
				   fi
			esac
			shift 2 ;;
		--softc)case "$2" in
				*) if [[ $softc == -1 ]]; then
					softc=$2;
					resource_limit_values[softc]=$2 ;
				   fi
			esac
			shift 2 ;;
		-d)	case "$2" in
				*)if [[ $hardd == -1 ]]; then
					resource_limit_values[hardd]=$2 ;
					hardd=$2 ;
				   fi
				   if [[ $softd == -1 ]]; then
					resource_limit_values[softd]=$2 ;
					softd=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardd)case "$2" in
				*) if [[ $hardd == -1 ]]; then
					resource_limit_values[hardd]=$2 ;
					hardd=$2 ;
				   fi
			esac
			shift 2 ;;
		--softd)case "$2" in
				*) if [[ $softd == -1 ]]; then
					resource_limit_values[softd]=$2 ;
					softd=$2 ;
				   fi
			esac
			shift 2 ;;
		-i)	case "$2" in
				*) if [[ $hardi == -1 ]]; then
					resource_limit_values[hardi]=$2 ;
					hardi=$2 ;
				   fi
				   if [[ $softi == -1 ]]; then
					resource_limit_values[softi]=$2 ;
					softi=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardi)case "$2" in
				*) if [[ $hardi == -1 ]]; then
					hardi=$2 ;
					resource_limit_values[hardi]=$2 ;
				fi
			esac
			shift 2 ;;
		--softi)case "$2" in
				*) if [[ $softi == -1 ]]; then
					softi=$2 ;
					resource_limit_values[softi]=$2 ;
				    fi
			esac
			shift 2 ;;
		-m)	case "$2" in
				*) if [[ $hardm == -1 ]]; then
					hardm=$2 ;
					resource_limit_values[hardm]=$2 ;
				   fi
				   if [[ $softm == -1 ]]; then
					resource_limit_values[softm]=$2 ;
					softm=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardm)case "$2" in
				*) if [[ $hardm == -1 ]]; then
					resource_limit_values[hardm]=$2 ;
					hardm=$2 ;
				   fi
			esac
			shift 2 ;;
		--softm)case "$2" in
				*) if [[ $softm == -1 ]]; then
					resource_limit_values[softm]=$2 ;
					softm=$2 ;
				   fi
			esac
			shift 2 ;;
		-s)	case "$2" in
				*) if [[ $hards == -1 ]]; then
					hards=$2 ;
					resource_limit_values[hards]=$2 ;
				   fi
				   if [[ $softs == -1 ]]; then
					resource_limit_values[softs]=$2 ;
					softs=$2 ;
				   fi
			esac
			shift 2 ;;
		--hards)case "$2" in
				*) if [[ $hards == -1 ]]; then
					hards=$2 ;
					resource_limit_values[hards]=$2 ;
				   fi
			esac
			shift 2 ;;
		--softs)case "$2" in
				*) if [[ $softs == -1 ]]; then
					resource_limit_values[softs]=$2 ;
					softs=$2 ;
				   fi
			esac
			shift 2 ;;
		-t)	case "$2" in
				*) if [[ $hardt == -1 ]]; then
					resource_limit_values[hardt]=$2 ;
					hardt=$2 ;
				   fi
				   if [[ $softt == -1 ]]; then
					resource_limit_values[softt]=$2 ;
					softt=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardt)case "$2" in
				*) if [[ $hardt == -1 ]]; then
					resource_limit_values[hardt]=$2 ;
					hardt=$2 ;
				   fi
			esac
			shift 2 ;;
		--softt)case "$2" in
				*) if [[ $softt == -1 ]]; then
					resource_limit_values[softt]=$2 ;
					softt=$2 ;
				   fi
			esac
			shift 2 ;;
		-v)	case "$2" in
				 *) if [[ $softv == -1 ]]; then
					resource_limit_values[softv]=$2 ;
					softv=$2 ;
				   fi
				 if [[ $hardv == -1 ]]; then
					resource_limit_values[hardv]=$2 ;
					hardv=$2 ;
				   fi
			esac
			shift 2 ;;
		--hardv)case "$2" in
				*) if [[ $hardv == -1 ]]; then
					resource_limit_values[hardv]=$2 ;
					hardv=$2 ;
				   fi
			esac
			shift 2 ;;
		--softv)
			case "$2" in
				*) if [[ $softv == -1 ]]; then
					resource_limit_values[softv]=$2 ;
					softv=$2 ;
				   fi
			esac
			shift 2 ;;
		--)	if [[ "$2" != "" ]]; then
				ve_limit_opt_usage;
			fi
			shift ;
			break ;;
		-*)	shift ;
			ve_limit_opt_usage;
			break ;;
		*)	ve_limit_opt_usage;
			break ;;
	esac
done

ve_limit_validate_display
}

#to display wrapper script usage
usage() {
        if [[ ${node_given} -eq 0 && -n ${VE_NODE_NUMBER} ]]; then
                VE_NODE=${VE_NODE_NUMBER};
        fi

        sysfs_path=/sys`/usr/bin/udevadm info -q path \
				/dev/veslot$VE_NODE 2> /dev/null`
        retval=$?
        if [ $retval -ne 0 ]; then
                normal_help_message;
                return;
        fi

        ve_mode=`cat $sysfs_path/partitioning_mode`
        if [ $ve_mode -ne 0 ]; then
                partitioning_help_message;
        else
                normal_help_message;
        fi
}

if [ "$#" -lt 1 ]; then
	echo "ERROR: VE binary is not provided"
	usage;
	exit 1
fi

#read the options
TEMP=`getopt -o "+VhN:c:" \
	--long version,help,traceme,localmembind,node:,core:,cpunodebind:,show-limit \
	-- "$@"`
retval=$?
if [ $retval -ne 0 ]; then
	usage;
	exit 1;
fi

eval set -- "$TEMP"
unset TEMP
# extract options and their arguments into variables
while true ; do
	case "$1" in
		-V|--version)
			echo "ve_exec (veos) 3.7.0";
			exit;;
		-h|--help)
			usage;
			exit;;
		-N|--node)
			case "$2" in
				"") shift 2 ;;
				*) VE_NODE=$2 ;
				node_given=1;
				shift 2 ;
			esac ;;
		-c|--core)
			case "$2" in
				"") shift 2 ;;
				*) VE_CORE=$2;
				ve_core_given=1;
				shift 2 ;
			esac ;;
	    --cpunodebind)
			case "$2" in
				"") shift 2 ;;
				*) NUMA_NODE_ID=$2;
				numa_node_id_given=1;
				shift 2 ;
			esac ;;
	    --localmembind)
			flag_membind=1;
			shift ;;
		 --traceme)
			flag_traceme=1;
			shift;;
	      --show-limit)
			flag_show_limit=1;
			ve_limit_opt_parse
			if [[ $flag_show_usage == 1 ]]; then
				exit 1 ;
			else
				exit 0 ;
			fi ;;
		--)
			shift ;
			break ;;
		-*)
			shift ;
			usage;
			exit 1
			break ;;
		*)
			usage;
			exit 1 ;;
	esac
done

if [[ ${node_given} -eq 0 && -n ${VE_NODE_NUMBER} ]]; then
	VE_NODE=${VE_NODE_NUMBER};
fi

#parsing VE_NUMA_OPT environment variable and checking combination
#for VE_NUMA_OPT
if [[ ${numa_node_id_given} -eq 0 || ${flag_membind} -eq 0
	&& -n $VE_NUMA_OPT ]]; then
	for num_opt_var in $(echo $VE_NUMA_OPT | sed "s/' '//g")
	do
		if [[ $num_opt_var == "--localmembind" ]]
		then
			flag_membind=1;
		elif [[ $num_opt_var =~ '--cpunodebind=' ]]
		then
			if [[ ${numa_node_id_given} -eq 0 ]]; then
				NUMA_NODE_ID=$(echo $num_opt_var |\
						 sed 's/--cpunodebind=//g')
				numa_node_id_given=1;
			fi
		else
			echo "ERROR: Invalid argument passed to VE_NUMA_OPT"
			exit 1;
		fi
	done
fi

if [[ ${numa_node_id_given} -eq 1 && ${ve_core_given} -eq 1 ]]; then
        echo "ERROR: 'Core id' and 'NUMA node ID' cannot be passed together"
        exit 1;
fi


if ! [[ ${VE_NODE} =~ $regex ]] ; then
	echo "ERROR: '$VE_NODE' is not a valid node number"
	exit 1;
fi

if [[ -v _VENODELIST ]]; then
	# The scheduler sets ve node number to _VENODELIST.  We check
	# the VE node to execute the program is assigned by the
	# scheduler. If it is not assigned, we don't execute the
	# program.  If _VENODELIST is an empty value, we don't execute
	# the program.
	FOUND=0
	for n in ${_VENODELIST}; do
		if [[ ${VE_NODE} == $n ]]; then
			FOUND=1
			break;
		fi
	done
	if [[ ${FOUND} -eq 0 ]]; then
		echo "ERROR: VE node #${VE_NODE} is not assigned by the scheduler"
		exit 1
	fi
fi

if  [[ ${VE_CORE} == -1 ]] ; then
        :
elif ! [[ ${VE_CORE} =~ $regex ]] ; then
        echo "ERROR: '$VE_CORE' is not a valid core number"
        exit 1;

fi

if  [[ ${NUMA_NODE_ID} == -1 ]] ; then
        :
elif ! [[ ${NUMA_NODE_ID} =~ $regex ]] ; then
	echo "ERROR: '$NUMA_NODE_ID' is not a valid numa node id"
	exit 1;
fi

if [[ -v VE_CORE_LIMIT ]] ; then
	core_limit=()
	IFS=', ' read -a ranges <<< "$VE_CORE_LIMIT"
	for range in "${ranges[@]}"; do
		IFS=- read start end <<< "$range"
		[ -z "$start" ] && continue
		[ -z "$end" ] && end=$start
		if ! [[ $start =~ $regex ]]; then
			echo "ERROR: VE_CORE_LIMIT has invalid core number:$start"
			exit 1
		fi
		if ! [[ $end =~ $regex ]]; then
			echo "ERROR: VE_CORE_LIMIT has invalid core number:$end"
			exit 1
		fi
		for (( i=start ; i <= end ; i++ )); do
			core_limit+=("$i")
		done
	done
	if [[ ${VE_CORE} != -1 && ! " ${core_limit[*]} " =~ $VE_CORE ]]; then
		echo "ERROR: \"-c|--core\" specifies cores outside the list of cores in VE_CORE_LIMIT"
		exit 1
	fi
fi
if [[ -v _VECORELIST ]] ; then
	core_list=()
	IFS=', ' read -a ranges <<< "$_VECORELIST"
	for range in "${ranges[@]}"; do
		IFS=- read start end <<< "$range"
		[ -z "$start" ] && continue
		[ -z "$end" ] && end=$start
		if ! [[ $start =~ $regex ]]; then
			echo "ERROR: Invalid core number '$start' assigned by job scheduler"
			exit 1
		fi
		if ! [[ $end =~ $regex ]]; then
			echo "ERROR: Invalid core number '$end' assigned by job scheduler"
			exit 1
		fi
		for (( i=start ; i <= end ; i++ )); do
			core_list+=("$i")
		done
	done
	if [[ ${VE_CORE} != -1 && ! " ${core_list[*]} " =~ $VE_CORE ]]; then
		echo "ERROR: \"-c|--core\" specifies core outside the list of cores assigned by job scheduler"
		exit 1
	fi
	for core_num in "${core_limit[@]}"; do
		if [[ ! " ${core_list[*]} " =~ $core_num ]]; then
			echo "ERROR: VE_CORE_LIMIT specifies cores outside the list of cores assigned by job scheduler"
			exit 1
		fi
	done
fi

if [[ -v _VENUMALIST && -v _VECORELIST ]]; then
	echo "ERROR: Job scheduler set both \"numa list\" and \"core list\". Cannot execute VE binary."
	exit 1
elif [[ -v _VENUMALIST ]]; then
	if ! [[ ${_VENUMALIST} =~ $regex ]] ; then
		echo "ERROR: The numa node id set by job scheduler is not valid "
		exit 1;
	elif [[ ${NUMA_NODE_ID} != -1 && $NUMA_NODE_ID -ne $_VENUMALIST ]]; then
		echo "ERROR: VE numa node $NUMA_NODE_ID is not assigned by the job scheduler."
		exit 1
	fi
	NUMA_NODE_ID=$_VENUMALIST
	flag_membind=1
fi
if [[ -v VE_CORE_LIMIT ]] ; then
	VE_CORE_LIMIT=0
	for core_num in ${core_limit[*]}; do
		((VE_CORE_LIMIT |= 1<<core_num))
	done
elif [[ -v _VECORELIST ]] ; then
	VE_CORE_LIMIT=0
	for core_num in ${core_list[*]}; do
		((VE_CORE_LIMIT |= 1<<core_num))
	done

fi

if [[ -v VE_CORE_LIMIT ]] ; then
	export VE_CORE_LIMIT
fi

ve_arg=( $@ )
if ! [[ -e "$ve_arg" ]]; then
        echo "ERROR: '$ve_arg' No such file exists"
        exit 1;
fi

if ! [[ -x "$ve_arg" ]]; then
	echo "ERROR: '$ve_arg' is not a valid executable"
	exit 1;
fi

export VE_NODE_NUMBER=$VE_NODE

#converting ve node number to special file path and socket file path
sock_driver=$(printf '/dev/veslot%s' "$VE_NODE" );
sock_veos=$(printf '/var/opt/nec/ve/veos/veos%s.sock' "$VE_NODE" );

#embedding option if traceme option is provided by user
if [[ ${flag_traceme} -eq 1 ]]; then
	PATH_VE_EXEC=$(printf '%s --traceme' "${PATH_VE_EXEC}");
fi

if [[ ${flag_membind} -eq 1 ]]; then
	PATH_VE_EXEC=$(printf '%s --localmembind' "${PATH_VE_EXEC}");
fi

if ! [[ -L $sock_driver ]]; then
	echo "Node '$VE_NODE' is Offline"
	exit 1;
fi

if ! [[ -e $sock_veos ]]; then
	echo "VEOS corresponding to Node '$VE_NODE' is Offline"
	exit 1;
fi

if [[ ( ! -v VE_ACC_IO || (-v VE_ACC_IO && "${VE_ACC_IO}" != "0") )
	&& (! -v VE_ATOMIC_IO || "${VE_ATOMIC_IO}" == "0")
	&& (! -v VE_PDMA_IO || "${VE_PDMA_IO}" == "0")]]; then
	export VE_LD_PRELOAD="libveaccio.so.1 $VE_LD_PRELOAD"
fi

PATH_VE_EXEC="${PATH_VE_EXEC} -d ${sock_driver} -s ${sock_veos} -c ${VE_CORE}
		--cpunodebind=${NUMA_NODE_ID}";
#extract and validate the VE process specific resource limit by
#reading VE_LIMIT_OPT environment variable
ve_limit_opt_parse

#executes the actual ve_exec binary
if [ $ld_show_aux_flag -eq 1 ];then
  LD_SHOW_AUXV=1
fi

exec $PATH_VE_EXEC -- "${@}"
exit 0
