#!/bin/sh
# Copyright (c) 2000-2015 Synology Inc. All rights reserved.
. /var/packages/Docker/scripts/pkg_utils
## Get modules list
source /usr/syno/etc.defaults/iptables_modules_list
DockerModules="xt_addrtype.ko xt_conntrack.ko veth.ko macvlan.ko aufs.ko"
DockerBridgeModules="llc.ko stp.ko bridge.ko macvlan.ko"
DockerPIDFile="/var/run/docker.pid"
TermdPIDFile="/var/run/termd.pid"

DockerBinLink="/usr/local/bin/docker"
DockerComposeBinLink="/usr/local/bin/docker-compose"
DockerContainerdBinLink="/usr/local/bin/docker-containerd"
DockerContainerdShimBinLink="/usr/local/bin/docker-containerd-shim"
DockerRuncBinLink="/usr/local/bin/docker-runc"
DockerEnterBinLink="/usr/local/bin/docker-enter"
InsertModules="${KERNEL_MODULES_CORE} ${KERNEL_MODULES_COMMON} ${KERNEL_MODULES_NAT} ${IPV6_MODULES} ${DockerModules} ${DockerBridgeModules}"
DockerServName="docker"
RunningContainerList="/var/packages/Docker/etc/LastRunningContainer"
DeleteDockerDSM="/var/packages/Docker/etc/delete_ddsm/"
SZF_DDSM_CTL_TOOL="/var/packages/Docker/target/tool/ddsmctl"
TargetPath="/var/packages/Docker/target"
DockerBin="$TargetPath/usr/bin/docker"
DockerComposeBin="$TargetPath/usr/bin/docker-compose"
DockerContainerdBin="$TargetPath/usr/bin/docker-containerd"
DockerContainerdShimBin="$TargetPath/usr/bin/docker-containerd-shim"
DockerRuncBin="$TargetPath/usr/bin/docker-runc"
DockerEnterBin="$TargetPath/ddsm/tool/docker-enter"
ContainerDepBin="$TargetPath/tool/container_sort"
TermdBin="$TargetPath/termd/termd"
ShutdownDockerDaemonFlag="/tmp/shutdown_docker_daemon"
SupportBtrfs="$(/bin/get_key_value /etc.defaults/synoinfo.conf support_btrfs)"
IsVDSM="$(/bin/get_key_value /etc.defaults/synoinfo.conf virtual_dsm)"

delete_ddsm()
{
	if [ ! -d "$DeleteDockerDSM" ]; then
		return
	fi

	if [ ! -z "$(ls -A $DeleteDockerDSM)" ]; then
		for DDSM in `ls -A $DeleteDockerDSM`; do
			/bin/rm $DeleteDockerDSM/$DDSM
			SHARE=`$SZF_DDSM_CTL_TOOL --get-share-name-by-ddsm $DDSM`
			if [ $? -eq 1 ] && ! /usr/syno/sbin/synoshare --get $SHARE; then
				#delete the docker dsm
				logger -p user.err "synoddsm: Delete Container $DDSM begin"
				synowebapi --exec api=SYNO.Docker.Container method=delete version=1 name="\"$DDSM\"" is_ddsm=true preserve_profile=false force=false
				logger -p user.err "synoddsm: Delete Container $DDSM end"
				/usr/syno/bin/synodsmnotify @administrators dsmnotify:system_event ddsm:ddsm_remove_by_share_delete $DDSM $SHARE
			fi
		done
	fi
}

wait_for_condition()
{
	local maxTryCount=60
	local timeGap=1
	while eval "$@" >&/dev/null; do
		if [ "${maxTryCount}" -le 0 ]; then
			break
		fi
		maxTryCount="$((maxTryCount-1))"
		sleep "${timeGap}"
	done
}

argument_reverse() {
	local args="$1"
	local arg
	local ret=""

	for arg in ${args}; do
		ret="${arg} ${ret}"
	done

	echo "${ret}"
}

running_container_record() {
	if "${DockerBin}" ps; then
		"${DockerBin}" ps --no-trunc=true | grep -v "SynologyDSM:" |awk '{print $1}' | sed '1 d' > ${RunningContainerList}
	fi
}

running_container_restore() {
	if [ -f ${RunningContainerList} ]; then
		list="$(cat "${RunningContainerList}")"
		if [ "x" != "x${list}" ]; then
			sort_list="$(${ContainerDepBin} ${list})"
			for container in $sort_list
			do
				/usr/syno/bin/synowebapi --exec api=SYNO.Docker.Container method=start version=1 name="${container}"
			done
		fi
		rm -f "${RunningContainerList}"
	fi
}

