#!/usr/local/bin/cbsd
#v11.2.1
MYARG=""
MYOPTARG="data jname node tryoffline"
MYDESC="Fetch sqldb from remote node"
ADDHELP="
${H3_COLOR}Description${N0_COLOR}:

Receive and save locally system info (e.g. database) from a remote 
node via a SSH connection.

When 'node' argument is empty - retrieve db from all nodes from node lists.

${H3_COLOR}Options${N0_COLOR}:

 ${N2_COLOR}data=${N0_COLOR}       - which part of info, can be: jdescr,nodedescr,db,rctl,fwcnt,bhyve,jail,qemu,xen. 
               When not specified - retrieive all of them.
 ${N2_COLOR}jname=${N0_COLOR}      - fetch data only for specified jail.
 ${N2_COLOR}tryoffline=${N0_COLOR} - when '1' - try to fetch inventory when node is offline.

${H3_COLOR}Examples${N0_COLOR}:

 # cbsd retrinv
 # cbsd retrinv node=fnode2.my.domain tryoffline=1 data=db

${H3_COLOR}See also${N0_COLOR}:

 cbsd node --help

"

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

retr_db()
{
	local _rnode="${1}"
	local _msg=

	[ -z "${_rnode}" ] && return 0

	_cmd="nodescp ${checkforonline} ${_rnode}:var/db/inv.${_rnode}.sqlite ${dbdir}/${_rnode}.sqlite"
	${_cmd} && ${CHMOD_CMD} 0640 "${dbdir}/${_rnode}.sqlite" && ${CHOWN_CMD} ${cbsduser} "${dbdir}/${_rnode}.sqlite"
	if [ $? -eq 0 ]; then
		${ECHO} "${N1_COLOR}CBSD: Fetching inventory done: ${N2_COLOR}${_rnode}${N0_COLOR}"
		idle_update ${_rnode}
	else
		${ECHO} "${N1_COLOR}CBSD: Fetching inventory failed: ${N2_COLOR}${_rnode}${N0_COLOR}"
		${ECHO} "${N1_COLOR}Guru meditaion: ${N2_COLOR}${_cmd}${N0_COLOR}"
	fi

	return 0
}

retr_nodedescr()
{
	local _rnode="${1}" _files= _i=
	local _res=
	local _ret=

	[ -z "${_rnode}" ] && return 0
	[ ! -d "${dbdir}/nodedescr" ] && ${MKDIR_CMD} -m 0700 -p "${dbdir}/nodedescr" && ${CHMOD_CMD} 0640 "${dbdir}/nodedescr" && ${cbsduser} "${dbdir}/nodedescr"

	_files="descr role domain notes location"

	for _i in ${_files}; do
		_res=$( nodescp ${checkforonline} ${_rnode}:node.${_i} ${dbdir}/nodedescr/${_rnode}.${_i} 2>/dev/null )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "nodescp failed [skipped]: ${_res}"
			continue
		fi

		${CHMOD_CMD} 0640 "${dbdir}/nodedescr/${_rnode}.${_i}" && ${CHOWN_CMD} ${cbsduser} "${dbdir}/nodedescr/${_rnode}.${_i}" 2>/dev/null
	done

	return 0
}

# todo: check for shared FS
retr_vm()
{
	local _rnode="${1}" _emulator="${2}"
	local _files= _i= _sqlfile=
	local _tmpdir=

	[ -z "${_rnode}" ] && return 0

	_tmpdir="${tmpdir}/${_rnode}"

	[ ! -d ${_tmpdir} ] && ${MKDIR_CMD} -p ${_tmpdir}

	cbsdsqlro ${_rnode} SELECT jname FROM jails WHERE emulator='${_emulator}' ORDER BY jname ASC | while read jname; do
		[ ! -d ${_tmpdir}/${jname} ] && ${MKDIR_CMD} -p ${_tmpdir}/${jname}
		_files="jails-system/${jname}"
		_res=$( nodescp ${checkforonline} ${_rnode}:${_files}/local.sqlite ${_tmpdir}/${jname}/local.sqlite 2>/dev/null )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "nodescp failed [skipped]: ${_res}"
			continue
		fi

		nodescp ${checkforonline} ${_rnode}:${_files}/vnc_port ${_tmpdir}/${jname}/vnc_port 2>/dev/null
	done

	return 0
}

retr_jail()
{
	local _rnode=${1} _files _i _sqlfile
	local _tmpdir

	[ -z "${_rnode}" ] && return 0
	_tmpdir="${tmpdir}/${_rnode}"

	[ ! -d ${_tmpdir} ] && ${MKDIR_CMD} -p ${_tmpdir}

	return 0
}


