secubox-openwrt/luci-app-system-hub/root/usr/libexec/rpcd/luci.system-hub
CyberMind-FR 34fe2dc26a feat: complete System Hub implementation - central control dashboard
Implements comprehensive system control and monitoring dashboard with health
metrics, service management, system logs, and backup/restore functionality.

Features:
- Real-time system monitoring with visual gauges (CPU, RAM, Disk)
- Comprehensive system information (hostname, model, uptime, kernel)
- Health metrics with temperature monitoring and storage breakdown
- Service management with start/stop/restart/enable/disable actions
- System log viewer with filtering and configurable line count
- Configuration backup creation and download (base64 encoded)
- Configuration restore from backup file
- System reboot functionality with confirmation

Components:
- RPCD backend (luci.system-hub): 10 ubus methods
  * status, get_system_info, get_health
  * list_services, service_action
  * get_logs, backup_config, restore_config
  * reboot, get_storage
- 4 JavaScript views: overview, services, logs, backup
- ACL with read/write permissions segregation
- Comprehensive README with API documentation

Technical implementation:
- System info from /proc filesystem and sysinfo
- Health metrics: CPU load, memory breakdown, disk usage, temperature
- Service control via /etc/init.d scripts
- Log retrieval via logread with filtering
- Backup/restore using sysupgrade with base64 encoding
- Visual gauges with SVG circular progress indicators
- Color-coded health status (green/orange/red)

Dashboard Features:
- Circular gauges for CPU, Memory, Disk (120px with 10px stroke)
- System information cards with detailed metrics
- Temperature monitoring with thermal zone detection
- Storage table for all mount points with progress bars
- Service table with inline action buttons
- Terminal-style log display (black bg, green text)
- File upload for backup restore
- Modal confirmations for destructive actions

Architecture follows SecuBox standards:
- RPCD naming convention (luci. prefix)
- Menu paths match view file structure
- All JavaScript in strict mode
- Form-based configuration management
- Comprehensive error handling

Dependencies: coreutils, coreutils-base64

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 11:02:07 +01:00

450 lines
11 KiB
Bash
Executable File

