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

Add power supplies #285

Merged
merged 1 commit into from
Oct 10, 2023
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
9 changes: 9 additions & 0 deletions redfish/computersystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,15 @@ const (
PowerCycleResetType ResetType = "PowerCycle"
// NmiResetType shall be used to trigger a crash/core dump file
NmiResetType ResetType = "Nmi"
// Pause execution on the unit but do not remove power.
// This is typically a feature of virtual machine hypervisors
PauseResetType ResetType = "Pause"
// Resume execution on the paused unit.
// This is typically a feature of virtual machine hypervisors
ResumeResetType ResetType = "Resume"
// Write the state of the unit to disk before powering off.
// This allows for the state to be restored when powered back on
SuspendResetType ResetType = "Suspend"
)

// ComputerSystem is used to represent resources that represent a
Expand Down
6 changes: 3 additions & 3 deletions redfish/powerdistribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,9 @@ func (powerDistribution *PowerDistribution) Sensors() ([]*Sensor, error) {
return ListReferencedSensors(powerDistribution.GetClient(), powerDistribution.sensors)
}

// Deprecated: (v1.3) in favor of the Sensors link in the Chassis resource.
func (powerDistribution *PowerDistribution) PowerSupplies() ([]*PowerSupply, error) {
return ListReferencedPowerSupplies(powerDistribution.GetClient(), powerDistribution.sensors)
// Deprecated: (v1.3) in favor of the PowerSupplies link in the Chassis resource.
func (powerDistribution *PowerDistribution) PowerSupplies() ([]*PowerSupplyUnit, error) {
return ListReferencedPowerSupplyUnits(powerDistribution.GetClient(), powerDistribution.powerSupplies)
}

// ManagedBy gets the collection of managers for this equipment.
Expand Down
327 changes: 327 additions & 0 deletions redfish/powersupplyunit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
//
// SPDX-License-Identifier: BSD-3-Clause
//

package redfish

import (
"encoding/json"
"fmt"
"reflect"

"github.com/stmcginnis/gofish/common"
)

type LineInputStatus string

const (
// No power detected at line input.
LossOfInputLineInputStatus LineInputStatus = "LossOfInput"
// Line input is within normal operating range.
NormalLineInputStatus LineInputStatus = "Normal"
// Line input voltage or current is outside of normal operating range.
OutOfRangeLineInputStatus LineInputStatus = "OutOfRange"
)

type PowerSupplyUnitType string

const (
// Alternating Current (AC) power supply.
ACPowerSupplyUnitType PowerSupplyUnitType = "AC"
// The power supply supports both DC or AC.
ACorDCPowerSupplyUnitType PowerSupplyUnitType = "ACorDC"
// Direct Current (DC) power supply.
DCPowerSupplyUnitType PowerSupplyUnitType = "DC"
// (v1.5+) Direct Current (DC) voltage regulator.
DCRegulatorPowerSupplyUnitType PowerSupplyUnitType = "DCRegulator"
)

// The efficiency ratings of this power supply.
type EfficiencyRating struct {
// The rated efficiency of this power supply at the specified load.
EfficiencyPercent float32
// The electrical load for this rating.
LoadPercent float32
}

// The input ranges that the power supply can use.
type PowerSupplyInputRange struct {
// The maximum capacity of this power supply when operating in this input range.
CapacityWatts float32
// The input voltage range.
NominalVoltageType NominalVoltage
}

// The input ranges that the power supply can use.
type OutputRail struct {
// The nominal voltage of this output power rail.
NominalVoltage float32
// The area or device to which this power rail applies.
PhysicalContext common.PhysicalContext
}

// PowerSupplyUnit shall represent a power supply unit for a Redfish implementation.
// It may also represent a location, such as a slot, socket, or bay, where a unit may be installed,
// but the State property within the Status property contains Absent.
type PowerSupplyUnit struct {
common.Entity

// ODataContext is the odata context.
ODataContext string `json:"@odata.context"`
// ODataType is the odata type.
ODataType string `json:"@odata.type"`
// Description provides a description of this resource.
Description string

// The link to the assembly associated with this power supply.
assembly string
// The efficiency ratings of this power supply.
EfficiencyRatings []EfficiencyRating
// The URIs of the management interfaces
// for the upstream electrical source connections for this power supply.
ElectricalSourceManagerURIs []string
// The names of the upstream electrical sources,
// such as circuits or outlets, connected to this power supply.
ElectricalSourceNames []string
// The firmware version for this power supply.
FirmwareVersion string
// An indication of whether this device can be inserted
// or removed while the equipment is in operation.
HotPluggable bool
// The nominal voltage type of the line input to this power supply.
InputNominalVoltageType NominalVoltage
// The input ranges that the power supply can use.
InputRanges []PowerSupplyInputRange
// The status of the line input.
LineInputStatus LineInputStatus
// The location of the power supply.
Location common.Location
// An indicator allowing an operator to physically locate this resource.
LocationIndicatorActive bool
// The manufacturer of this power supply.
Manufacturer string
// The link to the power supply metrics resource associated with this power supply.
metrics string
// The model number for this power supply.
Model string
// The nominal output voltage type of this power supply.
OutputNominalVoltageType NominalVoltage
// The output power rails provided by this power supply.
OutputRails []OutputRail
// The part number for this power supply.
PartNumber string
// The number of ungrounded current-carrying conductors (phases)
// and the total number of conductors (wires)
// provided for the power supply input connector.
PhaseWiringType PhaseWiringType
// The type of plug according to NEMA, IEC, or regional standards.
PlugType PlugType
// The maximum capacity of this power supply.
PowerCapacityWatts float32
// The power supply type (AC or DC).
PowerSupplyType PowerSupplyUnitType
// The production or manufacturing date of this power supply.
ProductionDate string
// An indication of whether this component can be independently replaced
// as allowed by the vendor's replacement policy.
Replaceable bool
// The serial number for this power supply.
SerialNumber string
// The spare part number for this power supply.
SparePartNumber string
// The status and health of the resource and its subordinate or dependent resources.
Status common.Status
// The hardware version of this power supply.
Version string

// Links section
// Deprecated (v1.4): A link to the outlet connected to this power supply.
outlet string
// An array of links to the chassis that are directly powered by this power supply.
poweringChassis []string
PoweringChassisCount int
// An array of links to the outlets that provide power to this power supply.
powerOutlets []string
PowerOutletsCount int
// OemLinks are all OEM data under link section
OemLinks json.RawMessage

// Actions section
// This action resets the power supply.
resetTarget string
// OemActions contains all the vendor specific actions.
// It is vendor responsibility to parse this field accordingly
OemActions json.RawMessage

// rawData holds the original serialized JSON so we can compare updates.
rawData []byte
}

// UnmarshalJSON unmarshals a PowerSupplyUnit object from the raw JSON.
func (powerSupplyUnit *PowerSupplyUnit) UnmarshalJSON(b []byte) error {
type temp PowerSupplyUnit
type linkReference struct {
Outlet common.Link
PoweringChassis common.Links
PoweringChassisCount int `json:"[email protected]"`
PowerOutlets common.Links
PowerOutletsCount int `json:"[email protected]"`
Oem json.RawMessage
}
type actions struct {
Reset struct {
Target string
} `json:"#PowerSupply.Reset"`
Oem json.RawMessage // OEM actions will be stored here
}
var t struct {
temp

Assembly common.Link
Metrics common.Link

Links linkReference
Actions actions
}

if err := json.Unmarshal(b, &t); err != nil {
return err
}

// Extract the links to other entities for later
*powerSupplyUnit = PowerSupplyUnit(t.temp)
powerSupplyUnit.assembly = t.Assembly.String()
powerSupplyUnit.metrics = t.Metrics.String()

powerSupplyUnit.outlet = t.Links.Outlet.String()
powerSupplyUnit.poweringChassis = t.Links.PoweringChassis.ToStrings()
powerSupplyUnit.PoweringChassisCount = t.Links.PoweringChassisCount
powerSupplyUnit.powerOutlets = t.Links.PowerOutlets.ToStrings()
powerSupplyUnit.PowerOutletsCount = t.Links.PowerOutletsCount
powerSupplyUnit.OemLinks = t.Links.Oem

powerSupplyUnit.resetTarget = t.Actions.Reset.Target
powerSupplyUnit.OemActions = t.Actions.Oem

// This is a read/write object, so we need to save the raw object data for later
powerSupplyUnit.rawData = b

return nil
}

// GetPowerSupplyUnit will get a PowerSupplyUnit instance from the Redfish service.
func GetPowerSupplyUnit(c common.Client, uri string) (*PowerSupplyUnit, error) {
var powerSupplyUnit PowerSupplyUnit
return &powerSupplyUnit, powerSupplyUnit.Get(c, uri, &powerSupplyUnit)
}

// Update commits updates to this object's properties to the running system.
func (powerSupplyUnit *PowerSupplyUnit) Update() error {
// Get a representation of the object's original state so we can find what
// to update.
psu := new(PowerSupplyUnit)
err := psu.UnmarshalJSON(powerSupplyUnit.rawData)
if err != nil {
return err
}

readWriteFields := []string{
"ElectricalSourceManagerURIs",
"ElectricalSourceNames",
"LocationIndicatorActive",
}

originalElement := reflect.ValueOf(psu).Elem()
currentElement := reflect.ValueOf(powerSupplyUnit).Elem()

return powerSupplyUnit.Entity.Update(originalElement, currentElement, readWriteFields)
}

// This action shall reset a power supply. A GracefulRestart ResetType shall reset the power supply
// but shall not affect the power output. A ForceRestart ResetType can affect the power supply output.
func (powerSupplyUnit *PowerSupplyUnit) Reset(resetType ResetType) error {
if powerSupplyUnit.resetTarget == "" {
return fmt.Errorf("Reset is not supported") //nolint:golint
}

t := struct {
ResetType ResetType
}{ResetType: resetType}

return powerSupplyUnit.Post(powerSupplyUnit.resetTarget, t)
}

// ListReferencedPowerSupplyUnits gets the collection of PowerSupplies from
// a provided reference.
func ListReferencedPowerSupplyUnits(c common.Client, link string) ([]*PowerSupplyUnit, error) { //nolint:dupl
var result []*PowerSupplyUnit
if link == "" {
return result, nil
}

type GetResult struct {
Item *PowerSupplyUnit
Link string
Error error
}

ch := make(chan GetResult)
collectionError := common.NewCollectionError()
get := func(link string) {
powerSupplyUnit, err := GetPowerSupplyUnit(c, link)
ch <- GetResult{Item: powerSupplyUnit, Link: link, Error: err}
}

go func() {
err := common.CollectList(get, c, link)
if err != nil {
collectionError.Failures[link] = err
}
close(ch)
}()

for r := range ch {
if r.Error != nil {
collectionError.Failures[r.Link] = r.Error
} else {
result = append(result, r.Item)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
}

// PoweringChassis gets the collection of the chassis directly powered by this power supply.
func (powerSupplyUnit *PowerSupplyUnit) PoweringChassis() ([]*Chassis, error) {
var result []*Chassis

collectionError := common.NewCollectionError()
for _, uri := range powerSupplyUnit.poweringChassis {
chassis, err := GetChassis(powerSupplyUnit.GetClient(), uri)
if err != nil {
collectionError.Failures[uri] = err
} else {
result = append(result, chassis)
}
}

if collectionError.Empty() {
return result, nil
}

return result, collectionError
}

// Metrics gets the metrics associated with this power supply.
func (powerSupplyUnit *PowerSupplyUnit) Metrics() (metrics *PowerSupplyUnitMetrics, err error) {
if powerSupplyUnit.metrics == "" {
return
}
return GetPowerSupplyUnitMetrics(powerSupplyUnit.GetClient(), powerSupplyUnit.metrics)
}

// TODO: assembly, outlet, powerOutlets
Loading