Features: - Service health monitoring with response times - Proxmox cluster integration (nodes, VMs, containers) - PBS backup server monitoring - Camera viewer with WebRTC (go2rtc) - Docker container monitoring - Uptime Kuma integration - Mobile-friendly responsive design - YAML-based configuration for easy setup
67 lines
4.6 KiB
HTML
67 lines
4.6 KiB
HTML
<div class="grid grid-cols-2 lg:grid-cols-4 gap-2">
|
|
{% for node in nodes_status %}
|
|
<div class="card rounded-lg p-3 cursor-pointer" onclick="toggleNodeExpand(this)">
|
|
<div class="flex items-center justify-between mb-2">
|
|
<div class="flex items-center gap-2">
|
|
<span class="w-2 h-2 rounded-full {% if node.status == 'online' %}bg-emerald-500{% else %}bg-red-500{% endif %}"></span>
|
|
<span class="font-semibold text-sm">{{ node.name }}</span>
|
|
</div>
|
|
{% if node.uptime_hours %}
|
|
<span class="text-xs text-gray-500">{{ (node.uptime_hours / 24) | round(1) }}d</span>
|
|
{% endif %}
|
|
</div>
|
|
|
|
{% if node.status == 'online' %}
|
|
<div class="mb-2">
|
|
<div class="flex items-center justify-between text-xs mb-1">
|
|
<span class="text-gray-400">CPU</span>
|
|
<span class="{% if node.cpu_percent and node.cpu_percent > 80 %}text-red-400{% elif node.cpu_percent and node.cpu_percent > 60 %}text-amber-400{% else %}text-emerald-400{% endif %}">{{ node.cpu_percent | default(0) | round(1) }}%</span>
|
|
</div>
|
|
<div class="progress-bar"><div class="progress-fill {% if node.cpu_percent and node.cpu_percent > 80 %}bg-red-500{% elif node.cpu_percent and node.cpu_percent > 60 %}bg-amber-500{% else %}bg-emerald-500{% endif %}" style="width: {{ node.cpu_percent | default(0) }}%"></div></div>
|
|
</div>
|
|
<div class="mb-2">
|
|
<div class="flex items-center justify-between text-xs mb-1">
|
|
<span class="text-gray-400">RAM</span>
|
|
<span class="{% if node.memory_percent and node.memory_percent > 85 %}text-red-400{% elif node.memory_percent and node.memory_percent > 70 %}text-amber-400{% else %}text-blue-400{% endif %}">{% if node.memory_used_gb %}{{ node.memory_used_gb }}{% else %}?{% endif %}/{% if node.memory_total_gb %}{{ node.memory_total_gb }}{% else %}?{% endif %}GB</span>
|
|
</div>
|
|
<div class="progress-bar"><div class="progress-fill {% if node.memory_percent and node.memory_percent > 85 %}bg-red-500{% elif node.memory_percent and node.memory_percent > 70 %}bg-amber-500{% else %}bg-blue-500{% endif %}" style="width: {{ node.memory_percent | default(0) }}%"></div></div>
|
|
</div>
|
|
<div>
|
|
<div class="flex items-center justify-between text-xs mb-1">
|
|
<span class="text-gray-400">Disk</span>
|
|
<span class="{% if node.disk_percent and node.disk_percent > 85 %}text-red-400{% elif node.disk_percent and node.disk_percent > 70 %}text-amber-400{% else %}text-purple-400{% endif %}">{{ node.disk_percent | default(0) | round(1) }}%</span>
|
|
</div>
|
|
<div class="progress-bar"><div class="progress-fill {% if node.disk_percent and node.disk_percent > 85 %}bg-red-500{% elif node.disk_percent and node.disk_percent > 70 %}bg-amber-500{% else %}bg-purple-500{% endif %}" style="width: {{ node.disk_percent | default(0) }}%"></div></div>
|
|
</div>
|
|
|
|
<!-- Expandable VM/CT list -->
|
|
<div class="node-expanded hidden mt-2 pt-2 border-t border-gray-700">
|
|
{% if node.vms %}
|
|
<div class="text-[10px] text-gray-400 mb-1">VMs ({{ node.vms | length }})</div>
|
|
<div class="flex flex-wrap gap-1 mb-2">
|
|
{% for vm in node.vms[:5] %}
|
|
<span class="px-1 py-0.5 rounded text-[9px] {% if vm.status == 'running' %}bg-emerald-900/50 text-emerald-400{% else %}bg-gray-700 text-gray-400{% endif %}">{{ vm.name[:10] }}</span>
|
|
{% endfor %}
|
|
{% if node.vms | length > 5 %}<span class="text-[9px] text-gray-500">+{{ node.vms | length - 5 }}</span>{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% if node.containers %}
|
|
<div class="text-[10px] text-gray-400 mb-1">LXC ({{ node.containers | length }})</div>
|
|
<div class="flex flex-wrap gap-1">
|
|
{% for ct in node.containers[:5] %}
|
|
<span class="px-1 py-0.5 rounded text-[9px] {% if ct.status == 'running' %}bg-blue-900/50 text-blue-400{% else %}bg-gray-700 text-gray-400{% endif %}">{{ ct.name[:10] }}</span>
|
|
{% endfor %}
|
|
{% if node.containers | length > 5 %}<span class="text-[9px] text-gray-500">+{{ node.containers | length - 5 }}</span>{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% else %}
|
|
<div class="text-center text-red-400 text-xs py-2">Offline</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% if cluster_uptime %}
|
|
<div class="text-xs text-gray-500 mt-2 text-right">Cluster total: {{ cluster_uptime }}h</div>
|
|
{% endif %}
|