#!/usr/bin/openrc-run

. /opt/etc/functions.openrc

START_TIMEOUT=${START_TIMEOUT-"50"}
VMSHUT_TIMEOUT=${VMSHUT_TIMEOUT-"90"}
VMKILL_TIMEOUT=${VMKILL_TIMEOUT-"30"}
# Command to test power status
PWC=${PWC-"true"}

depend() {
	provide ${SVCNAME}
}

wait_for_libvirtd()
{
	local _count=$1
	sleep 1
	while [ ${_count} -gt 0 ]; do
		virsh list > /dev/null 2>&1 && return 0
		_count=$((${_count}-1))
		update_me
		ewarn "${ME}: waiting for libvirtd, ${_count} more seconds..."
		sleep 1
	done
	return 1
}

start() {
	local _libvirt_daemons="libvirtd"
	ebegin "Starting \"${SVCNAME}\""
	if is_shutdown_scheduled; then
		update_me
		eerror "${ME}: shutdown is scheduled, unable to start libvirtd!"
	elif ! ${PWC}; then
		update_me
		eerror "${ME}: binary \"${PWC}\" have not reported good power status!"
	else
		which virtlogd > /dev/null 2>&1 && _libvirt_daemons="${_libvirt_daemons} virtlogd"
		start_fg_daemons "${_libvirt_daemons}" && wait_for_libvirtd ${START_TIMEOUT} && eend 0 && return 0
		pgrep libvirtd > /dev/null 2>&1 && stop_fg_daemons "${_libvirt_daemons}"
	fi
	eend 1
	return 1
}

# Executes command for all VMs that are not shut off.
# First argument: command (shutdown, destroy, ...)
vms_cmd_fns()
{
	local _vm _state _cmd=$1
	for _vm in $(virsh list --all --name); do
		_state=$(virsh list --all | grep -w ${_vm} | awk '{print $3}')
		[ "${_state}" = shut ] && continue
		if [ "${_state}" = paused ]; then
			ewarn "${ME}: VM \"${_vm}\" was suspended; resuming..."
			virsh resume ${_vm}
			sleep 1
			_state=$(virsh list --all | grep -w ${_vm} | awk '{print $3}')
		fi
		ewarn "${ME}: sending command \"${_cmd}\" to VM \"${_vm}\" which was in state \"${_state}\""
		virsh $1 ${_vm}
		_state=$(virsh list --all | grep -w ${_vm} | awk '{print $3}')
		ewarn "${ME}: sent command \"${_cmd}\" to VM \"${_vm}\" which is now in state \"${_state}\""
	done
}

# Executes command for all VMs that are not 'shut off'.
# First argument: command (shutdown or destroy)
# Second argument: timeout in seconds
vms_cmd_fns_timeout()
{
	local _count=$2 _cmd=$1
	while [ ${_count} -gt 0 ]; do
		if all_vms_shutoff; then
			return 0
		else
			einfo "${ME}: sending \"${_cmd}\" to VMs that are not shut off (${_count} seconds remaining)"
			vms_cmd_fns ${_cmd}
		fi
		sleep 1
		_count=$((${_count}-1))
	done
	eerror "${ME}: at least one VM is not responding to \"${_cmd}\""
	return 1
}

all_vms_shutoff()
{
	local _vm _state
	for _vm in $(virsh list --all --name); do
		is_vm_shutoff ${_vm} || return 1
	done
	return 0
}

ensure_no_vms_running()
{
	all_vms_shutoff && return 0
	ewarn "${ME}: not all VMs are shut off! Double check your config rules!"
	vms_cmd_fns_timeout shutdown ${VMSHUT_TIMEOUT} && return 0
	vms_cmd_fns_timeout destroy ${VMKILL_TIMEOUT} && return 0
	return 1
}

stop()
{
	local _libvirt_daemons="libvirtd"
	ebegin "Stopping service \"${SVCNAME}\""
	eindent
	ensure_no_vms_running
	which virtlogd > /dev/null 2>&1 && _libvirt_daemons="${_libvirt_daemons} virtlogd"
	stop_fg_daemons "${_libvirt_daemons}"
	eoutdent
	eend 0
	return 0
}

