#!/bin/sh
### BEGIN INIT INFO
# Provides:          nfsroot
# Required-Start:    $all
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:
# Short-Description: NFSROOT setup
# Description:       NFSROOT setup
### END INIT INFO

umask 002

export PATH=$PATH:$LKP_SRC/bin:$LKP_SRC/sbin

. $LKP_SRC/lib/bootstrap.sh
. $LKP_SRC/lib/http.sh
. $LKP_SRC/lib/reboot.sh
. $LKP_SRC/lib/ucode.sh
. $LKP_SRC/lib/env.sh

echo "export PATH=\$PATH:$PATH" >> $(shell_profile)

# https://stackoverflow.com/questions/19100708/mongodb-mongorestore-failure-localefacet-s-create-c-locale-name-not-valid
# To fix:
# terminate called after throwing an instance of 'std::runtime_error'
#  what():  locale::facet::_S_create_c_locale name not valid
[ -z "$LC_ALL" ] && locale -a 2>/dev/null | grep -qw C.UTF-8 && export LC_ALL=C.UTF-8

is_docker || {
	# disable oom killing entirely for the task
	cat > /proc/$$/oom_score_adj <<EOF
-1000
EOF
}

boot_init || {
	echo "LKP: rebooting due to boot init failure"
	set_tbox_wtmp 'rebooting'
	start_reboot_watchdog
	reboot_tbox 2>/dev/null && exit 1
}

# when to not reboot is a policy issue, which can be refined later.
# here just serves as an example only.
# FIXME: need to consider more factors, such as cmdline, boot_parameter
job_does_not_need_reboot()
{
	grep -q "^do_not_reboot: 1$" $job && {
		echo "LKP: [do_not_reboot] start a new job without rebooting"
		return 0
	}

	grep -q "^do_not_reboot_for_same_kernel: 1$" $job &&
	is_same_kernel_and_rootfs && is_same_suite && is_same_bp_memmap && {
		echo "LKP: [do_not_reboot_for_same_kernel] start a new job without rebooting"
		return 0
	}

	return 1
}

job_force_reboot()
{
	grep -q "^force_reboot: 1$" $job && return 0
	grep -q "^do_not_reboot: 1$" $job || return 0

	return 1
}

reboot_for_next_job()
{
	grep -q "^reboot_for_next_job: \+1$" $job
}

start_reboot_watchdog()
{
	[ -n "$boot_timeout" ] || return
	[ -f /var/lock/bmc-watchdog ] && return

	bmc-watchdog --set --start-after-set -i $boot_timeout
}

downgrade_ucode()
{
	local next_version=$(awk '/^ucode: /{print $2}' $job | tr -d "'")
	ucode_less_than_current $next_version
}

download_install_cgz()
{
	local url
	for url
	do
		echo "download $url"
		http_get_file $url /tmp/tmp.cgz
		(
			cd /
			gzip -dc /tmp/tmp.cgz | cpio -id
		)
	done
	rm -f /tmp/tmp.cgz
}

