Skip to content

Commit 5cdb882

Browse files
authored
Add detaching suffix to vm.status.volumes (#1320)
For batchAttachment workflow, CSI now adds `:detaching` suffix to volume name when a volume is being detached. But it only adds it once it finished a detaching request to CNS, which could take up to minutes. This means there is a time period that the volume is not in vm.spec.volumes but still in batchAttachment.status.volumes, we still want to capture those volumes' status inside vm.status.volumes.
1 parent 6b51a69 commit 5cdb882

File tree

3 files changed

+78
-22
lines changed

3 files changed

+78
-22
lines changed

controllers/virtualmachine/volumebatch/volumebatch_controller.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
storagev1 "k8s.io/api/storage/v1"
1717
apierrors "k8s.io/apimachinery/pkg/api/errors"
1818
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19+
"k8s.io/apimachinery/pkg/util/sets"
1920
storagehelpers "k8s.io/component-helpers/storage/volume"
2021
ctrl "sigs.k8s.io/controller-runtime"
2122
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -45,7 +46,10 @@ import (
4546
const (
4647
controllerName = "volumebatch"
4748
// In BatchAttachment status, CSI hardcode a volume name entry with :detaching
48-
// suffix if it's being detached.
49+
// suffix if it's being detached. CSI only adds that after they have finsihed
50+
// a CNS detach call, which could take up to minutes. So we still want to add
51+
// that suffix ourselves as soon as a volume is removed from vm.spec.volumes.
52+
//
4953
// Note: The reason why we have this suffix is because there is a case that
5054
// a volume's PVC was changed, that means we need to detach current vol,
5155
// and attach another one. But since volume name is unique, and there is a
@@ -655,6 +659,7 @@ func (r *Reconciler) getVMVolStatusesFromBatchAttachment(
655659
volumeStatuses = append(volumeStatuses,
656660
getVolumeStatusWithDetachingVolumeFromBatchAttachment(
657661
existingAttachVolStatus,
662+
volumeSpecs,
658663
)...,
659664
)
660665

@@ -920,12 +925,23 @@ func getVolumeStatusesWithDetachingVolumeInLegacyAttachment(
920925
// These volumes that are being detached all has same suffix ':detaching'.
921926
func getVolumeStatusWithDetachingVolumeFromBatchAttachment(
922927
existingAttachVolStatus map[string]cnsv1alpha1.VolumeStatus,
928+
volumeSpecs []cnsv1alpha1.VolumeSpec,
923929
) []vmopv1.VirtualMachineVolumeStatus {
930+
924931
volumeStatuses := []vmopv1.VirtualMachineVolumeStatus{}
925932

933+
attachVolSpecNames := sets.New[string]()
934+
for _, volSpecs := range volumeSpecs {
935+
attachVolSpecNames.Insert(volSpecs.Name)
936+
}
937+
926938
for _, volStatus := range existingAttachVolStatus {
927939
volName := volStatus.Name
928-
if strings.HasSuffix(volName, volumeNameDetachSuffix) {
940+
if !attachVolSpecNames.Has(volName) {
941+
// Append suffix if it's not added by CSI yet.
942+
if !strings.HasSuffix(volName, volumeNameDetachSuffix) {
943+
volName += volumeNameDetachSuffix
944+
}
929945
volumeStatuses = append(volumeStatuses,
930946
attachmentStatusToVolumeStatus(volName, volStatus),
931947
)
@@ -972,7 +988,7 @@ func (r *Reconciler) getVMVolStatusesFromLegacyAttachments(
972988
) []vmopv1.VirtualMachineVolumeStatus {
973989

974990
volumeStatuses := []vmopv1.VirtualMachineVolumeStatus{}
975-
// Maintain the mapping of AttachmentName -> Attachment.
991+
// Maintain the mapping of LegacyAttachmentName -> Attachment.
976992
orphanedAttachmentsMap := make(map[string]cnsv1alpha1.CnsNodeVmAttachment)
977993
for _, o := range orphanedAttachments {
978994
orphanedAttachmentsMap[o.Name] = o
@@ -1095,7 +1111,7 @@ func categorizeVolumeSpecs(
10951111
}
10961112

10971113
// Only include greenfield volumes that are not tracked by
1098-
// legacy CnsNodeVmAttachment
1114+
// legacy CnsNodeVmAttachment or those whose PVCs have been changed.
10991115
volumeSpecsForBatch = append(volumeSpecsForBatch, vol)
11001116
}
11011117
return volumeSpecsForBatch, volumeSpecsForLegacy

controllers/virtualmachine/volumebatch/volumebatch_controller_intg_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,13 @@ func intgTestsReconcile() {
427427
Expect(ctx.Client.Update(ctx, vm)).To(Succeed())
428428
})
429429

430-
By("VM Status.Volumes should still only have entry for volume volume2", func() {
430+
By("VM Status.Volumes should still have entries for volume1 and volume2", func() {
431431
// I'm not sure if we have a better way to check for this.
432432
Eventually(func(g Gomega) {
433433
vm = getVirtualMachine(vmKey)
434434
g.Expect(vm).ToNot(BeNil())
435-
g.Expect(vm.Status.Volumes).To(HaveLen(1))
436-
}).Should(Succeed())
435+
g.Expect(vm.Status.Volumes).To(HaveLen(2))
436+
}, "3s").Should(Succeed())
437437
})
438438
})
439439
})

controllers/virtualmachine/volumebatch/volumebatch_controller_unit_test.go

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ FaultMessage: ([]vimtypes.LocalizableMessage) \u003cnil\u003e\\n }\\n },\\n Type
866866
Expect(vm.Status.Volumes).To(HaveLen(1))
867867
Expect(attachment.Status.VolumeStatus).To(HaveLen(1))
868868
attachment.Status.VolumeStatus[0].PersistentVolumeClaim.Error = "failed to attach cns volume"
869-
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 0)
869+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 0, false)
870870
})
871871
})
872872
})
@@ -941,8 +941,8 @@ FaultMessage: ([]vimtypes.LocalizableMessage) \u003cnil\u003e\\n }\\n },\\n Type
941941
By("VM Status.Volumes are stable-sorted by Spec.Volumes order", func() {
942942
Expect(vm.Status.Volumes).To(HaveLen(2))
943943
Expect(attachment.Status.VolumeStatus).To(HaveLen(2))
944-
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 1, 0)
945-
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 1)
944+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 1, 0, false)
945+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 1, false)
946946
})
947947
})
948948

