#!/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