From fd109c8054d0cf3bae9708c7294dc8a07ce6b7cc Mon Sep 17 00:00:00 2001 From: "Astyrakakis Nikolaos (BD/ISA-PRC5)" Date: Mon, 25 Aug 2025 10:26:24 +0200 Subject: [PATCH 01/11] feat: added CustomExtraExportCIDRs variable in tridentBackendConfig for pushing custom IPs/Networks to Export Policy with AutoExportPolicy. --- storage_drivers/ontap/ontap_common.go | 50 +++++++++++++++++-- storage_drivers/types.go | 1 + .../backend-tbc-ontap-nas-advanced.yaml | 3 ++ .../backend-tbc-ontap-nas-autoexport.yaml | 3 ++ .../backend-tbc-ontap-nas-virtual-pools.yaml | 1 + .../ontap-nas/backend-tbc-ontap-nas.yaml | 3 ++ 6 files changed, 57 insertions(+), 4 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index 0af6cf8b3..edc3ad4f8 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -405,11 +405,26 @@ func ensureNodeAccessForPolicy( } desiredRules, err := network.FilterIPs(ctx, targetNode.IPs, config.AutoExportCIDRs) + if err != nil { err = fmt.Errorf("unable to determine desired export policy rules; %v", err) Logc(ctx).Error(err) return err } + + // Add CustomExtraExportCIDRs if they exist + if len(config.CustomExtraExportCIDRs) > 0 { + extraCustomRules, err := network.FilterIPs(ctx, config.CustomExtraExportCIDRs, config.AutoExportCIDRs) + if err != nil { + err = fmt.Errorf("unable to filter customExportPolicyCIDRs; %v", err) + Logc(ctx).Error(err) + return err + } + + // Append the extraCustomRules to desiredRules + desiredRules = append(desiredRules, extraCustomRules...) + } + Logc(ctx).WithField("desiredRules", desiredRules).Debug("Desired export policy rules.") // first grab all existing rules @@ -477,14 +492,31 @@ func ensureNodeAccessForPolicy( func getDesiredExportPolicyRules( ctx context.Context, nodes []*tridentmodels.Node, config *drivers.OntapStorageDriverConfig, ) ([]string, error) { + uniqueRules := make(map[string]struct{}) + for _, node := range nodes { - // Filter the IPs based on the CIDRs provided by user - filteredIPs, err := network.FilterIPs(ctx, node.IPs, config.AutoExportCIDRs) + + // Filter the Node IPs based on the AutoExportCIDRs provided by user + nodeFilteredIPs, err := network.FilterIPs(ctx, node.IPs, config.AutoExportCIDRs) + if err != nil { + return nil, err + } + + for _, ip := range nodeFilteredIPs { + uniqueRules[ip] = struct{}{} + } + } + + if len(config.CustomExtraExportCIDRs) > 0 { + + // Filter the CustomExtraExportCIDRs based on the AutoExportCIDRs provided by user + customExtraIPs, err := network.FilterIPs(ctx, config.CustomExtraExportCIDRs, config.AutoExportCIDRs) if err != nil { return nil, err } - for _, ip := range filteredIPs { + + for _, ip := range customExtraIPs { uniqueRules[ip] = struct{}{} } } @@ -1717,6 +1749,11 @@ func ValidateNASDriver( return fmt.Errorf("failed to validate auto-export CIDR(s): %w", err) } + // Ensure config has a set of valid customExportCIDRs + if err := network.ValidateCIDRs(ctx, config.CustomExtraExportCIDRs); err != nil { + return fmt.Errorf("failed to validate custom-export CIDR(s): %w", err) + } + return nil } @@ -1893,6 +1930,10 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto config.AutoExportCIDRs = []string{"0.0.0.0/0", "::/0"} } + if len(config.CustomExtraExportCIDRs) == 0 { + config.CustomExtraExportCIDRs = []string{} + } + if len(config.FlexGroupAggregateList) == 0 { config.FlexGroupAggregateList = []string{} } @@ -1963,6 +2004,7 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto "TieringPolicy": config.TieringPolicy, "AutoExportPolicy": config.AutoExportPolicy, "AutoExportCIDRs": config.AutoExportCIDRs, + "CustomExtraExportCIDRs": config.CustomExtraExportCIDRs, "FlexgroupAggregateList": config.FlexGroupAggregateList, "ADAdminUser": config.ADAdminUser, "NameTemplate": config.NameTemplate, @@ -3389,7 +3431,7 @@ func ValidateASAStoragePools( if len(config.AutoExportCIDRs) > 0 { return errors.New("invalid value for autoExportCIDRs") } - + switch config.SANType { case sa.ISCSI: break diff --git a/storage_drivers/types.go b/storage_drivers/types.go index ca3c74dbe..a96ea03c7 100644 --- a/storage_drivers/types.go +++ b/storage_drivers/types.go @@ -133,6 +133,7 @@ type OntapStorageDriverConfig struct { DenyNewVolumePools string `json:"denyNewVolumePools"` AutoExportPolicy bool `json:"autoExportPolicy"` AutoExportCIDRs []string `json:"autoExportCIDRs"` + CustomExtraExportCIDRs []string `json:"customExtraExportCIDRs"` OntapStorageDriverPool Storage []OntapStorageDriverPool `json:"storage"` UseCHAP bool `json:"useCHAP"` diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml index d32f75cfd..e8c3238ed 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml @@ -23,6 +23,9 @@ spec: limitAggregateUsage: 80% limitVolumeSize: 50Gi nfsMountOptions: nfsvers=4 + useRest: true + # customExtraExportCIDRs: + # - 192.168.0.0/24 defaults: spaceReserve: volume exportPolicy: myk8scluster diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml index 8f1b4c15f..8931c7331 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml @@ -20,6 +20,9 @@ spec: svm: trident_svm autoExportCIDRs: - 192.168.0.0/24 + # customExtraExportCIDRs: + # - 192.168.0.0/24 autoExportPolicy: true + # useRest: true credentials: name: backend-tbc-ontap-nas-autoexport-secret diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml index afefb713f..f253df87c 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml @@ -17,6 +17,7 @@ spec: managementLIF: 10.0.0.1 dataLIF: 10.0.0.2 backendName: tbc-ontap-nas-virtual-pools + useRest: true svm: trident_svm credentials: name: backend-tbc-ontap-nas-virtual-pools-secret diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml index 62c3fa895..8160a907c 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml @@ -18,5 +18,8 @@ spec: dataLIF: 10.0.0.2 backendName: tbc-ontap-nas svm: trident_svm + # useRest: true + # customExtraExportCIDRs: + # - 192.168.0.0/24 credentials: name: backend-tbc-ontap-nas-secret From 72858233569cfdfca90b535f2769ded7950a8aec Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 14:27:42 +0200 Subject: [PATCH 02/11] feat: Added Custom Export ClientIPs in Trident Backend Config --- pkg/network/network.go | 24 +++++++++++++++++++ storage_drivers/ontap/ontap_common.go | 24 +++++++++---------- storage_drivers/types.go | 2 +- .../backend-tbc-ontap-nas-advanced.yaml | 2 +- .../backend-tbc-ontap-nas-autoexport.yaml | 2 +- .../ontap-nas/backend-tbc-ontap-nas.yaml | 2 +- 6 files changed, 40 insertions(+), 16 deletions(-) diff --git a/pkg/network/network.go b/pkg/network/network.go index 27ffe5c75..43e89b901 100644 --- a/pkg/network/network.go +++ b/pkg/network/network.go @@ -42,6 +42,30 @@ func ValidateCIDRs(ctx context.Context, cidrs []string) error { return err } +// ValidateIPs parses a slice of strings, attempting to convert each into a net.IP. +// It returns a slice of parsed net.IP addresses and a multi-error for any parsing failures. +func ValidateIPs(ctx context.Context, ipStrings []string) error { + var err error + errors := make([]error, 0) + + for _, ipStr := range ipStrings { + // net.ParseIP parses s as an IP address, returning the result. + // If s is not a valid IP address, ParseIP returns nil. + ip := net.ParseIP(ipStr) + if ip == nil { + errors = append(errors, fmt.Errorf("found an invalid IP: %s", ipStr)) + logging.Logc(ctx).WithError(fmt.Errorf("found an invalid IP: %s", ipStr)).Error("Found an invalid IP.") + } + } + + if len(errors) != 0 { + err = multierr.Combine(errors...) + return err + } + + return err +} + // FilterIPs takes a list of IPs and CIDRs and returns the sorted list of IPs that are contained by one or more of the // CIDRs func FilterIPs(ctx context.Context, ips, cidrs []string) ([]string, error) { diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index edc3ad4f8..d160d148a 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -412,11 +412,11 @@ func ensureNodeAccessForPolicy( return err } - // Add CustomExtraExportCIDRs if they exist - if len(config.CustomExtraExportCIDRs) > 0 { - extraCustomRules, err := network.FilterIPs(ctx, config.CustomExtraExportCIDRs, config.AutoExportCIDRs) + // Add CustomExportClientIPs if they exist + if len(config.CustomExportClientIPs) > 0 { + extraCustomRules, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) if err != nil { - err = fmt.Errorf("unable to filter customExportPolicyCIDRs; %v", err) + err = fmt.Errorf("unable to filter customExportClientIPs; %v", err) Logc(ctx).Error(err) return err } @@ -508,10 +508,10 @@ func getDesiredExportPolicyRules( } } - if len(config.CustomExtraExportCIDRs) > 0 { + if len(config.CustomExportClientIPs) > 0 { - // Filter the CustomExtraExportCIDRs based on the AutoExportCIDRs provided by user - customExtraIPs, err := network.FilterIPs(ctx, config.CustomExtraExportCIDRs, config.AutoExportCIDRs) + // Filter the CustomExportClientIPs based on the AutoExportCIDRs provided by user + customExtraIPs, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) if err != nil { return nil, err } @@ -1750,8 +1750,8 @@ func ValidateNASDriver( } // Ensure config has a set of valid customExportCIDRs - if err := network.ValidateCIDRs(ctx, config.CustomExtraExportCIDRs); err != nil { - return fmt.Errorf("failed to validate custom-export CIDR(s): %w", err) + if err := network.ValidateIPs(ctx, config.CustomExportClientIPs); err != nil { + return fmt.Errorf("failed to validate custom export policy client IP(s): %w", err) } return nil @@ -1930,8 +1930,8 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto config.AutoExportCIDRs = []string{"0.0.0.0/0", "::/0"} } - if len(config.CustomExtraExportCIDRs) == 0 { - config.CustomExtraExportCIDRs = []string{} + if len(config.CustomExportClientIPs) == 0 { + config.CustomExportClientIPs = []string{} } if len(config.FlexGroupAggregateList) == 0 { @@ -2004,7 +2004,7 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto "TieringPolicy": config.TieringPolicy, "AutoExportPolicy": config.AutoExportPolicy, "AutoExportCIDRs": config.AutoExportCIDRs, - "CustomExtraExportCIDRs": config.CustomExtraExportCIDRs, + "CustomExportClientIPs": config.CustomExportClientIPs, "FlexgroupAggregateList": config.FlexGroupAggregateList, "ADAdminUser": config.ADAdminUser, "NameTemplate": config.NameTemplate, diff --git a/storage_drivers/types.go b/storage_drivers/types.go index a96ea03c7..02931de6b 100644 --- a/storage_drivers/types.go +++ b/storage_drivers/types.go @@ -133,7 +133,7 @@ type OntapStorageDriverConfig struct { DenyNewVolumePools string `json:"denyNewVolumePools"` AutoExportPolicy bool `json:"autoExportPolicy"` AutoExportCIDRs []string `json:"autoExportCIDRs"` - CustomExtraExportCIDRs []string `json:"customExtraExportCIDRs"` + CustomExportClientIPs []string `json:"customExportClientIPs"` OntapStorageDriverPool Storage []OntapStorageDriverPool `json:"storage"` UseCHAP bool `json:"useCHAP"` diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml index e8c3238ed..56e5994e1 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml @@ -24,7 +24,7 @@ spec: limitVolumeSize: 50Gi nfsMountOptions: nfsvers=4 useRest: true - # customExtraExportCIDRs: + # customExportClientIPs: # - 192.168.0.0/24 defaults: spaceReserve: volume diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml index 8931c7331..169ba05a9 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml @@ -20,7 +20,7 @@ spec: svm: trident_svm autoExportCIDRs: - 192.168.0.0/24 - # customExtraExportCIDRs: + # customExportClientIPs: # - 192.168.0.0/24 autoExportPolicy: true # useRest: true diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml index 8160a907c..bc5e5f829 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml @@ -19,7 +19,7 @@ spec: backendName: tbc-ontap-nas svm: trident_svm # useRest: true - # customExtraExportCIDRs: + # customExportClientIPs: # - 192.168.0.0/24 credentials: name: backend-tbc-ontap-nas-secret From 2cc77eccda1508dc533f9b3c52f864a40abd2292 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 14:35:22 +0200 Subject: [PATCH 03/11] feat: Added Custom Export ClientIPs in Trident Backend Config --- pkg/network/network.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/network/network.go b/pkg/network/network.go index 43e89b901..d2525e8a0 100644 --- a/pkg/network/network.go +++ b/pkg/network/network.go @@ -42,15 +42,14 @@ func ValidateCIDRs(ctx context.Context, cidrs []string) error { return err } -// ValidateIPs parses a slice of strings, attempting to convert each into a net.IP. -// It returns a slice of parsed net.IP addresses and a multi-error for any parsing failures. +// ValidateIPs parses a list of IPs, attempting to validate them with net.ParseIP. +// It returns error in case the IPs are not valid. func ValidateIPs(ctx context.Context, ipStrings []string) error { var err error errors := make([]error, 0) for _, ipStr := range ipStrings { - // net.ParseIP parses s as an IP address, returning the result. - // If s is not a valid IP address, ParseIP returns nil. + // net.ParseIP parses strings as an IP address, returning nil if error. ip := net.ParseIP(ipStr) if ip == nil { errors = append(errors, fmt.Errorf("found an invalid IP: %s", ipStr)) From 30a0d29c4ad190628192a6b279afb4d4aa84574e Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 14:54:02 +0200 Subject: [PATCH 04/11] fix: fix examples to ip instead of cidr. --- .../ontap-nas/backend-tbc-ontap-nas-advanced.yaml | 3 ++- .../ontap-nas/backend-tbc-ontap-nas-autoexport.yaml | 4 ++-- .../backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml | 3 --- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml index 56e5994e1..98dd8b5c8 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml @@ -24,8 +24,9 @@ spec: limitVolumeSize: 50Gi nfsMountOptions: nfsvers=4 useRest: true + # useRest: true # customExportClientIPs: - # - 192.168.0.0/24 + # - 192.168.0.1 defaults: spaceReserve: volume exportPolicy: myk8scluster diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml index 169ba05a9..fedbde928 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml @@ -20,9 +20,9 @@ spec: svm: trident_svm autoExportCIDRs: - 192.168.0.0/24 - # customExportClientIPs: - # - 192.168.0.0/24 autoExportPolicy: true # useRest: true + # customExportClientIPs: + # - 192.168.0.1 credentials: name: backend-tbc-ontap-nas-autoexport-secret diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml index bc5e5f829..62c3fa895 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas.yaml @@ -18,8 +18,5 @@ spec: dataLIF: 10.0.0.2 backendName: tbc-ontap-nas svm: trident_svm - # useRest: true - # customExportClientIPs: - # - 192.168.0.0/24 credentials: name: backend-tbc-ontap-nas-secret From 2cff9d9caba6d55ef9ca207152b85bcabbe43d11 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 14:55:25 +0200 Subject: [PATCH 05/11] fix: pools on tap virtual yaml example. --- .../ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml index f253df87c..afefb713f 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-virtual-pools.yaml @@ -17,7 +17,6 @@ spec: managementLIF: 10.0.0.1 dataLIF: 10.0.0.2 backendName: tbc-ontap-nas-virtual-pools - useRest: true svm: trident_svm credentials: name: backend-tbc-ontap-nas-virtual-pools-secret From 8fe0746791c8e5ae3a0560336463a2ce4758220a Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 15:49:45 +0200 Subject: [PATCH 06/11] fix: Ensure the export policy exists. If it doesn't, create it --- storage_drivers/ontap/ontap_nas.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/storage_drivers/ontap/ontap_nas.go b/storage_drivers/ontap/ontap_nas.go index f6d9ccebe..b223c117f 100644 --- a/storage_drivers/ontap/ontap_nas.go +++ b/storage_drivers/ontap/ontap_nas.go @@ -1702,12 +1702,13 @@ func (d *NASStorageDriver) reconcileNodeAccessForBackendPolicy( return nil } - if exists, err := d.API.ExportPolicyExists(ctx, policyName); err != nil { - return err - } else if !exists { - Logc(ctx).WithField("ExportPolicy", policyName).Debug("Export policy not found.") - return nil - } + // Ensure the export policy exists. If it doesn't, create it. + // This also handles the case where it might have been deleted out-of-band. + if err := ensureExportPolicyExists(ctx, policyName, d.API); err != nil { + Logc(ctx).WithError(err).WithField("ExportPolicy", policyName). + Error("Error ensuring export policy exists during backend node access reconciliation.") + return fmt.Errorf("error ensuring export policy %s exists: %v", policyName, err) + } desiredRules, err := getDesiredExportPolicyRules(ctx, nodes, &d.Config) if err != nil { From 10c68c63418c0fb0586841124a0fd189b640e8f7 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 16:28:35 +0200 Subject: [PATCH 07/11] fix: removeExportPolicyRules to remove custom export client ips --- storage_drivers/ontap/ontap_common.go | 25 ++++++++++++------------ storage_drivers/ontap/ontap_nas.go | 2 +- storage_drivers/ontap/ontap_nas_qtree.go | 2 +- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index d160d148a..642025492 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -335,14 +335,7 @@ func ensureNodeAccess( config *drivers.OntapStorageDriverConfig, ) error { policyName := getExportPolicyName(publishInfo.BackendUUID) - if exists, err := clientAPI.ExportPolicyExists(ctx, policyName); err != nil { - return err - } else if !exists { - Logc(ctx).WithField("exportPolicy", policyName).Debug("Export policy missing, will create it.") - return reconcileNASNodeAccess(ctx, publishInfo.Nodes, config, clientAPI, policyName) - } - Logc(ctx).WithField("exportPolicy", policyName).Debug("Export policy exists.") - return nil + return reconcileNASNodeAccess(ctx, publishInfo.Nodes, config, clientAPI, policyName) } func reconcileNASNodeAccess( @@ -4952,7 +4945,7 @@ func deleteAutomaticSnapshot( // retrieves its rules and matches the rules that exist to the IP addresses from the node. // Any matched IP addresses will be removed from the export policy. func removeExportPolicyRules( - ctx context.Context, exportPolicy string, publishInfo *tridentmodels.VolumePublishInfo, clientAPI api.OntapAPI, + ctx context.Context, exportPolicy string, publishInfo *tridentmodels.VolumePublishInfo, clientAPI api.OntapAPI, config drivers.OntapStorageDriverConfig ) error { fields := LogFields{ "Method": "removeExportPolicyRules", @@ -4968,10 +4961,18 @@ func removeExportPolicyRules( var removeRuleIndexes []int - nodeIPRules := make(map[string]struct{}) + finalNodes := make(map[string]struct{}) + + //parse host / node ips for _, ip := range publishInfo.HostIP { ip = strings.TrimSpace(ip) - nodeIPRules[ip] = struct{}{} + finalNodes[ip] = struct{}{} + } + + // parse custom export ips + for _, ip := range config.CustomExportClientIPs { + ip = strings.TrimSpace(ip) + finalNodes[ip] = struct{}{} } // Get export policy rules from given policy @@ -5006,7 +5007,7 @@ func removeExportPolicyRules( allMatch := true for _, singleClientMatch := range strings.Split(clientMatch, ",") { singleClientMatch = strings.TrimSpace(singleClientMatch) - if _, match := nodeIPRules[singleClientMatch]; !match { + if _, match := finalNodes[singleClientMatch]; !match { allMatch = false break } diff --git a/storage_drivers/ontap/ontap_nas.go b/storage_drivers/ontap/ontap_nas.go index b223c117f..f41baddf3 100644 --- a/storage_drivers/ontap/ontap_nas.go +++ b/storage_drivers/ontap/ontap_nas.go @@ -945,7 +945,7 @@ func (d *NASStorageDriver) Unpublish( exportPolicy := volConfig.ExportPolicy if exportPolicy == volExportPolicyName { // Remove export policy rules matching the node IP address from the volume level policy - if err = removeExportPolicyRules(ctx, exportPolicy, publishInfo, d.API); err != nil { + if err = removeExportPolicyRules(ctx, exportPolicy, publishInfo, d.API, d.Config); err != nil { Logc(ctx).WithError(err).Errorf("Error cleaning up export policy rules in %s.", exportPolicy) return err } diff --git a/storage_drivers/ontap/ontap_nas_qtree.go b/storage_drivers/ontap/ontap_nas_qtree.go index 7604ff514..1282abcd4 100644 --- a/storage_drivers/ontap/ontap_nas_qtree.go +++ b/storage_drivers/ontap/ontap_nas_qtree.go @@ -892,7 +892,7 @@ func (d *NASQtreeStorageDriver) Unpublish( } if exportPolicy == qtreeName { // Remove export policy rules matching the node IP address from qtree level policy - if err = removeExportPolicyRules(ctx, exportPolicy, publishInfo, d.API); err != nil { + if err = removeExportPolicyRules(ctx, exportPolicy, publishInfo, d.API, d.Config); err != nil { Logc(ctx).WithError(err).Errorf("Error cleaning up export policy rules in %s.", exportPolicy) return err } From 27e1b6962707afd1e71d7cff0de57ca698cfab44 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 16:50:24 +0200 Subject: [PATCH 08/11] fix: ensureExportPolicyExists broken function (revert) --- storage_drivers/ontap/ontap_common.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index 642025492..a379543a1 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -392,11 +392,11 @@ func ensureNodeAccessForPolicy( } else if !exists { Logc(ctx).WithField("exportPolicy", policyName).Debug("Export policy missing, will create it.") - if err = clientAPI.ExportPolicyCreate(ctx, policyName); err != nil { + if err = ensureExportPolicyExists(ctx, policyName, clientAPI); err != nil { return err } } - + desiredRules, err := network.FilterIPs(ctx, targetNode.IPs, config.AutoExportCIDRs) if err != nil { @@ -4945,7 +4945,7 @@ func deleteAutomaticSnapshot( // retrieves its rules and matches the rules that exist to the IP addresses from the node. // Any matched IP addresses will be removed from the export policy. func removeExportPolicyRules( - ctx context.Context, exportPolicy string, publishInfo *tridentmodels.VolumePublishInfo, clientAPI api.OntapAPI, config drivers.OntapStorageDriverConfig + ctx context.Context, exportPolicy string, publishInfo *tridentmodels.VolumePublishInfo, clientAPI api.OntapAPI, config drivers.OntapStorageDriverConfig, ) error { fields := LogFields{ "Method": "removeExportPolicyRules", From 82d6aad0a9eb6e625223e5c016fd551dd35fca0d Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 18:21:07 +0200 Subject: [PATCH 09/11] added enableCustomExportPolicySettings in TridentBackendConfig to enable and disable custom rules and have functionality based on it. --- storage_drivers/ontap/ontap_common.go | 202 ++++++++++-------- storage_drivers/ontap/ontap_nas.go | 13 +- storage_drivers/ontap/ontap_nas_qtree.go | 4 +- storage_drivers/types.go | 3 +- .../backend-tbc-ontap-nas-advanced.yaml | 1 + .../backend-tbc-ontap-nas-autoexport.yaml | 1 + 6 files changed, 127 insertions(+), 97 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index a379543a1..53dafd7f3 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -387,7 +387,8 @@ func ensureNodeAccessForPolicy( exportPolicyMutex.Lock(policyName) defer exportPolicyMutex.Unlock(policyName) - if exists, err := clientAPI.ExportPolicyExists(ctx, policyName); err != nil { + exists, err := clientAPI.ExportPolicyExists(ctx, policyName) + if err != nil { return err } else if !exists { Logc(ctx).WithField("exportPolicy", policyName).Debug("Export policy missing, will create it.") @@ -396,7 +397,7 @@ func ensureNodeAccessForPolicy( return err } } - + desiredRules, err := network.FilterIPs(ctx, targetNode.IPs, config.AutoExportCIDRs) if err != nil { @@ -405,17 +406,20 @@ func ensureNodeAccessForPolicy( return err } - // Add CustomExportClientIPs if they exist - if len(config.CustomExportClientIPs) > 0 { - extraCustomRules, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) - if err != nil { - err = fmt.Errorf("unable to filter customExportClientIPs; %v", err) - Logc(ctx).Error(err) - return err - } + // if EnableCustomExportPolicySettings enabled then + // Add Custom Export Client IPs if they exist. + if config.EnableCustomExportPolicySettings { + if len(config.CustomExportClientIPs) > 0 { + extraCustomRules, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) + if err != nil { + err = fmt.Errorf("unable to filter customExportClientIPs; %v", err) + Logc(ctx).Error(err) + return err + } - // Append the extraCustomRules to desiredRules - desiredRules = append(desiredRules, extraCustomRules...) + // Append the extraCustomRules to desiredRules + desiredRules = append(desiredRules, extraCustomRules...) + } } Logc(ctx).WithField("desiredRules", desiredRules).Debug("Desired export policy rules.") @@ -501,16 +505,19 @@ func getDesiredExportPolicyRules( } } - if len(config.CustomExportClientIPs) > 0 { - - // Filter the CustomExportClientIPs based on the AutoExportCIDRs provided by user - customExtraIPs, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) - if err != nil { - return nil, err - } + // if EnableCustomExportPolicySettings is enabled + // then check if CustomExportClientIPs exists and add IPs to list of desired rules. + if config.EnableCustomExportPolicySettings { + if len(config.CustomExportClientIPs) > 0 { + // Filter the CustomExportClientIPs based on the AutoExportCIDRs provided by user + customExtraIPs, err := network.FilterIPs(ctx, config.CustomExportClientIPs, config.AutoExportCIDRs) + if err != nil { + return nil, err + } - for _, ip := range customExtraIPs { - uniqueRules[ip] = struct{}{} + for _, ip := range customExtraIPs { + uniqueRules[ip] = struct{}{} + } } } @@ -1742,9 +1749,13 @@ func ValidateNASDriver( return fmt.Errorf("failed to validate auto-export CIDR(s): %w", err) } - // Ensure config has a set of valid customExportCIDRs - if err := network.ValidateIPs(ctx, config.CustomExportClientIPs); err != nil { - return fmt.Errorf("failed to validate custom export policy client IP(s): %w", err) + // If EnableCustomExportPolicySettings is enabled then + // Check validity of CustomExportClientIPs + if config.EnableCustomExportPolicySettings { + // Ensure config has a set of valid CustomExportClientIPs + if err := network.ValidateIPs(ctx, config.CustomExportClientIPs); err != nil { + return fmt.Errorf("failed to validate custom export policy client IP(s): %w", err) + } } return nil @@ -1927,6 +1938,10 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto config.CustomExportClientIPs = []string{} } + if !config.EnableCustomExportPolicySettings { + config.EnableCustomExportPolicySettings = false + } + if len(config.FlexGroupAggregateList) == 0 { config.FlexGroupAggregateList = []string{} } @@ -1974,33 +1989,34 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto } logFields := LogFields{ - "SpaceAllocation": config.SpaceAllocation, - "SpaceReserve": config.SpaceReserve, - "SnapshotPolicy": config.SnapshotPolicy, - "SnapshotReserve": config.SnapshotReserve, - "UnixPermissions": config.UnixPermissions, - "SnapshotDir": config.SnapshotDir, - "ExportPolicy": config.ExportPolicy, - "SecurityStyle": config.SecurityStyle, - "NfsMountOptions": config.NfsMountOptions, - "SplitOnClone": config.SplitOnClone, - "CloneSplitDelay": config.CloneSplitDelay, - "FileSystemType": config.FileSystemType, - "Encryption": config.Encryption, - "LUKSEncryption": config.LUKSEncryption, - "Mirroring": config.Mirroring, - "LimitAggregateUsage": config.LimitAggregateUsage, - "LimitVolumeSize": config.LimitVolumeSize, - "LimitVolumePoolSize": config.LimitVolumePoolSize, - "DenyNewVolumePools": config.DenyNewVolumePools, - "Size": config.Size, - "TieringPolicy": config.TieringPolicy, - "AutoExportPolicy": config.AutoExportPolicy, - "AutoExportCIDRs": config.AutoExportCIDRs, - "CustomExportClientIPs": config.CustomExportClientIPs, - "FlexgroupAggregateList": config.FlexGroupAggregateList, - "ADAdminUser": config.ADAdminUser, - "NameTemplate": config.NameTemplate, + "SpaceAllocation": config.SpaceAllocation, + "SpaceReserve": config.SpaceReserve, + "SnapshotPolicy": config.SnapshotPolicy, + "SnapshotReserve": config.SnapshotReserve, + "UnixPermissions": config.UnixPermissions, + "SnapshotDir": config.SnapshotDir, + "ExportPolicy": config.ExportPolicy, + "SecurityStyle": config.SecurityStyle, + "NfsMountOptions": config.NfsMountOptions, + "SplitOnClone": config.SplitOnClone, + "CloneSplitDelay": config.CloneSplitDelay, + "FileSystemType": config.FileSystemType, + "Encryption": config.Encryption, + "LUKSEncryption": config.LUKSEncryption, + "Mirroring": config.Mirroring, + "LimitAggregateUsage": config.LimitAggregateUsage, + "LimitVolumeSize": config.LimitVolumeSize, + "LimitVolumePoolSize": config.LimitVolumePoolSize, + "DenyNewVolumePools": config.DenyNewVolumePools, + "Size": config.Size, + "TieringPolicy": config.TieringPolicy, + "AutoExportPolicy": config.AutoExportPolicy, + "AutoExportCIDRs": config.AutoExportCIDRs, + "EnableCustomExportPolicySettings": config.EnableCustomExportPolicySettings, + "CustomExportClientIPs": config.CustomExportClientIPs, + "FlexgroupAggregateList": config.FlexGroupAggregateList, + "ADAdminUser": config.ADAdminUser, + "NameTemplate": config.NameTemplate, } if config.StoragePrefix != nil { @@ -3424,7 +3440,7 @@ func ValidateASAStoragePools( if len(config.AutoExportCIDRs) > 0 { return errors.New("invalid value for autoExportCIDRs") } - + switch config.SANType { case sa.ISCSI: break @@ -4969,10 +4985,13 @@ func removeExportPolicyRules( finalNodes[ip] = struct{}{} } - // parse custom export ips - for _, ip := range config.CustomExportClientIPs { - ip = strings.TrimSpace(ip) - finalNodes[ip] = struct{}{} + // if EnableCustomExportPolicySettings then add customExportClientIPs to list. + // Parse custom export ips + if config.EnableCustomExportPolicySettings { + for _, ip := range config.CustomExportClientIPs { + ip = strings.TrimSpace(ip) + finalNodes[ip] = struct{}{} + } } // Get export policy rules from given policy @@ -4980,41 +4999,50 @@ func removeExportPolicyRules( if err != nil { return err } + Logc(ctx).WithField("existingExportRules", existingExportRules).Debug("Existing export policy rules.") - // Match list of rules to rule index based on clientMatch address - // ONTAP expects the rule index to delete - for ruleIndex, clientMatch := range existingExportRules { - // For the policy, match the node IP addresses to the clientMatch to remove the matched items. - // Example: - // trident_pvc_123 is attached to node1 and node2. The policy is being unpublished from node1. - // node1 IP addresses [1.1.1.0, 1.1.1.1] node2 IP addresses [2.2.2.0, 2.2.2.2]. - // export policy "trident_pvc_123" should have the export rules: - // index 1: "1.1.1.0" - // index 2: "1.1.1.1" - // index 3: "2.2.2.0" - // index 4: "2.2.2.2" - // When the clientMatch is the same as the node IP that export rule index will be added to the list of - // indexes to be removed. For this example indexes 1 and 2 will be removed. - - // Legacy export policies created via ZAPI will have multiple clientMatch IPs for a node in a single rule. - // index 1: "1.1.1.0, 1.1.1.1" - // index 2: "2.2.2.0, 2.2.2.2" - // For this example, index 1 will be removed. - - // Add a ruleIndex for deletion only if ALL the IPs in the clientMatch are in the list of IPs we are trying - // to delete - allMatch := true - for _, singleClientMatch := range strings.Split(clientMatch, ",") { - singleClientMatch = strings.TrimSpace(singleClientMatch) - if _, match := finalNodes[singleClientMatch]; !match { - allMatch = false - break - } - } - if allMatch { + // If CustomExportClientIPs were defined + if config.EnableCustomExportPolicySettings { + // Remove all rules + for ruleIndex := range existingExportRules { removeRuleIndexes = append(removeRuleIndexes, ruleIndex) } + } else { + // Match list of rules to rule index based on clientMatch address + // ONTAP expects the rule index to delete + for ruleIndex, clientMatch := range existingExportRules { + // For the policy, match the node IP addresses to the clientMatch to remove the matched items. + // Example: + // trident_pvc_123 is attached to node1 and node2. The policy is being unpublished from node1. + // node1 IP addresses [1.1.1.0, 1.1.1.1] node2 IP addresses [2.2.2.0, 2.2.2.2]. + // export policy "trident_pvc_123" should have the export rules: + // index 1: "1.1.1.0" + // index 2: "1.1.1.1" + // index 3: "2.2.2.0" + // index 4: "2.2.2.2" + // When the clientMatch is the same as the node IP that export rule index will be added to the list of + // indexes to be removed. For this example indexes 1 and 2 will be removed. + + // Legacy export policies created via ZAPI will have multiple clientMatch IPs for a node in a single rule. + // index 1: "1.1.1.0, 1.1.1.1" + // index 2: "2.2.2.0, 2.2.2.2" + // For this example, index 1 will be removed. + + // Add a ruleIndex for deletion only if ALL the IPs in the clientMatch are in the list of IPs we are trying + // to delete + allMatch := true + for _, singleClientMatch := range strings.Split(clientMatch, ",") { + singleClientMatch = strings.TrimSpace(singleClientMatch) + if _, match := finalNodes[singleClientMatch]; !match { + allMatch = false + break + } + } + if allMatch { + removeRuleIndexes = append(removeRuleIndexes, ruleIndex) + } + } } // Attempt to remove node IP addresses from export policy rules diff --git a/storage_drivers/ontap/ontap_nas.go b/storage_drivers/ontap/ontap_nas.go index f41baddf3..d924413b4 100644 --- a/storage_drivers/ontap/ontap_nas.go +++ b/storage_drivers/ontap/ontap_nas.go @@ -1702,13 +1702,12 @@ func (d *NASStorageDriver) reconcileNodeAccessForBackendPolicy( return nil } - // Ensure the export policy exists. If it doesn't, create it. - // This also handles the case where it might have been deleted out-of-band. - if err := ensureExportPolicyExists(ctx, policyName, d.API); err != nil { - Logc(ctx).WithError(err).WithField("ExportPolicy", policyName). - Error("Error ensuring export policy exists during backend node access reconciliation.") - return fmt.Errorf("error ensuring export policy %s exists: %v", policyName, err) - } + // Ensure the export policy exists. If it doesn't, create it. + // This also handles the case where it might have been deleted out-of-band. + if err := ensureExportPolicyExists(ctx, policyName, d.API); err != nil { + Logc(ctx).WithError(err).WithField("ExportPolicy", policyName).Error("Error ensuring export policy exists during backend node access reconciliation.") + return fmt.Errorf("error ensuring export policy %s exists: %v", policyName, err) + } desiredRules, err := getDesiredExportPolicyRules(ctx, nodes, &d.Config) if err != nil { diff --git a/storage_drivers/ontap/ontap_nas_qtree.go b/storage_drivers/ontap/ontap_nas_qtree.go index 1282abcd4..e54760a4f 100644 --- a/storage_drivers/ontap/ontap_nas_qtree.go +++ b/storage_drivers/ontap/ontap_nas_qtree.go @@ -1810,7 +1810,7 @@ func (d *NASQtreeStorageDriver) reapDeletedQtrees(ctx context.Context) { func (d *NASQtreeStorageDriver) ensureDefaultExportPolicy(ctx context.Context) error { err := d.API.ExportPolicyCreate(ctx, d.flexvolExportPolicy) if err != nil { - return fmt.Errorf("error creating export policy %s: %v", d.flexvolExportPolicy, err) + return fmt.Errorf("error creating default export policy %s: %v", d.flexvolExportPolicy, err) } return d.ensureDefaultExportPolicyRule(ctx) } @@ -1821,7 +1821,7 @@ func (d *NASQtreeStorageDriver) ensureDefaultExportPolicy(ctx context.Context) e func (d *NASQtreeStorageDriver) ensureDefaultExportPolicyRule(ctx context.Context) error { ruleList, err := d.API.ExportRuleList(ctx, d.flexvolExportPolicy) if err != nil { - return fmt.Errorf("error listing export policy rules: %v", err) + return fmt.Errorf("error listing default export policy rules: %v", err) } if len(ruleList) == 0 { diff --git a/storage_drivers/types.go b/storage_drivers/types.go index 02931de6b..5060aab9b 100644 --- a/storage_drivers/types.go +++ b/storage_drivers/types.go @@ -133,7 +133,8 @@ type OntapStorageDriverConfig struct { DenyNewVolumePools string `json:"denyNewVolumePools"` AutoExportPolicy bool `json:"autoExportPolicy"` AutoExportCIDRs []string `json:"autoExportCIDRs"` - CustomExportClientIPs []string `json:"customExportClientIPs"` + CustomExportClientIPs []string `json:"customExportClientIPs"` + EnableCustomExportPolicySettings bool `json:"enableCustomExportPolicySettings"` OntapStorageDriverPool Storage []OntapStorageDriverPool `json:"storage"` UseCHAP bool `json:"useCHAP"` diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml index 98dd8b5c8..4e1a2176b 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-advanced.yaml @@ -25,6 +25,7 @@ spec: nfsMountOptions: nfsvers=4 useRest: true # useRest: true + # enableCustomExportPolicySettings: true # customExportClientIPs: # - 192.168.0.1 defaults: diff --git a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml index fedbde928..b6a1a3951 100644 --- a/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml +++ b/trident-installer/sample-input/backends-samples/ontap-nas/backend-tbc-ontap-nas-autoexport.yaml @@ -22,6 +22,7 @@ spec: - 192.168.0.0/24 autoExportPolicy: true # useRest: true + # enableCustomExportPolicySettings: true # customExportClientIPs: # - 192.168.0.1 credentials: From b53e2725f67d48435de2581d8db3a62605aeca27 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 18:45:06 +0200 Subject: [PATCH 10/11] extra print fields. --- storage_drivers/ontap/ontap_common.go | 64 ++++++++++++++------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index 53dafd7f3..5f6be7a52 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -375,10 +375,12 @@ func ensureNodeAccessForPolicy( config *drivers.OntapStorageDriverConfig, policyName string, ) error { fields := LogFields{ - "Method": "ensureNodeAccessForPolicy", - "Type": "ontap_common", - "policyName": policyName, - "targetNodeIPs": targetNode.IPs, + "Method": "ensureNodeAccessForPolicy", + "Type": "ontap_common", + "policyName": policyName, + "targetNodeIPs": targetNode.IPs, + "EnableCustomExportPolicySettings": config.EnableCustomExportPolicySettings, + "CustomExportClientIPs": config.CustomExportClientIPs, } Logc(ctx).WithFields(fields).Debug(">>>> ensureNodeAccessForPolicy") @@ -1989,34 +1991,34 @@ func PopulateConfigurationDefaults(ctx context.Context, config *drivers.OntapSto } logFields := LogFields{ - "SpaceAllocation": config.SpaceAllocation, - "SpaceReserve": config.SpaceReserve, - "SnapshotPolicy": config.SnapshotPolicy, - "SnapshotReserve": config.SnapshotReserve, - "UnixPermissions": config.UnixPermissions, - "SnapshotDir": config.SnapshotDir, - "ExportPolicy": config.ExportPolicy, - "SecurityStyle": config.SecurityStyle, - "NfsMountOptions": config.NfsMountOptions, - "SplitOnClone": config.SplitOnClone, - "CloneSplitDelay": config.CloneSplitDelay, - "FileSystemType": config.FileSystemType, - "Encryption": config.Encryption, - "LUKSEncryption": config.LUKSEncryption, - "Mirroring": config.Mirroring, - "LimitAggregateUsage": config.LimitAggregateUsage, - "LimitVolumeSize": config.LimitVolumeSize, - "LimitVolumePoolSize": config.LimitVolumePoolSize, - "DenyNewVolumePools": config.DenyNewVolumePools, - "Size": config.Size, - "TieringPolicy": config.TieringPolicy, - "AutoExportPolicy": config.AutoExportPolicy, - "AutoExportCIDRs": config.AutoExportCIDRs, + "SpaceAllocation": config.SpaceAllocation, + "SpaceReserve": config.SpaceReserve, + "SnapshotPolicy": config.SnapshotPolicy, + "SnapshotReserve": config.SnapshotReserve, + "UnixPermissions": config.UnixPermissions, + "SnapshotDir": config.SnapshotDir, + "ExportPolicy": config.ExportPolicy, + "SecurityStyle": config.SecurityStyle, + "NfsMountOptions": config.NfsMountOptions, + "SplitOnClone": config.SplitOnClone, + "CloneSplitDelay": config.CloneSplitDelay, + "FileSystemType": config.FileSystemType, + "Encryption": config.Encryption, + "LUKSEncryption": config.LUKSEncryption, + "Mirroring": config.Mirroring, + "LimitAggregateUsage": config.LimitAggregateUsage, + "LimitVolumeSize": config.LimitVolumeSize, + "LimitVolumePoolSize": config.LimitVolumePoolSize, + "DenyNewVolumePools": config.DenyNewVolumePools, + "Size": config.Size, + "TieringPolicy": config.TieringPolicy, + "AutoExportPolicy": config.AutoExportPolicy, + "AutoExportCIDRs": config.AutoExportCIDRs, "EnableCustomExportPolicySettings": config.EnableCustomExportPolicySettings, - "CustomExportClientIPs": config.CustomExportClientIPs, - "FlexgroupAggregateList": config.FlexGroupAggregateList, - "ADAdminUser": config.ADAdminUser, - "NameTemplate": config.NameTemplate, + "CustomExportClientIPs": config.CustomExportClientIPs, + "FlexgroupAggregateList": config.FlexGroupAggregateList, + "ADAdminUser": config.ADAdminUser, + "NameTemplate": config.NameTemplate, } if config.StoragePrefix != nil { From 85abe59d30e5d3093f5973982629f294d270bd85 Mon Sep 17 00:00:00 2001 From: Nikolaos Astyrakakis Date: Thu, 28 Aug 2025 20:18:50 +0200 Subject: [PATCH 11/11] feat: created code in ReconcileVolumeNodeAccess. added EnableCustomExportPolicySettings where needed --- core/concurrent_core.go | 3 +++ storage_drivers/ontap/ontap_common.go | 2 ++ storage_drivers/ontap/ontap_nas.go | 37 ++++++++++++++++++++++++--- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/concurrent_core.go b/core/concurrent_core.go index aeb305161..3df5b157d 100644 --- a/core/concurrent_core.go +++ b/core/concurrent_core.go @@ -1596,6 +1596,9 @@ func (o *ConcurrentTridentOrchestrator) updateBackendVolumes(ctx context.Context // Update volume cache on backend. backend.Volumes().Store(vol.Config.Name, vol) + + // Update volume based access policy when backend reloads. + backend.ReconcileVolumeNodeAccess(ctx, vol.Config, volResult.Nodes) } // update the backend cache diff --git a/storage_drivers/ontap/ontap_common.go b/storage_drivers/ontap/ontap_common.go index 5f6be7a52..95535d01d 100644 --- a/storage_drivers/ontap/ontap_common.go +++ b/storage_drivers/ontap/ontap_common.go @@ -473,6 +473,7 @@ func ensureNodeAccessForPolicy( // Rule does not exist, so create it if !ruleFound { + // Create Export Rule if err = clientAPI.ExportRuleCreate(ctx, policyName, desiredRule, config.NASType); err != nil { // Check if error is that the export policy rule already exist error if errors.IsAlreadyExistsError(err) { @@ -628,6 +629,7 @@ func reconcileExportPolicyRules( } deleted++ } + return nil } diff --git a/storage_drivers/ontap/ontap_nas.go b/storage_drivers/ontap/ontap_nas.go index d924413b4..5886da161 100644 --- a/storage_drivers/ontap/ontap_nas.go +++ b/storage_drivers/ontap/ontap_nas.go @@ -1726,14 +1726,45 @@ func (d *NASStorageDriver) reconcileNodeAccessForBackendPolicy( } func (d *NASStorageDriver) ReconcileVolumeNodeAccess( - ctx context.Context, _ *storage.VolumeConfig, _ []*models.Node, + ctx context.Context, volConfig *storage.VolumeConfig, nodes []*models.Node, ) error { + + if !d.Config.AutoExportPolicy { + return nil + } + + policyName := volConfig.ExportPolicy + fields := LogFields{ "Method": "ReconcileVolumeNodeAccess", "Type": "NASStorageDriver", + "policyName": policyName, + } + + Logc(ctx).WithFields(fields).Debug(">>>>>> ReconcileVolumeNodeAccess") + defer Logc(ctx).Debug("<<<<<< ReconcileVolumeNodeAccess") + + + // Ensure the export policy exists. If it doesn't, create it. + // This also handles the case where it might have been deleted out-of-band. + if err := ensureExportPolicyExists(ctx, policyName, d.API); err != nil { + Logc(ctx).WithError(err).WithField("ExportPolicy", policyName).Error("Error ensuring export policy exists during volume node access reconciliation.") + return fmt.Errorf("error ensuring export policy %s exists: %v", policyName, err) + } + + desiredRules, err := getDesiredExportPolicyRules(ctx, nodes, &d.Config) + if err != nil { + err = fmt.Errorf("unable to determine desired export policy rules; %v", err) + Logc(ctx).Error(err) + return err + } + + err = reconcileExportPolicyRules(ctx, policyName, desiredRules, d.API, &d.Config) + if err != nil { + err = fmt.Errorf("unabled to reconcile export policy rules; %v", err) + Logc(ctx).WithField("ExportPolicy", policyName).Error(err) + return err } - Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace(">>>> ReconcileVolumeNodeAccess") - defer Logd(ctx, d.Name(), d.Config.DebugTraceFlags["method"]).WithFields(fields).Trace("<<<< ReconcileVolumeNodeAccess") return nil }