@@ -997,8 +997,8 @@ FaultMessage: ([]vimtypes.LocalizableMessage) \u003cnil\u003e\\n }\\n },\\n Type
997997
Expect(vm.Status.Volumes[0]).To(Equal(classicDisk1()))
998998
Expect(vm.Status.Volumes[1]).To(Equal(classicDisk2()))
999999

1000-
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 2, 1)
1001-
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 3, 0)
1000+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 2, 1, false)
1001+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 3, 0, false)
10021002
})
10031003
}
10041004

@@ -1393,10 +1393,45 @@ FaultMessage: ([]vimtypes.LocalizableMessage) \u003cnil\u003e\\n }\\n },\\n Type
13931393

13941394
By("VM Status.Volumes should contain the volume with detaching suffix", func() {
13951395
Expect(vm.Status.Volumes).To(HaveLen(1))
1396-
Expect(vm.Status.Volumes[0].Name).To(Equal(volumeName1 + detachingVolumeSuffix))
1397-
Expect(vm.Status.Volumes[0].Attached).To(BeTrue())
1398-
Expect(vm.Status.Volumes[0].DiskUUID).To(Equal(dummyDiskUUID))
1399-
Expect(vm.Status.Volumes[0].Type).To(Equal(vmopv1.VolumeTypeManaged))
1396+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 0, false)
1397+
})
1398+
})
1399+
})
1400+
1401+
When("Volumes are just being detached and CnsNodeVMBatchAttachment's status has been cleared by CSI yet", func() {
1402+
BeforeEach(func() {
1403+
attachment.Status.VolumeStatus = append(attachment.Status.VolumeStatus,
1404+
cnsv1alpha1.VolumeStatus{
1405+
Name: volumeName1 + detachingVolumeSuffix,
1406+
PersistentVolumeClaim: cnsv1alpha1.PersistentVolumeClaimStatus{
1407+
ClaimName: claimName1,
1408+
Attached: false,
1409+
DiskUUID: dummyDiskUUID,
1410+
},
1411+
},
1412+
cnsv1alpha1.VolumeStatus{
1413+
Name: volumeName2,
1414+
PersistentVolumeClaim: cnsv1alpha1.PersistentVolumeClaimStatus{
1415+
ClaimName: claimName2,
1416+
Attached: true,
1417+
DiskUUID: dummyDiskUUID,
1418+
},
1419+
},
1420+
)
1421+
initObjects = append(initObjects, attachment)
1422+
})
1423+
It("returns success and refresh the vm volume status", func() {
1424+
err := reconciler.ReconcileNormal(volCtx)
1425+
Expect(err).ToNot(HaveOccurred())
1426+
1427+
attachment := getCNSBatchAttachmentForVolumeName(ctx, vm)
1428+
Expect(attachment).ToNot(BeNil())
1429+
Expect(attachment.Spec.Volumes).To(HaveLen(0))
1430+
1431+
By("VM Status.Volumes should contain the volume with detaching suffix", func() {
1432+
Expect(vm.Status.Volumes).To(HaveLen(2))
1433+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 0, 0, false)
1434+
assertVMVolStatusFromBatchAttachmentStatus(vm, attachment, 1, 1, true)
14001435
})
14011436
})
14021437
})
@@ -1476,17 +1511,22 @@ func assertVMVolStatusFromBatchAttachmentStatus(
14761511
vm *vmopv1.VirtualMachine,
14771512
attachment *cnsv1alpha1.CnsNodeVMBatchAttachment,
14781513
vmVolStatusIndex,
1479-
attachmentStatusIndex int) {
1514+
attachmentStatusIndex int,
1515+
detachingSuffix bool) {
14801516

14811517
GinkgoHelper()
14821518

1483-
Expect(len(vm.Status.Volumes) > vmVolStatusIndex).To(BeTrue(), fmt.Sprintf("vm volume status should have len larger than %d", vmVolStatusIndex))
1519+
Expect(len(vm.Status.Volumes)).To(BeNumerically(">", vmVolStatusIndex), fmt.Sprintf("vm volume status should have len larger than %d", vmVolStatusIndex))
14841520
vmVolStatus := vm.Status.Volumes[vmVolStatusIndex]
1485-
Expect(len(attachment.Status.VolumeStatus) > attachmentStatusIndex).To(BeTrue(), fmt.Sprintf("attachment volume status should have len larger than %d", attachmentStatusIndex))
1521+
Expect(len(attachment.Status.VolumeStatus)).To(BeNumerically(">", attachmentStatusIndex), fmt.Sprintf("attachment volume status should have len larger than %d", attachmentStatusIndex))
14861522
attachmentVolStatus := attachment.Status.VolumeStatus[attachmentStatusIndex]
14871523

1524+
volName := attachmentVolStatus.Name
1525+
if detachingSuffix {
1526+
volName = attachmentVolStatus.Name + ":detaching"
1527+
}
1528+
Expect(vmVolStatus.Name).To(Equal(volName), "volume name should match")
14881529
Expect(vmVolStatus.Type).To(Equal(vmopv1.VolumeTypeManaged), "type should match")
1489-
Expect(vmVolStatus.Name).To(Equal(attachmentVolStatus.Name), "volume name should match")
14901530
Expect(vmVolStatus.Attached).To(Equal(attachmentVolStatus.PersistentVolumeClaim.Attached), "attached should match")
14911531
Expect(vmVolStatus.DiskUUID).To(Equal(attachmentVolStatus.PersistentVolumeClaim.DiskUUID), "diskuuid should match")
14921532
Expect(vmVolStatus.Error).To(Equal(attachmentVolStatus.PersistentVolumeClaim.Error), "error shouuld match")
@@ -1500,9 +1540,9 @@ func assertVMVolStatusFromBatchAttachmentSpec(
15001540

15011541
GinkgoHelper()
15021542

1503-
Expect(len(vm.Status.Volumes) > vmVolStatusIndex).To(BeTrue(), fmt.Sprintf("vm volume status should have len larger than %d", vmVolStatusIndex))
1543+
Expect(len(vm.Status.Volumes)).To(BeNumerically(">", vmVolStatusIndex), fmt.Sprintf("vm volume status should have len larger than %d", vmVolStatusIndex))
15041544
vmVolStatus := vm.Status.Volumes[vmVolStatusIndex]
1505-
Expect(len(attachment.Spec.Volumes) > attachmentStatusIndex).To(BeTrue(), fmt.Sprintf("attachment volume spec should have len larger than %d", attachmentStatusIndex))
1545+
Expect(len(attachment.Spec.Volumes)).To(BeNumerically(">", attachmentStatusIndex), fmt.Sprintf("attachment volume spec should have len larger than %d", attachmentStatusIndex))
15061546
attachmentVolSpec := attachment.Spec.Volumes[attachmentStatusIndex]
15071547

15081548
Expect(vmVolStatus.Type).To(Equal(vmopv1.VolumeTypeManaged), "type should match")

0 commit comments

Comments
 (0)