diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/plugin/go.d/modules/adaptecraid/collect_pd.go | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/adaptecraid/collect_pd.go b/src/go/plugin/go.d/modules/adaptecraid/collect_pd.go new file mode 100644 index 000000000..272266b47 --- /dev/null +++ b/src/go/plugin/go.d/modules/adaptecraid/collect_pd.go @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package adaptecraid + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "strconv" + "strings" +) + +type physicalDevice struct { + number string + state string + location string + vendor string + model string + smart string + smartWarnings string + powerState string + temperature string +} + +func (a *AdaptecRaid) collectPhysicalDevices(mx map[string]int64) error { + bs, err := a.exec.physicalDevicesInfo() + if err != nil { + return err + } + + devices, err := parsePhysDevInfo(bs) + if err != nil { + return err + } + + if len(devices) == 0 { + return errors.New("no physical devices found") + } + + for _, pd := range devices { + if !a.pds[pd.number] { + a.pds[pd.number] = true + a.addPhysicalDeviceCharts(pd) + } + + px := fmt.Sprintf("pd_%s_", pd.number) + + // Unfortunately, all available states are unknown. + mx[px+"health_state_ok"] = 0 + mx[px+"health_state_critical"] = 0 + if isOkPDState(pd) { + mx[px+"health_state_ok"] = 1 + } else { + mx[px+"health_state_critical"] = 1 + } + + if v, err := strconv.ParseInt(pd.smartWarnings, 10, 64); err == nil { + mx[px+"smart_warnings"] = v + } + if v, err := strconv.ParseInt(pd.temperature, 10, 64); err == nil { + mx[px+"temperature"] = v + } + } + + return nil +} + +func isOkPDState(pd *physicalDevice) bool { + // https://github.com/thomas-krenn/check_adaptec_raid/blob/a104fd88deede87df4f07403b44394bffb30c5c3/check_adaptec_raid#L455 + switch pd.state { + case "Online", + "Global Hot-Spare", + "Dedicated Hot-Spare", + "Pooled Hot-Spare", + "Hot Spare", + "Ready", + "Online (JBOD)", + "Raw (Pass Through)": + return true + } + return false +} + +func parsePhysDevInfo(bs []byte) (map[string]*physicalDevice, error) { + devices := make(map[string]*physicalDevice) + + var pd *physicalDevice + + sc := bufio.NewScanner(bytes.NewReader(bs)) + + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + + if strings.HasPrefix(line, "Device #") { + num := strings.TrimPrefix(line, "Device #") + pd = &physicalDevice{number: num} + devices[num] = pd + continue + } + + if pd == nil { + continue + } + + switch { + case strings.HasPrefix(line, "State"): + pd.state = getColonSepValue(line) + case strings.HasPrefix(line, "Reported Location"): + pd.location = getColonSepValue(line) + case strings.HasPrefix(line, "Vendor"): + pd.vendor = getColonSepValue(line) + case strings.HasPrefix(line, "Model"): + pd.model = getColonSepValue(line) + case strings.HasPrefix(line, "S.M.A.R.T. warnings"): + pd.smartWarnings = getColonSepValue(line) + case strings.HasPrefix(line, "S.M.A.R.T."): + pd.smart = getColonSepValue(line) + case strings.HasPrefix(line, "Power State"): + pd.powerState = getColonSepValue(line) + case strings.HasPrefix(line, "Temperature"): + v := getColonSepValue(line) // '42 C/ 107 F' or 'Not Supported' + pd.temperature = strings.Fields(v)[0] + } + } + + return devices, nil +} |