- llm: Local LLM wrapper for llama-swap - homelab-status: Quick K8s/cluster health check - calc: Python/JS REPL for quick calculations - transcribe: Whisper audio transcription wrapper Added to fish PATH.
136 lines
4.6 KiB
Bash
Executable File
136 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Quick homelab status check
|
||
# Usage: homelab-status [--full]
|
||
|
||
set -e
|
||
|
||
FULL=false
|
||
[[ "$1" == "--full" || "$1" == "-f" ]] && FULL=true
|
||
|
||
# Colors
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
ok() { echo -e "${GREEN}✓${NC} $1"; }
|
||
warn() { echo -e "${YELLOW}⚠${NC} $1"; }
|
||
fail() { echo -e "${RED}✗${NC} $1"; }
|
||
info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
||
|
||
echo "═══════════════════════════════════════"
|
||
echo " 🏠 HOMELAB STATUS"
|
||
echo "═══════════════════════════════════════"
|
||
echo ""
|
||
|
||
# K8s Cluster
|
||
echo "☸️ KUBERNETES"
|
||
echo "───────────────────────────────────────"
|
||
|
||
if ! kubectl cluster-info &>/dev/null; then
|
||
fail "Cluster unreachable"
|
||
else
|
||
# Nodes
|
||
NODES_TOTAL=$(kubectl get nodes --no-headers 2>/dev/null | wc -l)
|
||
NODES_READY=$(kubectl get nodes --no-headers 2>/dev/null | grep -c " Ready" || echo 0)
|
||
if [[ "$NODES_READY" == "$NODES_TOTAL" ]]; then
|
||
ok "Nodes: $NODES_READY/$NODES_TOTAL Ready"
|
||
else
|
||
warn "Nodes: $NODES_READY/$NODES_TOTAL Ready"
|
||
fi
|
||
|
||
# Pods
|
||
PODS_RUNNING=$(kubectl get pods -A --no-headers 2>/dev/null | grep -c "Running" || echo 0)
|
||
PODS_NOT_RUNNING=$(kubectl get pods -A --no-headers 2>/dev/null | grep -cvE "Running|Completed" || echo 0)
|
||
if [[ "$PODS_NOT_RUNNING" == "0" ]]; then
|
||
ok "Pods: $PODS_RUNNING Running"
|
||
else
|
||
warn "Pods: $PODS_RUNNING Running, $PODS_NOT_RUNNING not ready"
|
||
fi
|
||
|
||
# Show failed pods if any
|
||
if [[ "$PODS_FAILED" != "0" ]] || $FULL; then
|
||
kubectl get pods -A --no-headers 2>/dev/null | grep -E "(Error|CrashLoop|Failed|Pending)" | head -5 | while read -r line; do
|
||
echo " $line"
|
||
done
|
||
fi
|
||
fi
|
||
echo ""
|
||
|
||
# Alertmanager
|
||
echo "🚨 ALERTS"
|
||
echo "───────────────────────────────────────"
|
||
ALERTMANAGER_URL="http://alertmanager.monitoring.192.168.153.240.nip.io"
|
||
ALERTS=$(curl -sf "$ALERTMANAGER_URL/api/v2/alerts?active=true&silenced=false" 2>/dev/null || echo "[]")
|
||
ALERT_COUNT=$(echo "$ALERTS" | jq 'length' 2>/dev/null || echo "?")
|
||
|
||
if [[ "$ALERT_COUNT" == "0" ]]; then
|
||
ok "No active alerts"
|
||
elif [[ "$ALERT_COUNT" == "?" ]]; then
|
||
warn "Alertmanager unreachable"
|
||
else
|
||
warn "$ALERT_COUNT active alert(s)"
|
||
echo "$ALERTS" | jq -r '.[].labels.alertname' 2>/dev/null | head -5 | while read -r alert; do
|
||
echo " - $alert"
|
||
done
|
||
fi
|
||
echo ""
|
||
|
||
# Key Services
|
||
echo "🔌 SERVICES"
|
||
echo "───────────────────────────────────────"
|
||
|
||
check_service() {
|
||
local name="$1"
|
||
local url="$2"
|
||
if curl -sf --max-time 3 "$url" >/dev/null 2>&1; then
|
||
ok "$name"
|
||
else
|
||
fail "$name"
|
||
fi
|
||
}
|
||
|
||
check_service "Grafana" "http://grafana.monitoring.192.168.153.240.nip.io/api/health"
|
||
check_service "ArgoCD" "https://argocd.taildb3494.ts.net" 2>/dev/null || check_service "ArgoCD" "http://argocd-server.argocd.svc:80" 2>/dev/null || warn "ArgoCD (via Tailscale only)"
|
||
check_service "Longhorn" "http://ui.longhorn-system.192.168.153.240.nip.io"
|
||
|
||
# Ollama (homelab)
|
||
if curl -sf --max-time 3 "http://100.85.116.57:11434/api/tags" >/dev/null 2>&1; then
|
||
ok "Ollama (homelab)"
|
||
else
|
||
warn "Ollama (homelab) - unreachable"
|
||
fi
|
||
echo ""
|
||
|
||
# Local LLM
|
||
echo "🤖 LOCAL LLM"
|
||
echo "───────────────────────────────────────"
|
||
if curl -sf "http://127.0.0.1:8080/health" >/dev/null 2>&1; then
|
||
ok "llama-swap running"
|
||
MODELS=$(curl -s "http://127.0.0.1:8080/v1/models" | jq -r '.data[].id' 2>/dev/null | tr '\n' ', ' | sed 's/,$//')
|
||
info "Models: $MODELS"
|
||
else
|
||
warn "llama-swap not running"
|
||
info "Start: systemctl --user start llama-swap"
|
||
fi
|
||
echo ""
|
||
|
||
# Storage (if full)
|
||
if $FULL; then
|
||
echo "💾 STORAGE"
|
||
echo "───────────────────────────────────────"
|
||
kubectl get pvc -A --no-headers 2>/dev/null | head -10 | while read -r ns name status vol cap mode class age; do
|
||
if [[ "$status" == "Bound" ]]; then
|
||
ok "$ns/$name ($cap)"
|
||
else
|
||
warn "$ns/$name - $status"
|
||
fi
|
||
done
|
||
echo ""
|
||
fi
|
||
|
||
echo "═══════════════════════════════════════"
|
||
echo " $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||
echo "═══════════════════════════════════════"
|