diff --git a/pkg/bmc/bmc.go b/pkg/bmc/bmc.go index 813160d8b..d30cfbfb7 100644 --- a/pkg/bmc/bmc.go +++ b/pkg/bmc/bmc.go @@ -586,6 +586,27 @@ func (bmc *BMC) SystemPowerState() (string, error) { return string(system.PowerState), nil } +// WaitForSystemPowerState waits up to timeout until the BMC returns the provided system power state. +func (bmc *BMC) WaitForSystemPowerState(powerState redfish.PowerState, timeout time.Duration) error { + if valid, err := bmc.validateRedfish(); !valid { + return err + } + + glog.V(100).Infof("Waiting up to %s until BMC returns power state %s", timeout, powerState) + + return wait.PollUntilContextTimeout( + context.TODO(), 10*time.Second, timeout, true, func(ctx context.Context) (bool, error) { + systemPowerState, err := bmc.SystemPowerState() + if err != nil { + glog.V(100).Infof("Failed to get system power state from BMC: %v", err) + + return false, nil + } + + return systemPowerState == string(powerState), nil + }) +} + // PowerUsage returns the current power usage of the chassis in watts using the Redfish API. This method uses the first // chassis with a power link and the power control index for the BMC client. func (bmc *BMC) PowerUsage() (float32, error) { diff --git a/pkg/bmc/bmc_test.go b/pkg/bmc/bmc_test.go index decda0991..8ab632a0c 100644 --- a/pkg/bmc/bmc_test.go +++ b/pkg/bmc/bmc_test.go @@ -1,6 +1,7 @@ package bmc import ( + "context" _ "embed" "encoding/json" "fmt" @@ -594,6 +595,22 @@ func TestBMCSystemPowerState(t *testing.T) { assert.Equal(t, expectedPowerState, powerState) } +func TestBMCWaitForSystemPowerState(t *testing.T) { + // Create fake redfish endpoint. + redfishServer := createFakeRedfishLocalServer(false, redfishAPIResponseCallbacks{}) + defer redfishServer.Close() + + host := strings.Split(redfishServer.URL, "//")[1] + bmc := New(host).WithRedfishUser(defaultUsername, defaultPassword) + + // The fake endpoint should be On, so will succeed when waiting till On and time out waiting for Off. + err := bmc.WaitForSystemPowerState(redfish.OnPowerState, time.Second) + assert.NoError(t, err) + + err = bmc.WaitForSystemPowerState(redfish.OffPowerState, time.Second) + assert.Equal(t, context.DeadlineExceeded, err) +} + func TestBMCPowerUsage(t *testing.T) { // Create a fake redfish api endpoint with secureBoot "disabled" redfishServer := createFakeRedfishLocalServer(false, redfishAPIResponseCallbacks{})