iptables_clear()
{
	eval $(iptables-save -t nat | grep DOCKER | grep -v "^:"| sed -e 1d -e  's/^-A/iptables -t filter -D/' -e 's/DEFAULT_//' -e 's/$/;/')
	eval $(iptables-save -t filter | grep DOCKER | grep -v "^:"| sed -e 1d -e  's/^-A/iptables -t filter -D/' -e 's/DEFAULT_//' -e 's/$/;/')

	iptables -t nat -X DOCKER
	iptables -t filter -X DOCKER
}

clean_lock_files() {
	rm /var/lock/dockerImage.lock /var/lock/dockerMapping.lock /var/lock/dockerRemoteAPI.lock*
}

umount_aufs() {
	for i in $(grep aufs/mnt /proc/mounts | sed 's@.*aufs/mnt/\(\w*\)@\1@'); do
		umount "${TargetPath}"/docker/aufs/mnt/$i
	done

	if grep -q @docker/aufs /proc/mounts; then
		umount "${TargetPath}"/docker/aufs
	fi
}

has_ddsm() {
	## check if any container use ddsm images
	if ${DockerBin} ps -a | awk '{print $2}' | grep SynologyDSM; then
		return 0
	fi

	return 1
}

case "$1" in
	start)
		[ -d /usr/local/bin ] || mkdir -p /usr/local/bin
		ln -sf "${DockerBin}" "${DockerBinLink}"
		ln -sf "${DockerComposeBin}" "${DockerComposeBinLink}"
		ln -sf "${DockerContainerdBin}" "${DockerContainerdBinLink}"
		ln -sf "${DockerContainerdShimBin}" "${DockerContainerdShimBinLink}"
		ln -sf "${DockerRuncBin}" "${DockerRuncBinLink}"
		ln -sf "${DockerEnterBin}" "${DockerEnterBinLink}"

		# install modules
		iptablestool --insmod "${DockerServName}" ${InsertModules}

		#start docker
		"${DockerBin}" daemon --ipv6=true &

		wait_for_condition [ ! -f "${DockerPIDFile}" ]
		wait_for_condition ! "${DockerBin}" version

		pid="$(cat "${DockerPIDFile}")"
		if ps -p "${pid}"; then
			## delete ddsm which share is deleted during package stop
			delete_ddsm

			## remove ready only bit before ddsm start
			$SZF_DDSM_CTL_TOOL --un-register-share

			## start synoddsm-hostd
			if [ "yes" = "$SupportBtrfs" -a "yes" != "$IsVDSM" ]; then
				start synoddsm-hostd
			fi
			has_ddsm && /usr/syno/bin/synowebapi --exec api=SYNO.Docker.DDSM method=start version=1
			running_container_restore
		else
			rm "${DockerPIDFile}"
			exit 1
		fi

		#start termd
		"$TermdBin" -d

		CreateHelpAndString

		cp -f $TargetPath/config/dsm.docker.conf /usr/local/etc/nginx/conf.d/

		exit 0
		;;

	stop)
		modules="$(argument_reverse "${InsertModules}")"

		/usr/syno/bin/synowebapi --exec api=SYNO.Docker.DDSM method=stop version=1
		rm "${DockerBinLink}"
		rm "${DockerComposeBinLink}"
		rm "${DockerContainerdBinLink}"
		rm "${DockerContainerdShimBinLink}"
		rm "${DockerRuncBinLink}"
		rm "${DockerEnterBinLink}"

		## Kill termd
		if [ -f "$TermdPIDFile" ]; then
			termdPID=$(cat "$TermdPIDFile")
			kill "$termdPID"
			wait_for_condition ps -p "$termdPID"

			## Force kill
			if ps -p "$termdPID"; then
				kill -9 "$termdPID"
				rm "$TermdPIDFile"
				logger -p 0 "Failed to stop termd so we kill"
			fi
		fi

		## Record running container
		running_container_record

		## touch flag to avoid container unexpected stopped false alarm
		touch $ShutdownDockerDaemonFlag
		## Kill docker
		if [ -f "$DockerPIDFile" ]; then
			dockerPID="$(cat "${DockerPIDFile}")"

			kill "${dockerPID}"
			wait_for_condition ps -p "${dockerPID}"

			## Force kill
			if ps -p "${dockerPID}"; then
				kill -9 "${dockerPID}"
				rm "${DockerPIDFile}"
				logger -p 0 "Failed to stop docker so we kill"
			fi
		fi
		## remove flag
		rm -f $ShutdownDockerDaemonFlag

		umount_aufs
		clean_lock_files
		iptables_clear

		## make sure synoddsm-hostd is stop when package stop
		stop synoddsm-hostd

		iptablestool --rmmod "${DockerServName}" ${modules}

		# unload modules load by ddsm
		/usr/syno/synoddsm/scripts/synoddsmhost_util unload-modules

		RemoveHelpAndString

		rm -f /usr/local/etc/nginx/conf.d/dsm.docker.conf

		exit 0
		;;

	status)
		[ -f "$DockerPIDFile" ] && kill -0 "$(cat "$DockerPIDFile")"
		;;

	*)
		exit 1
		;;
esac
