Move remote cmd functionality to baremetal cmd

Early airshipctl usage has identified the need to change the power of
remote hosts directly from airshipctl. This functionality is typically
required during the bootstrapping phase of airshipctl; however, the
functionality could be used anytime. A logical home for this
functionality would be in a baremetal command, not a bootstrap command.
Since all functionality performed by the bootstrap command is performed on
baremetal hosts, a natural need has developed to group this
functionality together under one baremetal command.

This change moves all functionality from the remote command to a new
baremetal command.

Once all functionality is grouped within the new baremetal command, a
user can control hosts like this:

airshipctl baremetal isogen                    generate ephemeral node ISO
airshipctl baremetal remotedirect              bootstrap ephemeral node
airshipctl baremetal poweroff       [DOC_NAME] shutdown baremetal node
airshipctl baremetal poweron        [DOC_NAME] power on baremetal node
airshipctl baremetal reboot         [DOC_NAME] reboot baremetal node
airshipctl baremetal powerstatus    [DOC_NAME] retrieve baremetal node status

Relates-To: #5

Change-Id: I31239df1593aac5810e66e1918d8d3207b9f60fb
Signed-off-by: Drew Walters <andrew.walters@att.com>
This commit is contained in:
Drew Walters 2020-04-10 21:09:08 +00:00
parent 5dc4881d20
commit fd65389f1a
14 changed files with 77 additions and 62 deletions

View File

@ -20,6 +20,11 @@ import (
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
) )
const (
flagPhase = "phase"
flagPhaseDescription = "airshipctl phase that contains the desired baremetal host document(s)"
)
// NewBaremetalCommand creates a new command for interacting with baremetal using airshipctl. // NewBaremetalCommand creates a new command for interacting with baremetal using airshipctl.
func NewBaremetalCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewBaremetalCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -30,6 +35,15 @@ func NewBaremetalCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Co
isoGenCmd := NewISOGenCommand(rootSettings) isoGenCmd := NewISOGenCommand(rootSettings)
cmd.AddCommand(isoGenCmd) cmd.AddCommand(isoGenCmd)
powerOffCmd := NewPowerOffCommand(rootSettings)
cmd.AddCommand(powerOffCmd)
powerStatusCmd := NewPowerStatusCommand(rootSettings)
cmd.AddCommand(powerStatusCmd)
rebootCmd := NewRebootCommand(rootSettings)
cmd.AddCommand(rebootCmd)
remoteDirectCmd := NewRemoteDirectCommand(rootSettings) remoteDirectCmd := NewRemoteDirectCommand(rootSettings)
cmd.AddCommand(remoteDirectCmd) cmd.AddCommand(remoteDirectCmd)

View File

@ -33,6 +33,21 @@ func TestBaremetal(t *testing.T) {
CmdLine: "-h", CmdLine: "-h",
Cmd: baremetal.NewISOGenCommand(nil), Cmd: baremetal.NewISOGenCommand(nil),
}, },
{
Name: "baremetal-poweroff-with-help",
CmdLine: "-h",
Cmd: baremetal.NewPowerOffCommand(nil),
},
{
Name: "baremetal-powerstatus-with-help",
CmdLine: "-h",
Cmd: baremetal.NewPowerStatusCommand(nil),
},
{
Name: "baremetal-reboot-with-help",
CmdLine: "-h",
Cmd: baremetal.NewRebootCommand(nil),
},
{ {
Name: "baremetal-remotedirect-with-help", Name: "baremetal-remotedirect-with-help",
CmdLine: "-h", CmdLine: "-h",

View File

@ -12,7 +12,7 @@
limitations under the License. limitations under the License.
*/ */
package remote package baremetal
import ( import (
"fmt" "fmt"
@ -28,8 +28,8 @@ import (
func NewPowerOffCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewPowerOffCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
var phase string var phase string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "poweroff SYSTEM_ID", Use: "poweroff BAREMETAL_HOST_DOC_NAME",
Short: "Shutdown a host", Short: "Shutdown a baremetal host",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByName(args[0])) m, err := remote.NewManager(rootSettings, phase, remote.ByName(args[0]))
@ -42,7 +42,7 @@ func NewPowerOffCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Com
return err return err
} }
fmt.Fprintf(cmd.OutOrStdout(), "Remote host %s powered off\n", args[0]) fmt.Fprintf(cmd.OutOrStdout(), "Remote host %s powered off\n", host.HostName)
} }
return nil return nil

