#!/usr/local/bin/cbsd
#v11.1.19
MYARG="old new"
MYOPTARG="verbose ip4_addr host_hostname promote mac_reinit"
MYDESC="Bhyve VM cloning"
CBSDMODULE="bhyve"
ADDHELP="promote - Promotes clone to no longer be dependent from origin: 0 or 1. Default is 0 (not promote)\n\
clone_method - can be 'auto' or 'rsync'. Default is: auto\n\
mac_reinit=0,1 (default 1). 0 - leave old MAC. 1 - set mac to 0 for re-generate new\n"
EXTHELP="wf_bclone.html"

. ${subr}
. ${tools}
. ${jfs}
. ${strings}

mac_reinit=1	# regenerate new MAC by default

init $*

readconf bclone.conf		# read users promote and clone_method settings

[ -z "${promote}" ] && promote=0
[ -z "${clone_method}" ] && clone_method="auto"

[ -z "${cbsd_queue_name}" ] && cbsd_queue_name="/clonos/bhyvevms/"

jname="${old}"
host_hostname_new="${host_hostname}"
ip4_addr_new="${ip4_addr}"

. ${jrcconf}
[ $? -eq 1 ] && err_log 1 "${MAGENTA}No such bhyve: ${GREEN}${jname}${NORMAL}"
[ "${emulator}" != "bhyve" ] && log_err 1 "${MAGENTA}Not in bhyve mode${NORMAL}"
[ ${jid} -ne 0 ] && log_err 1 "${MAGENTA}Bhyve is online. Please stop them: ${GREEN}${old}${NORMAL}"

myjid=$( cbsdsql local SELECT jid FROM jails WHERE jname=\"${new}\" 2>/dev/null )
[ -n "${myjid}" ] && log_err 1 "${MAGENTA}Bhyve already exist: ${GREEN}${new}${NORMAL}"

protected=$( cbsdsql local SELECT protected FROM bhyve WHERE jname=\"${old}\" )
hidden=$( cbsdsql local SELECT hidden FROM bhyve WHERE jname=\"${old}\" )

# CBSD QUEUE
if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
	[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" cmd=bclone status=1 vm_ram="${vm_ram}" vm_os_type="${vm_os_type}" vm_cpus="${vm_cpus}" hidden="${hidden}"
fi

DST="${jaildatadir}/${new}-${jaildatapref}"
SRC="${jaildatadir}/${old}-${jaildatapref}"
JAILDIR="${jaildir}/${new}"
JAILFSTAB="${jailfstabdir}/${jailfstabpref}${new}"
JAILLOCALFSTAB="${jailfstabdir}/${jailfstabpref}${new}.local"
JAILFSTABORIG="${jailfstabdir}/${jailfstabpref}${old}"
JAILLOCALFSTABORIG="${jailfstabdir}/${jailfstabpref}${old}.local"

JAILRCCONF="${tmpdir}/rc.conf_${new}"

JAILRCCONFORIG="${jailrcconfdir}/rc.conf_${old}"
SYSDIROLD="${jailsysdir}/${old}"
SYSDIRNEW="${jailsysdir}/${new}"

printf "${MAGENTA}Cloning.${NORMAL}"
cbsdlogger NOTICE ${CBSD_APP}: start cloning ${old} to ${new}
st_time=$( /bin/date +%s )

if [ -d "${SYSDIROLD}" ]; then
	[ -d "${SYSDIRNEW}" ] && /bin/rm -rf ${SYSDIRNEW}
	/bin/cp -Rp ${SYSDIROLD} ${SYSDIRNEW}
	dot "cp sysdir"
fi

#rename zfs fs source
case ${zfsfeat} in
	1)
		. ${zfstool}
		zfsmnt ${SRC}
		[ $? -eq 2  ] && /sbin/zfs mount ${ZPOOL}
	;;
esac

[ ! -d "${SRC}" ] && log_err 1 "${MAGENTA}No jail data: ${GREEN}${SRC}${NORMAL}"

if [ -d "${DST}" ]; then
	/bin/rmdir ${DST} >/dev/null 2>&1
	[ -d "${DST}" ] && log_err 1 "${MAGENTA}Jail data already exist and it not empty: ${GREEN}${DST}${NORMAL}"
fi

for i in ${JAILDIR} ${jailfstab} ${jailrcconf}; do
	[ ! -d "${i}" ] && /bin/mkdir -p ${i}
done

jmkrcconf jname=${old} > ${JAILRCCONF}

${SYSRC_CMD} -qf ${JAILRCCONF} jname="${new}" > /dev/null 2>&1

jregister rcfile=${JAILRCCONF} jname=${new}
[ -f ${JAILRCCONF} ] && /bin/rm -f ${JAILRCCONF}

if [ -f "${JAILFSTABORIG}" ]; then
	/usr/bin/sed "s/\/${old}/\/${new}/g" ${JAILFSTABORIG} > ${JAILFSTAB}
	dot "fstab"
fi

[ -f "${JAILLOCALFSTABORIG}" ] && /bin/cp ${JAILLOCALFSTABORIG} ${JAILLOCALFSTAB} && dot "cp fstablocal"
cbsdsql local UPDATE jails SET path=\"${jaildir}/${new}\",mount_fstab=\"${jailfstabdir}/${jailfstabpref}${new}\",data=\"${jaildatadir}/${new}-${jaildatapref}\",rcconf=\"${jailrcconfdir}/rc.conf_${new}\",host_hostname=\"${host_hostname_new}\" WHERE jname=\"${new}\"

if [ -n "${ip4_addr_new}" ]; then
	cbsdsql ${jailsysdir}/${new}/local.sqlite UPDATE settings SET ip4_addr=\"${ip4_addr_new}\"
	# back compatible:
	cbsdsql local UPDATE jails SET ip4_addr=\"${ip4_addr_new}\" WHERE jname=\"${new}\"
fi

[ -n "${host_hostname_new}" ] && cbsdsql local UPDATE jails SET host_hostname=\"${host_hostname_new}\" WHERE jname=\"${new}\"

jname=${new}

if [ "${zfsfeat}" != "1" ]; then
	clone_method="rsync"
fi

cbsdlogger NOTICE ${CBSD_APP}: copying method will be used for cloning: ${clone_method}

case ${clone_method} in
	auto)
		clonedata -s ${SRC} -d ${DST} -m zfs -n ${new} -p ${promote}
		;;
	*)
		if [ "${verbose}" = "1" ]; then
			clonedata -s ${SRC} -d ${DST} -m rsync
		else
			clonedata -s ${SRC} -d ${DST} -m rsync > /dev/null 2>&1
		fi
esac

dot "clone rsync"
[ -r ${data}/cbsd.img ] && /bin/rm -f ${data}/cbsd.img

# Re-init all MAC address
if [ ${mac_reinit} -eq 1 ]; then
	#${ECHO} "Re-init MAC address: ${GREEN}${new}${NORMAL}"
	cbsdlogger NOTICE ${CBSD_APP}: re-init MAC address, set to 0: ${new}
	cbsdsql ${jailsysdir}/${new}/local.sqlite "UPDATE bhyvenic SET nic_hwaddr=\"0\""
fi

# CBSD QUEUE
if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
	[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" cmd=bclone status=2 protected="${protected}" hidden="${hidden}" data_status=0 hidden="${hidden}"
fi

end_time=$( /bin/date +%s )
cbsdlogger NOTICE ${CBSD_APP}: vm ${old} has been cloned to ${new} in $(( end_time - st_time ))s

err 0 "${GREEN}ok${NORMAL}"
