#!/usr/local/bin/cbsd
#v12.1.6
CBSDMODULE="jail"
MYARG="node jname mkdatadir"
MYOPTARG="verbose scpdata sharedfs tryoffline"
MYDESC="Prepare remote node for accepting jail via j2slave"
ADDHELP="
 mkdatadir - 0 or 1: create data directory. 1 - create, by default\n\
"

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

sharedfs=0
mkdatadir=1
tryoffline=0
scpdata=0
. ${cbsdinit}

emulator="jail" # for jname_is_multiple
jail_list=
jname_is_multiple

. ${subrdir}/time.subr
st_time=$( ${DATE_CMD} +%s )

# -n "name of the tools" - show <name> in Info string, e.g: -n jexec, -n "pkg install" ...
# -o uniq_name_of_the_task (one world)
j2prepare_multi_init()
{
	local _jname

	while getopts "c:n:o:" opt; do
		case "${opt}" in
			c) cmd="${OPTARG}" ;;
			n) _multiple_consumer_name="${OPTARG}" ;;
			o) task_owner="${OPTARG}" ;;
		esac
		shift $(($OPTIND - 1))
	done

	[ -z "${task_owner}" ] && err 1 "${N1_COLOR}multiple_processing_spawn: empty -o multiple_task_owner${N0_COLOR}"

	. ${subrdir}/multiple.subr
	${ECHO} "${N1_COLOR}Hint: Press ${N2_COLOR}'Ctrl+t'${N1_COLOR} to see last logfile line for active task${N0_COLOR}" 1>&2
	task_id=
	task_id_cur=
	task_owner="${task_owner}"
	# spawn command for all jail
	for _jname in ${jail_list}; do
		task_id_cur=$( task mode=new logfile=/tmp/${task_owner}.${_jname}.log.$$ client_id=${_jname} autoflush=0 owner=${task_owner} /usr/bin/env NOCOLOR=1 /usr/local/bin/cbsd j2prepare jname=${_jname} ${cmd} 2>/dev/null )
		sleep 0.1               # dont bruce taskdb
		if ! is_number "${task_id_cur}"; then
			task_id="${task_id} ${task_id_cur}"
		fi
	done

	multiple_task_id_all=$( echo ${task_id} | ${TR_CMD} " " "," )
	sleep 0.5
	multiple_processing_spawn -o ${task_owner} -n "${_multiple_consumer_name}"
}

[ -z "${node}" ] && log_err 1 "${N1_COLOR}Give me node${N0_COLOR}"

# MAIN for multiple jails
if [ -n "${jail_list}" ]; then
	# multiple jailsastart always non interactive
	if [ -n "${jail_list}" ]; then
		JLIST="${jail_list}"
	fi

	_args=

	# trim for jname= in "$*"
	for i in $*; do
		prefix=
		prefix6=$( substr --pos=0 --len=6 --str="${i}" )
		[ "${prefix6}" = "jname=" ] && continue
		if [ -n "${_args}" ]; then
			_args="${_args} ${i}"
		else
			_args="${i}"
		fi
	done

	task_owner="j2prepare_multiple_remove"
	j2prepare_multi_init -c "${_args}" -o ${task_owner} -n "j2prepare"
	err 0 "${N1_COLOR}Multiple j2prepare: ${N2_COLOR}done${N0_COLOR}"
fi

## MAIN
[ -z "${jname}" ] && log_err 1 "${N1_COLOR}Give me jname${N0_COLOR}"

SECFILE="${workdir}/etc/${jname}.secrets"

. ${subrdir}/rcconf.subr
[ $? -eq 1 ] && log_err 1 "${N1_COLOR}No such jail: ${N2_COLOR}${jname}${N0_COLOR}"

printf "${N1_COLOR}Preparing.${N0_COLOR}"

JAIL_RCCONF="${ftmpdir}/rc.conf_${jname}"
REMOTE_JAIL_RCCONF="jails-rcconf/rc.conf_${jname}"

