Skip to content

Commit 4bd811c

Browse files
authored
Fix CnsVolumeOperationRequest update logic when transaction support is enabled (#3623)
Signed-off-by: Deepak Kinni <[email protected]>
1 parent d7653fa commit 4bd811c

File tree

8 files changed

+790
-10
lines changed

8 files changed

+790
-10
lines changed

pkg/common/cns-lib/volume/manager.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,14 @@ func (m *defaultManager) createSnapshotWithTransaction(ctx context.Context, volu
29102910
faultType := ExtractFaultTypeFromErr(ctx, err)
29112911
return nil, faultType, logger.LogNewErrorf(log, "failed to create snapshot with error: %v", err)
29122912
}
2913+
// Persist the volume operation details.
2914+
volumeOperationDetails = createRequestDetails(instanceName, volumeID, "", 0, quotaInfo,
2915+
volumeOperationDetails.OperationDetails.TaskInvocationTimestamp,
2916+
createSnapshotsTask.Reference().Value, "", "", taskInvocationStatusInProgress, "")
2917+
if err := m.operationStore.StoreRequestDetails(ctx, volumeOperationDetails); err != nil {
2918+
// Don't return if CreateSnapshot details can't be stored.
2919+
log.Warnf("failed to store CreateSnapshot details with error: %v", err)
2920+
}
29132921

29142922
var createSnapshotsTaskInfo *vim25types.TaskInfo
29152923
var faultType string

pkg/csi/service/vanilla/controller.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,13 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
187187
log.Infof("Initializing CNS controller")
188188
var err error
189189
var operationStore cnsvolumeoperationrequest.VolumeOperationRequest
190+
190191
operationStore, err = cnsvolumeoperationrequest.InitVolumeOperationRequestInterface(ctx,
191192
config.Global.CnsVolumeOperationRequestCleanupIntervalInMin,
192193
func() bool {
193194
return commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.BlockVolumeSnapshot)
194-
}, false)
195+
}, false,
196+
false)
195197
if err != nil {
196198
log.Errorf("failed to initialize VolumeOperationRequestInterface with error: %v", err)
197199
return err
@@ -202,7 +204,6 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
202204
common.CnsMgrSuspendCreateVolume)
203205
isTopologyAwareFileVolumeEnabled = commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
204206
common.TopologyAwareFileVolume)
205-
isCSITransactionSupportEnabled = commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.CSITransactionSupport)
206207

207208
vcManager := cnsvsphere.GetVirtualCenterManager(ctx)
208209
// Multi vCenter feature enabled
@@ -260,7 +261,8 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
260261
for _, authMgr := range authMgrs {
261262
go common.ComputeDatastoreMapForBlockVolumes(authMgr, config.Global.CSIAuthCheckIntervalInMin)
262263
}
263-
var vsanFileServiceNotSupported bool
264+
allVCentersSupportvSANFileService := true
265+
allVCentersSupportCnsTransaction := true
264266
for _, vcconfig := range c.managers.VcenterConfigs {
265267
isvSANFileServicesSupported, err := c.managers.VcenterManager.IsvSANFileServicesSupported(ctx,
266268
vcconfig.Host)
@@ -269,13 +271,29 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
269271
"Error:%+v", vcconfig.Host, err)
270272
}
271273
if !isvSANFileServicesSupported {
272-
vsanFileServiceNotSupported = true
273-
break
274+
allVCentersSupportvSANFileService = false
275+
}
276+
277+
isCnsTransactionSupported, err := c.managers.VcenterManager.IsCnsTransactionSupported(ctx,
278+
vcconfig.Host)
279+
if err != nil {
280+
return logger.LogNewErrorf(log, "failed to verify if CNS transaction is supported or not for vCenter: %s. "+
281+
"Error:%+v", vcconfig.Host, err)
282+
}
283+
if !isCnsTransactionSupported {
284+
allVCentersSupportCnsTransaction = false
274285
}
275286
}
276-
if vsanFileServiceNotSupported {
287+
if !allVCentersSupportvSANFileService {
277288
return logger.LogNewErrorf(log, "vSAN file service is not supported in one or more vCenter(s)")
278289
}
290+
291+
// CSI Transaction Support requires both FSS to be enabled AND all vCenters to support CNS transactions
292+
fssTransactionSupportEnabled := commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
293+
common.CSITransactionSupport)
294+
isCSITransactionSupportEnabled = fssTransactionSupportEnabled && allVCentersSupportCnsTransaction
295+
cnsvolumeoperationrequest.SetCSITransactionSupport(isCSITransactionSupportEnabled)
296+
279297
for _, vcconfig := range c.managers.VcenterConfigs {
280298
go common.ComputeFSEnabledClustersToDsMap(authMgrs[vcconfig.Host], config.Global.CSIAuthCheckIntervalInMin)
281299
}