#!/bin/sh
# System Hub RPCD Backend
# Central system control and monitoring
. /lib/functions.sh
. /usr/share/libubox/jshn.sh
# Get comprehensive system status
status() {
json_init
# Basic info
local hostname=$(cat /proc/sys/kernel/hostname 2>/dev/null || echo "unknown")
local uptime=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo 0)
local model=$(cat /tmp/sysinfo/model 2>/dev/null || cat /proc/device-tree/model 2>/dev/null | tr -d '\0' || echo "Unknown")
json_add_string "hostname" "$hostname"
json_add_string "model" "$model"
json_add_int "uptime" "$uptime"
# Health metrics
local cpu_load=$(awk '{print $1}' /proc/loadavg 2>/dev/null || echo "0")
# Memory
local mem_total=$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_free=$(awk '/MemFree/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_available=$(awk '/MemAvailable/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_used=$((mem_total - mem_available))
local mem_percent=0
if [ "$mem_total" -gt 0 ]; then
mem_percent=$(( (mem_used * 100) / mem_total ))
fi
json_add_object "health"
json_add_string "cpu_load" "$cpu_load"
json_add_int "mem_total_kb" "$mem_total"
json_add_int "mem_used_kb" "$mem_used"
json_add_int "mem_percent" "$mem_percent"
json_close_object
# Storage
local disk_root=$(df / | awk 'NR==2 {gsub("%","",$5); print $5}' 2>/dev/null || echo 0)
json_add_int "disk_percent" "$disk_root"
# Service count
local service_count=$(ls /etc/init.d/ 2>/dev/null | wc -l)
json_add_int "service_count" "$service_count"
json_dump
}
# Get detailed system information
get_system_info() {
json_init
# Hostname
local hostname=$(cat /proc/sys/kernel/hostname 2>/dev/null || echo "unknown")
json_add_string "hostname" "$hostname"
# Model
local model=$(cat /tmp/sysinfo/model 2>/dev/null || cat /proc/device-tree/model 2>/dev/null | tr -d '\0' || echo "Unknown")
json_add_string "model" "$model"
# Board name
local board=$(cat /tmp/sysinfo/board_name 2>/dev/null || echo "unknown")
json_add_string "board" "$board"
# OpenWrt version
local openwrt_version=$(cat /etc/openwrt_release 2>/dev/null | grep DISTRIB_DESCRIPTION | cut -d"'" -f2 || echo "Unknown")
json_add_string "openwrt_version" "$openwrt_version"
# Kernel version
local kernel=$(uname -r 2>/dev/null || echo "unknown")
json_add_string "kernel" "$kernel"
# Architecture
local arch=$(uname -m 2>/dev/null || echo "unknown")
json_add_string "architecture" "$arch"
# Uptime
local uptime_sec=$(awk '{print int($1)}' /proc/uptime 2>/dev/null || echo 0)
json_add_int "uptime_seconds" "$uptime_sec"
# Uptime formatted
local days=$((uptime_sec / 86400))
local hours=$(((uptime_sec % 86400) / 3600))
local mins=$(((uptime_sec % 3600) / 60))
json_add_string "uptime_formatted" "${days}d ${hours}h ${mins}m"
# Local time
local localtime=$(date '+%Y-%m-%d %H:%M:%S' 2>/dev/null || echo "unknown")
json_add_string "local_time" "$localtime"
json_dump
}
# Get system health metrics
get_health() {
json_init
# CPU info
local cpu_model=$(awk -F': ' '/model name|Processor/ {print $2; exit}' /proc/cpuinfo 2>/dev/null || echo "Unknown")
local cpu_cores=$(grep -c "^processor" /proc/cpuinfo 2>/dev/null || echo 1)
json_add_object "cpu"
json_add_string "model" "$cpu_model"
json_add_int "cores" "$cpu_cores"
json_close_object
# Load average
local load=$(cat /proc/loadavg 2>/dev/null || echo "0 0 0")
local load1=$(echo $load | awk '{print $1}')
local load5=$(echo $load | awk '{print $2}')
local load15=$(echo $load | awk '{print $3}')
json_add_object "load"
json_add_string "1min" "$load1"
json_add_string "5min" "$load5"
json_add_string "15min" "$load15"
json_close_object
# Memory
local mem_total=$(awk '/MemTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_free=$(awk '/MemFree/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_available=$(awk '/MemAvailable/ {print $2}' /proc/meminfo 2>/dev/null || echo $mem_free)
local mem_buffers=$(awk '/Buffers/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_cached=$(awk '/^Cached/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
local mem_used=$((mem_total - mem_available))
local mem_percent=0
if [ "$mem_total" -gt 0 ]; then
mem_percent=$(( (mem_used * 100) / mem_total ))
fi
json_add_object "memory"
json_add_int "total_kb" "$mem_total"
json_add_int "free_kb" "$mem_free"
json_add_int "available_kb" "$mem_available"
json_add_int "used_kb" "$mem_used"
json_add_int "buffers_kb" "$mem_buffers"
json_add_int "cached_kb" "$mem_cached"
json_add_int "percent" "$mem_percent"
json_close_object
# Storage
json_add_array "storage"
df -h | tail -n +2 | while read filesystem size used avail percent mountpoint; do
local percent_num=$(echo $percent | tr -d '%')
json_add_object ""
json_add_string "filesystem" "$filesystem"
json_add_string "size" "$size"
json_add_string "used" "$used"
json_add_string "available" "$avail"
json_add_int "percent" "$percent_num"
json_add_string "mountpoint" "$mountpoint"
json_close_object
done
json_close_array
# Temperature
json_add_array "temperatures"
for zone in /sys/class/thermal/thermal_zone*/temp; do
if [ -f "$zone" ]; then
local temp=$(cat "$zone" 2>/dev/null || echo 0)
local temp_c=$((temp / 1000))
local zone_name=$(basename $(dirname "$zone"))
json_add_object ""
json_add_string "zone" "$zone_name"
json_add_int "celsius" "$temp_c"
json_close_object
fi
done
json_close_array
json_dump
}
# List all services with status
list_services() {
json_init
json_add_array "services"
for service in /etc/init.d/*; do
[ -x "$service" ] || continue
local name=$(basename "$service")
# Skip special scripts
case "$name" in
boot|done|functions|rc.*|sysctl|umount) continue ;;
esac
# Check if enabled
local enabled=0
[ -f "/etc/rc.d/S"*"$name" ] && enabled=1
# Check if running
local running=0
"$service" running >/dev/null 2>&1 && running=1
json_add_object ""
json_add_string "name" "$name"
json_add_boolean "enabled" "$enabled"
json_add_boolean "running" "$running"
json_close_object
done
json_close_array
json_dump
}
# Perform service action
service_action() {
read -r input
json_load "$input"
local service action
json_get_var service service
json_get_var action action
json_cleanup
if [ -z "$service" ] || [ -z "$action" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "Service and action are required"
json_dump
return 1
fi
local service_script="/etc/init.d/$service"
if [ ! -x "$service_script" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "Service not found: $service"
json_dump
return 1
fi
local result=0
case "$action" in
start|stop|restart)
"$service_script" "$action" >/dev/null 2>&1
result=$?
;;
enable)
"$service_script" enable >/dev/null 2>&1
result=$?
;;
disable)
"$service_script" disable >/dev/null 2>&1
result=$?
;;
*)
json_init
json_add_boolean "success" 0
json_add_string "message" "Invalid action: $action"
json_dump
return 1
;;
esac
json_init
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Service $service $action successful"
else
json_add_boolean "success" 0
json_add_string "message" "Service $service $action failed"
fi
json_dump
}
# Get system logs
get_logs() {
read -r input
json_load "$input"
local lines filter
json_get_var lines lines "100"
json_get_var filter filter ""
json_cleanup
json_init
json_add_array "logs"
if [ -n "$filter" ]; then
logread | tail -n "$lines" | grep -i "$filter" | while IFS= read -r line; do
json_add_string "" "$line"
done
else
logread | tail -n "$lines" | while IFS= read -r line; do
json_add_string "" "$line"
done
fi
json_close_array
json_dump
}
# Create backup
backup_config() {
local backup_file="/tmp/backup-$(date +%Y%m%d-%H%M%S).tar.gz"
# Create backup
sysupgrade -b "$backup_file" >/dev/null 2>&1
if [ ! -f "$backup_file" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "Backup creation failed"
json_dump
return 1
fi
# Encode to base64
local backup_data=$(base64 < "$backup_file" 2>/dev/null)
local backup_size=$(stat -c%s "$backup_file" 2>/dev/null || echo 0)
# Cleanup
rm -f "$backup_file"
json_init
json_add_boolean "success" 1
json_add_string "data" "$backup_data"
json_add_int "size" "$backup_size"
json_add_string "filename" "backup-$(date +%Y%m%d-%H%M%S).tar.gz"
json_dump
}
# Restore configuration
restore_config() {
read -r input
json_load "$input"
local backup_data
json_get_var backup_data data
json_cleanup
if [ -z "$backup_data" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "No backup data provided"
json_dump
return 1
fi
local backup_file="/tmp/restore-$(date +%s).tar.gz"
# Decode base64
echo "$backup_data" | base64 -d > "$backup_file" 2>/dev/null
if [ ! -f "$backup_file" ]; then
json_init
json_add_boolean "success" 0
json_add_string "message" "Failed to decode backup data"
json_dump
return 1
fi
# Restore
sysupgrade -r "$backup_file" >/dev/null 2>&1
local result=$?
# Cleanup
rm -f "$backup_file"
json_init
if [ "$result" -eq 0 ]; then
json_add_boolean "success" 1
json_add_string "message" "Configuration restored successfully. Reboot required."
else
json_add_boolean "success" 0
json_add_string "message" "Configuration restore failed"
fi
json_dump
}
# Reboot system
reboot_system() {
json_init
json_add_boolean "success" 1
json_add_string "message" "System reboot initiated"
json_dump
# Reboot after 3 seconds
( sleep 3 && reboot ) &
}
# Get storage details
get_storage() {
json_init
json_add_array "storage"
df -h | tail -n +2 | while read filesystem size used avail percent mountpoint; do
local percent_num=$(echo $percent | tr -d '%')
json_add_object ""
json_add_string "filesystem" "$filesystem"
json_add_string "size" "$size"
json_add_string "used" "$used"
json_add_string "available" "$avail"
json_add_int "percent" "$percent_num"
json_add_string "mountpoint" "$mountpoint"
json_close_object
done
json_close_array
json_dump
}
# Main dispatcher
case "$1" in
list)
cat << 'EOF'
{
"status": {},
"get_system_info": {},
"get_health": {},
"list_services": {},
"service_action": { "service": "string", "action": "string" },
"get_logs": { "lines": 100, "filter": "" },
"backup_config": {},
"restore_config": { "data": "string" },
"reboot": {},
"get_storage": {}
}
EOF
;;
call)
case "$2" in
status) status ;;
get_system_info) get_system_info ;;
get_health) get_health ;;
list_services) list_services ;;
service_action) service_action ;;
get_logs) get_logs ;;
backup_config) backup_config ;;
restore_config) restore_config ;;
reboot) reboot_system ;;
get_storage) get_storage ;;
*)
json_init
json_add_boolean "success" 0
json_add_string "error" "Unknown method: $2"
json_dump
;;
esac
;;
esac