#!/usr/bin/openrc-run

. /opt/etc/functions.openrc

description="Manages user VMs"

VMS_AUTOSTART=${VMS_AUTOSTART-""}
VMS_HIBERNATE=${VMS_HIBERNATE-""}
SHUTDOWN_TIMEOUT=${SHUTDOWN_TIMEOUT-"45"}

extra_commands="start_managed_vms stop_managed_vms"

start_managed_vms()
{
	local _vm
	for _vm in ${VMS_AUTOSTART}; do
		update_me
		if is_vm_running "${_vm}"; then
			ewarn "${ME}: VM \"${_vm}\" is already running."
		else
			einfo "${ME}: starting VM \"${_vm}\""
			virsh start "${_vm}"
		fi
	done
}

is_still_managed_vms()
{
	for _vm in ${VMS_AUTOSTART}; do
		is_vm_shutoff "${_vm}" || return 0
	done
	return 1
}

depend()
{
	echo "  ${SVCNAME}::depend(): rc_need=\"${rc_need}\""
	need libvirtd
	after nfs tftpd dhcpd4 smbd
	provide ${SVCNAME}
}

start()
{
	ebegin "Starting \"${SVCNAME}\""
	eindent
	modprobe tun
	modprobe vfio_iommu_type1
	start_managed_vms
	eoutdent
	eend 0
	return 0
}

stop_managed_vms()
{
	local _vm _count=${SHUTDOWN_TIMEOUT}
	# Unpause all managed VMs
	for _vm in `virsh list --name --state-paused`; do
		var_in_list "${_vm}" "${VMS_AUTOSTART}" && virsh resume "${_vm}"
	done
	# If the running VM is not in VMS_HIBERNATE list, send shutdown command to it
	# BUGBUG: in most cases this does not work with Windows guests.
	for _vm in ${VMS_AUTOSTART}; do
		is_vm_shutoff "${_vm}" && continue
		var_in_list "${_vm}" "${VMS_HIBERNATE}" && continue;
		update_me
		einfo "${ME}: sending ACPI shutdown to VM \"${_vm}\""
		virsh shutdown "${_vm}"
	done
	# If the running VM is in VMS_HIBERNATE list, save it
	for _vm in ${VMS_HIBERNATE}; do
		is_vm_shutoff "${_vm}" && continue
		update_me
		einfo "${ME}: performing 'managedsave' on VM \"${_vm}\""
		virsh managedsave "${_vm}"
	done
	# Monitor shutdown process for VMs in VMS_AUTOSTART list
	while [ ${_count} -gt 0 ]; do
		is_still_managed_vms || return 0
		einfo "${ME}: waiting for VM(s) shutdown, ${_count} second(s) remaining..."
		sleep 1
		_count=$((${_count}-1))
	done
	for _vm in ${VMS_AUTOSTART}; do
		is_vm_shutoff "${_vm}" && continue
		update_me
		eerror "${ME}: VM \"${_vm}\" refuses to shut down; destroying it."
		virsh destroy "${_vm}"
	done
	return 0
}

stop()
{
	ebegin "Stopping \"${SVCNAME}\""
	eindent
	stop_managed_vms
	eoutdent
	eend 0
	return 0
}

