Files
nasmon/internal/collect/disks.go
T
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

93 lines
2.2 KiB
Go

package collect
import (
"encoding/json"
"strconv"
"strings"
"time"
)
type Disk struct {
Name string `json:"name"` // sda
Path string `json:"path"` // /dev/sda
Model string `json:"model"`
Serial string `json:"serial"`
Size uint64 `json:"size"`
Rota bool `json:"rota"`
Tran string `json:"tran"` // sata, nvme, usb
}
type lsblkOut struct {
Blockdevices []struct {
Name string `json:"name"`
Path string `json:"path"`
Type string `json:"type"`
Model string `json:"model"`
Serial string `json:"serial"`
Size flexUint `json:"size"`
Rota flexBool `json:"rota"`
Tran string `json:"tran"`
} `json:"blockdevices"`
}
// flexBool accepts true/false as well as the "1"/"0" strings older lsblk prints.
type flexBool bool
func (b *flexBool) UnmarshalJSON(data []byte) error {
switch strings.Trim(string(data), `"`) {
case "true", "1":
*b = true
default:
*b = false
}
return nil
}
// flexUint accepts a JSON number or a numeric string.
type flexUint uint64
func (u *flexUint) UnmarshalJSON(data []byte) error {
n, err := strconv.ParseUint(strings.Trim(string(data), `"`), 10, 64)
if err != nil {
*u = 0
return nil
}
*u = flexUint(n)
return nil
}
// ListDisks returns physical block devices (whole disks, no loop/zram/dm).
func ListDisks() ([]Disk, error) {
b, err := run(10*time.Second, "lsblk", "-J", "-b", "-d", "-o", "NAME,PATH,TYPE,MODEL,SERIAL,SIZE,ROTA,TRAN")
if err != nil {
return nil, err
}
return parseLsblk(b)
}
func parseLsblk(b []byte) ([]Disk, error) {
var o lsblkOut
if err := json.Unmarshal(b, &o); err != nil {
return nil, err
}
var out []Disk
for _, d := range o.Blockdevices {
if d.Type != "disk" {
continue
}
if strings.HasPrefix(d.Name, "zram") || strings.HasPrefix(d.Name, "loop") ||
strings.HasPrefix(d.Name, "dm-") || strings.HasPrefix(d.Name, "zd") || strings.HasPrefix(d.Name, "sr") {
continue
}
path := d.Path
if path == "" {
path = "/dev/" + d.Name
}
out = append(out, Disk{
Name: d.Name, Path: path, Model: strings.TrimSpace(d.Model),
Serial: strings.TrimSpace(d.Serial), Size: uint64(d.Size), Rota: bool(d.Rota), Tran: d.Tran,
})
}
return out, nil
}