summaryrefslogtreecommitdiffstats
path: root/src/go/plugin/go.d/modules/zfspool/collect_zpool_list.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/plugin/go.d/modules/zfspool/collect_zpool_list.go160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/zfspool/collect_zpool_list.go b/src/go/plugin/go.d/modules/zfspool/collect_zpool_list.go
new file mode 100644
index 000000000..f5e1c0812
--- /dev/null
+++ b/src/go/plugin/go.d/modules/zfspool/collect_zpool_list.go
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package zfspool
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+type zpoolEntry struct {
+ name string
+ sizeBytes string
+ allocBytes string
+ freeBytes string
+ fragPerc string
+ capPerc string
+ dedupRatio string
+ health string
+}
+
+func (z *ZFSPool) collectZpoolList(mx map[string]int64) error {
+ bs, err := z.exec.list()
+ if err != nil {
+ return err
+ }
+
+ zpools, err := parseZpoolListOutput(bs)
+ if err != nil {
+ return fmt.Errorf("bad zpool list output: %v", err)
+ }
+
+ seen := make(map[string]bool)
+
+ for _, zpool := range zpools {
+ seen[zpool.name] = true
+
+ if !z.seenZpools[zpool.name] {
+ z.addZpoolCharts(zpool.name)
+ z.seenZpools[zpool.name] = true
+ }
+
+ px := "zpool_" + zpool.name + "_"
+
+ if v, ok := parseInt(zpool.sizeBytes); ok {
+ mx[px+"size"] = v
+ }
+ if v, ok := parseInt(zpool.freeBytes); ok {
+ mx[px+"free"] = v
+ }
+ if v, ok := parseInt(zpool.allocBytes); ok {
+ mx[px+"alloc"] = v
+ }
+ if v, ok := parseFloat(zpool.capPerc); ok {
+ mx[px+"cap"] = int64(v)
+ }
+ if v, ok := parseFloat(zpool.fragPerc); ok {
+ mx[px+"frag"] = int64(v)
+ }
+ for _, s := range zpoolHealthStates {
+ mx[px+"health_state_"+s] = 0
+ }
+ mx[px+"health_state_"+zpool.health] = 1
+ }
+
+ for name := range z.seenZpools {
+ if !seen[name] {
+ z.removeZpoolCharts(name)
+ delete(z.seenZpools, name)
+ }
+ }
+
+ return nil
+}
+
+func parseZpoolListOutput(bs []byte) ([]zpoolEntry, error) {
+ /*
+ # zpool list -p
+ NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
+ rpool 21367462298 9051643576 12240656794 - 33 42 1.00 ONLINE -
+ zion - - - - - - - FAULTED -
+ */
+
+ var headers []string
+ var zpools []zpoolEntry
+ sc := bufio.NewScanner(bytes.NewReader(bs))
+
+ for sc.Scan() {
+ line := strings.TrimSpace(sc.Text())
+ if line == "" {
+ continue
+ }
+
+ if len(headers) == 0 {
+ if !strings.HasPrefix(line, "NAME") {
+ return nil, fmt.Errorf("missing headers (line '%s')", line)
+ }
+ headers = strings.Fields(line)
+ continue
+ }
+
+ values := strings.Fields(line)
+ if len(values) != len(headers) {
+ return nil, fmt.Errorf("unequal columns: headers(%d) != values(%d)", len(headers), len(values))
+ }
+
+ var zpool zpoolEntry
+
+ for i, v := range values {
+ v = strings.TrimSpace(v)
+ switch strings.ToLower(headers[i]) {
+ case "name":
+ zpool.name = v
+ case "size":
+ zpool.sizeBytes = v
+ case "alloc":
+ zpool.allocBytes = v
+ case "free":
+ zpool.freeBytes = v
+ case "frag":
+ zpool.fragPerc = v
+ case "cap":
+ zpool.capPerc = v
+ case "dedup":
+ zpool.dedupRatio = v
+ case "health":
+ zpool.health = strings.ToLower(v)
+ }
+ }
+
+ if zpool.name != "" && zpool.health != "" {
+ zpools = append(zpools, zpool)
+ }
+ }
+
+ if len(zpools) == 0 {
+ return nil, errors.New("no pools found")
+ }
+
+ return zpools, nil
+}
+
+func parseInt(s string) (int64, bool) {
+ if s == "-" {
+ return 0, false
+ }
+ v, err := strconv.ParseInt(s, 10, 64)
+ return v, err == nil
+}
+
+func parseFloat(s string) (float64, bool) {
+ if s == "-" {
+ return 0, false
+ }
+ v, err := strconv.ParseFloat(s, 64)
+ return v, err == nil
+}