#!/usr/local/bin/cbsd
#v12.1.11
MYARG="mode"
MYOPTARG="name"
MYDESC="Operate with virtual VALE switch"
CBSDMODULE="bhyve"
EXTHELP="wf_bhyvenetwork"
ADDHELP="\
mode=list,add/create,delete/destroy\n\
header=0 don't print header\n\
display= list by comma for column. Default: name,vm\n\
"

. ${subrdir}/nc.subr
. ${cbsdinit}
. ${system}

[ -z "${display}" ] && display="name,vm"

#remove commas for loop action on header
mydisplay=$( echo ${display} | ${TR_CMD} ',' '  ' )

# upper for header
myheader=$( echo ${mydisplay} | ${TR_CMD} '[:lower:]' '[:upper:]' )
[ -z "${header}" ] && header=1

show_header()
{
	local _header="${BOLD}${myheader}${N0_COLOR}"
	[ ${header} -eq 1 ] && ${ECHO} ${_header}
}

# if $1 = "Unregister" then overwrite status to "Unregister"
populate_output_data()
{
	local _i _val

	_status=

	printf "${N0_COLOR}" # for column sort

	#populate values for in output string
	for _i in ${mydisplay}; do

		_val=

		if [ "${_i}" = "vm" ]; then
			_val=$( populate_vale_member ${name} )
		else
			eval _val=\$$_i
		fi
		[ -z "${_val}" ] && _val="\-"

		printf "${_val} "
	done

	printf "\n"
}

# $1 - switch name
# compile vale member by jname
populate_vale_member()
{
	local _sql

	local _list _idx
	local count=0
	local _mydb="${dbdir}/local.sqlite"
	local _vms _vmdb _res _i
	local _vale_port _vale_port_tmp _vm_part

	_vms=$( ${miscdir}/sqlcli ${_mydb} "SELECT jname FROM jails WHERE emulator = \"bhyve\"" )

	for _i in ${_vms}; do
		_vmdb="${jailsysdir}/${_i}/local.sqlite"
		[ ! -r "${_vmdb}" ] && continue

		_sql="SELECT jname FROM bhyvenic WHERE nic_parent=\"${vale_name}\" OR nic_parent=\"${name}\" LIMIT 1"

		_res=$( cbsdsqlro ${_vmdb} ${_sql} )
		#echo "cbsdsqlro ${_vmdb} ${_sql}" >> /tmp/ff.txt
		[ -z "${_res}" ] && continue
		_vale_port_tmp=$( cbsdsqlro local "SELECT port_id FROM vale_ports WHERE vale_id=\"${idx}\" AND jname=\"${_i}\"" | ${XARGS_CMD} )

#		if [ -z "${_vale_port_tmp}" ]; then
#			# check for vale${idx}
#			_idx=$( cbsdsqlro local SELECT idx FROM vale WHERE name=\"vale${idx}\" LIMIT 1 )
#			[ -z "${_idx}" ] && continue
#			_vale_port_tmp=$( cbsdsqlro local "SELECT port_id FROM vale_ports WHERE vale_id=\"${_idx}\" AND jname=\"${_i}\"" | ${XARGS_CMD} )
#		fi

		[ -z "${_vale_port_tmp}" ] && continue

		if [ -n "${_vale_port_tmp}" ]; then
			for _vale_port in ${_vale_port_tmp}; do
				# concat VALE port number
				_vm_part="${_i}[${H3_COLOR}${_vale_port}${N0_COLOR}]"
				if [ -z "${_list}" ]; then
					_list="${_vm_part}"
				else
					_list="${_list},${_vm_part}"
				fi
			done
		fi
	done

	printf "${_list}"
}


# $1 - which file from. Eg: local
show_jaildata_from_sql()
{
	local _i

	_sql="SELECT idx,name FROM vale ORDER BY CAST(idx AS int)"
	cbsdsqlro local ${_sql} | while read idx name; do
		vale_name="cbsdvale_${name}"
		populate_output_data
	done
}


show_local()
{
	local _errcode _status

	show_header
	show_jaildata_from_sql local
}

add_vale()
{
	local _idx

	_idx=$( cbsdsqlro local SELECT idx FROM vale WHERE name=\"${name}\" LIMIT 2 2>/dev/null )
	[ -n "${_idx}" ] && err 1 "${N1_COLOR}${CBSD_APP}: switch already exist: ${N2_COLOR}${name}${N0_COLOR}"

	cbsdsqlrw local "INSERT INTO vale ( name ) VALUES ( \"${name}\" )"
	${ECHO} "${N1_COLOR}vale added: ${N2_COLOR}${name}${N0_COLOR}"
}

del_vale()
{
	local _sw _p1 _p2 _len _res

	/usr/sbin/valectl | ${GREP_CMD} ^${name}: | ${AWK_CMD} '{printf $1"\n"}' | while read _sw; do
		_p1=${_sw%%:*}
		_p2=${_sw##*:}
		# skip for external^
		[ -z "${_p2}" ] && continue
		_len=$( strlen "${_p2}" )
		_res=$( substr --pos=${_len} --len=1 --str="${_p2}" )
		[ "${_res}" = "^" ] && continue
		${ECHO} "${N1_COLOR}${CBSD_APP} detach: ${N2_COLOR}${_p2}${N0_COLOR}"
		/usr/sbin/valectl -d ${name}:${_p2}
	done
	cbsdsqlrw local "DELETE FROM vale WHERE name=\"${name}\""
	${ECHO} "${N1_COLOR}vale destroyed: ${N2_COLOR}${name}${N0_COLOR}"
}


#### MAIN
case "${mode}" in
	list)
		sqldelimer=" "
		show_local | ${COLUMN_CMD} -t
		;;
	add|create)
		[ -z "${name}" ] && err 1 "${N1_COLOR}${CBSD_APP}: switch name is mandatory, e.g: vale1: ${N2_COLOR}name=${N0_COLOR}"
		add_vale
		;;
	del*|destroy)
		[ -z "${name}" ] && err 1 "${N1_COLOR}${CBSD_APP}: switch name is mandatory, e.g: vale1: ${N2_COLOR}name=${N0_COLOR}"
		del_vale
		;;
	*)
		err 1 "${N1_COLOR}${CBSD_APP}: unknown node: ${N2_COLOR}${mode}${N0_COLOR}"
		;;
esac

exit 0
