Skip to content

Commit

Permalink
fix(inputs.redfish): Resolve iLO4 fan data (#14659)
Browse files Browse the repository at this point in the history
(cherry picked from commit d8dc29b)
  • Loading branch information
powersj committed Feb 20, 2024
1 parent b85a9ac commit 820c254
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 0 deletions.
5 changes: 5 additions & 0 deletions plugins/inputs/redfish/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## Available sets are: "chassis.location" and "chassis"
# include_tag_sets = ["chassis.location"]

## Workarounds
## Defines workarounds for certain hardware vendors. Choose from:
## * ilo4-thermal - Do not pass 0Data-Version header to Thermal endpoint
# workarounds = []

## Amount of time allowed to complete the HTTP request
# timeout = "5s"

Expand Down
23 changes: 23 additions & 0 deletions plugins/inputs/redfish/redfish.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"net/http"
"net/url"
"path"
"slices"
"strings"
"time"

"github.com/influxdata/telegraf"
Expand All @@ -28,6 +30,7 @@ type Redfish struct {
ComputerSystemID string `toml:"computer_system_id"`
IncludeMetrics []string `toml:"include_metrics"`
IncludeTagSets []string `toml:"include_tag_sets"`
Workarounds []string `toml:"workarounds"`
Timeout config.Duration `toml:"timeout"`

tagSet map[string]bool
Expand Down Expand Up @@ -111,6 +114,8 @@ type Thermal struct {
Fans []struct {
Name string
MemberID string
FanName string
CurrentReading *int64
Reading *int64
ReadingUnits *string
UpperThresholdCritical *int64
Expand Down Expand Up @@ -175,6 +180,13 @@ func (r *Redfish) Init() error {
}
}

for _, workaround := range r.Workarounds {
switch workaround {
case "ilo4-thermal":
default:
return fmt.Errorf("unknown workaround requested: %s", workaround)
}
}
r.tagSet = make(map[string]bool, len(r.IncludeTagSets))
for _, setLabel := range r.IncludeTagSets {
r.tagSet[setLabel] = true
Expand Down Expand Up @@ -212,6 +224,12 @@ func (r *Redfish) getData(address string, payload interface{}) error {
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("OData-Version", "4.0")

// workaround for iLO4 thermal data
if slices.Contains(r.Workarounds, "ilo4-thermal") && strings.Contains(address, "/Thermal") {
req.Header.Del("OData-Version")
}

resp, err := r.client.Do(req)
if err != nil {
return err
Expand Down Expand Up @@ -364,6 +382,9 @@ func (r *Redfish) gatherThermal(acc telegraf.Accumulator, address string, system
tags["member_id"] = j.MemberID
tags["address"] = address
tags["name"] = j.Name
if j.FanName != "" {
tags["name"] = j.FanName
}
tags["source"] = system.Hostname
tags["state"] = j.Status.State
tags["health"] = j.Status.Health
Expand All @@ -383,6 +404,8 @@ func (r *Redfish) gatherThermal(acc telegraf.Accumulator, address string, system
fields["lower_threshold_critical"] = j.LowerThresholdCritical
fields["lower_threshold_fatal"] = j.LowerThresholdFatal
fields["reading_rpm"] = j.Reading
} else if j.CurrentReading != nil {
fields["reading_percent"] = j.CurrentReading
} else {
fields["reading_percent"] = j.Reading
}
Expand Down
97 changes: 97 additions & 0 deletions plugins/inputs/redfish/redfish_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,103 @@ func TestHPApis(t *testing.T) {
testutil.IgnoreTime())
}

func TestHPilo4Apis(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !checkAuth(r, "test", "test") {
http.Error(w, "Unauthorized.", 401)
return
}

switch r.URL.Path {
case "/redfish/v1/Chassis/1/Thermal":
http.ServeFile(w, r, "testdata/hp_thermal_ilo4.json")
case "/redfish/v1/Chassis/1/Power":
http.ServeFile(w, r, "testdata/hp_power.json")
case "/redfish/v1/Systems/1":
http.ServeFile(w, r, "testdata/hp_systems.json")
case "/redfish/v1/Chassis/1/":
http.ServeFile(w, r, "testdata/hp_chassis.json")
default:
w.WriteHeader(http.StatusNotFound)
}
}))

defer ts.Close()

u, err := url.Parse(ts.URL)
require.NoError(t, err)
address, _, err := net.SplitHostPort(u.Host)
require.NoError(t, err)

expectedMetricsHp := []telegraf.Metric{
testutil.MustMetric(
"redfish_thermal_temperatures",
map[string]string{
"name": "01-Inlet Ambient",
"member_id": "0",
"source": "tpa-hostname",
"address": address,
"health": "OK",
"state": "Enabled",
},
map[string]interface{}{
"reading_celsius": 19.0,
"upper_threshold_critical": 42.0,
"upper_threshold_fatal": 47.0,
},
time.Unix(0, 0),
),
testutil.MustMetric(
"redfish_thermal_temperatures",
map[string]string{
"name": "44-P/S 2 Zone",
"member_id": "42",
"source": "tpa-hostname",
"address": address,
"health": "OK",
"state": "Enabled",
},
map[string]interface{}{
"reading_celsius": 34.0,
"upper_threshold_critical": 75.0,
"upper_threshold_fatal": 80.0,
},
time.Unix(0, 0),
),
testutil.MustMetric(
"redfish_thermal_fans",
map[string]string{
"address": address,
"health": "OK",
"member_id": "",
"name": "Fan 1",
"source": "tpa-hostname",
"state": "Enabled",
},
map[string]interface{}{
"reading_percent": 17,
},
time.Unix(0, 0),
),
}

hpPlugin := &Redfish{
Address: ts.URL,
Username: "test",
Password: "test",
ComputerSystemID: "1",
IncludeMetrics: []string{"thermal"},
}
require.NoError(t, hpPlugin.Init())
var hpAcc testutil.Accumulator

err = hpPlugin.Gather(&hpAcc)
require.NoError(t, err)
require.True(t, hpAcc.HasMeasurement("redfish_thermal_temperatures"))
testutil.RequireMetricsEqual(t, expectedMetricsHp, hpAcc.GetTelegrafMetrics(),
testutil.IgnoreTime())
}

func checkAuth(r *http.Request, username, password string) bool {
user, pass, ok := r.BasicAuth()
if !ok {
Expand Down
5 changes: 5 additions & 0 deletions plugins/inputs/redfish/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
## Available sets are: "chassis.location" and "chassis"
# include_tag_sets = ["chassis.location"]

## Workarounds
## Defines workarounds for certain hardware vendors. Choose from:
## * ilo4-thermal - Do not pass 0Data-Version header to Thermal endpoint
# workarounds = []

## Amount of time allowed to complete the HTTP request
# timeout = "5s"

Expand Down
72 changes: 72 additions & 0 deletions plugins/inputs/redfish/testdata/hp_thermal_ilo4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"@odata.context": "/redfish/v1/$metadata#Thermal.Thermal",
"@odata.etag": "W/\"14E8662D\"",
"@odata.id": "/redfish/v1/Chassis/1/Thermal",
"@odata.type": "#Thermal.v1_1_0.Thermal",
"Id": "Thermal",
"Fans": [
{
"CurrentReading": 17,
"FanName": "Fan 1",
"Oem": {
"Hp": {
"@odata.type": "#HpServerFan.1.0.0.HpServerFan",
"Location": "System",
"Type": "HpServerFan.1.0.0"
}
},
"Status": {
"Health": "OK",
"State": "Enabled"
},
"Units": "Percent"
}
],
"Name": "Thermal",
"Temperatures": [
{
"@odata.id": "/redfish/v1/Chassis/1/Thermal#Temperatures/0",
"MemberId": "0",
"Name": "01-Inlet Ambient",
"Oem": {
"Hpe": {
"@odata.context": "/redfish/v1/$metadata#HpeSeaOfSensors.HpeSeaOfSensors",
"@odata.type": "#HpeSeaOfSensors.v2_0_0.HpeSeaOfSensors",
"LocationXmm": 15,
"LocationYmm": 0
}
},
"PhysicalContext": "Intake",
"ReadingCelsius": 19,
"SensorNumber": 1,
"Status": {
"Health": "OK",
"State": "Enabled"
},
"UpperThresholdCritical": 42,
"UpperThresholdFatal": 47
},
{
"@odata.id": "/redfish/v1/Chassis/1/Thermal#Temperatures/42",
"MemberId": "42",
"Name": "44-P/S 2 Zone",
"Oem": {
"Hpe": {
"@odata.context": "/redfish/v1/$metadata#HpeSeaOfSensors.HpeSeaOfSensors",
"@odata.type": "#HpeSeaOfSensors.v2_0_0.HpeSeaOfSensors",
"LocationXmm": 4,
"LocationYmm": 7
}
},
"PhysicalContext": "PowerSupply",
"ReadingCelsius": 34,
"SensorNumber": 43,
"Status": {
"Health": "OK",
"State": "Enabled"
},
"UpperThresholdCritical": 75,
"UpperThresholdFatal": 80
}
]
}

0 comments on commit 820c254

Please sign in to comment.