1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
}
|