Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support dell 7x0xd models #84

Merged
merged 5 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ log is based on the [Keep a CHANGELOG](http://keepachangelog.com/) project.
- Firmware gathering endpoint update and add device info to other HP models [#55](https://github.com/Comcast/fishymetrics/issues/55)
- C220 drive metrics on hosts with fw < 4.0, psu metrics result and label values [#57](https://github.com/Comcast/fishymetrics/issues/57)
- Chassis ComputerSystems field is handled improperly [#68](https://github.com/Comcast/fishymetrics/issues/68)
- Power and Thermal metrics collection for Dell R7xxXD server models [#77](https://github.com/Comcast/fishymetrics/issues/77)
- Firmware metrics and request headers update for Dell iDRAC9 with FW ver.3.xx and 4.xx [#77](https://github.com/Comcast/fishymetrics/issues/77)

## Updated

Expand Down
2 changes: 2 additions & 0 deletions common/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ func BuildRequest(uri, host string) *retryablehttp.Request {

req, _ := retryablehttp.NewRequest(http.MethodGet, uri, nil)
req.SetBasicAuth(user, password)
// this header is required by iDRAC9 with FW ver. 3.xx and 4.xx
req.Header.Add("Accept", "application/json")

return req
}
Expand Down
25 changes: 13 additions & 12 deletions exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ func NewExporter(ctx context.Context, target, uri, profile, model string, exclud
return nil, err
}
exp.biosVersion = sysResp.BiosVersion
exp.ChassisSerialNumber = sysResp.SerialNumber
exp.ChassisSerialNumber = strings.TrimRight(sysResp.SerialNumber, " ")
exp.systemHostname = sysResp.SystemHostname

// call /redfish/v1/Systems/XXXXX/ for memory summary and smart storage batteries
Expand Down Expand Up @@ -364,20 +364,20 @@ func NewExporter(ctx context.Context, target, uri, profile, model string, exclud
zap.Any("trace_id", ctx.Value("traceID")))

// Call /redfish/v1/Managers/XXXX/UpdateService/FirmwareInventory/ for firmware inventory
firmwareInventoryEndpoints, err := getMemberUrls(exp.url+uri+"/UpdateService/FirmwareInventory/", target, retryClient)
firmwareInventoryEndpoints, err := getFirmwareEndpoints(exp.url+uri+"/UpdateService/FirmwareInventory/", target, retryClient)
if err != nil {
// Try the iLo 4 firmware inventory endpoint
// Use the collected sysEndpoints.systems to build url(s)
if len(sysEndpoints.systems) > 0 {
// call /redfish/v1/Systems/XXXX/FirmwareInventory/
for _, system := range sysEndpoints.systems {
firmwareInventoryEndpoints = append(firmwareInventoryEndpoints, system+"FirmwareInventory/")
}
// Ensure we have at least one firmware inventory endpoint
if len(firmwareInventoryEndpoints) == 0 {
log.Error("error when getting FirmwareInventory url", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
return nil, err
url := system + "FirmwareInventory/"
tasks = append(tasks,
pool.NewTask(common.Fetch(exp.url+url, target, profile, retryClient), exp.url+url, handle(&exp, FIRMWAREINVENTORY)))
}
} else {
log.Error("error when getting Firmware endpoints", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
return nil, err
}
}

Expand Down Expand Up @@ -426,12 +426,13 @@ func NewExporter(ctx context.Context, target, uri, profile, model string, exclud
}

// Firmware Inventory
for _, url := range firmwareInventoryEndpoints {
// this list can potentially be large and cause scrapes to take a long time please
for _, fwEp := range firmwareInventoryEndpoints.Members {
// this list can potentially be large and cause scrapes to take a long time
// see the '--collector.firmware.modules-exclude' config in the README for more information
if reg, ok := excludes["firmware"]; ok {
if !reg.(*regexp.Regexp).MatchString(url) {
tasks = append(tasks, pool.NewTask(common.Fetch(exp.url+url, target, profile, retryClient), exp.url+url, handle(&exp, FIRMWAREINVENTORY)))
if !reg.(*regexp.Regexp).MatchString(fwEp.URL) {
tasks = append(tasks,
pool.NewTask(common.Fetch(exp.url+fwEp.URL, target, profile, retryClient), exp.url+fwEp.URL, handle(&exp, FIRMWAREINVENTORY)))
}
}
}
Expand Down
98 changes: 75 additions & 23 deletions exporter/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,31 +111,50 @@ func getSystemEndpoints(chassisUrls []string, host string, client *retryablehttp
}
}

for _, power := range chas.Links.Power.LinksURLSlice {
url := appendSlash(power)
if chas.PowerAlt.URL != "" {
url := appendSlash(chas.PowerAlt.URL)
if checkUnique(sysEnd.power, url) {
sysEnd.power = append(sysEnd.power, url)
}
}

for _, power := range chas.LinksLower.Power.LinksURLSlice {
url := appendSlash(power)
if checkUnique(sysEnd.power, url) {
sysEnd.power = append(sysEnd.power, url)
if chas.ThermalAlt.URL != "" {
url := appendSlash(chas.ThermalAlt.URL)
if checkUnique(sysEnd.thermal, url) {
sysEnd.thermal = append(sysEnd.thermal, url)
}
}

for _, thermal := range chas.Links.Thermal.LinksURLSlice {
url := appendSlash(thermal)
if checkUnique(sysEnd.thermal, url) {
sysEnd.thermal = append(sysEnd.thermal, url)
// if power and thermal endpoints are not found in main level, check the nested results in Links/links
if len(sysEnd.power) == 0 {
for _, power := range chas.Links.Power.LinksURLSlice {
url := appendSlash(power)
if checkUnique(sysEnd.power, url) {
sysEnd.power = append(sysEnd.power, url)
}
}

for _, power := range chas.LinksLower.Power.LinksURLSlice {
url := appendSlash(power)
if checkUnique(sysEnd.power, url) {
sysEnd.power = append(sysEnd.power, url)
}
}
}

for _, thermal := range chas.LinksLower.Thermal.LinksURLSlice {
url := appendSlash(thermal)
if checkUnique(sysEnd.thermal, url) {
sysEnd.thermal = append(sysEnd.thermal, url)
if len(sysEnd.thermal) == 0 {
for _, thermal := range chas.Links.Thermal.LinksURLSlice {
url := appendSlash(thermal)
if checkUnique(sysEnd.thermal, url) {
sysEnd.thermal = append(sysEnd.thermal, url)
}
}

for _, thermal := range chas.LinksLower.Thermal.LinksURLSlice {
url := appendSlash(thermal)
if checkUnique(sysEnd.thermal, url) {
sysEnd.thermal = append(sysEnd.thermal, url)
}
}
}

Expand Down Expand Up @@ -188,15 +207,6 @@ func getSystemEndpoints(chassisUrls []string, host string, client *retryablehttp
}
}

// check last resort places for power and thermal endpoints if none were found
if len(sysEnd.power) == 0 && chas.PowerAlt.URL != "" {
sysEnd.power = append(sysEnd.power, appendSlash(chas.PowerAlt.URL))
}

if len(sysEnd.thermal) == 0 && chas.ThermalAlt.URL != "" {
sysEnd.thermal = append(sysEnd.thermal, appendSlash(chas.ThermalAlt.URL))
}

return sysEnd, nil
}

Expand Down Expand Up @@ -431,6 +441,48 @@ func getAllDriveEndpoints(ctx context.Context, fqdn, initialUrl, host string, cl
return driveEndpoints, nil
}

func getFirmwareEndpoints(url, host string, client *retryablehttp.Client) (oem.Collection, error) {
var fwEpUrls oem.Collection
var resp *http.Response
var err error
retryCount := 0
req := common.BuildRequest(url, host)

resp, err = common.DoRequest(client, req)
if err != nil {
return fwEpUrls, err
}
defer resp.Body.Close()
if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) {
if resp.StatusCode == http.StatusNotFound {
for retryCount < 1 && resp.StatusCode == http.StatusNotFound {
time.Sleep(client.RetryWaitMin)
resp, err = common.DoRequest(client, req)
retryCount = retryCount + 1
}
if err != nil {
return fwEpUrls, err
} else if !(resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices) {
return fwEpUrls, fmt.Errorf("HTTP status %d", resp.StatusCode)
}
} else {
return fwEpUrls, fmt.Errorf("HTTP status %d", resp.StatusCode)
}
}

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

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

return fwEpUrls, nil
}

func getProcessorEndpoints(url, host string, client *retryablehttp.Client) (oem.Collection, error) {
var processors oem.Collection
var resp *http.Response
Expand Down
Loading