diff options
Diffstat (limited to 'src/go/plugin/go.d/modules/megacli')
17 files changed, 2062 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/megacli/README.md b/src/go/plugin/go.d/modules/megacli/README.md new file mode 120000 index 00000000..bf0d3098 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/README.md @@ -0,0 +1 @@ +integrations/megacli_megaraid.md
\ No newline at end of file diff --git a/src/go/plugin/go.d/modules/megacli/charts.go b/src/go/plugin/go.d/modules/megacli/charts.go new file mode 100644 index 00000000..c479d567 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/charts.go @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "fmt" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" +) + +const ( + prioAdapterHealthState = module.Priority + iota + + prioPhysDriveMediaErrorsRate + prioPhysDrivePredictiveFailuresRate + + prioBBURelativeCharge + prioBBURechargeCycles + prioBBUCapDegradationPerc + prioBBUTemperature +) + +var adapterChartsTmpl = module.Charts{ + adapterHealthStateChartTmpl.Copy(), +} + +var ( + adapterHealthStateChartTmpl = module.Chart{ + ID: "adapter_%s_health_state", + Title: "Adapter health state", + Units: "state", + Fam: "adapter health", + Ctx: "megacli.adapter_health_state", + Type: module.Line, + Priority: prioAdapterHealthState, + Dims: module.Dims{ + {ID: "adapter_%s_health_state_optimal", Name: "optimal"}, + {ID: "adapter_%s_health_state_degraded", Name: "degraded"}, + {ID: "adapter_%s_health_state_partially_degraded", Name: "partially_degraded"}, + {ID: "adapter_%s_health_state_failed", Name: "failed"}, + }, + } +) + +var physDriveChartsTmpl = module.Charts{ + physDriveMediaErrorsRateChartTmpl.Copy(), + physDrivePredictiveFailuresRateChartTmpl.Copy(), +} + +var ( + physDriveMediaErrorsRateChartTmpl = module.Chart{ + ID: "phys_drive_%s_media_errors_rate", + Title: "Physical Drive media errors rate", + Units: "errors/s", + Fam: "phys drive errors", + Ctx: "megacli.phys_drive_media_errors", + Type: module.Line, + Priority: prioPhysDriveMediaErrorsRate, + Dims: module.Dims{ + {ID: "phys_drive_%s_media_error_count", Name: "media_errors"}, + }, + } + physDrivePredictiveFailuresRateChartTmpl = module.Chart{ + ID: "phys_drive_%s_predictive_failures_rate", + Title: "Physical Drive predictive failures rate", + Units: "failures/s", + Fam: "phys drive errors", + Ctx: "megacli.phys_drive_predictive_failures", + Type: module.Line, + Priority: prioPhysDrivePredictiveFailuresRate, + Dims: module.Dims{ + {ID: "phys_drive_%s_predictive_failure_count", Name: "predictive_failures"}, + }, + } +) + +var bbuChartsTmpl = module.Charts{ + bbuRelativeChargeChartsTmpl.Copy(), + bbuRechargeCyclesChartsTmpl.Copy(), + bbuCapacityDegradationChartsTmpl.Copy(), + bbuTemperatureChartsTmpl.Copy(), +} + +var ( + bbuRelativeChargeChartsTmpl = module.Chart{ + ID: "bbu_adapter_%s_relative_charge", + Title: "BBU relative charge", + Units: "percentage", + Fam: "bbu charge", + Ctx: "megacli.bbu_charge", + Type: module.Area, + Priority: prioBBURelativeCharge, + Dims: module.Dims{ + {ID: "bbu_adapter_%s_relative_state_of_charge", Name: "charge"}, + }, + } + bbuRechargeCyclesChartsTmpl = module.Chart{ + ID: "bbu_adapter_%s_recharge_cycles", + Title: "BBU recharge cycles", + Units: "cycles", + Fam: "bbu charge", + Ctx: "megacli.bbu_recharge_cycles", + Type: module.Line, + Priority: prioBBURechargeCycles, + Dims: module.Dims{ + {ID: "bbu_adapter_%s_cycle_count", Name: "recharge"}, + }, + } + bbuCapacityDegradationChartsTmpl = module.Chart{ + ID: "bbu_adapter_%s_capacity_degradation", + Title: "BBU capacity degradation", + Units: "percent", + Fam: "bbu charge", + Ctx: "megacli.bbu_capacity_degradation", + Type: module.Line, + Priority: prioBBUCapDegradationPerc, + Dims: module.Dims{ + {ID: "bbu_adapter_%s_capacity_degradation_perc", Name: "cap_degradation"}, + }, + } + bbuTemperatureChartsTmpl = module.Chart{ + ID: "bbu_adapter_%s_temperature", + Title: "BBU temperature", + Units: "Celsius", + Fam: "bbu temperature", + Ctx: "megacli.bbu_temperature", + Type: module.Line, + Priority: prioBBUTemperature, + Dims: module.Dims{ + {ID: "bbu_adapter_%s_temperature", Name: "temperature"}, + }, + } +) + +func (m *MegaCli) addAdapterCharts(ad *megaAdapter) { + charts := adapterChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, ad.number) + chart.Labels = []module.Label{ + {Key: "adapter_number", Value: ad.number}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, ad.number) + } + } + + if err := m.Charts().Add(*charts...); err != nil { + m.Warning(err) + } +} + +func (m *MegaCli) addPhysDriveCharts(pd *megaPhysDrive) { + charts := physDriveChartsTmpl.Copy() + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, pd.wwn) + chart.Labels = []module.Label{ + {Key: "adapter_number", Value: pd.adapterNumber}, + {Key: "wwn", Value: pd.wwn}, + {Key: "slot_number", Value: pd.slotNumber}, + {Key: "drive_position", Value: pd.drivePosition}, + {Key: "drive_type", Value: pd.pdType}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, pd.wwn) + } + } + + if err := m.Charts().Add(*charts...); err != nil { + m.Warning(err) + } +} + +func (m *MegaCli) addBBUCharts(bbu *megaBBU) { + charts := bbuChartsTmpl.Copy() + + if _, ok := calcCapDegradationPerc(bbu); !ok { + _ = charts.Remove(bbuCapacityDegradationChartsTmpl.ID) + } + + for _, chart := range *charts { + chart.ID = fmt.Sprintf(chart.ID, bbu.adapterNumber) + chart.Labels = []module.Label{ + {Key: "adapter_number", Value: bbu.adapterNumber}, + {Key: "battery_type", Value: bbu.batteryType}, + } + for _, dim := range chart.Dims { + dim.ID = fmt.Sprintf(dim.ID, bbu.adapterNumber) + } + } + + if err := m.Charts().Add(*charts...); err != nil { + m.Warning(err) + } +} diff --git a/src/go/plugin/go.d/modules/megacli/collect.go b/src/go/plugin/go.d/modules/megacli/collect.go new file mode 100644 index 00000000..c4e74b78 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/collect.go @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "strconv" + "strings" +) + +func (m *MegaCli) collect() (map[string]int64, error) { + mx := make(map[string]int64) + + if err := m.collectPhysDrives(mx); err != nil { + return nil, err + } + if err := m.collectBBU(mx); err != nil { + return nil, err + } + + return mx, nil +} + +func writeInt(mx map[string]int64, key, value string) { + v, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return + } + mx[key] = v +} + +func getColonSepValue(line string) string { + i := strings.IndexByte(line, ':') + if i == -1 { + return "" + } + return strings.TrimSpace(line[i+1:]) +} + +func getColonSepNumValue(line string) string { + v := getColonSepValue(line) + i := strings.IndexByte(v, ' ') + if i == -1 { + return v + } + return v[:i] +} diff --git a/src/go/plugin/go.d/modules/megacli/collect_bbu.go b/src/go/plugin/go.d/modules/megacli/collect_bbu.go new file mode 100644 index 00000000..33b048e6 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/collect_bbu.go @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "bufio" + "bytes" + "fmt" + "strconv" + "strings" +) + +type megaBBU struct { + adapterNumber string + batteryType string + temperature string + rsoc string + asoc string // apparently can be 0 while relative > 0 (e.g. relative 91%, absolute 0%) + cycleCount string + fullChargeCap string + designCap string +} + +func (m *MegaCli) collectBBU(mx map[string]int64) error { + bs, err := m.exec.bbuInfo() + if err != nil { + return err + } + + bbus, err := parseBBUInfo(bs) + if err != nil { + return err + } + + if len(bbus) == 0 { + m.Debugf("no BBUs found") + return nil + } + + for _, bbu := range bbus { + if !m.bbu[bbu.adapterNumber] { + m.bbu[bbu.adapterNumber] = true + m.addBBUCharts(bbu) + } + + px := fmt.Sprintf("bbu_adapter_%s_", bbu.adapterNumber) + + writeInt(mx, px+"temperature", bbu.temperature) + writeInt(mx, px+"relative_state_of_charge", bbu.rsoc) + writeInt(mx, px+"absolute_state_of_charge", bbu.asoc) + writeInt(mx, px+"cycle_count", bbu.cycleCount) + if v, ok := calcCapDegradationPerc(bbu); ok { + mx[px+"capacity_degradation_perc"] = v + } + } + + m.Debugf("found %d BBUs", len(m.bbu)) + + return nil +} + +func parseBBUInfo(bs []byte) (map[string]*megaBBU, error) { + bbus := make(map[string]*megaBBU) + + var section string + var bbu *megaBBU + + sc := bufio.NewScanner(bytes.NewReader(bs)) + + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + + switch { + case strings.HasPrefix(line, "BBU status for Adapter"): + section = "status" + ad := getColonSepValue(line) + if _, ok := bbus[ad]; !ok { + bbu = &megaBBU{adapterNumber: ad} + bbus[ad] = bbu + } + continue + case strings.HasPrefix(line, "BBU Capacity Info for Adapter"): + section = "capacity" + continue + case strings.HasPrefix(line, "BBU Design Info for Adapter"): + section = "design" + continue + case strings.HasPrefix(line, "BBU Firmware Status"), + strings.HasPrefix(line, "BBU GasGauge Status"), + strings.HasPrefix(line, "BBU Properties for Adapter"): + section = "" + continue + } + + if bbu == nil { + continue + } + + switch section { + case "status": + switch { + case strings.HasPrefix(line, "BatteryType:"): + bbu.batteryType = getColonSepValue(line) + case strings.HasPrefix(line, "Temperature:"): + bbu.temperature = getColonSepNumValue(line) + } + case "capacity": + switch { + case strings.HasPrefix(line, "Relative State of Charge:"): + bbu.rsoc = getColonSepNumValue(line) + case strings.HasPrefix(line, "Absolute State of charge:"): + bbu.asoc = getColonSepNumValue(line) + case strings.HasPrefix(line, "Full Charge Capacity:"): + bbu.fullChargeCap = getColonSepNumValue(line) + case strings.HasPrefix(line, "Cycle Count:"): + bbu.cycleCount = getColonSepNumValue(line) + } + case "design": + if strings.HasPrefix(line, "Design Capacity:") { + bbu.designCap = getColonSepNumValue(line) + } + } + } + + return bbus, nil +} + +func calcCapDegradationPerc(bbu *megaBBU) (int64, bool) { + full, err := strconv.ParseInt(bbu.fullChargeCap, 10, 64) + if err != nil || full == 0 { + return 0, false + } + design, err := strconv.ParseInt(bbu.designCap, 10, 64) + if err != nil || design == 0 { + return 0, false + } + + v := 100 - float64(full)/float64(design)*100 + + return int64(v), true +} diff --git a/src/go/plugin/go.d/modules/megacli/collect_phys_drives.go b/src/go/plugin/go.d/modules/megacli/collect_phys_drives.go new file mode 100644 index 00000000..71d4546e --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/collect_phys_drives.go @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "strings" +) + +type ( + megaAdapter struct { + number string + name string + state string + physDrives map[string]*megaPhysDrive + } + megaPhysDrive struct { + adapterNumber string + number string + wwn string + slotNumber string + drivePosition string + pdType string + mediaErrorCount string + predictiveFailureCount string + } +) + +var adapterStates = []string{ + "optimal", + "degraded", + "partially_degraded", + "failed", +} + +func (m *MegaCli) collectPhysDrives(mx map[string]int64) error { + bs, err := m.exec.physDrivesInfo() + if err != nil { + return err + } + + adapters, err := parsePhysDrivesInfo(bs) + if err != nil { + return err + } + if len(adapters) == 0 { + return errors.New("no adapters found") + } + + var drives int + + for _, ad := range adapters { + if !m.adapters[ad.number] { + m.adapters[ad.number] = true + m.addAdapterCharts(ad) + } + + px := fmt.Sprintf("adapter_%s_health_state_", ad.number) + for _, st := range adapterStates { + mx[px+st] = 0 + } + st := strings.ReplaceAll(strings.ToLower(ad.state), " ", "_") + mx[px+st] = 1 + + for _, pd := range ad.physDrives { + if !m.adapters[pd.wwn] { + m.adapters[pd.wwn] = true + m.addPhysDriveCharts(pd) + } + drives++ + + px := fmt.Sprintf("phys_drive_%s_", pd.wwn) + + writeInt(mx, px+"media_error_count", pd.mediaErrorCount) + writeInt(mx, px+"predictive_failure_count", pd.predictiveFailureCount) + } + } + + m.Debugf("found %d adapters, %d physical drives", len(m.adapters), drives) + + return nil +} + +func parsePhysDrivesInfo(bs []byte) (map[string]*megaAdapter, error) { + adapters := make(map[string]*megaAdapter) + + var ad *megaAdapter + var pd *megaPhysDrive + + sc := bufio.NewScanner(bytes.NewReader(bs)) + + for sc.Scan() { + line := strings.TrimSpace(sc.Text()) + + switch { + case strings.HasPrefix(line, "Adapter #"): + idx := strings.TrimPrefix(line, "Adapter #") + ad = &megaAdapter{number: idx, physDrives: make(map[string]*megaPhysDrive)} + adapters[idx] = ad + case strings.HasPrefix(line, "Name") && ad != nil: + ad.name = getColonSepValue(line) + case strings.HasPrefix(line, "State") && ad != nil: + ad.state = getColonSepValue(line) + case strings.HasPrefix(line, "PD:") && ad != nil: + if parts := strings.Fields(line); len(parts) == 3 { + idx := parts[1] + pd = &megaPhysDrive{number: idx, adapterNumber: ad.number} + ad.physDrives[idx] = pd + } + case strings.HasPrefix(line, "Slot Number:") && pd != nil: + pd.slotNumber = getColonSepValue(line) + case strings.HasPrefix(line, "Drive's position:") && pd != nil: + pd.drivePosition = getColonSepValue(line) + case strings.HasPrefix(line, "WWN:") && pd != nil: + pd.wwn = getColonSepValue(line) + case strings.HasPrefix(line, "PD Type:") && pd != nil: + pd.pdType = getColonSepValue(line) + case strings.HasPrefix(line, "Media Error Count:") && pd != nil: + pd.mediaErrorCount = getColonSepNumValue(line) + case strings.HasPrefix(line, "Predictive Failure Count:") && pd != nil: + pd.predictiveFailureCount = getColonSepNumValue(line) + } + } + + return adapters, nil +} diff --git a/src/go/plugin/go.d/modules/megacli/config_schema.json b/src/go/plugin/go.d/modules/megacli/config_schema.json new file mode 100644 index 00000000..6eb36519 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/config_schema.json @@ -0,0 +1,35 @@ +{ + "jsonSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "MegaCli collector configuration.", + "type": "object", + "properties": { + "update_every": { + "title": "Update every", + "description": "Data collection interval, measured in seconds.", + "type": "integer", + "minimum": 1, + "default": 10 + }, + "timeout": { + "title": "Timeout", + "description": "Timeout for executing the binary, specified in seconds.", + "type": "number", + "minimum": 0.5, + "default": 2 + } + }, + "additionalProperties": false, + "patternProperties": { + "^name$": {} + } + }, + "uiSchema": { + "uiOptions": { + "fullPage": true + }, + "timeout": { + "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)." + } + } +} diff --git a/src/go/plugin/go.d/modules/megacli/exec.go b/src/go/plugin/go.d/modules/megacli/exec.go new file mode 100644 index 00000000..846952b2 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/exec.go @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "context" + "fmt" + "os/exec" + "time" + + "github.com/netdata/netdata/go/plugins/logger" +) + +func newMegaCliExec(ndsudoPath string, timeout time.Duration, log *logger.Logger) *megaCliExec { + return &megaCliExec{ + Logger: log, + ndsudoPath: ndsudoPath, + timeout: timeout, + } +} + +type megaCliExec struct { + *logger.Logger + + ndsudoPath string + timeout time.Duration +} + +func (e *megaCliExec) physDrivesInfo() ([]byte, error) { + return e.execute("megacli-disk-info") +} + +func (e *megaCliExec) bbuInfo() ([]byte, error) { + return e.execute("megacli-battery-info") +} + +func (e *megaCliExec) execute(args ...string) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), e.timeout) + defer cancel() + + cmd := exec.CommandContext(ctx, e.ndsudoPath, args...) + e.Debugf("executing '%s'", cmd) + + bs, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("error on '%s': %v", cmd, err) + } + + return bs, nil +} diff --git a/src/go/plugin/go.d/modules/megacli/init.go b/src/go/plugin/go.d/modules/megacli/init.go new file mode 100644 index 00000000..78b7bf48 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/init.go @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/netdata/netdata/go/plugins/pkg/executable" +) + +func (m *MegaCli) initMegaCliExec() (megaCli, error) { + ndsudoPath := filepath.Join(executable.Directory, "ndsudo") + + if _, err := os.Stat(ndsudoPath); err != nil { + return nil, fmt.Errorf("ndsudo executable not found: %v", err) + } + + megaExec := newMegaCliExec(ndsudoPath, m.Timeout.Duration(), m.Logger) + + return megaExec, nil +} diff --git a/src/go/plugin/go.d/modules/megacli/integrations/megacli_megaraid.md b/src/go/plugin/go.d/modules/megacli/integrations/megacli_megaraid.md new file mode 100644 index 00000000..d1efa7df --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/integrations/megacli_megaraid.md @@ -0,0 +1,250 @@ +<!--startmeta +custom_edit_url: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/megacli/README.md" +meta_yaml: "https://github.com/netdata/netdata/edit/master/src/go/plugin/go.d/modules/megacli/metadata.yaml" +sidebar_label: "MegaCLI MegaRAID" +learn_status: "Published" +learn_rel_path: "Collecting Metrics/Storage, Mount Points and Filesystems" +most_popular: False +message: "DO NOT EDIT THIS FILE DIRECTLY, IT IS GENERATED BY THE COLLECTOR'S metadata.yaml FILE" +endmeta--> + +# MegaCLI MegaRAID + + +<img src="https://netdata.cloud/img/hard-drive.svg" width="150"/> + + +Plugin: go.d.plugin +Module: megacli + +<img src="https://img.shields.io/badge/maintained%20by-Netdata-%2300ab44" /> + +## Overview + +Monitors the health of MegaCLI Hardware RAID by tracking the status of RAID adapters, physical drives, and backup batteries in your storage system. +It relies on the `megacli` CLI tool but avoids directly executing the binary. +Instead, it utilizes `ndsudo`, a Netdata helper specifically designed to run privileged commands securely within the Netdata environment. +This approach eliminates the need to use `sudo`, improving security and potentially simplifying permission management. + +Executed commands: +- `megacli -LDPDInfo -aAll -NoLog` +- `megacli -AdpBbuCmd -aAll -NoLog` + + + + +This collector is supported on all platforms. + +This collector only supports collecting metrics from a single instance of this integration. + + +### Default Behavior + +#### Auto-Detection + +This integration doesn't support auto-detection. + +#### Limits + +The default configuration for this integration does not impose any limits on data collection. + +#### Performance Impact + +The default configuration for this integration is not expected to impose a significant performance impact on the system. + + +## Metrics + +Metrics grouped by *scope*. + +The scope defines the instance that the metric belongs to. An instance is uniquely identified by a set of labels. + + + +### Per adapter + +These metrics refer to the MegaCLI Adapter. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| adapter_number | Adapter number | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| megacli.adapter_health_state | optimal, degraded, partially_degraded, failed | state | + +### Per physical drive + +These metrics refer to the MegaCLI Physical Drive. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| adapter_number | Adapter number | +| wwn | World Wide Name | +| slot_number | Slot number | +| drive_position | Position (e.g. DiskGroup: 0, Span: 0, Arm: 2) | +| drive_type | Type (e.g. SATA) | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| megacli.phys_drive_media_errors_rate | media_errors | errors/s | +| megacli.phys_drive_predictive_failures_rate | predictive_failures | failures/s | + +### Per backup battery unit + +These metrics refer to the MegaCLI Backup Battery Unit. + +Labels: + +| Label | Description | +|:-----------|:----------------| +| adapter_number | Adapter number | +| battery_type | Battery type (e.g. BBU) | + +Metrics: + +| Metric | Dimensions | Unit | +|:------|:----------|:----| +| megacli.bbu_charge | charge | percentage | +| megacli.bbu_recharge_cycles | recharge | cycles | +| megacli.bbu_capacity_degradation | cap_degradation | percent | +| megacli.bbu_temperature | temperature | Celsius | + + + +## Alerts + + +The following alerts are available: + +| Alert name | On metric | Description | +|:------------|:----------|:------------| +| [ megacli_adapter_health_state ](https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf) | megacli.adapter_health_state | MegaCLI adapter ${label:adapter_number} is in the degraded state | +| [ megacli_phys_drive_media_errors ](https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf) | megacli.phys_drive_media_errors | MegaCLI physical drive adapter ${label:adapter_number} slot ${label:slot_number} media errors | +| [ megacli_phys_drive_predictive_failures ](https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf) | megacli.phys_drive_predictive_failures | MegaCLI physical drive (adapter ${label:adapter_number} slot ${label:slot_number}) predictive failures | +| [ megacli_bbu_charge ](https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf) | megacli.bbu_charge | MegaCLI Backup Battery Unit (adapter ${label:adapter_number}) average charge over the last minute | +| [ megacli_bbu_recharge_cycles ](https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf) | megacli.bbu_recharge_cycles | MegaCLI Backup Battery Unit (adapter ${label:adapter_number}) average charge over the last minute | + + +## Setup + +### Prerequisites + +No action required. + +### Configuration + +#### File + +The configuration file name for this integration is `go.d/megacli.conf`. + + +You can edit the configuration file using the `edit-config` script from the +Netdata [config directory](/docs/netdata-agent/configuration/README.md#the-netdata-config-directory). + +```bash +cd /etc/netdata 2>/dev/null || cd /opt/netdata/etc/netdata +sudo ./edit-config go.d/megacli.conf +``` +#### Options + +The following options can be defined globally: update_every. + + +<details open><summary>Config options</summary> + +| Name | Description | Default | Required | +|:----|:-----------|:-------|:--------:| +| update_every | Data collection frequency. | 10 | no | +| timeout | megacli binary execution timeout. | 2 | no | + +</details> + +#### Examples + +##### Custom update_every + +Allows you to override the default data collection interval. + +<details open><summary>Config</summary> + +```yaml +jobs: + - name: megacli + update_every: 5 # Collect MegaCli Hardware RAID statistics every 5 seconds + +``` +</details> + + + +## Troubleshooting + +### Debug Mode + +**Important**: Debug mode is not supported for data collection jobs created via the UI using the Dyncfg feature. + +To troubleshoot issues with the `megacli` collector, run the `go.d.plugin` with the debug option enabled. The output +should give you clues as to why the collector isn't working. + +- Navigate to the `plugins.d` directory, usually at `/usr/libexec/netdata/plugins.d/`. If that's not the case on + your system, open `netdata.conf` and look for the `plugins` setting under `[directories]`. + + ```bash + cd /usr/libexec/netdata/plugins.d/ + ``` + +- Switch to the `netdata` user. + + ```bash + sudo -u netdata -s + ``` + +- Run the `go.d.plugin` to debug the collector: + + ```bash + ./go.d.plugin -d -m megacli + ``` + +### Getting Logs + +If you're encountering problems with the `megacli` collector, follow these steps to retrieve logs and identify potential issues: + +- **Run the command** specific to your system (systemd, non-systemd, or Docker container). +- **Examine the output** for any warnings or error messages that might indicate issues. These messages should provide clues about the root cause of the problem. + +#### System with systemd + +Use the following command to view logs generated since the last Netdata service restart: + +```bash +journalctl _SYSTEMD_INVOCATION_ID="$(systemctl show --value --property=InvocationID netdata)" --namespace=netdata --grep megacli +``` + +#### System without systemd + +Locate the collector log file, typically at `/var/log/netdata/collector.log`, and use `grep` to filter for collector's name: + +```bash +grep megacli /var/log/netdata/collector.log +``` + +**Note**: This method shows logs from all restarts. Focus on the **latest entries** for troubleshooting current issues. + +#### Docker Container + +If your Netdata runs in a Docker container named "netdata" (replace if different), use this command: + +```bash +docker logs netdata 2>&1 | grep megacli +``` + + diff --git a/src/go/plugin/go.d/modules/megacli/megacli.go b/src/go/plugin/go.d/modules/megacli/megacli.go new file mode 100644 index 00000000..41abd7a1 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/megacli.go @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + _ "embed" + "errors" + "time" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web" +) + +//go:embed "config_schema.json" +var configSchema string + +func init() { + module.Register("megacli", module.Creator{ + JobConfigSchema: configSchema, + Defaults: module.Defaults{ + UpdateEvery: 10, + }, + Create: func() module.Module { return New() }, + Config: func() any { return &Config{} }, + }) +} + +func New() *MegaCli { + return &MegaCli{ + Config: Config{ + Timeout: web.Duration(time.Second * 2), + }, + charts: &module.Charts{}, + adapters: make(map[string]bool), + drives: make(map[string]bool), + bbu: make(map[string]bool), + } +} + +type Config struct { + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"` + Timeout web.Duration `yaml:"timeout,omitempty" json:"timeout"` +} + +type ( + MegaCli struct { + module.Base + Config `yaml:",inline" json:""` + + charts *module.Charts + + exec megaCli + + adapters map[string]bool + drives map[string]bool + bbu map[string]bool + } + megaCli interface { + physDrivesInfo() ([]byte, error) + bbuInfo() ([]byte, error) + } +) + +func (m *MegaCli) Configuration() any { + return m.Config +} + +func (m *MegaCli) Init() error { + lvmExec, err := m.initMegaCliExec() + if err != nil { + m.Errorf("megacli exec initialization: %v", err) + return err + } + m.exec = lvmExec + + return nil +} + +func (m *MegaCli) Check() error { + mx, err := m.collect() + if err != nil { + m.Error(err) + return err + } + + if len(mx) == 0 { + return errors.New("no metrics collected") + } + + return nil +} + +func (m *MegaCli) Charts() *module.Charts { + return m.charts +} + +func (m *MegaCli) Collect() map[string]int64 { + mx, err := m.collect() + if err != nil { + m.Error(err) + } + + if len(mx) == 0 { + return nil + } + + return mx +} + +func (m *MegaCli) Cleanup() {} diff --git a/src/go/plugin/go.d/modules/megacli/megacli_test.go b/src/go/plugin/go.d/modules/megacli/megacli_test.go new file mode 100644 index 00000000..4991a28c --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/megacli_test.go @@ -0,0 +1,301 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package megacli + +import ( + "errors" + "os" + "testing" + + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var ( + dataConfigJSON, _ = os.ReadFile("testdata/config.json") + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml") + + dataBBUInfoOld, _ = os.ReadFile("testdata/mega-bbu-info-old.txt") + dataBBUInfoRecent, _ = os.ReadFile("testdata/mega-bbu-info-recent.txt") + dataPhysDrivesInfo, _ = os.ReadFile("testdata/mega-phys-drives-info.txt") +) + +func Test_testDataIsValid(t *testing.T) { + for name, data := range map[string][]byte{ + "dataConfigJSON": dataConfigJSON, + "dataConfigYAML": dataConfigYAML, + + "dataBBUInfoOld": dataBBUInfoOld, + "dataBBUInfoRecent": dataBBUInfoRecent, + "dataPhysDrivesInfo": dataPhysDrivesInfo, + } { + require.NotNil(t, data, name) + } +} + +func TestMegaCli_ConfigurationSerialize(t *testing.T) { + module.TestConfigurationSerialize(t, &MegaCli{}, dataConfigJSON, dataConfigYAML) +} + +func TestMegaCli_Init(t *testing.T) { + tests := map[string]struct { + config Config + wantFail bool + }{ + "fails if 'ndsudo' not found": { + wantFail: true, + config: New().Config, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + mega := New() + + if test.wantFail { + assert.Error(t, mega.Init()) + } else { + assert.NoError(t, mega.Init()) + } + }) + } +} + +func TestMegaCli_Cleanup(t *testing.T) { + tests := map[string]struct { + prepare func() *MegaCli + }{ + "not initialized exec": { + prepare: func() *MegaCli { + return New() + }, + }, + "after check": { + prepare: func() *MegaCli { + mega := New() + mega.exec = prepareMockOK() + _ = mega.Check() + return mega + }, + }, + "after collect": { + prepare: func() *MegaCli { + mega := New() + mega.exec = prepareMockOK() + _ = mega.Collect() + return mega + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + mega := test.prepare() + + assert.NotPanics(t, mega.Cleanup) + }) + } +} + +func TestMegaCli_Charts(t *testing.T) { + assert.NotNil(t, New().Charts()) +} + +func TestMegaCli_Check(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockMegaCliExec + wantFail bool + }{ + "success case": { + wantFail: false, + prepareMock: prepareMockOK, + }, + "success case old bbu": { + wantFail: false, + prepareMock: prepareMockOldBbuOK, + }, + "err on exec": { + wantFail: true, + prepareMock: prepareMockErr, + }, + "unexpected response": { + wantFail: true, + prepareMock: prepareMockUnexpectedResponse, + }, + "empty response": { + wantFail: true, + prepareMock: prepareMockEmptyResponse, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + mega := New() + mock := test.prepareMock() + mega.exec = mock + + if test.wantFail { + assert.Error(t, mega.Check()) + } else { + assert.NoError(t, mega.Check()) + } + }) + } +} + +func TestMegaCli_Collect(t *testing.T) { + tests := map[string]struct { + prepareMock func() *mockMegaCliExec + wantMetrics map[string]int64 + wantCharts int + }{ + "success case": { + prepareMock: prepareMockOK, + wantCharts: len(adapterChartsTmpl)*1 + len(physDriveChartsTmpl)*8 + len(bbuChartsTmpl)*1, + wantMetrics: map[string]int64{ + "adapter_0_health_state_degraded": 0, + "adapter_0_health_state_failed": 0, + "adapter_0_health_state_optimal": 1, + "adapter_0_health_state_partially_degraded": 0, + "bbu_adapter_0_absolute_state_of_charge": 63, + "bbu_adapter_0_capacity_degradation_perc": 10, + "bbu_adapter_0_cycle_count": 4, + "bbu_adapter_0_relative_state_of_charge": 71, + "bbu_adapter_0_temperature": 33, + "phys_drive_5002538c00019b96_media_error_count": 0, + "phys_drive_5002538c00019b96_predictive_failure_count": 0, + "phys_drive_5002538c4002da83_media_error_count": 0, + "phys_drive_5002538c4002da83_predictive_failure_count": 0, + "phys_drive_5002538c4002dade_media_error_count": 0, + "phys_drive_5002538c4002dade_predictive_failure_count": 0, + "phys_drive_5002538c4002e6e9_media_error_count": 0, + "phys_drive_5002538c4002e6e9_predictive_failure_count": 0, + "phys_drive_5002538c4002e707_media_error_count": 0, + "phys_drive_5002538c4002e707_predictive_failure_count": 0, + "phys_drive_5002538c4002e70f_media_error_count": 0, + "phys_drive_5002538c4002e70f_predictive_failure_count": 0, + "phys_drive_5002538c4002e712_media_error_count": 0, + "phys_drive_5002538c4002e712_predictive_failure_count": 0, + "phys_drive_5002538c4002e713_media_error_count": 0, + "phys_drive_5002538c4002e713_predictive_failure_count": 0, + }, + }, + "success case old bbu": { + prepareMock: prepareMockOldBbuOK, + wantCharts: len(adapterChartsTmpl)*1 + len(physDriveChartsTmpl)*8 + len(bbuChartsTmpl)*1, + wantMetrics: map[string]int64{ + "adapter_0_health_state_degraded": 0, + "adapter_0_health_state_failed": 0, + "adapter_0_health_state_optimal": 1, + "adapter_0_health_state_partially_degraded": 0, + "bbu_adapter_0_absolute_state_of_charge": 83, + "bbu_adapter_0_capacity_degradation_perc": 17, + "bbu_adapter_0_cycle_count": 61, + "bbu_adapter_0_relative_state_of_charge": 100, + "bbu_adapter_0_temperature": 31, + "phys_drive_5002538c00019b96_media_error_count": 0, + "phys_drive_5002538c00019b96_predictive_failure_count": 0, + "phys_drive_5002538c4002da83_media_error_count": 0, + "phys_drive_5002538c4002da83_predictive_failure_count": 0, + "phys_drive_5002538c4002dade_media_error_count": 0, + "phys_drive_5002538c4002dade_predictive_failure_count": 0, + "phys_drive_5002538c4002e6e9_media_error_count": 0, + "phys_drive_5002538c4002e6e9_predictive_failure_count": 0, + "phys_drive_5002538c4002e707_media_error_count": 0, + "phys_drive_5002538c4002e707_predictive_failure_count": 0, + "phys_drive_5002538c4002e70f_media_error_count": 0, + "phys_drive_5002538c4002e70f_predictive_failure_count": 0, + "phys_drive_5002538c4002e712_media_error_count": 0, + "phys_drive_5002538c4002e712_predictive_failure_count": 0, + "phys_drive_5002538c4002e713_media_error_count": 0, + "phys_drive_5002538c4002e713_predictive_failure_count": 0, + }, + }, + "err on exec": { + prepareMock: prepareMockErr, + wantMetrics: nil, + }, + "unexpected response": { + prepareMock: prepareMockUnexpectedResponse, + wantMetrics: nil, + }, + "empty response": { + prepareMock: prepareMockEmptyResponse, + wantMetrics: nil, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + mega := New() + mock := test.prepareMock() + mega.exec = mock + + mx := mega.Collect() + + assert.Equal(t, test.wantMetrics, mx) + assert.Len(t, *mega.Charts(), test.wantCharts) + if len(test.wantMetrics) > 0 { + module.TestMetricsHasAllChartsDims(t, mega.Charts(), mx) + } + }) + } +} + +func prepareMockOK() *mockMegaCliExec { + return &mockMegaCliExec{ + physDrivesInfoData: dataPhysDrivesInfo, + bbuInfoData: dataBBUInfoRecent, + } +} + +func prepareMockOldBbuOK() *mockMegaCliExec { + return &mockMegaCliExec{ + physDrivesInfoData: dataPhysDrivesInfo, + bbuInfoData: dataBBUInfoOld, + } +} + +func prepareMockErr() *mockMegaCliExec { + return &mockMegaCliExec{ + errOnInfo: true, + } +} + +func prepareMockUnexpectedResponse() *mockMegaCliExec { + resp := []byte(` +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +Nulla malesuada erat id magna mattis, eu viverra tellus rhoncus. +Fusce et felis pulvinar, posuere sem non, porttitor eros. +`) + return &mockMegaCliExec{ + physDrivesInfoData: resp, + bbuInfoData: resp, + } +} + +func prepareMockEmptyResponse() *mockMegaCliExec { + return &mockMegaCliExec{} +} + +type mockMegaCliExec struct { + errOnInfo bool + physDrivesInfoData []byte + bbuInfoData []byte +} + +func (m *mockMegaCliExec) physDrivesInfo() ([]byte, error) { + if m.errOnInfo { + return nil, errors.New("mock.physDrivesInfo() error") + } + return m.physDrivesInfoData, nil +} + +func (m *mockMegaCliExec) bbuInfo() ([]byte, error) { + if m.errOnInfo { + return nil, errors.New("mock.bbuInfo() error") + } + return m.bbuInfoData, nil +} diff --git a/src/go/plugin/go.d/modules/megacli/metadata.yaml b/src/go/plugin/go.d/modules/megacli/metadata.yaml new file mode 100644 index 00000000..da5f4fef --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/metadata.yaml @@ -0,0 +1,183 @@ +plugin_name: go.d.plugin +modules: + - meta: + id: collector-go.d.plugin-megacli + plugin_name: go.d.plugin + module_name: megacli + monitored_instance: + name: MegaCLI MegaRAID + link: "https://wikitech.wikimedia.org/wiki/MegaCli" + icon_filename: "hard-drive.svg" + categories: + - data-collection.storage-mount-points-and-filesystems + keywords: + - storage + - raid-controller + - manage-disks + related_resources: + integrations: + list: [] + info_provided_to_referring_integrations: + description: "" + most_popular: false + overview: + data_collection: + metrics_description: | + Monitors the health of MegaCLI Hardware RAID by tracking the status of RAID adapters, physical drives, and backup batteries in your storage system. + It relies on the `megacli` CLI tool but avoids directly executing the binary. + Instead, it utilizes `ndsudo`, a Netdata helper specifically designed to run privileged commands securely within the Netdata environment. + This approach eliminates the need to use `sudo`, improving security and potentially simplifying permission management. + + Executed commands: + - `megacli -LDPDInfo -aAll -NoLog` + - `megacli -AdpBbuCmd -aAll -NoLog` + method_description: "" + supported_platforms: + include: [] + exclude: [] + multi_instance: false + additional_permissions: + description: "" + default_behavior: + auto_detection: + description: "" + limits: + description: "" + performance_impact: + description: "" + setup: + prerequisites: + list: [] + configuration: + file: + name: go.d/megacli.conf + options: + description: | + The following options can be defined globally: update_every. + folding: + title: Config options + enabled: true + list: + - name: update_every + description: Data collection frequency. + default_value: 10 + required: false + - name: timeout + description: megacli binary execution timeout. + default_value: 2 + required: false + examples: + folding: + title: Config + enabled: true + list: + - name: Custom update_every + description: Allows you to override the default data collection interval. + config: | + jobs: + - name: megacli + update_every: 5 # Collect MegaCli Hardware RAID statistics every 5 seconds + troubleshooting: + problems: + list: [] + alerts: + - name: megacli_adapter_health_state + metric: megacli.adapter_health_state + info: MegaCLI adapter ${label:adapter_number} is in the degraded state + link: https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf + - name: megacli_phys_drive_media_errors + metric: megacli.phys_drive_media_errors + info: MegaCLI physical drive adapter ${label:adapter_number} slot ${label:slot_number} media errors + link: https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf + - name: megacli_phys_drive_predictive_failures + metric: megacli.phys_drive_predictive_failures + info: MegaCLI physical drive (adapter ${label:adapter_number} slot ${label:slot_number}) predictive failures + link: https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf + - name: megacli_bbu_charge + metric: megacli.bbu_charge + info: MegaCLI Backup Battery Unit (adapter ${label:adapter_number}) average charge over the last minute + link: https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf + - name: megacli_bbu_recharge_cycles + metric: megacli.bbu_recharge_cycles + info: MegaCLI Backup Battery Unit (adapter ${label:adapter_number}) average charge over the last minute + link: https://github.com/netdata/netdata/blob/master/src/health/health.d/megacli.conf + metrics: + folding: + title: Metrics + enabled: false + description: "" + availability: [] + scopes: + - name: adapter + description: These metrics refer to the MegaCLI Adapter. + labels: + - name: adapter_number + description: Adapter number + metrics: + - name: megacli.adapter_health_state + description: Adapter health state + unit: state + chart_type: line + dimensions: + - name: optimal + - name: degraded + - name: partially_degraded + - name: failed + - name: physical drive + description: These metrics refer to the MegaCLI Physical Drive. + labels: + - name: adapter_number + description: Adapter number + - name: wwn + description: World Wide Name + - name: slot_number + description: Slot number + - name: drive_position + description: "Position (e.g. DiskGroup: 0, Span: 0, Arm: 2)" + - name: drive_type + description: Type (e.g. SATA) + metrics: + - name: megacli.phys_drive_media_errors_rate + description: Physical Drive media errors rate + unit: errors/s + chart_type: line + dimensions: + - name: media_errors + - name: megacli.phys_drive_predictive_failures_rate + description: Physical Drive predictive failures rate + unit: failures/s + chart_type: line + dimensions: + - name: predictive_failures + - name: backup battery unit + description: These metrics refer to the MegaCLI Backup Battery Unit. + labels: + - name: adapter_number + description: Adapter number + - name: battery_type + description: Battery type (e.g. BBU) + metrics: + - name: megacli.bbu_charge + description: BBU relative charge + unit: percentage + chart_type: area + dimensions: + - name: charge + - name: megacli.bbu_recharge_cycles + description: BBU relative charge + unit: cycles + chart_type: line + dimensions: + - name: recharge + - name: megacli.bbu_capacity_degradation + description: BBU capacity degradation + unit: percent + chart_type: area + dimensions: + - name: cap_degradation + - name: megacli.bbu_temperature + description: BBU bbu_temperature + unit: Celsius + chart_type: line + dimensions: + - name: temperature diff --git a/src/go/plugin/go.d/modules/megacli/testdata/config.json b/src/go/plugin/go.d/modules/megacli/testdata/config.json new file mode 100644 index 00000000..291ecee3 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/testdata/config.json @@ -0,0 +1,4 @@ +{ + "update_every": 123, + "timeout": 123.123 +} diff --git a/src/go/plugin/go.d/modules/megacli/testdata/config.yaml b/src/go/plugin/go.d/modules/megacli/testdata/config.yaml new file mode 100644 index 00000000..25b0b4c7 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/testdata/config.yaml @@ -0,0 +1,2 @@ +update_every: 123 +timeout: 123.123 diff --git a/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-old.txt b/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-old.txt new file mode 100644 index 00000000..054ce54d --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-old.txt @@ -0,0 +1,84 @@ +BBU status for Adapter: 0 + +BatteryType: BBU +Voltage: 4073 mV +Current: 0 mA +Temperature: 31 C +Battery State: Optimal +BBU Firmware Status: + + Charging Status : None + Voltage : OK + Temperature : OK + Learn Cycle Requested : No + Learn Cycle Active : No + Learn Cycle Status : OK + Learn Cycle Timeout : No + I2c Errors Detected : No + Battery Pack Missing : No + Battery Replacement required : No + Remaining Capacity Low : No + Periodic Learn Required : No + Transparent Learn : No + No space to cache offload : No + Pack is about to fail & should be replaced : No + Cache Offload premium feature required : No + Module microcode update required : No + + +GasGuageStatus: + Fully Discharged : No + Fully Charged : Yes + Discharging : Yes + Initialized : Yes + Remaining Time Alarm : No + Discharge Terminated : No + Over Temperature : No + Charging Terminated : Yes + Over Charged : No +Relative State of Charge: 100 % +Charger Status: Complete +Remaining Capacity: 1477 mAh +Full Charge Capacity: 1477 mAh +isSOHGood: Yes + Battery backup charge time : 0 hours + +BBU Capacity Info for Adapter: 0 + + Relative State of Charge: 100 % + Absolute State of charge: 83 % + Remaining Capacity: 1477 mAh + Full Charge Capacity: 1477 mAh + Run time to empty: Battery is not being charged. + Average time to empty: Battery is not being charged. + Estimated Time to full recharge: Battery is not being charged. + Cycle Count: 61 +Max Error = 2 % +Remaining Capacity Alarm = 180 mAh +Remining Time Alarm = 10 Min + +BBU Design Info for Adapter: 0 + + Date of Manufacture: 07/08, 2010 + Design Capacity: 1800 mAh + Design Voltage: 3700 mV + Specification Info: 49 + Serial Number: 4069 + Pack Stat Configuration: 0x0014 + Manufacture Name: SMP-PA1.9 + Firmware Version : � + Device Name: DLFR463 + Device Chemistry: LION + Battery FRU: N/A +Module Version = � + Transparent Learn = 0 + App Data = 0 + +BBU Properties for Adapter: 0 + + Auto Learn Period: 90 Days + Next Learn time: Fri Jan 28 13:07:56 2022 + Learn Delay Interval:0 Hours + Auto-Learn Mode: Enabled + +Exit Code: 0x00 diff --git a/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-recent.txt b/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-recent.txt new file mode 100644 index 00000000..948be372 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/testdata/mega-bbu-info-recent.txt @@ -0,0 +1,74 @@ +BBU status for Adapter: 0 + +BatteryType: iBBU08 +Voltage: 3922 mV +Current: 0 mA +Temperature: 33 C +Battery State: Optimal +Design Mode : 48+ Hrs retention with a non-transparent learn cycle and balanced service life. + +BBU Firmware Status: + + Charging Status : None + Voltage : OK + Temperature : OK + Learn Cycle Requested : No + Learn Cycle Active : No + Learn Cycle Status : OK + Learn Cycle Timeout : No + I2c Errors Detected : No + Battery Pack Missing : No + Battery Replacement required : No + Remaining Capacity Low : No + Periodic Learn Required : No + Transparent Learn : No + No space to cache offload : No + Pack is about to fail & should be replaced : No + Cache Offload premium feature required : No + Module microcode update required : No + +BBU GasGauge Status: 0x0100 + Relative State of Charge: 71 % + Charger System State: 1 + Charger System Ctrl: 0 + Charging current: 0 mA + Absolute state of charge: 63 % + Max Error: 0 % + Battery backup charge time : 48 hours + + +BBU Capacity Info for Adapter: 0 + + Relative State of Charge: 71 % + Absolute State of charge: 63 % + Remaining Capacity: 969 mAh + Full Charge Capacity: 1365 mAh + Run time to empty: Battery is not being charged. + Average time to empty: 1 Hour, 56 Min. + Estimated Time to full recharge: Battery is not being charged. + Cycle Count: 4 + +BBU Design Info for Adapter: 0 + + Date of Manufacture: 03/18, 2011 + Design Capacity: 1530 mAh + Design Voltage: 4100 mV + Specification Info: 0 + Serial Number: 5164 + Pack Stat Configuration: 0x0000 + Manufacture Name: LS36681 + Firmware Version : + Device Name: bq27541 + Device Chemistry: LPMR + Battery FRU: N/A + Transparent Learn = 0 + App Data = 0 + +BBU Properties for Adapter: 0 + + Auto Learn Period: 28 Days + Next Learn time: Thu Dec 21 18:32:56 2023 + Learn Delay Interval:0 Hours + Auto-Learn Mode: Enabled + BBU Mode = 4 + +Exit Code: 0x00 diff --git a/src/go/plugin/go.d/modules/megacli/testdata/mega-phys-drives-info.txt b/src/go/plugin/go.d/modules/megacli/testdata/mega-phys-drives-info.txt new file mode 100644 index 00000000..142ddc82 --- /dev/null +++ b/src/go/plugin/go.d/modules/megacli/testdata/mega-phys-drives-info.txt @@ -0,0 +1,433 @@ +Adapter #0 + +Number of Virtual Disks: 1 +Virtual Drive: 0 (Target Id: 0) +Name :Virtual Disk 0 +RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0 +Size : 3.491 TB +Sector Size : 512 +Is VD emulated : No +Mirror Data : 3.491 TB +State : Optimal +Strip Size : 64 KB +Number Of Drives : 8 +Span Depth : 1 +Default Cache Policy: WriteBack, ReadAhead, Direct, No Write Cache if Bad BBU +Current Cache Policy: WriteBack, ReadAhead, Direct, No Write Cache if Bad BBU +Default Access Policy: Read/Write +Current Access Policy: Read/Write +Disk Cache Policy : Disk's Default +Encryption Type : None +Default Power Savings Policy: Controller Defined +Current Power Savings Policy: None +Can spin up in 1 minute: No +LD has drives that support T10 power conditions: No +LD's IO profile supports MAX power savings with cached writes: No +Bad Blocks Exist: No +PI type: No PI + +Is VD Cached: No +Number of Spans: 1 +Span: 0 - Number of PDs: 8 + +PD: 0 Information +Enclosure Device ID: 32 +Slot Number: 0 +Drive's position: DiskGroup: 0, Span: 0, Arm: 0 +Enclosure position: 1 +Device Id: 0 +WWN: 5002538c4002e713 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221104000000 +Connected Port Number: 4(path0) +Inquiry Data: S1YHNXAG804005 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :33C (91.40 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 1 Information +Enclosure Device ID: 32 +Slot Number: 2 +Drive's position: DiskGroup: 0, Span: 0, Arm: 1 +Enclosure position: 1 +Device Id: 2 +WWN: 5002538c00019b96 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221106000000 +Connected Port Number: 6(path0) +Inquiry Data: S1YHNYAG600061 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :33C (91.40 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 2 Information +Enclosure Device ID: 32 +Slot Number: 1 +Drive's position: DiskGroup: 0, Span: 0, Arm: 2 +Enclosure position: 1 +Device Id: 1 +WWN: 5002538c4002e707 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221100000000 +Connected Port Number: 0(path0) +Inquiry Data: S1YHNXAG803993 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :34C (93.20 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 3 Information +Enclosure Device ID: 32 +Slot Number: 3 +Drive's position: DiskGroup: 0, Span: 0, Arm: 3 +Enclosure position: 1 +Device Id: 3 +WWN: 5002538c4002e70f +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221102000000 +Connected Port Number: 2(path0) +Inquiry Data: S1YHNXAG804001 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :34C (93.20 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 4 Information +Enclosure Device ID: 32 +Slot Number: 5 +Drive's position: DiskGroup: 0, Span: 0, Arm: 4 +Enclosure position: 1 +Device Id: 5 +WWN: 5002538c4002e712 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221101000000 +Connected Port Number: 1(path0) +Inquiry Data: S1YHNXAG804004 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :34C (93.20 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 5 Information +Enclosure Device ID: 32 +Slot Number: 4 +Drive's position: DiskGroup: 0, Span: 0, Arm: 5 +Enclosure position: 1 +Device Id: 4 +WWN: 5002538c4002e6e9 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221105000000 +Connected Port Number: 5(path0) +Inquiry Data: S1YHNXAG803963 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :33C (91.40 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 6 Information +Enclosure Device ID: 32 +Slot Number: 6 +Drive's position: DiskGroup: 0, Span: 0, Arm: 6 +Enclosure position: 1 +Device Id: 6 +WWN: 5002538c4002da83 +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221107000000 +Connected Port Number: 7(path0) +Inquiry Data: S1YHNXAG801029 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :33C (91.40 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +PD: 7 Information +Enclosure Device ID: 32 +Slot Number: 7 +Drive's position: DiskGroup: 0, Span: 0, Arm: 7 +Enclosure position: 1 +Device Id: 7 +WWN: 5002538c4002dade +Sequence Number: 2 +Media Error Count: 0 +Other Error Count: 0 +Predictive Failure Count: 0 +Last Predictive Failure Event Seq Number: 0 +PD Type: SATA + +Raw Size: 894.252 GB [0x6fc81ab0 Sectors] +Non Coerced Size: 893.752 GB [0x6fb81ab0 Sectors] +Coerced Size: 893.75 GB [0x6fb80000 Sectors] +Sector Size: 512 +Logical Sector Size: 512 +Physical Sector Size: 512 +Firmware state: Online, Spun Up +Device Firmware Level: 003Q +Shield Counter: 0 +Successful diagnostics completion on : N/A +SAS Address(0): 0x4433221103000000 +Connected Port Number: 3(path0) +Inquiry Data: S1YHNXAG801120 SAMSUNG MZ7LM960HCHP-00003 GXT3003Q +FDE Capable: Not Capable +FDE Enable: Disable +Secured: Unsecured +Locked: Unlocked +Needs EKM Attention: No +Foreign State: None +Device Speed: 6.0Gb/s +Link Speed: 6.0Gb/s +Media Type: Solid State Device +Drive: Not Certified +Drive Temperature :34C (93.20 F) +PI Eligibility: No +Drive is formatted for PI information: No +PI: No PI +Drive's NCQ setting : N/A +Port-0 : +Port status: Active +Port's Linkspeed: 6.0Gb/s +Drive has flagged a S.M.A.R.T alert : No + + + + +Exit Code: 0x00
\ No newline at end of file |