diff --git a/README.md b/README.md index b2f493a..439a3f7 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ git pull --rebase source venv/bin/activate pip install -r requirements.txt deactivate -sudo systemctl restart pve-ha-web +systemctl restart pve-ha-web ``` --- @@ -140,10 +140,10 @@ sudo systemctl restart pve-ha-web ## Uninstall ```bash -sudo systemctl disable --now pve-ha-web -sudo rm -f /etc/systemd/system/pve-ha-web.service -sudo systemctl daemon-reload -sudo rm -rf /opt/pve-ha-web +systemctl disable --now pve-ha-web +rm -f /etc/systemd/system/pve-ha-web.service +systemctl daemon-reload +rm -rf /opt/pve-ha-web ``` --- diff --git a/static/main.js b/static/main.js index 87b6d00..e6e3610 100644 --- a/static/main.js +++ b/static/main.js @@ -121,27 +121,6 @@ async function fetchNodeDetail(name) { return await r.json(); } -// ------ Services status ------ -function normSvcState(s) { - const vals = [ - s.active, s['active-state'], s.ActiveState, s.activestate, - s.SubState, s.substate, - s.state, s.State, - s.loadstate, s.LoadState, - s.result, s.Result, s['exit-code'] - ] - .filter(v => v !== undefined && v !== null && v !== '') - .map(v => String(v).toLowerCase()); - - const joined = ' ' + vals.join(' ') + ' '; - if (/\b(failed|error|dead|auto-restart\b.*fail)\b/.test(joined)) return 'failed'; - if (/\b(active|running|up)\b/.test(joined)) return 'active'; - if (/\b(activating|starting|start-pre|reload)\b/.test(joined)) return 'activating'; - if (/\b(deactivating|stopping|stop-post)\b/.test(joined)) return 'deactivating'; - if (vals.length) return 'inactive'; - return 'inactive'; -} - // ------ VM detail card ------ function renderVmDetailCard(d) { const meta = d.meta || {}; @@ -266,8 +245,7 @@ function renderVmDetailCard(d) {
Memory (used/free/total)
${(used != null && maxmem != null) ? `${humanBytes(used)} / ${humanBytes(free)} / ${humanBytes(maxmem)}` - : '—' - }
+ : '—'}
Ballooning: ${balloonEnabled ? badge('enabled', 'ok') : badge('disabled', 'err')}
${binfo ? `
Balloon actual: ${humanBytes(binfo.actual)} | guest free: ${humanBytes(binfo.free_mem)} | guest total: ${humanBytes(binfo.total_mem)}
` : ''} @@ -316,7 +294,6 @@ function renderNodeDetailCard(d) { const st = d.status || {}; const ver = d.version || {}; const tm = d.time || {}; - const svcs = ensureArr(d.services); const netcfg = ensureArr(d.network_cfg); const disks = ensureArr(d.disks); const sub = d.subscription || {}; @@ -334,6 +311,40 @@ function renderNodeDetailCard(d) { const root = st.rootfs || {}; const load = st.loadavg || ''; + // ---- SYSTEM DETAILS (zamiast "HA services") + const hw = d.hw || d.hardware || d.cpuinfo || st.cpuinfo || {}; + const cpuModel = pick( + hw.model, hw['model-name'], hw.model_name, + st['cpu-model'], ver['cpu-model'], ver.cpu, st.cpu_model + ); + const arch = pick(hw.arch, ver.arch, st.architecture, st.arch); + const sockets = pick(hw.sockets, st.sockets); + const coresPerSocket = pick(hw.cores, st.cores_per_socket, st.cores); + const threadsPerCore = pick(hw.threads, st.threads_per_core, st.threads); + const totalCPUs = pick(st.maxcpu, hw.total_cpus, hw.cpus); + const microcode = pick(hw.microcode, st.microcode); + const bios = pick(hw.bios, st.bios_version, ver.bios); + const virt = pick(hw.virtualization, ver.virtualization, st.virtualization); + const machine = pick(ver.machine, st.machine); + const kvm = pick(ver.kvm, st.kvm); + + const tech = { + 'Kernel': pick(ver.kernel, ver.release), + 'QEMU': pick(ver.qemu, ver['running-qemu']), + 'KVM': kvm, + 'PVE Manager': pick(ver.pvemanager, ver['pve-manager']), + 'Architecture': arch, + 'CPU model': cpuModel, + 'Sockets': sockets, + 'Cores/socket': coresPerSocket, + 'Threads/core': threadsPerCore, + 'Total CPUs': totalCPUs, + 'Microcode': microcode, + 'Virtualization': virt, + 'Machine': machine, + 'BIOS': bios + }; + const top = `
${safe(d.node)}
@@ -349,17 +360,15 @@ function renderNodeDetailCard(d) {
Memory
-
${(mem.used != null && mem.total != null) ? `${humanBytes(mem.used)} / ${humanBytes(mem.total)} (${pct(mem.used / mem.total)})` : '—' - }
+
${(mem.used != null && mem.total != null) ? `${humanBytes(mem.used)} / ${humanBytes(mem.total)} (${pct(mem.used / mem.total)})` : '—'}
RootFS
-
${(root.used != null && root.total != null) ? `${humanBytes(root.used)} / ${humanBytes(root.total)} (${pct(root.used / root.total)})` : '—' - }
+
${(root.used != null && root.total != null) ? `${humanBytes(root.used)} / ${humanBytes(root.total)} (${pct(root.used / root.total)})` : '—'}
Kernel / QEMU
-
${safe(ver.kernel || (ver['release'] || ''))} / ${safe(ver.qemu || ver['running-qemu'] || '')}
+
${safe(tech['Kernel'])} / ${safe(tech['QEMU'])}
Time
@@ -367,33 +376,13 @@ function renderNodeDetailCard(d) {
`; - // --- NORMALIZE service names + badge - const svcMap = {}; - svcs.forEach(s => { - const raw = (s && s.name) ? s.name : ''; - const key = raw.replace(/\.service$/, ''); // normalize - svcMap[key] = normSvcState(s); + // --- SYSTEM DETAILS GRID + const sysDetails = kvGrid(tech, Object.keys(tech), { + 'QEMU': 'QEMU version', 'KVM': 'KVM', + 'CPU model': 'CPU model', 'Architecture': 'Arch', + 'Cores/socket': 'Cores per socket', 'Threads/core': 'Threads per core', + 'Total CPUs': 'Total logical CPUs' }); - function svcBadge(name) { - const st = String(svcMap[name] || '').toLowerCase(); - if (st === 'active') return badge('active', 'ok'); - if (st === 'activating' || st === 'deactivating') return badge(st, 'warn'); - if (st === 'failed') return badge('failed', 'err'); - return badge('inactive', 'err'); - } - const svcTable = ` -
- - - - - - - - - -
ServiceStateServiceStateServiceState
watchdog-mux${svcBadge('watchdog-mux')}pve-ha-crm${svcBadge('pve-ha-crm')}pve-ha-lrm${svcBadge('pve-ha-lrm')}
-
`; // Network config const netRows = netcfg.map(n => { @@ -442,8 +431,8 @@ function renderNodeDetailCard(d) { ${memCard}
-
HA services
- ${svcTable} +
System details
+ ${sysDetails}