Skip to content

Commit

Permalink
Merge pull request #35 from Comcast/add_proliant_xl420g9
Browse files Browse the repository at this point in the history
Add proliant xl420
  • Loading branch information
ibrahimkk-moideen authored Mar 8, 2024
2 parents 7fcb4ef + 3152ed9 commit 3f9cc56
Show file tree
Hide file tree
Showing 16 changed files with 1,054 additions and 51 deletions.
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ log is based on the [Keep a CHANGELOG](http://keepachangelog.com/) project.
- Add ability to reference different vault paths for credential retrieval [#25](https://github.com/Comcast/fishymetrics/issues/25)
- Added HPE DL380 Gen10 support [#17](https://github.com/Comcast/fishymetrics/issues/17)
- Enhanced drive metrics collection for DL380 model servers to include NVME, Storage Disk Drives, and Logical Drives [#17](https://github.com/Comcast/fishymetrics/issues/17)
- add ability to send logs directly to elasticsearch endpoints [#10](https://github.com/Comcast/fishymetrics/issues/10)
- Add ability to send logs directly to elasticsearch endpoints [#10](https://github.com/Comcast/fishymetrics/issues/10)
- Add HPE Proliant DL560 Gen9 support [#23](https://github.com/Comcast/fishymetrics/issues/23)
- Add HPE Proliant XL420 Support [#33](https://github.com/Comcast/fishymetrics/issues/33)

## Fixed
- Cisco UCS C220 - add additional edge cases when collecting memory metrics [#2](https://github.com/Comcast/fishymetrics/issues/2)

## Updated
- Enhanced drive metrics collection for HPE DL360 model servers to include NVME, Storage Disk Drives, and Logical Drives. [#31](https://github.com/Comcast/fishymetrics/issues/31)
- removed references to internal URLs/FQDNs to opensource the project
- Removed references to internal URLs/FQDNs to opensource the project
- Cisco S3260M5 module to support FW Ver 4.2(xx) [#18](https://github.com/Comcast/fishymetrics/issues/18)
- HP DL360 module to support responses from iLO4 [#34](https://github.com/Comcast/fishymetrics/issues/34)

## [0.7.1]

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Current device models supported
- HP DL360
- HP DL560
- HP DL20
- HP XL420
- Cisco UCS C220 M5
- Cisco UCS S3260 M4
- Cisco UCS S3260 M5
Expand Down Expand Up @@ -142,7 +143,7 @@ comcast/fishymetrics:latest
## Prometheus Configuration
The fishymetrics exporter needs to be passed the address as a parameter, this can be
done with relabelling. available module options `["moonshot", "dl360", "dl20", "dl380", "dl560", "c220", "s3260m4", "s3260m5"]`
done with relabelling. available module options `["moonshot", "dl360", "dl20", "dl380", "dl560", "xl420", "c220", "s3260m4", "s3260m5"]`
Example config:
```YAML
Expand Down
5 changes: 4 additions & 1 deletion cmd/fishymetrics/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/comcast/fishymetrics/hpe/dl380"
"github.com/comcast/fishymetrics/hpe/dl560"
"github.com/comcast/fishymetrics/hpe/moonshot"
"github.com/comcast/fishymetrics/hpe/xl420"
"github.com/comcast/fishymetrics/logger"
"github.com/comcast/fishymetrics/middleware/muxprom"
fishy_vault "github.com/comcast/fishymetrics/vault"
Expand Down Expand Up @@ -157,6 +158,8 @@ func handler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
exporter = dl560.NewExporter(r.Context(), target, uri, credProf)
case "dl20":
exporter = dl20.NewExporter(r.Context(), target, uri, credProf)
case "xl420":
exporter = xl420.NewExporter(r.Context(), target, uri, credProf)
case "c220":
exporter, err = c220.NewExporter(r.Context(), target, uri, credProf)
case "s3260m4":
Expand All @@ -165,7 +168,7 @@ func handler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
exporter, err = s3260m5.NewExporter(r.Context(), target, uri, credProf)
default:
log.Error("'module' parameter does not match available options", zap.String("module", moduleName), zap.String("target", target), zap.Any("trace_id", r.Context().Value("traceID")))
http.Error(w, "'module' parameter does not match available options: [moonshot, dl360, dl380, dl560, dl20, c220, s3260m4, s3260m5]", http.StatusBadRequest)
http.Error(w, "'module' parameter does not match available options: [moonshot, dl360, dl380, dl560, dl20, xl420, c220, s3260m4, s3260m5]", http.StatusBadRequest)
return
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/fishymetrics/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ const indexTmpl string = `<html>
<option vaule="moonshot">moonshot</option>
<option vaule="dl380">dl380</option>
<option vaule="dl360">dl360</option>
<option vaule="dl360">dl560</option>
<option vaule="dl560">dl560</option>
<option vaule="dl20">dl20</option>
<option vaule="xl420">xl420</option>
<option vaule="c220">c220</option>
<option vaule="s3260m4">s3260m4</option>
<option vaule="s3260m5">s3260m5</option>
Expand Down
17 changes: 14 additions & 3 deletions hpe/dl360/drive.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,28 @@ type GenericDrive struct {
Members []struct {
URL string `json:"@odata.id"`
} `json:"Members,omitempty"`
Links struct {
Links *struct {
Drives []struct {
URL string `json:"@odata.id"`
} `json:"Drives,omitempty"`
LogicalDrives struct {
LogicalDrives *struct {
URL string `json:"@odata.id"`
} `json:"LogicalDrives,omitempty"`
PhysicalDrives struct {
PhysicalDrives *struct {
URL string `json:"@odata.id"`
} `json:"PhysicalDrives,omitempty"`
} `json:"Links,omitempty"`
Link *struct {
Drives []struct {
URL string `json:"href"`
} `json:"Drives,omitempty"`
LogicalDrives *struct {
URL string `json:"href"`
} `json:"LogicalDrives,omitempty"`
PhysicalDrives *struct {
URL string `json:"href"`
} `json:"PhysicalDrives,omitempty"`
} `json:"links,omitempty"`
MembersCount int `json:"[email protected],omitempty"`
}

Expand Down
121 changes: 90 additions & 31 deletions hpe/dl360/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,34 +154,70 @@ func NewExporter(ctx context.Context, target, uri, profile string) *Exporter {
continue
}

// If LogicalDrives is present, parse logical drive endpoint until all urls are found
if newOutput.Links.LogicalDrives.URL != "" {
logicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Links.LogicalDrives.URL, target, retryClient)
if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Links.LogicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
if newOutput.Links != nil {
// If LogicalDrives is present, parse logical drive endpoint until all urls are found
if newOutput.Links.LogicalDrives != nil && newOutput.Links.LogicalDrives.URL != "" {
logicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Links.LogicalDrives.URL, target, retryClient)
if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Links.LogicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
}

if logicalDriveOutput.MembersCount > 0 {
// loop through each Member in the "LogicalDrive" field
for _, member := range logicalDriveOutput.Members {
// append each URL in the Members array to the logicalDriveURLs array.
logicalDriveURLs = append(logicalDriveURLs, member.URL)
}
}
}

if logicalDriveOutput.MembersCount > 0 {
// loop through each Member in the "LogicalDrive" field
for _, member := range logicalDriveOutput.Members {
// append each URL in the Members array to the logicalDriveURLs array.
logicalDriveURLs = append(logicalDriveURLs, member.URL)
// If PhysicalDrives is present, parse physical drive endpoint until all urls are found
if newOutput.Links.PhysicalDrives != nil && newOutput.Links.PhysicalDrives.URL != "" {
physicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Links.PhysicalDrives.URL, target, retryClient)
if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Links.PhysicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
}

if physicalDriveOutput.MembersCount > 0 {
for _, member := range physicalDriveOutput.Members {
physicalDriveURLs = append(physicalDriveURLs, member.URL)
}
}
}
}

// If PhysicalDrives is present, parse physical drive endpoint until all urls are found
if newOutput.Links.PhysicalDrives.URL != "" {
physicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Links.PhysicalDrives.URL, target, retryClient)
if newOutput.Link != nil {
// If LogicalDrives is present, parse logical drive endpoint until all urls are found
if newOutput.Link.LogicalDrives != nil && newOutput.Link.LogicalDrives.URL != "" {
logicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Link.LogicalDrives.URL, target, retryClient)
if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Link.LogicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
}

if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Links.PhysicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
if logicalDriveOutput.MembersCount > 0 {
// loop through each Member in the "LogicalDrive" field
for _, member := range logicalDriveOutput.Members {
// append each URL in the Members array to the logicalDriveURLs array.
logicalDriveURLs = append(logicalDriveURLs, member.URL)
}
}
}
if physicalDriveOutput.MembersCount > 0 {
for _, member := range physicalDriveOutput.Members {
physicalDriveURLs = append(physicalDriveURLs, member.URL)

// If PhysicalDrives is present, parse physical drive endpoint until all urls are found
if newOutput.Link.PhysicalDrives != nil && newOutput.Link.PhysicalDrives.URL != "" {
physicalDriveOutput, err := getDriveEndpoint(fqdn.String()+newOutput.Link.PhysicalDrives.URL, target, retryClient)
if err != nil {
log.Error("api call "+fqdn.String()+newOutput.Links.PhysicalDrives.URL+" failed - ", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
continue
}

if physicalDriveOutput.MembersCount > 0 {
for _, member := range physicalDriveOutput.Members {
physicalDriveURLs = append(physicalDriveURLs, member.URL)
}
}
}
}
Expand All @@ -196,10 +232,12 @@ func NewExporter(ctx context.Context, target, uri, profile string) *Exporter {
}

// parse through "Links" to find "Drives" array
if len(chassisOutput.Links.Drives) > 0 {
// loop through drives array and append each odata.id url to nvmeDriveURLs list
for _, drive := range chassisOutput.Links.Drives {
nvmeDriveURLs = append(nvmeDriveURLs, drive.URL)
if chassisOutput.Links != nil {
if len(chassisOutput.Links.Drives) > 0 {
// loop through drives array and append each odata.id url to nvmeDriveURLs list
for _, drive := range chassisOutput.Links.Drives {
nvmeDriveURLs = append(nvmeDriveURLs, drive.URL)
}
}
}

Expand Down Expand Up @@ -426,20 +464,33 @@ func (e *Exporter) exportPowerMetrics(body []byte) error {
return fmt.Errorf("Error Unmarshalling DL360 PowerMetrics - " + err.Error())
}

for _, pc := range pm.PowerControl {
(*dlPower)["supplyTotalConsumed"].WithLabelValues(pc.MemberID).Set(float64(pc.PowerConsumedWatts))
(*dlPower)["supplyTotalCapacity"].WithLabelValues(pc.MemberID).Set(float64(pc.PowerCapacityWatts))
for idx, pc := range pm.PowerControl {
if pc.MemberID != "" {
(*dlPower)["supplyTotalConsumed"].WithLabelValues(pc.MemberID).Set(float64(pc.PowerConsumedWatts))
(*dlPower)["supplyTotalCapacity"].WithLabelValues(pc.MemberID).Set(float64(pc.PowerCapacityWatts))
} else {
(*dlPower)["supplyTotalConsumed"].WithLabelValues(strconv.Itoa(idx)).Set(float64(pc.PowerConsumedWatts))
(*dlPower)["supplyTotalCapacity"].WithLabelValues(strconv.Itoa(idx)).Set(float64(pc.PowerCapacityWatts))
}
}

for _, ps := range pm.PowerSupplies {
if ps.Status.State == "Enabled" {
(*dlPower)["supplyOutput"].WithLabelValues(ps.MemberID, ps.SparePartNumber).Set(float64(ps.LastPowerOutputWatts))
if ps.MemberID != "" {
(*dlPower)["supplyOutput"].WithLabelValues(ps.MemberID, ps.SparePartNumber).Set(float64(ps.LastPowerOutputWatts))
} else {
(*dlPower)["supplyOutput"].WithLabelValues(strconv.Itoa(ps.Oem.Hp.BayNumber), ps.SparePartNumber).Set(float64(ps.LastPowerOutputWatts))
}
if ps.Status.Health == "OK" {
state = OK
} else {
state = BAD
}
(*dlPower)["supplyStatus"].WithLabelValues(ps.MemberID, ps.SparePartNumber).Set(state)
if ps.MemberID != "" {
(*dlPower)["supplyStatus"].WithLabelValues(ps.MemberID, ps.SparePartNumber).Set(state)
} else {
(*dlPower)["supplyStatus"].WithLabelValues(strconv.Itoa(ps.Oem.Hp.BayNumber), ps.SparePartNumber).Set(state)
}
}
}

Expand All @@ -461,13 +512,21 @@ func (e *Exporter) exportThermalMetrics(body []byte) error {
for _, fan := range tm.Fans {
// Check fan status and convert string to numeric values
if fan.Status.State == "Enabled" {
(*dlThermal)["fanSpeed"].WithLabelValues(fan.Name).Set(float64(fan.Reading))
if fan.FanName != "" {
(*dlThermal)["fanSpeed"].WithLabelValues(fan.FanName).Set(float64(fan.CurrentReading))
} else {
(*dlThermal)["fanSpeed"].WithLabelValues(fan.Name).Set(float64(fan.Reading))
}
if fan.Status.Health == "OK" {
state = OK
} else {
state = BAD
}
(*dlThermal)["fanStatus"].WithLabelValues(fan.Name).Set(state)
if fan.FanName != "" {
(*dlThermal)["fanStatus"].WithLabelValues(fan.FanName).Set(state)
} else {
(*dlThermal)["fanStatus"].WithLabelValues(fan.Name).Set(state)
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions hpe/dl360/power.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Comcast Cable Communications Management, LLC
* Copyright 2024 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -62,7 +62,8 @@ type PowerSupply struct {

// OemPower is the top level json object for historical data for wattage
type OemPower struct {
Hpe Hpe `json:"Hpe"`
Hpe Hpe `json:"Hpe,omitempty"`
Hp Hpe `json:"Hp,omitempty"`
}

// Hpe contains metadata on power supply product info
Expand Down
14 changes: 8 additions & 6 deletions hpe/dl360/thermal.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Comcast Cable Communications Management, LLC
* Copyright 2024 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,11 +28,13 @@ type ThermalMetrics struct {

// Fan is the json object for a DL360 fan module
type Fan struct {
MemberID string `json:"MemberId"`
Name string `json:"Name"`
Reading int `json:"Reading"`
ReadingUnits string `json:"ReadingUnits"`
Status StatusThermal `json:"Status"`
MemberID string `json:"MemberId"`
Name string `json:"Name"`
FanName string `json:"FanName"`
Reading int `json:"Reading"`
CurrentReading int `json:"CurrentReading"`
ReadingUnits string `json:"ReadingUnits"`
Status StatusThermal `json:"Status"`
}

// StatusThermal is the variable to determine if a fan or temperature sensor module is OK or not
Expand Down
8 changes: 4 additions & 4 deletions hpe/dl560/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net"
"net/http"
"net/url"
Expand All @@ -46,7 +46,7 @@ const (
THERMAL = "ThermalMetrics"
// POWER represents the power metric endpoint
POWER = "PowerMetrics"
// DRIVE represents the logical drive metric endpoints
// DRIVE represents the physical drive metric endpoints
DRIVE = "PhysicalDriveMetrics"
// LOGICALDRIVE represents the Logical drive metric endpoint
LOGICALDRIVE = "LogicalDriveMetrics"
Expand Down Expand Up @@ -478,14 +478,14 @@ func getDriveEndpoints(url, host string, client *retryablehttp.Client) (GenericD
}
}

body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return drives, fmt.Errorf("Error reading Response Body - " + err.Error())
}

err = json.Unmarshal(body, &drives)
if err != nil {
return drives, fmt.Errorf("Error Unmarshalling S3260M5 Memory Collection struct - " + err.Error())
return drives, fmt.Errorf("Error Unmarshalling DL560 Drive Collection struct - " + err.Error())
}

return drives, nil
Expand Down
Loading

0 comments on commit 3f9cc56

Please sign in to comment.