bd51d1f31b
The remote package in airshipctl is tightly coupled to redfish. In the future, we may need to introduce IPMI or SMASH; however, adding those clients now would be difficult because of our tight dependence on redfish. This change adds a Client interface, remote.Client, that will be implemented by all OOB clients (i.e. Redfish, SMASH, IPMI) in order to satisfy remoteDirect and future power commands. This change also creates a Redfish client that implements the client. A future change will remove the old Redfish client and de-couple the remoteDirect functionality from the redfish package. Relates #5, #122 Change-Id: Id9fe09e74efef0c4fcd5b92a1c12897217a4dae1 Signed-off-by: Drew Walters <andrew.walters@att.com>
138 lines
3.2 KiB
Go
138 lines
3.2 KiB
Go
package remote
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"opendev.org/airship/airshipctl/pkg/config"
|
|
"opendev.org/airship/airshipctl/pkg/document"
|
|
"opendev.org/airship/airshipctl/pkg/environment"
|
|
alog "opendev.org/airship/airshipctl/pkg/log"
|
|
"opendev.org/airship/airshipctl/pkg/remote/redfish"
|
|
)
|
|
|
|
const (
|
|
AirshipRemoteTypeRedfish string = "redfish"
|
|
)
|
|
|
|
// Interface to be implemented by remoteDirect implementation
|
|
type RDClient interface {
|
|
DoRemoteDirect() error
|
|
}
|
|
|
|
// Get remotedirect client based on config
|
|
func getRemoteDirectClient(
|
|
remoteConfig *config.RemoteDirect,
|
|
remoteURL string,
|
|
username string,
|
|
password string) (RDClient, error) {
|
|
var client RDClient
|
|
switch remoteConfig.RemoteType {
|
|
case AirshipRemoteTypeRedfish:
|
|
alog.Debug("Remote type redfish")
|
|
|
|
rfURL, err := url.Parse(remoteURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
baseURL := fmt.Sprintf("%s://%s", rfURL.Scheme, rfURL.Host)
|
|
schemeSplit := strings.Split(rfURL.Scheme, redfish.RedfishURLSchemeSeparator)
|
|
if len(schemeSplit) > 1 {
|
|
baseURL = fmt.Sprintf("%s://%s", schemeSplit[len(schemeSplit)-1], rfURL.Host)
|
|
}
|
|
|
|
urlPath := strings.Split(rfURL.Path, "/")
|
|
nodeID := urlPath[len(urlPath)-1]
|
|
|
|
client, err = redfish.NewRedfishRemoteDirectClient(
|
|
baseURL,
|
|
nodeID,
|
|
username,
|
|
password,
|
|
remoteConfig.IsoURL,
|
|
remoteConfig.Insecure,
|
|
remoteConfig.UseProxy,
|
|
)
|
|
if err != nil {
|
|
alog.Debugf("redfish remotedirect client creation failed")
|
|
return nil, err
|
|
}
|
|
|
|
default:
|
|
return nil, NewRemoteDirectErrorf("invalid remote type")
|
|
}
|
|
|
|
return client, nil
|
|
}
|
|
|
|
func getRemoteDirectConfig(settings *environment.AirshipCTLSettings) (
|
|
remoteConfig *config.RemoteDirect,
|
|
remoteURL string,
|
|
username string,
|
|
password string,
|
|
err error) {
|
|
cfg := settings.Config()
|
|
bootstrapSettings, err := cfg.CurrentContextBootstrapInfo()
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
remoteConfig = bootstrapSettings.RemoteDirect
|
|
if remoteConfig == nil {
|
|
return nil, "", "", "", config.ErrMissingConfig{What: "RemoteDirect options not defined in bootstrap config"}
|
|
}
|
|
|
|
bundlePath, err := cfg.CurrentContextEntryPoint(config.Ephemeral, "")
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
docBundle, err := document.NewBundleByPath(bundlePath)
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
selector := document.NewEphemeralBMHSelector()
|
|
doc, err := docBundle.SelectOne(selector)
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
remoteURL, err = document.GetBMHBMCAddress(doc)
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
username, password, err = document.GetBMHBMCCredentials(doc, docBundle)
|
|
if err != nil {
|
|
return nil, "", "", "", err
|
|
}
|
|
|
|
return remoteConfig, remoteURL, username, password, nil
|
|
}
|
|
|
|
// Top level function to execute remote direct based on remote type
|
|
func DoRemoteDirect(settings *environment.AirshipCTLSettings) error {
|
|
remoteConfig, remoteURL, username, password, err := getRemoteDirectConfig(settings)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
client, err := getRemoteDirectClient(remoteConfig, remoteURL, username, password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = client.DoRemoteDirect()
|
|
if err != nil {
|
|
alog.Debugf("remote direct failed: %s", err)
|
|
return err
|
|
}
|
|
|
|
alog.Print("Remote direct successfully completed")
|
|
|
|
return nil
|
|
}
|