airshipctl/pkg/remote/remote_direct.go
Dmitry Ukov 97c114cb21 Switch remote direct to airshipctl configuration
Related #7
Change-Id: I015b178895359ea468748eb72e367b4ff56026bb
2020-02-07 22:01:45 +04:00

133 lines
3.3 KiB
Go

package remote
import (
"context"
"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"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
const (
AirshipRemoteTypeRedfish string = "redfish"
AirshipRemoteTypeSmash string = "smash"
AirshipHostKind string = "BareMetalHost"
)
// Interface to be implemented by remoteDirect implementation
type RemoteDirectClient interface {
DoRemoteDirect() error
}
// Get remotedirect client based on config
func getRemoteDirectClient(remoteConfig *config.RemoteDirect, remoteURL string) (RemoteDirectClient, error) {
var client RemoteDirectClient
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(
context.Background(),
baseURL,
nodeID,
remoteConfig.IsoURL)
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) (*config.RemoteDirect, string, error) {
cfg := settings.Config()
manifest, err := cfg.CurrentContextManifest()
if err != nil {
return nil, "", err
}
bootstrapSettings, err := cfg.CurrentContextBootstrapInfo()
if err != nil {
return nil, "", err
}
// TODO (dukov) replace with the appropriate function once it's available
// in document module
docBundle, err := document.NewBundle(fs.MakeRealFS(), manifest.TargetPath, "")
if err != nil {
return nil, "", err
}
filter := types.Selector{
Gvk: gvk.FromKind(AirshipHostKind),
LabelSelector: document.EphemeralClusterMarker,
}
docs, err := docBundle.Select(filter)
if err != nil {
return nil, "", err
}
if len(docs) == 0 {
return nil, "", document.ErrDocNotFound{
Annotation: document.EphemeralClusterMarker,
Kind: AirshipHostKind,
}
}
// NOTE If filter returned more than one document chose first
remoteURL, err := docs[0].GetString("spec.bmc.address")
if err != nil {
return nil, "", err
}
return bootstrapSettings.RemoteDirect, remoteURL, nil
}
// Top level function to execute remote direct based on remote type
func DoRemoteDirect(settings *environment.AirshipCTLSettings) error {
remoteConfig, remoteURL, err := getRemoteDirectConfig(settings)
if err != nil {
return err
}
client, err := getRemoteDirectClient(remoteConfig, remoteURL)
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
}