-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(metric): Added HPE SmartStorage specific drive metrics
- Loading branch information
1 parent
551eeda
commit 06312b0
Showing
9 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,10 @@ | |
run: | ||
tests: true | ||
|
||
issues: | ||
exclude-dirs: | ||
- pkg/oem/ | ||
|
||
linters: | ||
enable-all: true | ||
disable: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package metrics | ||
|
||
import ( | ||
"log" | ||
|
||
"github.com/g-portal/redfish_exporter/pkg/oem/hpe" | ||
"github.com/stmcginnis/gofish/common" | ||
"github.com/stmcginnis/gofish/redfish" | ||
) | ||
|
||
// vendorSpecifics is a helper function to collect vendor specific metrics. | ||
func (m *Metrics) vendorSpecifics(system *redfish.ComputerSystem) { | ||
switch system.Manufacturer { | ||
case hpe.Manufacturer: | ||
//nolint: nestif | ||
if hpeStorage, err := hpe.GetSmartStorage(system); err == nil { | ||
if arrayControllers, err := hpeStorage.ArrayControllers(); err == nil { | ||
for _, controller := range arrayControllers { | ||
m.WithRedfishStorageHealthMetric(convertHealthStatus(hpeStorage.Status.Health, | ||
hpeStorage.Status.State == common.EnabledState), map[string]string{ | ||
"system_id": system.ID, | ||
"storage_id": controller.ID, | ||
}) | ||
|
||
if drives, err := controller.PhysicalDrives(); err == nil { | ||
for _, drive := range drives { | ||
m.WithRedfishDriveHealthMetric(convertHealthStatus(drive.Status.Health, | ||
drive.Status.State == common.EnabledState), map[string]string{ | ||
"system_id": system.ID, | ||
"storage_id": controller.ID, | ||
"drive_id": drive.ID, | ||
}) | ||
m.WithRedfishDriveCapacityMetric(float64(drive.CapacityMiB), map[string]string{ | ||
"system_id": system.ID, | ||
"storage_id": controller.ID, | ||
"drive_id": drive.ID, | ||
}) | ||
} | ||
} else { | ||
log.Printf("error getting drives: %s", err) | ||
} | ||
} | ||
} else { | ||
log.Printf("error getting array controllers: %s", err) | ||
} | ||
} else { | ||
log.Printf("error getting SmartStorage: %s", err) | ||
} | ||
default: | ||
// no vendor specific metrics to collect | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package hpe | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/stmcginnis/gofish/common" | ||
"io" | ||
) | ||
|
||
type ArrayController struct { | ||
common.Entity | ||
|
||
OdataContext string `json:"@odata.context"` | ||
OdataID string `json:"@odata.id"` | ||
OdataType string `json:"@odata.type"` | ||
AdapterType string `json:"AdapterType"` | ||
BackupPowerSourceStatus string `json:"BackupPowerSourceStatus"` | ||
CurrentOperatingMode string `json:"CurrentOperatingMode"` | ||
Description string `json:"Description"` | ||
EncryptionCryptoOfficerPasswordSet bool `json:"EncryptionCryptoOfficerPasswordSet"` | ||
EncryptionEnabled bool `json:"EncryptionEnabled"` | ||
EncryptionFwLocked bool `json:"EncryptionFwLocked"` | ||
EncryptionHasLockedVolumesMissingBootPassword bool `json:"EncryptionHasLockedVolumesMissingBootPassword"` | ||
EncryptionMixedVolumesEnabled bool `json:"EncryptionMixedVolumesEnabled"` | ||
EncryptionStandaloneModeEnabled bool `json:"EncryptionStandaloneModeEnabled"` | ||
ExternalPortCount int `json:"ExternalPortCount"` | ||
FirmwareVersion struct { | ||
Current struct { | ||
VersionString string `json:"VersionString"` | ||
} `json:"Current"` | ||
} `json:"FirmwareVersion"` | ||
HardwareRevision string `json:"HardwareRevision"` | ||
ID string `json:"Id"` | ||
InternalPortCount int `json:"InternalPortCount"` | ||
Location string `json:"Location"` | ||
LocationFormat string `json:"LocationFormat"` | ||
Model string `json:"Model"` | ||
Name string `json:"Name"` | ||
SerialNumber string `json:"SerialNumber"` | ||
Status common.Status `json:"Status"` | ||
Type string `json:"Type"` | ||
Links struct { | ||
LogicalDrives struct { | ||
Href string `json:"href"` | ||
} `json:"LogicalDrives"` | ||
PhysicalDrives struct { | ||
Href string `json:"href"` | ||
} `json:"PhysicalDrives"` | ||
StorageEnclosures struct { | ||
Href string `json:"href"` | ||
} `json:"StorageEnclosures"` | ||
UnconfiguredDrives struct { | ||
Href string `json:"href"` | ||
} `json:"UnconfiguredDrives"` | ||
Self struct { | ||
Href string `json:"href"` | ||
} `json:"self"` | ||
} `json:"links"` | ||
} | ||
|
||
func (s *ArrayController) PhysicalDrives() ([]*Drive, error) { | ||
result := make([]*Drive, 0) | ||
|
||
drives, err := s.diskDrivesList() | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting ArrayControllers: %w", err) | ||
} | ||
|
||
for _, member := range drives.Members { | ||
data, err := s.GetClient().Get(member.OdataID) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting ArrayController data: %w", err) | ||
} | ||
|
||
var drive *Drive | ||
jsonPayload, err := io.ReadAll(data.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("error reading SmartStorage data: %w", err) | ||
} | ||
|
||
err = json.Unmarshal(jsonPayload, &drive) | ||
if err != nil { | ||
return nil, fmt.Errorf("error unmarshalling SmartStorage data: %w", err) | ||
} | ||
|
||
drive.SetClient(s.GetClient()) | ||
|
||
result = append(result, drive) | ||
} | ||
|
||
return result, nil | ||
|
||
} | ||
|
||
func (s *ArrayController) diskDrivesList() (*DiskDrives, error) { | ||
var result *DiskDrives | ||
|
||
data, err := s.GetClient().Get(s.Links.PhysicalDrives.Href) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting physical drives: %w", err) | ||
} | ||
|
||
jsonPayload, err := io.ReadAll(data.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("error reading SmartStorage data: %w", err) | ||
} | ||
|
||
err = json.Unmarshal(jsonPayload, &result) | ||
if err != nil { | ||
return nil, fmt.Errorf("error unmarshalling SmartStorage data: %w", err) | ||
} | ||
|
||
result.SetClient(s.GetClient()) | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package hpe | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/stmcginnis/gofish/common" | ||
"io" | ||
) | ||
|
||
type ArrayControllers struct { | ||
common.Entity | ||
|
||
OdataContext string `json:"@odata.context"` | ||
OdataID string `json:"@odata.id"` | ||
OdataType string `json:"@odata.type"` | ||
Description string `json:"Description"` | ||
MemberType string `json:"MemberType"` | ||
Members []struct { | ||
OdataID string `json:"@odata.id"` | ||
} `json:"Members"` | ||
MembersOdataCount int `json:"Members@odata.count"` | ||
Name string `json:"Name"` | ||
Total int `json:"Total"` | ||
Type string `json:"Type"` | ||
Links struct { | ||
Member []struct { | ||
Href string `json:"href"` | ||
} `json:"Member"` | ||
Self struct { | ||
Href string `json:"href"` | ||
} `json:"self"` | ||
} `json:"links"` | ||
} | ||
|
||
func (s *SmartStorage) ArrayControllers() ([]*ArrayController, error) { | ||
result := make([]*ArrayController, 0) | ||
|
||
controllers, err := s.arrayControllerList() | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting ArrayControllers: %w", err) | ||
} | ||
|
||
for _, member := range controllers.Members { | ||
data, err := s.GetClient().Get(member.OdataID) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting ArrayController data: %w", err) | ||
} | ||
|
||
var controller *ArrayController | ||
jsonPayload, err := io.ReadAll(data.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("error reading SmartStorage data: %w", err) | ||
} | ||
|
||
err = json.Unmarshal(jsonPayload, &controller) | ||
if err != nil { | ||
return nil, fmt.Errorf("error unmarshalling SmartStorage data: %w", err) | ||
} | ||
|
||
controller.SetClient(s.GetClient()) | ||
|
||
result = append(result, controller) | ||
} | ||
|
||
return result, nil | ||
} | ||
|
||
func (s *SmartStorage) arrayControllerList() (*ArrayControllers, error) { | ||
var result *ArrayControllers | ||
|
||
data, err := s.GetClient().Get(s.Links.ArrayControllers.Href) | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting ArrayControllers: %w", err) | ||
} | ||
|
||
jsonPayload, err := io.ReadAll(data.Body) | ||
if err != nil { | ||
return nil, fmt.Errorf("error reading SmartStorage data: %w", err) | ||
} | ||
|
||
err = json.Unmarshal(jsonPayload, &result) | ||
if err != nil { | ||
return nil, fmt.Errorf("error unmarshalling SmartStorage data: %w", err) | ||
} | ||
|
||
result.SetClient(s.GetClient()) | ||
|
||
return result, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package hpe | ||
|
||
import "github.com/stmcginnis/gofish/common" | ||
|
||
type Drive struct { | ||
common.Entity | ||
|
||
OdataContext string `json:"@odata.context"` | ||
OdataID string `json:"@odata.id"` | ||
OdataType string `json:"@odata.type"` | ||
BlockSizeBytes int `json:"BlockSizeBytes"` | ||
CapacityGB int `json:"CapacityGB"` | ||
CapacityLogicalBlocks int64 `json:"CapacityLogicalBlocks"` | ||
CapacityMiB int `json:"CapacityMiB"` | ||
CarrierApplicationVersion string `json:"CarrierApplicationVersion"` | ||
CarrierAuthenticationStatus string `json:"CarrierAuthenticationStatus"` | ||
CurrentTemperatureCelsius int `json:"CurrentTemperatureCelsius"` | ||
Description string `json:"Description"` | ||
DiskDriveStatusReasons []string `json:"DiskDriveStatusReasons"` | ||
EncryptedDrive bool `json:"EncryptedDrive"` | ||
FirmwareVersion struct { | ||
Current struct { | ||
VersionString string `json:"VersionString"` | ||
} `json:"Current"` | ||
} `json:"FirmwareVersion"` | ||
ID string `json:"Id"` | ||
InterfaceSpeedMbps int `json:"InterfaceSpeedMbps"` | ||
InterfaceType string `json:"InterfaceType"` | ||
Location string `json:"Location"` | ||
LocationFormat string `json:"LocationFormat"` | ||
MaximumTemperatureCelsius int `json:"MaximumTemperatureCelsius"` | ||
MediaType string `json:"MediaType"` | ||
Model string `json:"Model"` | ||
Name string `json:"Name"` | ||
PowerOnHours interface{} `json:"PowerOnHours"` | ||
RotationalSpeedRpm int `json:"RotationalSpeedRpm"` | ||
SSDEnduranceUtilizationPercentage interface{} `json:"SSDEnduranceUtilizationPercentage"` | ||
SerialNumber string `json:"SerialNumber"` | ||
Status common.Status `json:"Status"` | ||
Type string `json:"Type"` | ||
Links struct { | ||
Self struct { | ||
Href string `json:"href"` | ||
} `json:"self"` | ||
} `json:"links"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package hpe | ||
|
||
import "github.com/stmcginnis/gofish/common" | ||
|
||
type DiskDrives struct { | ||
common.Entity | ||
|
||
OdataContext string `json:"@odata.context"` | ||
OdataID string `json:"@odata.id"` | ||
OdataType string `json:"@odata.type"` | ||
Description string `json:"Description"` | ||
MemberType string `json:"MemberType"` | ||
Members []struct { | ||
OdataID string `json:"@odata.id"` | ||
} `json:"Members"` | ||
MembersOdataCount int `json:"Members@odata.count"` | ||
Name string `json:"Name"` | ||
Total int `json:"Total"` | ||
Type string `json:"Type"` | ||
Links struct { | ||
Member []struct { | ||
Href string `json:"href"` | ||
} `json:"Member"` | ||
Self struct { | ||
Href string `json:"href"` | ||
} `json:"self"` | ||
} `json:"links"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package hpe | ||
|
||
const Manufacturer = "HPE" |
Oops, something went wrong.