#!/bin/sh
# - tbox_group
# - nr_container
# - queues

# SPDX-License-Identifier: MulanPSL-2.0+
# Copyright (c) 2020 Huawei Technologies Co., Ltd. All rights reserved.

. $LKP_SRC/lib/log.sh
. $LKP_SRC/lib/env.sh

: ${queues:="$tbox_group.$HOSTNAME,$tbox_group.$(arch)"}

prepare_sysctl()
{
	sysctl -w fs.inotify.max_user_instances="12800"
	sysctl -w fs.inotify.max_user_watches="819200"
}

prepare_vars()
{
	export CCI_SRC=${CCI_SRC:-"/c/compass-ci"}

	# multi-docker need run simplify-ci firstly, simplify-ci will export LKP_SRC=/c/lkp-tests.
	# but multi-docker is called by /lkp/scheduled/job.sh, when executed here, LKP_SRC=/lkp/lkp/src/
	# so add this judgement.
	[ -d "/c/lkp-tests" ] && export LKP_SRC="/c/lkp-tests"

	hostname=$tbox_group.$HOSTNAME

	local mnt
	for mnt in $mount_points; do
		[[ "$mnt" =~ "multi-docker" ]] && docker_mount_point="$mnt" && break
	done
	[ -n "$docker_mount_point" ] || {
		docker_mount_point=/srv/$suite
		mkdir -p $docker_mount_point
	}

	[ -d "$docker_mount_point" ] || {
		log_error "cannot find dir: $docker_mount_point"
		exit 1
	}
}

get_unit_file_name()
{
	local index=0
	local limit=1000

	unset UNIT_FILE

	while true
	do
		local unit_file="/usr/lib/systemd/system/${suite}-${index}.service"
		[ -f "$unit_file" ] && {
			index=$(($index + 1))
			continue
		}

		[ $index -ge $limit ] && {
			log_error "cannot find right var in limit times: index"
			exit 1
		}

		export UNIT_FILE="$unit_file"
		break
	done

	[ -n "$UNIT_FILE" ] || {
		log_error "cannot get right var: UNIT_FILE."
		exit 1
	}

	export INDEX=$index
}

write_env()
{
	for env_t
        do
		value_env_t=$(eval echo "\$${env_t}")
                if [ -n "$value_env_t" ]; then
			cat >> ${UNIT_FILE}<<-EOF
			Environment="${env_t}=${value_env_t}"
			EOF
		else
			log_warn "cannot find value of var: ${env_t}."
		fi
        done

}

write_unit_file()
{
	cat > ${UNIT_FILE}<<-EOF
	[Unit]
	Description=${suite}-${INDEX}

	[Service]
	Type=simple
	EOF

	env_list=(
		"CCI_SRC"
		"LKP_SRC"
		"LKP_CGI_PORT"
		"MQ_HOST"
		"MQ_PORT"
		"LKP_SERVER"
		"runtime"
		"suite"
		"HOSTNAME"
		"id"
		"JOB_RESULT_ROOT"
	)
	write_env "${env_list[@]}"

	cat >> ${UNIT_FILE}<<-EOF
	ExecStart=$CCI_SRC/providers/multi-docker -n "$hostname" -c "$nr_container" -q "$queues" -i $INDEX
	WorkingDirectory=$docker_mount_point
	Restart=always
	StandardOutput=tty
	StandardError=tty
	TTYPath=/dev/ttyS0
	KillMode=process

	[Install]
	WantedBy=multi-user.target
	EOF
}

prepare_systemd_unit_file()
{
	local lock="/tmp/$HOSTNAME/get_unit_file_name.lock"
	mkdir -p $(dirname $lock)
	while ! lockfile-create --lock-name -p $lock ; do
		sleep 1
	done

	get_unit_file_name
	write_unit_file

	lockfile-remove --lock-name $lock
}

prepare_resource_record_file()
{
	local lock="/tmp/$HOSTNAME/get_resource_record_file.lock"
	mkdir -p $(dirname $lock)
	while ! lockfile-create --lock-name -p $lock ; do
		sleep 1
	done

	local mem_file="/tmp/$HOSTNAME/meminfo"
	[ -f "$mem_file" ] || {
		# / 1024 / 1024: KiB -> GiB
		# - 20: reserve 20G for system usage
		total_mem=$(($(grep MemAvailable /proc/meminfo | awk '{print $2}') / 1024 / 1024 - 20))
		cat > $mem_file <<-EOF
		total: $total_mem G
		usage: 0 G
		idle: $total_mem G
		EOF
	}

	lockfile-remove --lock-name $lock
}

start_multi_docker_service()
{
	prepare_sysctl
	prepare_vars

	has_cmd "lockfile-create" && has_cmd "lockfile-remove" || {
		log_error "cannot find cmd: lockfile-create | lockfile-remove"
		exit 1
	}

	prepare_systemd_unit_file
	prepare_resource_record_file

	systemctl daemon-reload
	systemctl start ${UNIT_FILE##*/}
}

start_multi_docker_service
