#!/usr/local/bin/cbsd
#v13.0.2
CBSDMODULE="jail"
MYARG=""
MYOPTARG="verbose"
MYDESC="get put file to remove nodes"
ADDHELP="[verbose=1] jail1:remotefile1 localfile1 [ localfile2 jail2@:remotefile2 ]\n\
verbose=1 for debug information\n"
EXTHELP="wf_jscp"

# ToDo:
# Instead of this need one jscp daemon/services with one lock and which will work on AMQP queue
# where executing
#     % cbsd jscp XXX YYY
# just add job to queue

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

verbose=0
cloud_api=0
. ${cbsdinit}


getjname()
{
	local _t

	_t=$( echo ${1} | ${GREP_CMD} ":")

	[ $? -ne 0 ] && return 1

	jname=${1%%:*}
	rfile=${1##*:}
}

try_remote()
{
	# this is only wrapper for compile correct arguments for cbsd nodescp

	node=$( jwhereis ${jname} )

	[ -z "${node}" ] && log_err 1 "Node not found for jail ${jname}"

	cbsdlogger NOTICE ${CBSD_APP}: try to get remote jstatus for ${jname} on ${node}
	status=$( rexe node=${node} cbsd jstatus ${jname} )
	[ "${status}" = "0" ] && log_err 1 "jail ${jname} not running on ${node}"
	sqlfile="${node}"
	. ${subrdir}/rcconf.subr
	[ "${baserw}" = "1" ] && path=${data}
	[ -z "${path}" ] && log_err 1 "path not found"
}

scp()
{
	local _ret _cmd

	[ $# -ne 2 ] && err 1 "${N1_COLOR}$0 jail1:remotefile1 localfile1 [ localfile2 jail2@:remotefile2 ]${N0_COLOR}"
	jname=
	rfile=
	rarg=0

	if getjname $1; then
		if getjname $2; then
			log_err 1 "${N1_COLOR}only one remote path${N0_COLOR}"
		fi
		rarg=1
	else
		if getjname $2; then
			rarg=2
		fi
	fi

	[ -z "${jname}" -o -z "${rfile}" ] && log_err 1 "${N1_COLOR}jail path via jail:path records not determine${N0_COLOR}"
	validate_jname "${jname}" || log_err 1 "${N1_COLOR}bad jname: ${jname}${N0_COLOR}"

	Makefile="${CBSD_PWD}/CBSDfile"
	if [ -r "${Makefile}" ]; then
		[ -z "${CBSDFILE_RECURSIVE}" ] && ${ECHO} "${N1_COLOR}found CBSDfile: ${N2_COLOR}${Makefile}${N0_COLOR}"
		. ${Makefile}
		all_jail_list=$( ${GREP_CMD} -E '^jail_[a-zA-Z0-9_@%:][-a-zA-Z0-9_@%:]*\(\)$' ${Makefile} | ${XARGS_CMD} | ${TR_CMD} -d "()" | ${SED_CMD} s#jail_##g )

		# limit by single jail
		[ -n "${jname}" ] && all_jail_list="${jname}"

		if [ -n "${CLOUD_URL}" -a -n "${CLOUD_KEY}" ]; then
			cbsd_api=1
		else
			cbsd_api=0
		fi
	else
		cbsd_api=0
	fi

	if [ ${cbsd_api} -eq 1 ]; then
		CURL_CMD=$( which curl )
		JQ_CMD=$( which jq )
		[ -z "${CURL_CMD}" ] && err 1 "${N1_COLOR}cloud up requires curl, please install: ${N2_COLOR}pkg install -y curl${N0_COLOR}"
		[ -z "${JQ_CMD}" ] && err 1 "${N1_COLOR}cloud up requires jq, please install: ${N2_COLOR}pkg install -y textproc/jq${N0_COLOR}"
		[ -z "${CBSDFILE_RECURSIVE}" ] && ${ECHO} "${N1_COLOR}main cloud api: ${N2_COLOR}${CLOUD_URL}${N0_COLOR}" 1>&2
		_cid=$( ${miscdir}/cbsd_md5 "${CLOUD_KEY}" )

		found=0
		for i in ${all_jail_list}; do
			if [ "${i}" = "${jname}" ]; then
				found=1
				break
			fi
		done
		[ ${found} -eq 0 ] && err 1 "${N1_COLOR}${CBSD_APP}: no such jail: ${N2_COLOR}${jname}${N0_COLOR}"

		for _jname in ${all_jail_list}; do
			_ssh=$( ${CURL_CMD} --no-progress-meter -H "cid:${_cid}" ${CLOUD_URL}/api/v1/status/${_jname} 2>&1 )
			_ret=$?
			if [ ${_ret} -ne 0 ]; then
				${ECHO} "${N1_COLOR}${CBSD_APP} error: curl error1: ${N2_COLOR}${_ssh}${N0_COLOR}"
				${ECHO} "${CURL_CMD} --no-progress-meter -H \"cid:XXXXX\" ${CLOUD_URL}/api/v1/status/${_jname}"
				continue
			fi
			_ssh_string=$( echo "${_ssh}" | ${JQ_CMD} '.ssh_string' | ${TR_CMD} -d '"' )
			_ssh_pref=$( substr --pos=0 --len=3 --str="${_ssh_string}" )

			if [ "${_ssh_pref}" != "ssh" ]; then
				${ECHO} "${N1_COLOR}${CBSD_APP} error: curl error2, no ssh_string:\n${N2_COLOR}${_ssh}${N0_COLOR}"
				${ECHO} "${CURL_CMD} --no-progress-meter -H \"cid:XXXXX\" ${CLOUD_URL}/api/v1/status/${_jname}"
				continue
			fi
			_ssh_len=$( strlen "${_ssh_string}" )
			_ssh_post=$( substr --pos=5 --len=${_ssh_len} --str="${_ssh_string}" )
			#echo "${SSH_CMD} ${_ssh_post}"
			_ssh_ip=$( echo ${_ssh_post} | ${AWK_CMD} '{printf $1}' )
			_ssh_port=$( echo ${_ssh_post} | ${AWK_CMD} '{printf $2}' | ${TR_CMD} -d '\-p' )
			# rewrite
			if [ -n "${SUDO_USER}" ]; then
				if [ -r /home/${SUDO_USER}/.ssh/id_ed25519 ]; then
					_ssh_sudo_arg="-oIdentityFile=/home/${SUDO_USER}/.ssh/id_ed25519"
				elif [ -r /home/${SUDO_USER}/.ssh/id_rsa ]; then
					_ssh_sudo_arg="-oIdentityFile=/home/${SUDO_USER}/.ssh/id_rsa"
				else
					_ssh_sudo_arg=
				fi
			fi

			# add brakets for IPv6: scp not work with IPv6 without [], unlike ssh
			_ssh_user=${_ssh_ip%%@*}
			_ssh_real_ip=${_ssh_ip##*@}

			iptype ${_ssh_real_ip}
			ret=$?

			if [ ${ret} -eq 2 ]; then
				# IPv6
				_ssh_ip="${_ssh_user}@[${_ssh_real_ip}]"
			fi

			if [ ${rarg} -eq 1 ]; then
				DIR=$( ${DIRNAME_CMD} ${2} )
				[ ! -d "${DIR}" ] && ${MKDIR_CMD} -p ${DIR}
				scp_exec="${SCP_CMD} -oPort=${_ssh_port} -T -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -oServerAliveInterval=10 ${_ssh_sudo_arg} ${_ssh_ip}:${rfile} ${2}"
				echo "[debug1] ${scp_exec}"
			else
				scp_exec="${SCP_CMD} -oPort=${_ssh_port} -T -oStrictHostKeyChecking=no -oBatchMode=yes -oConnectTimeout=5 -oServerAliveInterval=10 ${_ssh_sudo_arg} ${1} ${_ssh_ip}:${rfile}"
				echo "[debug2] ${scp_exec}"
			fi

			${scp_exec}

		done
		exit 0
	fi

	. ${subrdir}/rcconf.subr
	if [ $? -eq 1 ]; then
		try_remote

		if [ ${rarg} -eq 1 ]; then
			cbsdlogger NOTICE ${CBSD_APP}: nodescp for ${2} from ${node}:${path}${rfile}
			_cmd="nodescp root=1 ${node}:${path}${rfile} ${2}"
			${_cmd}
			_ret=$?
		else
			cbsdlogger NOTICE ${CBSD_APP}: nodescp for ${1} to ${node}:${path}${rfile}
			_cmd="nodescp root=1 $1 ${node}:${path}${rfile}"
			${_cmd}
			_ret=$?
		fi
		[ ${_ret} -ne 0 ] && ${ECHO} "${N1_COLOR}jscp cmd failed: ${N2_COLOR}${_cmd}${N0_COLOR}"
		return ${_ret}
	fi

	[ ${jid} -eq 0 ] && log_err 1 "${N1_COLOR}jail not active: ${jname}${N0_COLOR}"

	[ ${baserw} -eq 1 ] && path="${data}"

	if [ ${rarg} -eq 1 ]; then
		DIR=$( ${DIRNAME_CMD} ${2} )
		[ ! -d "${DIR}" ] && ${MKDIR_CMD} -p ${DIR}

		if [ -n "${RSYNC_CMD}" ]; then
			#we have rsync for that
			[ ${verbose} -eq 1 ] && set -o xtrace
			cbsdlogger NOTICE ${CBSD_APP}: rsync ${path}${rfile} ${2}
			_cmd="${RSYNC_CMD} -azzlH ${path}${rfile} ${2}"
			${_cmd}
			_ret=$?
			case ${_ret} in
				0|6|24|25)
					# rsync good codes
					_ret=0
					;;
				*)
					;;
			esac
			[ ${verbose} -eq 1 ] && set +o xtrace
		else
			#no rsync, just scp
			[ ${verbose} -eq 1 ] && set -o xtrace
			cbsdlogger NOTICE ${CBSD_APP}: cp for ${path}${rfile} to ${2}
			_cmd="${CP_CMD} -a ${path}${rfile} ${2}"
			${_cmd}
			_ret=$?
			[ ${verbose} -eq 1 ] && set +o xtrace
		fi
	else
		DIR=$( ${DIRNAME_CMD} ${path}${rfile} )
		[ ${verbose} -eq 1 ] && set -o xtrace
		[ ! -d "${DIR}" ] && ${MKDIR_CMD} -p "${DIR}"
		[ ${verbose} -eq 1 ] && set +o xtrace
		if [ -n "${RSYNC_CMD}" ]; then
			#we have rsync for that
			[ ${verbose} -eq 1 ] && set -o xtrace
			cbsdlogger NOTICE ${CBSD_APP}: rsync for ${1} to ${path}${rfile}
			_cmd="${RSYNC_CMD} -azzlH ${1} ${path}${rfile}"
			${_cmd}
			_ret=$?
			case ${_ret} in
				0|6|24|25)
					# rsync good codes
					_ret=0
					;;
				*)
					;;
			esac
			[ ${verbose} -eq 1 ] && set +o xtrace
		else
			#no rsync, just scp
			[ ${verbose} -eq 1 ] && set -o xtrace
			cbsdlogger NOTICE ${CBSD_APP}: cp for ${1} to ${path}${rfile}
			_cmd="${CP_CMD} -a ${1} ${path}${rfile}"
			${_cmd}
			_ret=$?
			[ ${verbose} -eq 1 ] && set +o xtrace
		fi
	fi

	[ ${_ret} -ne 0 ] && ${ECHO} "${N1_COLOR}jscp cmd failed: ${N2_COLOR}${_cmd}${N0_COLOR}"
	return ${_ret}
}

### MAIN ###
# change current dir
cd ${CBSD_PWD}

ARGS=

# exclude jname= and mode= params from args str
for i in $*; do
	prefix8=$( substr --pos=0 --len=7 --str="${i}" )
	[ "${prefix8}" = "verbose=" ] && continue
	if [ -z "${ARGS}" ]; then
		ARGS="${i}"
	else
		ARGS="${ARGS} ${i}"
	fi
done

if [ "${verbose}" = "0" ]; then
	quiet="-q"
else
	quiet=
fi

scp ${ARGS}
ret=$?
[ ${ret} -ne 0 ] && ${ECHO} "${N1_COLOR}jscp cmd failed: ${N2_COLOR}${_cmd}${N0_COLOR}"

exit ${ret}
