From fdad9efe9e90ae99841ccfab3ecceb404c405fde Mon Sep 17 00:00:00 2001 From: Sid Shukla Date: Tue, 13 Aug 2024 20:29:45 +0200 Subject: [PATCH] fix(controller): Use v3 VM VG Reference for v4 detachVGFromVM AOS 6.5 does not support v4 VMM APIs but does support v4 volume group APIs. --- controllers/helpers.go | 27 ++++-------- controllers/nutanixmachine_controller.go | 8 ++-- controllers/nutanixmachine_controller_test.go | 42 ++++++++++++++----- 3 files changed, 42 insertions(+), 35 deletions(-) diff --git a/controllers/helpers.go b/controllers/helpers.go index 6fa6ff6932..dea544c511 100644 --- a/controllers/helpers.go +++ b/controllers/helpers.go @@ -31,7 +31,6 @@ import ( prismclientv4 "github.com/nutanix-cloud-native/prism-go-client/v4" prismcommonconfig "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/common/v1/config" prismapi "github.com/nutanix/ntnx-api-golang-clients/prism-go-client/v4/models/prism/v4/config" - vmconfig "github.com/nutanix/ntnx-api-golang-clients/vmm-go-client/v4/models/vmm/v4/ahv/config" prismconfig "github.com/nutanix/ntnx-api-golang-clients/volumes-go-client/v4/models/prism/v4/config" volumesconfig "github.com/nutanix/ntnx-api-golang-clients/volumes-go-client/v4/models/volumes/v4/config" "k8s.io/apimachinery/pkg/api/resource" @@ -878,38 +877,26 @@ func getPrismCentralVersion(ctx context.Context, v3Client *prismclientv3.Client) return *pcInfo.Resources.Version, nil } -func detachVolumeGroupsFromVM(ctx context.Context, v4Client *prismclientv4.Client, vmUUID string) error { +func detachVolumeGroupsFromVM(ctx context.Context, v4Client *prismclientv4.Client, vm *prismclientv3.VMIntentResponse) error { log := ctrl.LoggerFrom(ctx) - vmResp, err := v4Client.VmApiInstance.GetVmById(&vmUUID) - if err != nil { - return fmt.Errorf("failed to get virtual machine: %w", err) - } - - data := vmResp.GetData() - vm, ok := data.(vmconfig.Vm) - if !ok { - return fmt.Errorf("failed to cast response to VM") - } - volumeGroupsToDetach := make([]string, 0) - for _, disk := range vm.Disks { - backingInfo, ok := disk.GetBackingInfo().(vmconfig.ADSFVolumeGroupReference) - if !ok { + for _, disk := range vm.Spec.Resources.DiskList { + if disk.VolumeGroupReference == nil { continue } - volumeGroupsToDetach = append(volumeGroupsToDetach, *backingInfo.VolumeGroupExtId) + volumeGroupsToDetach = append(volumeGroupsToDetach, *disk.VolumeGroupReference.UUID) } // Detach the volume groups from the virtual machine for _, volumeGroup := range volumeGroupsToDetach { - log.Info(fmt.Sprintf("detaching volume group %s from virtual machine %s", volumeGroup, vmUUID)) + log.Info(fmt.Sprintf("detaching volume group %s from virtual machine %s", volumeGroup, *vm.Metadata.Name)) body := &volumesconfig.VmAttachment{ - ExtId: &vmUUID, + ExtId: vm.Metadata.UUID, } resp, err := v4Client.VolumeGroupsApiInstance.DetachVm(&volumeGroup, body) if err != nil { - return fmt.Errorf("failed to detach volume group %s from virtual machine %s: %w", volumeGroup, vmUUID, err) + return fmt.Errorf("failed to detach volume group %s from virtual machine %s: %w", volumeGroup, *vm.Metadata.UUID, err) } data := resp.GetData() diff --git a/controllers/nutanixmachine_controller.go b/controllers/nutanixmachine_controller.go index 7fa05fd945..6eb2e68a90 100644 --- a/controllers/nutanixmachine_controller.go +++ b/controllers/nutanixmachine_controller.go @@ -379,7 +379,7 @@ func (r *NutanixMachineReconciler) reconcileDelete(rctx *nctx.MachineContext) (r } if vgDetachNeeded { - if err := r.detachVolumeGroups(rctx, vmUUID); err != nil { + if err := r.detachVolumeGroups(rctx, vm); err != nil { err := fmt.Errorf("failed to detach volume groups from VM %s with UUID %s: %v", vmName, vmUUID, err) log.Error(err, "failed to detach volume groups from VM") conditions.MarkFalse(rctx.NutanixMachine, infrav1.VMProvisionedCondition, infrav1.VolumeGroupDetachFailed, capiv1.ConditionSeverityWarning, err.Error()) @@ -401,7 +401,7 @@ func (r *NutanixMachineReconciler) reconcileDelete(rctx *nctx.MachineContext) (r return reconcile.Result{RequeueAfter: 5 * time.Second}, nil } -func (r *NutanixMachineReconciler) detachVolumeGroups(rctx *nctx.MachineContext, vmUUID string) error { +func (r *NutanixMachineReconciler) detachVolumeGroups(rctx *nctx.MachineContext, vm *prismclientv3.VMIntentResponse) error { createV4Client, err := isPrismCentralV4Compatible(rctx.Context, rctx.NutanixClient) if err != nil { return fmt.Errorf("error occurred while checking compatibility for Prism Central v4 APIs: %w", err) @@ -416,8 +416,8 @@ func (r *NutanixMachineReconciler) detachVolumeGroups(rctx *nctx.MachineContext, return fmt.Errorf("error occurred while fetching Prism Central v4 client: %w", err) } - if err := detachVolumeGroupsFromVM(rctx.Context, v4Client, vmUUID); err != nil { - return fmt.Errorf("failed to detach volume groups from VM %s with UUID %s: %w", rctx.Machine.Name, vmUUID, err) + if err := detachVolumeGroupsFromVM(rctx.Context, v4Client, vm); err != nil { + return fmt.Errorf("failed to detach volume groups from VM %s with UUID %s: %w", rctx.Machine.Name, *vm.Metadata.UUID, err) } return nil diff --git a/controllers/nutanixmachine_controller_test.go b/controllers/nutanixmachine_controller_test.go index ba4e0bba09..00031fa014 100644 --- a/controllers/nutanixmachine_controller_test.go +++ b/controllers/nutanixmachine_controller_test.go @@ -23,7 +23,7 @@ import ( "github.com/golang/mock/gomock" credentialTypes "github.com/nutanix-cloud-native/prism-go-client/environment/credentials" - v3 "github.com/nutanix-cloud-native/prism-go-client/v3" + prismclientv3 "github.com/nutanix-cloud-native/prism-go-client/v3" "github.com/nutanix-cloud-native/prism-go-client/v3/models" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -246,12 +246,16 @@ func TestNutanixMachineReconciler(t *testing.T) { mockv3Service := mocknutanixv3.NewMockService(mockctrl) mockv3Service.EXPECT().GetPrismCentral(gomock.Any()).Return(nil, errors.New("error")) - v3Client := &v3.Client{ + v3Client := &prismclientv3.Client{ V3: mockv3Service, } err := reconciler.detachVolumeGroups(&nctx.MachineContext{ NutanixClient: v3Client, - }, ntnxMachine.Status.VmUUID) + }, &prismclientv3.VMIntentResponse{ + Metadata: &prismclientv3.Metadata{ + UUID: &ntnxMachine.Status.VmUUID, + }, + }) g.Expect(err).To(HaveOccurred()) }) @@ -262,12 +266,16 @@ func TestNutanixMachineReconciler(t *testing.T) { Version: ptr.To(""), }}, nil) - v3Client := &v3.Client{ + v3Client := &prismclientv3.Client{ V3: mockv3Service, } err := reconciler.detachVolumeGroups(&nctx.MachineContext{ NutanixClient: v3Client, - }, ntnxMachine.Status.VmUUID) + }, &prismclientv3.VMIntentResponse{ + Metadata: &prismclientv3.Metadata{ + UUID: &ntnxMachine.Status.VmUUID, + }, + }) g.Expect(err).To(HaveOccurred()) }) @@ -278,12 +286,16 @@ func TestNutanixMachineReconciler(t *testing.T) { Version: ptr.To("pc."), }}, nil) - v3Client := &v3.Client{ + v3Client := &prismclientv3.Client{ V3: mockv3Service, } err := reconciler.detachVolumeGroups(&nctx.MachineContext{ NutanixClient: v3Client, - }, ntnxMachine.Status.VmUUID) + }, &prismclientv3.VMIntentResponse{ + Metadata: &prismclientv3.Metadata{ + UUID: &ntnxMachine.Status.VmUUID, + }, + }) g.Expect(err).To(HaveOccurred()) }) @@ -294,12 +306,16 @@ func TestNutanixMachineReconciler(t *testing.T) { Version: ptr.To("not.a.valid.version"), }}, nil) - v3Client := &v3.Client{ + v3Client := &prismclientv3.Client{ V3: mockv3Service, } err := reconciler.detachVolumeGroups(&nctx.MachineContext{ NutanixClient: v3Client, - }, ntnxMachine.Status.VmUUID) + }, &prismclientv3.VMIntentResponse{ + Metadata: &prismclientv3.Metadata{ + UUID: &ntnxMachine.Status.VmUUID, + }, + }) g.Expect(err).To(HaveOccurred()) }) @@ -310,12 +326,16 @@ func TestNutanixMachineReconciler(t *testing.T) { Version: ptr.To("pc.2023.4.0.1"), }}, nil) - v3Client := &v3.Client{ + v3Client := &prismclientv3.Client{ V3: mockv3Service, } err := reconciler.detachVolumeGroups(&nctx.MachineContext{ NutanixClient: v3Client, - }, ntnxMachine.Status.VmUUID) + }, &prismclientv3.VMIntentResponse{ + Metadata: &prismclientv3.Metadata{ + UUID: &ntnxMachine.Status.VmUUID, + }, + }) g.Expect(err).To(Not(HaveOccurred())) }) })