Skip to content

Commit

Permalink
fix(controller): Use v3 VM VG Reference for v4 detachVGFromVM
Browse files Browse the repository at this point in the history
AOS 6.5 does not support v4 VMM APIs but does support v4 volume group
APIs.
  • Loading branch information
thunderboltsid committed Aug 14, 2024
1 parent 237138a commit 5f4c671
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 36 deletions.
27 changes: 7 additions & 20 deletions controllers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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.Status.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()
Expand Down
8 changes: 4 additions & 4 deletions controllers/nutanixmachine_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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)
Expand All @@ -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
Expand Down
42 changes: 31 additions & 11 deletions controllers/nutanixmachine_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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())
})

Expand All @@ -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())
})

Expand All @@ -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())
})

Expand All @@ -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())
})

Expand All @@ -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()))
})
})
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/csi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ var _ = Describe("Nutanix flavor CSI", Label("capx-feature-test", "csi"), func()
Expect(workloadClient.Delete(ctx, csiPvc)).To(Succeed())
})

It("Create a cluster with Nutanix CSI 3.0 and use Nutanix Volumes to create PV and delete cluster without deleting PVC", Label("csi3"), func() {
It("Create a cluster with Nutanix CSI 3.0 and use Nutanix Volumes to create PV and delete cluster without deleting PVC", Label("csi30"), func() {
const flavor = "csi3"

Expect(namespace).NotTo(BeNil())
Expand Down

0 comments on commit 5f4c671

Please sign in to comment.