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

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

restart=0
init $*

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

[ -z "${cbsd_queue_name}" ] && cbsd_queue_name="/clonos/bhyvevms/"
DST="${jaildatadir}/${new}-${jaildatapref}"
SRC="${jaildatadir}/${old}-${jaildatapref}"
JAILDIR="${jaildir}/${new}"
JAILFSTAB="${jailfstabdir}/${jailfstabpref}${new}"
JAILFSTABORIG="${jailfstabdir}/${jailfstabpref}${old}"
JAILLOCALFSTAB="${jailfstabdir}/${jailfstabpref}${new}.local"
JAILLOCALFSTABORIG="${jailfstabdir}/${jailfstabpref}${old}.local"
SYSDIROLD="${jailsysdir}/${old}"
SYSDIRNEW="${jailsysdir}/${new}"

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

jname="${old}"
. ${jrcconf}

[ -z "${host_hostname_new}" ] && host_hostname_new="${host_hostname}"
[ -z "${ip4_addr_new}" ] && ip4_addr_new="${ip4_addr}"
[ "${emulator}" != "bhyve" ] && err 1 "${MAGENTA}Not bhyve mode${NORMAL}"

st_time=$( /bin/date +%s )

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

if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
	[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${old}" jname="${new}" cmd=brename status=1
fi

oldjid=${status}

case ${status} in
	0)
		;;
	*)
		if [ ${restart} -eq 1 ]; then
			cbsdlogger NOTICE ${CBSD_APP}: vm ${jname} will be stopped due to restart flags on
			bstop jname=${old}
		else
			if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
				[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" jname="${new}" cmd=brename status=2
			fi
			log_err 1 "${MAGENTA}VM is online. Please stop them: ${GREEN}${old}${MAGENTA} or add ${GREEN}restart=1${MAGENTA} to auto stop and start VM during rename${NORMAL}"
		fi
		;;
esac

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

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

[ ! -d "${JAILDIR}" ] && /bin/mkdir -p ${JAILDIR}
[ ! -d "${jailfstab}"  ] && /bin/mkdir -p ${jailfstabdir}

printf "${MAGENTA}Rename${NORMAL}"

if [ -f "${JAILFSTABORIG}" ]; then
	/bin/mv ${JAILFSTABORIG} ${JAILFSTAB}
	/usr/bin/sed -i '' s:/${old}:/${new}:g ${JAILFSTAB}
fi

[ -f "${JAILLOCALFSTABORIG}" ] && /bin/mv ${JAILLOCALFSTABORIG} ${JAILLOCALFSTAB} && dot "mv fstablocal"

cbsdsql local UPDATE jails SET jname=\"${new}\",path=\"${jaildir}/${new}\",mount_fstab=\"${jailfstabdir}/${jailfstabpref}${new}\",data=\"${jaildatadir}/${new}-${jaildatapref}\",rcconf=\"${jailrcconfdir}/rc.conf_${new}\" WHERE jname=\"${old}\"
cbsdsql local UPDATE rctl SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null
cbsdsql local UPDATE bhyve SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null
cbsdsql ${jailsysdir}/${jname}/local.sqlite UPDATE bhyvedsk SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null
cbsdsql ${jailsysdir}/${jname}/local.sqlite UPDATE bhyvenic SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null

#
# rename ppt
if [ "${new}" = "ppt" ]; then
	# sqlite3 use name of columt to insert data?? when new="ppt", we got 'ppt' value from column as jname, bug?
	cbsdsql local UPDATE bhyveppt SET jname=\'ppt\' WHERE jname=\"${old}\" 2>/dev/null
else
	cbsdsql local UPDATE bhyveppt SET jname=\"${new}\" WHERE jname=\"${old}\" 2>/dev/null
fi

if [ -n "${ip4_addr_new}" ]; then
	cbsdsql local UPDATE jails SET ip4_addr=\"${ip4_addr_new}\" WHERE jname=\"${new}\"
fi

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

jname=${new}
mvdata ${SRC} ${DST}
dot "mvdata"

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

		# additional loop to check for symlink and zvol
		for i in $( /usr/bin/find ${DST}/ -type l -depth 1 -maxdepth 1 ); do
			if is_getzvol ${i}; then
				old_zvol="${is_zvol}"
				new_zvol=$( echo ${is_zvol} |/usr/bin/sed s:${old}:${new}:g )
				/sbin/zfs rename ${old_zvol} ${new_zvol}
				/bin/ln -sf /dev/zvol/${new_zvol} ${i}
			fi
		done
	;;
esac

for i in $( /usr/bin/find ${DST}/ -type l -or -type f -depth 1 -maxdepth 1 -name dsk\* ); do
	mydsk=$( /usr/bin/basename ${i} );
	[ -z "${mydsk}" ] && continue
	media mode=register name="hdd-${mydsk}" path="${i}" type="hdd" jname="${jname}"
done

if [ -d "$SYSDIROLD" ]; then
	/bin/mv $SYSDIROLD ${SYSDIRNEW}
	[ -r ${jailsysdir}/${jname}/local.sqlite ] && cbsdsql ${jailsysdir}/${jname}/local.sqlite "UPDATE bhyvedsk set jname=\"${jname}\""
	[ -r ${jailsysdir}/${jname}/local.sqlite ] && cbsdsql ${jailsysdir}/${jname}/local.sqlite "UPDATE bhyvenic set jname=\"${jname}\""
fi

if [ ${restart} -eq 1 -a ${oldjid} -ne 0 ]; then
	cbsdlogger NOTICE ${CBSD_APP}: vm ${jname} will be started due to restart flags on
	bstart jname=${new}
	data_status=1
else
	data_status=0
fi

if [ -x "${moduledir}/cbsd_queue.d/cbsd_queue" ]; then
	[ "${cbsd_queue_name}" != "none" ] && cbsd_queue cbsd_queue_name=${cbsd_queue_name} id="${new}" cmd=brename status=2 data_status=${data_status}
fi

[ -d "${SRC}" ] && /bin/rmdir ${SRC}

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

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