Add initial QVM CLI, Nix flake, scripts and README
This commit is contained in:
parent
25b1cca0e6
commit
8534f7efb9
14 changed files with 2359 additions and 0 deletions
94
bin/qvm-stop
Executable file
94
bin/qvm-stop
Executable file
|
|
@ -0,0 +1,94 @@
|
|||
#!/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 "$@"
|
||||
Loading…
Add table
Add a link
Reference in a new issue