master
go 258 lines 7.45 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package storcli
4
5 import (
6 "fmt"
7 "strconv"
8 "strings"
9
10 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
11 )
12
13 const (
14 prioControllerHealthStatus = collectorapi.Priority + iota
15 prioControllerStatus
16 prioControllerBBUStatus
17 prioControllerROCTemperature
18
19 prioPhysDriveErrors
20 prioPhysDrivePredictiveFailures
21 prioPhysDriveSmartAlertStatus
22 prioPhysDriveTemperature
23
24 prioBBUTemperature
25 )
26
27 var controllerMegaraidChartsTmpl = collectorapi.Charts{
28 controllerHealthStatusChartTmpl.Copy(),
29 controllerStatusChartTmpl.Copy(),
30 controllerBBUStatusChartTmpl.Copy(),
31 }
32
33 var controllerMpt3sasChartsTmpl = collectorapi.Charts{
34 controllerHealthStatusChartTmpl.Copy(),
35 controllerROCTemperatureChartTmpl.Copy(),
36 }
37
38 var (
39 controllerHealthStatusChartTmpl = collectorapi.Chart{
40 ID: "controller_%s_health_status",
41 Title: "Controller health status",
42 Units: "status",
43 Fam: "cntrl status",
44 Ctx: "storcli.controller_health_status",
45 Type: collectorapi.Line,
46 Priority: prioControllerHealthStatus,
47 Dims: collectorapi.Dims{
48 {ID: "cntrl_%s_health_status_healthy", Name: "healthy"},
49 {ID: "cntrl_%s_health_status_unhealthy", Name: "unhealthy"},
50 },
51 }
52 controllerStatusChartTmpl = collectorapi.Chart{
53 ID: "controller_%s_status",
54 Title: "Controller status",
55 Units: "status",
56 Fam: "cntrl status",
57 Ctx: "storcli.controller_status",
58 Type: collectorapi.Line,
59 Priority: prioControllerStatus,
60 Dims: collectorapi.Dims{
61 {ID: "cntrl_%s_status_optimal", Name: "optimal"},
62 {ID: "cntrl_%s_status_degraded", Name: "degraded"},
63 {ID: "cntrl_%s_status_partially_degraded", Name: "partially_degraded"},
64 {ID: "cntrl_%s_status_failed", Name: "failed"},
65 },
66 }
67 controllerBBUStatusChartTmpl = collectorapi.Chart{
68 ID: "controller_%s_bbu_status",
69 Title: "Controller BBU status",
70 Units: "status",
71 Fam: "cntrl status",
72 Ctx: "storcli.controller_bbu_status",
73 Type: collectorapi.Line,
74 Priority: prioControllerBBUStatus,
75 Dims: collectorapi.Dims{
76 {ID: "cntrl_%s_bbu_status_healthy", Name: "healthy"},
77 {ID: "cntrl_%s_bbu_status_unhealthy", Name: "unhealthy"},
78 {ID: "cntrl_%s_bbu_status_na", Name: "na"},
79 },
80 }
81 controllerROCTemperatureChartTmpl = collectorapi.Chart{
82 ID: "controller_%s_roc_temperature",
83 Title: "Controller ROC temperature",
84 Units: "Celsius",
85 Fam: "cntrl roc temperature",
86 Ctx: "storcli.controller_roc_temperature",
87 Type: collectorapi.Line,
88 Priority: prioControllerROCTemperature,
89 Dims: collectorapi.Dims{
90 {ID: "cntrl_%s_roc_temperature_celsius", Name: "temperature"},
91 },
92 }
93 )
94
95 var physDriveChartsTmpl = collectorapi.Charts{
96 physDriveMediaErrorsRateChartTmpl.Copy(),
97 physDrivePredictiveFailuresRateChartTmpl.Copy(),
98 physDriveSmartAlertStatusChartTmpl.Copy(),
99 physDriveTemperatureChartTmpl.Copy(),
100 }
101
102 var (
103 physDriveMediaErrorsRateChartTmpl = collectorapi.Chart{
104 ID: "phys_drive_%s_cntrl_%s_media_errors_rate",
105 Title: "Physical Drive media errors rate",
106 Units: "errors/s",
107 Fam: "pd errors",
108 Ctx: "storcli.phys_drive_errors",
109 Type: collectorapi.Line,
110 Priority: prioPhysDriveErrors,
111 Dims: collectorapi.Dims{
112 {ID: "phys_drive_%s_cntrl_%s_media_error_count", Name: "media"},
113 {ID: "phys_drive_%s_cntrl_%s_other_error_count", Name: "other"},
114 },
115 }
116 physDrivePredictiveFailuresRateChartTmpl = collectorapi.Chart{
117 ID: "phys_drive_%s_cntrl_%s_predictive_failures_rate",
118 Title: "Physical Drive predictive failures rate",
119 Units: "failures/s",
120 Fam: "pd errors",
121 Ctx: "storcli.phys_drive_predictive_failures",
122 Type: collectorapi.Line,
123 Priority: prioPhysDrivePredictiveFailures,
124 Dims: collectorapi.Dims{
125 {ID: "phys_drive_%s_cntrl_%s_predictive_failure_count", Name: "predictive_failures"},
126 },
127 }
128 physDriveSmartAlertStatusChartTmpl = collectorapi.Chart{
129 ID: "phys_drive_%s_cntrl_%s_smart_alert_status",
130 Title: "Physical Drive SMART alert status",
131 Units: "status",
132 Fam: "pd smart",
133 Ctx: "storcli.phys_drive_smart_alert_status",
134 Type: collectorapi.Line,
135 Priority: prioPhysDriveSmartAlertStatus,
136 Dims: collectorapi.Dims{
137 {ID: "phys_drive_%s_cntrl_%s_smart_alert_status_active", Name: "active"},
138 {ID: "phys_drive_%s_cntrl_%s_smart_alert_status_inactive", Name: "inactive"},
139 },
140 }
141 physDriveTemperatureChartTmpl = collectorapi.Chart{
142 ID: "phys_drive_%s_cntrl_%s_temperature",
143 Title: "Physical Drive temperature",
144 Units: "Celsius",
145 Fam: "pd temperature",
146 Ctx: "storcli.phys_drive_temperature",
147 Type: collectorapi.Line,
148 Priority: prioPhysDriveTemperature,
149 Dims: collectorapi.Dims{
150 {ID: "phys_drive_%s_cntrl_%s_temperature", Name: "temperature"},
151 },
152 }
153 )
154
155 var bbuChartsTmpl = collectorapi.Charts{
156 bbuTemperatureChartTmpl.Copy(),
157 }
158
159 var (
160 bbuTemperatureChartTmpl = collectorapi.Chart{
161 ID: "bbu_%s_cntrl_%s_temperature",
162 Title: "BBU temperature",
163 Units: "Celsius",
164 Fam: "bbu temperature",
165 Ctx: "storcli.bbu_temperature",
166 Type: collectorapi.Line,
167 Priority: prioBBUTemperature,
168 Dims: collectorapi.Dims{
169 {ID: "bbu_%s_cntrl_%s_temperature", Name: "temperature"},
170 },
171 }
172 )
173
174 func (c *Collector) addControllerCharts(cntrl controllerInfo) {
175 var charts *collectorapi.Charts
176
177 switch cntrl.Version.DriverName {
178 case driverNameMegaraid:
179 charts = controllerMegaraidChartsTmpl.Copy()
180 case driverNameSas:
181 charts = controllerMpt3sasChartsTmpl.Copy()
182 if !strings.EqualFold(cntrl.HwCfg.TemperatureSensorForROC, "present") {
183 _ = charts.Remove(controllerROCTemperatureChartTmpl.ID)
184 }
185 default:
186 return
187 }
188
189 num := strconv.Itoa(cntrl.Basics.Controller)
190
191 for _, chart := range *charts {
192 chart.ID = fmt.Sprintf(chart.ID, num)
193 chart.Labels = []collectorapi.Label{
194 {Key: "controller_number", Value: num},
195 {Key: "model", Value: strings.TrimSpace(cntrl.Basics.Model)},
196 {Key: "driver_name", Value: cntrl.Version.DriverName},
197 }
198 for _, dim := range chart.Dims {
199 dim.ID = fmt.Sprintf(dim.ID, num)
200 }
201 }
202
203 if err := c.Charts().Add(*charts...); err != nil {
204 c.Warning(err)
205 }
206 }
207
208 func (c *Collector) addPhysDriveCharts(cntrlNum int, di *driveInfo, ds *driveState, da *driveAttrs) {
209 charts := physDriveChartsTmpl.Copy()
210
211 if _, ok := parseInt(getTemperature(ds.DriveTemperature)); !ok {
212 _ = charts.Remove(physDriveTemperatureChartTmpl.ID)
213 }
214
215 num := strconv.Itoa(cntrlNum)
216
217 var enc, slot string
218 if parts := strings.Split(di.EIDSlt, ":"); len(parts) == 2 { // EID:Slt
219 enc, slot = parts[0], parts[1]
220 }
221
222 for _, chart := range *charts {
223 chart.ID = fmt.Sprintf(chart.ID, da.WWN, num)
224 chart.Labels = []collectorapi.Label{
225 {Key: "controller_number", Value: num},
226 {Key: "enclosure_number", Value: enc},
227 {Key: "slot_number", Value: slot},
228 {Key: "media_type", Value: di.Med},
229 }
230 for _, dim := range chart.Dims {
231 dim.ID = fmt.Sprintf(dim.ID, da.WWN, num)
232 }
233 }
234
235 if err := c.Charts().Add(*charts...); err != nil {
236 c.Warning(err)
237 }
238 }
239
240 func (c *Collector) addBBUCharts(cntrlNum, bbuNum, model string) {
241 charts := bbuChartsTmpl.Copy()
242
243 for _, chart := range *charts {
244 chart.ID = fmt.Sprintf(chart.ID, bbuNum, cntrlNum)
245 chart.Labels = []collectorapi.Label{
246 {Key: "controller_number", Value: cntrlNum},
247 {Key: "bbu_number", Value: bbuNum},
248 {Key: "model", Value: model},
249 }
250 for _, dim := range chart.Dims {
251 dim.ID = fmt.Sprintf(dim.ID, bbuNum, cntrlNum)
252 }
253 }
254
255 if err := c.Charts().Add(*charts...); err != nil {
256 c.Warning(err)
257 }
258 }