View File

@ -12,7 +12,7 @@
limitations under the License. limitations under the License.
*/ */
package remote package baremetal
import ( import (
"fmt" "fmt"
@ -24,12 +24,12 @@ import (
"opendev.org/airship/airshipctl/pkg/remote" "opendev.org/airship/airshipctl/pkg/remote"
) )
// NewPowerStatusCommand provides a command to retrieve the power status of a remote host. // NewPowerStatusCommand provides a command to retrieve the power status of a baremetal host.
func NewPowerStatusCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewPowerStatusCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
var phase string var phase string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "powerstatus SYSTEM_ID", Use: "powerstatus BAREMETAL_HOST_DOC_NAME",
Short: "Retrieve the power status of a host", Short: "Retrieve the power status of a baremetal host",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
m, err := remote.NewManager(rootSettings, phase, remote.ByName(args[0])) m, err := remote.NewManager(rootSettings, phase, remote.ByName(args[0]))
@ -43,7 +43,7 @@ func NewPowerStatusCommand(rootSettings *environment.AirshipCTLSettings) *cobra.
return err return err
} }
fmt.Fprintf(cmd.OutOrStdout(), "Remote host %s has power status: %s\n", args[0], fmt.Fprintf(cmd.OutOrStdout(), "Remote host %s has power status: %s\n", host.HostName,
powerStatus) powerStatus)
} }

View File

@ -12,7 +12,7 @@ Licensed under the Apache License, Version 2.0 (the "License");
limitations under the License. limitations under the License.
*/ */
package remote package baremetal
import ( import (
"fmt" "fmt"
@ -24,11 +24,11 @@ import (
"opendev.org/airship/airshipctl/pkg/remote" "opendev.org/airship/airshipctl/pkg/remote"
) )
// NewRebootCommand provides a command with the capability to reboot hosts. // NewRebootCommand provides a command with the capability to reboot baremetal hosts.
func NewRebootCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { func NewRebootCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
var phase string var phase string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "reboot SYSTEM_ID", Use: "reboot BAREMETAL_HOST_DOC_NAME",
Short: "Reboot a host", Short: "Reboot a host",
Args: cobra.ExactArgs(1), Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
@ -42,7 +42,7 @@ func NewRebootCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
return err return err
} }
fmt.Fprintf(cmd.OutOrStdout(), "Rebooted remote host %s\n", args[0]) fmt.Fprintf(cmd.OutOrStdout(), "Rebooted remote host at %s\n", host.HostName)
} }
return nil return nil

View File

@ -0,0 +1,8 @@
Shutdown a baremetal host
Usage:
poweroff BAREMETAL_HOST_DOC_NAME [flags]
Flags:
-h, --help help for poweroff
--phase string airshipctl phase that contains the desired baremetal host document(s) (default "bootstrap")

View File

@ -0,0 +1,8 @@
Retrieve the power status of a baremetal host
Usage:
powerstatus BAREMETAL_HOST_DOC_NAME [flags]
Flags:
-h, --help help for powerstatus
--phase string airshipctl phase that contains the desired baremetal host document(s) (default "bootstrap")

View File

@ -0,0 +1,8 @@
Reboot a host
Usage:
reboot BAREMETAL_HOST_DOC_NAME [flags]
Flags:
-h, --help help for reboot
--phase string airshipctl phase that contains the desired baremetal host document(s) (default "bootstrap")

View File

@ -6,6 +6,9 @@ Usage:
Available Commands: Available Commands:
help Help about any command help Help about any command
isogen Generate baremetal host ISO image isogen Generate baremetal host ISO image
poweroff Shutdown a baremetal host
powerstatus Retrieve the power status of a baremetal host
reboot Reboot a host
remotedirect Bootstrap the ephemeral host remotedirect Bootstrap the ephemeral host
Flags: Flags:

View File

