banger/rm.sh

87 lines
1.9 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
log() {
printf '[rm] %s\n' "$*"
}
usage() {
cat <<'EOF'
Usage: ./rm.sh <id-or-name-prefix>
Removes VM artifacts from state/ and cleans up TAP and mapped devices.
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/vm-*/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")"
VM_DIR="${INFO_FILE%/info}"
PID="$(get_prop "$INFO_FILE" "pid")"
TAP="$(get_prop "$INFO_FILE" "tap")"
API_SOCK="$(get_prop "$INFO_FILE" "api_sock")"
BASE_LOOP="$(get_prop "$INFO_FILE" "base_loop")"
COW_LOOP="$(get_prop "$INFO_FILE" "cow_loop")"
DM_DEV="$(get_prop "$INFO_FILE" "dm_dev")"
DM_NAME="$(get_prop "$INFO_FILE" "dm_name")"
if [[ -n "$PID" ]]; then
sudo kill "$PID" 2>/dev/null || true
fi
if [[ -n "$TAP" ]]; then
sudo ip link del "$TAP" 2>/dev/null || true
fi
if [[ -n "$API_SOCK" ]]; then
rm -f "$API_SOCK"
fi
if [[ -n "$DM_DEV" || -n "$DM_NAME" ]]; then
sudo dmsetup remove "${DM_NAME:-$DM_DEV}" 2>/dev/null || true
fi
if [[ -n "$COW_LOOP" ]]; then
sudo losetup -d "$COW_LOOP" 2>/dev/null || true
fi
if [[ -n "$BASE_LOOP" ]]; then
sudo losetup -d "$BASE_LOOP" 2>/dev/null || true
fi
if [[ -d "$VM_DIR" ]]; then
rm -rf "$VM_DIR"
fi
log "removed $VM_DIR"