diff --git a/pkg/controller/plan/adapter/ovirt/BUILD.bazel b/pkg/controller/plan/adapter/ovirt/BUILD.bazel index 5d0a9904a..4a7d0a624 100644 --- a/pkg/controller/plan/adapter/ovirt/BUILD.bazel +++ b/pkg/controller/plan/adapter/ovirt/BUILD.bazel @@ -33,12 +33,12 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/errors", "//vendor/k8s.io/apimachinery/pkg/api/resource", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", "//vendor/k8s.io/apimachinery/pkg/labels", "//vendor/k8s.io/apimachinery/pkg/runtime", "//vendor/k8s.io/apimachinery/pkg/runtime/schema", "//vendor/k8s.io/apimachinery/pkg/types", "//vendor/k8s.io/client-go/dynamic", - "//vendor/k8s.io/client-go/kubernetes", "//vendor/kubevirt.io/api/core/v1:core", "//vendor/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1", "//vendor/sigs.k8s.io/controller-runtime/pkg/client", diff --git a/pkg/controller/plan/adapter/ovirt/builder.go b/pkg/controller/plan/adapter/ovirt/builder.go index c01494489..1d697cbde 100644 --- a/pkg/controller/plan/adapter/ovirt/builder.go +++ b/pkg/controller/plan/adapter/ovirt/builder.go @@ -10,11 +10,12 @@ import ( "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1" api "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1" - ocpclient "github.com/konveyor/forklift-controller/pkg/lib/client/openshift" meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/kubernetes" + "k8s.io/client-go/dynamic" "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/plan" "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/ref" @@ -24,6 +25,7 @@ import ( "github.com/konveyor/forklift-controller/pkg/controller/provider/web/base" "github.com/konveyor/forklift-controller/pkg/controller/provider/web/ocp" model "github.com/konveyor/forklift-controller/pkg/controller/provider/web/ovirt" + ocpclient "github.com/konveyor/forklift-controller/pkg/lib/client/openshift" liberr "github.com/konveyor/forklift-controller/pkg/lib/error" libitr "github.com/konveyor/forklift-controller/pkg/lib/itinerary" core "k8s.io/api/core/v1" @@ -768,51 +770,56 @@ func (r *Builder) mapStorageDomainToStorageClass() (map[string]string, error) { return sdToStorageClass, nil } +// Get the OvirtVolumePopulator CustomResource based on the disk ID. // Get the OvirtVolumePopulator CustomResource based on the disk ID. func (r *Builder) getVolumePopulator(diskID string) (populatorCr api.OvirtVolumePopulator, err error) { - apiGroup, err := r.calculateAPIGroup() + gvk, err := utils.CalculateAPIGroup(v1beta1.OvirtVolumePopulatorKind, r.Destination.Provider, r.Plan.Secret) + if err != nil { + err = liberr.Wrap(err) + return + } + + dynamicClient, err := dynamic.NewForConfig(ocpclient.RestCfg(r.Destination.Provider, r.Plan.Secret)) if err != nil { err = liberr.Wrap(err) return } - gvk := schema.GroupVersionKind{ - Group: apiGroup, - Version: "v1", // Adjust the version if necessary - Kind: "OvirtVolumePopulatorList", + resource := schema.GroupVersionResource{ + Group: gvk.Group, + Version: gvk.Version, + Resource: "ovirtvolumepopulators", } - r.Log.Info("Benny OvirtVolumePopulatorList", "apiGroup", apiGroup, "gvk", gvk) - list := api.OvirtVolumePopulatorList{} - err = r.Destination.Client.List(context.TODO(), &list, &client.ListOptions{ - Namespace: r.Plan.Spec.TargetNamespace, + listOptions := meta.ListOptions{ LabelSelector: labels.SelectorFromSet(map[string]string{ "migration": string(r.Migration.UID), "diskID": diskID, - }), - Raw: &meta.ListOptions{ - TypeMeta: meta.TypeMeta{ - APIVersion: gvk.GroupVersion().String(), - Kind: gvk.Kind, - }, - }, - }) + }).String(), + } + + unstructuredList, err := dynamicClient.Resource(resource).Namespace(r.Plan.Spec.TargetNamespace).List(context.TODO(), listOptions) if err != nil { err = liberr.Wrap(err) return } - r.Log.Info("using API group", "apiGroup", apiGroup) - if len(list.Items) == 0 { - err = k8serr.NewNotFound(api.SchemeGroupVersion.WithResource("OvirtVolumePopulator").GroupResource(), diskID) + if len(unstructuredList.Items) == 0 { + err = k8serr.NewNotFound(api.SchemeGroupVersion.WithResource(v1beta1.OvirtVolumePopulatorKind).GroupResource(), diskID) return } - if len(list.Items) > 1 { + if len(unstructuredList.Items) > 1 { err = liberr.New("Multiple OvirtVolumePopulator CRs found for the same disk", "diskID", diskID) return } - populatorCr = list.Items[0] + // Convert the unstructured object to the structured type + populatorCr = api.OvirtVolumePopulator{} + err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredList.Items[0].UnstructuredContent(), &populatorCr) + if err != nil { + err = liberr.Wrap(err) + return + } return } @@ -829,17 +836,16 @@ func (r *Builder) createVolumePopulatorCR(diskAttachment model.XDiskAttachment, Host: providerURL.Host, } - apiGroup, err := r.calculateAPIGroup() + gvk, err := utils.CalculateAPIGroup(v1beta1.OvirtVolumePopulatorKind, r.Destination.Provider, r.Plan.Secret) if err != nil { err = liberr.Wrap(err) return } - r.Log.Info("using API group", "apiGroup", apiGroup) populatorCR := &api.OvirtVolumePopulator{ TypeMeta: meta.TypeMeta{ - Kind: api.OvirtVolumePopulatorKind, - APIVersion: apiGroup, + Kind: gvk.Kind, + APIVersion: gvk.GroupVersion().String(), }, ObjectMeta: meta.ObjectMeta{ GenerateName: fmt.Sprintf("%s-", diskAttachment.DiskAttachment.ID), @@ -857,13 +863,37 @@ func (r *Builder) createVolumePopulatorCR(diskAttachment model.XDiskAttachment, TransferNetwork: r.Plan.Spec.TransferNetwork, }, } - err = r.Context.Client.Create(context.TODO(), populatorCR, &client.CreateOptions{}) + + // Convert the structured object to an unstructured object + unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(populatorCR) + if err != nil { + err = liberr.Wrap(err) + return + } + unstructuredObj := &unstructured.Unstructured{ + Object: unstructuredMap, + } + + dynamicClient, err := dynamic.NewForConfig(ocpclient.RestCfg(r.Destination.Provider, r.Plan.Secret)) if err != nil { err = liberr.Wrap(err) return } - name = populatorCR.Name + resource := schema.GroupVersionResource{ + Group: gvk.Group, + Version: gvk.Version, + Resource: "ovirtvolumepopulators", // Use the plural form of the resource + } + + r.Log.Info("Creating OvirtVolumePopulator", "populatorCR", populatorCR) + unstructuredResult, err := dynamicClient.Resource(resource).Namespace(r.Plan.Spec.TargetNamespace).Create(context.TODO(), unstructuredObj, meta.CreateOptions{}) + if err != nil { + err = liberr.Wrap(err) + return + } + + name = unstructuredResult.GetName() return } @@ -911,14 +941,12 @@ func (r *Builder) persistentVolumeClaimWithSourceRef(diskAttachment model.XDiskA annotations[planbase.AnnDiskSource] = diskAttachment.ID - apiGroup, err := r.calculateAPIGroup() + gvk, err := utils.CalculateAPIGroup(v1beta1.OvirtVolumePopulatorKind, r.Destination.Provider, r.Plan.Secret) if err != nil { err = liberr.Wrap(err) return } - r.Log.Info("using API group", "apiGroup", apiGroup) - pvc = &core.PersistentVolumeClaim{ ObjectMeta: meta.ObjectMeta{ GenerateName: fmt.Sprintf("%s-", diskAttachment.DiskAttachment.ID), @@ -939,7 +967,7 @@ func (r *Builder) persistentVolumeClaimWithSourceRef(diskAttachment model.XDiskA StorageClassName: &storageClassName, VolumeMode: volumeMode, DataSourceRef: &core.TypedObjectReference{ - APIGroup: &apiGroup, + APIGroup: &gvk.Group, Kind: v1beta1.OvirtVolumePopulatorKind, Name: populatorName, }, @@ -950,38 +978,6 @@ func (r *Builder) persistentVolumeClaimWithSourceRef(diskAttachment model.XDiskA return } -func (r *Builder) calculateAPIGroup() (string, error) { - // If OCP version is >= 4.16 use forklift.cdi.konveyor.io - // Otherwise use forklift.konveyor.io - restCfg := ocpclient.RestCfg(r.Source.Provider, r.Plan.Referenced.Secret) - clientset, err := kubernetes.NewForConfig(restCfg) - if err != nil { - return "", liberr.Wrap(err) - } - - discoveryClient := clientset.Discovery() - version, err := discoveryClient.ServerVersion() - if err != nil { - return "", liberr.Wrap(err) - } - - major, err := strconv.Atoi(version.Major) - if err != nil { - return "", liberr.Wrap(err) - } - - minor, err := strconv.Atoi(version.Minor) - if err != nil { - return "", liberr.Wrap(err) - } - - if major < 1 || (major == 1 && minor <= 28) { - return "forklift.konveyor.io", nil - } - - return "forklift.cdi.konveyor.io", nil -} - func (r *Builder) PopulatorTransferredBytes(pvc *core.PersistentVolumeClaim) (transferredBytes int64, err error) { if _, ok := pvc.Annotations["lun"]; ok { // skip LUNs diff --git a/pkg/controller/plan/adapter/ovirt/destinationclient.go b/pkg/controller/plan/adapter/ovirt/destinationclient.go index a76979981..5543cc00b 100644 --- a/pkg/controller/plan/adapter/ovirt/destinationclient.go +++ b/pkg/controller/plan/adapter/ovirt/destinationclient.go @@ -3,11 +3,11 @@ package ovirt import ( "context" "path" - "strconv" "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1" "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/plan" plancontext "github.com/konveyor/forklift-controller/pkg/controller/plan/context" + utils "github.com/konveyor/forklift-controller/pkg/controller/plan/util" ocpclient "github.com/konveyor/forklift-controller/pkg/lib/client/openshift" liberr "github.com/konveyor/forklift-controller/pkg/lib/error" core "k8s.io/api/core/v1" @@ -17,7 +17,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" - "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/client" k8sutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) @@ -70,56 +69,14 @@ func (r *DestinationClient) SetPopulatorCrOwnership() (err error) { return } -func (r *DestinationClient) calculateAPIGroup(kind string) (*schema.GroupVersionKind, error) { - // If OCP version is >= 4.16 use forklift.cdi.konveyor.io - // Otherwise use forklift.konveyor.io - r.Log.Info("Benny calculateAPIGroup") - restCfg := ocpclient.RestCfg(r.Destination.Provider, r.Plan.Referenced.Secret) - r.Log.Info("Benny Rest", "restCfg", restCfg) - clientset, err := kubernetes.NewForConfig(restCfg) - if err != nil { - return nil, liberr.Wrap(err) - } - - r.Log.Info("Benny Before discoveryClient.ServerVersion()") - - discoveryClient := clientset.Discovery() - version, err := discoveryClient.ServerVersion() - if err != nil { - r.Log.Info("Benny ServerVersion() error", "error", err) - - return nil, liberr.Wrap(err) - } - - r.Log.Info("Benny calculateAPIGroup after discoveryClient.ServerVersion()") - - major, err := strconv.Atoi(version.Major) - if err != nil { - return nil, liberr.Wrap(err) - } - - minor, err := strconv.Atoi(version.Minor) - if err != nil { - return nil, liberr.Wrap(err) - } - - r.Log.Info("Benny calculateAPIGroup before return") - - if major < 1 || (major == 1 && minor <= 28) { - return &schema.GroupVersionKind{Group: "forklift.konveyor.io", Version: "v1beta1", Kind: kind}, nil - } - - return &schema.GroupVersionKind{Group: "forklift.cdi.konveyor.io", Version: "v1beta1", Kind: kind}, nil -} - // Get the OvirtVolumePopulator CustomResource List. // Get the OvirtVolumePopulator CustomResource List. func (r *DestinationClient) getPopulatorCrList() (populatorCrList v1beta1.OvirtVolumePopulatorList, err error) { r.Log.Info("Getting OvirtVolumePopulatorList") populatorCrList = v1beta1.OvirtVolumePopulatorList{} - gvk, err := r.calculateAPIGroup("OvirtVolumePopulator") + gvk, err := utils.CalculateAPIGroup("OvirtVolumePopulator", r.Destination.Provider, r.Plan.Referenced.Secret) if err != nil { - r.Log.Info("Error calculating API group", "error", err) + r.Log.Error(err, "Error calculating API group") return } r.Log.Info("API Group", "apiGroup", gvk) @@ -127,14 +84,14 @@ func (r *DestinationClient) getPopulatorCrList() (populatorCrList v1beta1.OvirtV // Create a dynamic client using the correct GVK dynamicClient, err := dynamic.NewForConfig(ocpclient.RestCfg(r.Destination.Provider, r.Plan.Referenced.Secret)) if err != nil { - r.Log.Info("Error creating dynamic client", "error", err) + r.Log.Error(err, "Error creating dynamic client") return } resource := schema.GroupVersionResource{ Group: gvk.Group, Version: gvk.Version, - Resource: "ovirtvolumepopulators", // Use the plural form of the resource + Resource: "ovirtvolumepopulators", } unstructuredList, err := dynamicClient.Resource(resource).Namespace(r.Plan.Spec.TargetNamespace).List(context.TODO(), meta.ListOptions{ @@ -152,7 +109,6 @@ func (r *DestinationClient) getPopulatorCrList() (populatorCrList v1beta1.OvirtV return } - r.Log.Info("Successfully retrieved OvirtVolumePopulator list") return } diff --git a/pkg/controller/plan/util/BUILD.bazel b/pkg/controller/plan/util/BUILD.bazel index 54588add3..048c2a825 100644 --- a/pkg/controller/plan/util/BUILD.bazel +++ b/pkg/controller/plan/util/BUILD.bazel @@ -13,8 +13,12 @@ go_library( "//pkg/apis/forklift/v1beta1", "//pkg/controller/provider/web/openstack", "//pkg/controller/provider/web/ovirt", + "//pkg/lib/client/openshift", + "//pkg/lib/error", "//pkg/settings", "//vendor/k8s.io/api/core/v1:core", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:meta", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema", + "//vendor/k8s.io/client-go/kubernetes", ], ) diff --git a/pkg/controller/plan/util/utils.go b/pkg/controller/plan/util/utils.go index dbafdf24c..adf7ad8ff 100644 --- a/pkg/controller/plan/util/utils.go +++ b/pkg/controller/plan/util/utils.go @@ -2,9 +2,16 @@ package util import ( "math" + "strconv" "github.com/konveyor/forklift-controller/pkg/settings" core "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/kubernetes" + + api "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1" + ocpclient "github.com/konveyor/forklift-controller/pkg/lib/client/openshift" + liberr "github.com/konveyor/forklift-controller/pkg/lib/error" ) // Disk alignment size used to align FS overhead, @@ -31,3 +38,35 @@ func CalculateSpaceWithOverhead(requestedSpace int64, volumeMode *core.Persisten } return spaceWithOverhead } + +func CalculateAPIGroup(kind string, provider *api.Provider, secret *core.Secret) (*schema.GroupVersionKind, error) { + // If OCP version is >= 4.16 use forklift.cdi.konveyor.io + // Otherwise use forklift.konveyor.io + restCfg := ocpclient.RestCfg(provider, secret) + clientset, err := kubernetes.NewForConfig(restCfg) + if err != nil { + return nil, liberr.Wrap(err) + } + + discoveryClient := clientset.Discovery() + version, err := discoveryClient.ServerVersion() + if err != nil { + return nil, liberr.Wrap(err) + } + + major, err := strconv.Atoi(version.Major) + if err != nil { + return nil, liberr.Wrap(err) + } + + minor, err := strconv.Atoi(version.Minor) + if err != nil { + return nil, liberr.Wrap(err) + } + + if major < 1 || (major == 1 && minor <= 28) { + return &schema.GroupVersionKind{Group: "forklift.konveyor.io", Version: "v1beta1", Kind: kind}, nil + } + + return &schema.GroupVersionKind{Group: "forklift.cdi.konveyor.io", Version: "v1beta1", Kind: kind}, nil +}