airshipctl/pkg/remote/remote_direct.go
Alan Meadows 28db50e6d6 [#45] iso generation pulls network data from ephemeral host
This commit updates the iso generation process to pull the
network data from the ephemeral host network data from the
baremetalhost spec of the host with the right label, namely:

airshipit.org/ephemeral-node=true

It will back into the secret name and namespace specified
for the given host and extract the network data from this
secret which should be identical to the network configuration
the host would receive during normal provisioning.

It also pulls the user-data for the iso generation process
which is specific to the iso generation process from a secret
with a similar special label:

airshipit.org/ephemeral-user-data=true

Change-Id: Iae6edeb231d9dbae0b316aa73009f145d57ac316
2020-03-11 19:07:14 +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"
)
const (
AirshipRemoteTypeRedfish string = "redfish"
AirshipRemoteTypeSmash string = "smash"
AirshipHostKind string = "BareMetalHost"
)
// Interface to be implemented by remoteDirect implementation
type Client interface {
DoRemoteDirect() error
}
// Get remotedirect client based on config
func getRemoteDirectClient(remoteConfig *config.RemoteDirect, remoteURL string) (Client, error) {
var client Client
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
}
remoteConfig := bootstrapSettings.RemoteDirect
if remoteConfig == nil {
return nil, "", config.ErrMissingConfig{What: "RemoteDirect options not defined in bootstrap config"}
}
// TODO (dukov) replace with the appropriate function once it's available
// in document module
docBundle, err := document.NewBundle(document.NewDocumentFs(), manifest.TargetPath, "")
if err != nil {
return nil, "", err
}
ls := document.EphemeralClusterSelector
selector := document.NewSelector().
ByGvk("", "", AirshipHostKind).
ByLabel(ls)
docs, err := docBundle.Select(selector)
if err != nil {
return nil, "", err
}
if len(docs) == 0 {
return nil, "", document.ErrDocNotFound{
Selector: selector,
}
}
// 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 remoteConfig, 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
}