Coverage for manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_single_svm.py: 100%
163 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2015 Clinton Knight. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14"""
15Unit tests for the NetApp Data ONTAP cDOT single-SVM storage driver library.
16"""
18from unittest import mock
20import ddt
21from oslo_log import log
23from manila import exception
24from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion
25from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base
26from manila.share.drivers.netapp.dataontap.cluster_mode import lib_single_svm
27from manila.share.drivers.netapp import utils as na_utils
28from manila import test
29from manila.tests.share.drivers.netapp.dataontap.cluster_mode.test_lib_base\
30 import _get_config
31import manila.tests.share.drivers.netapp.dataontap.fakes as fake
34@ddt.ddt
35class NetAppFileStorageLibraryTestCase(test.TestCase):
37 def setUp(self):
38 super(NetAppFileStorageLibraryTestCase, self).setUp()
40 self.mock_object(na_utils, 'validate_driver_instantiation')
42 # Mock loggers as themselves to allow logger arg validation
43 mock_logger = log.getLogger('mock_logger')
44 self.mock_object(lib_single_svm.LOG,
45 'info',
46 mock.Mock(side_effect=mock_logger.info))
48 config = fake.get_config_cmode()
49 config.netapp_vserver = fake.VSERVER1
51 kwargs = {
52 'configuration': config,
53 'private_storage': mock.Mock(),
54 'app_version': fake.APP_VERSION
55 }
57 self.library = lib_single_svm.NetAppCmodeSingleSVMFileStorageLibrary(
58 fake.DRIVER_NAME, **kwargs)
60 self.library._client = mock.Mock()
61 self.client = self.library._client
63 def test_init(self):
64 self.assertEqual(fake.VSERVER1, self.library._vserver)
66 def test_check_for_setup_error(self):
68 self.library._client.vserver_exists.return_value = True
69 self.library._have_cluster_creds = True
70 mock_client = mock.Mock()
71 mock_client.list_vserver_aggregates.return_value = fake.AGGREGATES
72 self.mock_object(self.library,
73 '_get_api_client',
74 mock.Mock(return_value=mock_client))
75 mock_init_flexgroup = self.mock_object(self.library,
76 '_initialize_flexgroup_pools')
77 self.mock_object(self.library,
78 'is_flexvol_pool_configured',
79 mock.Mock(return_value=True))
80 self.mock_object(self.library,
81 '_find_matching_aggregates',
82 mock.Mock(return_value=fake.AGGREGATES))
83 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
84 'check_for_setup_error')
86 self.library.check_for_setup_error()
88 self.assertTrue(lib_single_svm.LOG.info.called)
89 mock_super.assert_called_once_with()
90 mock_client.list_vserver_aggregates.assert_called_once_with()
91 self.assertTrue(self.library._get_api_client.called)
92 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
93 self.assertTrue(self.library.is_flexvol_pool_configured.called)
94 self.assertTrue(self.library._find_matching_aggregates.called)
96 def test_check_for_setup_error_no_vserver(self):
97 self.library._vserver = None
99 self.assertRaises(exception.InvalidInput,
100 self.library.check_for_setup_error)
102 def test_check_for_setup_error_vserver_not_found(self):
103 self.library._client.vserver_exists.return_value = False
105 self.assertRaises(exception.VserverNotFound,
106 self.library.check_for_setup_error)
108 def test_check_for_setup_error_cluster_creds_vserver_match(self):
109 self.library._client.vserver_exists.return_value = True
110 self.library._have_cluster_creds = False
111 self.library._client.list_vservers.return_value = [fake.VSERVER1]
112 mock_client = mock.Mock()
113 mock_client.list_vserver_aggregates.return_value = fake.AGGREGATES
114 self.mock_object(self.library,
115 '_get_api_client',
116 mock.Mock(return_value=mock_client))
117 mock_init_flexgroup = self.mock_object(self.library,
118 '_initialize_flexgroup_pools')
119 self.mock_object(self.library,
120 'is_flexvol_pool_configured',
121 mock.Mock(return_value=True))
122 self.mock_object(self.library,
123 '_find_matching_aggregates',
124 mock.Mock(return_value=fake.AGGREGATES))
125 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
126 'check_for_setup_error')
128 self.library.check_for_setup_error()
130 mock_super.assert_called_once_with()
131 mock_client.list_vserver_aggregates.assert_called_once_with()
132 self.assertTrue(self.library._get_api_client.called)
133 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
134 self.assertTrue(self.library.is_flexvol_pool_configured.called)
135 self.assertTrue(self.library._find_matching_aggregates.called)
137 def test_check_for_setup_error_no_aggregates_no_flexvol_pool(self):
138 self.library._client.vserver_exists.return_value = True
139 self.library._have_cluster_creds = True
140 mock_client = mock.Mock()
141 mock_client.list_vserver_aggregates.return_value = fake.AGGREGATES
142 self.mock_object(self.library,
143 '_get_api_client',
144 mock.Mock(return_value=mock_client))
145 self.mock_object(self.library, '_initialize_flexgroup_pools')
146 self.mock_object(self.library,
147 'is_flexvol_pool_configured',
148 mock.Mock(return_value=False))
149 self.mock_object(self.library,
150 '_find_matching_aggregates',
151 mock.Mock(return_value=[]))
153 self.library.check_for_setup_error()
155 self.assertTrue(self.library.is_flexvol_pool_configured.called)
156 self.assertTrue(self.library._find_matching_aggregates.called)
158 def test_check_for_setup_error_cluster_creds_vserver_mismatch(self):
159 self.library._client.vserver_exists.return_value = True
160 self.library._have_cluster_creds = False
161 self.library._client.list_vservers.return_value = [fake.VSERVER2]
163 self.assertRaises(exception.InvalidInput,
164 self.library.check_for_setup_error)
166 def test_check_for_setup_error_no_aggregates(self):
167 self.library._client.vserver_exists.return_value = True
168 self.library._have_cluster_creds = True
169 mock_client = mock.Mock()
170 mock_client.list_vserver_aggregates.return_value = fake.AGGREGATES
171 self.mock_object(self.library,
172 '_get_api_client',
173 mock.Mock(return_value=mock_client))
174 self.mock_object(self.library, '_initialize_flexgroup_pools')
175 self.mock_object(self.library,
176 'is_flexvol_pool_configured',
177 mock.Mock(return_value=True))
178 self.mock_object(self.library,
179 '_find_matching_aggregates',
180 mock.Mock(return_value=[]))
182 self.assertRaises(exception.NetAppException,
183 self.library.check_for_setup_error)
184 self.assertTrue(self.library.is_flexvol_pool_configured.called)
185 self.assertTrue(self.library._find_matching_aggregates.called)
187 def test_get_vserver(self):
188 self.library._client.vserver_exists.return_value = True
189 self.mock_object(self.library,
190 '_get_api_client',
191 mock.Mock(return_value='fake_client'))
193 result_vserver, result_vserver_client = self.library._get_vserver()
195 self.assertEqual(fake.VSERVER1, result_vserver)
196 self.assertEqual('fake_client', result_vserver_client)
198 def test_get_vserver_share_server_specified(self):
199 self.assertRaises(exception.InvalidParameterValue,
200 self.library._get_vserver,
201 share_server=fake.SHARE_SERVER)
203 def test_get_vserver_no_vserver(self):
204 self.library._vserver = None
206 self.assertRaises(exception.InvalidInput,
207 self.library._get_vserver)
209 def test_get_vserver_vserver_not_found(self):
210 self.library._client.vserver_exists.return_value = False
212 self.assertRaises(exception.VserverNotFound,
213 self.library._get_vserver)
215 def test_get_ems_pool_info(self):
217 self.mock_object(self.library,
218 '_find_matching_aggregates',
219 mock.Mock(return_value=['aggr1', 'aggr2']))
220 self.library._flexgroup_pools = {'fg': ['aggr1', 'aggr2']}
222 result = self.library._get_ems_pool_info()
224 expected = {
225 'pools': {
226 'vserver': fake.VSERVER1,
227 'aggregates': ['aggr1', 'aggr2'],
228 'flexgroup_aggregates': {'fg': ['aggr1', 'aggr2']},
229 },
230 }
231 self.assertEqual(expected, result)
233 @ddt.data(True, False)
234 def test_handle_housekeeping_tasks_with_cluster_creds(self, have_creds):
235 self.library._have_cluster_creds = have_creds
236 mock_vserver_client = mock.Mock()
237 self.mock_object(self.library,
238 '_get_api_client',
239 mock.Mock(return_value=mock_vserver_client))
240 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
241 '_handle_housekeeping_tasks')
243 self.library._handle_housekeeping_tasks()
245 self.assertTrue(
246 mock_vserver_client.prune_deleted_nfs_export_policies.called)
247 self.assertTrue(mock_vserver_client.prune_deleted_snapshots.called)
248 self.assertIs(
249 have_creds,
250 mock_vserver_client.remove_unused_qos_policy_groups.called)
251 self.assertTrue(mock_super.called)
253 @ddt.data(True, False)
254 def test_find_matching_aggregates(self, have_cluster_creds):
256 self.mock_object(self.library,
257 'is_flexvol_pool_configured',
258 mock.Mock(return_value=True))
259 self.library._have_cluster_creds = have_cluster_creds
260 aggregates = fake.AGGREGATES + fake.ROOT_AGGREGATES
261 mock_vserver_client = mock.Mock()
262 mock_vserver_client.list_vserver_aggregates.return_value = aggregates
263 self.mock_object(self.library,
264 '_get_api_client',
265 mock.Mock(return_value=mock_vserver_client))
266 mock_client = mock.Mock()
267 mock_client.list_root_aggregates.return_value = fake.ROOT_AGGREGATES
268 self.library._client = mock_client
270 self.library.configuration.netapp_aggregate_name_search_pattern = (
271 '.*_aggr_1')
273 result = self.library._find_matching_aggregates()
275 if have_cluster_creds:
276 self.assertListEqual([fake.AGGREGATES[0]], result)
277 mock_client.list_root_aggregates.assert_called_once_with()
278 else:
279 self.assertListEqual([fake.AGGREGATES[0], fake.ROOT_AGGREGATES[0]],
280 result)
281 self.assertFalse(mock_client.list_root_aggregates.called)
283 def test_find_matching_aggregates_no_flexvol_pool(self):
285 self.mock_object(self.library,
286 'is_flexvol_pool_configured',
287 mock.Mock(return_value=False))
289 result = self.library._find_matching_aggregates()
291 self.assertListEqual([], result)
293 def test_get_network_allocations_number(self):
294 self.assertEqual(0, self.library.get_network_allocations_number())
296 def test_get_admin_network_allocations_number(self):
298 result = self.library.get_admin_network_allocations_number()
300 self.assertEqual(0, result)
302 def test__get_backup_vserver(self):
303 self.mock_object(self.library,
304 '_get_backend',
305 mock.Mock(return_value=fake.BACKEND_NAME))
306 self.mock_object(data_motion,
307 'get_backend_configuration',
308 mock.Mock(return_value=_get_config()))
309 self.library._get_backup_vserver(fake.SHARE_BACKUP)
311 def test__get_backup_vserver_with_share_server_negative(self):
312 self.mock_object(self.library,
313 '_get_backend',
314 mock.Mock(return_value=fake.BACKEND_NAME))
315 self.mock_object(data_motion,
316 'get_backend_configuration',
317 mock.Mock(return_value=_get_config()))
318 self.assertRaises(
319 exception.InvalidParameterValue,
320 self.library._get_backup_vserver,
321 fake.SHARE_BACKUP,
322 fake.SHARE_SERVER,
323 )