sysinfo/internal/sysinfo/collector_block.go
2025-05-01 03:25:38 -07:00

78 lines
1.9 KiB
Go

package sysinfo
import (
"encoding/json"
"path/filepath"
"regexp"
"strings"
"time"
)
type BlockCollector struct{}
func (BlockCollector) SectionKey() string { return "blockdevs" }
func (BlockCollector) EnsurePrerequisites(pm PackageManager, _ *Context) error {
if pm.Distro() == "ubuntu" {
return pm.InstallPackages("smartmontools", "util-linux", "blkid")
}
return nil
}
func (BlockCollector) IsSupported(pm PackageManager, _ *Context) bool {
return pm.ExecExists("lsblk")
}
func (BlockCollector) CollectData(c *Context) (json.RawMessage, error) {
rePU := regexp.MustCompile(`PARTUUID="([^"]+)"`)
all := map[string]any{}
links, _ := filepath.Glob("/dev/disk/by-id/*")
seen := map[string]bool{}
for _, link := range links {
base := filepath.Base(link)
target, _ := filepath.EvalSymlinks(link)
dev := filepath.Base(target)
if seen[dev] {
continue
}
seen[dev] = true
bd := map[string]any{
"timestamp": c.Now.Format(time.RFC3339),
"smartctl": c.SafeRun("smartctl", "-a", "/dev/"+dev),
"blkid": c.SafeRun("blkid", "-p", "/dev/"+dev),
}
sfd, _ := c.Run("sfdisk", "-J", "/dev/"+dev)
bd["sfdisk"] = json.RawMessage(sfd)
lsb, _ := c.Run("lsblk", "-J", "/dev/"+dev)
bd["lsblk"] = json.RawMessage(lsb)
parts := map[string]any{}
var ls struct {
Blockdevices []struct {
Children []struct{ Name string `json:"name"` } `json:"children"`
} `json:"blockdevices"`
}
_ = json.Unmarshal(lsb, &ls)
for _, d := range ls.Blockdevices {
for _, ch := range d.Children {
part := "/dev/" + ch.Name
blk := c.SafeRun("blkid", "-p", part)
m := rePU.FindStringSubmatch(blk)
if len(m) != 2 {
continue
}
uuid := strings.ToLower(m[1])
pinfo := map[string]any{"blkid": blk}
plsb, _ := c.Run("lsblk", "-J", part)
pinfo["lsblk"] = json.RawMessage(plsb)
parts[uuid] = pinfo
}
}
bd["partitions"] = parts
all[base] = bd
}
return json.Marshal(all)
}