diff --git a/pkg/asset/machines/powervs/images.go b/pkg/asset/machines/powervs/images.go new file mode 100644 index 00000000000..8830fc09504 --- /dev/null +++ b/pkg/asset/machines/powervs/images.go @@ -0,0 +1,74 @@ +package powervs + +import ( + "context" + "fmt" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/ibmpisession" + "github.com/IBM/go-sdk-core/v5/core" + "github.com/sirupsen/logrus" + + powervsconfig "github.com/openshift/installer/pkg/asset/installconfig/powervs" +) + +// GetBootImageFromWorkspace retrieves a boot image from the PowerVS workspace. +// If an active image is found in the workspace, it returns that image name. +// If no images are found, it returns a default name in the format "rhcos-{clusterID}". +func GetBootImageFromWorkspace(ctx context.Context, serviceInstanceGUID string, zone string, clusterID string) (string, error) { + // Create a new PowerVS client + client, err := powervsconfig.NewClient() + if err != nil { + return "", fmt.Errorf("failed to create PowerVS client: %w", err) + } + + // Create authenticator + authenticator := &core.IamAuthenticator{ + ApiKey: client.GetAPIKey(), + } + + // Create PI session + piSession, err := ibmpisession.NewIBMPISession(&ibmpisession.IBMPIOptions{ + Authenticator: authenticator, + UserAccount: client.BXCli.User.Account, + Zone: zone, + Debug: false, + }) + if err != nil { + return "", fmt.Errorf("failed to create PowerVS session: %w", err) + } + + // Create image client + imageClient := instance.NewIBMPIImageClient(ctx, piSession, serviceInstanceGUID) + if imageClient == nil { + return "", fmt.Errorf("failed to create PowerVS image client") + } + + // Get all images from the workspace + images, err := imageClient.GetAll() + if err != nil { + return "", fmt.Errorf("failed to list images from PowerVS workspace: %w", err) + } + + // If no images found in workspace, use default naming pattern + if images == nil || len(images.Images) == 0 { + defaultImage := fmt.Sprintf("rhcos-%s", clusterID) + logrus.Infof("No images found in PowerVS workspace, using default image name: %s", defaultImage) + return defaultImage, nil + } + + // Find the first active image + for _, image := range images.Images { + if image.State != nil && *image.State == "active" && image.Name != nil { + logrus.Infof("Selected PowerVS boot image from workspace: %s", *image.Name) + return *image.Name, nil + } + } + + // If no active images found, use default naming pattern + defaultImage := fmt.Sprintf("rhcos-%s", clusterID) + logrus.Infof("No active images found in PowerVS workspace, using default image name: %s", defaultImage) + return defaultImage, nil +} + +// Made with Bob diff --git a/pkg/asset/machines/powervs/machinesets.go b/pkg/asset/machines/powervs/machinesets.go index fa25c40cacf..3617943297d 100644 --- a/pkg/asset/machines/powervs/machinesets.go +++ b/pkg/asset/machines/powervs/machinesets.go @@ -2,8 +2,11 @@ package powervs import ( + "context" "fmt" + "time" + "github.com/sirupsen/logrus" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -25,7 +28,16 @@ func MachineSets(clusterID string, config *types.InstallConfig, pool *types.Mach platform := config.Platform.PowerVS mpool := pool.Platform.PowerVS var network string - image := fmt.Sprintf("rhcos-%s", clusterID) + + // Get the boot image from the PowerVS workspace, fallback to default if error occurs + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + image, err := GetBootImageFromWorkspace(ctx, config.PowerVS.ServiceInstanceGUID, config.PowerVS.Zone, clusterID) + if err != nil { + // Fallback to default image naming pattern + image = fmt.Sprintf("rhcos-%s", clusterID) + logrus.Warnf("Failed to get boot image from PowerVS workspace, using default: %s (error: %v)", image, err) + } total := int32(0) if pool.Replicas != nil { diff --git a/pkg/asset/machines/powervs/powervsmachines.go b/pkg/asset/machines/powervs/powervsmachines.go index 59fe92a1d2b..3c325f7a9fb 100644 --- a/pkg/asset/machines/powervs/powervsmachines.go +++ b/pkg/asset/machines/powervs/powervsmachines.go @@ -2,8 +2,11 @@ package powervs import ( + "context" "fmt" + "time" + "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -37,10 +40,18 @@ func GenerateMachines(clusterID string, ic *types.InstallConfig, pool *types.Mac powerVSMachine *capibm.IBMPowerVSMachine dataSecret string machine *capi.Machine + err error ) - // Note: This will be created later - image = fmt.Sprintf("rhcos-%s", clusterID) + // Get the boot image from the PowerVS workspace, fallback to default if error occurs + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + image, err = GetBootImageFromWorkspace(ctx, ic.PowerVS.ServiceInstanceGUID, ic.PowerVS.Zone, clusterID) + if err != nil { + // Fallback to default image naming pattern + image = fmt.Sprintf("rhcos-%s", clusterID) + logrus.Warnf("Failed to get boot image from PowerVS workspace, using default: %s (error: %v)", image, err) + } if ic.PowerVS.ServiceInstanceGUID == "" { serviceName := fmt.Sprintf("%s-power-iaas", clusterID) @@ -112,13 +123,11 @@ func GenerateMachine(ic *types.InstallConfig, service capibm.IBMPowerVSResourceR ServiceInstanceID: ic.PowerVS.ServiceInstanceGUID, ServiceInstance: &service, SSHKey: "", - ImageRef: &v1.LocalObjectReference{ - Name: image, - }, - SystemType: mpool.SysType, - ProcessorType: capibm.PowerVSProcessorType(mpool.ProcType), - Processors: mpool.Processors, - MemoryGiB: mpool.MemoryGiB, + Image: &capibm.IBMPowerVSResourceReference{Name: &image}, + SystemType: mpool.SysType, + ProcessorType: capibm.PowerVSProcessorType(mpool.ProcType), + Processors: mpool.Processors, + MemoryGiB: mpool.MemoryGiB, }, } utils.SetMachineOSStreamLabels(machine, ic)