Add drive SMART attributes and health status

This commit is contained in:
josh committed 2026-04-13 21:57:00 -04:00
1 parent 40109b5c62
commit 23d7e79605
3 files changed
+128 -6

No files matched your search

+68 -2
View File
@@ -97,18 +97,84 @@ if cgi.params.key?("content")
exit
end
thousands = ->(n) { n.to_s.gsub(/(\d)(?=(\d{3})+$)/, '\1,') }
drive_stats = lambda do |dt, smart|
stats = []
case smart["passed"]
when true then stats << ["ok", "SMART PASSED"]
when false then stats << ["bad", "SMART FAILED"]
end
if (t = smart["temperature"])
cls = t >= 60 ? "bad" : t >= 50 ? "warn" : "ok"
stats << [cls, "🌡 #{t} °C"]
end
if (poh = smart["power_on_hours"])
stats << ["ok", "POH #{thousands.(poh)} h"]
end
if dt == "nvme"
if (p = smart["percentage_used"])
cls = p >= 90 ? "bad" : p >= 70 ? "warn" : "ok"
stats << [cls, "Wear #{p}%"]
end
if (m = smart["media_errors"])
stats << [m > 0 ? "bad" : "ok", "Media err #{m}"]
end
if (cw = smart["critical_warning"]) && cw != 0
stats << ["bad", "Crit warn 0x#{cw.to_s(16)}"]
end
else
if (r = smart["reallocated_sectors"])
stats << [r > 0 ? "warn" : "ok", "Realloc #{r}"]
end
if (s = smart["spin_retry"])
stats << [s > 0 ? "warn" : "ok", "Spin retry #{s}"]
end
if (p = smart["pending_sectors"])
stats << [p > 0 ? "warn" : "ok", "Pending #{p}"]
end
if (c = smart["crc_errors"])
stats << [c > 0 ? "warn" : "ok", "CRC #{c}"]
end
end
stats
end
info.each do |entry|
case entry["type"]
when "drive"
dt = entry["drivetype"]
name = CGI.escapeHTML(entry["name"].to_s)
model = CGI.escapeHTML(entry["model"])
capacity = CGI.escapeHTML(entry["capacity"])
smart = entry["smart"]
stats = smart ? drive_stats.(dt, smart) : []
card_cls = if stats.any? { |c, _| c == "bad" } then "bad"
elsif stats.any? { |c, _| c == "warn" } then "warn"
else "ok"
end
stats_html = stats.map { |c, txt|
%(<span class="stat #{c}">#{CGI.escapeHTML(txt)}</span>)
}.join
stats_block = stats.empty? ? "" :
%(<div class="drive-stats" style="margin-top:0.6rem;">#{stats_html}</div>)
title = name.empty? ? model : "#{name} · #{model}"
html << <<~HTML
<div class="card ok">
<div class="card #{card_cls} span-2">
<div class="card-header">
<span class="card-title">#{model} <span class="drive-type #{dt}">#{dt.upcase}</span></span>
<span class="card-title">#{title} <span class="drive-type #{dt}">#{dt.upcase}</span></span>
</div>
<div class="card-sub">#{capacity}</div>
#{stats_block}
</div>
HTML
end