#!/usr/local/bin/cbsd
#v11.2.1
CBSDMODULE="bhyve"
MYARG="jname"
MYOPTARG="nice"
MYDESC="Re-nice bhyve processes on-the-fly"
ADDHELP="nice=[new value]\n\
  or skip nice= to apply values from RCTL databases\n\"
"

. ${subrdir}/nc.subr
. ${tools}
. ${strings}

. ${cbsdinit}

emulator="bhyve" # for jname_is_multiple
jname_is_multiple

if [ -n "${jail_list}" ]; then
	TMP_JLIST="${jail_list}"
else
	TMP_JLIST=$*
fi

JLIST=

# check for actual vm list in arg list
jail_num=0
for i in ${TMP_JLIST}; do
	exist=$( cbsdsqlro local SELECT jname FROM jails WHERE jname=\"${i}\" AND emulator=\"${emulator}\" LIMIT 1 )
	if [ -n "${exist}" ]; then
		JLIST="${exist} ${JLIST}"
		jail_num=$(( jail_num + 1 ))
	fi
done

# this is multiple list, split it by parallel bstop execution
if [ ${jail_num} -gt 1 ]; then
	cbsdlogger NOTICE ${CBSD_APP}: executing for multiple brenice: ${JLIST}
	new_arg=

	for i in $*; do
		_is_jname=$( substr --pos=0 --len=5 --str=${i} )
		[ "${_is_jname}" = "jname" ] && continue
		new_arg="${new_arg} ${i}"
	done

	for jname in ${JLIST}; do
		brenice jname=${jname} ${new_arg}
	done
	exit 0
fi

[ -z "${jname}" ] && jname=$( echo ${JLIST} | ${AWK_CMD} '{printf $1}' )
[ -z "${jname}" ] && jname="${1}"
[ -z "${jname}" ] && err 1 "${N1_COLOR}Give me domain name${N0_COLOR}"

. ${distsharedir}/bhyve.conf		# only for for MYCOL variables: used in exports below

. ${subrdir}/rcconf.subr
if [ $? -eq 1 ]; then
	[ ${sqlreplica} -eq 0 ] && err 1 "${N1_COLOR}No such domain: ${N2_COLOR}${jname}${N0_COLOR}"
	remotenode=$( bwhereis ${jname} )
	[ -z "${remotenode}" ] && err 1 "${N1_COLOR}No such domain: ${N2_COLOR}${jname}${N0_COLOR}"
	for i in ${remotenode}; do
		${ECHO} "${N1_COLOR}Remote bstop: ${N2_COLOR}${jname} ${N1_COLOR}on${N2_COLOR} ${i}${N0_COLOR}"
		rexe node=${i} cbsd bstop jname=${jname}
		if [ $? -eq 0 ]; then
			# update inventory
			${ECHO} "${N1_COLOR}Updating inventory...${N0_COLOR}"
			task autoflush=2 mode=new cbsd retrinv node=${i} tryoffline=1 data=db > /dev/null 2>&1
		fi
	done
	exit 0
fi

. ${subrdir}/rcconf.subr
[ "${emulator}" != "bhyve" ] && log_err 1 "${N1_COLOR}Not in bhyve emulator: ${N2_COLOR}${emulator}${NORMAL}"
[ ${jid} -eq 0 ] && exit 0

if [ -z "${nice}" ]; then
	_formfile="${jailsysdir}/${jname}/helpers/brctl.sqlite"
	[ -r "${_formfile}" ] && nice=$( cbsdsqlro ${_formfile} "SELECT cur FROM forms WHERE param=\"nice\"" )
	# just reset
	[ -z "${nice}" ] && nice="0"
fi

search_cmd="bhyve: ${jname}"
strlen_search_cmd=$( strlen "${search_cmd}" )

vm_pid=

eval $( /bin/ps axopid,state,ucomm,command -ww | while read pid state ucomm command; do
	[ "${ucomm}" != "bhyve" ] && continue
	cmd_pref=$( substr --pos=0 --len=${strlen_search_cmd} --str="${command}" )

	b_jname=$( echo "${command}" | ${AWK_CMD} '/bhyve: /{print $2}' )
	[ "${b_jname}" != "${jname}" ] && continue

	pid_count=$(( pid_count + 1 ))

	if $( echo "${state}" | ${GREP_CMD} -q "T" ); then
		pid_count=$(( pid_count - 1 ))
	fi

	if [ "${cmd_pref}" = "${search_cmd}" ]; then
		echo pid_count=\"${pid_count}\"
		echo vm_pid=\"${pid}\"
		break
	fi

	if echo "${command}" | ${GREP_CMD} -E -q -e " ${jname}"$ 2>/dev/null; then
		echo pid_count=\"${pid_count}\"
		echo vm_pid=\"${pid}\"
		break
	fi

done )

if [ -z "${vm_pid}" -o "${vm_pid}" = "0" ]; then
	cbsdlogger WARNING ${CBSD_APP}: unable to determine pid for: ${jname}
	log_err 1 "${N1_COLOR}Unable to determine pid for: ${N2_COLOR}${jname}${N0_COLOR}"
fi

if [ -z "${pid_count}" ]; then
	cbsdlogger WARNING ${CBSD_APP}: unable to determine pid_count for: ${jname}
	log_err 1 "${N1_COLOR}Unable to determine pid_count for: ${N2_COLOR}${jname}${N0_COLOR}"
fi

cbsdlogger NOTICE ${CBSD_APP}: re-nice ${nice} to bhyve ${jname} pid: ${vm_pid}
/usr/bin/renice ${nice} -p ${vm_pid}
