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:
2026-09-19 10:24:34 +03:00
co-authored by Claude Sonnet 5
commit 09159a5f31
61 changed files with 7882 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
package collect
import (
"encoding/json"
"os/exec"
"strings"
"time"
)
// ShareServices is the read-only view of the file-sharing daemons.
type ShareServices struct {
SMBInstalled bool `json:"smb_installed"`
NFSInstalled bool `json:"nfs_installed"`
SMBActive bool `json:"smb_active"`
NFSActive bool `json:"nfs_active"`
SMBSessions int `json:"smb_sessions"`
}
// ReadShareServices checks which sharing daemons exist and run.
func ReadShareServices() ShareServices {
var s ShareServices
if _, err := exec.LookPath("smbd"); err == nil {
s.SMBInstalled = true
s.SMBActive = unitActive("smbd")
if s.SMBActive {
s.SMBSessions = smbSessions()
}
}
if _, err := exec.LookPath("exportfs"); err == nil {
s.NFSInstalled = true
s.NFSActive = unitActive("nfs-server")
}
return s
}
func unitActive(unit string) bool {
out, _ := run(5*time.Second, "systemctl", "is-active", unit)
return strings.TrimSpace(string(out)) == "active"
}
// smbSessions counts connected SMB sessions via smbstatus --json (Samba ≥ 4.17).
func smbSessions() int {
out, err := run(10*time.Second, "smbstatus", "--json", "-b")
if err != nil && len(out) == 0 {
return 0
}
return parseSmbSessions(out)
}
func parseSmbSessions(b []byte) int {
var j struct {
Sessions map[string]json.RawMessage `json:"sessions"`
}
if json.Unmarshal(b, &j) != nil {
return 0
}
return len(j.Sessions)
}