install_proxy_yum()
{
	echo "proxy=http://$SQUID_HOST:$SQUID_PORT" >> /etc/yum.conf
	if ls /etc/yum.repos.d/*.repo >/dev/null 2>&1; then
		sed -i 's/https:/http:/g' /etc/yum.repos.d/*.repo
	fi

	return 0
}

install_proxy_apt()
{
	cat << EOF > /etc/apt/apt.conf.d/proxy
Acquire::http::proxy "http://$SQUID_HOST:$SQUID_PORT/";
Acquire::ftp::proxy "ftp://$SQUID_HOST:$SQUID_PORT/";
EOF

	for cfg in /etc/apt/sources.list /etc/apt/sources.list.d/*
	do
		[ -f "$cfg" ] || continue
		sed -i 's/https:/http:/g' $cfg
	done

	return 0
}

install_docker_proxy()
{
	[ -n "$DOCKER_PROXY_HOST" ] || return 0
	[ -n "$DOCKER_PROXY_PORT" ] || return 0

	mkdir -p /etc/pki/ca-trust/source/anchors
	curl http://$DOCKER_PROXY_HOST:$DOCKER_PROXY_PORT/ca.crt > \
		/etc/pki/ca-trust/source/anchors/docker_registry_proxy.crt || return

	mkdir -p /etc/systemd/system/docker.service.d
	cat << EOF > /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTPS_PROXY=http://$DOCKER_PROXY_HOST:$DOCKER_PROXY_PORT/"
EOF

	update-ca-trust extract

	systemctl daemon-reload
	has_cmd docker && systemctl restart docker.service

	return 0
}

modify_gem_source()
{
       echo ':sources: ["http://rubygems.org"]' >> /root/.gemrc
}

install_goproxy()
{
	mkdir -p /root/.config/go/ || return
	echo "GOPROXY=https://goproxy.io,direct" >> /root/.config/go/env
}

install_http_proxy()
{
	local shell_profile=$(shell_profile)
	[ -n "$HTTP_PROXY" ]  && echo "export http_proxy=$HTTP_PROXY"   >> "$shell_profile"
	[ -n "$HTTPS_PROXY" ] && echo "export https_proxy=$HTTPS_PROXY" >> "$shell_profile"
	[ -n "$NO_PROXY" ]    && echo "export no_proxy=$NO_PROXY"       >> "$shell_profile"
	source "$shell_profile"
}

install_proxy()
{
	modify_gem_source || return

	install_http_proxy
	install_docker_proxy

	install_goproxy || return

	[ -z "$SQUID_HOST" ] && return
	[ -z "$SQUID_PORT" ] && return

	if [ -d "/etc/yum/" ]; then
		install_proxy_yum
	elif [ -d "/etc/apt/" ]; then
		install_proxy_apt
	else
		:
	fi
}

# Save the result to
# "/srv/initrd/pkg/$os/$os_arch/$os_version/$benchmark.cgz",
# get the result through download $initrd_pkgs.
define_files_pkg_pack()
{
	(
		local benchmark=${1#pkg/}
		export benchmark=${benchmark%/PKGBUILD}
		$LKP_SRC/tests/cci-makepkg
	)
}

# There may be $program-dev or $program-dev-dev in the
# "$LKP_SRC/distro/depends" directory,
# when the value passed by $define_files is "distro/depends/$program-dev",
# you don't know which script in "cci-makepkg" or "cci-depends" to execute,
# so it needs to be handled sparately.
# Save the result to
# "/srv/initrd/deps/$os/$os_arch/$os_version/$deps_benchmark.cgz",
# get the result through download $initrd_deps.
define_files_deps_pack()
{
	local deps_benchmark=${1##*/}
	local pkg_benchmark=${deps_benchmark%-dev}
	local suffix=${deps_benchmark##*-}

	[ $suffix == "dev" ] && [ -f "$LKP_SRC/pkg/$pkg_benchmark/PKGBUILD" ] && {
		(
			export benchmark=$pkg_benchmark
			$LKP_SRC/tests/cci-makepkg
		)
		return 0
	}

	(
		export benchmark=$deps_benchmark
		export pack_arch=$os_arch
		$LKP_SRC/tests/cci-depends
	)
}

# $define_files may be like this:
# "pkg/$program/PKGBUILD distro/depends/$program distro/depends/$program-dev".
define_files_auto_pack()
{
	[ "$suite" = "cci-makepkg" ] && return
	[ "$suite" = "cci-depends" ] && return

	for path
	do
		[ -f "$LKP_SRC/$path" ] || continue

		[ ${path##*/} = PKGBUILD ] && {
			define_files_pkg_pack $path
		}
		[ ${path#distro/depends/} != $path ] && {
			define_files_deps_pack $path
		}
	done
}

chmod_root_ssh()
{
	[ -d "/root/.ssh" ] || return
	[ -f "/root/.ssh/id_rsa" ] || return
	chmod 700 /root/.ssh/
	chmod 600 /root/.ssh/id_rsa
}

install_proxy || exit_with_job_state 'error:proxy'
chmod_root_ssh

while true; do
	set_tbox_wtmp 'running'
	. $job_script define_files
	define_files_auto_pack $define_files
	if [ "$os_mount" != "initramfs" ]; then
		download_install_cgz $initrd_deps
		download_install_cgz $initrd_pkgs
	fi
	install_rpms
	install_deb
	install_pkgs

	echo $LKP_DEBUG_PREFIX $LKP_SRC/bin/run-lkp
	$LKP_DEBUG_PREFIX $LKP_SRC/bin/run-lkp $job

	is_docker && {
		echo "LKP: exiting"
		exit
	}
	
	if tbox_cant_kexec || job_force_reboot; then
		echo "LKP: rebooting forcely"
		set_tbox_wtmp 'rebooting'
		# Avoid get stuck in yocto minimal rootfs.
		# LKP: rebooting
		# [    8.124081] LKP: rebooting
		# # (shell prompt)
		is_virt && [ -e '/proc/sysrq-trigger' ] && {
			sync
			echo s > /proc/sysrq-trigger
			echo b > /proc/sysrq-trigger
		}

		start_reboot_watchdog
		reboot_tbox 2>/dev/null && exit
	fi

	if [ -n "$LKP_DEBUG" ]; then
		# To debug what left from last run
		set -x
		ps faux 2>/dev/null || ps
		ls -l /tmp/
		ls -l /tmp/lkp
		lsmod
	fi

	reboot_for_next_job
	need_reboot=$?

	next_job
	rsync_rootfs
	[ "$need_reboot" -eq 0 ] && break
	job_does_not_need_reboot || break
done

if downgrade_ucode; then
	echo "reboot tbox to downgrade ucode"
	set_job_state 'downgrade_ucode'
	sleep 5
	reboot_tbox 2>/dev/null && exit
fi

set_tbox_wtmp 'kexec_to_next_job'
$LKP_SRC/bin/kexec-lkp ${pxe_user:-lkp} $NEXT_JOB
