Skip to content

Commit 866eb5f

Browse files
authored
Merge pull request #1187 from rackerlabs/fix-cinder
fix(cinder-understack): correct cleanup and error handling to not be the problem
2 parents 77c88a0 + 50bca11 commit 866eb5f

File tree

2 files changed

+35
-26
lines changed

2 files changed

+35
-26
lines changed

python/cinder-understack/cinder_understack/dynamic_netapp_driver.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -233,18 +233,12 @@ def do_setup(self, ctxt):
233233
svm_lib.do_setup(ctxt)
234234
self._libraries[svm_name] = svm_lib
235235

236-
def _remove_svm_lib(self, svm_name: str, svm_lib: NetAppMinimalLibrary):
236+
def _remove_svm_lib(self, svm_lib: NetAppMinimalLibrary):
237237
"""Remove resources for a given SVM library."""
238238
# TODO: Need to free up resources here.
239-
LOG.info("Removing resources for SVM library %s", svm_name)
240-
# Stop any looping calls if they exist
241-
if svm_lib._looping_call and hasattr(svm_lib, "loopingcalls"):
242-
LOG.info("Stopping looping call for SVM library %s", svm_name)
243-
svm_lib.loopingcalls.stop_tasks()
244-
# Adding None coz it has a reference to the looping call
245-
svm_lib.looping_call = None
246-
# There are other attributes which are in svm_lib even after
247-
# Stopping the looping.
239+
for task in svm_lib.loopingcalls.tasks:
240+
task.looping_call.stop()
241+
svm_lib.loopingcalls.tasks = []
248242

249243
def _refresh_svm_libraries(self):
250244
return self._actual_refresh_svm_libraries(context.get_admin_context())
@@ -262,17 +256,16 @@ def _actual_refresh_svm_libraries(self, ctxt):
262256
stale_svms = existing_libs - current_svms
263257
for svm_name in stale_svms:
264258
LOG.info("Removing stale NVMe library for SVM: %s", svm_name)
265-
# TODO : stop looping calls, free resources.
266-
svm_lib = self._libraries.get(svm_name)
267-
self._remove_svm_lib(svm_name, svm_lib)
259+
svm_lib = self._libraries[svm_name]
260+
self._remove_svm_lib(svm_lib)
268261
del self._libraries[svm_name]
269262

270263
# Add new SVM libraries
271264
new_svms = current_svms - existing_libs
272265
for svm_name in new_svms:
273266
LOG.info("Creating NVMe library for new SVM: %s", svm_name)
267+
lib = self._create_svm_lib(svm_name)
274268
try:
275-
lib = self._create_svm_lib(svm_name)
276269
# Call do_setup to initialize the library
277270
lib.do_setup(ctxt)
278271
lib.check_for_setup_error()
@@ -283,13 +276,21 @@ def _actual_refresh_svm_libraries(self, ctxt):
283276
"Failed to create library for SVM %s",
284277
svm_name,
285278
)
279+
self._remove_svm_lib(lib)
286280
LOG.info("Final libraries loaded: %s", list(self._libraries.keys()))
287281

288282
def check_for_setup_error(self):
289283
"""Check for setup errors."""
290-
for svm_name, svm_lib in self._libraries.items():
284+
svm_to_init = set(self._libraries.keys())
285+
for svm_name in svm_to_init:
291286
LOG.info("Checking NVMe library for errors for SVM %s", svm_name)
292-
svm_lib.check_for_setup_error()
287+
svm_lib = self._libraries[svm_name]
288+
try:
289+
svm_lib.check_for_setup_error()
290+
except Exception:
291+
LOG.exception("Failed to initialize SVM %s, skipping", svm_name)
292+
self._remove_svm_lib(svm_lib)
293+
del self._libraries[svm_name]
293294

294295
# looping call to refresh SVM libraries
295296
if not self._looping_call:

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,20 @@
1010
from cinder.tests.unit import utils as test_utils
1111
from cinder.tests.unit.volume.drivers.netapp import fakes as na_fakes
1212
from cinder.volume.drivers.netapp.dataontap.nvme_library import NetAppNVMeStorageLibrary
13+
from cinder.volume.drivers.netapp.dataontap.utils import loopingcalls
1314

1415
from cinder_understack import dynamic_netapp_driver
1516

1617

18+
def _create_mock_svm_lib(svm_name: str):
19+
mock_lib = mock.create_autospec(
20+
dynamic_netapp_driver.NetAppMinimalLibrary, instance=True
21+
)
22+
mock_lib.vserver = svm_name
23+
mock_lib.loopingcalls = loopingcalls.LoopingCalls()
24+
return mock_lib
25+
26+
1727
class NetappDynamicDriverTestCase(test.TestCase):
1828
"""Test case for NetappCinderDynamicDriver."""
1929

@@ -152,21 +162,16 @@ def test_refresh_svm_libraries_adds_and_removes_svms(
152162
expected_svm = f"os-{self.project_id}"
153163

154164
self.driver._libraries = {
155-
"os-old-svm": mock.Mock(vserver="os-old-svm"),
156-
expected_svm: mock.Mock(vserver=expected_svm),
165+
"os-old-svm": _create_mock_svm_lib("os-old-svm"),
166+
expected_svm: _create_mock_svm_lib(expected_svm),
157167
}
158168

159169
self.driver._get_svms = mock_get_svms
160170
# Returned by _get_svms (after refresh)
161171
mock_get_svms.return_value = [expected_svm, "os-new-svm"]
162172

163173
# make the created lib look like the real thing
164-
mock_lib_instance = mock.create_autospec(
165-
dynamic_netapp_driver.NetAppMinimalLibrary, instance=True
166-
)
167-
168-
# Mock the new lib instance created
169-
mock_lib_instance.vserver = "os-new-svm"
174+
mock_lib_instance = _create_mock_svm_lib("os-new-svm")
170175
mock_create_svm_lib.return_value = mock_lib_instance
171176

172177
# Trigger refresh
@@ -196,8 +201,11 @@ def test_refresh_svm_libraries_handles_lib_creation_failure(
196201
self, mock_get_svms, mock_create_svm_lib
197202
):
198203
"""Ensure that failure in lib creation is caught and logged, not raised."""
199-
mock_get_svms.return_value = ["os-new-failing-svm"]
200-
mock_create_svm_lib.side_effect = Exception("Simulated failure")
204+
test_svm_name = "os-new-failing_svm"
205+
mock_get_svms.return_value = [test_svm_name]
206+
mock_svm_lib = _create_mock_svm_lib(test_svm_name)
207+
mock_svm_lib.check_for_setup_error.side_effect = Exception("Simulated failure")
208+
mock_create_svm_lib.return_value = mock_svm_lib
201209

202210
self.driver._libraries = {}
203211

0 commit comments

Comments
 (0)