Add remote system shutdown command

This change introduces a system shutdown command that can be used to
power off remote hosts.

Relates-To: #5

Change-Id: I4fa52db055dcb17e344283fbdd772506e12f77fe
Signed-off-by: Drew Walters <andrew.walters@att.com>
This commit is contained in:
Drew Walters 2020-04-01 19:46:59 +00:00
parent a4001d255f
commit 263f2ecd6f
5 changed files with 76 additions and 0 deletions

View File

@ -25,6 +25,9 @@ func NewRemoteCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
Short: "Control remote entities, i.e. hosts.",
}
powerOffCmd := NewPowerOffCommand(rootSettings)
remoteRootCmd.AddCommand(powerOffCmd)
powerStatusCmd := NewPowerStatusCommand(rootSettings)
remoteRootCmd.AddCommand(powerStatusCmd)

View File

@ -0,0 +1,47 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package remote
import (
"fmt"
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/remote"
)
// NewPowerOffCommand provides a command to shutdown a remote host.
func NewPowerOffCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
powerOffCmd := &cobra.Command{
Use: "poweroff SYSTEM_ID",
Short: "Shutdown a host",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
a, err := remote.NewAdapter(rootSettings)
if err != nil {
return err
}
if err := a.OOBClient.SystemPowerOff(a.Context, args[0]); err != nil {
return err
}
fmt.Fprintf(cmd.OutOrStdout(), "Remote host %s powered off\n", args[0])
return nil
},
}
return powerOffCmd
}

View File

@ -146,6 +146,16 @@ func (c *Client) SetVirtualMedia(ctx context.Context, isoPath string) error {
return ScreenRedfishError(httpResp, err)
}
// SystemPowerOff shuts down a host.
func (c *Client) SystemPowerOff(ctx context.Context, systemID string) error {
resetReq := redfishClient.ResetRequestBody{}
resetReq.ResetType = redfishClient.RESETTYPE_FORCE_OFF
_, httpResp, err := c.redfishAPI.ResetSystem(ctx, systemID, resetReq)
return ScreenRedfishError(httpResp, err)
}
// SystemPowerStatus retrieves the power status of a host as a human-readable string.
func (c *Client) SystemPowerStatus(ctx context.Context, systemID string) (string, error) {
computerSystem, httpResp, err := c.redfishAPI.GetSystem(ctx, systemID)

View File

@ -21,9 +21,12 @@ import (
type Client interface {
RebootSystem(context.Context, string) error
SystemPowerOff(context.Context, string) error
// TODO(drewwalters96): Should this be a string forever? We may want to define our own custom type, as the
// string format will be client dependent when we add new clients.
SystemPowerStatus(context.Context, string) (string, error)
EphemeralNodeID() string
// TODO(drewwalters96): This function may be too tightly coupled to remoteDirect operations. This could probably

View File

@ -82,6 +82,19 @@ func (m *MockClient) SetVirtualMedia(ctx context.Context, isoPath string) error
return args.Error(0)
}
// SystemPowerOff provides a stubbed method that can be mocked to test functions that use the
// Redfish client without making any Redfish API calls or requiring the appropriate Redfish client settings.
//
// Example usage:
// client := redfishutils.NewClient()
// client.On("SystemPowerOff").Return(<return values>)
//
// err := client.SystemPowerOff(<args>)
func (m *MockClient) SystemPowerOff(ctx context.Context, systemID string) error {
args := m.Called(ctx, systemID)
return args.Error(0)
}
// SystemPowerStatus provides a stubbed method that can be mocked to test functions that use the
// Redfish client without making any Redfish API calls or requiring the appropriate Redfish client settings.
//