diff --git a/app/gather_info.sh b/app/gather_info.sh index 205efd5..337ef4a 100755 --- a/app/gather_info.sh +++ b/app/gather_info.sh @@ -143,6 +143,45 @@ while read -r line; do gpu_idx=$((gpu_idx + 1)) done < <(lspci 2>/dev/null | grep -iE 'vga|3d|display') +# GPU utilization (NVIDIA) +if command -v nvidia-smi &>/dev/null; then + nv_idx=0 + while IFS=',' read -r name util mem_used mem_total temp; do + echo "[nvidia_gpu:$nv_idx]" + echo "name=$(echo "$name" | xargs)" + echo "utilization_percent=$(echo "$util" | xargs)" + echo "memory_used_mb=$(echo "$mem_used" | xargs)" + echo "memory_total_mb=$(echo "$mem_total" | xargs)" + echo "temperature=$(echo "$temp" | xargs)" + nv_idx=$((nv_idx + 1)) + done < <(nvidia-smi --query-gpu=name,utilization.gpu,memory.used,memory.total,temperature.gpu --format=csv,noheader,nounits 2>/dev/null) +fi + +# GPU utilization (Intel) +igpu_cmd=$(command -v intel_gpu_top 2>/dev/null) +if [ -n "$igpu_cmd" ]; then + igpu_prefix="" + [ "$(id -u)" -ne 0 ] && igpu_prefix="sudo" + igpu_idx=0 + for drm in /sys/class/drm/card*; do + [ -d "$drm" ] || continue + driver=$(readlink "$drm/device/driver" 2>/dev/null | xargs basename 2>/dev/null) + [ "$driver" = "i915" ] || [ "$driver" = "xe" ] || continue + card=$(basename "$drm") + igpu_raw=$(timeout 2 $igpu_prefix intel_gpu_top -J -s 500 -d /dev/dri/"$card" 2>/dev/null) + if [ -n "$igpu_raw" ]; then + echo "[intel_gpu:$igpu_idx]" + busy=$(echo "$igpu_raw" | grep -oP '"busy"\s*:\s*\K[0-9.]+' | sort -rn | head -1) + echo "utilization_percent=${busy:-0}" + freq=$(echo "$igpu_raw" | grep -oP '"actual"\s*:\s*\K[0-9.]+' | head -1) + [ -n "$freq" ] && echo "frequency_mhz=${freq%.*}" + power=$(echo "$igpu_raw" | grep -oP '"GPU"\s*:\s*\K[0-9.]+' | head -1) + [ -n "$power" ] && echo "power_w=$power" + igpu_idx=$((igpu_idx + 1)) + fi + done +fi + # Network interfaces for iface in $(ls /sys/class/net/ 2>/dev/null); do [ "$iface" = "lo" ] && continue @@ -311,6 +350,22 @@ if command -v virsh &>/dev/null; then done fi +# Dropshell services +ds_idx=0 +for svc_dir in /home/dropshell/dropshell/services/*/; do + [ -d "$svc_dir" ] || continue + svc_env="$svc_dir/config/service.env" + [ -f "$svc_env" ] || continue + svc_name=$(basename "$svc_dir") + echo "[dropshell_service:$ds_idx]" + echo "name=$svc_name" + container_name=$(grep '^CONTAINER_NAME=' "$svc_env" 2>/dev/null | head -1 | cut -d= -f2 | tr -d '"') + [ -n "$container_name" ] && echo "container_name=$container_name" + template=$(grep '^TEMPLATE=' "$svc_env" 2>/dev/null | head -1 | cut -d= -f2 | tr -d '"') + [ -n "$template" ] && echo "template=$template" + ds_idx=$((ds_idx + 1)) +done + # Docker containers if command -v docker &>/dev/null; then _sudo docker ps -a --format '{{.Names}}\t{{.State}}\t{{.Image}}\t{{.Status}}' 2>/dev/null | while IFS=$'\t' read -r name state image status_text; do diff --git a/app/templates/index.html b/app/templates/index.html index 23d914d..1ef38fa 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -32,6 +32,21 @@ {% set max_temp.val = v|float %} {% endif %} {% endfor %} + {% set nvidia_gpus = d.get('nvidia_gpu', []) if d.get('nvidia_gpu') else [] %} + {% set intel_gpus = d.get('intel_gpu', []) if d.get('intel_gpu') else [] %} + {% set max_gpu_pct = namespace(val=-1.0) %} + {% for ng in nvidia_gpus %} + {% set gp = ng.get('utilization_percent', '0')|float %} + {% if gp > max_gpu_pct.val %} + {% set max_gpu_pct.val = gp %} + {% endif %} + {% endfor %} + {% for ig in intel_gpus %} + {% set gp = ig.get('utilization_percent', '0')|float %} + {% if gp > max_gpu_pct.val %} + {% set max_gpu_pct.val = gp %} + {% endif %} + {% endfor %} {% set cpu_pct = cpu.get('usage_percent', '0')|float %} {% set mem_pct = mem.get('usage_percent', '0')|float %} {% set disk_usages = d.get('disk_usage', []) if d.get('disk_usage') else [] %} @@ -91,6 +106,26 @@ {% set _ = containers.append(ct) %} {% endif %} {% endfor %} + {% set ds_services = d.get('dropshell_service', []) if d.get('dropshell_service') else [] %} + {% set svc_container_names = [] %} + {% for svc in ds_services %} + {% if svc.get('container_name') %} + {% set _ = svc_container_names.append(svc.get('container_name')) %} + {% endif %} + {% endfor %} + {% set orphan_containers = [] %} + {% for ct in containers %} + {% set ct_name = ct.get('name', '') %} + {% set ns = namespace(is_svc=false) %} + {% for cn in svc_container_names %} + {% if ct_name.startswith(cn ~ '-') %} + {% set ns.is_svc = true %} + {% endif %} + {% endfor %} + {% if not ns.is_svc %} + {% set _ = orphan_containers.append(ct) %} + {% endif %} + {% endfor %} {% if server.is_online %}
{% endif %} + {% if max_gpu_pct.val >= 0 %} +| GPU {{ loop.index0 }} | {{ gpu.get('description', '-')|clean_gpu }} | ||
| {{ ng.get('name', 'NVIDIA GPU ' ~ loop.index0) }} | +{{ ng.get('utilization_percent', '-') }}% | +{{ ng.get('memory_used_mb', '-') }} / {{ ng.get('memory_total_mb', '-') }} MB | +{{ ng.get('temperature', '-') }}°C | +
| Intel GPU {{ loop.index0 }} | +{{ ig.get('utilization_percent', '-') }}% | +{% if ig.get('frequency_mhz') %}{{ ig.get('frequency_mhz') }} MHz{% else %}-{% endif %} | +{% if ig.get('power_w') %}{{ ig.get('power_w') }} W{% else %}-{% endif %} | +
| {{ gpu.get('description', '-')|clean_gpu }} | |||