Files
bee/iso/overlay-debug/usr/local/bin/bee-tui

621 lines
15 KiB
Bash
Executable File

#!/bin/sh
# bee-tui: interactive text menu for debug LiveCD operations.
set -u
pause() {
echo
printf 'Press Enter to continue... '
read -r _
}
header() {
clear
echo "=============================================="
echo " bee TUI (debug)"
echo "=============================================="
echo
}
list_ifaces() {
ip -o link show \
| awk -F': ' '{print $2}' \
| grep -v '^lo$' \
| grep -vE '^(docker|virbr|veth|tun|tap|br-|bond|dummy)' \
| sort
}
show_network_status() {
header
echo "Network interfaces"
echo
for iface in $(list_ifaces); do
state=$(ip -o link show "$iface" | awk '{print $9}')
ipv4=$(ip -o -4 addr show dev "$iface" | awk '{print $4}' | paste -sd ',')
[ -n "$ipv4" ] || ipv4="(no IPv4)"
echo "- $iface: state=$state ip=$ipv4"
done
echo
ip route | sed 's/^/ route: /'
pause
}
choose_interface() {
ifaces="$(list_ifaces)"
if [ -z "$ifaces" ]; then
echo "No physical interfaces found"
return 1
fi
echo "$ifaces" | nl -w2 -s'. '
echo
printf 'Select interface number: '
read -r idx
iface=$(echo "$ifaces" | sed -n "${idx}p")
if [ -z "$iface" ]; then
echo "Invalid interface selection"
return 1
fi
CHOSEN_IFACE="$iface"
return 0
}
network_dhcp_one() {
header
echo "DHCP on one interface"
echo
choose_interface || { pause; return; }
iface="$CHOSEN_IFACE"
echo
echo "Starting DHCP on $iface..."
ip link set "$iface" up 2>/dev/null || true
udhcpc -i "$iface" -t 5 -T 3
pause
}
network_dhcp_all() {
header
echo "Restarting DHCP on all physical interfaces..."
echo
/usr/local/bin/bee-net-restart
pause
}
network_static_one() {
header
echo "Static IPv4 setup"
echo
choose_interface || { pause; return; }
iface="$CHOSEN_IFACE"
echo
printf 'IPv4 address (example 192.168.1.10): '
read -r ip
if [ -z "$ip" ]; then
echo "IP address is required"
pause
return
fi
printf 'Netmask (example 24 or 255.255.255.0): '
read -r mask
if [ -z "$mask" ]; then
echo "Netmask is required"
pause
return
fi
prefix=$(mask_to_prefix "$mask")
if [ -z "$prefix" ]; then
echo "Invalid netmask: $mask"
pause
return
fi
cidr="$ip/$prefix"
printf 'Default gateway: '
read -r gw
if [ -z "$gw" ]; then
echo "Default gateway is required"
pause
return
fi
printf 'DNS server (optional): '
read -r dns
ip link set "$iface" up 2>/dev/null || true
ip addr flush dev "$iface"
if ! ip addr add "$cidr" dev "$iface"; then
echo "Failed to set IP"
pause
return
fi
if [ -n "$gw" ]; then
ip route del default >/dev/null 2>&1 || true
ip route add default via "$gw" dev "$iface"
fi
if [ -n "$dns" ]; then
printf 'nameserver %s\n' "$dns" > /etc/resolv.conf
fi
echo
echo "Static config applied to $iface"
pause
}
mask_to_prefix() {
mask="$(echo "$1" | tr -d '[:space:]')"
case "$mask" in
0|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)
echo "$mask"
return 0
;;
esac
case "$mask" in
255.0.0.0) echo 8 ;;
255.128.0.0) echo 9 ;;
255.192.0.0) echo 10 ;;
255.224.0.0) echo 11 ;;
255.240.0.0) echo 12 ;;
255.248.0.0) echo 13 ;;
255.252.0.0) echo 14 ;;
255.254.0.0) echo 15 ;;
255.255.0.0) echo 16 ;;
255.255.128.0) echo 17 ;;
255.255.192.0) echo 18 ;;
255.255.224.0) echo 19 ;;
255.255.240.0) echo 20 ;;
255.255.248.0) echo 21 ;;
255.255.252.0) echo 22 ;;
255.255.254.0) echo 23 ;;
255.255.255.0) echo 24 ;;
255.255.255.128) echo 25 ;;
255.255.255.192) echo 26 ;;
255.255.255.224) echo 27 ;;
255.255.255.240) echo 28 ;;
255.255.255.248) echo 29 ;;
255.255.255.252) echo 30 ;;
255.255.255.254) echo 31 ;;
255.255.255.255) echo 32 ;;
*) return 1 ;;
esac
}
network_menu() {
while true; do
header
echo "Network"
echo "1. Show network status"
echo "2. DHCP on all interfaces"
echo "3. DHCP on one interface"
echo "4. Set static IPv4 on one interface"
echo "5. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) show_network_status ;;
2) network_dhcp_all ;;
3) network_dhcp_one ;;
4) network_static_one ;;
5) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
bee_services_list() {
for path in /etc/init.d/bee-*; do
[ -e "$path" ] || continue
basename "$path"
done
}
services_status_all() {
header
echo "bee service status"
echo
for svc in $(bee_services_list); do
if rc-service "$svc" status >/dev/null 2>&1; then
echo "- $svc: running"
else
echo "- $svc: stopped"
fi
done
pause
}
choose_service() {
svcs="$(bee_services_list)"
if [ -z "$svcs" ]; then
echo "No bee-* services found"
return 1
fi
echo "$svcs" | nl -w2 -s'. '
echo
printf 'Select service number: '
read -r idx
svc=$(echo "$svcs" | sed -n "${idx}p")
if [ -z "$svc" ]; then
echo "Invalid service selection"
return 1
fi
CHOSEN_SERVICE="$svc"
return 0
}
service_action_menu() {
header
echo "Service action"
echo
choose_service || { pause; return; }
svc="$CHOSEN_SERVICE"
echo
echo "Selected: $svc"
echo "1. status"
echo "2. restart"
echo "3. start"
echo "4. stop"
echo "5. toggle start/stop"
echo
printf 'Choice: '
read -r act
case "$act" in
1)
rc-service "$svc" status || true
;;
2)
rc-service "$svc" restart || true
;;
3)
rc-service "$svc" start || true
;;
4)
rc-service "$svc" stop || true
;;
5)
if rc-service "$svc" status >/dev/null 2>&1; then
rc-service "$svc" stop || true
else
rc-service "$svc" start || true
fi
;;
*)
echo "Invalid action"
;;
esac
pause
}
services_menu() {
while true; do
header
echo "bee Services"
echo "1. Status of all bee-* services"
echo "2. Manage one service (status/restart/start/stop/toggle)"
echo "3. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) services_status_all ;;
2) service_action_menu ;;
3) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
confirm_phrase() {
phrase="$1"
prompt="$2"
echo
printf '%s (%s): ' "$prompt" "$phrase"
read -r value
[ "$value" = "$phrase" ]
}
shutdown_menu() {
while true; do
header
echo "Shutdown/Reboot Tests"
echo "1. Reboot now"
echo "2. Power off now"
echo "3. Schedule poweroff in 60s"
echo "4. Cancel scheduled shutdown"
echo "5. IPMI chassis power status"
echo "6. IPMI chassis power soft"
echo "7. IPMI chassis power cycle"
echo "8. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1)
confirm_phrase "REBOOT" "Type confirmation" || { echo "Canceled"; pause; continue; }
reboot
;;
2)
confirm_phrase "POWEROFF" "Type confirmation" || { echo "Canceled"; pause; continue; }
poweroff
;;
3)
confirm_phrase "SCHEDULE" "Type confirmation" || { echo "Canceled"; pause; continue; }
shutdown -P +1 "bee test: scheduled poweroff in 60 seconds"
echo "Scheduled"
pause
;;
4)
shutdown -c || true
echo "Canceled (if any schedule existed)"
pause
;;
5)
ipmitool chassis power status || echo "ipmitool power status failed"
pause
;;
6)
confirm_phrase "IPMI-SOFT" "Type confirmation" || { echo "Canceled"; pause; continue; }
ipmitool chassis power soft || echo "ipmitool soft power failed"
pause
;;
7)
confirm_phrase "IPMI-CYCLE" "Type confirmation" || { echo "Canceled"; pause; continue; }
ipmitool chassis power cycle || echo "ipmitool power cycle failed"
pause
;;
8)
return
;;
*)
echo "Invalid choice"
pause
;;
esac
done
}
gpu_burn_10m() {
header
echo "GPU Burn (10 minutes)"
echo
if ! command -v gpu_burn >/dev/null 2>&1; then
echo "gpu_burn binary not found in PATH"
echo "Expected command: gpu_burn"
pause
return
fi
if ! command -v nvidia-smi >/dev/null 2>&1 || ! nvidia-smi -L >/dev/null 2>&1; then
echo "NVIDIA driver/GPU not ready (nvidia-smi failed)"
pause
return
fi
confirm_phrase "GPU-BURN" "Type confirmation to start benchmark" || { echo "Canceled"; pause; return; }
echo "Running: gpu_burn 600"
echo "Log: /var/log/bee-gpuburn.log"
gpu_burn 600 2>&1 | tee /var/log/bee-gpuburn.log
echo
echo "GPU Burn finished"
pause
}
gpu_benchmarks_menu() {
while true; do
header
echo "Benchmarks -> GPU"
echo "1. GPU Burn (10 minutes)"
echo "2. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) gpu_burn_10m ;;
2) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
benchmarks_menu() {
while true; do
header
echo "Benchmarks"
echo "1. GPU"
echo "2. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) gpu_benchmarks_menu ;;
2) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
run_cmd_log() {
label="$1"
cmd="$2"
log_file="$3"
{
echo "=== $label ==="
echo "time: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
echo "cmd: $cmd"
echo
sh -c "$cmd"
} >"$log_file" 2>&1
return $?
}
run_gpu_nvidia_acceptance_test() {
header
echo "System acceptance tests -> GPU NVIDIA"
echo
confirm_phrase "SAT-GPU" "Type confirmation to start tests" || { echo "Canceled"; pause; return; }
ts="$(date -u '+%Y%m%d-%H%M%S')"
base_dir="/var/log/bee-sat"
run_dir="$base_dir/gpu-nvidia-$ts"
archive="$base_dir/gpu-nvidia-$ts.tar.gz"
mkdir -p "$run_dir"
summary="$run_dir/summary.txt"
: >"$summary"
echo "Running acceptance commands..."
echo "Logs directory: $run_dir"
echo "Archive target: $archive"
echo
c1="nvidia-smi -q"
c2="dmidecode -t baseboard"
c3="dmidecode -t system"
c4="nvidia-bug-report.sh"
run_cmd_log "nvidia_smi_q" "$c1" "$run_dir/01-nvidia-smi-q.log"; rc1=$?
run_cmd_log "dmidecode_baseboard" "$c2" "$run_dir/02-dmidecode-baseboard.log"; rc2=$?
run_cmd_log "dmidecode_system" "$c3" "$run_dir/03-dmidecode-system.log"; rc3=$?
run_cmd_log "nvidia_bug_report" "$c4" "$run_dir/04-nvidia-bug-report.log"; rc4=$?
# Collect any bug report artifact generated in cwd.
bug_report="$(ls -1 nvidia-bug-report.log.gz 2>/dev/null | head -n1 || true)"
if [ -n "$bug_report" ] && [ -f "$bug_report" ]; then
cp -f "$bug_report" "$run_dir/"
fi
{
echo "run_at_utc=$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
echo "cmd_nvidia_smi_q_rc=$rc1"
echo "cmd_dmidecode_baseboard_rc=$rc2"
echo "cmd_dmidecode_system_rc=$rc3"
echo "cmd_nvidia_bug_report_rc=$rc4"
} >>"$summary"
tar -czf "$archive" -C "$base_dir" "gpu-nvidia-$ts"
tar_rc=$?
echo "archive_rc=$tar_rc" >>"$summary"
echo
echo "Done."
echo "- Logs: $run_dir"
echo "- Archive: $archive (rc=$tar_rc)"
pause
}
gpu_nvidia_sat_menu() {
while true; do
header
echo "System acceptance tests -> GPU NVIDIA"
echo "1. Run command pack"
echo "2. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) run_gpu_nvidia_acceptance_test ;;
2) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
system_acceptance_tests_menu() {
while true; do
header
echo "System acceptance tests"
echo "1. GPU NVIDIA"
echo "2. Back"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) gpu_nvidia_sat_menu ;;
2) return ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
run_audit_now() {
header
echo "Run audit now"
echo
/usr/local/bin/audit --output stdout > /var/log/bee-audit.json 2>/var/log/bee-audit.log
rc=$?
if [ "$rc" -eq 0 ]; then
echo "Audit completed successfully"
else
echo "Audit finished with errors (rc=$rc)"
fi
echo "Logs: /var/log/bee-audit.log, /var/log/bee-audit.json"
pause
}
check_required_tools() {
header
echo "Required tools check"
echo
for tool in dmidecode smartctl nvme ipmitool lspci audit nvidia-smi gpu_burn; do
if command -v "$tool" >/dev/null 2>&1; then
echo "- $tool: OK ($(command -v "$tool"))"
else
echo "- $tool: MISSING"
fi
done
pause
}
main_menu() {
while true; do
header
echo "Main Menu"
echo "1. Network setup"
echo "2. bee service management"
echo "3. Shutdown/reboot tests"
echo "4. Benchmarks"
echo "5. System acceptance tests"
echo "6. Run audit now"
echo "7. Check required tools"
echo "8. Show last audit log tail"
echo "9. Exit to console"
echo
printf 'Choice: '
read -r choice
case "$choice" in
1) network_menu ;;
2) services_menu ;;
3) shutdown_menu ;;
4) benchmarks_menu ;;
5) system_acceptance_tests_menu ;;
6) run_audit_now ;;
7) check_required_tools ;;
8)
header
tail -n 40 /var/log/bee-audit.log 2>/dev/null || echo "No /var/log/bee-audit.log"
echo
tail -n 20 /var/log/bee-audit.json 2>/dev/null || true
pause
;;
9) exit 0 ;;
*) echo "Invalid choice"; pause ;;
esac
done
}
main_menu