#!/usr/local/bin/cbsd
#v12.1.11
MYARG="mode"
MYOPTARG="display header name"
MYDESC="Operate with virtual VALE switch"
CBSDMODULE="bhyve"
EXTHELP="wf_bhyvenetwork"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

 List and/or configure VALE switch

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}header=${N0_COLOR}    - when '0' - don't print header;
 ${N2_COLOR}display=${N0_COLOR}   - list by comma for column. Default: 'name,vm';
 ${N2_COLOR}mode=${N0_COLOR}      - action, the capabilities:
   add        - add new VALE switch;
   create     - alias for 'add';
   delete     - destroy VALE switch;
   destroy    - alias for 'delete';
   list       - list of VALE switch;
 ${N2_COLOR}name=${N0_COLOR}      - name of the VALE switch, e.g.: 'vale1';

${H3_COLOR}Examples${N0_COLOR}:

# cbsd valecfg mode=add name=vale2
# cbsd valecfg mode=list
# cbsd valecfg mode=delete name=vale2

${H3_COLOR}See also${N0_COLOR}:

 cbsd valecfg-tui --help
 cbsd ngcfg --help
 cbsd ngcfg-tui --help

"

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

[ -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} )
		[ -z "${_res}" ] && continue
		_vale_port_tmp=$( cbsdsqlro local "SELECT port_id FROM vale_ports WHERE vale_id=\"${idx}\" AND jname=\"${_i}\"" | ${XARGS_CMD} )

		[ -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
}

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