Original .sh file
This commit is contained in:
1 parent
e9ee3ff3fe
commit
6f44deff64
1 file changed
+229
Executable
+229
@@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
# Simple interactive toolkit for a Proxmox VE node.
|
||||
# Run as root. Uses whiptail for the GUI and does not execute arbitrary input.
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
printf 'Run this script as root, for example: sudo bash %s\n' "$0" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v whiptail >/dev/null 2>&1; then
|
||||
printf 'whiptail is required. Install it with: apt install whiptail\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMPDIR_TOOLKIT=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR_TOOLKIT"' EXIT
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
whiptail --title "Command unavailable" \
|
||||
--msgbox "The command '$1' is not installed or not available on this node." 8 70
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
valid_id() {
|
||||
[[ "$1" =~ ^[0-9]+$ ]]
|
||||
}
|
||||
|
||||
ask_id() {
|
||||
local prompt=$1
|
||||
local value
|
||||
|
||||
value=$(whiptail --title "Enter ID" --inputbox "$prompt" 9 60 3>&1 1>&2 2>&3) || return 1
|
||||
|
||||
if ! valid_id "$value"; then
|
||||
whiptail --title "Invalid ID" --msgbox "Enter a numeric VM or container ID." 8 55
|
||||
return 1
|
||||
fi
|
||||
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
show_output() {
|
||||
local title=$1
|
||||
shift
|
||||
local output="$TMPDIR_TOOLKIT/output.txt"
|
||||
local status=0
|
||||
|
||||
"$@" >"$output" 2>&1 || status=$?
|
||||
|
||||
if [[ ! -s "$output" ]]; then
|
||||
printf 'Command completed with exit status %s; no output.\n' "$status" >"$output"
|
||||
elif (( status != 0 )); then
|
||||
printf '\nCommand exited with status %s.\n' "$status" >>"$output"
|
||||
fi
|
||||
|
||||
whiptail --title "$title" --textbox "$output" 24 85
|
||||
}
|
||||
|
||||
confirm_action() {
|
||||
whiptail --title "Confirm" --yesno "$1" 10 70
|
||||
}
|
||||
|
||||
vm_menu() {
|
||||
local choice id
|
||||
|
||||
while true; do
|
||||
choice=$(whiptail --title "Virtual Machines (QEMU)" --menu "Choose an action:" \
|
||||
16 72 8 \
|
||||
"list" "List VMs (qm list)" \
|
||||
"config" "Show VM configuration" \
|
||||
"memory" "Show VM memory setting" \
|
||||
"unlock" "Unlock a VM" \
|
||||
"back" "Back" 3>&1 1>&2 2>&3) || return
|
||||
|
||||
case "$choice" in
|
||||
list)
|
||||
require_command qm && show_output "VM list" qm list
|
||||
;;
|
||||
config|memory|unlock)
|
||||
require_command qm || continue
|
||||
id=$(ask_id "Enter the VMID:") || continue
|
||||
|
||||
case "$choice" in
|
||||
config) show_output "VM $id configuration" qm config "$id" ;;
|
||||
memory) show_output "VM $id memory" bash -c 'qm config "$1" | grep -E "^memory:" || true' _ "$id" ;;
|
||||
unlock)
|
||||
if confirm_action "Unlock VM $id?\n\nOnly do this if you have confirmed that no task is still running for this VM."; then
|
||||
show_output "Unlock VM $id" qm unlock "$id"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
back) return ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
container_menu() {
|
||||
local choice id
|
||||
|
||||
while true; do
|
||||
choice=$(whiptail --title "Containers (LXC)" --menu "Choose an action:" \
|
||||
14 72 6 \
|
||||
"list" "List containers (pct list)" \
|
||||
"config" "Show container configuration" \
|
||||
"unlock" "Unlock a container" \
|
||||
"back" "Back" 3>&1 1>&2 2>&3) || return
|
||||
|
||||
case "$choice" in
|
||||
list)
|
||||
require_command pct && show_output "Container list" pct list
|
||||
;;
|
||||
config|unlock)
|
||||
require_command pct || continue
|
||||
id=$(ask_id "Enter the container ID:") || continue
|
||||
|
||||
if [[ "$choice" == "config" ]]; then
|
||||
show_output "Container $id configuration" pct config "$id"
|
||||
elif confirm_action "Unlock container $id?\n\nOnly do this if you have confirmed that no task is still running for this container."; then
|
||||
show_output "Unlock container $id" pct unlock "$id"
|
||||
fi
|
||||
;;
|
||||
back) return ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
backup_menu() {
|
||||
local id
|
||||
|
||||
require_command vzdump || return
|
||||
id=$(ask_id "Enter the VM or container ID to back up:") || return
|
||||
|
||||
if confirm_action "Start a backup for ID $id using vzdump defaults?\n\nReview your node's backup configuration and storage capacity first."; then
|
||||
show_output "Backup ID $id" vzdump "$id"
|
||||
fi
|
||||
}
|
||||
|
||||
restore_menu() {
|
||||
local choice id archive
|
||||
|
||||
choice=$(whiptail --title "Restore" --menu "Choose what to restore:" \
|
||||
12 72 4 \
|
||||
"vm" "Restore a QEMU VM (qmrestore)" \
|
||||
"ct" "Restore a container (pct restore)" \
|
||||
"back" "Back" 3>&1 1>&2 2>&3) || return
|
||||
[[ "$choice" == "back" ]] && return
|
||||
|
||||
id=$(ask_id "Enter the new VMID or container ID:") || return
|
||||
archive=$(whiptail --title "Backup archive" --inputbox \
|
||||
"Enter the full path to the vzdump archive:" 9 72 3>&1 1>&2 2>&3) || return
|
||||
|
||||
if [[ -z "$archive" || ! -f "$archive" ]]; then
|
||||
whiptail --title "Archive not found" --msgbox "That file does not exist or is not a regular file." 8 65
|
||||
return
|
||||
fi
|
||||
|
||||
if ! confirm_action "Restore '$archive' as ID $id?\n\nRestoring can create or overwrite resources. Confirm the target ID and archive carefully."; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$choice" == "vm" ]]; then
|
||||
require_command qmrestore && show_output "Restore VM $id" qmrestore "$archive" "$id"
|
||||
else
|
||||
require_command pct && show_output "Restore container $id" pct restore "$id" "$archive"
|
||||
fi
|
||||
}
|
||||
|
||||
storage_menu() {
|
||||
local choice
|
||||
|
||||
while true; do
|
||||
choice=$(whiptail --title "Storage / LVM" --menu "Choose a read-only report:" \
|
||||
14 72 6 \
|
||||
"pvs" "Physical volumes (pvs)" \
|
||||
"vgs" "Volume groups (vgs)" \
|
||||
"lvs" "Logical volumes (lvs)" \
|
||||
"back" "Back" 3>&1 1>&2 2>&3) || return
|
||||
|
||||
case "$choice" in
|
||||
pvs) require_command pvs && show_output "Physical volumes" pvs ;;
|
||||
vgs) require_command vgs && show_output "Volume groups" vgs ;;
|
||||
lvs) require_command lvs && show_output "Logical volumes" lvs ;;
|
||||
back) return ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
while true; do
|
||||
choice=$(whiptail --title "Proxmox VE Toolkit" --menu "Select a task:" \
|
||||
21 76 13 \
|
||||
"vms" "Virtual machines (QEMU)" \
|
||||
"containers" "Containers (LXC)" \
|
||||
"backup" "Back up a VM or container (vzdump)" \
|
||||
"restore" "Restore a VM or container" \
|
||||
"cluster" "Cluster status (pvecm status)" \
|
||||
"version" "Proxmox version (pveversion -v)" \
|
||||
"storage" "Storage / LVM reports" \
|
||||
"perf" "Host performance test (pveperf)" \
|
||||
"subscription" "Subscription status" \
|
||||
"dab" "Debian Appliance Builder help" \
|
||||
"quit" "Exit" 3>&1 1>&2 2>&3) || break
|
||||
|
||||
case "$choice" in
|
||||
vms) vm_menu ;;
|
||||
containers) container_menu ;;
|
||||
backup) backup_menu ;;
|
||||
restore) restore_menu ;;
|
||||
cluster) require_command pvecm && show_output "Cluster status" pvecm status ;;
|
||||
version) require_command pveversion && show_output "Proxmox VE version" pveversion -v ;;
|
||||
storage) storage_menu ;;
|
||||
perf)
|
||||
if require_command pveperf && confirm_action "Run pveperf?\n\nThis can cause temporary disk activity."; then
|
||||
show_output "Host performance" pveperf
|
||||
fi
|
||||
;;
|
||||
subscription) require_command pvesubscription && show_output "Subscription status" pvesubscription get ;;
|
||||
dab)
|
||||
if require_command dab; then
|
||||
show_output "Debian Appliance Builder help" dab help
|
||||
fi
|
||||
;;
|
||||
quit) break ;;
|
||||
esac
|
||||
done
|
||||
Reference in new issue
Block a user