@@ -386,6 +386,7 @@ func (m *defaultManager) MonitorCreateVolumeTask(ctx context.Context,
386
386
vCenterServerForVolumeOperationCR string
387
387
)
388
388
log := logger .GetLogger (ctx )
389
+ log .Debugf ("Invoked MonitorCreateVolumeTask for task: %v" , task .Reference ())
389
390
if m .multivCenterTopologyDeployment {
390
391
vCenterServerForVolumeOperationCR = m .virtualCenter .Config .Host
391
392
}
@@ -467,21 +468,33 @@ func (m *defaultManager) MonitorCreateVolumeTask(ctx context.Context,
467
468
}
468
469
volumeOperationRes := taskResult .GetCnsVolumeOperationResult ()
469
470
if volumeOperationRes .Fault != nil {
470
- // Validate if the volume is already registered.
471
- faultType = ExtractFaultTypeFromVolumeResponseResult (ctx , volumeOperationRes )
472
- resp , err := validateCreateVolumeResponseFault (ctx , volNameFromInputSpec , volumeOperationRes )
471
+ if IsNotSupportedFault (ctx , volumeOperationRes .Fault ) {
472
+ faultType = "vim25:NotSupported"
473
+ err = fmt .Errorf ("failed to create volume with fault: %q" , faultType )
474
+ } else if _ , ok := volumeOperationRes .Fault .Fault .(* cnstypes.CnsVolumeAlreadyExistsFault ); ok {
475
+ faultType = "vim.fault.CnsVolumeAlreadyExistsFault"
476
+ err = fmt .Errorf ("failed to create volume with fault: %q" , faultType )
477
+ } else {
478
+ // Validate if the volume is already registered.
479
+ faultType = ExtractFaultTypeFromVolumeResponseResult (ctx , volumeOperationRes )
480
+ resp , err := validateCreateVolumeResponseFault (ctx , volNameFromInputSpec , volumeOperationRes )
481
+ if err == nil {
482
+ * volumeOperationDetails = createRequestDetails (volNameFromInputSpec , resp .VolumeID .Id , "" , 0 ,
483
+ (* volumeOperationDetails ).QuotaDetails ,
484
+ (* volumeOperationDetails ).OperationDetails .TaskInvocationTimestamp , task .Reference ().Value ,
485
+ vCenterServerForVolumeOperationCR , taskInfo .ActivationId , taskInvocationStatusSuccess , "" )
486
+ return resp , faultType , err
487
+ }
488
+ }
473
489
if err != nil {
490
+ log .Errorf ("err:%v observed for task: %v, volume name: %q, OpID: %q" ,
491
+ err .Error (), task .Reference ().Value , volNameFromInputSpec , taskInfo .ActivationId )
474
492
* volumeOperationDetails = createRequestDetails (volNameFromInputSpec , "" , "" , 0 ,
475
493
(* volumeOperationDetails ).QuotaDetails , (* volumeOperationDetails ).OperationDetails .TaskInvocationTimestamp ,
476
494
task .Reference ().Value , vCenterServerForVolumeOperationCR , taskInfo .ActivationId ,
477
495
taskInvocationStatusError , err .Error ())
478
- } else {
479
- * volumeOperationDetails = createRequestDetails (volNameFromInputSpec , resp .VolumeID .Id , "" , 0 ,
480
- (* volumeOperationDetails ).QuotaDetails ,
481
- (* volumeOperationDetails ).OperationDetails .TaskInvocationTimestamp , task .Reference ().Value ,
482
- vCenterServerForVolumeOperationCR , taskInfo .ActivationId , taskInvocationStatusSuccess , "" )
496
+ return nil , faultType , err
483
497
}
484
- return resp , faultType , err
485
498
}
486
499
// Extract the CnsVolumeInfo from the taskResult.
487
500
resp , faultType , err := getCnsVolumeInfoFromTaskResult (ctx , m .virtualCenter , volNameFromInputSpec ,
@@ -658,6 +671,125 @@ func (m *defaultManager) createVolumeWithImprovedIdempotency(ctx context.Context
658
671
spec .Metadata .ContainerClusterArray [0 ].ClusterId )
659
672
}
660
673
674
+ // createVolumeWithTransaction creates volume with supplied PVC UUID as VolumeID in the CreateVolumeSpec
675
+ func (m * defaultManager ) createVolumeWithTransaction (ctx context.Context , spec * cnstypes.CnsVolumeCreateSpec ,
676
+ extraParams interface {}) (resp * CnsVolumeInfo , faultType string , finalErr error ) {
677
+ log := logger .GetLogger (ctx )
678
+ var (
679
+ // Store the volume name passed in by input spec, this
680
+ // name may exceed 80 characters.
681
+ volNameFromInputSpec = spec .Name
682
+ // Reference to the CreateVolume task on CNS.
683
+ task * object.Task
684
+ // Local instance of CreateVolume details that needs to
685
+ // be persisted.
686
+ volumeOperationDetails * cnsvolumeoperationrequest.VolumeOperationRequestDetails
687
+ // quotaInfo consists of values required to populate QuotaDetails in CnsVolumeOperationRequest CR.
688
+ quotaInfo * cnsvolumeoperationrequest.QuotaDetails
689
+ isPodVMOnStretchSupervisorFSSEnabled bool
690
+ )
691
+
692
+ if extraParams != nil {
693
+ createVolParams , ok := extraParams .(* CreateVolumeExtraParams )
694
+ if ! ok {
695
+ return nil , csifault .CSIInternalFault ,
696
+ logger .LogNewErrorf (log , "unrecognised type for CreateVolume params: %+v" , extraParams )
697
+ }
698
+ log .Debugf ("Received CreateVolume extraParams: %+v" , * createVolParams )
699
+
700
+ isPodVMOnStretchSupervisorFSSEnabled = createVolParams .IsPodVMOnStretchSupervisorFSSEnabled
701
+ if isPodVMOnStretchSupervisorFSSEnabled && m .clusterFlavor == cnstypes .CnsClusterFlavorWorkload {
702
+ var storagePolicyID string
703
+ if len (spec .Profile ) >= 1 {
704
+ storagePolicyID = spec .Profile [0 ].(* vim25types.VirtualMachineDefinedProfileSpec ).ProfileId
705
+ }
706
+ reservedQty := resource .NewQuantity (createVolParams .VolSizeBytes , resource .BinarySI )
707
+ quotaInfo = & cnsvolumeoperationrequest.QuotaDetails {
708
+ Reserved : reservedQty ,
709
+ StoragePolicyId : storagePolicyID ,
710
+ StorageClassName : createVolParams .StorageClassName ,
711
+ Namespace : createVolParams .Namespace ,
712
+ }
713
+ log .Infof ("QuotaInfo during CreateVolume call: %+v" , * quotaInfo )
714
+ }
715
+ }
716
+
717
+ if m .operationStore == nil {
718
+ return nil , csifault .CSIInternalFault , logger .LogNewError (log , "operation store cannot be nil" )
719
+ }
720
+ var vCenterServerForVolumeOperationCR string
721
+ if m .multivCenterTopologyDeployment {
722
+ vCenterServerForVolumeOperationCR = m .virtualCenter .Config .Host
723
+ }
724
+
725
+ volumeOperationDetails , finalErr = m .operationStore .GetRequestDetails (ctx , volNameFromInputSpec )
726
+ if ! apierrors .IsNotFound (finalErr ) {
727
+ return nil , csifault .CSIInternalFault , finalErr
728
+ }
729
+ defer func () {
730
+ // Persist the operation details before returning. Only success or error
731
+ // needs to be stored as InProgress details are stored when the task is
732
+ // created on CNS.
733
+ if volumeOperationDetails != nil && volumeOperationDetails .OperationDetails != nil &&
734
+ volumeOperationDetails .OperationDetails .TaskStatus != taskInvocationStatusInProgress {
735
+
736
+ if m .clusterFlavor == cnstypes .CnsClusterFlavorWorkload && isPodVMOnStretchSupervisorFSSEnabled {
737
+ // Decrease the reserved field in QuotaDetails when the CreateVolume task is
738
+ // successful or has errored out.
739
+ taskStatus := volumeOperationDetails .OperationDetails .TaskStatus
740
+ if (taskStatus == taskInvocationStatusSuccess || taskStatus == taskInvocationStatusError ) &&
741
+ volumeOperationDetails .QuotaDetails != nil {
742
+ volumeOperationDetails .QuotaDetails .Reserved = resource .NewQuantity (0 ,
743
+ resource .BinarySI )
744
+ log .Infof ("Setting the reserved field for VolumeOperationDetails instance %s to 0" ,
745
+ volumeOperationDetails .Name )
746
+ }
747
+ tempErr := m .operationStore .StoreRequestDetails (ctx , volumeOperationDetails )
748
+ if finalErr == nil && tempErr != nil {
749
+ log .Errorf ("failed to store CreateVolume details with error: %v" , tempErr )
750
+ finalErr = tempErr
751
+ }
752
+ } else {
753
+ err := m .operationStore .StoreRequestDetails (ctx , volumeOperationDetails )
754
+ if err != nil {
755
+ log .Warnf ("failed to store CreateVolume details with error: %v" , err )
756
+ }
757
+ }
758
+ }
759
+ }()
760
+ volumeOperationDetails = createRequestDetails (volNameFromInputSpec , "" , "" , 0 ,
761
+ quotaInfo , metav1 .Now (), "" , vCenterServerForVolumeOperationCR , "" ,
762
+ taskInvocationStatusInProgress , "" )
763
+ err := m .operationStore .StoreRequestDetails (ctx , volumeOperationDetails )
764
+ if err != nil {
765
+ // Don't return if CreateVolume details can't be stored.
766
+ log .Warnf ("failed to store CreateVolume details with error: %v" , err )
767
+ }
768
+ task , finalErr = invokeCNSCreateVolume (ctx , m .virtualCenter , spec )
769
+ if finalErr != nil {
770
+ log .Errorf ("failed to create volume with error: %v" , finalErr )
771
+ volumeOperationDetails = createRequestDetails (volNameFromInputSpec , "" , "" , 0 ,
772
+ quotaInfo , volumeOperationDetails .OperationDetails .TaskInvocationTimestamp , "" ,
773
+ vCenterServerForVolumeOperationCR , "" , taskInvocationStatusError , finalErr .Error ())
774
+ faultType = ExtractFaultTypeFromErr (ctx , finalErr )
775
+ return nil , faultType , finalErr
776
+ }
777
+ if ! isStaticallyProvisioned (spec ) {
778
+ // Persist task details only for dynamically provisioned volumes.
779
+ volumeOperationDetails = createRequestDetails (volNameFromInputSpec , "" , "" , 0 ,
780
+ quotaInfo , metav1 .Now (), task .Reference ().Value , vCenterServerForVolumeOperationCR , "" ,
781
+ taskInvocationStatusInProgress , "" )
782
+ err := m .operationStore .StoreRequestDetails (ctx , volumeOperationDetails )
783
+ if err != nil {
784
+ // Don't return if CreateVolume details can't be stored.
785
+ log .Warnf ("failed to store CreateVolume details with error: %v" , err )
786
+ }
787
+ }
788
+
789
+ return m .MonitorCreateVolumeTask (ctx , & volumeOperationDetails , task , volNameFromInputSpec ,
790
+ spec .Metadata .ContainerClusterArray [0 ].ClusterId )
791
+ }
792
+
661
793
// IsTaskPending returns true in two cases -
662
794
// 1. if the task status was in progress
663
795
// 2. if the status was an error but the error was for adding the task to the listview
@@ -853,7 +985,29 @@ func (m *defaultManager) CreateVolume(ctx context.Context, spec *cnstypes.CnsVol
853
985
}
854
986
// Call CreateVolume implementation based on FSS value.
855
987
if m .idempotencyHandlingEnabled {
856
- return m .createVolumeWithImprovedIdempotency (ctx , spec , extraParams )
988
+ if spec .VolumeId != nil && spec .VolumeId .Id != "" {
989
+ var cnsVolumeInfo * CnsVolumeInfo
990
+ cnsVolumeInfo , faultType , err = m .createVolumeWithTransaction (ctx , spec , extraParams )
991
+ if err != nil {
992
+ log .Errorf ("failed to create volume with VolumeID: %q, faultType: %q, err: %v" ,
993
+ spec .VolumeId .Id , faultType , err )
994
+ if IsCnsVolumeAlreadyExistsFault (ctx , faultType ) {
995
+ log .Infof ("Observed volume with Id: %q is already Exists. Deleting Volume." , spec .VolumeId .Id )
996
+ deleteFaultType , deleteError := m .deleteVolume (ctx , spec .VolumeId .Id , true )
997
+ if deleteError != nil {
998
+ log .Errorf ("failed to delete volume: %q to handle CnsVolumeAlreadyExistsFault , err :%v" , spec .VolumeId .Id , err )
999
+ return nil , deleteFaultType , deleteError
1000
+ }
1001
+ log .Infof ("Attempt to re-create volume with Id: %q" , spec .VolumeId .Id )
1002
+ cnsVolumeInfo , faultType , err = m .createVolumeWithTransaction (ctx , spec , extraParams )
1003
+ return cnsVolumeInfo , faultType , err
1004
+ }
1005
+ return nil , faultType , err
1006
+ }
1007
+ return cnsVolumeInfo , faultType , err
1008
+ } else {
1009
+ return m .createVolumeWithImprovedIdempotency (ctx , spec , extraParams )
1010
+ }
857
1011
}
858
1012
return m .createVolume (ctx , spec )
859
1013
}
@@ -1854,7 +2008,7 @@ func (m *defaultManager) expandVolumeWithImprovedIdempotency(ctx context.Context
1854
2008
1855
2009
volumeOperationRes := taskResult .GetCnsVolumeOperationResult ()
1856
2010
if volumeOperationRes .Fault != nil {
1857
- if _ , ok := volumeOperationRes .Fault .Fault .(cnstypes.CnsFault ); ok {
2011
+ if _ , ok := volumeOperationRes .Fault .Fault .(* cnstypes.CnsFault ); ok {
1858
2012
log .Debugf ("ExtendVolume task %s returned with CnsFault. Querying CNS to " +
1859
2013
"determine if volume with ID %s was successfully expanded." ,
1860
2014
task .Reference ().Value , volumeID )
@@ -2562,7 +2716,7 @@ func (m *defaultManager) createSnapshotWithImprovedIdempotencyCheck(ctx context.
2562
2716
errMsg = fmt .Sprintf ("snapshot %q on volume %q got created, but post-processing failed. " +
2563
2717
"Fault: %q, opID: %q" , instanceName , volumeID , spew .Sdump (createSnapshotsOperationRes .Fault ),
2564
2718
createSnapshotsTaskInfo .ActivationId )
2565
- snapshotId := createSnapshotsOperationRes .Fault .Fault .(cnstypes.CnsSnapshotCreatedFault ).SnapshotId .Id
2719
+ snapshotId := createSnapshotsOperationRes .Fault .Fault .(* cnstypes.CnsSnapshotCreatedFault ).SnapshotId .Id
2566
2720
volumeOperationDetails = createRequestDetails (instanceName , volumeID , snapshotId , 0 , nil ,
2567
2721
volumeOperationDetails .OperationDetails .TaskInvocationTimestamp , createSnapshotsTask .Reference ().Value ,
2568
2722
"" , createSnapshotsTaskInfo .ActivationId , taskInvocationStatusPartiallyFailed , errMsg )
0 commit comments