Skip to content

Commit

Permalink
updates to storage controller and memory metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
ibrahimkk-moideen committed Jun 5, 2024
1 parent 8b8651a commit 119e601
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 24 deletions.
22 changes: 18 additions & 4 deletions exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ type SystemEndpoints struct {
}

type DriveEndpoints struct {
logicalDriveURLs []string
physicalDriveURLs []string
arrayControllerURLs []string
logicalDriveURLs []string
physicalDriveURLs []string
}

type Excludes map[string]interface{}
Expand Down Expand Up @@ -305,11 +306,24 @@ func NewExporter(ctx context.Context, target, uri, profile, model string, exclud
}
}

log.Debug("drive endpoints response", zap.Strings("logical_drive_endpoints", driveEndpointsResp.logicalDriveURLs),
if len(sysEndpoints.storageController) == 0 && ss == "" {
driveEndpointsResp, err = getAllDriveEndpoints(ctx, exp.url, exp.url+sysEndpoints.systems[0]+"Storage/", target, retryClient)
if err != nil {
log.Error("error when getting drive endpoints", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
return nil, err
}
}

log.Debug("drive endpoints response", zap.Strings("array_controller_endpoints", driveEndpointsResp.arrayControllerURLs),
zap.Strings("logical_drive_endpoints", driveEndpointsResp.logicalDriveURLs),
zap.Strings("physical_drive_endpoints", driveEndpointsResp.physicalDriveURLs),
zap.Any("trace_id", ctx.Value("traceID")))

// Loop through logicalDriveURLs, physicalDriveURLs, and nvmeDriveURLs and append each URL to the tasks pool
// Loop through arrayControllerURLs, logicalDriveURLs, physicalDriveURLs, and nvmeDriveURLs and append each URL to the tasks pool
for _, url := range driveEndpointsResp.arrayControllerURLs {
tasks = append(tasks, pool.NewTask(common.Fetch(exp.url+url, target, profile, retryClient), exp.url+url, handle(&exp, STORAGE_CONTROLLER)))
}

for _, url := range driveEndpointsResp.logicalDriveURLs {
tasks = append(tasks, pool.NewTask(common.Fetch(exp.url+url, target, profile, retryClient), exp.url+url, handle(&exp, LOGICALDRIVE)))
}
Expand Down
36 changes: 34 additions & 2 deletions exporter/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,22 @@ func (e *Exporter) exportLogicalDriveMetrics(body []byte) error {
var state float64
var dllogical oem.LogicalDriveMetrics
var dllogicaldrive = (*e.DeviceMetrics)["logicalDriveMetrics"]
var ldName string
var raidType string
var volIdentifier string
err := json.Unmarshal(body, &dllogical)
if err != nil {
return fmt.Errorf("Error Unmarshalling LogicalDriveMetrics - " + err.Error())
}
if dllogical.Raid == "" {
ldName = dllogical.DisplayName
raidType = dllogical.RaidType
volIdentifier = dllogical.Identifiers[0].DurableName
} else {
ldName = dllogical.LogicalDriveName
raidType = dllogical.Raid
volIdentifier = dllogical.VolumeUniqueIdentifier
}
// Check physical drive is enabled then check status and convert string to numeric values
if dllogical.Status.State == "Enabled" {
if dllogical.Status.Health == "OK" {
Expand All @@ -306,7 +318,7 @@ func (e *Exporter) exportLogicalDriveMetrics(body []byte) error {
state = DISABLED
}

(*dllogicaldrive)["raidStatus"].WithLabelValues(dllogical.Name, e.ChassisSerialNumber, e.Model, dllogical.LogicalDriveName, dllogical.VolumeUniqueIdentifier, dllogical.Raid).Set(state)
(*dllogicaldrive)["raidStatus"].WithLabelValues(dllogical.Name, e.ChassisSerialNumber, e.Model, ldName, volIdentifier, raidType).Set(state)
return nil
}

Expand Down Expand Up @@ -381,6 +393,17 @@ func (e *Exporter) exportStorageControllerMetrics(body []byte) error {
}
}

if len(scm.StorageController.StorageController) == 0 {
if scm.Status.State == "Enabled" {
if scm.Status.Health == "OK" {
state = OK
} else {
state = BAD
}
(*drv)["storageControllerStatus"].WithLabelValues(scm.Name, e.ChassisSerialNumber, e.Model, scm.ControllerFirmware.FirmwareVersion, scm.Model).Set(state)
}
}

return nil
}

Expand All @@ -395,7 +418,10 @@ func (e *Exporter) exportMemorySummaryMetrics(body []byte) error {
return fmt.Errorf("Error Unmarshalling MemorySummaryMetrics - " + err.Error())
}
// Check memory status and convert string to numeric values
if dlm.MemorySummary.Status.HealthRollup == "OK" {
// Ignore memory summary if status is not present
if dlm.MemorySummary.Status.HealthRollup == "" {
return nil
} else if dlm.MemorySummary.Status.HealthRollup == "OK" {
state = OK
} else {
state = BAD
Expand Down Expand Up @@ -566,6 +592,12 @@ func (e *Exporter) exportProcessorMetrics(body []byte) error {
case int:
totCores = strconv.Itoa(pm.TotalCores.(int))
}

// Ignore metrics if processor is absent
if pm.Status.State == "Absent" {
return nil
}

if pm.Status.Health == "OK" {
state = OK
} else {
Expand Down
37 changes: 37 additions & 0 deletions exporter/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,43 @@ func getAllDriveEndpoints(ctx context.Context, fqdn, initialUrl, host string, cl
return driveEndpoints, err
}

// This if condition is for servers with iLO6. Gather metrics only from controllers with drives
// /redfish/v1/Systems/XXXX/Storage/XXXXX/
if len(arrayCtrlResp.StorageDrives) > 0 {
for _, member := range arrayCtrlResp.StorageDrives {
driveEndpoints.physicalDriveURLs = append(driveEndpoints.physicalDriveURLs, appendSlash(member.URL))
}

// If Volumes are present, parse volumes endpoint until all urls are found
if arrayCtrlResp.Volumes.URL != "" {
volumeOutput, err := getDriveEndpoint(fqdn+arrayCtrlResp.Volumes.URL, host, client)
if err != nil {
log.Error("api call "+fqdn+arrayCtrlResp.Volumes.URL+" failed", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
return driveEndpoints, err
}

for _, member := range volumeOutput.Members {
driveEndpoints.logicalDriveURLs = append(driveEndpoints.logicalDriveURLs, appendSlash(member.URL))
}
}

if arrayCtrlResp.Controllers.URL != "" {
controllerOutput, err := getDriveEndpoint(fqdn+arrayCtrlResp.Controllers.URL, host, client)
if err != nil {
log.Error("api call "+fqdn+arrayCtrlResp.Controllers.URL+" failed", zap.Error(err), zap.Any("trace_id", ctx.Value("traceID")))
return driveEndpoints, err
}

for _, member := range controllerOutput.Members {
driveEndpoints.arrayControllerURLs = append(driveEndpoints.arrayControllerURLs, appendSlash(member.URL))
}
}
} else if arrayCtrlResp.LinksUpper.PhysicalDrives.URL != "" || arrayCtrlResp.LinksLower.PhysicalDrives.URL != "" {
// /redfish/v1/Systems/XXXX/SmartStorage/ArrayControllers/X/
driveEndpoints.arrayControllerURLs = append(driveEndpoints.arrayControllerURLs, appendSlash(member.URL))
}

// all other servers apart from iLO6
// If LogicalDrives is present, parse logical drive endpoint until all urls are found
if arrayCtrlResp.LinksUpper.LogicalDrives.URL != "" {
logicalDriveOutput, err := getDriveEndpoint(fqdn+arrayCtrlResp.LinksUpper.LogicalDrives.URL, host, client)
Expand Down
41 changes: 26 additions & 15 deletions oem/drive.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,24 @@ type NVMeDriveMetrics struct {
// Logical Drives
// /redfish/v1/Systems/X/SmartStorage/ArrayControllers/X/LogicalDrives/X/
type LogicalDriveMetrics struct {
Id string `json:"Id"`
CapacityMiB int `json:"CapacityMiB"`
Description string `json:"Description"`
InterfaceType string `json:"InterfaceType"`
LogicalDriveName string `json:"LogicalDriveName"`
LogicalDriveNumber int `json:"LogicalDriveNumber"`
Name string `json:"Name"`
Raid string `json:"Raid"`
Status Status `json:"Status"`
StripeSizebytes int `json:"StripeSizebytes"`
VolumeUniqueIdentifier string `json:"VolumeUniqueIdentifier"`
Id string `json:"Id"`
CapacityMiB int `json:"CapacityMiB"`
Description string `json:"Description"`
DisplayName string `json:"DisplayName"`
InterfaceType string `json:"InterfaceType"`
Identifiers []Identifiers `json:"Identifiers"`
LogicalDriveName string `json:"LogicalDriveName"`
LogicalDriveNumber int `json:"LogicalDriveNumber"`
Name string `json:"Name"`
Raid string `json:"Raid"`
RaidType string `json:"RAIDType"`
Status Status `json:"Status"`
StripeSizebytes int `json:"StripeSizebytes"`
VolumeUniqueIdentifier string `json:"VolumeUniqueIdentifier"`
}

type Identifiers struct {
DurableName string `json:"DurableName"`
}

// Disk Drives
Expand Down Expand Up @@ -116,10 +123,14 @@ func (w *LocationWrapper) UnmarshalJSON(data []byte) error {
// /redfish/v1/Systems/X/SmartStorage/ArrayControllers/ for Logical and Physical Drives
// /redfish/v1/Chassis/X/Drives/ for NVMe Drive(s)
type GenericDrive struct {
Members []Members `json:"Members,omitempty"`
LinksUpper LinksUpper `json:"Links,omitempty"`
LinksLower LinksLower `json:"links,omitempty"`
MembersCount int `json:"[email protected],omitempty"`
Members []Members `json:"Members,omitempty"`
LinksUpper LinksUpper `json:"Links,omitempty"`
LinksLower LinksLower `json:"links,omitempty"`
MembersCount int `json:"[email protected],omitempty"`
DriveCount int `json:"[email protected],omitempty"`
StorageDrives []Link `json:"Drives,omitempty"`
Volumes Link `json:"Volumes,omitempty"`
Controllers Link `json:"Controllers,omitempty"`
}

type Members struct {
Expand Down
31 changes: 28 additions & 3 deletions oem/storage_ctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ import (
// /redfish/v1/Systems/WZPXXXXX/Storage/MRAID

type StorageControllerMetrics struct {
Name string `json:"Name"`
StorageController StorageControllerWrapper `json:"StorageControllers"`
Drives []Drive `json:"Drives"`
Name string `json:"Name"`
StorageController StorageControllerWrapper `json:"StorageControllers"`
Drives []Drive `json:"Drives"`
Status Status `json:"Status"`
Model string `json:"Model"`
ControllerFirmware FirmwareVersionWrapper `json:"FirmwareVersion"`
}

// StorageController contains status metadata of the C220 chassis storage controller
Expand Down Expand Up @@ -62,6 +65,28 @@ func (w *StorageControllerWrapper) UnmarshalJSON(data []byte) error {
return nil
}

type FirmwareVersionWrapper struct {
FirmwareVersion string
}

func (w *FirmwareVersionWrapper) UnmarshalJSON(data []byte) error {
// because of a change in output between firmware versions we need to account for this
// firmware version can either be a string or a json object
var CurrentFirmware struct {
Current struct {
VersionString string `json:"VersionString"`
} `json:"Current"`
}
err := json.Unmarshal(data, &CurrentFirmware)
if err == nil {
w.FirmwareVersion = CurrentFirmware.Current.VersionString
} else {
return json.Unmarshal(data, &w.FirmwareVersion)
}

return nil
}

type Drive struct {
Url string `json:"@odata.id"`
}
Expand Down

0 comments on commit 119e601

Please sign in to comment.