5
5
from cinder import interface
6
6
from cinder .objects import volume_type as vol_type_obj
7
7
from cinder .volume import driver as volume_driver
8
- from cinder .volume .drivers .netapp import options
8
+ from cinder .volume .drivers .netapp import options as na_opts
9
9
from cinder .volume .drivers .netapp .dataontap .client .client_cmode_rest import (
10
10
RestClient as RestNaServer ,
11
11
)
21
21
# Configuration options for dynamic NetApp driver
22
22
# Using cinder.volume.configuration approach for better abstraction
23
23
NETAPP_DYNAMIC_OPTS = [
24
- options .netapp_proxy_opts ,
25
- options .netapp_connection_opts ,
26
- options .netapp_transport_opts ,
27
- options .netapp_basicauth_opts ,
28
- options .netapp_provisioning_opts ,
29
- options .netapp_cluster_opts ,
30
- options .netapp_san_opts ,
31
- volume_driver .volume_opts ,
24
+ na_opts .netapp_connection_opts ,
25
+ na_opts .netapp_basicauth_opts ,
26
+ na_opts .netapp_transport_opts ,
27
+ na_opts .netapp_provisioning_opts ,
28
+ na_opts .netapp_support_opts ,
29
+ na_opts .netapp_san_opts ,
30
+ na_opts .netapp_cluster_opts ,
32
31
]
33
32
34
33
@@ -40,84 +39,18 @@ class NetappDynamicLibrary(NetAppNVMeStorageLibrary):
40
39
- Ours: Multiple SVMs per backend, SVM name from volume type
41
40
"""
42
41
42
+ REQUIRED_CMODE_FLAGS = []
43
+
43
44
def __init__ (self , * args , ** kwargs ):
44
45
"""Initialize driver without creating SVM connections.
45
46
46
47
Parent driver creates static connections during init. We defer
47
48
SVM connections until volume creation when we know which SVM to use.
48
49
"""
49
- self . initialized = False
50
+ super (). __init__ ( * args , ** kwargs )
50
51
self .client = None
51
- driver_name = kwargs .pop ("driver_name" , "NetAppDynamicNVMe" )
52
- driver_protocol = kwargs .pop ("driver_protocol" , "nvme" )
53
- self .app_version = kwargs .get ("app_version" , "1.0.0" )
54
-
55
- self ._setup_configuration (** kwargs )
56
-
57
- super ().__init__ (driver_name , driver_protocol , ** kwargs )
58
52
self .ssc_library = None
59
53
self .perf_library = None
60
- self .init_capabilities ()
61
-
62
- def _setup_configuration (self , ** kwargs ):
63
- """Setup configuration using cinder.volume.configuration module."""
64
- from cinder .volume import configuration
65
-
66
- config_obj = kwargs .get ("configuration" , None )
67
-
68
- if config_obj :
69
- # here we can access any cinder-provided config .
70
- self .configuration = config_obj
71
- config_group = getattr (config_obj , "config_group" , "netapp_nvme" )
72
-
73
- # Register NetApp-specific options using configuration.append()
74
- # Following the exact pattern from upstream NetApp drivers
75
-
76
- try :
77
- for opt_group in NETAPP_DYNAMIC_OPTS :
78
- self .configuration .append_config_values (opt_group )
79
-
80
- LOG .info (
81
- "Registered NetApp configuration options for group: %s" ,
82
- config_group ,
83
- )
84
-
85
- except Exception as e :
86
- LOG .warning ("Failed to register configuration options: %s" , e )
87
- # Continue default configuration handling for backward compatibility
88
- else :
89
- # Testing/Fallback: Create configuration object with all options
90
- config_group = "netapp_nvme"
91
- self .configuration = configuration .Configuration (
92
- volume_driver .volume_opts , config_group = config_group
93
- )
94
-
95
- # Register additional NetApp options for testing
96
- try :
97
- for opt_group in NETAPP_DYNAMIC_OPTS :
98
- if (
99
- opt_group != volume_driver .volume_opts
100
- ): # Avoid duplicate registration
101
- self .configuration .append_config_values (opt_group )
102
-
103
- LOG .info (
104
- "Registered NetApp configuration options for testing group: %s" ,
105
- config_group ,
106
- )
107
-
108
- except Exception as e :
109
- LOG .warning (
110
- "Failed to register configuration options for testing: %s" , e
111
- )
112
-
113
- @property
114
- def supported (self ):
115
- # Used by Cinder to determine whether this driver is active/enabled
116
- return True
117
-
118
- def get_version (self ):
119
- # Called at Cinder service startup to report backend driver version
120
- return "NetappCinderDynamicDriver 1.0"
121
54
122
55
def do_setup (self , context ):
123
56
"""Skip static NetApp connections, defer to volume creation time."""
@@ -132,22 +65,6 @@ def check_for_setup_error(self):
132
65
"""Skip static validation since we connect to SVMs dynamically."""
133
66
pass
134
67
135
- def init_capabilities (self ):
136
- """Set driver capabilities for Cinder scheduler."""
137
- max_over_subscription_ratio = self .configuration .max_over_subscription_ratio
138
- self ._capabilities = {
139
- "thin_provisioning_support" : True ,
140
- "thick_provisioning_support" : True ,
141
- "multiattach" : True ,
142
- "snapshot_support" : True ,
143
- "max_over_subscription_ratio" : max_over_subscription_ratio ,
144
- }
145
- self .capabilities = self ._capabilities
146
-
147
- def set_initialized (self ):
148
- """Mark driver as ready for volume operations."""
149
- self .initialized = True
150
-
151
68
def _get_all_svm_clients_from_volume_types (self ):
152
69
"""Connect to all SVMs found in volume type metadata."""
153
70
svm_clients = {}
@@ -539,37 +456,6 @@ def get_goodness_function(self):
539
456
"""Return the goodness function for Cinder's scheduler scoring."""
540
457
return self .configuration .safe_get ("goodness_function" ) or None
541
458
542
- def update_provider_info (self , * args , ** kwargs ):
543
- """Update provider info for existing volumes.
544
-
545
- This is called during service startup to sync our view of volumes
546
- with what's actually on the storage. The parent class has some
547
- weird argument handling, so we have to be defensive here.
548
- """
549
- # Called during _sync_provider_info() in VolumeManager.
550
- # If not implemented, Cinder raises a TypeError during service startup.
551
- # Wrote this logic because it was registered with 3 and was called using 2 args
552
- # There is issue with in-built drivers calling logic
553
- if len (args ) == 2 :
554
- volumes , snapshots = args
555
- elif len (args ) >= 3 :
556
- _ , volumes , snapshots = args [:3 ]
557
- else :
558
- raise TypeError (
559
- "update_provider_info() expects at least volumes and snapshots."
560
- )
561
- return {}, {}
562
-
563
- def set_throttle (self ):
564
- """No-op throttle implementation to prevent AttributeError.
565
-
566
- Some parts of Cinder expect this method to exist for rate limiting,
567
- but our driver doesn't implement throttling. This empty method
568
- prevents crashes when Cinder tries to call it.
569
- """
570
- # Got AttributeError
571
- pass
572
-
573
459
def _get_flexvol_capacity_with_fallback (self , client , vol_name ):
574
460
"""Get FlexVol capacity with custom volume name to junction path mapping."""
575
461
# TODO : find a API endpoint to fetch the junction path with svm and pool
@@ -981,6 +867,11 @@ def __init__(self, *args, **kwargs):
981
867
super ().__init__ (* args , ** kwargs )
982
868
self .library = NetappDynamicLibrary (self .DRIVER_NAME , "NVMe" , ** kwargs )
983
869
870
+ @staticmethod
871
+ def get_driver_options ():
872
+ """All options this driver supports."""
873
+ return [item for sublist in NETAPP_DYNAMIC_OPTS for item in sublist ]
874
+
984
875
def do_setup (self , context ):
985
876
"""Setup the driver."""
986
877
self .library .do_setup (context )
@@ -1029,10 +920,6 @@ def get_volume_stats(self, refresh=False):
1029
920
"""Get volume stats."""
1030
921
return self .library .get_volume_stats (refresh )
1031
922
1032
- def update_provider_info (self , volumes , snapshots ):
1033
- """Update provider info."""
1034
- return self .library .update_provider_info (volumes , snapshots )
1035
-
1036
923
def create_export (self , context , volume , connector ):
1037
924
"""Create export for volume."""
1038
925
return self .library .create_export (context , volume , connector )
@@ -1044,12 +931,3 @@ def ensure_export(self, context, volume):
1044
931
def remove_export (self , context , volume ):
1045
932
"""Remove export for volume."""
1046
933
return self .library .remove_export (context , volume )
1047
-
1048
-
1049
- # NOTES
1050
- # Namespace: Manually created because we skip standard do_setup()
1051
- # Pool: Custom svm#flexvol format to support multi-SVM
1052
- # Client: Runtime creation based on volume type metadata vs static config
1053
- # Metadata: volume type extra_specs vs cinder.conf
1054
- # Library Initialization: Lazy initialization during volume creation
1055
- # Pool Discovery: Multi-SVM aggregation vs single SVM
0 commit comments