From a68ce42138fa4cd7a56a3142057ee1d49d0a8cc1 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 19 Nov 2025 16:02:32 +0000 Subject: [PATCH] Added the limitAggregateUsageOnResize configuration parameter for ONTAP backends that support the limitAggregateUsage configuration parameter. If the limitAggregateUsageOnResize parameter is not set, the original behavior with the limitAggregateUsage parameter is used. If the limitAggregateUsageOnResize is configured, PVC expansion can be allowed at a different aggregate utilization threshold than PVC creation. --- storage_drivers/ontap/ontap_common.go | 17 ++++++++++++++--- storage_drivers/ontap/ontap_common_test.go | 14 +++++++------- storage_drivers/ontap/ontap_nas.go | 2 +- storage_drivers/ontap/ontap_nas_qtree.go | 2 +- storage_drivers/ontap/ontap_san.go | 2 +- storage_drivers/ontap/ontap_san_economy.go | 2 +- storage_drivers/ontap/ontap_san_nvme.go | 2 +- storage_drivers/types.go | 1 + 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index 6221928fc..4b4c6ac1c 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -1760,6 +1760,7 @@ const ( DefaultLuksEncryption = "false" DefaultMirroring = "false" DefaultLimitAggregateUsage = "" + DefaultLimitAggregateUsageOnResize = "" DefaultLimitVolumeSize = "" DefaultLimitVolumePoolSize = "" DefaultDenyNewVolumePools = "false" @@ -1962,6 +1963,7 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto "LUKSEncryption": config.LUKSEncryption, "Mirroring": config.Mirroring, "LimitAggregateUsage": config.LimitAggregateUsage, + "LimitAggregateUsageOnResize": config.LimitAggregateUsageOnResize, "LimitVolumeSize": config.LimitVolumeSize, "LimitVolumePoolSize": config.LimitVolumePoolSize, "DenyNewVolumePools": config.DenyNewVolumePools, @@ -2092,6 +2094,7 @@ func PopulateASAConfigurationDefaults(ctx context.Context, config *drivers.Ontap "LUKSEncryption": config.LUKSEncryption, "Mirroring": config.Mirroring, "LimitAggregateUsage": config.LimitAggregateUsage, + "LimitAggregateUsageOnResize": config.LimitAggregateUsageOnResize, "LimitVolumeSize": config.LimitVolumeSize, "Size": config.Size, "TieringPolicy": config.TieringPolicy, @@ -2117,12 +2120,12 @@ func checkAggregateLimitsForFlexvol( return fmt.Errorf("aggregate info not available from Flexvol %s", flexvol) } - return checkAggregateLimits(ctx, volInfo.Aggregates[0], volInfo.SpaceReserve, requestedSizeInt, config, - client) + return checkAggregateLimits(ctx, volInfo.Aggregates[0], volInfo.SpaceReserve, requestedSizeInt, "resize", + config, client) } func checkAggregateLimits( - ctx context.Context, aggregate, spaceReserve string, requestedSizeInt uint64, + ctx context.Context, aggregate, spaceReserve string, requestedSizeInt uint64, checkType string, config drivers.OntapStorageDriverConfig, client api.OntapAPI, ) error { if aggregate == managedStoragePoolName { @@ -2132,7 +2135,15 @@ func checkAggregateLimits( requestedSize := float64(requestedSizeInt) + // checkType should be either "resize" or "create". + // Fall back to limitAggregateUsage for a resize if the + // limitAggregateUsageOnResize config is not set. limitAggregateUsage := config.LimitAggregateUsage + if checkType != "" && checkType == "resize" { + if config.LimitAggregateUsageOnResize != "" { + limitAggregateUsage = config.LimitAggregateUsageOnResize + } + } limitAggregateUsage = strings.Replace(limitAggregateUsage, "%", "", -1) // strip off any % Logc(ctx).WithFields(LogFields{ diff --git a/storage_drivers/ontap/ontap_common_test.go b/storage_drivers/ontap/ontap_common_test.go index 3b75b73a0..85edcc711 100644 --- a/storage_drivers/ontap/ontap_common_test.go +++ b/storage_drivers/ontap/ontap_common_test.go @@ -641,7 +641,7 @@ func TestCheckAggregateLimits(t *testing.T) { }, ).AnyTimes() - err := checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err := checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Equal(t, "could not find aggregate, cannot check aggregate provisioning limits for aggr1", err.Error()) // //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -654,7 +654,7 @@ func TestCheckAggregateLimits(t *testing.T) { }, ).AnyTimes() - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Equal(t, "could not find aggregate, cannot check aggregate provisioning limits for aggr1", err.Error()) // //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -673,7 +673,7 @@ func TestCheckAggregateLimits(t *testing.T) { }, ).AnyTimes() - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Nil(t, err) // //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -681,7 +681,7 @@ func TestCheckAggregateLimits(t *testing.T) { aggr = "" - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Error(t, err) @@ -693,7 +693,7 @@ func TestCheckAggregateLimits(t *testing.T) { mockOntapAPI.EXPECT().GetSVMAggregateSpace(gomock.Any(), aggr).Return([]api.SVMAggregateSpace{}, errors.New("GetSVMAggregateSpace returned error")) - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Error(t, err) @@ -716,7 +716,7 @@ func TestCheckAggregateLimits(t *testing.T) { }, ).AnyTimes() - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Error(t, err) @@ -739,7 +739,7 @@ func TestCheckAggregateLimits(t *testing.T) { }, ).AnyTimes() - err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), ontapConfig, mockOntapAPI) + err = checkAggregateLimits(ctx, aggr, spaceReserve, uint64(requestedSizeInt), "create", ontapConfig, mockOntapAPI) assert.Error(t, err) } diff --git a/storage_drivers/ontap/ontap_nas.go b/storage_drivers/ontap/ontap_nas.go index d09921425..469785c5f 100644 --- a/storage_drivers/ontap/ontap_nas.go +++ b/storage_drivers/ontap/ontap_nas.go @@ -389,7 +389,7 @@ func (d *NASStorageDriver) Create( physicalPoolNames = append(physicalPoolNames, aggregate) if aggrLimitsErr := checkAggregateLimits( - ctx, aggregate, spaceReserve, sizeBytes, d.Config, d.GetAPI(), + ctx, aggregate, spaceReserve, sizeBytes, "create", d.Config, d.GetAPI(), ); aggrLimitsErr != nil { errMessage := fmt.Sprintf("ONTAP-NAS pool %s/%s; error: %v", storagePool.Name(), aggregate, aggrLimitsErr) Logc(ctx).Error(errMessage) diff --git a/storage_drivers/ontap/ontap_nas_qtree.go b/storage_drivers/ontap/ontap_nas_qtree.go index d7d2058e8..176f75d40 100644 --- a/storage_drivers/ontap/ontap_nas_qtree.go +++ b/storage_drivers/ontap/ontap_nas_qtree.go @@ -451,7 +451,7 @@ func (d *NASQtreeStorageDriver) Create( physicalPoolNames = append(physicalPoolNames, aggregate) if aggrLimitsErr := checkAggregateLimits( - ctx, aggregate, spaceReserve, sizeBytes, d.Config, d.GetAPI(), + ctx, aggregate, spaceReserve, sizeBytes, "create", d.Config, d.GetAPI(), ); aggrLimitsErr != nil { errMessage := fmt.Sprintf("ONTAP-NAS-QTREE pool %s/%s; error: %v", storagePool.Name(), aggregate, aggrLimitsErr) diff --git a/storage_drivers/ontap/ontap_san.go b/storage_drivers/ontap/ontap_san.go index 335779fa1..88272c52a 100644 --- a/storage_drivers/ontap/ontap_san.go +++ b/storage_drivers/ontap/ontap_san.go @@ -481,7 +481,7 @@ func (d *SANStorageDriver) Create( physicalPoolNames = append(physicalPoolNames, aggregate) if aggrLimitsErr := checkAggregateLimits( - ctx, aggregate, spaceReserve, flexvolBufferSize, d.Config, d.GetAPI(), + ctx, aggregate, spaceReserve, flexvolBufferSize, "create", d.Config, d.GetAPI(), ); aggrLimitsErr != nil { errMessage := fmt.Sprintf("ONTAP-SAN pool %s/%s; error: %v", storagePool.Name(), aggregate, aggrLimitsErr) Logc(ctx).Error(errMessage) diff --git a/storage_drivers/ontap/ontap_san_economy.go b/storage_drivers/ontap/ontap_san_economy.go index 73e84500c..b33d2c1e2 100644 --- a/storage_drivers/ontap/ontap_san_economy.go +++ b/storage_drivers/ontap/ontap_san_economy.go @@ -587,7 +587,7 @@ func (d *SANEconomyStorageDriver) Create( physicalPoolNames = append(physicalPoolNames, aggregate) if aggrLimitsErr := checkAggregateLimits( - ctx, aggregate, spaceReserve, sizeBytes, d.Config, d.GetAPI(), + ctx, aggregate, spaceReserve, sizeBytes, "create", d.Config, d.GetAPI(), ); aggrLimitsErr != nil { errMessage := fmt.Sprintf( "ONTAP-SAN-ECONOMY pool %s/%s; error: %v", storagePool.Name(), aggregate, aggrLimitsErr, diff --git a/storage_drivers/ontap/ontap_san_nvme.go b/storage_drivers/ontap/ontap_san_nvme.go index 233afcfb8..e544afde3 100644 --- a/storage_drivers/ontap/ontap_san_nvme.go +++ b/storage_drivers/ontap/ontap_san_nvme.go @@ -415,7 +415,7 @@ func (d *NVMeStorageDriver) Create( physicalPoolNames = append(physicalPoolNames, aggregate) if aggrLimitsErr := checkAggregateLimits( - ctx, aggregate, spaceReserve, flexVolBufferSize, d.Config, d.GetAPI(), + ctx, aggregate, spaceReserve, flexVolBufferSize, "create", d.Config, d.GetAPI(), ); aggrLimitsErr != nil { errMessage := fmt.Sprintf("ONTAP-NVMe pool %s/%s; error: %v", storagePool.Name(), aggregate, aggrLimitsErr) Logc(ctx).Error(errMessage) diff --git a/storage_drivers/types.go b/storage_drivers/types.go index ade6ccbbc..25a7bae11 100644 --- a/storage_drivers/types.go +++ b/storage_drivers/types.go @@ -127,6 +127,7 @@ type OntapStorageDriverConfig struct { CloneSplitDelay string `json:"cloneSplitDelay,omitempty"` // in seconds, default to 10 NfsMountOptions string `json:"nfsMountOptions"` LimitAggregateUsage string `json:"limitAggregateUsage"` + LimitAggregateUsageOnResize string `json:"limitAggregateUsageOnResize"` LimitVolumePoolSize string `json:"limitVolumePoolSize"` DenyNewVolumePools string `json:"denyNewVolumePools"` AutoExportPolicy bool `json:"autoExportPolicy"`