#!/usr/bin/bash

DOCKER="/usr/bin/docker"
LOGGER="/usr/bin/logger"
SYSTEMCTL="/usr/bin/systemctl"
TRIES_TO_START=10
UPGRADE_MARK="/run/.node_is_being_updated"

function log() {
	if [ ! -x $LOGGER ]; then
		echo $*
	fi
	$LOGGER "$0: $*"
}

if [ ! -x $DOCKER -o ! -x $SYSTEMCTL ]; then
	log "Some binaries not found, nothing to do."
	exit 0
fi

function get_image() {
	local images
	images="$(docker images --filter=reference='*/*/*neutron-openvswitch-agent' \
				--format '{{.Repository}}:{{.Tag}}')"
	if [[ $? -ne 0 || -z "${images}" ]]; then
		return 1
	fi

	# there might be >1 images while upgrade is incomplete
	# return the most recent one
	sort -V <<< "${images}" | tail -n1
}

function neutron_ovs_cleanup() {
	local docker_image
	local neutron_conf=/etc/kolla/neutron-openvswitch-agent/neutron.conf
	local ml2_conf=/etc/kolla/neutron-openvswitch-agent/ml2_conf.ini
	local log_dir=/var/log/hci/neutron
	local cleanup_lock=/var/run/neutron_ovs_cleanup.lock
	if [[ ! -f "${neutron_conf}" || ! -f "${ml2_conf}" || ! -d "${log_dir}"  ]]; then
		# Compute has not been installed yet. Create a lock file to prevent
		# executing ovs-cleanup script after compute deploy and a further
		# docker service restart.
		touch "${cleanup_lock}"
		return 0
	fi
	if [[ -f "${cleanup_lock}" ]]; then
		# nothing to do
		return 0
	elif pgrep qemu-kvm >/dev/null; then
		# For some reason, the previous startup of the docker service could not
		# create a lock file and the VMs had already been started. We are not
		# going to break these VMs.
		log "ERROR: neutron_ovs_cleanup: qemu processes found without ${cleanup_lock} file"
		touch "${cleanup_lock}"
		return 0
	fi

	docker_image="$(get_image)"
	if [[ $? -ne 0 || -z "${docker_image}" ]]; then
		log "Failed to get docker neutron-openvswitch-agent image"
		return 1
	fi

	$DOCKER run \
		--user root \
		--rm \
		--network host \
		--volume "${neutron_conf}":"${neutron_conf}" \
		--volume "${ml2_conf}":"${ml2_conf}" \
		--entrypoint /usr/bin/neutron-ovs-cleanup \
		"${docker_image}" \
		--config-file "${neutron_conf}" \
		--config-file "${ml2_conf}" \
		--log-dir '' >>"${log_dir}/neutron-ovs-cleanup.log"
	if [[ $? -ne 0 ]]; then
		log "neutron_ovs_cleanup failed"
		return 1
	fi
	touch "${cleanup_lock}"
	log "neutron_ovs_cleanup success"
	return 0
}

function start_containers_pre() {
	neutron_ovs_cleanup
}

function start_containers() {
	local cts ct_list
	cts=0

	# list command may timeout too
	ct_list=`$DOCKER container list -a --format "table {{.ID}}\t{{.Status}}" 2>/dev/null | grep -v '^CONTAINER' | awk '{if ($2 !~ /Up/){ print $1 }}'`
	if [ $? -ne 0 ]; then
		log "Failed to get docker containers list"
		return 1
	fi

	for ct in $ct_list; do
		$DOCKER container start $ct >/dev/null 2>&1 &
		[ $? -ne 0 ] && log "Failed to start docker container $ct" || log "Starting docker container $ct"
		cts=$((cts+1))
	done

	# Wait for docker container start processes
	wait

	return $cts
}

# Do it in a loop because on huge HN load docker-containerd
# daemon can lock, so will start until we success

# Prepare for containers start
for i in `seq 1 $TRIES_TO_START`; do
	start_containers_pre
	[ $? -eq 0 ] && break
	sleep 1
	if [[ $i -eq $TRIES_TO_START ]]; then
		log "ERROR: failed to prepare to run containers"
	fi
done

if [ -f "${UPGRADE_MARK}" ]; then
	log "Host is being updated"
else
	# Start all existing containers
	for i in `seq 1 $TRIES_TO_START`; do
		start_containers
		[ $? -eq 0 ] && break
	done
	log "All docker container started"
fi

/usr/bin/vcmmdctl unregister vstorage.slice/vstorage-compute.slice || :
/usr/bin/vcmmdctl register SRVC vstorage.slice/vstorage-compute.slice --cache 1073741824 --swap 0
/usr/bin/vcmmdctl unregister vstorage.slice/vstorage-compute.slice/vstorage-compute-storage.slice || :
/usr/bin/vcmmdctl register SRVC vstorage.slice/vstorage-compute.slice/vstorage-compute-storage.slice --cache 536870912 --swap 0
/usr/bin/vcmmdctl activate vstorage.slice/vstorage-compute.slice/vstorage-compute-storage.slice || :
/usr/bin/vcmmdctl activate vstorage.slice/vstorage-compute.slice || :

exit 0
