Files
a.gritsenkoandClaude Sonnet 5 09159a5f31 Initial import: nasmon health monitor, split out of home_nas
Go service (nasmon/) plus nfpm packaging (packaging/), carried over from
the home_nas monorepo. Adds rpm packaging alongside the existing deb
build (Fedora/RHEL/Rocky dependency names via nfpm overrides, per-format
systemd unit path, dpkg+rpm-compatible maintainer scripts) and a Gitea
Actions workflow that builds both formats on every push.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 10:24:34 +03:00

81 lines
4.6 KiB
HTML

{{define "content"}}
{{template "flash" .}}
{{with .Data}}{{$sm := .D.Smart}}
<section class="card">
<h2>{{.D.Model}} <span class="muted">{{.D.Serial}}</span></h2>
<div class="kv cols">
<div><span class="muted">device</span> {{.D.Path}}</div>
{{if .D.Size}}<div><span class="muted">size</span> {{bytes .D.Size}}</div>{{end}}
<div><span class="muted">bus</span> {{.D.Tran}}{{if .D.Rota}} (rotational){{else}} (ssd){{end}}</div>
{{if $sm}}
<div><span class="muted">protocol</span> {{$sm.Protocol}}</div>
<div><span class="muted">firmware</span> {{$sm.Firmware}}</div>
<div><span class="muted">health</span> {{if not $sm.Supported}}<span class="muted">not supported</span>{{else if $sm.Healthy}}<span class="badge ok">PASSED</span>{{else}}<span class="badge crit">FAILED</span>{{end}}</div>
<div><span class="muted">temperature</span> {{if $sm.HasTemp}}<span class="{{tempClass $sm.TempC $.Data.Th.DiskTempC}}">{{$sm.TempC}}°C</span>{{else}}—{{end}}{{if .D.Standby}} <span class="muted">(standby, last read)</span>{{end}}</div>
<div><span class="muted">power-on</span> {{hours $sm.PowerOnHrs}}</div>
<div><span class="muted">power cycles</span> {{$sm.PowerCycles}}</div>
<div><span class="muted">last SMART read</span> {{dt $sm.CheckedAt}}</div>
{{with $sm.LastTest}}<div><span class="muted">self-test</span> {{if .InProgress}}<span class="badge">in progress, {{.Remaining}}% left</span>{{else}}{{.Type}}: <span class="{{if .Passed}}ok{{else}}crit{{end}}">{{.Status}}</span> <span class="muted">at {{.Hours}} h</span>{{end}}</div>{{end}}
{{if $sm.Error}}<div class="crit-text">{{$sm.Error}}</div>{{end}}
{{end}}
</div>
{{if .Known}}<form method="post" action="/disks/{{.D.Serial}}/forget" class="inline" onsubmit="return confirm('Forget this disk? It will no longer trigger a \'disk disappeared\' alert.')"><button type="submit" class="secondary">Forget disk</button></form>{{end}}
</section>
{{if $sm}}
{{with $sm.NVMe}}
<section class="card">
<h2>NVMe health</h2>
<div class="kv cols">
<div><span class="muted">critical warning</span> {{if .CriticalWarning}}<span class="crit">0x{{printf "%02x" .CriticalWarning}}</span>{{else}}<span class="ok">none</span>{{end}}</div>
<div><span class="muted">percentage used</span> {{.PercentageUsed}}%</div>
<div><span class="muted">available spare</span> {{.AvailableSpare}}% <span class="muted">(threshold {{.SpareThreshold}}%)</span></div>
<div><span class="muted">media errors</span> {{if .MediaErrors}}<span class="crit">{{.MediaErrors}}</span>{{else}}0{{end}}</div>
<div><span class="muted">error log entries</span> {{.ErrLogEntries}}</div>
<div><span class="muted">unsafe shutdowns</span> {{.UnsafeShutdowns}}</div>
</div>
</section>
{{end}}
<section class="card">
<h2>Temperature, last 30 days <span class="muted small">{{len .History}} snapshots</span></h2>
{{.TempSpark}}
</section>
{{if $sm.Attrs}}
<section class="card">
<h2>SMART attributes</h2>
<div class="tablewrap"><table>
<thead><tr><th class="num">ID</th><th>Name</th><th class="num">Value</th><th class="num">Worst</th><th class="num">Thresh</th><th class="num">Raw</th><th>Failed</th></tr></thead>
<tbody>
{{range $sm.Attrs}}
{{$crit := and (or (eq .ID 5) (eq .ID 187) (eq .ID 188) (eq .ID 197) (eq .ID 198)) (gt .Raw 0)}}
<tr class="{{if or $crit .WhenFailed}}row-crit{{end}}">
<td class="num">{{.ID}}</td><td class="mono">{{.Name}}</td>
<td class="num">{{.Value}}</td><td class="num">{{.Worst}}</td><td class="num">{{.Thresh}}</td>
<td class="num">{{.RawString}}</td>
<td>{{if .WhenFailed}}<span class="badge crit">{{.WhenFailed}}</span>{{end}}</td>
</tr>
{{end}}
</tbody>
</table></div>
</section>
{{end}}
{{if .History}}
<section class="card">
<h2>History</h2>
<div class="tablewrap"><table class="compact">
<thead><tr><th>Time</th><th class="num">Temp</th><th>Health</th><th class="num">Hours</th><th class="num">{{if $sm.NVMe}}Media err{{else}}Realloc (5){{end}}</th><th class="num">Pending (197)</th><th class="num">CRC (199)</th></tr></thead>
<tbody>
{{range .HistoryRev}}<tr><td class="small">{{dt (unix .T)}}</td><td class="num">{{.TempC}}°C</td><td>{{if .Healthy}}<span class="ok">ok</span>{{else}}<span class="crit">FAIL</span>{{end}}</td><td class="num">{{.Hours}}</td><td class="num">{{.Realloc}}</td><td class="num">{{.Pending}}</td><td class="num">{{.CRC}}</td></tr>{{end}}
</tbody>
</table></div>
</section>
{{end}}
{{else}}
<section class="card"><p class="muted">No SMART data yet{{if .D.Standby}} — disk is in standby, waiting for it to wake up{{end}}.</p></section>
{{end}}
{{end}}
{{end}}