#!/bin/sh
#
# $FreeBSD$
#

# PROVIDE: ix-update
# BEFORE: ix-fstab

. /etc/rc.freenas

readonly UPDATE_FAILED_LOG="/data/update.failed"
HBA_FIRMWARE_UPDATE="/data/.hba_firmware_update"
REBOOT_REQUIRED=0

# The function below takes two arguments
# 1. The path you want it to write its output to (the .crt and .key files)
# 2. The old pre-certui database (do not give it the post certmanager migrated db as it will fail)
# It writes the cert file as "precertman.crt" and key file as "precertman.key"
upgrade_cert_migration()
{
    local write_path="${1}"
    local freenas_old_db="${2}"
    local tmpcertfile=$(mktemp /tmp/tmp.XXXXXX)

    ${FREENAS_SQLITE_CMD} ${freenas_old_db} "
    SELECT
           ssl_certfile

    FROM
           system_ssl

    ORDER BY
           -id

    LIMIT 1
           " > "${tmpcertfile}"
    # Now seperate the certs and keys into seperate files
    sed -nE '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----|end/p ' "${tmpcertfile}" > "${write_path}/precertman.crt"
    sed -nE '/-----BEGIN RSA PRIVATE KEY-----/,/-----END RSA PRIVATE KEY-----|end/p' "${tmpcertfile}" > "${write_path}/precertman.key"
}

db_update_real()
{
	echo "Applying database schema changes"

	touch /tmp/.sqlite3_ha_skip
	yes | /usr/local/bin/python \
	    /usr/local/www/freenasUI/manage.py migrate --merge --delete-ghost-migrations > \
		$UPDATE_FAILED_LOG 2>&1
	if [ $? -ne 0 ]; then
		rm -f /tmp/.sqlite3_ha_skip
		echo "manage.py migrate failed"
		return 1
	fi
	rm -f /tmp/.sqlite3_ha_skip
	rm -f $UPDATE_FAILED_LOG
	return 0
}

handle_error()
{
	local LABELNAME OTHER_PARTNUM PARTNUM TARGET_DRIVE

	echo "Reverting to previous state"

	rm -f $NEED_UPDATE_SENTINEL
	mv ${FREENAS_CONFIG}.bak ${FREENAS_CONFIG}
	if [ -f $CD_UPGRADE_SENTINEL ]; then
		rm $CD_UPGRADE_SENTINEL
		cat <<EOF
Database upgrade FAILED; check $UPDATE_FAILED_LOG for more details.
Reverting a failed CD upgrade is not totally possible
Rebooting in 15 seconds..
EOF
		sleep 15
		reboot
	fi

	. /etc/nanobsd.conf

	# Need to be fixed for #4689
	LABELNAME=`echo ${NANO_DRIVE} | cut -f2 -d/`
	if mount | grep ${NANO_DRIVE}s1 > /dev/null ; then
		PARTNUM=1
		OTHER_PARTNUM=2
	else
		PARTNUM=2
		OTHER_PARTNUM=1
	fi
	TARGET_DRIVE=`glabel status | awk '/ufs\/'${LABELNAME}s${PARTNUM}'a/ { print $3; }' | sed -e 's/s.a//'`
	gpart set -a active -i $OTHER_PARTNUM ${TARGET_DRIVE}

	cat <<EOF
Database upgrade FAILED; check $UPDATE_FAILED_LOG for more details.
Rebooting in 15 seconds..
EOF
	sleep 15
	reboot
}

db_update()
{
	local precertman
	if [ -f ${HBA_FIRMWARE_UPDATE} ]; then
		mount -uw /
		if [ -f /usr/local/sbin/firmware_update.py ]; then
			LD_LIBRARY_PATH=/usr/local/lib /usr/local/bin/python /usr/local/sbin/firmware_update.py
			if [ $? -eq 0 ]; then
				# A reboot will be required, but we'll hold off
				# on that and do database upgrades if they need
				# to be done as well to avoid a double reboot.
				REBOOT_REQUIRED=1
			fi
		else
			# The auto firmware update tool is only in TrueNAS
			# FreeNAS users will mostly be happy that FreeNAS doesn't
			# muck with their HBA firmware...because the chance of bricking
			# a random card is a non-zero number.  (Besides, tracking down
			# the firmware for every embedded Avago card out there is not
			# realistic.)
			rm ${HBA_FIRMWARE_UPDATE}
		fi
	fi
			
	if [ ! -f $NEED_UPDATE_SENTINEL ]; then
		if [ ${REBOOT_REQUIRED} -eq 1 ]; then
			reboot
		fi
		# exit this script and continue with normal boot.
		exit 0
	fi

	# We are running very early, make / read-write.
	mount -uw /
	echo "Saving current ${FREENAS_CONFIG} to ${FREENAS_CONFIG}.bak"
	cp ${FREENAS_CONFIG} ${FREENAS_CONFIG}.bak

	if [ -f /data/uploaded.db ]; then
		echo "Moving uploaded config to ${FREENAS_CONFIG}"
		mv /data/uploaded.db ${FREENAS_CONFIG}
		if [ "$(/usr/local/bin/python /usr/local/www/freenasUI/middleware/notifier.py pwenc_check 2> /dev/null)" != "True" ]; then
			/usr/local/bin/python /usr/local/www/freenasUI/middleware/notifier.py pwenc_generate_secret > /dev/null
		fi
	fi

	# The call below checks if the version of freenas we are updating form is
	# a pre-cert-UI version or not and stores its result in a local var.
	${FREENAS_SQLITE_CMD} ${FREENAS_CONFIG} "select * from system_ssl;" > /dev/null 2>&1
	precertman=$?
	if [ "${precertman}" == 0 ]; then
		# The step below will parse and write the old cert and key to /root/precertman.crt/.key
		upgrade_cert_migration "/root" ${FREENAS_CONFIG}
	fi

	set +e
	db_update_real || handle_error
	set -e

	rm -f $NEED_UPDATE_SENTINEL
	rm -f $CD_UPGRADE_SENTINEL

	# remove ${FIRST_INSTALL_SENTINEL} from this loader call
	rm -f ${FIRST_INSTALL_SENTINEL}
	# NOTE: this must be run via the rc.d script, not service(8).
	env AUTOTUNE_REBOOT=false /etc/ix.rc.d/ix-loader start
	# we need it for the ix-loader service call later on
	touch ${FIRST_INSTALL_SENTINEL}

	echo "Database upgrade complete.  Rebooting."
	cd /
	if [ "${precertman}" == 0 ]; then
		# Now that the migration is done we just take the earlier saved cert and key
		# and add it to the current scheme of things (the call to the python code below
		# does that) after it is done delete the precertman.crt and .key files
		/usr/local/bin/python /usr/local/www/freenasUI/tools/updatessl.py /root/precertman.crt /root/precertman.key >/dev/null 2>&1
	fi
	rm -f /root/precertman.*
	sleep 2
	reboot
}

name="ix-update"
start_cmd='db_update'
stop_cmd=':'

load_rc_config $name
run_rc_command "$1"
