#!/usr/local/bin/cbsd
#v12.1.14
MYARG="search_profile"
MYOPTARG="active arch_only display extra_profile_dir has_init header show_bhyve show_cloud show_jail show_qemu show_xen uniq"
MYDESC="Scan/print virtual machine profiles"
CBSDMODULE="bhyve,qemu,xen"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

The CBSD includes profiles (text files) of virtual machines that are available to run 
through supported hypervisors (bhyve, QEMU/NVMM, XEN). 'show_profile_list' script scan 
relevant directories for vm- profiles and print list.

The script aggressively uses grep: if you use it in automation, 
it is desirable to cache the output.

Standard profile directories:

  ~cbsd/etc/defaults - for build-in/contrib CBSD profiles;
  ~cbsd/etc          - for user's profiles;

profiles have a filename starting with 'vm-' prefix.

You can add custom profile directories via extra_profile_dir= args or ~cbsd/etc/bhyve-default-default.conf

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}arch_only=${N0_COLOR}        - show profiles for the specified architecture, e.g.: 'aarch64',
                     when not set, 'amd64' architecture is used by default;
 ${N2_COLOR}display=${N0_COLOR}          - list by comma for column: path,name,active,contrib,imginit.
                     Default value: 'path,name,active';
 ${N2_COLOR}extra_profile_dir${N0_COLOR} - Extra directory to search VMs profiles.
 ${N2_COLOR}has_init${N0_COLOR}          - set '1' to show profiles only who has initialized images, default: '0';
 ${N2_COLOR}header=${N0_COLOR}           - set '0' to skip print header;
 ${N2_COLOR}search_profile=${N0_COLOR}   - prefix/mask for filename, e.g: vm-\${vm_os_type}, \${emulator}-freebsd-;
 ${N2_COLOR}show_bhyve=${N0_COLOR}       - '0','1','2': show only active=0 (disabled), 1-(enabled) and 2 - (any).
                     Default is: 2;
 ${N2_COLOR}show_qemu=${N0_COLOR}        - '0','1','2': show only active=0 (disabled), 1-(enabled) and 2 - (any).
                     Default is: 2;
 ${N2_COLOR}show_xen=${N0_COLOR}         - '0','1','2' show only active=0 (disabled), 1-(enabled) and 2 - (any).
                     Default is: 2;
 ${N2_COLOR}show_jail=${N0_COLOR}        - '0','1','2' show only active=0 (disabled), 1-(enabled) and 2 - (any).
                     Default is: 2;
 ${N2_COLOR}show_cloud=${N0_COLOR}       - '0','1','2' show only cloud=0 (disabled), 1-(enabled) and 2 - (any).
                     Default is: 0;
 ${N2_COLOR}uniq=${N0_COLOR}             - '0','1'. When '0' (default) - show all profiles, 
                     when '1' - sort uniq by name with ~cbsd/etc/ win over ~cbsd/etc/defaults;

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd show_profile_list search_profile=vm-linux show_cloud=1 show_bhyve=1 uniq=1
 # env NOCOLOR=1 cbsd show_profile_list search_profile=vm-freebsd show_cloud=0 show_qemu=1 uniq=1 display=path,name,contrib header=0 arch_only=riscv64
 # cbsd show_profile_list search_profile=vm-other show_bhyve=1 extra_profile_dir="/root/cbsd-profiles"
 # cbsd show_profile_list search_profile=vm-\\\*-cloud show_cloud=1 show_bhyve=1 uniq=1 display=path header=0 has_init=1

${H3_COLOR}See also${N0_COLOR}:

 cbsd summary --help
 cbsd bconstruct-tui --help
 cbsd qconstruct-tui --help
 cbsd xconstruct-tui --help

"

. ${subrdir}/nc.subr
arch_only="native"

oextra_profile_dir=
extra_profile_dir=
ohas_init=
has_init=
readconf bhyve-default-default.conf
. ${cbsdinit}

[ -n "${extra_profile_dir}" ] && oextra_profile_dir="${extra_profile_dir}"

. ${system}

[ -z "${show_bhyve}" ] && show_bhyve=0
[ -z "${show_jail}" ] && show_jail=0
[ -z "${show_qemu}" ] && show_qemu=0
[ -z "${show_xen}" ] && show_xen=0
[ -z "${show_cloud}" ] && show_cloud=0
[ -z "${has_init}" ] && has_init=0
[ -z "${uniq}" ] && uniq=0
[ -z "${display}" ] && display="path,name,active"
[ -z "${only_bhyve_active}" ] && only_bhyve_active=2
[ -z "${only_xen_active}" ] && only_xen_active=2

case "${arch_only}" in
	native)
		arch_only=$( ${UNAME_CMD} -m )
		[ "${arch_only}" = "x86_64" ] && arch_only="amd64"
		;;
esac

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

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

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=""

		eval _val="\$$_i"
		[ -z "${_val}" ] && _val="\-"

		printf "${_val} "
	done

	printf "\n"
}

# return 1 if $1 exist in global $vm_name_list variable
is_uniq()
{
	for i in ${vm_name_list}; do
		[ "${i}" = "${1}" ] && return 1
	done

	return 0
}