JAIL_DIR="${jaildatadir}/${jname}-${jaildatapref}"
JAIL_FSTAB_LEGACY="${jailfstabdir}/${jailfstabpref}${jname}"
JAIL_FSTAB_DIR="${jailfstabdir}/${jname}"

REMOTE_JAIL_DIR="jails-data/${jname}-${jaildatapref}"
REMOTE_FSTAB_LEGACY="jails-fstab/${jailfstabpref}${jname}"
REMOTE_JAIL_FSTAB_DIR="jails-fstab/${jname}"

[ ! -d ${JAIL_DIR} ] && err 1 "No jail data for ${jname}"

# Update Redis
if [ "${mod_cbsd_redis_enabled}" = "YES" -a -z "${MOD_CBSD_REDIS_DISABLED}" ]; then
	cbsdredis publish cbsd_events '{"cmd":"'${CBSD_APP}'", "node":"'${nodename}'", "dest":"'${node}'", "jail":"'${jname}'", "status":1}'
fi

not_sharedfs_action()
{
	cbsdlogger NOTICE ${CBSD_APP}: generate secrets for ${jname}
	jgensecrets jname=${jname} mode=force > ${DEBLOG} 2>&1
	dot "jgensecrets"

	[ ! -f "${SECFILE}" ] && log_err 1 "${N1_COLOR}No such secrets${N0_COLOR}"

	NODEDATA=$( cbsdsqlro nodes select ip,port,keyfile from nodelist where nodename=\"${node}\" )

	[ -z "${NODEDATA}" ] && log_err 1 "${N1_COLOR}: No such node. Please execute ${N2_COLOR}cbsd add node=${node} ${N1_COLOR}first${N0_COLOR}"
	sqllist "${NODEDATA}" myip myport mykey

	SSHOP="-oBatchMode=yes -oStrictHostKeyChecking=no -oConnectTimeout=5 -q -oPort=${myport} -i ${mykey} ${myip}"

	cbsdlogger NOTICE ${CBSD_APP}: register secrets for ${jname} on remote node: ${node}
	rexe node=${node} tryoffline=${tryoffline} /usr/local/bin/cbsd secretsfile jname=${jname} mode=off > ${DEBLOG} 2>&1
	dot "rexe_1"
	cbsdlogger NOTICE ${CBSD_APP}: copy secrets for ${jname} to remote node: ${node}
	nodescp tryoffline=${tryoffline} ${SECFILE} ${node}:etc > ${DEBLOG} 2>&1
	dot "scp_secfile"

	# sysdata
	imgpart mode=pack jname=${jname} part=sysdata out=${tmpdir}/${jname}-sysdata.tgz > ${DEBLOG} 2>&1
	trap "${RM_CMD} -f ${tmpdir}/${jname}-sysdata.tgz" 0 1 2 3 4

	if [ ! -r ${tmpdir}/${jname}-sysdata.tgz ]; then
		err 1 "no such ${tmpdir}/${jname}-sysdata.tgz: cbsd imgpart mode=pack jname=${jname} part=sysdata out=${tmpdir}/${jname}-sysdata.tgz"
	else
		${DU_CMD} -sh ${tmpdir}/${jname}-sysdata.tgz
	fi

	cbsdlogger NOTICE ${CBSD_APP}: copy sysdata for ${jname} to ${node}
	nodescp tryoffline=${tryoffline} ${tmpdir}/${jname}-sysdata.tgz ${node}:jails-system > ${DEBLOG} 2>&1
	dot "scp_sysdata"
	# sysdata

	if [ "${scpdata}" = "1" ]; then
		# data
		imgpart mode=pack jname=${jname} part=data out=${tmpdir}/${jname}-data.tgz > ${DEBLOG} 2>&1
		trap "${RM_CMD} -f ${tmpdir}/${jname}-data.tgz" 0 1 2 3 4

		if [ ! -r ${tmpdir}/${jname}-data.tgz ]; then
			err 1 "no such ${tmpdir}/${jname}-data.tgz: cbsd imgpart mode=pack jname=${jname} part=data out=${tmpdir}/${jname}-data.tgz"
		else
			${DU_CMD} -sh ${tmpdir}/${jname}-data.tgz
		fi

		cbsdlogger NOTICE ${CBSD_APP}: copy data for ${jname} to ${node}
		nodescp tryoffline=${tryoffline} ${tmpdir}/${jname}-data.tgz ${node}:jails-system > ${DEBLOG} 2>&1
		dot "scp_data"
	fi
	# data

	rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd secretsfile jname=${jname} mode=on > ${DEBLOG} 2>&1
	dot "rexe_2"
	RDIR="${jname}-data"
	if [ "${mkdatadir}" = "1" ]; then
		cbsdlogger NOTICE ${CBSD_APP}: create datadir for ${jname} on ${node}
		rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd mkdatadir jname=${jname} > ${DEBLOG} 2>&1
		dot "rexe_mkdatadir"
	fi

	# Legacy/old fstab location, < CBSD 12.1.5
	if [ -r ${JAIL_FSTAB_LEGACY} ]; then
		cbsdlogger NOTICE ${CBSD_APP}: copy fstabs for ${jname} to ${node}
		nodescp tryoffline=${tryoffline} ${JAIL_FSTAB_LEGACY} ${node}:${REMOTE_FSTAB_LEGACY} > ${DEBLOG} 2>&1
		dot "scp legacy fstab"

		cbsdlogger NOTICE ${CBSD_APP}: replacewdir for ${jname} fstab on ${node}
		rexe tryoffline=${tryoffline} node=${node} cbsd replacewdir old=${workdir} file0=${REMOTE_FSTAB_LEGACY} > ${DEBLOG} 2>&1
		dot "rexe_fstab_legacy"
	fi
	# Legacy/old fstab.local location, < CBSD 12.1.5
	if [ -r ${JAIL_FSTAB_LEGACY}.local ]; then
		cbsdlogger NOTICE ${CBSD_APP}: copy local fstabs for ${jname} to ${node}
		nodescp tryoffline=${tryoffline} ${JAIL_FSTAB_LEGACY}.local ${node}:${REMOTE_FSTAB_LEGACY}.local > ${DEBLOG} 2>&1
		dot "scp legacy local fstab"

		cbsdlogger NOTICE ${CBSD_APP}: replacewdir for ${jname} fstab.local on ${node}
		rexe tryoffline=${tryoffline} node=${node} cbsd replacewdir old=${workdir} file0=${REMOTE_FSTAB_LEGACY}.local > ${DEBLOG} 2>&1
		dot "rexe_fstab_legacy_local"
	fi

	# New fstab location, > CBSD 12.1.5
	if [ -r ${JAIL_FSTAB_DIR}/fstab ]; then
		cbsdlogger NOTICE ${CBSD_APP}: copy fstabs for ${jname} to ${node}
		nodescp tryoffline=${tryoffline} ${JAIL_FSTAB_DIR}/fstab ${node}:${REMOTE_JAIL_FSTAB_DIR}/fstab > ${DEBLOG} 2>&1
		dot "scp fstab"

		cbsdlogger NOTICE ${CBSD_APP}: replacewdir for ${jname} fstab on ${node}
		rexe tryoffline=${tryoffline} node=${node} cbsd replacewdir old=${workdir} file0=${REMOTE_JAIL_FSTAB_DIR}/fstab > ${DEBLOG} 2>&1
		dot "rexe_fstab"
	fi
	# New fstab location, > CBSD 12.1.5
	if [ -r ${JAIL_FSTAB_DIR}.local ]; then
		cbsdlogger NOTICE ${CBSD_APP}: copy local fstabs for ${jname} to ${node}
		nodescp tryoffline=${tryoffline} ${JAIL_FSTAB_DIR}.local ${node}:${JAIL_FSTAB_DIR}.local > ${DEBLOG} 2>&1
		dot "scp fstab"

		cbsdlogger NOTICE ${CBSD_APP}: replacewdir for ${jname} fstab.local on ${node}
		rexe tryoffline=${tryoffline} node=${node} cbsd replacewdir old=${workdir} file0=${JAIL_FSTAB_DIR}.local > ${DEBLOG} 2>&1
		dot "rexe_fstab_local"
	fi

	cbsdlogger NOTICE ${CBSD_APP}: extract sysdata for ${jname} on ${node}
	rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd imgpart mode=extract jname=jails-system/${jname}-sysdata.tgz part=sysdata out=jails-system > ${DEBLOG} 2>&1
	dot "rexe_img_extract_sysdata"

	rexe tryoffline=${tryoffline} node=${node} ${RM_CMD} -f jails-system/${jname}-sysdata.tgz jails-system/${jname}/locked > ${DEBLOG} 2>&1
	dot "rexe_rm-f-sysdata"

	if [ "${scpdata}" = "1" ]; then
		cbsdlogger NOTICE ${CBSD_APP}: extract data for ${jname} on ${node}
		rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd imgpart mode=extract jname=jails-system/${jname}-data.tgz part=data out=jails-data > ${DEBLOG} 2>&1
		dot "rexe_img_extract_data"

		rexe tryoffline=${tryoffline} node=${node} ${RM_CMD} -f jails-system/${jname}-data.tgz jails-data/${jname}/locked > ${DEBLOG} 2>&1
		dot "rexe_rm-f-data"
	fi
}

printf "   ${H5_COLOR}* ${N1_COLOR}check for remote CBSD version: ${N0_COLOR}"
# todo: we can get this version from the nodes database (from retrinv task)
d_cbsd_ver=$( rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd -c version 2>/dev/null | ${TR_CMD} -d \\r | ${AWK_CMD} '/./{print $1}' )
[ $? -ne 0 ] && err 1 "${N1_COLOR}${CBSD_APP}: failed: tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd -c version${N0_COLOR}"
[ -z "${d_cbsd_ver}" ] && err 1 "${N1_COLOR}${CBSD_APP}: failed: cbsd rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd -c version${N0_COLOR}"
printf "${H3_COLOR}${d_cbsd_ver}${N0_COLOR}"
echo
s_cbsd_ver=$( version | ${AWK_CMD} '/./{print $1}' )

[ "${s_cbsd_ver}" != "${d_cbsd_ver}" ] && err 1 "${W1_COLOR}${CBSD_APP} error: ${N1_COLOR}local CBSD version not equal: ${s_cbsd_ver} != ${d_cbsd_ver}${N0_COLOR}"

if [ ${sharedfs} -eq 0 ]; then
	cbsdlogger NOTICE ${CBSD_APP}: not shared fs with ${node}, perform not_sharedfs_action
	not_sharedfs_action
fi

jmkrcconf jname=${jname} > ${JAIL_RCCONF}
cbsdlogger NOTICE ${CBSD_APP}: copy rcconf for ${jname} to ${node}
nodescp tryoffline=${tryoffline} ${JAIL_RCCONF} ${node}:${REMOTE_JAIL_RCCONF} > ${DEBLOG} 2>&1
dot "scp rcconf"
${RM_CMD} -f ${JAIL_RCCONF}

cbsdlogger NOTICE ${CBSD_APP}: jrsyncconf for ${jname} on ${node}
rexe tryoffline=${tryoffline} node=${node} /usr/local/bin/cbsd jrsyncconf jname=${jname} > ${DEBLOG} 2>&1
dot "rexe_jrsyncconf"

cbsdlogger NOTICE ${CBSD_APP}: replacewdir for ${jname} on ${node}
rexe tryoffline=${tryoffline} node=${node} cbsd replacewdir old=${workdir} file0=jails-rcconf/rc.conf_${jname} > ${DEBLOG} 2>&1
dot "rexe_4"

# Update Redis
if [ "${mod_cbsd_redis_enabled}" = "YES" -a -z "${MOD_CBSD_REDIS_DISABLED}" ]; then
	end_time=$( ${DATE_CMD} +%s )
	diff_time=$(( end_time - st_time ))
	cbsdredis publish cbsd_events '{"cmd":"'${CBSD_APP}'", "node":"'${nodename}'", "dest":"'${node}'", "jail":"'${jname}'", "status":0, "duration":'${diff_time}'}'
fi

err 0 "${N2_COLOR}ok${N0_COLOR}"
