qvm/bin/qvm-stop

94 lines
2.5 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# qvm-stop - Gracefully shut down the QEMU VM
#
# This script stops the running VM by sending SIGTERM first for graceful
# shutdown, waiting up to 30 seconds, then sending SIGKILL if necessary.
# It cleans up state files (vm.pid, ssh.port) after shutdown completes.
#
# Usage: qvm stop
#
set -euo pipefail
# Source common library
readonly QVM_LIB_DIR="${QVM_LIB_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../lib" && pwd)}"
source "${QVM_LIB_DIR}/common.sh"
# Timeout for graceful shutdown in seconds
readonly SHUTDOWN_TIMEOUT=30
#
# wait_for_process_exit - Wait for process to terminate
# Args: $1 - PID to wait for
# $2 - timeout in seconds
# Returns: 0 if process exits, 1 on timeout
#
wait_for_process_exit() {
local pid="$1"
local timeout="$2"
local elapsed=0
while (( elapsed < timeout )); do
if ! kill -0 "$pid" 2>/dev/null; then
return 0
fi
sleep 1
(( elapsed++ ))
done
return 1
}
#
# main - Main shutdown orchestration
#
main() {
# Check if VM is running
if ! is_vm_running; then
log_info "VM is not running"
exit 0
fi
# Get VM process PID
local vm_pid
vm_pid=$(cat "$QVM_PID_FILE")
log_info "Shutting down VM (PID: $vm_pid)..."
# Send SIGTERM for graceful shutdown
if kill -TERM "$vm_pid" 2>/dev/null; then
log_info "Sent SIGTERM, waiting up to ${SHUTDOWN_TIMEOUT}s for graceful shutdown..."
if wait_for_process_exit "$vm_pid" "$SHUTDOWN_TIMEOUT"; then
log_info "VM shut down gracefully"
else
log_warn "Graceful shutdown timeout, forcefully terminating..."
# Send SIGKILL to force termination
if kill -KILL "$vm_pid" 2>/dev/null; then
# Wait briefly to ensure process is dead
sleep 1
# Verify process is actually dead
if kill -0 "$vm_pid" 2>/dev/null; then
die "Failed to kill VM process $vm_pid"
fi
log_info "VM forcefully terminated"
else
log_warn "Process $vm_pid already terminated"
fi
fi
else
log_warn "Process $vm_pid already terminated (could not send SIGTERM)"
fi
# Clean up state files
log_info "Cleaning up state files..."
rm -f "$QVM_PID_FILE" "$QVM_SSH_PORT_FILE"
log_info "VM stopped successfully"
}
main "$@"