@@ -138,6 +138,67 @@ func getVolumesToDetachFromInstance(ctx context.Context,
138138 return pvcsToDetach , nil
139139}
140140
141+ // getVolumesToAttach adds those PVCs to attach list which satisfy either of the following:
142+ // 1. The volumes which are present in instance spec but not in attachedFCDs list.
143+ // 2. The volumes which are present in instance spec and in attachedFCDs list but have different backing details.
144+ func getVolumesToAttach (ctx context.Context ,
145+ instance * v1alpha1.CnsNodeVMBatchAttachment ,
146+ attachedFCDs map [string ]FCDBackingDetails ,
147+ volumeIdsInSpec map [string ]FCDBackingDetails ,
148+ pvcNameToVolumeIDInSpec map [string ]string ) (pvcsToAttach map [string ]string , err error ) {
149+ log := logger .GetLogger (ctx )
150+
151+ // Map contains volumes which need to be attached.
152+ pvcsToAttach = make (map [string ]string )
153+
154+ pvcsInStatus := make (map [string ]bool )
155+ for _ , volumeStatus := range instance .Status .VolumeStatus {
156+ pvcsInStatus [volumeStatus .PersistentVolumeClaim .ClaimName ] = false
157+ if volumeStatus .PersistentVolumeClaim .Error != "" {
158+ pvcsInStatus [volumeStatus .PersistentVolumeClaim .ClaimName ] = true
159+ }
160+ }
161+
162+ /// Add those volumes to to pvcsToAttach
163+ // which are present in attachedFCDs list but not in
164+ // instance spec.
165+ for _ , pvc := range instance .Spec .Volumes {
166+ volumeIDForPVC , ok := pvcNameToVolumeIDInSpec [pvc .PersistentVolumeClaim .ClaimName ]
167+ if ! ok {
168+ msg := fmt .Sprintf ("failed to find volumeID for PVC %s" , pvc .PersistentVolumeClaim .ClaimName )
169+ log .Errorf (msg )
170+ err = errors .New (msg )
171+ return
172+ }
173+
174+ attachedFcdIDBacking , found := attachedFCDs [volumeIDForPVC ]
175+ if ! found {
176+ log .Infof ("PVC %s not attached to VM. Adding it to volumesToAttach list" ,
177+ pvc .PersistentVolumeClaim .ClaimName )
178+ // If PVC is present in instance spec but is not attached to the VM, then add it to PVCs to attach list.
179+ pvcsToAttach [pvc .PersistentVolumeClaim .ClaimName ] = volumeIDForPVC
180+ } else if * pvc .PersistentVolumeClaim .ControllerKey != attachedFcdIDBacking .ControllerKey ||
181+ * pvc .PersistentVolumeClaim .UnitNumber != attachedFcdIDBacking .UnitNumber ||
182+ string (pvc .PersistentVolumeClaim .SharingMode ) != attachedFcdIDBacking .SharingMode ||
183+ string (pvc .PersistentVolumeClaim .DiskMode ) != attachedFcdIDBacking .DiskMode {
184+ log .Infof ("PVC %s is attached to VM but its backing has changed. Adding it to volumesToAttach list" ,
185+ pvc .PersistentVolumeClaim .ClaimName )
186+ // If PVC is already attached to VM, but its device backing has changed, then add it to PVCs to attach list,
187+ // as it needs to be re-attached with new details.
188+ pvcsToAttach [pvc .PersistentVolumeClaim .ClaimName ] = volumeIDForPVC
189+ } else if hasError ,
190+ pvcExistsInStatus := pvcsInStatus [pvc .PersistentVolumeClaim .ClaimName ]; ! pvcExistsInStatus || hasError {
191+ log .Infof ("PVC %s is missing or is not successful in Status. Adding it to attach list." ,
192+ pvc .PersistentVolumeClaim .ClaimName )
193+ pvcsToAttach [pvc .PersistentVolumeClaim .ClaimName ] = volumeIDForPVC
194+ }
195+
196+ }
197+
198+ log .Infof ("Obtained volumes to attach %+v for instance %s" , pvcsToAttach , instance .Name )
199+ return pvcsToAttach , nil
200+ }
201+
141202// isSharedPvc returns true for PVCs which allow multi attach.
142203func isSharedPvc (pvcObj v1.PersistentVolumeClaim ) bool {
143204 for _ , accessMode := range pvcObj .Spec .AccessModes {
@@ -227,20 +288,16 @@ func getVolumesToDetachForVmFromVC(ctx context.Context,
227288 instance * v1alpha1.CnsNodeVMBatchAttachment ,
228289 client client.Client ,
229290 k8sClient kubernetes.Interface ,
230- attachedFCDs map [string ]FCDBackingDetails ) (map [string ]string , error ) {
291+ attachedFCDs map [string ]FCDBackingDetails ,
292+ volumeIdsInSpec map [string ]FCDBackingDetails ,
293+ volumeNamesInSpec map [string ]string ) (map [string ]string , error ) {
231294 log := logger .GetLogger (ctx )
232295
233296 pvcsToDetach := make (map [string ]string )
234- // Get all PVCs and their corresponding volumeID mapping from instance spec.
235- volumeIdsInSpec , volumeNamesInSpec , err := getVolumeNameVolumeIdMapsInSpec (ctx , instance )
236- if err != nil {
237- log .Errorf ("failed to get PVCs in spec. Err: %s" , err )
238- return pvcsToDetach , err
239- }
240297
241298 // Find out the volumes to detach by taking a diff between
242299 // the instance spec and the FCDs currently attached to the VM on vCenter.
243- pvcsToDetach , err = getVolumesToDetachFromInstance (ctx , instance , attachedFCDs , volumeIdsInSpec )
300+ pvcsToDetach , err : = getVolumesToDetachFromInstance (ctx , instance , attachedFCDs , volumeIdsInSpec )
244301 if err != nil {
245302 log .Errorf ("failed to find volumes to attach and volumes to detach from instance spec. Err: %s" , err )
246303 return pvcsToDetach , err
@@ -358,17 +415,21 @@ func deleteVolumeFromStatus(pvc string, instance *v1alpha1.CnsNodeVMBatchAttachm
358415 })
359416}
360417
361- // getVolumeNameVolumeIdMapsInSpec returns the volumes in instance spec.
362- // It return two maps:
418+ // getVolumeMetadataMaps returns the volumes in instance spec.
419+ // It returns three maps:
363420// 1. volumeID to PVC name
364421// 2. VolumeName to PVC name
365- func getVolumeNameVolumeIdMapsInSpec (ctx context.Context ,
422+ // 3. PVC name to volumeID
423+ func getVolumeMetadataMaps (ctx context.Context ,
366424 instance * v1alpha1.CnsNodeVMBatchAttachment ) (volumeIdsInSpec map [string ]FCDBackingDetails ,
367- volumeNamesInSpec map [string ]string , err error ) {
425+ volumeNamesInSpec map [string ]string ,
426+ pvcNameToVolumeIDInSpec map [string ]string ,
427+ err error ) {
368428 log := logger .GetLogger (ctx )
369429
370430 volumeIdsInSpec = make (map [string ]FCDBackingDetails )
371431 volumeNamesInSpec = make (map [string ]string )
432+ pvcNameToVolumeIDInSpec = make (map [string ]string )
372433 for _ , volume := range instance .Spec .Volumes {
373434 volumeId , ok := commonco .ContainerOrchestratorUtility .GetVolumeIDFromPVCName (
374435 instance .Namespace , volume .PersistentVolumeClaim .ClaimName )
@@ -378,9 +439,13 @@ func getVolumeNameVolumeIdMapsInSpec(ctx context.Context,
378439 err = errors .New (msg )
379440 return
380441 }
381- volumeIdsInSpec [volumeId ] = FCDBackingDetails {* volume .PersistentVolumeClaim .ControllerKey ,
382- * volume .PersistentVolumeClaim .UnitNumber ,
383- string (volume .PersistentVolumeClaim .SharingMode ), string (volume .PersistentVolumeClaim .DiskMode )}
442+ volumeNamesInSpec [volume .Name ] = volume .PersistentVolumeClaim .ClaimName
443+ volumeIdsInSpec [volumeId ] = FCDBackingDetails {
444+ ControllerKey : * volume .PersistentVolumeClaim .ControllerKey ,
445+ UnitNumber : * volume .PersistentVolumeClaim .UnitNumber ,
446+ SharingMode : string (volume .PersistentVolumeClaim .SharingMode ),
447+ DiskMode : string (volume .PersistentVolumeClaim .DiskMode )}
448+ pvcNameToVolumeIDInSpec [volume .PersistentVolumeClaim .ClaimName ] = volumeId
384449 }
385450 return
386451}
@@ -466,7 +531,11 @@ func listAttachedFcdsForVM(ctx context.Context,
466531 }
467532
468533 log .Infof ("Adding volume with ID %s to attachedFCDs list" , virtualDisk .VDiskId .Id )
469- attachedFCDs [virtualDisk .VDiskId .Id ] = FCDBackingDetails {controllerKey , unitNumber , sharingMode , diskMode }
534+ attachedFCDs [virtualDisk .VDiskId .Id ] = FCDBackingDetails {
535+ ControllerKey : controllerKey ,
536+ UnitNumber : unitNumber ,
537+ SharingMode : sharingMode ,
538+ DiskMode : diskMode }
470539 }
471540
472541 }
@@ -477,6 +546,7 @@ func listAttachedFcdsForVM(ctx context.Context,
477546// constructs the batchAttach request for each of them.
478547// It also validates each of the requests to make sure user input is correct.
479548func constructBatchAttachRequest (ctx context.Context ,
549+ volumesToAttach map [string ]string ,
480550 instance * v1alpha1.CnsNodeVMBatchAttachment ) (pvcsInSpec map [string ]string ,
481551 volumeIdsInSpec map [string ]string ,
482552 batchAttachRequest []volumes.BatchAttachRequest , err error ) {
@@ -491,31 +561,27 @@ func constructBatchAttachRequest(ctx context.Context,
491561 // This map has mapping of volumeID to PVC.
492562 volumeIdsInSpec = make (map [string ]string )
493563
494- for _ , volume := range instance .Spec .Volumes {
495- pvcName := volume .PersistentVolumeClaim .ClaimName
496- volumeName := volume .Name
497-
498- // Find volumeID for PVC.
499- attachVolumeId , ok := commonco .ContainerOrchestratorUtility .GetVolumeIDFromPVCName (instance .Namespace , pvcName )
500- if ! ok {
501- err := fmt .Errorf ("failed to find volumeID for PVC %s" , pvcName )
502- log .Error (err )
503- return pvcsInSpec , volumeIdsInSpec , batchAttachRequest , err
504- }
564+ for pvcName , volumeID := range volumesToAttach {
565+ for _ , volume := range instance .Spec .Volumes {
566+ if volume .PersistentVolumeClaim .ClaimName != pvcName {
567+ continue
568+ }
505569
506- // Populate these 2 maps as these values are required later during batch attach.
507- pvcsInSpec [volume .PersistentVolumeClaim .ClaimName ] = volumeName
508- volumeIdsInSpec [attachVolumeId ] = volume .PersistentVolumeClaim .ClaimName
570+ // Populate these 2 maps as these values are required later during batch attach.
571+ pvcsInSpec [volume .PersistentVolumeClaim .ClaimName ] = volume .Name
572+ volumeIdsInSpec [volumeID ] = volume .PersistentVolumeClaim .ClaimName
573+
574+ // Populate values for attach request.
575+ currentBatchAttachRequest := volumes.BatchAttachRequest {
576+ VolumeID : volumeID ,
577+ SharingMode : string (volume .PersistentVolumeClaim .SharingMode ),
578+ DiskMode : string (volume .PersistentVolumeClaim .DiskMode ),
579+ ControllerKey : volume .PersistentVolumeClaim .ControllerKey ,
580+ UnitNumber : volume .PersistentVolumeClaim .UnitNumber ,
581+ }
582+ batchAttachRequest = append (batchAttachRequest , currentBatchAttachRequest )
509583
510- // Populate values for attach request.
511- currentBatchAttachRequest := volumes.BatchAttachRequest {
512- VolumeID : attachVolumeId ,
513- SharingMode : string (volume .PersistentVolumeClaim .SharingMode ),
514- DiskMode : string (volume .PersistentVolumeClaim .DiskMode ),
515- ControllerKey : volume .PersistentVolumeClaim .ControllerKey ,
516- UnitNumber : volume .PersistentVolumeClaim .UnitNumber ,
517584 }
518- batchAttachRequest = append (batchAttachRequest , currentBatchAttachRequest )
519585 }
520586 return pvcsInSpec , volumeIdsInSpec , batchAttachRequest , nil
521587}
@@ -541,52 +607,71 @@ func getVmObject(ctx context.Context, client client.Client, configInfo config.Co
541607 return vm , nil
542608}
543609
544- // getVolumesToDetach checks if:
545- // Instance is being deleted, then it adds all the volumes in the spec for detach.
546- // If instance is not being deleted then finds the volumes to be detached by querying vCenter.
547- func getVolumesToDetach (ctx context.Context , instance * v1alpha1.CnsNodeVMBatchAttachment ,
548- vm * cnsvsphere.VirtualMachine , client client.Client , k8sClient kubernetes.Interface ) (map [string ]string , error ) {
610+ func getVolumesToAttachAndDetach (ctx context.Context , instance * v1alpha1.CnsNodeVMBatchAttachment ,
611+ vm * cnsvsphere.VirtualMachine , client client.Client , k8sClient kubernetes.Interface ) (map [string ]string ,
612+ map [string ]string , error ) {
549613 log := logger .GetLogger (ctx )
550614
615+ pvcsToAttach := make (map [string ]string , 0 )
616+ pvcsToDetach := make (map [string ]string , 0 )
617+
551618 if instance .DeletionTimestamp != nil {
552619 log .Debugf ("Instance %s is being deleted, adding all volumes in spec to volumesToDetach list." , instance .Name )
553620 volumesToDetach , err := getPvcsInSpec (ctx , instance , k8sClient )
554621 if err != nil {
555622 log .Errorf ("failed to get volumes to detach from instance spec. Err: %s" , err )
556- return volumesToDetach , err
623+ return pvcsToAttach , volumesToDetach , err
557624 }
558625 log .Debugf ("Volumes to detach list %+v for instance %s" , volumesToDetach , instance .Name )
559- return volumesToDetach , nil
626+ return pvcsToAttach , volumesToDetach , nil
627+ }
628+
629+ // Query vCenter to find the list of FCDs which are attached to the VM.
630+ attachedFcdList , err := listAttachedFcdsForVM (ctx , vm )
631+ if err != nil {
632+ log .Errorf ("failed to find the FCDs attached to VM %s. Err: %s" , vm , err )
633+ return map [string ]string {}, map [string ]string {}, err
634+ }
635+ log .Infof ("List of attached FCDs %+v to VM %s" , attachedFcdList , instance .Spec .InstanceUUID )
636+
637+ // Get all PVCs and their corresponding volumeID mapping from instance spec.
638+ volumeIdsInSpec , volumeNamesInSpec , pvcNameToVolumeIDInSpec , err := getVolumeMetadataMaps (ctx , instance )
639+ if err != nil {
640+ log .Errorf ("failed to get PVCs in spec. Err: %s" , err )
641+ return pvcsToAttach , pvcsToDetach , err
560642 }
561643
562644 // Find the volumes to detach from the vCenter.
563- volumesToDetach , err := getVolumesToDetachFromVM (ctx , client , k8sClient , instance , vm )
645+ pvcsToDetach , err = getVolumesToDetach (ctx , client , k8sClient , instance , vm ,
646+ attachedFcdList , volumeIdsInSpec , volumeNamesInSpec )
564647 if err != nil {
565648 log .Errorf ("failed to find volumes to detach from the vCenter for instance %s" , instance .Name )
566- return volumesToDetach , err
649+ return pvcsToAttach , pvcsToDetach , err
567650 }
568- log .Debugf ("Volumes to detach list %+v for instance %s" , volumesToDetach , instance .Name )
569- return volumesToDetach , nil
651+
652+ // Find the volumes to attach from the vCenter.
653+ pvcsToAttach , err = getVolumesToAttach (ctx , instance ,
654+ attachedFcdList , volumeIdsInSpec , pvcNameToVolumeIDInSpec )
655+ if err != nil {
656+ log .Errorf ("failed to find volumes to attach from the vCenter for instance %s" , instance .Name )
657+ return pvcsToAttach , pvcsToDetach , err
658+ }
659+ log .Debugf ("Volumes to attach list %+v for instance %s" , pvcsToAttach , instance .Name )
660+ return pvcsToAttach , pvcsToDetach , nil
570661}
571662
572- // getVolumesToDetachFromVM queries vCenter to find the list of FCDs
663+ // getVolumesToDetach queries vCenter to find the list of FCDs
573664// which have to be detached from the VM.
574- func getVolumesToDetachFromVM (ctx context.Context , client client.Client ,
665+ func getVolumesToDetach (ctx context.Context , client client.Client ,
575666 k8sClient kubernetes.Interface ,
576667 instance * v1alpha1.CnsNodeVMBatchAttachment ,
577- vm * cnsvsphere.VirtualMachine ) (map [string ]string , error ) {
668+ vm * cnsvsphere.VirtualMachine , attachedFcdList map [string ]FCDBackingDetails ,
669+ volumeIdsInSpec map [string ]FCDBackingDetails , volumeNamesInSpec map [string ]string ) (map [string ]string , error ) {
578670 log := logger .GetLogger (ctx )
579671
580- // Query vCenter to find the list of FCDs which are attached to the VM.
581- attachedFcdList , err := listAttachedFcdsForVM (ctx , vm )
582- if err != nil {
583- log .Errorf ("failed to find the FCDs attached to VM %s. Err: %s" , vm , err )
584- return map [string ]string {}, err
585- }
586- log .Infof ("List of attached FCDs %+v to VM %s" , attachedFcdList , instance .Spec .InstanceUUID )
587-
588672 // Find volumes to be detached from the VM by takinga diff with FCDs attached to VM on vCenter.
589- volumesToDetach , err := getVolumesToDetachForVmFromVC (ctx , instance , client , k8sClient , attachedFcdList )
673+ volumesToDetach , err := getVolumesToDetachForVmFromVC (ctx , instance , client , k8sClient ,
674+ attachedFcdList , volumeIdsInSpec , volumeNamesInSpec )
590675 if err != nil {
591676 log .Errorf ("failed to find volumes to attach and detach. Err: %s" , err )
592677 return map [string ]string {}, err
@@ -595,7 +680,6 @@ func getVolumesToDetachFromVM(ctx context.Context, client client.Client,
595680 log .Infof ("Volumes to be detached %+v for instance %s" , volumesToDetach , instance .Name )
596681
597682 return volumesToDetach , nil
598-
599683}
600684
601685// addPvcAnnotation adds the vmInstanceUUID as an annotation to the given PVC.
@@ -632,7 +716,7 @@ func patchPVCAnnotations(ctx context.Context, k8sClient kubernetes.Interface,
632716 log .Infof ("Removing annotation %s from PVC %s" , key , pvc .Name )
633717 patchAnnotations [key ] = nil
634718 } else {
635- log .Infof ("Adding annotation %s on PVC" , key , pvc .Name )
719+ log .Infof ("Adding annotation %s on PVC %s " , key , pvc .Name )
636720 patchAnnotations [key ] = ""
637721 }
638722
0 commit comments