Improve VM lifecycle tooling
Make spawned VMs easier to use and restore from the host. Add shared DNS and runtime helpers, publish <vm-name>.vm records through mapdns, and teach run/customize/interactive/restore to persist the metadata needed for SSH, DNS cleanup, and clean restores. Seed per-VM /home and /var disks from the rootfs snapshot so package state is present on first boot, add an interactive customization entrypoint plus ssh.sh and human-friendly list output, and let stop/kill/rm operate on multiple VM identifiers. Tear down stale TAP, dm, and loop state when VMs stop so restore can recreate them safely, and validate the updated scripts with bash -n plus targeted dry-run harnesses for teardown and restore paths.
This commit is contained in:
parent
a8078f2393
commit
9191b7e370
11 changed files with 966 additions and 144 deletions
102
rm.sh
102
rm.sh
|
|
@ -5,9 +5,14 @@ log() {
|
|||
printf '[rm] %s\n' "$*"
|
||||
}
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$DIR/dns.sh"
|
||||
STATE="$DIR/state"
|
||||
VM_ROOT="$STATE/vms"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: ./rm.sh <id-or-name-prefix>
|
||||
Usage: ./rm.sh <id-or-name-prefix>...
|
||||
|
||||
Removes VM artifacts from state/ and cleans up TAP and mapped devices.
|
||||
EOF
|
||||
|
|
@ -17,7 +22,7 @@ find_vm_json() {
|
|||
local query="$1"
|
||||
local vm_json match_count=0 match=""
|
||||
|
||||
for vm_json in state/vms/*/vm.json; do
|
||||
for vm_json in "$VM_ROOT"/*/vm.json; do
|
||||
[[ -f "$vm_json" ]] || continue
|
||||
local id name
|
||||
id="$(jq -r '.meta.id // empty' "$vm_json")"
|
||||
|
|
@ -40,42 +45,69 @@ find_vm_json() {
|
|||
printf '%s' "$match"
|
||||
}
|
||||
|
||||
QUERY="${1:-}"
|
||||
if [[ -z "$QUERY" || "$QUERY" == "-h" || "$QUERY" == "--help" ]]; then
|
||||
QUERIES=("$@")
|
||||
if (( ${#QUERIES[@]} == 1 )) && [[ "${QUERIES[0]}" == "-h" || "${QUERIES[0]}" == "--help" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
if (( ${#QUERIES[@]} == 0 )); then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VM_JSON="$(find_vm_json "$QUERY")"
|
||||
VM_DIR="$(dirname "$VM_JSON")"
|
||||
PID="$(jq -r '.meta.pid // empty' "$VM_JSON")"
|
||||
TAP="$(jq -r '.meta.tap // empty' "$VM_JSON")"
|
||||
API_SOCK="$(jq -r '.meta.api_sock // empty' "$VM_JSON")"
|
||||
BASE_LOOP="$(jq -r '.meta.base_loop // empty' "$VM_JSON")"
|
||||
COW_LOOP="$(jq -r '.meta.cow_loop // empty' "$VM_JSON")"
|
||||
DM_DEV="$(jq -r '.meta.dm_dev // empty' "$VM_JSON")"
|
||||
DM_NAME="$(jq -r '.meta.dm_name // empty' "$VM_JSON")"
|
||||
VM_JSONS=()
|
||||
for query in "${QUERIES[@]}"; do
|
||||
VM_JSON="$(find_vm_json "$query")"
|
||||
already_added=0
|
||||
for existing_vm_json in "${VM_JSONS[@]}"; do
|
||||
if [[ "$existing_vm_json" == "$VM_JSON" ]]; then
|
||||
already_added=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
if (( already_added == 0 )); then
|
||||
VM_JSONS+=("$VM_JSON")
|
||||
fi
|
||||
done
|
||||
|
||||
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
|
||||
for vm_json in "${VM_JSONS[@]}"; do
|
||||
vm_dir="$(dirname "$vm_json")"
|
||||
vm_id="$(jq -r '.meta.id // empty' "$vm_json")"
|
||||
vm_name="$(jq -r '.meta.name // empty' "$vm_json")"
|
||||
pid="$(jq -r '.meta.pid // empty' "$vm_json")"
|
||||
tap="$(jq -r '.meta.tap // empty' "$vm_json")"
|
||||
api_sock="$(jq -r '.meta.api_sock // empty' "$vm_json")"
|
||||
base_loop="$(jq -r '.meta.base_loop // empty' "$vm_json")"
|
||||
cow_loop="$(jq -r '.meta.cow_loop // empty' "$vm_json")"
|
||||
dm_dev="$(jq -r '.meta.dm_dev // empty' "$vm_json")"
|
||||
dm_name="$(jq -r '.meta.dm_name // empty' "$vm_json")"
|
||||
dns_name="$(jq -r '.meta.dns_name // empty' "$vm_json")"
|
||||
if [[ -z "$dns_name" ]]; then
|
||||
dns_name="$(banger_dns_name "$vm_name")"
|
||||
fi
|
||||
|
||||
log "removed $VM_DIR"
|
||||
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
|
||||
banger_dns_remove_record_name "$dns_name"
|
||||
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_name:-$vm_dir}"
|
||||
done
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue