Add vm control scripts
This commit is contained in:
parent
6aa191663a
commit
75f03aeb04
6 changed files with 270 additions and 16 deletions
87
kill.sh
Executable file
87
kill.sh
Executable file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
log() {
|
||||||
|
printf '[kill] %s\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: ./kill.sh <id-or-name-prefix> [--signal SIGTERM|SIGKILL|...]
|
||||||
|
|
||||||
|
Sends a signal to the Firecracker process.
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
SIGNAL="TERM"
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--signal)
|
||||||
|
SIGNAL="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ -z "${QUERY:-}" ]]; then
|
||||||
|
QUERY="$1"
|
||||||
|
shift
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
log "unknown option: $1"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$QUERY" || "$QUERY" == "-h" || "$QUERY" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
INFO_FILE="$(find_vm_info "$QUERY")"
|
||||||
|
PID="$(get_prop "$INFO_FILE" "pid")"
|
||||||
|
if [[ -z "$PID" ]]; then
|
||||||
|
log "pid not found in $INFO_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "sending SIG$SIGNAL to pid $PID"
|
||||||
|
sudo kill "-$SIGNAL" "$PID"
|
||||||
|
log "signal sent"
|
||||||
20
list.sh
20
list.sh
|
|
@ -3,14 +3,20 @@ set -euo pipefail
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
|
|
||||||
|
get_prop() {
|
||||||
|
local info="$1"
|
||||||
|
local key="$2"
|
||||||
|
awk -F= -v k="$key" '$1==k {print $2}' "$info"
|
||||||
|
}
|
||||||
|
|
||||||
for info in state/vm-*/info; do
|
for info in state/vm-*/info; do
|
||||||
id="$(awk -F= '$1=="id"{print $2}' "$info")"
|
id="$(get_prop "$info" "id")"
|
||||||
name="$(awk -F= '$1=="name"{print $2}' "$info")"
|
name="$(get_prop "$info" "name")"
|
||||||
created_at="$(awk -F= '$1=="created_at"{print $2}' "$info")"
|
created_at="$(get_prop "$info" "created_at")"
|
||||||
guest_ip="$(awk -F= '$1=="guest_ip"{print $2}' "$info")"
|
guest_ip="$(get_prop "$info" "guest_ip")"
|
||||||
pid="$(awk -F= '$1=="pid"{print $2}' "$info")"
|
pid="$(get_prop "$info" "pid")"
|
||||||
tap="$(awk -F= '$1=="tap"{print $2}' "$info")"
|
tap="$(get_prop "$info" "tap")"
|
||||||
api_sock="$(awk -F= '$1=="api_sock"{print $2}' "$info")"
|
api_sock="$(get_prop "$info" "api_sock")"
|
||||||
|
|
||||||
status="stale"
|
status="stale"
|
||||||
if [[ -n "$pid" && -n "$api_sock" ]]; then
|
if [[ -n "$pid" && -n "$api_sock" ]]; then
|
||||||
|
|
|
||||||
20
ps.sh
20
ps.sh
|
|
@ -3,14 +3,20 @@ set -euo pipefail
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
|
|
||||||
|
get_prop() {
|
||||||
|
local info="$1"
|
||||||
|
local key="$2"
|
||||||
|
awk -F= -v k="$key" '$1==k {print $2}' "$info"
|
||||||
|
}
|
||||||
|
|
||||||
for info in state/vm-*/info; do
|
for info in state/vm-*/info; do
|
||||||
id="$(awk -F= '$1=="id"{print $2}' "$info")"
|
id="$(get_prop "$info" "id")"
|
||||||
name="$(awk -F= '$1=="name"{print $2}' "$info")"
|
name="$(get_prop "$info" "name")"
|
||||||
created_at="$(awk -F= '$1=="created_at"{print $2}' "$info")"
|
created_at="$(get_prop "$info" "created_at")"
|
||||||
guest_ip="$(awk -F= '$1=="guest_ip"{print $2}' "$info")"
|
guest_ip="$(get_prop "$info" "guest_ip")"
|
||||||
pid="$(awk -F= '$1=="pid"{print $2}' "$info")"
|
pid="$(get_prop "$info" "pid")"
|
||||||
tap="$(awk -F= '$1=="tap"{print $2}' "$info")"
|
tap="$(get_prop "$info" "tap")"
|
||||||
api_sock="$(awk -F= '$1=="api_sock"{print $2}' "$info")"
|
api_sock="$(get_prop "$info" "api_sock")"
|
||||||
|
|
||||||
if [[ -z "$pid" || -z "$api_sock" ]]; then
|
if [[ -z "$pid" || -z "$api_sock" ]]; then
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
87
rm.sh
Executable file
87
rm.sh
Executable file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/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"
|
||||||
6
run.sh
6
run.sh
|
|
@ -36,7 +36,9 @@ CIDR="24"
|
||||||
|
|
||||||
DEFAULT_VCPU=2
|
DEFAULT_VCPU=2
|
||||||
DEFAULT_RAM=1024
|
DEFAULT_RAM=1024
|
||||||
|
MIN_VCPU=1
|
||||||
MAX_VCPU=16
|
MAX_VCPU=16
|
||||||
|
MIN_RAM=256
|
||||||
MAX_RAM=32768
|
MAX_RAM=32768
|
||||||
MAX_DISK_BYTES=$((128 * 1024 * 1024 * 1024))
|
MAX_DISK_BYTES=$((128 * 1024 * 1024 * 1024))
|
||||||
|
|
||||||
|
|
@ -108,7 +110,7 @@ if ! [[ "$VCPU_COUNT" =~ ^[0-9]+$ ]]; then
|
||||||
log "invalid --vcpu value: $VCPU_COUNT"
|
log "invalid --vcpu value: $VCPU_COUNT"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if (( VCPU_COUNT < 1 || VCPU_COUNT > MAX_VCPU )); then
|
if (( VCPU_COUNT < MIN_VCPU || VCPU_COUNT > MAX_VCPU )); then
|
||||||
log "vcpu must be between 1 and $MAX_VCPU"
|
log "vcpu must be between 1 and $MAX_VCPU"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -117,7 +119,7 @@ if ! [[ "$RAM_MIB" =~ ^[0-9]+$ ]]; then
|
||||||
log "invalid --ram value: $RAM_MIB"
|
log "invalid --ram value: $RAM_MIB"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if (( RAM_MIB < 256 || RAM_MIB > MAX_RAM )); then
|
if (( RAM_MIB < MIN_RAM || RAM_MIB > MAX_RAM )); then
|
||||||
log "ram must be between 256 and $MAX_RAM MiB"
|
log "ram must be between 256 and $MAX_RAM MiB"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
66
stop.sh
Executable file
66
stop.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/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/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")"
|
||||||
|
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"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue