Repository navigation
Expand file tree
/
Copy pathlist-vms.sh
More file actions
executable file
·125 lines (110 loc) · 4.89 KB
/
Copy pathlist-vms.sh
File metadata and controls
executable file
·125 lines (110 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env bash
# list-vms.sh — list firecracker VMs started by start-vm.sh, with live status.
#
# Usage: ./list-vms.sh [VM_ID ...]
#
# With no arguments, scans for API sockets (FC_SOCKET_DIR, default /tmp) and
# reports every VM found. With explicit ids, reports those ids whether or not
# a socket exists (useful for confirming a VM is really gone). With exactly
# one explicit id, API_SOCKET is honored like in start-vm.sh, so a non-default
# socket path can be probed.
#
# Columns: VM GUEST IP TAP FC PID vCPU MEM (MB) ROOTFS STATUS
#
# ROOTFS: which bytes the VM runs on — overlay:<layer> (read-only base + this
# VM's writable layer) or rw:<image> (writable root) — so you can confirm no VM
# is writing an image another VM has open.
#
# STATUS is one of:
# up firecracker running and guest answers ping
# running firecracker running but guest not pinging (booting, or no tap)
# stale socket file left behind by a dead process (./stop-vm.sh cleans up)
# absent no socket — VM not running
# No -e on purpose: every failure path below is an explicit if/|| check.
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FC_DIR="${FC_DIR:-$SCRIPT_DIR}"
# shellcheck source=lib-fcnet.sh
source "$SCRIPT_DIR/lib-fcnet.sh"
SOCKET_DIR="$(fc_socket_dir)"
need() { command -v "$1" >/dev/null || { echo "missing: $1" >&2; exit 1; }; }
need curl; need jq; need pgrep; need ip; need ping
# Collect VM ids: explicit args, or whatever sockets exist. /tmp is scanned too
# so VMs booted by a pre-hardening start-vm.sh still show up rather than
# looking like they are not running.
if [ "$#" -gt 0 ]; then
ids=("$@")
else
ids=()
for sock in "$SOCKET_DIR"/firecracker-vm*.sock /tmp/firecracker-vm*.sock; do
[ -e "$sock" ] || continue
ids+=("$(basename "$sock" .sock | sed 's/^firecracker-vm//')")
done
# dedupe: the same id can appear in both directories
if [ "${#ids[@]}" -gt 0 ]; then
mapfile -t ids < <(printf '%s\n' "${ids[@]}" | sort -nu)
fi
if [ "${#ids[@]}" -eq 0 ]; then
echo "No firecracker VMs running (no sockets in $SOCKET_DIR or /tmp)."
exit 0
fi
fi
# With exactly one explicit id, honor a non-default API_SOCKET (as start-vm.sh does).
single_sock=""
if [ "$#" -eq 1 ] && [ -n "${API_SOCKET:-}" ]; then
single_sock="$API_SOCKET"
fi
printf '%-4s %-14s %-5s %-8s %-5s %-9s %-22s %s\n' VM "GUEST IP" TAP "FC PID" VCPU "MEM (MB)" ROOTFS STATUS
for id in "${ids[@]}"; do
# Sanity-check the id (10# defuses leading zeros like "08").
if ! [[ "$id" =~ ^[0-9]+$ ]] || (( 10#$id > 63 )); then
printf '%-4s %-14s %-5s %-8s %-5s %-9s %-22s %s\n' "$id" - - - - - - "bad id (must be 0..63)"
continue
fi
id=$((10#$id))
sock="${single_sock:-$(API_SOCKET= fc_api_socket "$id")}"
guest="$(fc_guest_ip "$id")"
tap="$(fc_tap "$id")"
if [ ! -S "$sock" ]; then
printf '%-4s %-14s %-5s %-8s %-5s %-9s %-22s %s\n' "$id" "$guest" "$tap" - - - - absent
continue
fi
# One snapshot: a failed fetch means no live process behind the socket.
# Liveness endpoint: GET /machine-config answers 200 even before
# configuration (the old /instance-info is gone from current Firecracker APIs).
if ! config="$(curl -sf --max-time 1 --unix-socket "$sock" http://localhost/machine-config 2>/dev/null)"; then
printf '%-4s %-14s %-5s %-8s %-5s %-9s %-22s %s\n' "$id" "$guest" "$tap" - - - - "stale (run ./stop-vm.sh $id)"
continue
fi
# -xf: exact full-command-line match. A loose -f pattern would also hit any
# shell wrapper (e.g. an agent's bash -c) that merely mentions this command.
pid="$(pgrep -xf "firecracker --api-sock $sock" | head -1)"
vcpu="$(jq -r '.vcpu_count // "-"' <<<"$config")"
mem="$(jq -r '.mem_size_mib // "-"' <<<"$config")"
# Which bytes is this VM running on? GET /vm/config reports the drives of a
# configured VM (column meanings in the header); degrades to "-" on older
# Firecracker that lacks the endpoint.
rootfs="-"
if vmcfg="$(curl -sf --max-time 1 --unix-socket "$sock" http://localhost/vm/config 2>/dev/null)"; then
rootfs="$(jq -r '
[.. | objects | select(has("path_on_host"))] as $d
| ($d | map(select(.is_root_device == true)) | first) as $r
| ($d | map(select(.is_root_device != true)) | first) as $x
| if $r == null then "-"
elif ($r.is_read_only == true) and ($x != null)
then "overlay:" + ($x.path_on_host | split("/") | last)
elif ($r.is_read_only == true)
then "ro:" + ($r.path_on_host | split("/") | last)
else "rw:" + ($r.path_on_host | split("/") | last)
end' <<<"$vmcfg" 2>/dev/null)"
[ -n "$rootfs" ] || rootfs="-"
fi
if ping -c1 -W1 "$guest" >/dev/null 2>&1; then
status=up
elif ! ip link show "$tap" >/dev/null 2>&1; then
status="running (no $tap)"
else
status=running
fi
printf '%-4s %-14s %-5s %-8s %-5s %-9s %-22s %s\n' "$id" "$guest" "$tap" "${pid:--}" "$vcpu" "$mem" "$rootfs" "$status"
done