#!/usr/local/bin/cbsd
#v12.1.6
MYARG="old new"
MYOPTARG="host_hostname ip4_addr restart"
MYDESC="Rename jail"
CBSDMODULE="jail"
EXTHELP="wf_jrename"
ADDHELP="restart=1 - for online jails. Force to stop if online, rename and start again\n"

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

restart=0

. ${cbsdinit}

[ -z "${old}" ] && err 1 "${N1_COLOR}Give me old jname${N0_COLOR}"
[ -z "${new}" ] && err 1 "${N1_COLOR}Give me new jname${N0_COLOR}"

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

if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	readconf cbsd_queue.conf
	[ -z "${cbsd_queue_backend}" ] && MOD_CBSD_QUEUE_DISABLED="1"
fi

DST="${jaildatadir}/${new}-${jaildatapref}"
SRC="${jaildatadir}/${old}-${jaildatapref}"
JAIL_DIR="${jaildir}/${new}"

JAIL_FSTAB_LEGACY="${jailfstabdir}/${jailfstabpref}${new}"		# legacy/new fstab location, < CBSD 12.1.5
JAIL_FSTAB_ORIG_LEGACY="${jailfstabdir}/${jailfstabpref}${old}"		# legacy/old fstab location, < CBSD 12.1.5
JAIL_LOCAL_FSTAB_LEGACY="${jailfstabdir}/${jailfstabpref}${new}.local"	# legacy/new fstab.local location, < CBSD 12.1.5
JAIL_LOCAL_FSTAB_ORIG="${jailfstabdir}/${jailfstabpref}${old}.local"	# legacy/old fstab.local location, < CBSD 12.1.5

JAIL_FSTAB_DIR_OLD="${jailfstabdir}/${old}"				# old jail fstab dir, CBSD > 12.1.5
JAIL_FSTAB_DIR_NEW="${jailfstabdir}/${new}"				# new jail fstab dir, CBSD > 12.1.5

JAIL_SYS_DIR_OLD="${jailsysdir}/${old}"					# old jails-system environment directory
JAIL_SYS_DIR_NEW="${jailsysdir}/${new}"					# new jails-system environment directory

# store new params in tmp variable
host_hostname_new="${host_hostname}"
ip4_addr_new="${ip4_addr}"

oldjid=$( cbsdsqlro local SELECT jid FROM jails WHERE jname=\"${old}\" 2>/dev/null )
[ -z "${oldjid}" ] && err 1 "${N1_COLOR}No such jail: ${N2_COLOR}${old}${N0_COLOR}"

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

if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	[ -n "${cbsd_jail_queue_name}" ] && ${cbsd_queue_backend} cbsd_queue_name=${cbsd_jail_queue_name} id="${old}" jname="${new}" cmd=jrename ip4_addr="${ip4_addr_new}" status=1
fi

case ${oldjid} in
	0)
		;;
	*)
		if [ ${restart} -eq 1 ]; then
			jstop jname=${old}
		else
			if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
				[ -n "${cbsd_jail_queue_name}" ] && ${cbsd_queue_backend} cbsd_queue_name=${cbsd_jail_queue_name} id="${new}" jname="${new}" cmd=jrename ip4_addr="${ip4_addr_new}" status=2
			fi

			err 1 "${N1_COLOR}Jail is online. Please stop them: ${N2_COLOR}${old}${N1_COLOR} or add ${N2_COLOR}restart=1${N1_COLOR} to auto stop and start jail during rename${N0_COLOR}"
		fi
		;;
esac

jname="${old}"
. ${subrdir}/rcconf.subr

[ -z "${host_hostname_new}" ] && host_hostname_new="${host_hostname}"
[ -z "${ip4_addr_new}" ] && ip4_addr_new="${ip4_addr}"

[ "${emulator}" = "bhyve" ] && err 1 "${N1_COLOR}Jail in bhyve mode. Use ${N2_COLOR}cbsd brename${N1_COLOR} instead${N0_COLOR}"
[ ! -d "${SRC}" ] && err 1 "${N1_COLOR}No jail data: ${N2_COLOR}${SRC}${N0_COLOR}"

if [ -d "${DST}" ]; then
	${RMDIR_CMD} ${DST} >/dev/null 2>&1
	[ -d "${DST}" ] && err 1 "${N1_COLOR}Jail data already exist and it not empty: ${N2_COLOR}${DST}${N0_COLOR}"
fi

printf "${N1_COLOR}Rename${N0_COLOR}"

jcleanup jname=${old}
# todo: cleanup errcode, fstat/lsof check
# all set for rename

[ ! -d "${JAIL_DIR}" ] && ${MKDIR_CMD} -p ${JAIL_DIR}
[ ! -d "${jailfstab}"  ] && ${MKDIR_CMD} -p ${jailfstabdir}

# CBSD > 12.1.5
if [ -d ${JAIL_FSTAB_DIR_OLD} ]; then
	${MV_CMD} ${JAIL_FSTAB_DIR_OLD} ${JAIL_FSTAB_DIR_NEW}
	[ -r ${JAIL_FSTAB_DIR_NEW}/fstab ] && ${SED_CMD} -i${SED_DELIMER}'' s:/${old}:/${new}:g ${JAIL_FSTAB_DIR_NEW}/fstab
	[ -r ${JAIL_FSTAB_DIR_NEW}/fstab.local ] && ${SED_CMD} -i${SED_DELIMER}'' s:/${old}:/${new}:g ${JAIL_FSTAB_DIR_NEW}/fstab.local
else
	[ ! -d ${JAIL_FSTAB_DIR_NEW} ] && ${MKDIR_CMD} -p ${JAIL_FSTAB_DIR_NEW}
fi

# check for legacy ( CBSD < 12.1.5) fstabs file
if [ -r "${JAIL_FSTAB_ORIG_LEGACY}" ]; then
	${SED_CMD} s:/${old}:/${new}:g ${JAIL_FSTAB_ORIG_LEGACY} > ${JAIL_FSTAB_DIR_NEW}/fstab
	${RM_CMD} ${JAIL_FSTAB_ORIG_LEGACY}
fi
if [ -r "${JAIL_LOCAL_FSTAB_ORIG_LEGACY}" ]; then
	${SED_CMD} s:/${old}:/${new}:g ${JAIL_LOCAL_FSTAB_ORIG_LEGACY} > ${JAIL_FSTAB_DIR_NEW}/fstab.local
	${RM_CMD} ${JAIL_LOCAL_FSTAB_ORIG_LEGACY}
fi

case "${ip4_addr_new}" in
	[Dd][Hh][Cc][Pp])
		dhcpip=$( dhcpd )
		[ $? -eq 2 ] && err 1 "${N1_COLOR}No free IP address for DHCP in nodeippool${N0_COLOR}"
		[ -z "${dhcpip}" ] && err 1 "${N1_COLOR}Unable to dhcpd${N0_COLOR}"
		ipwmask ${dhcpip}
		[ -z "${IWM}" ] && err 1 "${N1_COLOR}Unable IWM for dhcpd${N0_COLOR}"
		iptype ${IWM}
		[ $? -eq 0 ] && err 1 "${N1_COLOR}Not ip from dhcpd?: ${dhcpip} / ${IWM}"
		ip4_addr_new="${dhcpip}"
		${ECHO} "${N1_COLOR}Selected IP: ${N2_COLOR}${ip4_addr_new}${N0_COLOR}"
		;;
esac

cbsdsqlrw local UPDATE jails SET jname=\"${new}\",path=\"${jaildir}/${new}\",mount_fstab=\"${JAIL_FSTAB_DIR_NEW}/fstab\",data=\"${jaildatadir}/${new}-${jaildatapref}\",rcconf=\"${jailrcconfdir}/rc.conf_${new}\" WHERE jname=\"${old}\"
cbsdsqlrw local UPDATE rctl SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null

cbsdsqlrw local UPDATE jails SET ip4_addr=\"${ip4_addr_new}\" WHERE jname=\"${new}\"
cbsdsqlrw local UPDATE jails SET host_hostname=\"${host_hostname_new}\" WHERE jname=\"${new}\"

if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	[ -n "${cbsd_jail_queue_name}" ] && ${cbsd_queue_backend} cbsd_queue_name=${cbsd_jail_queue_name} id="${new}" cmd=update ip4_addr="${ip4_addr_new}" host_hostname="${host_hostname}" status=1
fi

jname=${new}

if [ ${zfsfeat} -eq 1 ]; then
	. ${subrdir}/zfs.subr
	zfsmnt ${SRC}
	_err=$?

	if [ ${_err} -eq 1 -o ${_err} -eq 2 ]; then
		# rename snapshots tag first
		zfs_snapshot_rename ${old} ${new}
	fi
fi

mvdata ${SRC} ${DST}
dot "mvdata"

#rename zfs fs source
case ${zfsfeat} in
	1)
		zfsmnt ${DST}
		_err=$?
		if [ ${_err} -eq 2 -o ${_err} -eq 1 ]; then
			OLDPOOL=$ZPOOL
			DATA=$( ${ZFS_CMD} get -Ho value name ${jaildatadir} )
			NEWPOOL="${DATA}/${new}"
			if [ ${_err} -eq 1 ]; then
				# we need unmount this first
				${ZFS_CMD} unmount -f ${DST}
				sleep 5  #Hack - sometimes we got "cannot rename: dataset is busy"
				${ZFS_CMD} unmount -f ${DST} >/dev/null 2>&1
			fi
			zfs rename ${OLDPOOL} ${NEWPOOL}
			if [ $? -eq 0 ]; then
				${ZFS_CMD} mount ${NEWPOOL}
				[ -d ${SRC} ] && rmdir ${SRC}
			fi
		fi
		;;
esac

[ -d "${JAIL_SYS_DIR_OLD}" ] && ${MV_CMD} ${JAIL_SYS_DIR_OLD} ${JAIL_SYS_DIR_NEW}
[ -d "${SRC}" ] && ${RMDIR_CMD} ${SRC}

[ ${restart} -eq 1 -a ${oldjid} -ne 0 ] && jstart jname=${new}

myjid=$( cbsdsqlro local SELECT jid FROM jails WHERE jname=\"${new}\" 2>/dev/null )

[ -z "${myjid}" ] && myjid=0

if [ ${myjid} -eq 0 ]; then
	data_status=0
else
	data_status=1
fi

if [ "${mod_cbsd_queue_enabled}" = "YES" -a -z "${MOD_CBSD_QUEUE_DISABLED}" ]; then
	[ -n "${cbsd_jail_queue_name}" ] && ${cbsd_queue_backend} cbsd_queue_name=${cbsd_jail_queue_name} id="${new}" cmd=jrename status=2 data_status=${data_status}
fi

${ECHO} "${N2_COLOR}ok${N0_COLOR}"

end_time=$( ${DATE_CMD} +%s )
diff_time=$(( end_time - st_time ))
diff_time=$( displaytime ${diff_time} )
${ECHO} "${N1_COLOR}${CBSD_APP} done ${N2_COLOR}in ${diff_time}${N0_COLOR}"
cbsdlogger NOTICE ${CBSD_APP}: jail ${old} has been renamed to ${old} in ${diff_time}

exit 0
