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>
93 lines
2.2 KiB
Go
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
|
|
}
|