Add virtual machines list

This commit is contained in:
josh committed 2026-04-14 09:12:30 -04:00
1 parent 23008b4997
commit 5773347bda
3 files changed
+177 -5

No files matched your search

+81 -3
View File
@@ -109,6 +109,87 @@ if cgi.params.key?("content")
exit
end
drives = info.select { |e| e["type"] == "drive" }
filesystems = info.select { |e| e["type"] == "filesystem" }
vms = info.select { |e| e["type"] == "vm" }
if vms.any?
running = vms.count { |v| v["state"].to_s == "running" }
total = vms.size
hdr_cls = running == total ? "ok" : running == 0 ? "bad" : "warn"
html << %(<div class="span-3">)
html << %(<div class="section-label">Virtual Machines</div>)
html << <<~HTML
<div class="card #{hdr_cls}">
<div class="card-header">
<span class="card-title">Libvirt</span>
<span class="badge #{hdr_cls}">#{running} / #{total} Running</span>
</div>
<div class="subitems">
<div style="display:grid;grid-template-columns:1fr 110px 1.2fr 100px;gap:0.5rem;padding:0 0.6rem;font-size:0.68rem;color:#334155;text-transform:uppercase;letter-spacing:0.06em;font-weight:600;">
<span>VM</span>
<span style="text-align:right;">Resources</span>
<span>Disk</span>
<span style="text-align:right;">State</span>
</div>
HTML
vms.each do |vm|
name = CGI.escapeHTML(vm["name"].to_s)
os = vm["os"] ? CGI.escapeHTML(vm["os"]) : nil
state = vm["state"].to_s
state_cls = case state
when "running" then "ok"
when "paused", "in shutdown", "pmsuspended" then "warn"
when "shut off", "crashed" then "bad"
else "warn"
end
state_label = CGI.escapeHTML(state.split.map(&:capitalize).join(" "))
vcpus = vm["vcpus"].to_i
mem_b = vm["memory"].to_i
res = vcpus > 0 || mem_b > 0 ? "#{vcpus} CPU#{vcpus > 1 ? "s" : ""} · #{human_capacity(mem_b)}" : "—"
cap = vm["disk_total"].to_i
used = vm["disk_used"].to_i
dpct_f = cap > 0 ? (used * 100.0 / cap) : 0.0
dpct = dpct_f.round
disk_cls = dpct_f >= 90 ? "bad" : dpct_f >= 75 ? "warn" : "ok"
disk_html = if cap > 0
%(<div>
<div style="font-size:0.72rem;color:#94a3b8;">#{dpct}% · #{CGI.escapeHTML(human_capacity(used))} / #{CGI.escapeHTML(human_capacity(cap))}</div>
<div class="bar-track" style="margin-top:0.25rem;"><div class="bar-fill #{disk_cls}" style="width:#{dpct}%"></div></div>
</div>)
else
%(<div><span style="font-size:0.72rem;color:#475569;">—</span></div>)
end
os_html = os ? %(<div style="font-size:0.67rem;color:#475569;">#{os}</div>) : ""
html << <<~HTML
<div class="subitem" style="flex-direction:column;align-items:stretch;gap:0.35rem;">
<div style="display:grid;grid-template-columns:1fr 110px 1.2fr 100px;gap:0.5rem;align-items:center;">
<div class="subitem-left">
<div class="dot #{state_cls}"></div>
<div>
<div class="subitem-name">#{name}</div>
#{os_html}
</div>
</div>
<div style="text-align:right;"><span class="subitem-value ok">#{CGI.escapeHTML(res)}</span></div>
#{disk_html}
<div style="text-align:right;"><span class="subitem-value #{state_cls}">#{state_label}</span></div>
</div>
</div>
HTML
end
html << %(</div></div>)
html << %(</div>)
end
thousands = ->(n) { n.to_s.gsub(/(\d)(?=(\d{3})+$)/, '\1,') }
drive_stats = lambda do |dt, smart|
@@ -157,9 +238,6 @@ if cgi.params.key?("content")
stats
end
drives = info.select { |e| e["type"] == "drive" }
filesystems = info.select { |e| e["type"] == "filesystem" }
if drives.any?
html << %(<div class="span-2">)
html << %(<div class="section-label">Storage Drives</div>)