pkg/csi/service/wcp/controller.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
160160
common.PodVMOnStretchedSupervisor)
161161
idempotencyHandlingEnabled := commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
162162
common.CSIVolumeManagerIdempotency)
163+
isCSITransactionSupportEnabled := commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
164+
common.FCDTransactionSupport)
163165
IsMultipleClustersPerVsphereZoneFSSEnabled = commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
164166
common.MultipleClustersPerVsphereZone)
165167
if !IsMultipleClustersPerVsphereZoneFSSEnabled {
@@ -177,7 +179,8 @@ func (c *controller) Init(config *cnsconfig.Config, version string) error {
177179
config.Global.CnsVolumeOperationRequestCleanupIntervalInMin,
178180
func() bool {
179181
return commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.BlockVolumeSnapshot)
180-
}, isPodVMOnStretchSupervisorFSSEnabled)
182+
}, isPodVMOnStretchSupervisorFSSEnabled,
183+
isCSITransactionSupportEnabled)
181184
if err != nil {
182185
log.Errorf("failed to initialize VolumeOperationRequestInterface with error: %v", err)
183186
return err
@@ -403,13 +406,16 @@ func (c *controller) ReloadConfiguration(reconnectToVCFromNewConfig bool) error
403406
}
404407
idempotencyHandlingEnabled := commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
405408
common.CSIVolumeManagerIdempotency)
409+
isCSITransactionSupportEnabled := commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx,
410+
common.FCDTransactionSupport)
406411
if idempotencyHandlingEnabled {
407412
log.Info("CSI Volume manager idempotency handling feature flag is enabled.")
408413
operationStore, err = cnsvolumeoperationrequest.InitVolumeOperationRequestInterface(ctx,
409414
c.manager.CnsConfig.Global.CnsVolumeOperationRequestCleanupIntervalInMin,
410415
func() bool {
411416
return commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.BlockVolumeSnapshot)
412-
}, isPodVMOnStretchSupervisorFSSEnabled)
417+
}, isPodVMOnStretchSupervisorFSSEnabled,
418+
isCSITransactionSupportEnabled)
413419
if err != nil {
414420
log.Errorf("failed to initialize VolumeOperationRequestInterface with error: %v", err)
415421
return err
@@ -2551,7 +2557,7 @@ func (c *controller) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshot
25512557
StorageClassName: cnsVolumeInfo.Spec.StorageClassName,
25522558
StoragePolicyID: cnsVolumeInfo.Spec.StoragePolicyID,
25532559
Capacity: resource.NewQuantity(0, resource.BinarySI),
2554-
Namespace: cnsVolumeInfo.Namespace,
2560+
Namespace: cnsVolumeInfo.Spec.Namespace,
25552561
IsStorageQuotaM2FSSEnabled: isStorageQuotaM2FSSEnabled,
25562562
})
25572563
if err != nil {

pkg/internalapis/cnsvolumeoperationrequest/cnsvolumeoperationrequest.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,16 @@ var (
7878
operationRequestStoreInstance *operationRequestStore
7979
operationStoreInitLock = &sync.Mutex{}
8080
isPodVMOnStretchSupervisorFSSEnabled bool
81+
isCSITransactionSupportEnabled bool
8182
)
8283

8384
// InitVolumeOperationRequestInterface creates the CnsVolumeOperationRequest
8485
// definition on the API server and returns an implementation of
8586
// VolumeOperationRequest interface. Clients are unaware of the implementation
8687
// details to read and persist volume operation details.
8788
func InitVolumeOperationRequestInterface(ctx context.Context, cleanupInterval int,
88-
isBlockVolumeSnapshotEnabled func() bool, isPodVMOnStretchSupervisorEnabled bool) (
89+
isBlockVolumeSnapshotEnabled func() bool, isPodVMOnStretchSupervisorEnabled bool,
90+
csiTransactionSupportEnabled bool) (
8991
VolumeOperationRequest, error) {
9092
log := logger.GetLogger(ctx)
9193
csiNamespace = getCSINamespace()
@@ -130,6 +132,8 @@ func InitVolumeOperationRequestInterface(ctx context.Context, cleanupInterval in
130132
}
131133
// Store PodVMOnStretchedSupervisor FSS value for later use.
132134
isPodVMOnStretchSupervisorFSSEnabled = isPodVMOnStretchSupervisorEnabled
135+
// Store CSI Transaction Support FSS value for later use.
136+
isCSITransactionSupportEnabled = csiTransactionSupportEnabled
133137

134138
return operationRequestStoreInstance, nil
135139
}
@@ -261,6 +265,32 @@ func (or *operationRequestStore) StoreRequestDetails(
261265
// Create a deep copy since we modify the object.
262266
updatedInstance := instance.DeepCopy()
263267

268+
// If CSI Transaction Support is enabled and we're storing a new InProgress operation with empty TaskID,
269+
// mark any existing InProgress entries as TrackingAborted since this indicates a retry scenario.
270+
if isCSITransactionSupportEnabled && operationDetailsToStore.TaskStatus == TaskInvocationStatusInProgress &&
271+
operationDetailsToStore.TaskID == "" {
272+
// This is a new operation attempt (Phase 1: Intent Registration)
273+
// Mark any existing InProgress entries as TrackingAborted since this is clearly a retry
274+
for index := range updatedInstance.Status.LatestOperationDetails {
275+
existingOp := &updatedInstance.Status.LatestOperationDetails[index]
276+
if existingOp.TaskStatus == TaskInvocationStatusInProgress {
277+
// This is a retry - mark the previous attempt as aborted
278+
existingOp.TaskStatus = TaskInvocationStatusTrackingAborted
279+
existingOp.Error = "Operation tracking aborted due to retry attempt"
280+
log.Infof("Marked previous InProgress operation as TrackingAborted due to retry detection. Instance: %s",
281+
operationToStore.Name)
282+
}
283+
}
284+
285+
// Also check FirstOperationDetails
286+
if updatedInstance.Status.FirstOperationDetails.TaskStatus == TaskInvocationStatusInProgress {
287+
updatedInstance.Status.FirstOperationDetails.TaskStatus = TaskInvocationStatusTrackingAborted
288+
updatedInstance.Status.FirstOperationDetails.Error = "Operation tracking aborted due to retry attempt"
289+
log.Infof("Marked FirstOperationDetails as TrackingAborted due to retry detection. Instance: %s",
290+
operationToStore.Name)
291+
}
292+
}
293+
264294
// Modify VolumeID, SnapshotID and Capacity
265295
updatedInstance.Status.VolumeID = operationToStore.VolumeID
266296
updatedInstance.Status.SnapshotID = operationToStore.SnapshotID
@@ -409,6 +439,12 @@ func (or *operationRequestStore) cleanupStaleInstances(cleanupInterval int) {
409439
}
410440
}
411441

442+
// SetCSITransactionSupport sets the CSI Transaction Support feature flag.
443+
// This function allows runtime modification of the isCSITransactionSupportEnabled variable.
444+
func SetCSITransactionSupport(enabled bool) {
445+
isCSITransactionSupportEnabled = enabled
446+
}
447+
412448
func getCSINamespace() string {
413449
csiNamespace := os.Getenv(EnvCSINamespace)
414450
if strings.TrimSpace(csiNamespace) == "" {

0 commit comments

Comments
 (0)