# $1 - which file from. Eg: local
show_jaildata_from_sql()
{
	local _i
	local _tmp_profile_list
	local _profile_list
	local _etcdefdir_len=$( strlen ${etcdir}/default )
	local _etcdef_part=$( substr --pos=0 --len=${_etcdefdir_len} --str=${etcdir}/default )
	local _dir_list

	[ -n "${oextra_profile_dir}" ] && extra_profile_dir="${oextra_profile_dir}"

	if [ -n "${extra_profile_dir}" ]; then
		if [ -d "${extra_profile_dir}" ]; then
			_dir_list="${etcdir}/defaults ${etcdir} ${extra_profile_dir}"
		else
			${ECHO} "${W1_COLOR}${CBSD_APP} warning: ${N1_COLOR}no such extra_profile_dir: ${N2_COLOR}${extra_profile_dir}${N0_COLOR}" >&2
			_dir_list="${etcdir}/defaults ${etcdir}"
		fi
	else
		_dir_list="${etcdir}/defaults ${etcdir} ${extra_profile_dir}"
	fi

	# sort - /etc must win before etc/default
	_tmp_profile_list=$( ${FIND_CMD} ${_dir_list} -mindepth 1 -maxdepth 1 -name ${search_profile}\* -type f -exec ${REALPATH_CMD} {} \; | ${SORT_CMD} -r )

	vm_name_list=

	local name_col=1

	# determine column number for name field
	# it will come in handy for sorting
	for _i in ${mydisplay}; do
		[ "${_i}" = "name" ] && break
		name_col=$(( name_col + 1 ))
	done

	for _i in ${_tmp_profile_list}; do
		vm_profile=
		vm_arch=
		bhyve_active=0
		xen_active=0
		jail_active=0
		is_cloud=0
		eval $( ${GREP_CMD} -E "(^jail_profile=)|(^vm_profile=)|(^bhyve_active=)|(^qemu_active=)|(^xen_active=)|(^jail_active)|(^is_cloud)|(^vm_arch)" ${_i} )
		[ ${show_bhyve} -eq 1 -a -z "${vm_profile}" ] && continue
		[ ${show_xen} -eq 1 -a -z "${vm_profile}" ] && continue
		[ ${show_qemu} -eq 1 -a -z "${vm_profile}" ] && continue
		path="${_i}"
		[ -z "${is_cloud}" ] && is_cloud=0
		[ -z "${xen_active}" ] && xen_active=0
		[ -z "${qemu_active}" ] && qemu_active=0
		[ -z "${jail_active}" ] && jail_active=0
		[ -z "${bhyve_active}" ] && bhyve_active="99"
		[ -n "${jail_profile}" ] && name="${jail_profile}"
		[ -n "${vm_profile}" ] && name="${vm_profile}"
		[ -z "${vm_arch}" ] && vm_arch=0

		case "${show_cloud}" in
			0)
				[ "${is_cloud}" = "1" ] && continue
				;;
			1)
				[ "${is_cloud}" = "0" ] && continue
				;;
		esac

		if [ ${show_bhyve} -eq 1 ]; then
			case "${show_bhyve}" in
				0|1)
					[ "${bhyve_active}" != "${show_bhyve}" ] && continue
					;;
			esac
		fi

		if [ ${show_qemu} -eq 1 ]; then
			case "${show_qemu}" in
				0|1)
					[ "${qemu_active}" != "${show_qemu}" ] && continue
					;;
			esac
		fi

		if [ ${show_xen} -eq 1 ]; then
			case "${show_xen}" in
				0|1)
					[ "${xen_active}" != "${show_xen}" ] && continue
					;;
			esac
		fi

		if [ ${show_jail} -eq 1 ]; then
			case "${show_jail}" in
				0|1)
					[ "${jail_active}" != "${show_jail}" ] && continue
					;;
			esac
		fi

		if [ ${uniq} -eq 1 ]; then
			if ! is_uniq ${name}; then
				continue
			fi
			vm_name_list="${vm_name_list} ${name}"
		fi

		if [ -n "${arch_only}" ]; then
			if [ "${vm_arch}" != "0" ]; then
				[ "${arch_only}" != "${vm_arch}" ] && continue
			else
				# amd64 arch is default
				[ "${arch_only}" != "amd64" ] && continue
			fi
		fi

		contrib=0
		_cur_part=$( substr --pos=0 --len=${_etcdefdir_len} --str=${_i} )
		if [ "${_cur_part}" = "${_etcdef_part}" ]; then
			contrib=1
		fi

		img_initcontrib=0
		_cur_part=$( substr --pos=0 --len=${_etcdefdir_len} --str=${_i} )
		if [ "${_cur_part}" = "${_etcdef_part}" ]; then
			contrib=1
		fi

		[ -n "${ohas_init}" ] && has_init="${ohas_init}"

		imginit=$( . ${_i} 2>/dev/null; [ -z "${register_iso_name}" ] && exit 0 ; [ -r "${srcdir}/iso/${register_iso_name}" ] && echo "1" )

		if [ "${has_init}" = "1" ]; then
			iso_img=
			iso_img1=
			iso_img2=
			eval $( ${GREP_CMD} -E "(^iso_img=)" ${_i} )
			if [ -n "${iso_img}" ]; then
				iso_img1="${srcdir}/iso/cbsd-${iso_img}"

				# back compatible
				iso_img2="${srcdir}/iso/cbsd-cloud-${iso_img}"
				iso_img3="${srcdir}/iso/${iso_img}"

				if [ ! -e "${iso_img}" ]; then
					if [ ! -e "${iso_img2}" ]; then
						[ ! -e "${iso_img3}" ] && continue
					fi
				fi
			fi
		fi

		populate_output_data

	done | ${SORT_CMD} -k${name_col} -n

	unset vm_name_list
}


show_local()
{
	local _errcode _status

	show_header
	show_jaildata_from_sql local
}

show_vhid()
{
	show_local
}

#### MAIN
[ -z "${header}" ] && header=1
sqldelimer=" "
show_local | ${COLUMN_CMD} -t

exit 0
