Skip to content

Commit

Permalink
Extract storage details of a Server using Redfish (#143)
Browse files Browse the repository at this point in the history
* adds storage details to server crd

* uses k8s resource quantity

* removes unused types

* minor fix

* use pointer for Capacity; load storages in discovery

* adds missing comment

* Regenerate api reference docs

---------

Co-authored-by: Andreas Fritzler <[email protected]>
  • Loading branch information
stefanhipfel and afritzler authored Oct 16, 2024
1 parent 7ccca8c commit 65a4530
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 0 deletions.
36 changes: 36 additions & 0 deletions api/v1alpha1/server_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package v1alpha1

import (
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -142,6 +143,20 @@ const (
OffIndicatorLED IndicatorLED = "Off"
)

// StorageState represents Storage states
type StorageState string

const (
// StorageStateEnabled indicates that the storage device is enabled.
StorageStateEnabled StorageState = "Enabled"

// StorageStateDisabled indicates that the storage device is disabled.
StorageStateDisabled StorageState = "Disabled"

// StorageStateAbsent indicates that the storage device is absent.
StorageStateAbsent StorageState = "Absent"
)

// ServerStatus defines the observed state of Server.
type ServerStatus struct {
// Manufacturer is the name of the server manufacturer.
Expand All @@ -168,6 +183,9 @@ type ServerStatus struct {
// NetworkInterfaces is a list of network interfaces associated with the server.
NetworkInterfaces []NetworkInterface `json:"networkInterfaces,omitempty"`

// Storages is a list of storages associated with the server.
Storages []Storage `json:"storages,omitempty"`

BIOS BIOSSettings `json:"BIOS,omitempty"`

// Conditions represents the latest available observations of the server's current state.
Expand All @@ -192,6 +210,24 @@ type NetworkInterface struct {
MACAddress string `json:"macAddress"`
}

// Storage defines the details of one storage device
type Storage struct {
// Name is the name of the storage interface.
Name string `json:"name,omitempty"`
// Rotational specifies whether the storage device is rotational.
Rotational bool `json:"rotational,omitempty"`
// Type specifies the type of the storage device.
Type string `json:"type,omitempty"`
// SizeBytes specifies the size of the storage device in bytes.
Capacity *resource.Quantity `json:"capacity,omitempty"`
// Vendor specifies the vendor of the storage device.
Vendor string `json:"vendor,omitempty"`
// Model specifies the model of the storage device.
Model string `json:"model,omitempty"`
// State specifies the state of the storage device.
State StorageState `json:"state,omitempty"`
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Cluster
Expand Down
27 changes: 27 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions bmc/bmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type BMC interface {
GetBiosVersion(systemUUID string) (string, error)

SetBootOrder(systemUUID string, order []string) error

GetStorages(systemUUID string) ([]Storage, error)
}

type Bios struct {
Expand Down Expand Up @@ -105,6 +107,23 @@ type Server struct {
SerialNumber string
}

type Storage struct {
// Name is the name of the storage interface.
Name string `json:"name,omitempty"`
// Rotational specifies whether the storage device is rotational.
Rotational bool `json:"rotational,omitempty"`
// Type specifies the type of the storage device.
Type redfish.FormFactor `json:"type,omitempty"`
// SizeBytes specifies the size of the storage device in bytes.
SizeBytes int64 `json:"sizeBytes,omitempty"`
// Vendor specifies the vendor of the storage device.
Vendor string `json:"vendor,omitempty"`
// Model specifies the model of the storage device.
Model string `json:"model,omitempty"`
// State specifies the state of the storage device.
State common.State `json:"state,omitempty"`
}

// PowerState is the power state of the system.
type PowerState string

Expand Down
50 changes: 50 additions & 0 deletions bmc/redfish.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,56 @@ func (r *RedfishBMC) checkBiosAttributes(attrs map[string]string) (reset bool, e
return
}

func (r *RedfishBMC) GetStorages(systemUUID string) ([]Storage, error) {
system, err := r.getSystemByUUID(systemUUID)
if err != nil {
return nil, err
}
systemStorage, err := system.Storage()
if err != nil {
return nil, err
}
result := make([]Storage, 0, len(systemStorage))
for _, s := range systemStorage {
drives, err := s.Drives()
if err != nil {
return nil, err
}
for _, d := range drives {
result = append(result, Storage{
Name: d.Name,
Rotational: d.RotationSpeedRPM != 0,
Type: d.DriveFormFactor,
SizeBytes: d.CapacityBytes,
Vendor: d.Manufacturer,
Model: d.Model,
State: d.Status.State,
})
}
}
if len(result) == 0 {
// if no storage is found, fall back to simpleStorage (outdated storage API)
simpleStorages, err := system.SimpleStorages()
result = make([]Storage, 0, len(systemStorage))
if err != nil {
return nil, err
}
for _, s := range simpleStorages {
for _, d := range s.Devices {
result = append(result, Storage{
Name: d.Name,
SizeBytes: d.CapacityBytes,
Vendor: d.Manufacturer,
Model: d.Model,
State: d.Status.State,
})
}
}
return result, nil
}
return result, nil
}

func (r *RedfishBMC) getSystemByUUID(systemUUID string) (*redfish.ComputerSystem, error) {
service := r.client.GetService()
systems, err := service.Systems()
Expand Down
34 changes: 34 additions & 0 deletions config/crd/bases/metal.ironcore.dev_servers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,40 @@ spec:
state:
description: State represents the current state of the server.
type: string
storages:
description: Storages is a list of storages associated with the server.
items:
description: Storage defines the details of one storage device
properties:
capacity:
anyOf:
- type: integer
- type: string
description: SizeBytes specifies the size of the storage device
in bytes.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
model:
description: Model specifies the model of the storage device.
type: string
name:
description: Name is the name of the storage interface.
type: string
rotational:
description: Rotational specifies whether the storage device
is rotational.
type: boolean
state:
description: State specifies the state of the storage device.
type: string
type:
description: Type specifies the type of the storage device.
type: string
vendor:
description: Vendor specifies the vendor of the storage device.
type: string
type: object
type: array
type: object
type: object
served: true
Expand Down
Loading

0 comments on commit 65a4530

Please sign in to comment.