66 lines
1.4 KiB
Bash
Executable file
66 lines
1.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
log() {
|
|
printf '[stop] %s\n' "$*"
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: ./stop.sh <id-or-name-prefix>
|
|
|
|
Sends Ctrl+Alt+Del to the guest via the Firecracker API socket.
|
|
EOF
|
|
}
|
|
|
|
get_prop() {
|
|
local info="$1"
|
|
local key="$2"
|
|
awk -F= -v k="$key" '$1==k {print $2}' "$info"
|
|
}
|
|
|
|
find_vm_info() {
|
|
local query="$1"
|
|
local info match_count=0 match=""
|
|
|
|
for info in state/vms/*/info; do
|
|
[[ -f "$info" ]] || continue
|
|
local id name
|
|
id="$(get_prop "$info" "id")"
|
|
name="$(get_prop "$info" "name")"
|
|
if [[ "$id" == "$query"* || "$name" == "$query"* ]]; then
|
|
match="$info"
|
|
match_count=$((match_count + 1))
|
|
fi
|
|
done
|
|
|
|
if (( match_count == 0 )); then
|
|
log "no VM found for prefix: $query"
|
|
exit 1
|
|
fi
|
|
if (( match_count > 1 )); then
|
|
log "multiple VMs found for prefix: $query"
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s' "$match"
|
|
}
|
|
|
|
QUERY="${1:-}"
|
|
if [[ -z "$QUERY" || "$QUERY" == "-h" || "$QUERY" == "--help" ]]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
INFO_FILE="$(find_vm_info "$QUERY")"
|
|
API_SOCK="$(get_prop "$INFO_FILE" "api_sock")"
|
|
if [[ -z "$API_SOCK" || ! -S "$API_SOCK" ]]; then
|
|
log "api socket not found: $API_SOCK"
|
|
exit 1
|
|
fi
|
|
|
|
log "sending Ctrl+Alt+Del to guest"
|
|
sudo -E curl --unix-socket "$API_SOCK" -X PUT http://localhost/actions \
|
|
-H "Content-Type: application/json" \
|
|
-d '{ "action_type": "SendCtrlAltDel" }' >/dev/null
|
|
log "requested shutdown"
|