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>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
{{define "content"}}
|
||||
{{template "flash" .}}
|
||||
{{with .Data}}
|
||||
{{template "alertlist" .S.Alerts}}
|
||||
|
||||
<section class="grid metrics">
|
||||
<div class="card metric">
|
||||
<h2>CPU <span class="muted">{{.S.CPU.Cores}} cores</span></h2>
|
||||
<div class="big {{levelClass .S.CPU.UsagePct 70 90}}">{{f0 .S.CPU.UsagePct}}%</div>
|
||||
<div class="muted">load {{f1 (index .S.CPU.Load 0)}} / {{f1 (index .S.CPU.Load 1)}} / {{f1 (index .S.CPU.Load 2)}}</div>
|
||||
{{.CPUSpark}}
|
||||
<div class="muted small">last 24 h</div>
|
||||
</div>
|
||||
|
||||
<div class="card metric">
|
||||
<h2>Memory <span class="muted">{{bytes .S.Mem.Total}}</span></h2>
|
||||
<div class="big {{levelClass .MemPct 80 95}}">{{f0 .MemPct}}%</div>
|
||||
<div class="bar">
|
||||
<span class="fill mem" style="width:{{f1 .MemPct}}%"></span>
|
||||
{{if .S.Mem.ARCSize}}<span class="fill arc" style="width:{{f1 .ARCPct}}%"></span>{{end}}
|
||||
</div>
|
||||
<div class="muted">used {{bytes .S.Mem.Used}}{{if .S.Mem.ARCSize}} · <span class="arc-dot"></span>ARC {{bytes .S.Mem.ARCSize}} / {{bytes .S.Mem.ARCMax}}{{end}}</div>
|
||||
{{if .S.Mem.SwapTotal}}<div class="muted">swap {{bytes .S.Mem.SwapUsed}} / {{bytes .S.Mem.SwapTotal}} ({{f0 .SwapPct}}%)</div>{{end}}
|
||||
{{.MemSpark}}
|
||||
<div class="muted small">last 24 h</div>
|
||||
</div>
|
||||
|
||||
<div class="card metric">
|
||||
<h2>Temperature</h2>
|
||||
{{if .S.HasCPUTemp}}<div class="big {{tempClass .S.CPUTemp .Th.CPUTempC}}">{{f0 .S.CPUTemp}}°C</div><div class="muted">CPU</div>{{else}}<div class="big muted">—</div><div class="muted">no CPU sensor</div>{{end}}
|
||||
{{.TempSpark}}
|
||||
<details class="sensors">
|
||||
<summary class="muted small">{{len .S.Temps}} sensors</summary>
|
||||
<table class="compact">
|
||||
{{range .S.Temps}}<tr><td class="muted">{{.Chip}}</td><td>{{.Label}}</td><td class="num">{{f0 .C}}°C</td></tr>{{end}}
|
||||
</table>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="card metric">
|
||||
<h2>System</h2>
|
||||
<div class="kv">
|
||||
<div><span class="muted">host</span> {{.S.Host}}</div>
|
||||
<div><span class="muted">root fs</span> {{bytes .S.RootFS.Free}} free of {{bytes .S.RootFS.Total}}</div>
|
||||
<div><span class="muted">SMART check</span> {{ago .S.LastSmartCheck}}{{if .S.SmartRunning}} <span class="badge">running</span>{{else}} · next {{dt .S.NextSmartCheck}}{{end}}</div>
|
||||
<div><span class="muted">nasmon</span> {{.S.Version}} · up {{dur .S.Uptime}}</div>
|
||||
{{if .S.LastMailErr}}<div class="crit-text">mail error: {{.S.LastMailErr}}</div>{{end}}
|
||||
</div>
|
||||
<form method="post" action="/smart/run" class="inline"><button type="submit" {{if .S.SmartRunning}}disabled{{end}}>Check SMART now</button></form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h2>Disks</h2>
|
||||
{{if .S.DisksErr}}<div class="flash crit">{{.S.DisksErr}}</div>{{end}}
|
||||
<div class="tablewrap"><table>
|
||||
<thead><tr><th>Device</th><th>Model</th><th>Serial</th><th class="num">Size</th><th>Bus</th><th class="num">Temp</th><th>Health</th><th class="num">Power-on</th><th>Self-test</th><th>Warnings</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .S.Disks}}{{$sm := .Smart}}
|
||||
<tr>
|
||||
<td><a href="/disks/{{.Serial}}">{{.Name}}</a></td>
|
||||
<td>{{.Model}}</td>
|
||||
<td class="mono small">{{.Serial}}</td>
|
||||
<td class="num">{{bytes .Size}}</td>
|
||||
<td class="muted">{{.Tran}}{{if not .Rota}} ssd{{end}}</td>
|
||||
{{if $sm}}
|
||||
<td class="num">{{if $sm.HasTemp}}<span class="{{tempClass $sm.TempC $.Data.Th.DiskTempC}}">{{$sm.TempC}}°C</span>{{if .Standby}} <span class="muted small" title="disk in standby, value from last read">zz</span>{{end}}{{else}}—{{end}}</td>
|
||||
<td>{{if .Error}}<span class="badge warn" title="{{.Error}}">n/a</span>{{else if not $sm.Supported}}<span class="muted">n/a</span>{{else if $sm.Healthy}}<span class="badge ok">PASSED</span>{{else}}<span class="badge crit">FAILED</span>{{end}}</td>
|
||||
<td class="num">{{if $sm.PowerOnHrs}}{{$sm.PowerOnHrs}} h{{else}}—{{end}}</td>
|
||||
<td class="small">{{with $sm.LastTest}}{{if .InProgress}}<span class="badge">{{.Remaining}}% left</span>{{else}}<span class="{{if .Passed}}ok{{else}}crit{{end}}">{{.Status}}</span>{{end}}{{else}}—{{end}}</td>
|
||||
<td class="small">
|
||||
{{range $sm.Attrs}}{{if and (or (eq .ID 5) (eq .ID 187) (eq .ID 188) (eq .ID 197) (eq .ID 198)) (gt .Raw 0)}}<span class="badge crit" title="{{.Name}}">{{.ID}}: {{.Raw}}</span> {{end}}{{if .WhenFailed}}<span class="badge crit">{{.ID}} {{.WhenFailed}}</span> {{end}}{{end}}
|
||||
{{with $sm.NVMe}}{{if .CriticalWarning}}<span class="badge crit">warn 0x{{printf "%02x" .CriticalWarning}}</span> {{end}}{{if .MediaErrors}}<span class="badge crit">media err {{.MediaErrors}}</span> {{end}}<span class="muted">{{.PercentageUsed}}% used</span>{{end}}
|
||||
</td>
|
||||
{{else}}
|
||||
<td class="num">—</td><td>{{if .Standby}}<span class="muted">standby</span>{{else if .Error}}<span class="badge warn" title="{{.Error}}">n/a</span>{{else}}<span class="muted">pending</span>{{end}}</td><td></td><td></td><td></td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{else}}<tr><td colspan="10" class="muted">no disks found</td></tr>{{end}}
|
||||
</tbody>
|
||||
</table></div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h2>ZFS pools <a class="muted small" href="/zfs">details</a></h2>
|
||||
{{if .S.PoolsErr}}<div class="flash crit">{{.S.PoolsErr}}</div>{{end}}
|
||||
<div class="tablewrap"><table>
|
||||
<thead><tr><th>Pool</th><th>Health</th><th class="num">Used</th><th class="num">Free</th><th class="num">Size</th><th>Capacity</th><th class="num">Frag</th><th>Last scrub</th><th>Errors</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .S.Pools}}
|
||||
<tr>
|
||||
<td><a href="/zfs#{{.Name}}">{{.Name}}</a></td>
|
||||
<td><span class="badge {{healthClass .Health}}">{{.Health}}</span></td>
|
||||
<td class="num">{{bytes .Alloc}}</td>
|
||||
<td class="num">{{bytes .Free}}</td>
|
||||
<td class="num">{{bytes .Size}}</td>
|
||||
<td><div class="bar small"><span class="fill {{capClass .CapPct 75 90}}" style="width:{{.CapPct}}%"></span></div> <span class="small">{{.CapPct}}%</span></td>
|
||||
<td class="num">{{.FragPct}}%</td>
|
||||
<td class="small">{{if .Scrubbing}}<span class="badge">scrubbing</span>{{else if .LastScrub}}{{agop .LastScrub}}{{else}}<span class="muted">never</span>{{end}}</td>
|
||||
<td class="small">{{if .Errors}}{{.Errors}}{{end}}</td>
|
||||
</tr>
|
||||
{{else}}<tr><td colspan="9" class="muted">no pools</td></tr>{{end}}
|
||||
</tbody>
|
||||
</table></div>
|
||||
</section>
|
||||
|
||||
<section class="card">
|
||||
<h2>Datasets</h2>
|
||||
<div class="tablewrap"><table>
|
||||
<thead><tr><th>Dataset</th><th>Mountpoint</th><th class="num">Used</th><th class="num">Referenced</th><th class="num">Available</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .S.Datasets}}<tr><td class="mono">{{.Name}}</td><td class="muted mono small">{{.Mountpoint}}</td><td class="num">{{bytes .Used}}</td><td class="num">{{bytes .Refer}}</td><td class="num">{{bytes .Avail}}</td></tr>{{end}}
|
||||
</tbody>
|
||||
</table></div>
|
||||
</section>
|
||||
{{end}}
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user