retr_jdescr()
{
	local _rnode="${1}" _jname=
	local _res=

	[ -z "${_rnode}" ] && return 0

	[ ! -f "${dbdir}/${_rnode}.sqlite" ] && return 0
	[ ! -d "${dbdir}/nodedescr" ] && ${MKDIR_CMD} -p "${dbdir}/nodedescr"

	if [ -z "${jname}" ]; then
		_jname=$( /usr/local/bin/cbsd -c "cbsdsqlro ${_rnode} SELECT jname FROM jails WHERE status\<2" )
	else
		_jname="${jname}"
	fi

	[ -z "${_jname}" ] && return 0

	for _i in ${_jname}; do
		_res=$( nodescp ${checkforonline} ${_rnode}:jails-system/${_i}/descr ${dbdir}/nodedescr/${_rnode}.${_i}.descr 2>/dev/null )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "nodescp failed [skipped]: ${_res}"
			continue
		fi
		${CHMOD_CMD} 0640 "${dbdir}/nodedescr/${_rnode}.${_i}.descr"
		${CHOWN_CMD} ${cbsduser} "${dbdir}/nodedescr/${_rnode}.${_i}.descr" 2>/dev/null
	done
}

retr_rctl()
{
	local _rnode="${1}" _jname=
	local _res=

	[ -z "${_rnode}" ] && return 0

	[ ! -f "${dbdir}/${_rnode}.sqlite" ] && return 0

	if [ -z "$jname" ]; then
		_jname=$( /usr/local/bin/cbsd -c "cbsdsqlro ${_rnode} SELECT jname FROM jails WHERE status\<2" )
	else
		_jname=${jname}
	fi

	[ -z "${_jname}" ] && return 0

	for _i in ${_jname}; do
		[ ! -d "${dbdir}/rctl/${_rnode}-${_i}" ] && ${MKDIR_CMD} -p "${dbdir}/rctl/${_rnode}-${_i}"
		_res=$( nodescp ${checkforonline} ${_rnode}:jails-system/${_i}/rctl/* ${dbdir}/rctl/${_rnode}.${_i}.descr 2>/dev/null )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "nodescp failed [skipped]: ${_res}"
			continue
		fi
		${CHMOD_CMD} 0640 ${dbdir}/rctl/${_rnode}-${_i}/*
		${CHOWN_CMD} ${cbsduser} ${dbdir}/rctl/${_rnode}-${_i}/* 2>/dev/null
	done

	return 0
}

retr_fwcnt()
{
	local _rnode="${1}" _jname=

	[ -z "${_rnode}" ] && return 0

	[ ! -f "${dbdir}/${_rnode}.sqlite" ] && return 0

	if [ -z "${jname}" ]; then
		_jname=$( /usr/local/bin/cbsd -c "cbsdsqlro ${_rnode} SELECT jname FROM jails WHERE status\<2" )
	else
		_jname=${jname}
	fi

	[ -z "${_jname}" ] && return 0

	for _i in ${_jname}; do
		[ ! -d "${dbdir}/fwcnt/${_rnode}-${_i}" ] && ${MKDIR_CMD} -p "${dbdir}/fwcnt/${_rnode}-${_i}"
		_res=$( nodescp ${checkforonline} ${_rnode}:jails-system/${_i}/traffic/* ${dbdir}/fwcnt/${_rnode}-${_i}/ 2>/dev/null )
		_ret=$?
		if [ ${_ret} -ne 0 ]; then
			${ECHO} "nodescp failed [skipped]: ${_res}"
			continue
		fi
		${CHMOD_CMD} 0640 ${dbdir}/fwcnt/${_rnode}-${_i}/*
		${CHOWN_CMD} ${cbsduser} ${dbdir}/fwcnt/${_rnode}-${_i}/* 2>/dev/null
	done

	return 0
}


# MAIN #
[ -z "${data}" ] && data="db jdescr nodedescr rctl bhyve jail qemu xen"
if [ -z "${tryoffline}" ]; then
	tryoffline=0
	checkforonline="tryoffline=0"
else
	checkforonline="tryoffline=${tryoffline}"
fi

if [ -z "${node}" ]; then
	sqldelimer=" "
	node=$( cbsdsqlro nodes select nodename from nodelist 2>/dev/null )
	unset sqldelimer
fi

# check node online and repopulate array of online nodes if needed
if [ ${sqlreplica} -eq 1 -a ${tryoffline} -eq 0 ]; then
	testnode="${node}"
	node=
	for i in ${testnode}; do
		NODEDATA=$( cbsdsqlro nodes "SELECT ip,port,keyfile FROM nodelist WHERE nodename='${i}'" )
		sqllist "${NODEDATA}" myip myport mykey
		if ! check_locktime ${ftmpdir}/shmux_${myip}.lock >/dev/null 2>&1; then
			${ECHO} "${N1_COLOR}Node is offline: ${N2_COLOR}${i}${N0_COLOR}"
			continue
		fi
		node="${node} ${i}"
	done
fi

for i in ${node}; do
	for items in ${data}; do
		case "${items}" in
			db)
				retr_db ${i}
				;;
			nodedescr)
				retr_nodedescr ${i}
				;;
			jdescr)
				retr_jdescr ${i}
				;;
			# rctl)
			# retr_rctl ${i}
			# ;;
			fwcnt)
				retr_fwcnt ${i}
				;;
			bhyve|xen|qemu)
				retr_vm ${i} ${items}
				;;
			jail)
				retr_jail ${i}
				;;
		esac
	done
done

exit 0
