homelab-codex-ws/scripts/bootstrap/discover-node.sh

131 lines
3.4 KiB
Bash
Raw Normal View History

2026-05-12 13:18:00 +02:00
#!/bin/bash
# scripts/bootstrap/discover-node.sh
# Node discovery script for the homelab platform.
# Collects system information and outputs it in JSON format.
set -e
# Help function
show_help() {
echo "Usage: $0 [options]"
echo "Options:"
echo " --json Output in JSON format (default)"
echo " --yaml Output in YAML format"
echo " --help Show this help"
}
OUTPUT_FORMAT="json"
while [[ "$#" -gt 0 ]]; do
case $1 in
--json) OUTPUT_FORMAT="json"; shift ;;
--yaml) OUTPUT_FORMAT="yaml"; shift ;;
--help) show_help; exit 0 ;;
*) echo "Unknown parameter: $1"; show_help; exit 1 ;;
esac
done
# Check dependencies
for cmd in hostnamectl lscpu free lsblk ip curl; do
if ! command -v "$cmd" &> /dev/null; then
echo "Error: Required command '$cmd' not found." >&2
exit 1
fi
done
# Collect Data
HOSTNAME=$(hostname)
OS_DISTRO=$(grep PRETTY_NAME /etc/os-release | cut -d'"' -f2)
ARCH=$(uname -m)
CPU_MODEL=$(lscpu | grep "Model name:" | sed 's/Model name:[[:space:]]*//')
CPU_CORES=$(lscpu | grep "^CPU(s):" | awk '{print $2}')
CPU_THREADS=$(lscpu | grep "^Thread(s) per core:" | awk '{print $4 * $CPU_CORES}') # Simplistic
RAM_TOTAL_GB=$(free -g | grep "Mem:" | awk '{print $2}')
# Disks
DISKS=$(lsblk -dno NAME,SIZE,TYPE,MODEL | grep disk | awk '{printf "{\"name\": \"%s\", \"size\": \"%s\", \"model\": \"%s\"},", $1, $2, $4}' | sed 's/,$//')
# GPU Presence
GPU_PRESENT=false
if lspci | grep -i 'vga\|3d\|display' | grep -i 'nvidia\|amd\|intel' > /dev/null; then
GPU_PRESENT=true
GPU_INFO=$(lspci | grep -i 'vga\|3d\|display' | head -n 1 | cut -d ':' -f3 | sed 's/^[[:space:]]*//')
fi
# Virtualization
VIRT_SUPPORTED=false
if lscpu | grep "Virtualization:" > /dev/null; then
VIRT_SUPPORTED=true
VIRT_TYPE=$(lscpu | grep "Virtualization:" | awk '{print $2}')
fi
# Network Interfaces
INTERFACES=$(ip -j addr show | jq -c '[.[] | {name: .ifname, active: (if .operstate == "UP" then true else false end), ips: [.addr_info[].local]}]' 2>/dev/null || ip addr show | grep '^[0-9]' | awk '{print $2}' | sed 's/://' | xargs -I {} echo -n "\"{}\", " | sed 's/, $//')
# Tailscale
TAILSCALE_STATUS="not-installed"
TAILSCALE_IP="null"
if command -v tailscale &> /dev/null; then
if tailscale status &> /dev/null; then
TAILSCALE_STATUS="active"
TAILSCALE_IP=$(tailscale ip -4)
else
TAILSCALE_STATUS="installed-inactive"
fi
fi
# Docker
DOCKER_AVAILABLE=false
if command -v docker &> /dev/null; then
if docker info &> /dev/null; then
DOCKER_AVAILABLE=true
fi
fi
# Connectivity
CONNECTIVITY="unknown"
if curl -s --head https://google.com &> /dev/null; then
CONNECTIVITY="internet-access"
fi
# Output Construction (JSON)
cat <<EOF
{
"hostname": "$HOSTNAME",
"os": {
"distro": "$OS_DISTRO",
"arch": "$ARCH"
},
"hardware": {
"cpu": {
"model": "$CPU_MODEL",
"cores": $CPU_CORES,
"threads": $(lscpu | grep "^CPU(s):" | awk '{print $2}')
},
"memory": {
"total_gb": $RAM_TOTAL_GB
},
"gpu": {
"present": $GPU_PRESENT,
"info": "${GPU_INFO:-none}"
},
"disks": [$DISKS]
},
"virtualization": {
"supported": $VIRT_SUPPORTED,
"type": "${VIRT_TYPE:-none}"
},
"network": {
"interfaces": $INTERFACES,
"tailscale": {
"status": "$TAILSCALE_STATUS",
"ip": "$TAILSCALE_IP"
},
"connectivity": "$CONNECTIVITY"
},
"docker": {
"available": $DOCKER_AVAILABLE
}
}
EOF