#!/usr/local/bin/cbsd
#v10.0.10
MYARG="old new host_hostname"
MYOPTARG="ip4_addr checkstate verbose promote clone_method"
MYDESC="Jail cloning"
CBSDMODULE="jail"
ADDHELP="ip4_addr - can be DHCP\n\
checkstate - 0 do not check for jail online. Default is 1 - check\n\
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"
EXTHELP="wf_jclone.html"

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

checkstate=1

readconf jclone.conf		# read users promote and clone_method settings

init $*

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

myjid=$( cbsdsql local SELECT jid FROM jails WHERE jname=\"${old}\" 2>/dev/null )
[ -z "${myjid}" ] && err 1 "${MAGENTA}No such jail: ${GREEN}${old}${NORMAL}"

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

if [ ${checkstate} -eq 1 ]; then
	[ $myjid -ne 0 ] && err 1 "${MAGENTA}Jail is online. Please stop them: ${GREEN}${old}${NORMAL}"
fi

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

jname="${old}"

protected=$( cbsdsql local SELECT protected FROM jails 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=jclone ip4_addr="${ip4_addr}" protected="${protected}" status=1
fi

case "${ip4_addr}" in
	[Dd][Hh][Cc][Pp])
		dhcpip=$( dhcpd )
		[ $? -eq 2 ] && err 1 "${MAGENTA}No free IP address for DHCP in nodeippool${NORMAL}"
		[ -z "${dhcpip}" ] && err 1 "${MAGENTA}Unable to dhcpd${NORMAL}"
		ipwmask ${dhcpip}
		[ -z "${IWM}" ] && err 1 "${MAGENTA}Unable IWM for dhcpd${NORMAL}"
		iptype ${IWM}
		[ $? -eq 0 ] && err 1 "${MAGENTA}Not ip from dhcpd?: ${dhcpip} / ${IWM}"
		ip4_addr="${dhcpip}"
		${ECHO} "${MAGENTA}Selected IP: ${GREEN}${ip4_addr}${NORMAL}"
		if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
			[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" cmd=update ip4_addr="${ip4_addr}" status=1
		fi
		;;
	*)
		[ -z "${ip4_addr}" ] && ip4_addr=$( cbsdsql local SELECT ip4_addr FROM jails WHERE jname=\"${old}\" )
		if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
			[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" cmd=update ip4_addr="${ip4_addr}" status=1
		fi
		;;
esac

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

. ${jrcconf}
[ "${emulator}" = "bhyve" ] && err 1 "${MAGENTA}Jail in bhyve mode. Use ${GREEN}cbsd brename${MAGENTA} instead${NORMAL}"

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="${jailrcconfdir}/rc.conf_${new}"
JAILRCCONFORIG="${jailrcconfdir}/rc.conf_${old}"
SYSDIROLD="${jailsysdir}/${old}"
SYSDIRNEW="${jailsysdir}/${new}"

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

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

if [ -d "${DST}" ]; then
	/bin/rmdir ${DST} >/dev/null 2>&1

	# 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=jclone status=2 data_status=0
	fi

	[ -d "${DST}" ] && 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

printf "${MAGENTA}Cloning.${NORMAL}"
jmkrcconf jname=${old} > ${JAILRCCONF}

${SYSRC_CMD} -qf ${JAILRCCONF} jname="${new}" > /dev/null 2>&1
# set status to offline if original jail was active
${SYSRC_CMD} -qf ${JAILRCCONF} status="0" > /dev/null 2>&1

jregister jname=${new}

/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}\" WHERE jname=\"${new}\"

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

jname=${new}

[ "${zfsfeat}" != "1" ] && clone_method="rsync"

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"

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

#rctl
LIMITS="${jailsysdir}/${old}/jail.limits"
jmkrctlconf jname=${old} type=rctl mode=tofile file=${LIMITS}
jmkrctlconf jname=${old} type=extra mode=tofile file=${LIMITS}.extra
jmkrctlconf jname=${new} type=rctl mode=tosql file=${LIMITS}
jmkrctlconf jname=${new} type=extra mode=tosql file=${LIMITS}.extra
#

# 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=jclone status=2 data_status=0
fi

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