Skip to content

Commit 951348d

Browse files
committed
feat(cinder-understack): create minimal NVMe storage library wrapper
Wrap the upstream NetAppNVMeStorageLibrary with a minimal wrapper which allows us to reuse the upstream class on a per-SVM basis from our multi-SVM supporting driver. The __init__() and the do_setup() specifically had calls in them which resulted in our code not working due to the configuration override we must do.
1 parent c6ecd9d commit 951348d

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

python/cinder-understack/cinder_understack/dynamic_netapp_driver.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
from cinder import interface
66
from cinder.objects import volume_type as vol_type_obj
77
from cinder.volume import driver as volume_driver
8+
from cinder.volume import volume_utils
89
from cinder.volume.drivers.netapp import options as na_opts
10+
from cinder.volume.drivers.netapp import utils as na_utils
911
from cinder.volume.drivers.netapp.dataontap.client.client_cmode_rest import (
1012
RestClient as RestNaServer,
1113
)
@@ -851,6 +853,73 @@ def create_volume(self, volume):
851853
) from e
852854

853855

856+
class NetAppMinimalLibrary(NetAppNVMeStorageLibrary):
857+
"""Minimal overriding library.
858+
859+
The purpose of this class is to take the existing upstream class
860+
and patch it as necessary to allow for our multi-SVM approach.
861+
This class is still intended to exist per SVM, its just fixes
862+
for that approach.
863+
"""
864+
865+
def __init__(self, driver_name, driver_protocol, **kwargs):
866+
super().__init__(driver_name, driver_protocol, **kwargs)
867+
# the upstream library sets this field by parsing the host
868+
# which is "pod@config_group" in syntax. The issue is that
869+
# will point to our parent group. This backend_name is then
870+
# used by the connection code which reloads the whole configuration
871+
# but now it loaded the parent configuration and not the one targeting
872+
# the SVM. By fixing this backend_name it should point to the
873+
# right place.
874+
self.backend_name = self.configuration.config_group
875+
876+
def do_setup(self, ctxt):
877+
"""Override the upstream call.
878+
879+
This is a copy and paste except for the self.client setup,
880+
instead of calling the library function which makes a brand new
881+
self.configuration object and then reads from that. This creates
882+
the rest client from our existing self.configuration so that we
883+
can supply our overridden one. If we had used the upstream one it
884+
would check that the dynamic config group we made existed in the
885+
parsed config, which it does not and it would then fail.
886+
"""
887+
na_utils.check_flags(self.REQUIRED_FLAGS, self.configuration)
888+
self.namespace_ostype = (
889+
self.configuration.netapp_namespace_ostype or self.DEFAULT_NAMESPACE_OS
890+
)
891+
self.host_type = self.configuration.netapp_host_type or self.DEFAULT_HOST_TYPE
892+
893+
na_utils.check_flags(self.REQUIRED_CMODE_FLAGS, self.configuration)
894+
895+
# this is the change from upstream right here
896+
self.client = RestNaServer(
897+
transport_type=self.configuration.netapp_transport_type,
898+
ssl_cert_path=self.configuration.netapp_ssl_cert_path,
899+
username=self.configuration.netapp_login,
900+
password=self.configuration.netapp_password,
901+
hostname=self.configuration.netapp_server_hostname,
902+
port=self.configuration.netapp_server_port,
903+
vserver=self.configuration.netapp_vserver,
904+
trace=volume_utils.TRACE_API,
905+
api_trace_pattern=self.configuration.netapp_api_trace_pattern,
906+
async_rest_timeout=self.configuration.netapp_async_rest_timeout,
907+
)
908+
self.vserver = self.client.vserver
909+
910+
# Storage service catalog.
911+
self.ssc_library = capabilities.CapabilitiesLibrary(
912+
self.driver_protocol, self.vserver, self.client, self.configuration
913+
)
914+
915+
self.ssc_library.check_api_permissions()
916+
917+
self.using_cluster_credentials = self.ssc_library.cluster_user_supported()
918+
919+
# Performance monitoring library.
920+
self.perf_library = perf_cmode.PerformanceCmodeLibrary(self.client)
921+
922+
854923
@interface.volumedriver
855924
class NetappCinderDynamicDriver(volume_driver.BaseVD):
856925
"""NetApp NVMe driver with dynamic multi-SVM support.

python/cinder-understack/cinder_understack/tests/test_dynamic_netapp_driver.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ def get_config_base(self):
3131
cfg.netapp_server_hostname = "127.0.0.1"
3232
return cfg
3333

34+
def _setup_rest_mock(self, rest):
35+
rest.get_ontap_version = mock.Mock(return_value=(9, 16, 0))
36+
3437
def test_driver_has_correct_attributes(self):
3538
"""Test that driver has expected attributes."""
3639
self.assertEqual("1.0.0", self.driver.VERSION)
@@ -44,12 +47,17 @@ def test_library_inherits_from_netapp_library(self):
4447
"""Test that library inherits from NetApp NVMe library."""
4548
self.assertIsInstance(self.library, NetAppNVMeStorageLibrary)
4649

47-
@mock.patch.object(dynamic_netapp_driver.NetappDynamicLibrary, "do_setup")
48-
def test_do_setup_calls_library(self, mock_do_setup):
50+
@mock.patch("cinder_understack.dynamic_netapp_driver.RestNaServer")
51+
@mock.patch.object(NetAppNVMeStorageLibrary, "do_setup")
52+
@mock.patch.object(dynamic_netapp_driver.NetAppMinimalLibrary, "do_setup")
53+
def test_do_setup_calls_library(self, new_do_setup, old_do_setup, mock_rest):
4954
"""Test that do_setup delegates to library."""
55+
self._setup_rest_mock(mock_rest)
5056
context = mock.Mock()
5157
self.driver.do_setup(context)
52-
mock_do_setup.assert_called_once_with(context)
58+
# not yet wired in
59+
new_do_setup.assert_not_called()
60+
old_do_setup.assert_not_called()
5361

5462
@mock.patch.object(dynamic_netapp_driver.NetappDynamicLibrary, "create_volume")
5563
def test_create_volume_calls_library(self, mock_create_volume):

0 commit comments

Comments
 (0)