@ -1,45 +0,0 @@
/*
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 (
"github.com/spf13/cobra"
"opendev.org/airship/airshipctl/pkg/environment"
)
const (
flagPhase = "phase"
flagPhaseDescription = "airshipctl phase that contains the desired baremetal host document(s)"
)
// NewRemoteCommand creates a new command that provides functionality to control remote entities.
func NewRemoteCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
remoteRootCmd := &cobra.Command{
Use: "remote",
Short: "Control remote entities, i.e. hosts.",
}
powerOffCmd := NewPowerOffCommand(rootSettings)
remoteRootCmd.AddCommand(powerOffCmd)
powerStatusCmd := NewPowerStatusCommand(rootSettings)
remoteRootCmd.AddCommand(powerStatusCmd)
rebootCmd := NewRebootCommand(rootSettings)
remoteRootCmd.AddCommand(rebootCmd)
return remoteRootCmd
}

View File

@ -27,7 +27,6 @@ import (
"opendev.org/airship/airshipctl/cmd/completion" "opendev.org/airship/airshipctl/cmd/completion"
"opendev.org/airship/airshipctl/cmd/config" "opendev.org/airship/airshipctl/cmd/config"
"opendev.org/airship/airshipctl/cmd/document" "opendev.org/airship/airshipctl/cmd/document"
"opendev.org/airship/airshipctl/cmd/remote"
"opendev.org/airship/airshipctl/cmd/secret" "opendev.org/airship/airshipctl/cmd/secret"
"opendev.org/airship/airshipctl/pkg/environment" "opendev.org/airship/airshipctl/pkg/environment"
"opendev.org/airship/airshipctl/pkg/log" "opendev.org/airship/airshipctl/pkg/log"
@ -71,7 +70,6 @@ func AddDefaultAirshipCTLCommands(cmd *cobra.Command, settings *environment.Airs
cmd.AddCommand(completion.NewCompletionCommand()) cmd.AddCommand(completion.NewCompletionCommand())
cmd.AddCommand(document.NewDocumentCommand(settings)) cmd.AddCommand(document.NewDocumentCommand(settings))
cmd.AddCommand(config.NewConfigCommand(settings)) cmd.AddCommand(config.NewConfigCommand(settings))
cmd.AddCommand(remote.NewRemoteCommand(settings))
cmd.AddCommand(secret.NewSecretCommand()) cmd.AddCommand(secret.NewSecretCommand())
return cmd return cmd

View File

@ -10,7 +10,6 @@ Available Commands:
config Manage the airshipctl config file config Manage the airshipctl config file
document Manage deployment documents document Manage deployment documents
help Help about any command help Help about any command
remote Control remote entities, i.e. hosts.
secret Manage secrets secret Manage secrets
version Show the version number of airshipctl version Show the version number of airshipctl

View File

@ -58,6 +58,7 @@ type baremetalHost struct {
Client Client
Context context.Context Context context.Context
BMCAddress string BMCAddress string
HostName string
username string username string
password string password string
} }
@ -182,7 +183,7 @@ func newBaremetalHost(mgmtCfg config.ManagementConfiguration,
return host, err return host, err
} }
host = baremetalHost{client, ctx, address, username, password} host = baremetalHost{client, ctx, address, hostDoc.GetName(), username, password}
default: default:
return host, ErrUnknownManagementType{Type: mgmtCfg.Type} return host, ErrUnknownManagementType{Type: mgmtCfg.Type}
} }

View File

@ -54,6 +54,7 @@ func TestDoRemoteDirectMissingConfigOpts(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }
@ -73,6 +74,7 @@ func TestDoRemoteDirectMissingISOURL(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }
@ -98,6 +100,7 @@ func TestDoRemoteDirectRedfish(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }
@ -127,6 +130,7 @@ func TestDoRemoteDirectRedfishVirtualMediaError(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }
@ -158,6 +162,7 @@ func TestDoRemoteDirectRedfishBootSourceError(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }
@ -190,6 +195,7 @@ func TestDoRemoteDirectRedfishRebootError(t *testing.T) {
rMock, rMock,
ctx, ctx,
redfishURL, redfishURL,
"doc-name",
username, username,
password, password,
} }