package unraid import ( "context" "errors" "strings" "time" "github.com/itworx/pulse/internal/pool" ) // PoolSource maps only cache records that carry filesystem totals. Unraid 7.2 // exposes one such aggregate record per named pool; the remaining member // devices have null filesystem fields. This avoids inferring membership from // device names while still preserving the API's truthful pool boundary. type PoolSource struct { Client *Client Now func() time.Time } func (s PoolSource) Snapshot(ctx context.Context) (pool.RawSnapshot, error) { doc, now, err := (ArraySource{Client: s.Client, Now: s.Now}).document(ctx) if err != nil { return pool.RawSnapshot{}, err } items := make([]pool.RawPool, 0, len(doc.Array.Caches)) for _, item := range doc.Array.Caches { if len(item.FSSize) == 0 || string(item.FSSize) == "null" { continue } total, err := rawUint(item.FSSize) if err != nil || total == 0 || strings.TrimSpace(item.Name) == "" { return pool.RawSnapshot{}, errors.New("Unraid pool identity or capacity is invalid") } used, err := rawUint(item.FSUsed) if err != nil || used > total { return pool.RawSnapshot{}, errors.New("Unraid pool usage is invalid") } items = append(items, pool.RawPool{ ID: identity(item.ID, item.Name), Name: item.Name, Filesystem: item.FSType, State: poolState(item.Status), UsableBytes: kilobytes(total), UsedBytes: kilobytes(used), Capabilities: pool.Capabilities{ Members: pool.CapabilityUnsupported, Capacity: pool.CapabilityAvailable, Redundancy: pool.CapabilityUnsupported, Scrub: pool.CapabilityUnsupported, FilesystemErrors: pool.CapabilityUnsupported, Performance: pool.CapabilityUnsupported, SSDWear: pool.CapabilityUnsupported, MoverSignals: pool.CapabilityUnsupported, }, }) } if len(items) > 64 { return pool.RawSnapshot{}, errors.New("Unraid pool response exceeds bounds") } return pool.RawSnapshot{Source: pool.Source{ID: "unraid", Type: "unraid"}, Pools: items, ObservedAt: now, ReceivedAt: now}, nil } func poolState(value string) string { if strings.EqualFold(strings.TrimSpace(value), "DISK_OK") { return pool.StateHealthy } return pool.StateUnknown }