Add Server Info card

This commit is contained in:
Josh Holtrop 2026-04-20 20:51:45 -04:00
parent 5687d8a4e7
commit 49a20a946f
2 changed files with 106 additions and 0 deletions

View File

@ -166,6 +166,52 @@ def read_virtual_machines
end end
end end
def read_server_info
info = { "type" => "server" }
if File.exist?("/etc/os-release")
File.readlines("/etc/os-release").each do |line|
if line =~ /^PRETTY_NAME="(.+)"$/
info["os_name"] = $1
break
end
end
end
out = `stat -c %W / 2>/dev/null`.strip
if out =~ /^\d+$/ && out.to_i > 0
info["install_date"] = Time.at(out.to_i).strftime("%Y-%m-%d")
elsif File.exist?("/etc/machine-id")
info["install_date"] = File.mtime("/etc/machine-id").strftime("%Y-%m-%d")
end
if File.exist?("/proc/cpuinfo")
cpuinfo = File.read("/proc/cpuinfo")
if cpuinfo =~ /^model name\s*:\s*(.+)$/
info["cpu_model"] = $1.strip
end
cores = cpuinfo.scan(/^processor\s*:/).size
info["cpu_cores"] = cores if cores > 0
end
if File.exist?("/proc/meminfo")
mem = {}
File.read("/proc/meminfo").each_line do |line|
if line =~ /^(\w+):\s+(\d+)/
mem[$1] = $2.to_i * 1024
end
end
if (total = mem["MemTotal"])
available = mem["MemAvailable"] ||
(mem["MemFree"].to_i + mem["Buffers"].to_i + mem["Cached"].to_i)
info["mem_total"] = total
info["mem_used"] = total - available
end
end
info
end
def read_ups def read_ups
out = `apcaccess 2>/dev/null` out = `apcaccess 2>/dev/null`
return nil unless $?.success? && !out.empty? return nil unless $?.success? && !out.empty?
@ -232,6 +278,8 @@ def handle_info(conn)
info.concat(read_filesystems) info.concat(read_filesystems)
info.concat(read_virtual_machines) info.concat(read_virtual_machines)
info << read_server_info
if (ups = read_ups) if (ups = read_ups)
info << ups info << ups
end end

View File

@ -112,9 +112,67 @@ if cgi.params.key?("content")
drives = info.select { |e| e["type"] == "drive" } drives = info.select { |e| e["type"] == "drive" }
filesystems = info.select { |e| e["type"] == "filesystem" } filesystems = info.select { |e| e["type"] == "filesystem" }
vms = info.select { |e| e["type"] == "vm" } vms = info.select { |e| e["type"] == "vm" }
server = info.find { |e| e["type"] == "server" }
html << %(<div class="span-3">) html << %(<div class="span-3">)
if server
html << %(<div class="section-label">Server</div>)
html << %(<div class="card ok"><div class="card-header"><span class="card-title">Server Info</span></div><div class="subitems">)
if server["os_name"]
html << <<~HTML
<div class="subitem">
<div class="subitem-left"><div class="dot ok"></div><span class="subitem-name">OS</span></div>
<span class="subitem-value ok">#{CGI.escapeHTML(server["os_name"])}</span>
</div>
HTML
end
if server["install_date"]
html << <<~HTML
<div class="subitem">
<div class="subitem-left"><div class="dot ok"></div><span class="subitem-name">Installed</span></div>
<span class="subitem-value ok">#{CGI.escapeHTML(server["install_date"])}</span>
</div>
HTML
end
cpu_model = server["cpu_model"]
cpu_cores = server["cpu_cores"]
if cpu_model || cpu_cores
cpu_text = [
cpu_model,
cpu_cores ? "#{cpu_cores} thread#{cpu_cores == 1 ? "" : "s"}" : nil
].compact.join(" · ")
html << <<~HTML
<div class="subitem">
<div class="subitem-left"><div class="dot ok"></div><span class="subitem-name">CPU</span></div>
<span class="subitem-value ok">#{CGI.escapeHTML(cpu_text)}</span>
</div>
HTML
end
mem_total = server["mem_total"].to_i
mem_used = server["mem_used"].to_i
if mem_total > 0
mem_pct_f = mem_used * 100.0 / mem_total
mem_pct = mem_pct_f.round
mem_cls = mem_pct_f >= 90 ? "bad" : mem_pct_f >= 75 ? "warn" : "ok"
html << <<~HTML
<div class="subitem" style="flex-direction:column;align-items:stretch;gap:0.35rem;">
<div style="display:flex;justify-content:space-between;align-items:center;">
<div class="subitem-left"><div class="dot #{mem_cls}"></div><span class="subitem-name">Memory</span></div>
<span class="subitem-value #{mem_cls}">#{mem_pct}% · #{CGI.escapeHTML(human_capacity(mem_used))} / #{CGI.escapeHTML(human_capacity(mem_total))}</span>
</div>
<div class="bar-track"><div class="bar-fill #{mem_cls}" style="width:#{mem_pct}%"></div></div>
</div>
HTML
end
html << %(</div></div>)
end
if vms.any? if vms.any?
running = vms.count { |v| v["state"].to_s == "running" } running = vms.count { |v| v["state"].to_s == "running" }
total = vms.size total = vms.size