This commit is contained in:
root
2025-10-17 13:37:18 +02:00
commit 6be406c7da
9 changed files with 1437 additions and 0 deletions

206
templates/index.html Normal file
View File

@@ -0,0 +1,206 @@
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>PVE HA Panel</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="{{ url_for('static', filename='styles.css') }}" rel="stylesheet">
</head>
<body>
<div class="container py-4">
<div class="d-flex flex-wrap justify-content-between align-items-center mb-3 gap-2">
<h1 class="h4 m-0">PVE HA Panel</h1>
<div class="d-flex flex-wrap align-items-center gap-2">
<input class="form-control form-control-sm" id="node" value="{{ node }}" style="width: 180px">
<button class="btn btn-outline-secondary btn-sm" id="btnToggleAll">Collapse/Expand all</button>
<div class="vr d-none d-md-block"></div>
<button class="btn btn-primary btn-sm" id="btnRefresh">Refresh now</button>
<div class="input-group input-group-sm" style="width:220px">
<span class="input-group-text">Auto-refresh</span>
<select class="form-select" id="selInterval" disabled>
<option value="10000">10 s</option>
<option value="20000">20 s</option>
<option value="30000" selected>30 s</option>
<option value="45000">45 s</option>
<option value="60000">60 s</option>
<option value="120000">120 s</option>
</select>
<button class="btn btn-outline-success" id="btnAuto">OFF</button>
</div>
<div class="vr d-none d-md-block"></div>
<button type="button" class="btn btn-success btn-sm" id="btnEnable">Enable maintenance</button>
<button type="button" class="btn btn-danger btn-sm" id="btnDisable">Disable maintenance</button>
</div>
</div>
<!-- Global loading -->
<div id="global-loading" class="d-flex align-items-center gap-2 mb-3">
<div class="spinner-border spinner-border-sm" role="status"></div>
<span class="small text-muted">Loading data…</span>
</div>
<!-- HEALTH -->
<div class="card mb-3 border-0 shadow health-card">
<div class="card-body d-flex flex-wrap align-items-center gap-3">
<div class="health-dot" id="healthDot"></div>
<div>
<div class="fw-bold" id="healthTitle">Loading…</div>
<div class="text-muted small" id="healthSub"></div>
</div>
</div>
</div>
<ul class="nav nav-tabs mb-3" id="mainTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tab-ha" type="button">HA</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-nonha" type="button">VM/CT (non-HA)</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-nodes" type="button">Nodes</button>
</li>
</ul>
<div class="tab-content">
<!-- TAB: HA -->
<div class="tab-pane fade show active" id="tab-ha">
<div class="accordion" id="acc">
<!-- Cluster / Quorum -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-q">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-q">
Cluster / Quorum
</button>
</h2>
<div id="c-q" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body">
<div id="q-summary" class="mb-3 small">Loading…</div>
<div class="row g-3" id="q-cards"><div class="text-muted small">Loading…</div></div>
</div>
</div>
</div>
<!-- Systemd -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-sd">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-sd">
Systemd (HA)
</button>
</h2>
<div id="c-sd" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body">
<div id="units" class="d-flex flex-wrap gap-2"><span class="text-muted small">Loading…</span></div>
</div>
</div>
</div>
<!-- Replication -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-repl">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-repl">
Replication (pvesr)
</button>
</h2>
<div id="c-repl" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body"><div id="repl"><span class="text-muted small">Loading…</span></div></div>
</div>
</div>
<!-- HA resources -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-res">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-res">
HA — resources
</button>
</h2>
<div id="c-res" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body table-responsive">
<table class="table table-sm table-striped align-middle table-nowrap" id="ha-res">
<thead><tr><th>SID</th><th>State</th><th>Node</th><th>Group</th><th>Flags/Comment</th></tr></thead>
<tbody></tbody>
</table>
<div class="small text-muted">Click a row to expand VM/CT details.</div>
</div>
</div>
</div>
<!-- HA status -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-hastatus">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-hastatus">
HA — status
</button>
</h2>
<div id="c-hastatus" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body table-responsive">
<table class="table table-sm table-striped align-middle table-nowrap" id="ha-status">
<thead><tr><th>Node</th><th>Status</th><th>CRM</th><th>LRM</th></tr></thead>
<tbody><tr><td colspan="4" class="text-muted">Loading…</td></tr></tbody>
</table>
</div>
</div>
</div>
<!-- Raw -->
<div class="accordion-item">
<h2 class="accordion-header" id="h-raw">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#c-raw">
Raw: pvecm / cfgtool
</button>
</h2>
<div id="c-raw" class="accordion-collapse collapse" data-bs-parent="#acc">
<div class="accordion-body">
<div class="row g-3">
<div class="col-lg-6"><pre id="pvecm" class="mb-0 small"></pre></div>
<div class="col-lg-6"><pre id="cfgtool" class="mb-0 small"></pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- TAB: Non-HA -->
<div class="tab-pane fade" id="tab-nonha">
<div class="card border-0">
<div class="card-body table-responsive">
<table class="table table-sm table-striped align-middle table-nowrap" id="nonha">
<thead><tr><th>SID</th><th>Type</th><th>Name</th><th>Node</th><th>Status</th></tr></thead>
<tbody><tr><td colspan="5" class="text-muted">Loading…</td></tr></tbody>
</table>
<div class="small text-muted">Click a row to expand VM/CT details.</div>
</div>
</div>
</div>
<!-- TAB: Nodes (expandable) -->
<div class="tab-pane fade" id="tab-nodes">
<div class="card border-0">
<div class="card-body table-responsive">
<table class="table table-sm table-striped align-middle table-nowrap" id="nodes">
<thead><tr><th>Node</th><th>Status</th><th>CPU</th><th>Load</th><th>Mem</th><th>RootFS</th><th>Uptime</th></tr></thead>
<tbody><tr><td colspan="7" class="text-muted">Loading…</td></tr></tbody>
</table>
<div class="small text-muted">Click a row to expand node details.</div>
</div>
</div>
</div>
</div>
<div class="text-muted small mt-3" id="footer"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="{{ url_for('static', filename='main.js') }}"></script>
</body>
</html>