Coverage for manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode_rest.py: 99%
3229 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) 2023 NetApp, Inc. 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.
15import copy
16import math
17import time
18from unittest import mock
20import ddt
21from oslo_log import log
22from oslo_utils import netutils
23from oslo_utils import units
25from manila import exception
26from manila.share.drivers.netapp.dataontap.client import client_cmode
27from manila.share.drivers.netapp.dataontap.client import client_cmode_rest
28from manila.share.drivers.netapp.dataontap.client import rest_api as netapp_api
29from manila.share.drivers.netapp import utils as netapp_utils
30from manila import test
31from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
32from manila import utils
35@ddt.ddt
36class NetAppRestCmodeClientTestCase(test.TestCase):
38 def setUp(self):
39 super(NetAppRestCmodeClientTestCase, self).setUp()
41 # Mock loggers as themselves to allow logger arg validation
42 mock_logger = log.getLogger('mock_logger')
43 self.mock_object(client_cmode_rest.LOG,
44 'error',
45 mock.Mock(side_effect=mock_logger.error))
46 self.mock_object(client_cmode_rest.LOG,
47 'warning',
48 mock.Mock(side_effect=mock_logger.warning))
49 self.mock_object(client_cmode_rest.LOG,
50 'debug',
51 mock.Mock(side_effect=mock_logger.debug))
52 self.mock_object(client_cmode.NetAppCmodeClient,
53 'get_ontapi_version',
54 mock.Mock(return_value=(1, 20)))
55 # store the original reference so we can call it later in
56 # test_get_ontap_version
57 self.original_get_ontap_version = (
58 client_cmode_rest.NetAppRestClient.get_ontap_version)
59 self.mock_object(client_cmode_rest.NetAppRestClient,
60 'get_ontap_version',
61 mock.Mock(return_value={
62 'version-tuple': (9, 12, 1),
63 'version': fake.VERSION,
64 }))
65 self.original_check_for_cluster_credentials = (
66 client_cmode_rest.NetAppRestClient._check_for_cluster_credentials)
67 self.mock_object(client_cmode_rest.NetAppRestClient,
68 '_check_for_cluster_credentials',
69 mock.Mock(return_value=True))
70 self.mock_object(client_cmode.NetAppCmodeClient,
71 'get_system_version',
72 mock.Mock(return_value={
73 'version-tuple': (9, 10, 1),
74 'version': fake.VERSION,
75 }))
77 self.client = client_cmode_rest.NetAppRestClient(
78 **fake.CONNECTION_INFO)
79 self.client.connection = mock.MagicMock()
81 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None)
82 self.sleep_patcher.start()
83 self.addCleanup(self.sleep_patcher.stop)
85 def _mock_api_error(self, code='fake', message='fake'):
86 return mock.Mock(
87 side_effect=netapp_api.api.NaApiError(code=code, message=message))
89 def test_send_request(self):
90 expected = 'fake_response'
91 mock_get_records = self.mock_object(
92 self.client, 'get_records',
93 mock.Mock(return_value=expected))
95 res = self.client.send_request(
96 fake.FAKE_ACTION_URL, 'get',
97 body=fake.FAKE_HTTP_BODY,
98 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False)
100 self.assertEqual(expected, res)
101 mock_get_records.assert_called_once_with(
102 fake.FAKE_ACTION_URL,
103 fake.FAKE_HTTP_QUERY, False, 10000)
105 def test_send_request_post(self):
106 expected = (201, 'fake_response')
107 mock_invoke = self.mock_object(
108 self.client.connection, 'invoke_successfully',
109 mock.Mock(return_value=expected))
111 res = self.client.send_request(
112 fake.FAKE_ACTION_URL, 'post',
113 body=fake.FAKE_HTTP_BODY,
114 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False)
116 self.assertEqual(expected[1], res)
117 mock_invoke.assert_called_once_with(
118 fake.FAKE_ACTION_URL, 'post',
119 body=fake.FAKE_HTTP_BODY,
120 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False)
122 def test_send_request_wait(self):
123 expected = (202, fake.JOB_RESPONSE_REST)
124 mock_invoke = self.mock_object(
125 self.client.connection, 'invoke_successfully',
126 mock.Mock(return_value=expected))
128 mock_wait = self.mock_object(
129 self.client, '_wait_job_result',
130 mock.Mock(return_value=expected[1]))
132 res = self.client.send_request(
133 fake.FAKE_ACTION_URL, 'post',
134 body=fake.FAKE_HTTP_BODY,
135 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False)
137 self.assertEqual(expected[1], res)
138 mock_invoke.assert_called_once_with(
139 fake.FAKE_ACTION_URL, 'post',
140 body=fake.FAKE_HTTP_BODY,
141 query=fake.FAKE_HTTP_QUERY, enable_tunneling=False)
142 mock_wait.assert_called_once_with(
143 expected[1]['job']['_links']['self']['href'][4:])
145 @ddt.data(True, False)
146 def test_get_records(self, enable_tunneling):
147 api_responses = [
148 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE),
149 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE),
150 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE),
151 ]
153 mock_invoke = self.mock_object(
154 self.client.connection, 'invoke_successfully',
155 mock.Mock(side_effect=copy.deepcopy(api_responses)))
157 query = {
158 'fields': 'name'
159 }
161 result = self.client.get_records(
162 '/storage/volumes/', query=query,
163 enable_tunneling=enable_tunneling,
164 max_page_length=10)
166 num_records = result['num_records']
167 self.assertEqual(28, num_records)
168 self.assertEqual(28, len(result['records']))
170 expected_records = []
171 expected_records.extend(api_responses[0][1]['records'])
172 expected_records.extend(api_responses[1][1]['records'])
173 expected_records.extend(api_responses[2][1]['records'])
175 self.assertEqual(expected_records, result['records'])
177 next_tag = result.get('next')
178 self.assertIsNone(next_tag)
180 expected_query = copy.deepcopy(query)
181 expected_query['max_records'] = 10
183 next_url_1 = api_responses[0][1]['_links']['next']['href'][4:]
184 next_url_2 = api_responses[1][1]['_links']['next']['href'][4:]
186 mock_invoke.assert_has_calls([
187 mock.call('/storage/volumes/', 'get', query=expected_query,
188 enable_tunneling=enable_tunneling),
189 mock.call(next_url_1, 'get', query=None,
190 enable_tunneling=enable_tunneling),
191 mock.call(next_url_2, 'get', query=None,
192 enable_tunneling=enable_tunneling),
193 ])
195 def test_get_records_single_page(self):
197 api_response = (
198 200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE)
199 mock_invoke = self.mock_object(self.client.connection,
200 'invoke_successfully',
201 mock.Mock(return_value=api_response))
203 query = {
204 'fields': 'name'
205 }
207 result = self.client.get_records(
208 '/storage/volumes/', query=query, max_page_length=10)
210 num_records = result['num_records']
211 self.assertEqual(8, num_records)
212 self.assertEqual(8, len(result['records']))
214 next_tag = result.get('next')
215 self.assertIsNone(next_tag)
217 args = copy.deepcopy(query)
218 args['max_records'] = 10
220 mock_invoke.assert_has_calls([
221 mock.call('/storage/volumes/', 'get', query=args,
222 enable_tunneling=True),
223 ])
225 def test_get_records_not_found(self):
227 api_response = (200, fake.NO_RECORDS_RESPONSE_REST)
228 mock_invoke = self.mock_object(self.client.connection,
229 'invoke_successfully',
230 mock.Mock(return_value=api_response))
232 result = self.client.get_records('/storage/volumes/')
234 num_records = result['num_records']
235 self.assertEqual(0, num_records)
236 self.assertEqual(0, len(result['records']))
238 args = {
239 'max_records': client_cmode_rest.DEFAULT_MAX_PAGE_LENGTH
240 }
242 mock_invoke.assert_has_calls([
243 mock.call('/storage/volumes/', 'get', query=args,
244 enable_tunneling=True),
245 ])
247 def test_get_records_timeout(self):
248 # To simulate timeout, max_records is 30, but the API returns less
249 # records and fill the 'next url' pointing to the next page.
250 max_records = 30
251 api_responses = [
252 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE),
253 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE),
254 (200, fake.VOLUME_GET_ITER_RESPONSE_REST_LAST_PAGE),
255 ]
257 mock_invoke = self.mock_object(
258 self.client.connection, 'invoke_successfully',
259 mock.Mock(side_effect=copy.deepcopy(api_responses)))
261 query = {
262 'fields': 'name'
263 }
265 result = self.client.get_records(
266 '/storage/volumes/', query=query, max_page_length=max_records)
268 num_records = result['num_records']
269 self.assertEqual(28, num_records)
270 self.assertEqual(28, len(result['records']))
272 expected_records = []
273 expected_records.extend(api_responses[0][1]['records'])
274 expected_records.extend(api_responses[1][1]['records'])
275 expected_records.extend(api_responses[2][1]['records'])
277 self.assertEqual(expected_records, result['records'])
279 next_tag = result.get('next', None)
280 self.assertIsNone(next_tag)
282 args1 = copy.deepcopy(query)
283 args1['max_records'] = max_records
285 next_url_1 = api_responses[0][1]['_links']['next']['href'][4:]
286 next_url_2 = api_responses[1][1]['_links']['next']['href'][4:]
288 mock_invoke.assert_has_calls([
289 mock.call('/storage/volumes/', 'get', query=args1,
290 enable_tunneling=True),
291 mock.call(next_url_1, 'get', query=None, enable_tunneling=True),
292 mock.call(next_url_2, 'get', query=None, enable_tunneling=True),
293 ])
295 def test__getattr__(self):
296 # NOTE(nahimsouza): get_ontapi_version is implemented only in ZAPI
297 # client, therefore, it will call __getattr__
298 self.client.get_ontapi_version()
300 @ddt.data(True, False)
301 def test_get_ontap_version(self, cached):
302 self.client.get_ontap_version = self.original_get_ontap_version
303 api_response = {
304 'records': [
305 {
306 'version': {
307 'generation': 9,
308 'major': 11,
309 'minor': 1,
310 'full': 'NetApp Release 9.11.1'
311 }
312 }]
314 }
315 return_mock = {
316 'version': 'NetApp Release 9.11.1',
317 'version-tuple': (9, 11, 1)
318 }
319 mock_connect = self.mock_object(self.client.connection,
320 'get_ontap_version',
321 mock.Mock(return_value=return_mock))
322 mock_send_request = self.mock_object(
323 self.client,
324 'send_request',
325 mock.Mock(return_value=api_response))
327 result = self.client.get_ontap_version(self=self.client, cached=cached)
329 if cached:
330 mock_connect.assert_called_once()
331 else:
332 mock_send_request.assert_called_once_with(
333 '/cluster/nodes', 'get', query={'fields': 'version'},
334 enable_tunneling=False)
336 self.assertEqual(return_mock, result)
338 def test__wait_job_result(self):
339 response = fake.JOB_SUCCESSFUL_REST
340 self.mock_object(self.client,
341 'send_request',
342 mock.Mock(return_value=response))
343 result = self.client._wait_job_result(
344 f'/cluster/jobs/{fake.FAKE_UUID}')
345 self.assertEqual(response, result)
347 def test__wait_job_result_failure(self):
348 response = fake.JOB_ERROR_REST
349 self.mock_object(self.client,
350 'send_request',
351 mock.Mock(return_value=response))
352 self.assertRaises(netapp_utils.NetAppDriverException,
353 self.client._wait_job_result,
354 f'/cluster/jobs/{fake.FAKE_UUID}')
356 def test__wait_job_result_timeout(self):
357 response = fake.JOB_RUNNING_REST
358 self.client.async_rest_timeout = 2
359 self.mock_object(self.client,
360 'send_request',
361 mock.Mock(return_value=response))
362 self.assertRaises(netapp_utils.NetAppDriverException,
363 self.client._wait_job_result,
364 f'/cluster/jobs/{fake.FAKE_UUID}')
366 def test_list_cluster_nodes(self):
367 """Get all available cluster nodes."""
369 return_value = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST
371 self.mock_object(self.client, 'send_request',
372 mock.Mock(return_value=return_value))
373 test_result = self.client.list_cluster_nodes()
375 self.client.send_request.assert_called_once_with(
376 '/cluster/nodes', 'get'
377 )
379 nodes = return_value.get('records', [])
381 expected_result = [node['name'] for node in nodes]
383 self.assertEqual(expected_result, test_result)
385 @ddt.data(True, False)
386 def test_check_for_cluster_credentials(self, cluster_creds):
387 self.client._have_cluster_creds = cluster_creds
389 result = self.client.check_for_cluster_credentials()
391 self.assertEqual(cluster_creds, result)
393 def test__check_for_cluster_credentials(self):
394 self.client._check_for_cluster_credentials = (
395 self.original_check_for_cluster_credentials)
396 api_response = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST
397 self.mock_object(self.client,
398 'list_cluster_nodes',
399 mock.Mock(return_value=api_response))
401 result = self.client._check_for_cluster_credentials(self=self.client)
403 self.assertTrue(result)
405 def test__check_for_cluster_credentials_not_cluster(self):
406 self.client._check_for_cluster_credentials = (
407 self.original_check_for_cluster_credentials)
408 self.mock_object(self.client, 'list_cluster_nodes',
409 self._mock_api_error(
410 netapp_api.EREST_NOT_AUTHORIZED))
412 result = self.client._check_for_cluster_credentials(self=self.client)
414 self.assertFalse(result)
416 def test__check_for_cluster_credentials_api_error(self):
417 self.client._check_for_cluster_credentials = (
418 self.original_check_for_cluster_credentials)
419 self.mock_object(self.client, 'list_cluster_nodes',
420 self._mock_api_error())
422 self.assertRaises(netapp_api.api.NaApiError,
423 self.client._check_for_cluster_credentials,
424 self.client)
426 def test_get_licenses(self):
427 return_value = fake.FAKE_GET_LICENSES_REST
429 self.mock_object(self.client, 'send_request',
430 mock.Mock(return_value=return_value))
432 test_result = self.client.get_licenses()
434 expected_result = sorted(
435 [license['name'] for license in return_value.get('records', [])])
437 self.assertEqual(test_result, expected_result)
439 @ddt.data(((9, 1, 0), fake.VERSION_NO_DARE), ((8, 3, 2), fake.VERSION))
440 @ddt.unpack
441 def test_is_nve_supported_unsupported_release_or_platform(self, gen, ver):
442 system_version = {'version-tuple': gen, 'version': ver}
443 self.mock_object(self.client,
444 'get_ontap_version',
445 mock.Mock(return_value=system_version))
446 self.mock_object(self.client,
447 '_get_security_key_manager_nve_support',
448 mock.Mock(return_value=False))
449 self.mock_object(self.client,
450 'list_cluster_nodes',
451 mock.Mock(return_value=fake.NODE_NAMES))
453 result = self.client.is_nve_supported()
455 self.assertFalse(result)
457 def test_is_nve_supported_valid_platform_and_supported_release(self):
459 system_version = {
460 'version-tuple': (9, 1, 0),
461 'version': fake.VERSION,
462 }
463 self.mock_object(self.client,
464 'get_ontap_version',
465 mock.Mock(return_value=system_version))
466 self.mock_object(self.client,
467 '_get_security_key_manager_nve_support',
468 mock.Mock(return_value=True))
469 self.mock_object(self.client,
470 'list_cluster_nodes',
471 mock.Mock(return_value=fake.NODE_NAMES))
473 result = self.client.is_nve_supported()
474 self.assertTrue(result)
476 def test_is_nve_supported_key_manager_not_enabled(self):
478 system_version = {
479 'version-tuple': (9, 1, 0),
480 'version': fake.VERSION,
481 }
482 self.mock_object(self.client,
483 'get_ontap_version',
484 mock.Mock(return_value=system_version))
485 self.mock_object(self.client,
486 '_get_security_key_manager_nve_support',
487 mock.Mock(return_value=False))
488 self.mock_object(self.client,
489 'list_cluster_nodes',
490 mock.Mock(return_value=fake.NODE_NAMES))
492 result = self.client.is_nve_supported()
494 self.assertFalse(result)
496 def test__get_volume_by_args(self):
497 response = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST
498 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
500 self.mock_object(self.client, 'send_request',
501 mock.Mock(return_value=response))
503 result = self.client._get_volume_by_args(
504 vol_name=fake.VOLUME_NAMES[0],
505 aggregate_name=fake.SHARE_AGGREGATE_NAME,
506 vol_path=fake.VOLUME_JUNCTION_PATH,
507 vserver=fake.VSERVER_NAME,
508 fields='name,style,svm.name,svm.uuid')
510 query = {
511 'name': fake.VOLUME_NAMES[0],
512 'aggregates.name': fake.SHARE_AGGREGATE_NAME,
513 'nas.path': fake.VOLUME_JUNCTION_PATH,
514 'svm.name': fake.VSERVER_NAME,
515 'style': 'flex*', # Match both 'flexvol' and 'flexgroup'
516 'error_state.is_inconsistent': 'false',
517 'fields': 'name,style,svm.name,svm.uuid'
518 }
519 self.client.send_request.assert_called_once_with(
520 '/storage/volumes/', 'get', query=query)
522 self.assertEqual(volume, result)
524 def test_restore_snapshot(self):
525 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
526 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"]
527 body = {
528 'restore_to.snapshot.name': fake.SNAPSHOT_NAME
529 }
531 self.mock_object(self.client, '_get_volume_by_args',
532 mock.Mock(return_value=volume))
533 self.mock_object(self.client, 'send_request')
535 self.client.restore_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME)
537 self.client._get_volume_by_args.assert_called_once_with(
538 vol_name=fake.VOLUME_NAMES[0])
539 self.client.send_request.assert_called_once_with(
540 f'/storage/volumes/{uuid}', 'patch', body=body)
542 @ddt.data(0, 10)
543 def test__has_records(self, num_records):
544 result = self.client._has_records({'num_records': num_records})
546 if not num_records or num_records == 0:
547 self.assertFalse(result)
548 else:
549 self.assertTrue(result)
551 def test_vserver_exists(self):
552 query = {
553 'name': fake.VSERVER_NAME
554 }
555 return_value = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
557 self.mock_object(self.client, 'send_request',
558 mock.Mock(return_value=return_value))
560 self.mock_object(self.client, '_has_records',
561 mock.Mock(return_value=True))
563 result = self.client.vserver_exists(fake.VSERVER_NAME)
565 self.client.send_request.assert_called_once_with(
566 '/svm/svms', 'get', query=query, enable_tunneling=False)
567 self.client._has_records.assert_called_once_with(
568 fake.SVMS_LIST_SIMPLE_RESPONSE_REST)
570 self.assertEqual(result, True)
572 def test_get_aggregate(self):
574 response = fake.AGGR_GET_ITER_RESPONSE_REST['records']
575 self.mock_object(self.client,
576 '_get_aggregates',
577 mock.Mock(return_value=response))
579 result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME)
581 fields = ('name,block_storage.primary.raid_type,'
582 'block_storage.storage_type,snaplock_type')
584 self.client._get_aggregates.assert_has_calls([
585 mock.call(
586 aggregate_names=[fake.SHARE_AGGREGATE_NAME],
587 fields=fields)])
589 expected = {
590 'name': fake.SHARE_AGGREGATE_NAME,
591 'raid-type': response[0]['block_storage']['primary']['raid_type'],
592 'is-hybrid':
593 response[0]['block_storage']['storage_type'] == 'hybrid',
594 'snaplock-type': response[0]['snaplock_type'],
595 'is-snaplock': response[0]['is_snaplock']
596 }
598 self.assertEqual(expected, result)
600 def test_get_cluster_aggregate_capacities(self):
602 response = fake.AGGR_GET_ITER_RESPONSE_REST['records']
603 self.mock_object(self.client,
604 '_get_aggregates',
605 mock.Mock(return_value=response))
607 result = self.client.get_cluster_aggregate_capacities(
608 response)
610 fields = 'name,space'
611 self.client._get_aggregates.assert_has_calls([
612 mock.call(
613 aggregate_names=response,
614 fields=fields)])
615 expected = {
616 response[0]['name']: {
617 'available': 568692293632,
618 'total': 1271819509760,
619 'used': 703127216128,
620 },
621 response[1]['name']: {
622 'available': 727211110400,
623 'total': 1426876227584,
624 'used': 699665117184,
625 }
626 }
628 self.assertDictEqual(expected, result)
630 def test_list_non_root_aggregates(self):
631 return_value = fake.FAKE_AGGR_LIST
632 self.mock_object(self.client, 'send_request',
633 mock.Mock(return_value=return_value))
635 result = self.client.list_non_root_aggregates()
637 expected = [fake.SHARE_AGGREGATE_NAMES_LIST[0]]
638 self.assertEqual(expected, result)
640 def test__get_aggregates(self):
642 api_response = fake.AGGR_GET_ITER_RESPONSE_REST
643 self.mock_object(self.client, 'send_request',
644 mock.Mock(return_value=api_response))
645 result = self.client._get_aggregates(
646 aggregate_names=fake.SHARE_AGGREGATE_NAMES)
647 expected = fake.AGGR_GET_ITER_RESPONSE_REST['records']
648 self.assertEqual(expected, result)
650 def test_get_node_for_aggregate(self):
652 response = fake.AGGR_GET_ITER_RESPONSE_REST['records']
653 self.mock_object(self.client,
654 '_get_aggregates',
655 mock.Mock(return_value=response))
656 result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
657 expected = 'fake_home_node_name'
658 self.assertEqual(expected, result)
660 @ddt.data({'types': {'FCAL'}, 'expected': ['FCAL']},
661 {'types': {'SATA', 'SSD'}, 'expected': ['SATA', 'SSD']}, )
662 @ddt.unpack
663 def test_get_aggregate_disk_types(self, types, expected):
665 mock_get_aggregate_disk_types = self.mock_object(
666 self.client, '_get_aggregate_disk_types',
667 mock.Mock(return_value=types))
669 result = self.client.get_aggregate_disk_types(
670 fake.SHARE_AGGREGATE_NAME)
672 self.assertEqual(sorted(expected), sorted(result))
673 mock_get_aggregate_disk_types.assert_called_once_with(
674 fake.SHARE_AGGREGATE_NAME)
676 def test_volume_exists(self):
677 query = {
678 'name': fake.VOLUME_NAMES[0]
679 }
680 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST
682 self.mock_object(self.client, 'send_request',
683 mock.Mock(return_value=return_value))
685 self.mock_object(self.client, '_has_records',
686 mock.Mock(return_value=True))
688 result = self.client.volume_exists(fake.VOLUME_NAMES[0])
690 self.client.send_request.assert_called_once_with(
691 '/storage/volumes', 'get', query=query)
692 self.client._has_records.assert_called_once_with(
693 fake.VOLUME_LIST_SIMPLE_RESPONSE_REST)
694 self.assertEqual(result, True)
696 def test_list_vserver_aggregates(self):
698 self.mock_object(self.client,
699 'get_vserver_aggregate_capacities',
700 mock.Mock(return_value=fake.VSERVER_AGGREGATES))
702 result = self.client.list_vserver_aggregates()
704 self.assertListEqual(list(fake.VSERVER_AGGREGATES.keys()), result)
706 def test_list_vserver_aggregates_none_found(self):
708 self.mock_object(self.client,
709 'get_vserver_aggregate_capacities',
710 mock.Mock(return_value={}))
712 result = self.client.list_vserver_aggregates()
714 self.assertListEqual([], result)
716 def test_get_vserver_aggregate_capacities(self):
718 response = fake.FAKE_SVM_AGGREGATES
719 self.mock_object(self.client,
720 'send_request',
721 mock.Mock(return_value=response))
723 result = self.client.get_vserver_aggregate_capacities(
724 fake.SHARE_AGGREGATE_NAMES_LIST)
726 query = {
727 'fields': 'name,aggregates.name,aggregates.available_size'
728 }
730 self.client.send_request.assert_has_calls([
731 mock.call('/svm/svms', 'get', query=query)])
733 expected = {
734 response['records'][0].get('aggregates')[0].get('name'): {
735 'available': 568692293632,
736 },
737 response['records'][0].get('aggregates')[1].get('name'): {
738 'available': 727211110400,
739 }
740 }
742 self.assertDictEqual(expected, result)
744 def test_get_vserver_aggregate_capacities_partial_request(self):
745 response = fake.FAKE_SVM_AGGREGATES
746 size = response['records'][0].get('aggregates')[0].get(
747 'available_size')
748 self.mock_object(self.client,
749 'send_request',
750 mock.Mock(return_value=response))
752 result = self.client.get_vserver_aggregate_capacities(
753 [fake.SHARE_AGGREGATE_NAMES[0]])
755 expected = {
756 fake.SHARE_AGGREGATE_NAMES[0]: {
757 'available': size
758 }
759 }
760 self.assertDictEqual(expected, result)
762 def test_get_vserver_aggregate_capacities_aggregate_not_found(self):
763 self.mock_object(self.client,
764 'send_request',
765 mock.Mock(return_value=fake.FAKE_SVM_AGGR_EMPTY))
767 result = self.client.get_vserver_aggregate_capacities(
768 ['other-aggr'])
770 self.assertDictEqual({}, result)
771 self.assertEqual(1, client_cmode_rest.LOG.warning.call_count)
773 def test_get_vserver_aggregate_capacities_none_requested(self):
774 result = self.client.get_vserver_aggregate_capacities([])
775 self.assertEqual({}, result)
777 @ddt.data((None, None),
778 (fake.QOS_MAX_THROUGHPUT, None),
779 (fake.QOS_MAX_THROUGHPUT_IOPS, None),
780 (None, None),
781 (None, fake.QOS_MIN_THROUGHPUT),
782 (None, fake.QOS_MIN_THROUGHPUT_IOPS),
783 (fake.QOS_MAX_THROUGHPUT_IOPS, fake.QOS_MIN_THROUGHPUT_IOPS))
784 @ddt.unpack
785 def test_qos_policy_group_create(self, max_throughput, min_throughput):
786 return_value = fake.GENERIC_JOB_POST_RESPONSE
787 body = {
788 'name': fake.QOS_POLICY_GROUP_NAME,
789 'svm.name': fake.VSERVER_NAME,
790 }
791 if max_throughput:
792 if 'iops' in max_throughput:
793 qos = fake.QOS_MAX_THROUGHPUT_IOPS_NO_UNIT
794 body['fixed.max_throughput_iops'] = qos
795 else:
796 qos = math.ceil(fake.QOS_MAX_THROUGHPUT_NO_UNIT / units.Mi)
797 body['fixed.max_throughput_mbps'] = qos
799 if min_throughput:
800 if 'iops' in min_throughput:
801 qos = fake.QOS_MIN_THROUGHPUT_IOPS_NO_UNIT
802 body['fixed.min_throughput_iops'] = qos
803 else:
804 qos = math.ceil(fake.QOS_MIN_THROUGHPUT_NO_UNIT / units.Mi)
805 body['fixed.min_throughput_mbps'] = qos
807 self.mock_object(self.client, 'send_request',
808 mock.Mock(return_value=return_value))
810 result = self.client.qos_policy_group_create(
811 fake.QOS_POLICY_GROUP_NAME, fake.VSERVER_NAME,
812 max_throughput, min_throughput)
814 self.client.send_request.assert_called_once_with(
815 '/storage/qos/policies', 'post', body=body)
816 self.assertEqual(result, return_value)
818 @ddt.data(None, ['CIFS', 'NFS'])
819 def test_get_network_interfaces(self, protocols):
820 return_value = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE
822 lif_info = return_value.get('records', [])[0]
824 fake_lif = [{
825 'uuid': lif_info['uuid'],
826 'administrative-status': 'up' if lif_info['enabled'] else 'down',
827 'address': lif_info['ip']['address'],
828 'home-node': lif_info['location']['home_node']['name'],
829 'home-port': lif_info['location']['home_port']['name'],
830 'interface-name': lif_info['name'],
831 'netmask': lif_info['ip']['netmask'],
832 'role': lif_info['services'],
833 'vserver': lif_info['svm']['name'],
834 }]
836 if protocols:
837 query = {
838 'services': 'data_cifs,data_nfs',
839 'fields': 'ip.address,location.home_node.name,'
840 'location.home_port.name,ip.netmask,'
841 'services,svm.name,enabled'
842 }
843 else:
844 query = {
845 'fields': 'ip.address,location.home_node.name,'
846 'location.home_port.name,ip.netmask,'
847 'services,svm.name,enabled'
848 }
850 self.mock_object(self.client, 'send_request',
851 mock.Mock(return_value=return_value))
853 result = self.client.get_network_interfaces(protocols)
855 self.client.send_request.assert_called_once_with(
856 '/network/ip/interfaces', 'get', query=query)
858 self.assertEqual(result, fake_lif)
860 def test_clear_nfs_export_policy_for_volume(self):
862 mock_set_nfs_export_policy_for_volume = self.mock_object(
863 self.client, 'set_nfs_export_policy_for_volume')
865 self.client.clear_nfs_export_policy_for_volume(fake.SHARE_NAME)
867 mock_set_nfs_export_policy_for_volume.assert_called_once_with(
868 fake.SHARE_NAME, 'default')
870 def test_set_nfs_export_policy_for_volume(self):
871 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
872 query = {'name': volume['name']}
874 body = {
875 'nas.export_policy.name': fake.EXPORT_POLICY_NAME
876 }
878 self.mock_object(self.client, 'send_request')
880 self.client.set_nfs_export_policy_for_volume(
881 fake.VOLUME_NAMES[0], fake.EXPORT_POLICY_NAME)
883 self.client.send_request.assert_called_once_with(
884 '/storage/volumes/', 'patch',
885 query=query, body=body)
887 def test_create_nfs_export_policy(self):
889 body = {'name': fake.EXPORT_POLICY_NAME}
891 self.mock_object(self.client, 'send_request')
893 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME)
895 self.client.send_request.assert_called_once_with(
896 '/protocols/nfs/export-policies', 'post', body=body)
898 def test_soft_delete_nfs_export_policy(self):
899 self.mock_object(self.client, 'delete_nfs_export_policy',
900 mock.Mock(side_effect=self._mock_api_error()))
901 self.mock_object(self.client, 'rename_nfs_export_policy')
903 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
905 self.client.rename_nfs_export_policy.assert_has_calls([
906 mock.call(
907 fake.EXPORT_POLICY_NAME,
908 'deleted_manila_' + fake.EXPORT_POLICY_NAME)])
910 def test_rename_nfs_export_policy(self):
911 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
912 uuid = "fake-policy-uuid"
914 self.mock_object(self.client, 'send_request',
915 mock.Mock(return_value=return_uuid))
916 self.mock_object(self.client, '_has_records',
917 mock.Mock(return_value=True))
919 body = {
920 'name': 'fake_new_policy_name'
921 }
923 self.client.rename_nfs_export_policy(fake.EXPORT_POLICY_NAME,
924 'fake_new_policy_name')
926 self.client._has_records.assert_called_once_with(return_uuid)
928 self.client.send_request.assert_has_calls([
929 mock.call('/protocols/nfs/export-policies', 'get',
930 query={'name': fake.EXPORT_POLICY_NAME}),
931 mock.call(f'/protocols/nfs/export-policies/{uuid}', 'patch',
932 body=body)])
934 def test_get_volume_junction_path(self):
935 return_value = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
937 query = {
938 'name': fake.SHARE_NAME,
939 'fields': 'nas.path'
940 }
942 self.mock_object(self.client, 'send_request',
943 mock.Mock(return_value=return_value))
945 result = self.client.get_volume_junction_path(fake.SHARE_NAME)
947 expected = fake.VOLUME_JUNCTION_PATH
949 self.client.send_request.assert_called_once_with('/storage/volumes/',
950 'get', query=query)
952 self.assertEqual(result, expected)
954 def test_get_volume_snapshot_attributes(self):
955 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
956 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
958 self.mock_object(self.client, '_get_volume_by_args',
959 mock.Mock(return_value=volume))
960 self.mock_object(self.client, 'send_request',
961 mock.Mock(return_value=return_value))
963 expected = {
964 'snapdir-access-enabled': 'false',
965 'snapshot-policy': 'daily',
966 }
968 result = self.client.get_volume_snapshot_attributes(fake.SHARE_NAME)
969 self.assertEqual(result, expected)
971 def test_get_volume(self):
972 return_value = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
974 fake_volume = return_value.get('records', [])[0]
976 expected = {
977 'aggregate': fake.SHARE_AGGREGATE_NAME,
978 'aggr-list': [fake.SHARE_AGGREGATE_NAME],
979 'junction-path': fake_volume.get('nas', {}).get('path', ''),
980 'name': fake_volume.get('name', ''),
981 'owning-vserver-name': fake_volume.get('svm', {}).get('name', ''),
982 'type': fake_volume.get('type', ''),
983 'style': fake_volume.get('style', ''),
984 'size': fake_volume.get('space', {}).get('size', ''),
985 'size-used': fake_volume.get('space', {}).get('used', ''),
986 'qos-policy-group-name': fake_volume.get('qos', {})
987 .get('policy', {})
988 .get('name'),
989 'style-extended': fake_volume.get('style', ''),
990 'snaplock-type': fake_volume.get('snaplock', {}).get('type', '')
991 }
993 self.mock_object(self.client, 'send_request',
994 mock.Mock(return_value=return_value))
995 self.mock_object(self.client, '_has_records',
996 mock.Mock(return_value=True))
998 result = self.client.get_volume(fake.SHARE_NAME)
1000 self.client._has_records.assert_called_once_with(return_value)
1001 self.assertEqual(result, expected)
1003 def test_cifs_share_exists(self):
1004 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST
1005 self.mock_object(self.client, 'send_request',
1006 mock.Mock(return_value=return_value))
1007 self.mock_object(self.client, '_has_records',
1008 mock.Mock(return_value=True))
1010 result = self.client.cifs_share_exists(fake.SHARE_NAME)
1012 query = {
1013 'name': fake.SHARE_NAME,
1014 'path': fake.VOLUME_JUNCTION_PATH
1015 }
1016 self.client._has_records.assert_called_once_with(return_value)
1017 self.client.send_request.assert_called_once_with(
1018 '/protocols/cifs/shares', 'get', query=query)
1019 self.assertTrue(result)
1021 def test_create_cifs_share(self):
1023 body = {
1024 'name': fake.SHARE_NAME,
1025 'path': fake.VOLUME_JUNCTION_PATH,
1026 'svm.name': self.client.vserver,
1027 }
1029 self.mock_object(self.client, 'send_request')
1031 self.client.create_cifs_share(fake.SHARE_NAME, f'/{fake.SHARE_NAME}')
1033 self.client.send_request.assert_called_once_with(
1034 '/protocols/cifs/shares', 'post', body=body)
1036 @ddt.data(None, 'fake_security_style')
1037 def test_set_volume_security_style(self, security_style):
1039 self.mock_object(self.client, 'send_request')
1041 if security_style:
1042 self.client.set_volume_security_style(fake.VOLUME_NAMES[0],
1043 security_style)
1044 else:
1045 self.client.set_volume_security_style(fake.VOLUME_NAMES[0])
1047 query = {
1048 'name': fake.VOLUME_NAMES[0],
1049 }
1050 body = {
1051 'nas.security_style': security_style if security_style else 'unix'
1052 }
1053 self.client.send_request.assert_called_once_with(
1054 '/storage/volumes', 'patch', body=body, query=query)
1056 def test_remove_cifs_share_access(self):
1057 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
1058 self.mock_object(self.client, 'send_request',
1059 mock.Mock(return_value=return_uuid))
1061 self.client.remove_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME)
1063 fake_uuid = "fake_uuid"
1064 self.client.send_request.assert_has_calls([
1065 mock.call('/protocols/cifs/shares', 'get',
1066 query={'name': fake.SHARE_NAME, 'fields': 'svm.uuid'}),
1067 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake.SHARE_NAME}/'
1068 f'acls/{fake.USER_NAME}/windows', 'delete')])
1070 def test_create_volume(self):
1072 mock_create_volume_async = self.mock_object(self.client,
1073 'create_volume_async')
1074 mock_update = self.mock_object(
1075 self.client, 'update_volume_efficiency_attributes')
1076 mock_max_files = self.mock_object(self.client, 'set_volume_max_files')
1077 options = {'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}
1078 self.client.create_volume(fake.SHARE_AGGREGATE_NAME,
1079 fake.VOLUME_NAMES[0], fake.SHARE_SIZE,
1080 max_files=1, snaplock_type="enterprise",
1081 **options)
1082 mock_create_volume_async.assert_called_once_with(
1083 [fake.SHARE_AGGREGATE_NAME], fake.VOLUME_NAMES[0], fake.SHARE_SIZE,
1084 is_flexgroup=False, thin_provisioned=False, snapshot_policy=None,
1085 language=None, max_files=1, snapshot_reserve=None,
1086 volume_type='rw', qos_policy_group=None, encrypt=False,
1087 adaptive_qos_policy_group=None, mount_point_name=None,
1088 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME,
1089 snaplock_type="enterprise",
1090 )
1091 mock_update.assert_called_once_with(
1092 fake.VOLUME_NAMES[0], False, False,
1093 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME)
1094 mock_max_files.assert_called_once_with(fake.VOLUME_NAMES[0], 1)
1096 def test_create_volume_async(self):
1097 body = {
1098 'size': 1073741824,
1099 'name': fake.VOLUME_NAMES[0],
1100 'style': 'flexvol',
1101 'aggregates': [{'name': fake.SHARE_AGGREGATE_NAME}]
1102 }
1104 return_value = fake.GENERIC_JOB_POST_RESPONSE
1106 expected_result = {
1107 'jobid': fake.GENERIC_JOB_POST_RESPONSE['job']['uuid'],
1108 'error-code': '',
1109 'error-message': '',
1110 }
1112 self.mock_object(self.client, '_get_create_volume_body',
1113 mock.Mock(return_value={}))
1114 self.mock_object(self.client, 'send_request',
1115 mock.Mock(return_value=return_value))
1117 result = self.client.create_volume_async([
1118 fake.SHARE_AGGREGATE_NAME], fake.VOLUME_NAMES[0], 1,
1119 is_flexgroup=False)
1121 self.client._get_create_volume_body.assert_called_once_with(
1122 fake.VOLUME_NAMES[0], False, None, None, None, 'rw', None, False,
1123 None, None, None)
1124 self.client.send_request.assert_called_once_with(
1125 '/storage/volumes', 'post', body=body, wait_on_accepted=True)
1126 self.assertEqual(expected_result, result)
1128 def test_get_volume_efficiency_status(self):
1129 return_value = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST
1131 query = {
1132 'efficiency.volume_path': '/vol/%s' % fake.VOLUME_NAMES[0],
1133 'fields': 'efficiency.state,efficiency.compression'
1134 }
1136 expected_result = {
1137 'dedupe': True,
1138 'compression': True
1139 }
1141 self.mock_object(self.client, 'send_request',
1142 mock.Mock(return_value=return_value))
1144 result = self.client.get_volume_efficiency_status(fake.VOLUME_NAMES[0])
1146 self.client.send_request.assert_called_once_with(
1147 '/storage/volumes', 'get', query=query)
1148 self.assertEqual(expected_result, result)
1150 def test_enable_dedupe_async(self):
1151 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1152 uuid = volume["uuid"]
1153 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1155 self.mock_object(self.client, '_get_volume_by_args',
1156 mock.Mock(return_value=volume))
1157 self.mock_object(self.client, 'send_request',
1158 mock.Mock(return_value=return_value))
1160 body = {
1161 'efficiency': {'dedupe': 'background'}
1162 }
1164 self.client.enable_dedupe_async(fake.VOLUME_NAMES[0])
1166 self.client.send_request.assert_called_once_with(
1167 f'/storage/volumes/{uuid}', 'patch', body=body)
1168 self.client._get_volume_by_args.assert_called_once_with(
1169 vol_name=fake.VOLUME_NAMES[0])
1171 def test_disable_dedupe_async(self):
1172 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1173 uuid = volume["uuid"]
1174 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1176 self.mock_object(self.client, '_get_volume_by_args',
1177 mock.Mock(return_value=volume))
1178 self.mock_object(self.client, 'send_request',
1179 mock.Mock(return_value=return_value))
1181 body = {
1182 'efficiency': {'dedupe': 'none'}
1183 }
1185 self.client.disable_dedupe_async(fake.VOLUME_NAMES[0])
1187 self.client.send_request.assert_called_once_with(
1188 f'/storage/volumes/{uuid}', 'patch', body=body)
1189 self.client._get_volume_by_args.assert_called_once_with(
1190 vol_name=fake.VOLUME_NAMES[0])
1192 def test_enable_compression_async(self):
1193 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1194 uuid = volume["uuid"]
1195 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1197 self.mock_object(self.client, '_get_volume_by_args',
1198 mock.Mock(return_value=volume))
1199 self.mock_object(self.client, 'send_request',
1200 mock.Mock(return_value=return_value))
1202 body = {
1203 'efficiency': {'compression': 'background'}
1204 }
1206 self.client.enable_compression_async(fake.VOLUME_NAMES[0])
1208 self.client.send_request.assert_called_once_with(
1209 f'/storage/volumes/{uuid}', 'patch', body=body)
1210 self.client._get_volume_by_args.assert_called_once_with(
1211 vol_name=fake.VOLUME_NAMES[0])
1213 def test_disable_compression_async(self):
1214 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1215 uuid = volume["uuid"]
1216 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1218 self.mock_object(self.client, '_get_volume_by_args',
1219 mock.Mock(return_value=volume))
1220 self.mock_object(self.client, 'send_request',
1221 mock.Mock(return_value=return_value))
1223 body = {
1224 'efficiency': {'compression': 'none'}
1225 }
1227 self.client.disable_compression_async(fake.VOLUME_NAMES[0])
1229 self.client.send_request.assert_called_once_with(
1230 f'/storage/volumes/{uuid}', 'patch', body=body)
1231 self.client._get_volume_by_args.assert_called_once_with(
1232 vol_name=fake.VOLUME_NAMES[0])
1234 def test_apply_volume_efficiency_policy(self):
1235 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1236 uuid = volume["uuid"]
1237 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1239 self.mock_object(self.client, '_get_volume_by_args',
1240 mock.Mock(return_value=volume))
1241 self.mock_object(self.client, 'send_request',
1242 mock.Mock(return_value=return_value))
1244 body = {
1245 'efficiency': {'policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}
1246 }
1248 self.client.apply_volume_efficiency_policy(
1249 fake.VOLUME_NAMES[0],
1250 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME
1251 )
1253 self.client.send_request.assert_called_once_with(
1254 f'/storage/volumes/{uuid}', 'patch', body=body)
1255 self.client._get_volume_by_args.assert_called_once_with(
1256 vol_name=fake.VOLUME_NAMES[0])
1258 def test_apply_volume_efficiency_none_policy(self):
1259 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1260 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1262 self.mock_object(self.client, '_get_volume_by_args',
1263 mock.Mock(return_value=volume))
1264 self.mock_object(self.client, 'send_request',
1265 mock.Mock(return_value=return_value))
1267 self.client.apply_volume_efficiency_policy(
1268 fake.VOLUME_NAMES[0],
1269 efficiency_policy=None
1270 )
1272 self.client._get_volume_by_args.assert_not_called()
1274 def test_set_volume_max_files(self):
1275 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1276 uuid = volume["uuid"]
1277 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1278 fake_max_files = '40000'
1280 self.mock_object(self.client, '_get_volume_by_args',
1281 mock.Mock(return_value=volume))
1282 self.mock_object(self.client, 'send_request',
1283 mock.Mock(return_value=return_value))
1285 body = {
1286 'files.maximum': int(fake_max_files)
1287 }
1289 self.client.set_volume_max_files(fake.VOLUME_NAMES[0], fake_max_files)
1291 self.client.send_request.assert_called_once_with(
1292 f'/storage/volumes/{uuid}', 'patch', body=body)
1293 self.client._get_volume_by_args.assert_called_once_with(
1294 vol_name=fake.VOLUME_NAMES[0])
1296 def test_set_volume_max_files_retry_allocated(self):
1297 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1298 uuid = volume["uuid"]
1299 fake_max_files = '40000'
1300 fake_used_files = '30000'
1301 alloc_files = {'maximum': fake_max_files, 'used': fake_used_files}
1302 side_effect = [
1303 netapp_api.api.NaApiError(
1304 code=netapp_api.EREST_CANNOT_MODITY_SPECIFIED_FIELD), None]
1306 self.mock_object(self.client, '_get_volume_by_args',
1307 mock.Mock(return_value=volume))
1308 mock_sr = self.mock_object(self.client, 'send_request',
1309 mock.Mock(side_effect=side_effect))
1310 self.mock_object(self.client, 'get_volume_allocated_files',
1311 mock.Mock(return_value=alloc_files))
1313 body_before = {
1314 'files.maximum': int(fake_max_files)
1315 }
1316 body_retry = {
1317 'files.maximum': int(fake_used_files)
1318 }
1320 self.client.set_volume_max_files(
1321 fake.VOLUME_NAMES[0], fake_max_files, retry_allocated=True)
1323 mock_sr.assert_has_calls([
1324 mock.call(f'/storage/volumes/{uuid}', 'patch', body=body_before),
1325 mock.call(f'/storage/volumes/{uuid}', 'patch', body=body_retry),
1326 ])
1327 self.client._get_volume_by_args.assert_called()
1329 def test_set_volume_snapdir_access(self):
1330 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1331 uuid = volume["uuid"]
1332 return_value = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1333 fake_hide_snapdir = 'fake-snapdir'
1335 self.mock_object(self.client, '_get_volume_by_args',
1336 mock.Mock(return_value=volume))
1337 self.mock_object(self.client, 'send_request',
1338 mock.Mock(return_value=return_value))
1340 body = {
1341 'snapshot_directory_access_enabled': str(
1342 not fake_hide_snapdir).lower()
1343 }
1345 self.client.set_volume_snapdir_access(fake.VOLUME_NAMES[0],
1346 fake_hide_snapdir)
1348 self.client.send_request.assert_called_once_with(
1349 f'/storage/volumes/{uuid}', 'patch', body=body)
1350 self.client._get_volume_by_args.assert_called_once_with(
1351 vol_name=fake.VOLUME_NAMES[0])
1353 def test_get_fpolicy_scopes(self):
1354 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1355 uuid = volume["uuid"]
1356 return_value = fake.GENERIC_FPOLICY_RESPONSE
1358 query = {
1359 'name': fake.FPOLICY_POLICY_NAME,
1360 'scope.include_shares': fake.VOLUME_NAMES[0],
1361 'scope.include_extension': fake.FPOLICY_EXT_TO_INCLUDE,
1362 'scope.exclude_extension': fake.FPOLICY_EXT_TO_EXCLUDE
1363 }
1365 expected_result = [
1366 {
1367 'policy-name': fake.FPOLICY_POLICY_NAME,
1368 'file-extensions-to-include': fake.FPOLICY_EXT_TO_INCLUDE_LIST,
1369 'file-extensions-to-exclude': fake.FPOLICY_EXT_TO_EXCLUDE_LIST,
1370 'shares-to-include': [fake.VOLUME_NAMES[0]],
1371 }
1372 ]
1374 self.mock_object(self.client, '_get_volume_by_args',
1375 mock.Mock(return_value=volume))
1376 self.mock_object(self.client, '_has_records',
1377 mock.Mock(return_value=True))
1378 self.mock_object(self.client, 'send_request',
1379 mock.Mock(return_value=return_value))
1381 result = self.client.get_fpolicy_scopes(
1382 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME,
1383 fake.FPOLICY_EXT_TO_INCLUDE_LIST, fake.FPOLICY_EXT_TO_EXCLUDE_LIST,
1384 [fake.VOLUME_NAMES[0]])
1386 self.client._get_volume_by_args.assert_called_once_with(
1387 vol_name=fake.VOLUME_NAMES[0])
1388 self.client.send_request.assert_called_once_with(
1389 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query)
1391 self.assertEqual(expected_result, result)
1393 def test_get_fpolicy_policies_status(self):
1394 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1395 uuid = volume["uuid"]
1396 return_value = fake.GENERIC_FPOLICY_RESPONSE
1398 query = {
1399 'name': fake.FPOLICY_POLICY_NAME,
1400 'enabled': 'true'
1401 }
1403 expected_result = [
1404 {
1405 'policy-name': fake.FPOLICY_POLICY_NAME,
1406 'status': True,
1407 'sequence-number': 1
1408 }
1409 ]
1411 self.mock_object(self.client, '_get_volume_by_args',
1412 mock.Mock(return_value=volume))
1413 self.mock_object(self.client, '_has_records',
1414 mock.Mock(return_value=True))
1415 self.mock_object(self.client, 'send_request',
1416 mock.Mock(return_value=return_value))
1418 result = self.client.get_fpolicy_policies_status(
1419 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 'true')
1421 self.client._get_volume_by_args.assert_called_once_with(
1422 vol_name=fake.VOLUME_NAMES[0])
1423 self.client.send_request.assert_called_once_with(
1424 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query)
1426 self.assertEqual(expected_result, result)
1428 def test_get_fpolicy_policies(self):
1429 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1430 uuid = volume["uuid"]
1431 return_value = fake.GENERIC_FPOLICY_RESPONSE
1433 query = {
1434 'name': fake.FPOLICY_POLICY_NAME,
1435 'engine.name': 'native',
1436 'events': fake.FPOLICY_EVENT_NAME
1437 }
1439 expected_result = [
1440 {
1441 'policy-name': fake.FPOLICY_POLICY_NAME,
1442 'engine-name': 'native',
1443 'events': [fake.FPOLICY_EVENT_NAME]
1444 }
1445 ]
1447 self.mock_object(self.client, '_get_volume_by_args',
1448 mock.Mock(return_value=volume))
1449 self.mock_object(self.client, '_has_records',
1450 mock.Mock(return_value=True))
1451 self.mock_object(self.client, 'send_request',
1452 mock.Mock(return_value=return_value))
1454 result = self.client.get_fpolicy_policies(
1455 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 'native',
1456 [fake.FPOLICY_EVENT_NAME])
1458 self.client._get_volume_by_args.assert_called_once_with(
1459 vol_name=fake.VOLUME_NAMES[0])
1460 self.client.send_request.assert_called_once_with(
1461 f'/protocols/fpolicy/{uuid}/policies', 'get', query=query)
1463 self.assertEqual(expected_result, result)
1465 def test_get_fpolicy_events(self):
1466 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1467 uuid = volume["uuid"]
1468 return_value = fake.GENERIC_FPOLICY_EVENTS_RESPONSE
1470 query = {
1471 'name': fake.FPOLICY_EVENT_NAME,
1472 'protocol': fake.FPOLICY_PROTOCOL,
1473 'fields': 'file_operations.create,file_operations.write,'
1474 'file_operations.rename'
1475 }
1477 expected_result = [
1478 {
1479 'event-name': fake.FPOLICY_EVENT_NAME,
1480 'protocol': fake.FPOLICY_PROTOCOL,
1481 'file-operations': fake.FPOLICY_FILE_OPERATIONS_LIST
1482 }
1483 ]
1485 self.mock_object(self.client, '_get_volume_by_args',
1486 mock.Mock(return_value=volume))
1487 self.mock_object(self.client, '_has_records',
1488 mock.Mock(return_value=True))
1489 self.mock_object(self.client, 'send_request',
1490 mock.Mock(return_value=return_value))
1492 result = self.client.get_fpolicy_events(
1493 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME,
1494 fake.FPOLICY_PROTOCOL, fake.FPOLICY_FILE_OPERATIONS_LIST)
1496 self.client._get_volume_by_args.assert_called_once_with(
1497 vol_name=fake.VOLUME_NAMES[0])
1498 self.client.send_request.assert_called_once_with(
1499 f'/protocols/fpolicy/{uuid}/events', 'get', query=query)
1501 self.assertEqual(expected_result, result)
1503 def test_create_fpolicy_event(self):
1504 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1505 uuid = volume["uuid"]
1507 body = {
1508 'name': fake.FPOLICY_EVENT_NAME,
1509 'protocol': fake.FPOLICY_PROTOCOL,
1510 'file_operations.create': 'true',
1511 'file_operations.write': 'true',
1512 'file_operations.rename': 'true'
1513 }
1515 self.mock_object(self.client, '_get_volume_by_args',
1516 mock.Mock(return_value=volume))
1517 self.mock_object(self.client, 'send_request')
1519 self.client.create_fpolicy_event(
1520 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME,
1521 fake.FPOLICY_PROTOCOL, fake.FPOLICY_FILE_OPERATIONS_LIST)
1523 self.client._get_volume_by_args.assert_called_once_with(
1524 vol_name=fake.VOLUME_NAMES[0])
1525 self.client.send_request.assert_called_once_with(
1526 f'/protocols/fpolicy/{uuid}/events', 'post', body=body)
1528 def test_delete_fpolicy_policy(self):
1529 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1530 uuid = volume["uuid"]
1532 self.mock_object(self.client, '_get_volume_by_args',
1533 mock.Mock(return_value=volume))
1534 self.mock_object(self.client, 'send_request')
1536 self.client.delete_fpolicy_policy(
1537 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME)
1539 self.client._get_volume_by_args.assert_called_once_with(
1540 vol_name=fake.VOLUME_NAMES[0])
1541 self.client.send_request.assert_called_once_with(
1542 f'/protocols/fpolicy/{uuid}/policies/{fake.FPOLICY_POLICY_NAME}',
1543 'delete')
1545 def test_delete_fpolicy_event(self):
1546 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1547 uuid = volume["uuid"]
1549 self.mock_object(self.client, '_get_volume_by_args',
1550 mock.Mock(return_value=volume))
1551 self.mock_object(self.client, 'send_request')
1553 self.client.delete_fpolicy_event(
1554 fake.VOLUME_NAMES[0], fake.FPOLICY_EVENT_NAME)
1556 self.client._get_volume_by_args.assert_called_once_with(
1557 vol_name=fake.VOLUME_NAMES[0])
1558 self.client.send_request.assert_called_once_with(
1559 f'/protocols/fpolicy/{uuid}/events/{fake.FPOLICY_EVENT_NAME}',
1560 'delete')
1562 def test_enable_fpolicy_policy(self):
1563 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1564 uuid = volume["uuid"]
1566 body = {
1567 'priority': 1,
1568 }
1570 self.mock_object(self.client, '_get_volume_by_args',
1571 mock.Mock(return_value=volume))
1572 self.mock_object(self.client, 'send_request')
1574 self.client.enable_fpolicy_policy(
1575 fake.VOLUME_NAMES[0], fake.FPOLICY_POLICY_NAME, 1)
1577 self.client._get_volume_by_args.assert_called_once_with(
1578 vol_name=fake.VOLUME_NAMES[0])
1579 self.client.send_request.assert_called_once_with(
1580 f'/protocols/fpolicy/{uuid}/policies/{fake.FPOLICY_POLICY_NAME}',
1581 'patch', body=body)
1583 def test_create_fpolicy_policy_with_scope(self):
1584 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1585 uuid = volume["uuid"]
1587 body = {
1588 'name': fake.FPOLICY_POLICY_NAME,
1589 'events.name': fake.FPOLICY_EVENT_NAME,
1590 'engine.name': fake.FPOLICY_ENGINE,
1591 'scope.include_shares': [fake.VOLUME_NAMES[0]],
1592 'scope.include_extension': fake.FPOLICY_EXT_TO_INCLUDE_LIST,
1593 'scope.exclude_extension': fake.FPOLICY_EXT_TO_EXCLUDE_LIST
1594 }
1596 self.mock_object(self.client, '_get_volume_by_args',
1597 mock.Mock(return_value=volume))
1598 self.mock_object(self.client, 'send_request')
1600 self.client.create_fpolicy_policy_with_scope(
1601 fake.FPOLICY_POLICY_NAME, fake.VOLUME_NAMES[0],
1602 fake.FPOLICY_EVENT_NAME, fake.FPOLICY_ENGINE,
1603 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
1604 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE)
1606 self.client._get_volume_by_args.assert_called_once_with(
1607 vol_name=fake.VOLUME_NAMES[0])
1608 self.client.send_request.assert_called_once_with(
1609 f'/protocols/fpolicy/{uuid}/policies', 'post', body=body)
1611 def test_delete_nfs_export_policy(self):
1612 policy_name = 'fake_policy_name'
1614 query = {
1615 'name': policy_name,
1616 }
1618 api_response = fake.EXPORT_POLICY_REST
1620 mock_sr = self.mock_object(self.client, 'send_request', mock.Mock(
1621 return_value=api_response))
1623 if not api_response.get('records'): 1623 ↛ 1624line 1623 didn't jump to line 1624 because the condition on line 1623 was never true
1624 return
1625 id = api_response.get('records')[0]['id']
1627 self.client.delete_nfs_export_policy(policy_name)
1629 mock_sr.assert_has_calls([
1630 mock.call('/protocols/nfs/export-policies', 'get',
1631 query=query),
1632 mock.call(f'/protocols/nfs/export-policies/{id}', 'delete'),
1633 ])
1635 def test_delete_volume(self):
1636 """Deletes a volume."""
1637 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1639 self.mock_object(self.client, '_get_volume_by_args',
1640 mock.Mock(return_value=volume))
1642 mock_sr = self.mock_object(self.client, 'send_request')
1643 # Get volume UUID.
1644 uuid = volume['uuid']
1646 self.client.delete_volume('fake_volume_name')
1648 mock_sr.assert_called_once_with(f'/storage/volumes/{uuid}', 'delete')
1650 def test_soft_delete_volume_error(self):
1651 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1653 self.mock_object(self.client, '_get_volume_by_args',
1654 mock.Mock(return_value=volume))
1655 self.mock_object(
1656 self.client, 'send_request',
1657 self._mock_api_error(
1658 code=netapp_api.EREST_VOLDEL_NOT_ALLOW_BY_CLONE))
1659 mock_rename = self.mock_object(self.client, 'rename_volume')
1661 # Get volume UUID.
1662 uuid = volume['uuid']
1664 self.client.soft_delete_volume('fake_volume_name')
1666 self.client.send_request.assert_called_once_with(
1667 f'/storage/volumes/{uuid}', 'delete')
1668 mock_rename.assert_called_once_with(
1669 'fake_volume_name',
1670 client_cmode_rest.DELETED_PREFIX + 'fake_volume_name')
1672 def test_soft_delete_volume_error_return_errors(self):
1673 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1675 self.mock_object(self.client, '_get_volume_by_args',
1676 mock.Mock(return_value=volume))
1677 self.mock_object(
1678 self.client, 'send_request',
1679 self._mock_api_error(
1680 code=netapp_api.EREST_VOLDEL_NOT_ALLOW_BY_CLONE))
1682 ret = self.client.soft_delete_volume('fake_volume_name',
1683 return_errors=True)
1684 self.assertEqual('del_not_allow_by_clone', ret)
1686 def test_prune_deleted_volumes_no_clones_online(self):
1687 api_response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST]
1688 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1689 self.mock_object(self.client, 'get_deleted_volumes_to_prune',
1690 mock.Mock(return_value=api_response))
1691 self.mock_object(self.client, '_get_volume_by_args',
1692 mock.Mock(return_value=volume))
1693 self.mock_object(self.client, 'send_request')
1695 self.mock_object(
1696 copy, 'deepcopy', mock.Mock(return_value=self.client))
1697 mock_get_clones = self.mock_object(
1698 self.client, 'get_clones_of_parent_volume',
1699 mock.Mock(return_value=[]))
1701 self.client.prune_deleted_volumes()
1703 mock_get_clones.assert_called_once_with(
1704 api_response[0]['svm']['name'], api_response[0]['name'])
1706 def test_prune_deleted_volumes_no_clones_offline(self):
1707 response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST]
1708 api_response = copy.deepcopy(response)
1709 api_response[0]['state'] = 'offline'
1711 self.mock_object(self.client, 'get_deleted_volumes_to_prune',
1712 mock.Mock(return_value=api_response))
1713 self.mock_object(
1714 copy, 'deepcopy', mock.Mock(return_value=self.client))
1715 mock_get_clones = self.mock_object(
1716 self.client, 'get_clones_of_parent_volume',
1717 mock.Mock(return_value=[]))
1718 mock_delete = self.mock_object(
1719 self.client, 'delete_volume',
1720 mock.Mock(return_value='success'))
1722 self.client.prune_deleted_volumes()
1724 mock_get_clones.assert_called_once_with(
1725 api_response[0]['svm']['name'], api_response[0]['name'])
1726 mock_delete.assert_called()
1728 def test_prune_deleted_volumes_clones_online(self):
1729 api_response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST]
1730 self.mock_object(self.client, 'get_deleted_volumes_to_prune',
1731 mock.Mock(return_value=api_response))
1732 self.mock_object(
1733 copy, 'deepcopy', mock.Mock(return_value=self.client))
1734 mock_get_clones = self.mock_object(
1735 self.client, 'get_clones_of_parent_volume',
1736 mock.Mock(return_value=['fake_clone']))
1737 mock_status = self.mock_object(
1738 self.client, 'volume_clone_split_status',
1739 mock.Mock(return_value='unknown'))
1740 mock_start = self.mock_object(
1741 self.client, 'volume_clone_split_start')
1743 self.client.prune_deleted_volumes()
1745 mock_get_clones.assert_called_once_with(
1746 api_response[0]['svm']['name'], api_response[0]['name'])
1747 mock_status.assert_called_once_with('fake_clone')
1748 mock_start.assert_called_once_with('fake_clone')
1750 def test_prune_deleted_volumes_clones_offline(self):
1751 response = [fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST]
1752 api_response = copy.deepcopy(response)
1753 api_response[0]['state'] = 'offline'
1755 self.mock_object(self.client, 'get_deleted_volumes_to_prune',
1756 mock.Mock(return_value=api_response))
1757 self.mock_object(
1758 copy, 'deepcopy', mock.Mock(return_value=self.client))
1759 mock_get_clones = self.mock_object(
1760 self.client, 'get_clones_of_parent_volume',
1761 mock.Mock(return_value=['fake_clone']))
1762 mock_online = self.mock_object(self.client, 'online_volume')
1764 self.client.prune_deleted_volumes()
1766 mock_get_clones.assert_called_once_with(
1767 api_response[0]['svm']['name'], api_response[0]['name'])
1768 mock_online.assert_has_calls([
1769 mock.call(api_response[0]['name']),
1770 mock.call('fake_clone'),
1771 ])
1773 def test__unmount_volume(self):
1774 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1776 self.mock_object(self.client, '_get_volume_by_args',
1777 mock.Mock(return_value=volume))
1778 mock_send_request = self.mock_object(self.client, 'send_request')
1779 uuid = volume['uuid']
1781 # Unmount volume async operation.
1782 body = {"nas": {"path": ""}}
1784 self.client._unmount_volume('fake_volume_name')
1785 mock_send_request.assert_called_once_with(
1786 f'/storage/volumes/{uuid}', 'patch', body=body)
1788 def test_online_volume(self):
1789 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1791 self.mock_object(self.client, '_get_volume_by_args',
1792 mock.Mock(return_value=volume))
1793 mock_send_request = self.mock_object(self.client, 'send_request')
1794 uuid = volume['uuid']
1796 body = {'state': 'online'}
1797 self.client.online_volume('fake_volume_name')
1798 mock_send_request.assert_called_once_with(f'/storage/volumes/{uuid}',
1799 'patch', body=body)
1801 def test_offline_volume(self):
1802 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
1804 self.mock_object(self.client, '_get_volume_by_args',
1805 mock.Mock(return_value=volume))
1806 mock_send_request = self.mock_object(self.client, 'send_request')
1807 uuid = volume['uuid']
1809 body = {'state': 'offline'}
1810 self.client.offline_volume('fake_volume_name')
1811 mock_send_request.assert_called_once_with(f'/storage/volumes/{uuid}',
1812 'patch', body=body)
1814 def test_qos_policy_group_rename(self):
1815 """Renames a QoS policy group."""
1817 qos_policy_group_name = 'extreme'
1818 new_name = 'new_name'
1819 res = fake.QOS_POLICY_GROUP_REST
1820 mock_send_request = self.mock_object(self.client, 'send_request',
1821 mock.Mock(return_value=res))
1822 query = {
1823 'name': qos_policy_group_name,
1824 'fields': 'uuid',
1825 }
1826 uuid = res.get('records')[0]['uuid']
1827 body = {"name": new_name}
1829 self.client.qos_policy_group_rename(qos_policy_group_name, new_name)
1831 mock_send_request.assert_has_calls([
1832 mock.call('/storage/qos/policies', 'get', query=query),
1833 mock.call(f'/storage/qos/policies/{uuid}', 'patch',
1834 body=body),
1835 ])
1837 def test_qos_policy_group_get(self):
1838 qos_policy_group_name = 'extreme'
1839 qos_policy_group = fake.QOS_POLICY_GROUP_REST
1840 qos_policy = qos_policy_group.get('records')[0]
1841 max_throughput = qos_policy.get('fixed',
1842 {}).get('max_throughput_iops')
1843 min_throughput = qos_policy.get('fixed',
1844 {}).get('min_throughput_iops')
1846 expected = {
1847 'policy-group': qos_policy.get('name'),
1848 'vserver': qos_policy.get('svm', {}).get('name'),
1849 'max-throughput': max_throughput if max_throughput else None,
1850 'min-throughput': min_throughput if min_throughput else None,
1851 'num-workloads': int(qos_policy.get('object_count')),
1852 }
1854 query = {
1855 'name': qos_policy_group_name,
1856 'fields': 'name,object_count,fixed.max_throughput_iops,' +
1857 'fixed.max_throughput_mbps,svm.name,' +
1858 'fixed.min_throughput_iops,fixed.min_throughput_mbps'
1859 }
1861 mock_sr = self.mock_object(self.client, 'send_request',
1862 mock.Mock(return_value=qos_policy_group))
1864 result = self.client.qos_policy_group_get(qos_policy_group_name)
1865 mock_sr.assert_called_once_with('/storage/qos/policies', 'get',
1866 query=query)
1867 self.assertEqual(expected, result)
1869 def test_remove_unused_qos_policy_groups(self):
1871 result = fake.QOS_POLICY_GROUP_REST
1873 query = {
1874 'name': '%s*' % client_cmode_rest.DELETED_PREFIX,
1875 'fields': 'uuid,name',
1876 }
1878 mock_send_request = self.mock_object(self.client, 'send_request',
1879 mock.Mock(return_value=result))
1881 res = result.get('records')
1882 for record in res:
1883 uuid = record['uuid']
1885 self.client.remove_unused_qos_policy_groups()
1887 mock_send_request.assert_has_calls([
1888 mock.call('/storage/qos/policies', 'get', query=query),
1889 mock.call(f'/storage/qos/policies/{uuid}', 'delete')])
1891 def test_unmount_volume(self):
1893 self.mock_object(self.client, '_unmount_volume')
1895 self.client.unmount_volume(fake.SHARE_NAME)
1897 self.client._unmount_volume.assert_called_once_with(fake.SHARE_NAME)
1898 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
1899 self.assertEqual(0, client_cmode_rest.LOG.warning.call_count)
1901 def test_unmount_volume_api_error(self):
1903 self.mock_object(self.client,
1904 '_unmount_volume',
1905 self._mock_api_error())
1907 self.assertRaises(netapp_api.api.NaApiError,
1908 self.client.unmount_volume,
1909 fake.SHARE_NAME)
1911 self.assertEqual(1, self.client._unmount_volume.call_count)
1912 self.assertEqual(0, client_cmode_rest.LOG.debug.call_count)
1913 self.assertEqual(0, client_cmode_rest.LOG.warning.call_count)
1915 def test_unmount_volume_with_retries(self):
1916 return_code = netapp_api.EREST_UNMOUNT_FAILED_LOCK
1917 side_effect = [netapp_api.api.NaApiError(code=return_code,
1918 message='...job ID...')] * 5
1919 side_effect.append(None)
1920 self.mock_object(self.client,
1921 '_unmount_volume',
1922 mock.Mock(side_effect=side_effect))
1923 self.mock_object(time, 'sleep')
1925 self.client.unmount_volume(fake.SHARE_NAME)
1927 self.assertEqual(6, self.client._unmount_volume.call_count)
1928 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
1929 self.assertEqual(5, client_cmode_rest.LOG.warning.call_count)
1931 def test_unmount_volume_with_max_retries(self):
1932 return_code = netapp_api.EREST_UNMOUNT_FAILED_LOCK
1933 side_effect = [netapp_api.api.NaApiError(code=return_code,
1934 message='...job ID...')] * 30
1935 self.mock_object(self.client,
1936 '_unmount_volume',
1937 mock.Mock(side_effect=side_effect))
1938 self.mock_object(time, 'sleep')
1940 self.assertRaises(exception.NetAppException,
1941 self.client.unmount_volume,
1942 fake.SHARE_NAME)
1944 self.assertEqual(10, self.client._unmount_volume.call_count)
1945 self.assertEqual(0, client_cmode_rest.LOG.debug.call_count)
1946 self.assertEqual(10, client_cmode_rest.LOG.warning.call_count)
1948 def test_qos_policy_group_exists(self):
1949 mock = self.mock_object(self.client, 'qos_policy_group_get')
1950 response = self.client.qos_policy_group_exists('extreme')
1951 mock.assert_called_once_with('extreme')
1952 self.assertTrue(response)
1954 def test_mark_qos_policy_group_for_deletion_rename_failure(self):
1955 self.mock_object(self.client, 'qos_policy_group_exists',
1956 mock.Mock(return_value=True))
1957 self.mock_object(self.client, 'qos_policy_group_rename',
1958 mock.Mock(side_effect=netapp_api.api.NaApiError))
1959 self.mock_object(client_cmode_rest.LOG, 'warning')
1960 self.mock_object(self.client, 'remove_unused_qos_policy_groups')
1962 retval = self.client.mark_qos_policy_group_for_deletion(
1963 fake.QOS_POLICY_GROUP_NAME)
1965 self.assertIsNone(retval)
1966 client_cmode_rest.LOG.warning.assert_called_once()
1967 self.client.qos_policy_group_exists.assert_called_once_with(
1968 fake.QOS_POLICY_GROUP_NAME)
1969 self.client.qos_policy_group_rename.assert_called_once_with(
1970 fake.QOS_POLICY_GROUP_NAME,
1971 client_cmode_rest.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME)
1972 self.client.remove_unused_qos_policy_groups.assert_called_once_with()
1974 @ddt.data(True, False)
1975 def test_mark_qos_policy_group_for_deletion_policy_exists(self, exists):
1976 self.mock_object(self.client, 'qos_policy_group_exists',
1977 mock.Mock(return_value=exists))
1978 self.mock_object(self.client, 'qos_policy_group_rename')
1979 mock_remove_unused_policies = self.mock_object(
1980 self.client, 'remove_unused_qos_policy_groups')
1981 self.mock_object(client_cmode_rest.LOG, 'warning')
1983 retval = self.client.mark_qos_policy_group_for_deletion(
1984 fake.QOS_POLICY_GROUP_NAME)
1986 self.assertIsNone(retval)
1988 if exists:
1989 self.client.qos_policy_group_rename.assert_called_once_with(
1990 fake.QOS_POLICY_GROUP_NAME,
1991 client_cmode_rest.DELETED_PREFIX + fake.QOS_POLICY_GROUP_NAME)
1992 mock_remove_unused_policies.assert_called_once_with()
1993 else:
1994 self.assertFalse(self.client.qos_policy_group_rename.called)
1995 self.assertFalse(
1996 self.client.remove_unused_qos_policy_groups.called)
1997 self.assertFalse(client_cmode_rest.LOG.warning.called)
1999 def test_set_volume_size(self):
2000 unique_volume_return = {'uuid': 'fake_uuid'}
2001 self.mock_object(self.client, '_get_volume_by_args',
2002 mock.Mock(return_value=unique_volume_return))
2003 mock_sr = self.mock_object(self.client, 'send_request')
2004 self.client.set_volume_size('fake_name', 1)
2006 body = {
2007 'space.size': 1 * units.Gi
2008 }
2009 mock_sr.assert_called_once_with(
2010 '/storage/volumes/fake_uuid', 'patch', body=body)
2012 def test_qos_policy_group_modify(self):
2013 return_request = {
2014 'records': [{'uuid': 'fake_uuid'}]
2015 }
2016 mock_sr = self.mock_object(self.client, 'send_request',
2017 mock.Mock(return_value=return_request))
2018 self.client.qos_policy_group_modify('qos_fake_name', '1000iops')
2020 query = {
2021 'name': 'qos_fake_name',
2022 }
2023 body = {
2024 'fixed.max_throughput_iops': 1000,
2025 'fixed.max_throughput_mbps': 0
2026 }
2027 mock_sr.assert_has_calls([
2028 mock.call('/storage/qos/policies', 'get', query=query),
2029 mock.call('/storage/qos/policies/fake_uuid', 'patch', body=body),
2030 ])
2032 @ddt.data(True, False)
2033 def test_set_volume_filesys_size_fixed(self, filesys_size_fixed):
2034 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2036 self.mock_object(self.client, '_get_volume_by_args',
2037 mock.Mock(return_value=volume))
2038 mock_send_request = self.mock_object(self.client, 'send_request')
2039 fake_uuid = volume['uuid']
2041 self.client.set_volume_filesys_size_fixed(fake.SHARE_NAME,
2042 filesys_size_fixed)
2043 body = {
2044 'space.filesystem_size_fixed': filesys_size_fixed}
2045 mock_send_request.assert_called_once_with(
2046 f'/storage/volumes/{fake_uuid}',
2047 'patch', body=body)
2049 def test_create_snapshot(self):
2050 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2051 mock_get_volume = self.mock_object(
2052 self.client, '_get_volume_by_args',
2053 mock.Mock(return_value=volume))
2054 mock_send_request = self.mock_object(self.client, 'send_request')
2056 self.client.create_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME)
2058 mock_get_volume.assert_called_once_with(
2059 vol_name=fake.VOLUME_NAMES[0])
2060 body = {
2061 'name': fake.SNAPSHOT_NAME,
2062 }
2063 uuid = volume['uuid']
2064 mock_send_request.assert_called_once_with(
2065 f'/storage/volumes/{uuid}/snapshots', 'post', body=body)
2067 def test_is_flexgroup_supported(self):
2068 flexgroup_supported = self.client.is_flexgroup_supported()
2070 self.assertTrue(flexgroup_supported)
2072 def test_reset_volume_autosize(self):
2073 """Test reset_volume_autosize method."""
2074 mock_sr = self.mock_object(self.client, 'send_request')
2076 volume_name = fake.VOLUME_NAMES[0]
2077 vserver_name = fake.VSERVER_NAME
2079 self.client.reset_volume_autosize(volume_name, vserver_name)
2081 expected_query = {
2082 "vserver": vserver_name,
2083 "volume": volume_name
2084 }
2085 expected_body = {
2086 "autosize-reset": "true"
2087 }
2089 mock_sr.assert_called_once_with(
2090 '/private/cli/volume', 'patch',
2091 query=expected_query, body=expected_body)
2093 def test_reset_volume_autosize_api_error(self):
2094 """Test reset_volume_autosize method handles API errors."""
2095 mock_sr = self.mock_object(
2096 self.client, 'send_request',
2097 mock.Mock(side_effect=netapp_api.api.NaApiError(
2098 code='fake_code', message='fake_message')))
2100 volume_name = fake.VOLUME_NAMES[0]
2101 vserver_name = fake.VSERVER_NAME
2103 self.assertRaises(
2104 netapp_api.api.NaApiError,
2105 self.client.reset_volume_autosize,
2106 volume_name, vserver_name)
2108 self.assertTrue(mock_sr.called)
2110 @ddt.data(True, False)
2111 def test_is_flexgroup_volume(self, is_flexgroup):
2112 response = copy.deepcopy(fake.VOLUME_LIST_SIMPLE_RESPONSE_REST)
2113 expected_style = 'flexgroup' if is_flexgroup else 'flexvol'
2114 response['records'][0]['style'] = expected_style
2115 mock_send_request = self.mock_object(self.client, 'send_request',
2116 mock.Mock(return_value=response))
2117 mock_has_records = self.mock_object(
2118 self.client, '_has_records', mock.Mock(return_value=True))
2119 mock_na_utils_is_flexgroup = self.mock_object(
2120 netapp_utils, 'is_style_extended_flexgroup',
2121 mock.Mock(return_value=is_flexgroup))
2123 result = self.client.is_flexgroup_volume(fake.VOLUME_NAMES[0])
2125 self.assertEqual(is_flexgroup, result)
2126 query = {
2127 'name': fake.VOLUME_NAMES[0],
2128 'fields': 'style'
2129 }
2130 mock_send_request.assert_called_once_with('/storage/volumes/', 'get',
2131 query=query)
2132 mock_has_records.assert_called_once_with(response)
2133 mock_na_utils_is_flexgroup.assert_called_once_with(expected_style)
2135 def test_is_flexgroup_volume_raise_no_records(self):
2136 self.mock_object(self.client, 'send_request',
2137 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST))
2138 self.mock_object(
2139 self.client, '_has_records', mock.Mock(return_value=False))
2141 self.assertRaises(
2142 exception.StorageResourceNotFound,
2143 self.client.is_flexgroup_volume,
2144 fake.VOLUME_NAMES[0])
2146 def test_is_flexgroup_volume_raise_more_than_one_volume(self):
2147 self.mock_object(
2148 self.client, 'send_request',
2149 mock.Mock(return_value=fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE))
2150 self.mock_object(
2151 self.client, '_has_records', mock.Mock(return_value=True))
2153 self.assertRaises(
2154 exception.NetAppException,
2155 self.client.is_flexgroup_volume,
2156 fake.VOLUME_NAMES[0])
2158 @ddt.data(
2159 {'is_busy': True, 'owners': ['volume_clone']},
2160 {'is_busy': False, 'owners': ['snap_restore_dependent']})
2161 @ddt.unpack
2162 def test__is_busy_snapshot(self, is_busy, owners):
2163 result = self.client._is_busy_snapshot(owners)
2165 self.assertEqual(is_busy, result)
2167 @ddt.data(True, False)
2168 def test_get_snapshot(self, locked):
2169 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2170 mock_get_volume = self.mock_object(
2171 self.client, '_get_volume_by_args',
2172 mock.Mock(return_value=volume))
2173 response = copy.deepcopy(fake.SNAPSHOTS_REST_RESPONSE)
2174 owners = ['volume_clone'] if locked else []
2175 response['records'][0]['owners'] = owners
2176 mock_send_request = self.mock_object(self.client, 'send_request',
2177 mock.Mock(return_value=response))
2178 mock_has_records = self.mock_object(
2179 self.client, '_has_records', mock.Mock(return_value=True))
2181 mock_is_busy = self.mock_object(self.client, '_is_busy_snapshot',
2182 mock.Mock(return_value=True))
2184 result = self.client.get_snapshot(fake.VOLUME_NAMES[0],
2185 fake.SNAPSHOT_NAME)
2187 expected_snapshot = {
2188 'access-time': fake.SNAPSHOT_REST['create_time'],
2189 'name': fake.SNAPSHOT_REST['name'],
2190 'volume': fake.SNAPSHOT_REST['volume']['name'],
2191 'owners': set(owners),
2192 'busy': True,
2193 'locked_by_clone': locked,
2194 }
2195 self.assertEqual(expected_snapshot, result)
2196 mock_get_volume.assert_called_once_with(
2197 vol_name=fake.VOLUME_NAMES[0])
2198 uuid = volume['uuid']
2199 query = {
2200 'name': fake.SNAPSHOT_NAME,
2201 'fields': 'name,volume,create_time,owners'
2202 }
2203 mock_send_request.assert_called_once_with(
2204 f'/storage/volumes/{uuid}/snapshots', 'get', query=query)
2205 mock_has_records.assert_called_once_with(response)
2206 mock_is_busy.assert_called_once_with(set(owners))
2208 def test_get_snapshot_raise_not_found(self):
2209 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2210 self.mock_object(
2211 self.client, '_get_volume_by_args',
2212 mock.Mock(return_value=volume))
2213 self.mock_object(
2214 self.client, 'send_request',
2215 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST))
2216 self.mock_object(
2217 self.client, '_has_records', mock.Mock(return_value=False))
2219 self.assertRaises(
2220 exception.SnapshotResourceNotFound,
2221 self.client.get_snapshot,
2222 fake.VOLUME_NAMES[0],
2223 fake.SNAPSHOT_NAME)
2225 def test_get_snapshot_raise_more_than_one(self):
2226 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2227 self.mock_object(
2228 self.client, '_get_volume_by_args',
2229 mock.Mock(return_value=volume))
2230 self.mock_object(
2231 self.client, 'send_request',
2232 mock.Mock(return_value=fake.SNAPSHOTS_MULTIPLE_REST_RESPONSE))
2233 self.mock_object(
2234 self.client, '_has_records', mock.Mock(return_value=True))
2236 self.assertRaises(
2237 exception.NetAppException,
2238 self.client.get_snapshot,
2239 fake.VOLUME_NAMES[0],
2240 fake.SNAPSHOT_NAME)
2242 def test_get_clone_children_for_snapshot(self):
2243 mock_get_records = self.mock_object(
2244 self.client, 'get_records',
2245 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST))
2247 result = self.client.get_clone_children_for_snapshot(
2248 fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME)
2250 expected_children = [{'name': fake.VOLUME_NAMES[0]}]
2251 self.assertEqual(expected_children, result)
2252 query = {
2253 'clone.parent_snapshot.name': fake.SNAPSHOT_NAME,
2254 'clone.parent_volume.name': fake.VOLUME_NAMES[0],
2255 'fields': 'name'
2256 }
2257 mock_get_records.assert_called_once_with(
2258 '/storage/volumes', query=query)
2260 def test_volume_clone_split_start(self):
2261 fake_resp_vol = fake.REST_SIMPLE_RESPONSE["records"][0]
2262 fake_uuid = fake_resp_vol['uuid']
2263 mock_get_unique_volume = self.mock_object(
2264 self.client, "_get_volume_by_args",
2265 mock.Mock(return_value=fake_resp_vol)
2266 )
2267 mock_send_request = self.mock_object(
2268 self.client, 'send_request',
2269 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST))
2271 self.client.volume_clone_split_start(fake.VOLUME_NAMES[0])
2272 mock_get_unique_volume.assert_called_once()
2273 body = {
2274 'clone.split_initiated': 'true',
2275 }
2276 mock_send_request.assert_called_once_with(
2277 f'/storage/volumes/{fake_uuid}', 'patch', body=body,
2278 wait_on_accepted=False)
2280 def test_volume_clone_split_stop(self):
2281 fake_resp_vol = fake.REST_SIMPLE_RESPONSE["records"][0]
2282 fake_uuid = fake_resp_vol['uuid']
2283 mock_get_unique_volume = self.mock_object(
2284 self.client, "_get_volume_by_args",
2285 mock.Mock(return_value=fake_resp_vol)
2286 )
2287 mock_send_request = self.mock_object(
2288 self.client, 'send_request',
2289 mock.Mock(return_value=fake.VOLUME_LIST_SIMPLE_RESPONSE_REST))
2291 self.client.volume_clone_split_stop(fake.VOLUME_NAMES[0])
2292 mock_get_unique_volume.assert_called_once()
2293 body = {
2294 'clone.split_initiated': 'false',
2295 }
2296 mock_send_request.assert_called_once_with(
2297 f'/storage/volumes/{fake_uuid}', 'patch', body=body,
2298 wait_on_accepted=False)
2300 def test_rename_snapshot(self):
2301 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2302 mock_get_volume = self.mock_object(
2303 self.client, '_get_volume_by_args',
2304 mock.Mock(return_value=volume))
2305 mock_send_request = self.mock_object(self.client, 'send_request')
2307 self.client.rename_snapshot(
2308 fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME,
2309 'new_' + fake.SNAPSHOT_NAME)
2311 mock_get_volume.assert_called_once_with(
2312 vol_name=fake.VOLUME_NAMES[0])
2313 query = {
2314 'name': fake.SNAPSHOT_NAME,
2315 }
2316 body = {
2317 'name': 'new_' + fake.SNAPSHOT_NAME,
2318 }
2319 uuid = volume['uuid']
2320 mock_send_request.assert_called_once_with(
2321 f'/storage/volumes/{uuid}/snapshots', 'patch', query=query,
2322 body=body)
2324 def test__get_soft_deleted_snapshots(self):
2325 mock_get_records = self.mock_object(
2326 self.client, 'get_records',
2327 mock.Mock(return_value=fake.SNAPSHOTS_MULTIPLE_REST_RESPONSE))
2328 self.mock_object(
2329 self.client, '_is_busy_snapshot',
2330 mock.Mock(side_effect=[True, False]))
2332 snapshots_map = self.client._get_soft_deleted_snapshots()
2334 expected_snapshots = {
2335 fake.VSERVER_NAME: [{
2336 "uuid": fake.FAKE_SNAPSHOT_UUID,
2337 "volume_uuid": fake.FAKE_VOLUME_UUID,
2338 }]
2339 }
2340 self.assertEqual(expected_snapshots, snapshots_map)
2341 query = {
2342 'name': 'deleted_manila_*',
2343 'fields': 'uuid,volume,owners,svm.name'
2344 }
2345 mock_get_records.assert_called_once_with(
2346 '/storage/volumes/*/snapshots', query=query)
2348 @ddt.data(True, False)
2349 def test_prune_deleted_snapshots(self, fail_deleting):
2350 soft_deleted_snapshots = {
2351 fake.VSERVER_NAME: [{
2352 "uuid": fake.FAKE_SNAPSHOT_UUID,
2353 "volume_uuid": fake.FAKE_VOLUME_UUID,
2354 }]
2355 }
2356 mock_get_snaps = self.mock_object(
2357 self.client, '_get_soft_deleted_snapshots',
2358 mock.Mock(return_value=soft_deleted_snapshots)
2359 )
2360 if fail_deleting:
2361 mock_send_request = self.mock_object(
2362 self.client, 'send_request',
2363 mock.Mock(side_effect=netapp_api.api.NaApiError))
2364 else:
2365 mock_send_request = self.mock_object(self.client, 'send_request')
2367 self.client.prune_deleted_snapshots()
2369 mock_get_snaps.assert_called_once_with()
2370 vol_uuid = fake.FAKE_VOLUME_UUID
2371 snap_uuid = fake.FAKE_SNAPSHOT_UUID
2372 mock_send_request.assert_called_once_with(
2373 f'/storage/volumes/{vol_uuid}/snapshots/{snap_uuid}', 'delete')
2375 @ddt.data(True, False)
2376 def test_snapshot_exists(self, exists):
2377 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2378 vol_uuid = volume['uuid']
2379 mock_get_vol = self.mock_object(
2380 self.client, '_get_volume_by_args',
2381 mock.Mock(return_value=volume))
2382 mock_send_request = self.mock_object(
2383 self.client, 'send_request',
2384 mock.Mock(return_value=fake.SNAPSHOTS_REST_RESPONSE))
2385 mock_has_records = self.mock_object(self.client, '_has_records',
2386 mock.Mock(return_value=exists))
2388 res = self.client.snapshot_exists(fake.SNAPSHOT_NAME,
2389 fake.VOLUME_NAMES[0])
2391 self.assertEqual(exists, res)
2392 mock_get_vol.assert_called_once_with(
2393 vol_name=fake.VOLUME_NAMES[0], fields='uuid,state')
2394 query = {
2395 'name': fake.SNAPSHOT_NAME
2396 }
2397 mock_send_request.assert_called_once_with(
2398 f'/storage/volumes/{vol_uuid}/snapshots/', 'get', query=query)
2399 mock_has_records.assert_called_once_with(fake.SNAPSHOTS_REST_RESPONSE)
2401 def test_snapshot_exists_error(self):
2402 volume = {'state': 'offline'}
2403 self.mock_object(
2404 self.client, '_get_volume_by_args',
2405 mock.Mock(return_value=volume))
2407 self.assertRaises(
2408 exception.SnapshotUnavailable,
2409 self.client.snapshot_exists,
2410 fake.SNAPSHOT_NAME, fake.VOLUME_NAMES[0])
2412 @ddt.data('source', 'destination', None)
2413 def test_volume_has_snapmirror_relationships(self, snapmirror_rel_type):
2414 """Snapmirror relationships can be both ways."""
2416 vol = fake.FAKE_MANAGE_VOLUME
2417 snapmirror = {
2418 'source-vserver': fake.SM_SOURCE_VSERVER,
2419 'source-volume': fake.SM_SOURCE_VOLUME,
2420 'destination-vserver': fake.SM_DEST_VSERVER,
2421 'destination-volume': fake.SM_DEST_VOLUME,
2422 'mirror-state': 'snapmirrored',
2423 'schedule': 'daily',
2424 }
2425 expected_get_snapmirrors_call_count = 2
2426 expected_get_snapmirrors_calls = [
2427 mock.call(source_vserver=vol['owning-vserver-name'],
2428 source_volume=vol['name']),
2429 mock.call(dest_vserver=vol['owning-vserver-name'],
2430 dest_volume=vol['name']),
2431 ]
2432 if snapmirror_rel_type is None:
2433 side_effect = ([], [])
2434 elif snapmirror_rel_type == 'source':
2435 snapmirror['source-vserver'] = vol['owning-vserver-name']
2436 snapmirror['source-volume'] = vol['name']
2437 side_effect = ([snapmirror], None)
2438 expected_get_snapmirrors_call_count = 1
2439 expected_get_snapmirrors_calls.pop()
2440 else:
2441 snapmirror['destination-vserver'] = vol['owning-vserver-name']
2442 snapmirror['destination-volume'] = vol['name']
2443 side_effect = (None, [snapmirror])
2444 mock_get_snapmirrors_call = self.mock_object(
2445 self.client, 'get_snapmirrors', mock.Mock(side_effect=side_effect))
2446 mock_exc_log = self.mock_object(client_cmode.LOG, 'exception')
2447 expected_retval = True if snapmirror_rel_type else False
2449 retval = self.client.volume_has_snapmirror_relationships(vol)
2451 self.assertEqual(expected_retval, retval)
2452 self.assertEqual(expected_get_snapmirrors_call_count,
2453 mock_get_snapmirrors_call.call_count)
2454 mock_get_snapmirrors_call.assert_has_calls(
2455 expected_get_snapmirrors_calls)
2456 self.assertFalse(mock_exc_log.called)
2458 def test_volume_has_snapmirror_relationships_api_error(self):
2460 vol = fake.FAKE_MANAGE_VOLUME
2461 expected_get_snapmirrors_calls = [
2462 mock.call(source_vserver=vol['owning-vserver-name'],
2463 source_volume=vol['name']),
2464 ]
2465 mock_get_snapmirrors_call = self.mock_object(
2466 self.client, 'get_snapmirrors', mock.Mock(
2467 side_effect=self._mock_api_error()))
2468 mock_exc_log = self.mock_object(client_cmode_rest.LOG, 'exception')
2470 retval = self.client.volume_has_snapmirror_relationships(vol)
2472 self.assertFalse(retval)
2473 self.assertEqual(1, mock_get_snapmirrors_call.call_count)
2474 mock_get_snapmirrors_call.assert_has_calls(
2475 expected_get_snapmirrors_calls)
2476 self.assertTrue(mock_exc_log.called)
2478 def test_get_snapmirrors_svm(self):
2479 return_get_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE
2481 mock_get_snap = self.mock_object(
2482 self.client, 'get_snapmirrors',
2483 mock.Mock(return_value=return_get_snp))
2485 res = self.client.get_snapmirrors_svm(fake.SM_SOURCE_VSERVER,
2486 fake.SM_DEST_VSERVER,
2487 None)
2489 mock_get_snap.assert_called_once_with(
2490 source_path=fake.SM_SOURCE_VSERVER + ':*',
2491 dest_path=fake.SM_DEST_VSERVER + ':*',
2492 desired_attributes=None)
2493 self.assertEqual(return_get_snp, res)
2495 def test_get_snapmirrors(self):
2497 api_response = fake.SNAPMIRROR_GET_ITER_RESPONSE_REST
2498 mock_send_request = self.mock_object(
2499 self.client,
2500 'send_request',
2501 mock.Mock(return_value=api_response))
2503 result = self.client.get_snapmirrors(
2504 fake.SM_SOURCE_PATH, fake.SM_DEST_PATH,
2505 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
2506 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME,
2507 enable_tunneling=True)
2509 expected = fake.REST_GET_SNAPMIRRORS_RESPONSE
2511 query = {
2512 'source.path': (fake.SM_SOURCE_VSERVER + ':' +
2513 fake.SM_SOURCE_VOLUME),
2514 'destination.path': (fake.SM_DEST_VSERVER +
2515 ':' + fake.SM_DEST_VOLUME),
2516 'fields': 'state,source.svm.name,source.path,destination.svm.name,'
2517 'destination.path,transfer.end_time,uuid,policy.type,'
2518 'transfer_schedule.name,transfer.state,'
2519 'last_transfer_type,transfer.bytes_transferred,healthy'
2520 }
2522 mock_send_request.assert_called_once_with('/snapmirror/relationships',
2523 'get', query=query,
2524 enable_tunneling=True)
2525 self.assertEqual(expected, result)
2527 @ddt.data(
2528 {'source_path': fake.SM_SOURCE_PATH, 'dest_path': fake.SM_DEST_PATH},
2529 {'source_path': None, 'dest_path': None})
2530 @ddt.unpack
2531 def test__get_snapmirrors(self, source_path, dest_path):
2533 api_response = fake.SNAPMIRROR_GET_ITER_RESPONSE_REST
2534 mock_send_request = self.mock_object(
2535 self.client,
2536 'send_request',
2537 mock.Mock(return_value=api_response))
2539 result = self.client._get_snapmirrors(
2540 source_path, dest_path,
2541 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
2542 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME)
2544 query = {
2545 'source.path': (fake.SM_SOURCE_VSERVER + ':' +
2546 fake.SM_SOURCE_VOLUME),
2547 'destination.path': (fake.SM_DEST_VSERVER +
2548 ':' + fake.SM_DEST_VOLUME),
2549 'fields': 'state,source.svm.name,source.path,destination.svm.name,'
2550 'destination.path,transfer.end_time,uuid,policy.type,'
2551 'transfer_schedule.name,transfer.state,'
2552 'last_transfer_type,transfer.bytes_transferred,healthy'
2553 }
2555 mock_send_request.assert_called_once_with('/snapmirror/relationships',
2556 'get', query=query,
2557 enable_tunneling=True)
2558 self.assertEqual(1, len(result))
2560 def test__get_snapmirrors_not_found(self):
2562 api_response = fake.NO_RECORDS_RESPONSE_REST
2563 mock_send_request = self.mock_object(
2564 self.client,
2565 'send_request',
2566 mock.Mock(return_value=api_response))
2568 result = self.client._get_snapmirrors(
2569 fake.SM_SOURCE_PATH, fake.SM_DEST_PATH,
2570 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
2571 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME)
2573 query = {
2574 'source.path': (fake.SM_SOURCE_VSERVER + ':' +
2575 fake.SM_SOURCE_VOLUME),
2576 'destination.path': (fake.SM_DEST_VSERVER +
2577 ':' + fake.SM_DEST_VOLUME),
2578 'fields': 'state,source.svm.name,source.path,destination.svm.name,'
2579 'destination.path,transfer.end_time,uuid,policy.type,'
2580 'transfer_schedule.name,transfer.state,'
2581 'last_transfer_type,transfer.bytes_transferred,healthy'
2582 }
2584 mock_send_request.assert_called_once_with('/snapmirror/relationships',
2585 'get', query=query,
2586 enable_tunneling=True)
2587 self.assertEqual([], result)
2589 @ddt.data(True, False)
2590 def test_modify_volume_no_optional_args(self, is_flexgroup):
2592 self.mock_object(self.client, 'send_request')
2593 mock_update_volume_efficiency_attributes = self.mock_object(
2594 self.client, 'update_volume_efficiency_attributes')
2596 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2597 self.mock_object(self.client, '_get_volume_by_args',
2598 mock.Mock(return_value=volume))
2599 self.mock_object(self.client, '_is_snaplock_enabled_volume',
2600 mock.Mock(return_value=True))
2601 aggr = fake.SHARE_AGGREGATE_NAME
2602 if is_flexgroup:
2603 aggr = list(fake.SHARE_AGGREGATE_NAMES)
2605 self.client.modify_volume(aggr, fake.SHARE_NAME)
2607 # default body for call with no optional params
2608 body = {'guarantee': {'type': 'volume'}}
2609 self.client.send_request.assert_called_once_with(
2610 '/storage/volumes/' + volume['uuid'], 'patch', body=body)
2611 mock_update_volume_efficiency_attributes.assert_called_once_with(
2612 fake.SHARE_NAME, False, False,
2613 is_flexgroup=is_flexgroup, efficiency_policy=None
2614 )
2616 @ddt.data((fake.QOS_POLICY_GROUP_NAME, None),
2617 (None, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME))
2618 @ddt.unpack
2619 def test_modify_volume_all_optional_args(self, qos_group,
2620 adaptive_qos_group):
2621 self.client.features.add_feature('ADAPTIVE_QOS')
2622 self.mock_object(self.client, 'send_request')
2623 mock_update_volume_efficiency_attributes = self.mock_object(
2624 self.client, 'update_volume_efficiency_attributes')
2626 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
2627 self.mock_object(self.client, '_get_volume_by_args',
2628 mock.Mock(return_value=volume))
2629 options = {'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}
2630 self.mock_object(self.client, '_is_snaplock_enabled_volume',
2631 mock.Mock(return_value=True))
2633 self.client.modify_volume(
2634 fake.SHARE_AGGREGATE_NAME,
2635 fake.SHARE_NAME,
2636 thin_provisioned=True,
2637 snapshot_policy=fake.SNAPSHOT_POLICY_NAME,
2638 language=fake.LANGUAGE,
2639 dedup_enabled=True,
2640 compression_enabled=False,
2641 max_files=fake.MAX_FILES,
2642 qos_policy_group=qos_group,
2643 adaptive_qos_policy_group=adaptive_qos_group,
2644 autosize_attributes=fake.VOLUME_AUTOSIZE_ATTRS,
2645 hide_snapdir=True,
2646 **options
2647 )
2649 qos_policy_name = qos_group or adaptive_qos_group
2650 body = {
2651 'guarantee': {'type': 'none'},
2652 'autosize': {
2653 'mode': 'off',
2654 'grow_threshold': '85',
2655 'shrink_threshold': '50',
2656 'maximum': '1258288',
2657 'minimum': '1048576'
2658 },
2659 'files': {'maximum': 5000},
2660 'snapshot_policy': {'name': 'fake_snapshot_policy'},
2661 'qos': {'policy': {'name': qos_policy_name}},
2662 'snapshot_directory_access_enabled': 'false',
2663 'language': 'fake_language'
2664 }
2666 self.client.send_request.assert_called_once_with(
2667 '/storage/volumes/' + volume['uuid'], 'patch', body=body)
2668 mock_update_volume_efficiency_attributes.assert_called_once_with(
2669 fake.SHARE_NAME, True, False,
2670 is_flexgroup=False,
2671 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME
2672 )
2674 def test__parse_timestamp(self):
2675 test_time_str = '2022-11-25T14:41:20+00:00'
2676 res = self.client._parse_timestamp(test_time_str)
2677 self.assertEqual(1669387280.0, res)
2679 def test__parse_timestamp_exception(self):
2680 test_time_str = None
2681 self.assertRaises(TypeError,
2682 self.client._parse_timestamp,
2683 test_time_str)
2685 def test__build_autosize_attributes(self):
2686 """Test _build_autosize_attributes with various input scenarios."""
2688 # Test case 1: Basic functionality with all supported attributes
2689 autosize_attrs = {
2690 'grow-threshold-percent': 90,
2691 'shrink-threshold-percent': 50,
2692 'maximum-size': '10GB',
2693 'minimum-size': '1GB',
2694 'mode': 'grow'
2695 }
2697 result = self.client._build_autosize_attributes(autosize_attrs)
2699 expected = {
2700 'grow_threshold': 90,
2701 'shrink_threshold': 50,
2702 'maximum': '10GB',
2703 'minimum': '1GB',
2704 'mode': 'grow'
2705 }
2706 self.assertEqual(expected, result)
2708 def test__build_autosize_attributes_partial_attrs(self):
2709 """Test _build_autosize_attributes with only some attributes."""
2710 autosize_attrs = {
2711 'grow-threshold-percent': 85,
2712 'maximum-size': '5GB'
2713 }
2715 result = self.client._build_autosize_attributes(autosize_attrs)
2717 expected = {
2718 'grow_threshold': 85,
2719 'maximum': '5GB'
2720 }
2721 self.assertEqual(expected, result)
2723 def test__build_autosize_attributes_empty_dict(self):
2724 """Test _build_autosize_attributes returns None for empty dict."""
2725 autosize_attrs = {}
2727 result = self.client._build_autosize_attributes(autosize_attrs)
2729 self.assertIsNone(result)
2731 def test__build_autosize_attributes_with_mode_only(self):
2732 """Test _build_autosize_attributes with only mode attribute."""
2733 autosize_attrs = {
2734 'mode': 'grow_shrink'
2735 }
2737 result = self.client._build_autosize_attributes(autosize_attrs)
2739 expected = {
2740 'mode': 'grow_shrink'
2741 }
2742 self.assertEqual(expected, result)
2743 autosize_attrs = {
2744 'grow-threshold-percent': 90,
2745 'maximum-size': '10GB'
2746 }
2748 result = self.client._build_autosize_attributes(autosize_attrs)
2750 expected = {
2751 'grow_threshold': 90,
2752 'maximum': '10GB'
2753 }
2754 self.assertEqual(expected, result)
2756 def test_start_volume_move(self):
2758 mock__send_volume_move_request = self.mock_object(
2759 self.client, '_send_volume_move_request')
2761 self.client.start_volume_move(fake.VOLUME_NAMES[0], fake.VSERVER_NAME,
2762 fake.SHARE_AGGREGATE_NAME,
2763 'fake_cutover', False)
2765 mock__send_volume_move_request.assert_called_once_with(
2766 fake.VOLUME_NAMES[0], fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAME,
2767 cutover_action='fake_cutover', encrypt_destination=False)
2769 def test_check_volume_move(self):
2771 mock__send_volume_move_request = self.mock_object(
2772 self.client, '_send_volume_move_request')
2774 self.client.check_volume_move(fake.VOLUME_NAMES[0], fake.VSERVER_NAME,
2775 fake.SHARE_AGGREGATE_NAME, False)
2777 mock__send_volume_move_request.assert_called_once_with(
2778 fake.VOLUME_NAMES[0], fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAME,
2779 validation_only=True, encrypt_destination=False)
2781 def test__send_volume_move_request(self):
2782 mock_sr = self.mock_object(self.client, 'send_request')
2783 self.client._send_volume_move_request('volume_name', 'vserver',
2784 'destination_aggregate',
2785 cutover_action='wait',
2786 validation_only=True,
2787 encrypt_destination=False)
2788 query = {'name': 'volume_name'}
2789 body = {
2790 'movement.destination_aggregate.name': 'destination_aggregate',
2791 'encryption.enabled': 'false',
2792 'validate_only': 'true',
2793 'movement.state': 'wait',
2794 }
2795 mock_sr.assert_called_once_with(
2796 '/storage/volumes/', 'patch', query=query, body=body,
2797 wait_on_accepted=False)
2799 def test_get_nfs_export_policy_for_volume(self):
2801 fake_query = {
2802 'name': 'fake_volume_name',
2803 'fields': 'nas.export_policy.name'
2804 }
2806 ret = {
2807 'records': [
2808 {
2809 'nas': {
2810 'export_policy': {
2811 'name': 'fake_name'
2812 }
2813 }
2814 }
2815 ]
2816 }
2818 mock_records = self.mock_object(self.client, '_has_records',
2819 mock.Mock(return_value=True))
2820 mock_sr = self.mock_object(self.client, 'send_request',
2821 mock.Mock(return_value=ret))
2823 res = self.client.get_nfs_export_policy_for_volume('fake_volume_name')
2825 mock_records.assert_called_once_with(ret)
2826 mock_sr.assert_called_once_with('/storage/volumes/', 'get',
2827 query=fake_query)
2828 expected = 'fake_name'
2829 self.assertEqual(expected, res)
2831 def test_get_unique_export_policy_id(self):
2832 mock_records = self.mock_object(self.client, '_has_records',
2833 mock.Mock(return_value=True))
2834 expected = 'fake_uuid'
2835 ret = {
2836 'records': [
2837 {
2838 'id': 'fake_uuid'
2839 }
2840 ]
2841 }
2842 mock_sr = self.mock_object(self.client, 'send_request',
2843 mock.Mock(return_value=ret))
2844 res = self.client.get_unique_export_policy_id('fake_policy_name')
2845 mock_records.assert_called_once_with(ret)
2846 mock_sr.assert_called_once_with(
2847 '/protocols/nfs/export-policies', 'get',
2848 query={'name': 'fake_policy_name'})
2849 self.assertEqual(expected, res)
2851 def test__get_nfs_export_rule_indices(self):
2852 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id',
2853 mock.Mock(return_value='fake_policy_id'))
2855 fake_uuid = 'fake_policy_id'
2857 fake_query = {
2858 'clients.match': 'fakecl',
2859 'fields': 'clients.match,index'
2860 }
2862 ret = {
2863 'records': [
2864 {
2865 'index': '0'
2866 }
2867 ]
2868 }
2870 mock_sr = self.mock_object(self.client, 'send_request',
2871 mock.Mock(return_value=ret))
2872 res = self.client._get_nfs_export_rule_indices('fake_policy', 'fakecl')
2873 mockpid.assert_called_once_with('fake_policy')
2874 mock_sr.assert_called_once_with(
2875 f'/protocols/nfs/export-policies/{fake_uuid}/rules', 'get',
2876 query=fake_query)
2877 expected = ['0']
2878 self.assertEqual(expected, res)
2880 def test__add_nfs_export_rule(self):
2881 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id',
2882 mock.Mock(return_value='fake_policy_id'))
2883 mock_sr = self.mock_object(self.client, 'send_request')
2884 self.client._add_nfs_export_rule('fake_policy', 'fakecl', False,
2885 ['rw'])
2886 mockpid.assert_called_once_with('fake_policy')
2888 body = {
2889 'clients': [{'match': 'fakecl'}],
2890 'ro_rule': ['rw'],
2891 'rw_rule': ['rw'],
2892 'superuser': ['rw']
2893 }
2894 mock_sr.assert_called_once_with(
2895 '/protocols/nfs/export-policies/fake_policy_id/rules',
2896 'post', body=body)
2898 def test__update_nfs_export_rule(self):
2900 fake_body = {
2901 'client_match': 'fake_cli',
2902 'ro_rule': ['rw'],
2903 'rw_rule': ['rw'],
2904 'superuser': ['rw']
2905 }
2907 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id',
2908 mock.Mock(return_value='fake_policy_id'))
2909 mock_sr = self.mock_object(self.client, 'send_request')
2910 self.client._update_nfs_export_rule('fake_policy', 'fake_cli', False,
2911 '0', ['rw'])
2912 mockpid.assert_called_once_with('fake_policy')
2913 mock_sr.assert_called_once_with(
2914 '/protocols/nfs/export-policies/fake_policy_id/rules/0',
2915 'patch', body=fake_body)
2917 def test__remove_nfs_export_rules(self):
2919 fake_body = {
2920 'index': 0
2921 }
2923 mockpid = self.mock_object(self.client, 'get_unique_export_policy_id',
2924 mock.Mock(return_value='fake_policy_id'))
2925 mock_sr = self.mock_object(self.client, 'send_request')
2926 self.client._remove_nfs_export_rules('fake_policy', [0])
2927 mockpid.assert_called_once_with('fake_policy')
2928 mock_sr.assert_called_once_with(
2929 '/protocols/nfs/export-policies/fake_policy_id/rules/0', 'delete',
2930 body=fake_body)
2932 def test_modify_cifs_share_access(self):
2933 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
2934 self.mock_object(self.client, 'send_request',
2935 mock.Mock(return_value=return_uuid))
2936 self.client.modify_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME,
2937 'read')
2938 fake_user = 'fake_user'
2939 FAKE_CIFS_USER_GROUP_TYPE = 'windows'
2940 fake_uuid = 'fake_uuid'
2941 fake_share = fake.SHARE_NAME
2942 query = {'name': 'fake_share'}
2943 body = {'permission': 'read'}
2945 self.client.send_request.assert_has_calls([
2946 mock.call('/protocols/cifs/shares', 'get', query=query),
2947 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake_share}'
2948 f'/acls/{fake_user}/{FAKE_CIFS_USER_GROUP_TYPE}',
2949 'patch', body=body)])
2951 def test_add_cifs_share_access(self):
2952 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
2953 self.mock_object(self.client, 'send_request',
2954 mock.Mock(return_value=return_uuid))
2955 self.client.add_cifs_share_access(fake.SHARE_NAME,
2956 fake.USER_NAME, 'read')
2957 fake_uuid = "fake_uuid"
2958 query = {'name': 'fake_share'}
2959 body = {'permission': 'read',
2960 'user_or_group': 'fake_user'}
2961 self.client.send_request.assert_has_calls([
2962 mock.call('/protocols/cifs/shares', 'get', query=query),
2963 mock.call(f'/protocols/cifs/shares/{fake_uuid}/{fake.SHARE_NAME}'
2964 '/acls', 'post', body=body)])
2966 def test_get_cifs_share_access_rules_empty(self):
2967 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
2968 self.mock_object(self.client, 'send_request',
2969 mock.Mock(return_value=return_uuid))
2971 def test_get_cifs_share_access_rules_not_empty(self):
2972 return_uuid = fake.GENERIC_EXPORT_POLICY_RESPONSE_AND_VOLUMES
2973 self.mock_object(self.client, 'send_request',
2974 mock.Mock(return_value=return_uuid))
2976 rules = {}
2978 fake_results = fake.FAKE_CIFS_RECORDS
2980 for record in fake_results['records']:
2981 user_or_group = record['user_or_group']
2982 permission = record['permission']
2983 rules[user_or_group] = permission
2985 def test_mount_volume_with_junction_path(self):
2986 volume_name = fake.SHARE_NAME
2987 junction_path = '/fake_path'
2988 volume = fake.VOLUME
2990 self.mock_object(self.client, '_get_volume_by_args',
2991 mock.Mock(return_value=volume))
2992 self.mock_object(self.client, 'send_request')
2994 self.client.mount_volume(volume_name, junction_path=junction_path)
2996 uuid = volume['uuid']
2998 body = {
2999 'nas.path': junction_path
3000 }
3002 self.client.send_request.assert_called_once_with(
3003 f'/storage/volumes/{uuid}', 'patch', body=body)
3005 def test_mount_volume_with_volume_name(self):
3006 volume_name = fake.SHARE_NAME
3007 volume = fake.VOLUME
3009 self.mock_object(self.client, '_get_volume_by_args',
3010 mock.Mock(return_value=volume))
3011 self.mock_object(self.client, 'send_request')
3013 self.client.mount_volume(volume_name)
3015 uuid = volume['uuid']
3017 body = {
3018 'nas.path': '/%s' % volume_name
3019 }
3021 self.client.send_request.assert_called_once_with(
3022 f'/storage/volumes/{uuid}', 'patch', body=body)
3024 def test_set_volume_name(self):
3025 volume_name = fake.SHARE_NAME
3026 new_volume_name = 'fake_name'
3028 volume = fake.VOLUME
3030 self.mock_object(self.client, '_get_volume_by_args',
3031 mock.Mock(return_value=volume))
3032 self.mock_object(self.client, 'send_request')
3034 self.client.set_volume_name(volume_name, new_volume_name)
3036 uuid = volume['uuid']
3038 body = {
3039 'name': new_volume_name
3040 }
3042 self.client.send_request.assert_called_once_with(
3043 f'/storage/volumes/{uuid}', 'patch', body=body)
3045 def test_get_job(self):
3046 mock_sr = self.mock_object(self.client, 'send_request')
3047 self.client.get_job('fake_job_uuid')
3048 mock_sr.assert_called_once_with('/cluster/jobs/fake_job_uuid',
3049 'get', enable_tunneling=False)
3051 @ddt.data(netapp_api.EREST_VSERVER_NOT_FOUND, 'fake')
3052 def test_vserver_exists_exception(self, er):
3053 self.mock_object(self.client, 'send_request',
3054 mock.Mock(side_effect=self._mock_api_error(code=er)))
3055 if er == netapp_api.EREST_VSERVER_NOT_FOUND:
3056 result = self.client.vserver_exists(fake.VSERVER_NAME)
3057 self.assertFalse(result)
3058 else:
3059 self.assertRaises(netapp_api.api.NaApiError,
3060 self.client.vserver_exists,
3061 fake.VSERVER_NAME)
3063 def test__get_aggregate_disk_types(self):
3064 response = fake.FAKE_DISK_TYPE_RESPONSE
3065 aggr = fake.SHARE_AGGREGATE_NAME
3066 mock_sr = self.mock_object(self.client, 'send_request',
3067 mock.Mock(return_value=response))
3068 query = {
3069 'aggregates.name': aggr,
3070 'fields': 'effective_type'
3071 }
3072 expected = {'fakedisk'}
3074 result = self.client._get_aggregate_disk_types(aggr)
3076 mock_sr.assert_called_once_with('/storage/disks', 'get', query=query)
3077 self.assertEqual(expected, result)
3079 def test__get_aggregate_disk_types_exception(self):
3080 aggr = fake.SHARE_AGGREGATE_NAME
3081 self.mock_object(self.client, 'send_request',
3082 mock.Mock(side_effect=self._mock_api_error()))
3083 result = self.client._get_aggregate_disk_types(aggr)
3084 self.assertEqual(set(), result)
3086 def test_create_nfs_export_policy_exception(self):
3087 self.mock_object(self.client, 'send_request',
3088 mock.Mock(side_effect=self._mock_api_error()))
3089 self.assertRaises(netapp_api.api.NaApiError,
3090 self.client.create_nfs_export_policy,
3091 fake.EXPORT_POLICY_NAME)
3093 @ddt.data(True, False)
3094 def test__get_create_volume_body(self, thin_provisioned):
3095 expected = {
3096 'type': 'fake_type',
3097 'guarantee.type': ('none' if thin_provisioned else 'volume'),
3098 'nas.path': '/%s' % fake.SHARE_MOUNT_POINT,
3099 'snapshot_policy.name': fake.SNAPSHOT_POLICY_NAME,
3100 'language': 'fake_language',
3101 'space.snapshot.reserve_percent': 'fake_percent',
3102 'qos.policy.name': fake.QOS_POLICY_GROUP_NAME,
3103 'svm.name': 'fake_vserver',
3104 'encryption.enabled': 'true',
3105 'snaplock.type': 'compliance',
3106 }
3108 self.mock_object(self.client.connection, 'get_vserver',
3109 mock.Mock(return_value='fake_vserver'))
3110 res = self.client._get_create_volume_body(fake.VOLUME_NAMES[0],
3111 thin_provisioned,
3112 fake.SNAPSHOT_POLICY_NAME,
3113 'fake_language',
3114 'fake_percent',
3115 'fake_type',
3116 fake.QOS_POLICY_GROUP_NAME,
3117 True,
3118 fake.QOS_POLICY_GROUP_NAME,
3119 fake.SHARE_MOUNT_POINT,
3120 "compliance")
3121 self.assertEqual(expected, res)
3123 def test_get_job_state(self):
3124 expected = 'success'
3125 query = {
3126 'uuid': 'fake_uuid',
3127 'fields': 'state'
3128 }
3129 response = {
3130 'records': [fake.JOB_SUCCESSFUL_REST]
3131 }
3132 mock_sr = self.mock_object(self.client, 'send_request',
3133 mock.Mock(return_value=response))
3134 self.mock_object(self.client, '_has_records',
3135 mock.Mock(return_value=True))
3136 result = self.client.get_job_state('fake_uuid')
3137 mock_sr.assert_called_once_with('/cluster/jobs/', 'get', query=query,
3138 enable_tunneling=False)
3139 self.assertEqual(expected, result)
3141 def test_get_job_state_not_found(self):
3142 self.mock_object(self.client, 'send_request')
3143 self.mock_object(self.client, '_has_records',
3144 mock.Mock(return_value=False))
3145 self.assertRaises(exception.NetAppException,
3146 self.client.get_job_state,
3147 'fake_uuid')
3149 def test_update_volume_snapshot_policy(self):
3150 return_uuid = {
3151 'uuid': 'fake_uuid'
3152 }
3153 mock_get_vol = self.mock_object(self.client, '_get_volume_by_args',
3154 mock.Mock(return_value=return_uuid))
3155 mock_sr = self.mock_object(self.client, 'send_request')
3157 self.client.update_volume_snapshot_policy('fake_volume_name',
3158 fake.SNAPSHOT_POLICY_NAME)
3159 body = {
3160 'snapshot_policy.name': fake.SNAPSHOT_POLICY_NAME
3161 }
3162 mock_sr.assert_called_once_with('/storage/volumes/fake_uuid',
3163 'patch', body=body)
3164 mock_get_vol.assert_called_once_with(vol_name='fake_volume_name')
3166 @ddt.data(True, False)
3167 def test_update_volume_efficiency_attributes(self, status):
3168 response = {
3169 'dedupe': not status,
3170 'compression': not status
3171 }
3172 self.mock_object(self.client, 'get_volume_efficiency_status',
3173 mock.Mock(return_value=response))
3174 en_dedupe = self.mock_object(self.client, 'enable_dedupe_async')
3175 dis_dedupe = self.mock_object(self.client, 'disable_dedupe_async')
3176 en_comp = self.mock_object(self.client, 'enable_compression_async')
3177 dis_comp = self.mock_object(self.client, 'disable_compression_async')
3178 apply_efficiency_policy = self.mock_object(
3179 self.client, 'apply_volume_efficiency_policy'
3180 )
3182 self.client.update_volume_efficiency_attributes(
3183 fake.VOLUME_NAMES[0],
3184 status, status,
3185 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME)
3187 if status:
3188 en_dedupe.assert_called_once_with(fake.VOLUME_NAMES[0])
3189 en_comp.assert_called_once_with(fake.VOLUME_NAMES[0])
3190 apply_efficiency_policy.assert_called_once_with(
3191 fake.VOLUME_NAMES[0],
3192 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME
3193 )
3194 else:
3195 dis_dedupe.assert_called_once_with(fake.VOLUME_NAMES[0])
3196 dis_comp.assert_called_once_with(fake.VOLUME_NAMES[0])
3197 apply_efficiency_policy.assert_called_once_with(
3198 fake.VOLUME_NAMES[0],
3199 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME
3200 )
3202 def test_trigger_volume_move_cutover(self):
3203 query = {
3204 'name': fake.VOLUME_NAMES[0]
3205 }
3206 body = {
3207 'movement.state': 'cutover'
3208 }
3209 self.mock_object(self.client, 'send_request')
3210 self.client.trigger_volume_move_cutover(
3211 fake.VOLUME_NAMES[0], fake.VSERVER_NAME)
3212 self.client.send_request.assert_called_once_with(
3213 '/storage/volumes/', 'patch', query=query,
3214 body=body)
3216 def test_abort_volume_move(self):
3217 return_uuid = {
3218 'uuid': 'fake_uuid'
3219 }
3220 mock_get_vol = self.mock_object(self.client, '_get_volume_by_args',
3221 mock.Mock(return_value=return_uuid))
3222 mock_sr = self.mock_object(self.client, 'send_request')
3224 self.client.abort_volume_move('fake_volume_name', 'fake_vserver')
3226 mock_sr.assert_called_once_with('/storage/volumes/fake_uuid', 'patch')
3227 mock_get_vol.assert_called_once_with(vol_name='fake_volume_name')
3229 def test_get_volume_move_status(self):
3230 """Gets the current state of a volume move operation."""
3232 return_sr = fake.FAKE_VOL_MOVE_STATUS
3234 fields = 'movement.percent_complete,movement.state'
3236 query = {
3237 'name': 'fake_name',
3238 'svm.name': 'fake_svm',
3239 'fields': fields
3240 }
3242 mock_sr = self.mock_object(self.client, 'send_request',
3243 mock.Mock(return_value=return_sr))
3245 result = self.client.get_volume_move_status('fake_name', 'fake_svm')
3247 mock_sr.assert_called_once_with('/storage/volumes/',
3248 'get', query=query)
3250 volume_move_info = return_sr.get('records')[0]
3251 volume_movement = volume_move_info['movement']
3253 expected = {
3254 'percent-complete': volume_movement['percent_complete'],
3255 'estimated-completion-time': '',
3256 'state': volume_movement['state'],
3257 'details': '',
3258 'cutover-action': '',
3259 'phase': volume_movement['state'],
3260 }
3262 self.assertEqual(expected, result)
3264 def test_list_snapmirror_snapshots(self):
3265 fake_response = fake.SNAPSHOTS_REST_RESPONSE
3266 api_response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
3267 mock_volume = self.mock_object(self.client,
3268 '_get_volume_by_args',
3269 mock.Mock(return_value=api_response))
3270 mock_request = self.mock_object(self.client, 'send_request',
3271 mock.Mock(return_value=fake_response))
3272 self.client.list_snapmirror_snapshots(fake.VOLUME_NAMES[0])
3274 query = {
3275 'owners': 'snapmirror_dependent',
3276 }
3277 mock_request.assert_called_once_with(
3278 '/storage/volumes/fake_uuid/snapshots/',
3279 'get', query=query)
3280 mock_volume.assert_called_once_with(vol_name=fake.VOLUME_NAMES[0])
3282 @ddt.data({'policy': 'fake_policy'},
3283 {'policy': None})
3284 @ddt.unpack
3285 def test_create_snapmirror_vol(self, policy):
3286 api_responses = [
3287 {
3288 "job": {
3289 "uuid": fake.FAKE_UUID,
3290 },
3291 },
3292 ]
3293 self.mock_object(self.client, 'send_request',
3294 mock.Mock(side_effect=copy.deepcopy(api_responses)))
3295 self.client.create_snapmirror_vol(
3296 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3297 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME,
3298 relationship_type=netapp_utils.EXTENDED_DATA_PROTECTION_TYPE,
3299 policy=policy)
3301 body = {
3302 'source': {
3303 'path': (fake.SM_SOURCE_VSERVER + ':' +
3304 fake.SM_SOURCE_VOLUME),
3305 },
3306 'destination': {
3307 'path': (fake.SM_DEST_VSERVER + ':' +
3308 fake.SM_DEST_VOLUME)
3309 }
3310 }
3312 if policy:
3313 body['policy.name'] = policy
3315 self.client.send_request.assert_has_calls([
3316 mock.call('/snapmirror/relationships/', 'post', body=body)])
3318 def test_create_snapmirror_vol_already_exists(self):
3319 api_responses = netapp_api.api.NaApiError(
3320 code=netapp_api.EREST_ERELATION_EXISTS)
3321 self.mock_object(self.client, 'send_request',
3322 mock.Mock(side_effect=api_responses))
3324 response = self.client.create_snapmirror_vol(
3325 fake.SM_SOURCE_VSERVER,
3326 fake.SM_SOURCE_VOLUME,
3327 fake.SM_DEST_VSERVER,
3328 fake.SM_DEST_VOLUME,
3329 schedule=None,
3330 policy=None,
3331 relationship_type='data_protection')
3332 self.assertIsNone(response)
3333 self.assertTrue(self.client.send_request.called)
3335 def test_create_snapmirror_vol_error(self):
3336 self.mock_object(
3337 self.client, 'send_request',
3338 mock.Mock(side_effect=netapp_api.api.NaApiError(code=123)))
3340 self.assertRaises(netapp_api.api.NaApiError,
3341 self.client.create_snapmirror_vol,
3342 fake.SM_SOURCE_VSERVER,
3343 fake.SM_SOURCE_VOLUME,
3344 fake.SM_DEST_VSERVER,
3345 fake.SM_DEST_VOLUME,
3346 schedule=None,
3347 policy=None,
3348 relationship_type='data_protection')
3349 self.assertTrue(self.client.send_request.called)
3351 def test__set_snapmirror_state(self):
3353 api_responses = [
3354 fake.SNAPMIRROR_GET_ITER_RESPONSE_REST,
3355 {
3356 "job":
3357 {
3358 "uuid": fake.FAKE_UUID
3359 },
3360 "num_records": 1
3361 }
3362 ]
3364 expected_body = {'state': 'snapmirrored'}
3365 self.mock_object(self.client,
3366 'send_request',
3367 mock.Mock(side_effect=copy.deepcopy(api_responses)))
3369 result = self.client._set_snapmirror_state(
3370 'snapmirrored', None, None,
3371 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3372 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME)
3374 self.client.send_request.assert_has_calls([
3375 mock.call('/snapmirror/relationships/' + fake.FAKE_UUID,
3376 'patch', body=expected_body, wait_on_accepted=True)])
3378 expected = {
3379 'operation-id': None,
3380 'status': None,
3381 'jobid': fake.FAKE_UUID,
3382 'error-code': None,
3383 'error-message': None,
3384 'relationship-uuid': fake.FAKE_UUID
3385 }
3386 self.assertEqual(expected, result)
3388 def test_initialize_snapmirror_vol(self):
3390 expected_job = {
3391 'operation-id': None,
3392 'status': None,
3393 'jobid': fake.FAKE_UUID,
3394 'error-code': None,
3395 'error-message': None,
3396 }
3398 mock_set_snapmirror_state = self.mock_object(
3399 self.client,
3400 '_set_snapmirror_state',
3401 mock.Mock(return_value=expected_job))
3403 result = self.client.initialize_snapmirror_vol(
3404 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3405 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME)
3407 mock_set_snapmirror_state.assert_called_once_with(
3408 'snapmirrored', None, None,
3409 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3410 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME,
3411 wait_result=False)
3413 self.assertEqual(expected_job, result)
3415 def test_modify_snapmirror_vol(self):
3417 expected_job = {
3418 'operation-id': None,
3419 'status': None,
3420 'jobid': fake.FAKE_UUID,
3421 'error-code': None,
3422 'error-message': None,
3423 }
3425 mock_set_snapmirror_state = self.mock_object(
3426 self.client,
3427 '_set_snapmirror_state',
3428 mock.Mock(return_value=expected_job))
3430 result = self.client.modify_snapmirror_vol(
3431 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3432 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME,
3433 None)
3435 mock_set_snapmirror_state.assert_called_once_with(
3436 None, None, None,
3437 fake.SM_SOURCE_VSERVER, fake.SM_SOURCE_VOLUME,
3438 fake.SM_DEST_VSERVER, fake.SM_DEST_VOLUME,
3439 wait_result=False, schedule=None)
3441 self.assertEqual(expected_job, result)
3443 def test__abort_snapmirror(self):
3444 return_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE
3445 mock_get_snap = self.mock_object(self.client, '_get_snapmirrors',
3446 mock.Mock(return_value=return_snp))
3447 return_sr = fake.REST_SIMPLE_RESPONSE
3448 mock_sr = self.mock_object(self.client, 'send_request',
3449 mock.Mock(return_value=return_sr))
3451 self.client._abort_snapmirror(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH)
3453 mock_get_snap.assert_called_once_with(
3454 source_path=fake.SM_SOURCE_PATH,
3455 dest_path=fake.SM_DEST_PATH,
3456 source_vserver=None,
3457 source_volume=None,
3458 dest_vserver=None,
3459 dest_volume=None,
3460 enable_tunneling=None,
3461 list_destinations_only=None)
3463 mock_sr.assert_has_calls([
3464 mock.call(f'/snapmirror/relationships/{return_snp[0]["uuid"]}'
3465 '/transfers/', 'get',
3466 query={'state': 'transferring'}),
3467 mock.call(f'/snapmirror/relationships/{return_snp[0]["uuid"]}'
3468 f'/transfers/{return_sr["records"][0]["uuid"]}',
3469 'patch', body={'state': 'aborted'}),
3470 ])
3472 def test_abort_snapmirror_vol(self):
3473 mock_abort = self.mock_object(self.client, '_abort_snapmirror')
3474 self.client.abort_snapmirror_vol(fake.VSERVER_NAME,
3475 fake.VOLUME_NAMES[0],
3476 fake.VSERVER_NAME_2,
3477 fake.VOLUME_NAMES[1])
3478 mock_abort.assert_called_once_with(source_vserver=fake.VSERVER_NAME,
3479 source_volume=fake.VOLUME_NAMES[0],
3480 dest_vserver=fake.VSERVER_NAME_2,
3481 dest_volume=fake.VOLUME_NAMES[1],
3482 clear_checkpoint=False)
3484 def test_release_snapmirror_vol(self):
3485 mock_sr = self.mock_object(self.client, 'send_request')
3486 return_snp = fake.REST_GET_SNAPMIRRORS_RESPONSE
3487 mock_sd = self.mock_object(self.client, 'get_snapmirror_destinations',
3488 mock.Mock(return_value=return_snp))
3490 self.client.release_snapmirror_vol(fake.VSERVER_NAME,
3491 fake.VOLUME_NAMES[0],
3492 fake.VSERVER_NAME_2,
3493 fake.VOLUME_NAMES[1])
3495 mock_sd.assert_called_once_with(source_vserver=fake.VSERVER_NAME,
3496 source_volume=fake.VOLUME_NAMES[0],
3497 dest_vserver=fake.VSERVER_NAME_2,
3498 dest_volume=fake.VOLUME_NAMES[1],
3499 desired_attributes=['relationship-id'])
3501 uuid = return_snp[0].get("uuid")
3502 query = {"source_only": 'true'}
3503 mock_sr.assert_called_once_with(f'/snapmirror/relationships/{uuid}',
3504 'delete', query=query)
3506 def test_delete_snapmirror_no_records(self):
3507 query_uuid = {}
3508 query_uuid['source.path'] = (fake.SM_SOURCE_VSERVER + ':' +
3509 fake.SM_SOURCE_VOLUME)
3511 query_uuid['destination.path'] = (fake.SM_DEST_VSERVER + ':' +
3512 fake.SM_DEST_VOLUME)
3513 query_uuid['fields'] = 'uuid'
3515 self.mock_object(self.client, 'send_request',
3516 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST))
3517 self.client._delete_snapmirror(fake.SM_SOURCE_VSERVER,
3518 fake.SM_SOURCE_VOLUME,
3519 fake.SM_DEST_VSERVER,
3520 fake.SM_DEST_VOLUME)
3521 self.client.send_request.assert_called_once_with(
3522 '/snapmirror/relationships/', 'get', query=query_uuid)
3524 def test_delete_snapmirror(self):
3525 query_uuid = {}
3526 query_uuid['source.path'] = (fake.SM_SOURCE_VSERVER + ':' +
3527 fake.SM_SOURCE_VOLUME)
3529 query_uuid['destination.path'] = (fake.SM_DEST_VSERVER + ':' +
3530 fake.SM_DEST_VOLUME)
3531 query_uuid['fields'] = 'uuid'
3532 fake_cluster = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST
3533 self.mock_object(self.client, 'send_request',
3534 mock.Mock(return_value=fake_cluster))
3535 self.client._delete_snapmirror(fake.SM_SOURCE_VSERVER,
3536 fake.SM_SOURCE_VOLUME,
3537 fake.SM_DEST_VSERVER,
3538 fake.SM_DEST_VOLUME)
3540 query_delete = {"destination_only": "true"}
3541 snapmirror_uuid = fake_cluster.get('records')[0].get('uuid')
3542 self.client.send_request.assert_has_calls([
3543 mock.call('/snapmirror/relationships/', 'get', query=query_uuid),
3544 mock.call('/snapmirror/relationships/' + snapmirror_uuid, 'delete',
3545 query=query_delete)
3546 ])
3548 def test_get_snapmirror_destinations(self):
3549 mock_get_sm = self.mock_object(self.client, '_get_snapmirrors')
3550 self.client.get_snapmirror_destinations(fake.SM_SOURCE_PATH,
3551 fake.SM_DEST_PATH,
3552 fake.SM_SOURCE_VSERVER,
3553 fake.SM_SOURCE_VOLUME,
3554 fake.SM_DEST_VSERVER,
3555 fake.SM_DEST_VOLUME)
3557 mock_get_sm.assert_called_once_with(
3558 source_path=fake.SM_SOURCE_PATH,
3559 dest_path=fake.SM_DEST_PATH,
3560 source_vserver=fake.SM_SOURCE_VSERVER,
3561 source_volume=fake.SM_SOURCE_VOLUME,
3562 dest_vserver=fake.SM_DEST_VSERVER,
3563 dest_volume=fake.SM_DEST_VOLUME,
3564 enable_tunneling=False,
3565 list_destinations_only=True)
3567 def test_delete_snapmirror_vol(self):
3568 mock_delete = self.mock_object(self.client, '_delete_snapmirror')
3569 self.client.delete_snapmirror_vol(fake.SM_SOURCE_VSERVER,
3570 fake.SM_SOURCE_VOLUME,
3571 fake.SM_DEST_VSERVER,
3572 fake.SM_DEST_VOLUME)
3573 mock_delete.assert_called_once_with(
3574 source_vserver=fake.SM_SOURCE_VSERVER,
3575 dest_vserver=fake.SM_DEST_VSERVER,
3576 source_volume=fake.SM_SOURCE_VOLUME,
3577 dest_volume=fake.SM_DEST_VOLUME)
3579 def test_disable_fpolicy_policy(self):
3580 query = {
3581 'name': fake.VSERVER_NAME,
3582 'fields': 'uuid'
3583 }
3584 response_svm = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
3585 self.client.vserver = fake.VSERVER_NAME
3586 self.mock_object(self.client,
3587 'send_request',
3588 mock.Mock(side_effect=[response_svm, None]))
3590 self.client.disable_fpolicy_policy(fake.FPOLICY_POLICY_NAME)
3592 svm_id = response_svm.get('records')[0]['uuid']
3594 self.client.send_request.assert_has_calls([
3595 mock.call('/svm/svms', 'get', query=query,
3596 enable_tunneling=False),
3597 mock.call(f'/protocols/fpolicy/{svm_id}/policies'
3598 f'/{fake.FPOLICY_POLICY_NAME}', 'patch')
3599 ])
3601 @ddt.data([fake.NO_RECORDS_RESPONSE_REST, None],
3602 [fake.SVMS_LIST_SIMPLE_RESPONSE_REST,
3603 netapp_api.api.NaApiError(code="1000", message="")])
3604 def test_disable_fpolicy_policy_failure(self, side_effect):
3605 self.mock_object(self.client,
3606 'send_request',
3607 mock.Mock(side_effect=side_effect))
3609 self.assertRaises(exception.NetAppException,
3610 self.client.disable_fpolicy_policy,
3611 fake.FPOLICY_POLICY_NAME)
3613 @ddt.data({'qos_policy_group_name': None,
3614 'adaptive_qos_policy_group_name': None},
3615 {'qos_policy_group_name': fake.QOS_POLICY_GROUP_NAME,
3616 'adaptive_qos_policy_group_name': None},
3617 {'qos_policy_group_name': None,
3618 'adaptive_qos_policy_group_name':
3619 fake.ADAPTIVE_QOS_POLICY_GROUP_NAME},
3620 {'mount_point_name': None},
3621 )
3622 @ddt.unpack
3623 def test_create_volume_clone(self, qos_policy_group_name=None,
3624 adaptive_qos_policy_group_name=None,
3625 mount_point_name=None):
3626 self.mock_object(self.client, 'send_request')
3628 if qos_policy_group_name:
3629 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
3630 uuid = volume["uuid"]
3631 self.mock_object(self.client,
3632 '_get_volume_by_args',
3633 mock.Mock(return_value=volume))
3634 self.mock_object(self.client, 'volume_clone_split_start')
3635 self.mock_object(
3636 self.client.connection, 'get_vserver',
3637 mock.Mock(return_value='fake_svm'))
3638 set_qos_adapt_mock = self.mock_object(
3639 self.client,
3640 'set_qos_adaptive_policy_group_for_volume')
3642 self.client.create_volume_clone(
3643 fake.SHARE_NAME,
3644 fake.PARENT_SHARE_NAME,
3645 fake.PARENT_SNAPSHOT_NAME,
3646 mount_point_name=mount_point_name,
3647 qos_policy_group=qos_policy_group_name,
3648 adaptive_qos_policy_group=adaptive_qos_policy_group_name)
3650 body = {
3651 'name': fake.SHARE_NAME,
3652 'clone.parent_volume.name': fake.PARENT_SHARE_NAME,
3653 'clone.parent_snapshot.name': fake.PARENT_SNAPSHOT_NAME,
3654 'nas.path': '/%s' % (mount_point_name or fake.SHARE_NAME),
3655 'clone.is_flexclone': 'true',
3656 'svm.name': 'fake_svm',
3657 }
3659 if adaptive_qos_policy_group_name is not None:
3660 set_qos_adapt_mock.assert_called_once_with(
3661 fake.SHARE_NAME, fake.ADAPTIVE_QOS_POLICY_GROUP_NAME
3662 )
3664 if qos_policy_group_name:
3665 self.client._get_volume_by_args.assert_called_once_with(
3666 vol_name=fake.SHARE_NAME)
3667 self.client.send_request.assert_has_calls([
3668 mock.call('/storage/volumes', 'post', body=body),
3669 mock.call(f'/storage/volumes/{uuid}', 'patch',
3670 body={'qos.policy.name': qos_policy_group_name})
3671 ])
3672 else:
3673 self.client.send_request.assert_called_once_with(
3674 '/storage/volumes', 'post', body=body)
3675 self.assertFalse(self.client.volume_clone_split_start.called)
3677 @ddt.data(True, False)
3678 def test_create_volume_split(self, split):
3679 self.mock_object(self.client, 'send_request')
3680 self.mock_object(self.client, 'volume_clone_split_start')
3681 self.mock_object(
3682 self.client.connection, 'get_vserver',
3683 mock.Mock(return_value='fake_svm'))
3684 body = {
3685 'name': fake.SHARE_NAME,
3686 'clone.parent_volume.name': fake.PARENT_SHARE_NAME,
3687 'clone.parent_snapshot.name': fake.PARENT_SNAPSHOT_NAME,
3688 'nas.path': '/%s' % fake.SHARE_NAME,
3689 'clone.is_flexclone': 'true',
3690 'svm.name': 'fake_svm',
3691 }
3693 self.client.create_volume_clone(
3694 fake.SHARE_NAME,
3695 fake.PARENT_SHARE_NAME,
3696 fake.PARENT_SNAPSHOT_NAME,
3697 split=split)
3699 self.assertFalse(self.client.volume_clone_split_start.called)
3701 self.client.send_request.assert_called_once_with(
3702 '/storage/volumes', 'post', body=body)
3704 def test_quiesce_snapmirror_vol(self):
3705 mock__quiesce_snapmirror = self.mock_object(
3706 self.client, '_quiesce_snapmirror')
3708 self.client.quiesce_snapmirror_vol(fake.SM_SOURCE_VSERVER,
3709 fake.SM_SOURCE_VOLUME,
3710 fake.SM_DEST_VSERVER,
3711 fake.SM_DEST_VOLUME)
3713 mock__quiesce_snapmirror.assert_called_once_with(
3714 source_vserver=fake.SM_SOURCE_VSERVER,
3715 source_volume=fake.SM_SOURCE_VOLUME,
3716 dest_vserver=fake.SM_DEST_VSERVER,
3717 dest_volume=fake.SM_DEST_VOLUME)
3719 def test__quiesce_snapmirror(self):
3720 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE
3721 fake_uuid = fake_snapmirror[0]['uuid']
3722 fake_body = {'state': 'paused'}
3724 self.mock_object(self.client, 'send_request')
3726 mock_get_snap = self.mock_object(
3727 self.client, '_get_snapmirrors',
3728 mock.Mock(return_value=fake_snapmirror))
3730 self.client._quiesce_snapmirror()
3732 mock_get_snap.assert_called_once()
3733 self.client.send_request.assert_called_once_with(
3734 f'/snapmirror/relationships/{fake_uuid}', 'patch', body=fake_body)
3736 def test_break_snapmirror_vol(self):
3738 self.mock_object(self.client, '_break_snapmirror')
3740 self.client.break_snapmirror_vol(source_vserver=fake.SM_SOURCE_VSERVER,
3741 source_volume=fake.SM_SOURCE_VOLUME,
3742 dest_vserver=fake.SM_DEST_VSERVER,
3743 dest_volume=fake.SM_DEST_VOLUME)
3745 self.client._break_snapmirror.assert_called_once_with(
3746 source_vserver=fake.SM_SOURCE_VSERVER,
3747 source_volume=fake.SM_SOURCE_VOLUME,
3748 dest_vserver=fake.SM_DEST_VSERVER,
3749 dest_volume=fake.SM_DEST_VOLUME)
3751 def test__break_snapmirror(self):
3752 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE
3753 fake_uuid = fake_snapmirror[0]['uuid']
3754 fake_body = {'state': 'broken_off'}
3756 self.mock_object(self.client, 'send_request')
3758 mock_get_snap = self.mock_object(
3759 self.client, '_get_snapmirrors',
3760 mock.Mock(return_value=fake_snapmirror))
3762 self.client._break_snapmirror()
3764 mock_get_snap.assert_called_once()
3765 self.client.send_request.assert_called_once_with(
3766 f'/snapmirror/relationships/{fake_uuid}', 'patch', body=fake_body)
3768 def test_resume_snapmirror_vol(self):
3769 mock = self.mock_object(self.client, '_resume_snapmirror')
3770 self.client.resume_snapmirror_vol(fake.SM_SOURCE_VSERVER,
3771 fake.SM_SOURCE_VOLUME,
3772 fake.SM_DEST_VSERVER,
3773 fake.SM_DEST_VOLUME)
3774 mock.assert_called_once_with(
3775 source_vserver=fake.SM_SOURCE_VSERVER,
3776 dest_vserver=fake.SM_DEST_VSERVER,
3777 source_volume=fake.SM_SOURCE_VOLUME,
3778 dest_volume=fake.SM_DEST_VOLUME)
3780 def test_resync_snapmirror_vol(self):
3781 mock = self.mock_object(self.client, '_resync_snapmirror')
3782 self.client.resync_snapmirror_vol(fake.SM_SOURCE_VSERVER,
3783 fake.SM_SOURCE_VOLUME,
3784 fake.SM_DEST_VSERVER,
3785 fake.SM_DEST_VOLUME)
3786 mock.assert_called_once_with(
3787 source_vserver=fake.SM_SOURCE_VSERVER,
3788 dest_vserver=fake.SM_DEST_VSERVER,
3789 source_volume=fake.SM_SOURCE_VOLUME,
3790 dest_volume=fake.SM_DEST_VOLUME)
3792 @ddt.data('async', 'sync')
3793 def test__resume_snapmirror(self, snapmirror_policy):
3794 api_response = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE)
3795 api_response[0]['policy-type'] = snapmirror_policy
3796 mock_snapmirror = self.mock_object(
3797 self.client, '_get_snapmirrors',
3798 mock.Mock(return_value=api_response))
3799 mock_request = self.mock_object(self.client, 'send_request')
3801 snapmirror_uuid = fake.FAKE_UUID
3803 body_resync = {}
3804 if snapmirror_policy == 'async':
3805 body_resync['state'] = 'snapmirrored'
3806 elif snapmirror_policy == 'sync': 3806 ↛ 3809line 3806 didn't jump to line 3809 because the condition on line 3806 was always true
3807 body_resync['state'] = 'in_sync'
3809 self.client._resume_snapmirror(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH)
3811 mock_request.assert_called_once_with('/snapmirror/relationships/' +
3812 snapmirror_uuid, 'patch',
3813 body=body_resync,
3814 wait_on_accepted=False)
3816 mock_snapmirror.assert_called_once_with(
3817 source_path=fake.SM_SOURCE_PATH,
3818 dest_path=fake.SM_DEST_PATH,
3819 source_vserver=None,
3820 source_volume=None,
3821 dest_vserver=None,
3822 dest_volume=None,
3823 enable_tunneling=None,
3824 list_destinations_only=None)
3826 def test__resync_snapmirror(self):
3827 mock = self.mock_object(self.client, '_resume_snapmirror')
3828 self.client._resume_snapmirror(fake.SM_SOURCE_PATH,
3829 fake.SM_DEST_PATH)
3830 mock.assert_called_once_with(fake.SM_SOURCE_PATH, fake.SM_DEST_PATH)
3832 def test_add_nfs_export_rule(self):
3834 mock_get_nfs_export_rule_indices = self.mock_object(
3835 self.client, '_get_nfs_export_rule_indices',
3836 mock.Mock(return_value=[]))
3837 mock_add_nfs_export_rule = self.mock_object(
3838 self.client, '_add_nfs_export_rule')
3839 mock_update_nfs_export_rule = self.mock_object(
3840 self.client, '_update_nfs_export_rule')
3841 auth_methods = ['sys']
3843 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
3844 fake.IP_ADDRESS,
3845 False,
3846 auth_methods)
3848 mock_get_nfs_export_rule_indices.assert_called_once_with(
3849 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
3850 mock_add_nfs_export_rule.assert_called_once_with(
3851 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, auth_methods)
3852 self.assertFalse(mock_update_nfs_export_rule.called)
3854 def test_set_qos_policy_group_for_volume(self):
3855 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
3856 mock_get_volume = self.mock_object(
3857 self.client, '_get_volume_by_args',
3858 mock.Mock(return_value=volume))
3860 mock_send_request = self.mock_object(
3861 self.client, 'send_request')
3863 self.client.set_qos_policy_group_for_volume(
3864 volume['name'], fake.QOS_POLICY_GROUP_NAME)
3866 mock_get_volume.assert_called_once_with(vol_name=volume['name'])
3868 body = {'qos.policy.name': fake.QOS_POLICY_GROUP_NAME}
3869 mock_send_request.assert_called_once_with(
3870 f'/storage/volumes/{volume["uuid"]}', 'patch', body=body)
3872 def test__update_snapmirror(self):
3873 api_response = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE)
3874 mock_snapmirror = self.mock_object(
3875 self.client, '_get_snapmirrors',
3876 mock.Mock(return_value=api_response))
3877 mock_sr = self.mock_object(self.client, 'send_request')
3878 self.client._update_snapmirror(fake.SM_SOURCE_PATH,
3879 fake.SM_DEST_PATH,
3880 fake.SM_SOURCE_VSERVER,
3881 fake.SM_DEST_VSERVER,
3882 fake.SM_SOURCE_VOLUME,
3883 fake.SM_DEST_VOLUME)
3884 mock_sr.assert_called_once()
3885 mock_snapmirror.assert_called_once_with(
3886 source_path=fake.SM_SOURCE_PATH,
3887 dest_path=fake.SM_DEST_PATH,
3888 source_vserver=fake.SM_SOURCE_VSERVER,
3889 source_volume=fake.SM_SOURCE_VOLUME,
3890 dest_vserver=fake.SM_DEST_VSERVER,
3891 dest_volume=fake.SM_DEST_VOLUME,
3892 enable_tunneling=None,
3893 list_destinations_only=None)
3895 def test_get_cluster_name(self):
3896 """Get all available cluster nodes."""
3898 return_value = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST
3900 self.mock_object(self.client, 'send_request',
3901 mock.Mock(return_value=return_value))
3902 test_result = self.client.get_cluster_name()
3904 self.client.send_request.assert_called_once_with(
3905 '/cluster', 'get', enable_tunneling=False
3906 )
3908 expected_result = return_value.get('name')
3910 self.assertEqual(test_result, expected_result)
3912 @ddt.data(True, False)
3913 def test_check_volume_clone_split_completed(self, clone):
3914 mock__get_volume_by_args = self.mock_object(
3915 self.client, '_get_volume_by_args',
3916 mock.Mock(return_value={'clone': {'is_flexclone': clone}}))
3918 res = self.client.check_volume_clone_split_completed(
3919 fake.VOLUME_NAMES[0])
3921 mock__get_volume_by_args.assert_called_once_with(
3922 vol_name=fake.VOLUME_NAMES[0], fields='clone.is_flexclone')
3923 self.assertEqual(not clone, res)
3925 def test_rehost_volume(self):
3926 self.mock_object(self.client, 'send_request')
3927 self.client.rehost_volume("fake_vol", "fake_svm", "fake_svm_2")
3928 body = {
3929 "vserver": "fake_svm",
3930 "volume": "fake_vol",
3931 "destination_vserver": "fake_svm_2"
3932 }
3933 self.client.send_request.assert_called_once_with(
3934 "/private/cli/volume/rehost", 'post', body=body)
3936 def test_get_net_options(self):
3938 res = self.client.get_net_options()
3940 self.assertTrue(res['ipv6-enabled'])
3942 def test_set_qos_adaptive_policy_group_for_volume(self):
3943 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
3944 mock_get_volume = self.mock_object(
3945 self.client, '_get_volume_by_args',
3946 mock.Mock(return_value=volume))
3948 mock_send_request = self.mock_object(
3949 self.client, 'send_request')
3951 self.client.set_qos_adaptive_policy_group_for_volume(
3952 volume['name'], fake.QOS_POLICY_GROUP_NAME)
3954 mock_get_volume.assert_called_once_with(vol_name=volume['name'])
3956 body = {'qos.policy.name': fake.QOS_POLICY_GROUP_NAME}
3957 mock_send_request.assert_called_once_with(
3958 f'/storage/volumes/{volume["uuid"]}', 'patch', body=body)
3960 def test__list_vservers(self):
3961 api_response = fake.VSERVER_DATA_LIST_RESPONSE_REST
3962 self.mock_object(self.client,
3963 'send_request',
3964 mock.Mock(return_value=api_response))
3965 result = self.client._list_vservers()
3966 query = {
3967 'fields': 'name',
3968 }
3969 self.client.send_request.assert_has_calls([
3970 mock.call('/svm/svms', 'get', query=query,
3971 enable_tunneling=False)])
3972 self.assertListEqual(
3973 [fake.VSERVER_NAME, fake.VSERVER_NAME_2], result)
3975 def test_list_vservers_not_found(self):
3976 api_response = fake.NO_RECORDS_RESPONSE_REST
3977 self.mock_object(self.client,
3978 'send_request',
3979 mock.Mock(return_value=api_response))
3980 result = self.client._list_vservers()
3981 self.assertListEqual([], result)
3983 def test_get_ems_log_destination_vserver(self):
3984 mock_list_vservers = self.mock_object(
3985 self.client,
3986 '_list_vservers',
3987 mock.Mock(return_value=[fake.VSERVER_NAME]))
3988 result = self.client._get_ems_log_destination_vserver()
3989 mock_list_vservers.assert_called_once_with()
3990 self.assertEqual(fake.VSERVER_NAME, result)
3992 def test_get_ems_log_destination_vserver_not_found(self):
3993 mock_list_vservers = self.mock_object(
3994 self.client,
3995 '_list_vservers',
3996 mock.Mock(return_value=[]))
3998 self.assertRaises(exception.NotFound,
3999 self.client._get_ems_log_destination_vserver)
4001 mock_list_vservers.assert_called_once_with()
4003 def test_send_ems_log_message(self):
4005 message_dict = {
4006 'computer-name': '25-dev-vm',
4007 'event-source': 'Cinder driver NetApp_iSCSI_Cluster_direct',
4008 'app-version': '20.1.0.dev|vendor|Linux-5.4.0-120-generic-x86_64',
4009 'category': 'provisioning',
4010 'log-level': '5',
4011 'auto-support': 'false',
4012 'event-id': '1',
4013 'event-description':
4014 '{"pools": {"vserver": "vserver_name",'
4015 + '"aggregates": [], "flexvols": ["flexvol_01"]}}'
4016 }
4018 body = {
4019 'computer_name': message_dict['computer-name'],
4020 'event_source': message_dict['event-source'],
4021 'app_version': message_dict['app-version'],
4022 'category': message_dict['category'],
4023 'severity': 'notice',
4024 'autosupport_required': message_dict['auto-support'] == 'true',
4025 'event_id': message_dict['event-id'],
4026 'event_description': message_dict['event-description'],
4027 }
4029 self.mock_object(self.client, '_get_ems_log_destination_vserver',
4030 mock.Mock(return_value='vserver_name'))
4031 self.mock_object(self.client, 'send_request')
4033 self.client.send_ems_log_message(message_dict)
4035 self.client.send_request.assert_called_once_with(
4036 '/support/ems/application-logs', 'post', body=body)
4038 @ddt.data('cp_phase_times', 'domain_busy')
4039 def test_get_performance_counter_info(self, counter_name):
4041 response1 = fake.PERF_COUNTER_LIST_INFO_WAFL_RESPONSE_REST
4042 response2 = fake.PERF_COUNTER_TABLE_ROWS_WAFL
4044 object_name = 'wafl'
4046 mock_send_request = self.mock_object(
4047 self.client, 'send_request',
4048 mock.Mock(side_effect=[response1, response2]))
4050 result = self.client.get_performance_counter_info(object_name,
4051 counter_name)
4053 expected = {
4054 'name': 'cp_phase_times',
4055 'base-counter': 'total_cp_msecs',
4056 'labels': fake.PERF_COUNTER_TOTAL_CP_MSECS_LABELS_RESULT,
4057 }
4059 query1 = {
4060 'counter_schemas.name': counter_name,
4061 'fields': 'counter_schemas.*'
4062 }
4064 query2 = {
4065 'counters.name': counter_name,
4066 'fields': 'counters.*'
4067 }
4069 if counter_name == 'domain_busy':
4070 expected['name'] = 'domain_busy'
4071 expected['labels'] = (
4072 fake.PERF_COUNTER_TOTAL_CP_MSECS_LABELS_REST)
4073 query1['counter_schemas.name'] = 'domain_busy_percent'
4074 query2['counters.name'] = 'domain_busy_percent'
4076 self.assertEqual(expected, result)
4078 mock_send_request.assert_has_calls([
4079 mock.call(f'/cluster/counter/tables/{object_name}',
4080 'get', query=query1),
4081 mock.call(f'/cluster/counter/tables/{object_name}/rows',
4082 'get', query=query2, enable_tunneling=False),
4083 ])
4085 def test_get_performance_counter_info_not_found_rows(self):
4086 response1 = fake.PERF_COUNTER_LIST_INFO_WAFL_RESPONSE_REST
4087 response2 = fake.NO_RECORDS_RESPONSE_REST
4089 object_name = 'wafl'
4090 counter_name = 'cp_phase_times'
4092 self.mock_object(
4093 self.client, 'send_request',
4094 mock.Mock(side_effect=[response1, response2]))
4096 result = self.client.get_performance_counter_info(object_name,
4097 counter_name)
4099 expected = {
4100 'name': 'cp_phase_times',
4101 'base-counter': 'total_cp_msecs',
4102 'labels': [],
4103 }
4104 self.assertEqual(expected, result)
4106 def test_get_performance_instance_uuids(self):
4107 response = fake.PERF_COUNTER_TABLE_ROWS_WAFL
4109 mock_send_request = self.mock_object(
4110 self.client, 'send_request',
4111 mock.Mock(return_value=response))
4113 object_name = 'wafl'
4114 result = self.client.get_performance_instance_uuids(
4115 object_name, fake.NODE_NAME)
4117 expected = [fake.NODE_NAME + ':wafl']
4118 self.assertEqual(expected, result)
4120 query = {
4121 'id': fake.NODE_NAME + ':*',
4122 }
4123 mock_send_request.assert_called_once_with(
4124 f'/cluster/counter/tables/{object_name}/rows',
4125 'get', query=query, enable_tunneling=False)
4127 def test_get_performance_counters(self):
4128 response = fake.PERF_GET_INSTANCES_PROCESSOR_RESPONSE_REST
4130 mock_send_request = self.mock_object(
4131 self.client, 'send_request',
4132 mock.Mock(return_value=response))
4134 instance_uuids = [
4135 fake.NODE_NAME + ':processor0',
4136 fake.NODE_NAME + ':processor1',
4137 ]
4138 object_name = 'processor'
4139 counter_names = ['domain_busy', 'processor_elapsed_time']
4140 rest_counter_names = ['domain_busy_percent', 'elapsed_time']
4141 result = self.client.get_performance_counters(object_name,
4142 instance_uuids,
4143 counter_names)
4145 expected = fake.PERF_COUNTERS_PROCESSOR_EXPECTED
4146 self.assertEqual(expected, result)
4148 query = {
4149 'id': '|'.join(instance_uuids),
4150 'counters.name': '|'.join(rest_counter_names),
4151 'fields': 'id,counter_table.name,counters.*',
4152 }
4154 mock_send_request.assert_called_once_with(
4155 f'/cluster/counter/tables/{object_name}/rows',
4156 'get', query=query)
4158 def test__get_deleted_nfs_export_policies(self):
4160 api_response = fake.DELETED_EXPORT_POLICY_GET_ITER_RESPONSE_REST
4161 self.mock_object(self.client,
4162 'send_request',
4163 mock.Mock(return_value=api_response))
4165 result = self.client._get_deleted_nfs_export_policies()
4167 query = {
4168 'name': 'deleted_manila_*',
4169 'fields': 'name,svm.name',
4170 }
4172 self.assertSequenceEqual(fake.DELETED_EXPORT_POLICIES, result)
4173 self.client.send_request.assert_has_calls([
4174 mock.call('/protocols/nfs/export-policies',
4175 'get', query=query)])
4177 def test_prune_deleted_nfs_export_policies(self):
4178 self.mock_object(self.client, '_get_deleted_nfs_export_policies',
4179 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
4180 self.mock_object(self.client, 'delete_nfs_export_policy')
4182 self.client.prune_deleted_nfs_export_policies()
4184 self.assertTrue(self.client.delete_nfs_export_policy.called)
4186 self.client.delete_nfs_export_policy.assert_has_calls([
4187 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME][0]),
4188 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME][1]),
4189 mock.call(fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME_2][0]),
4190 ])
4192 def test_prune_deleted_nfs_export_policies_api_error(self):
4193 self.mock_object(self.client,
4194 '_get_deleted_nfs_export_policies',
4195 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
4196 self.mock_object(self.client,
4197 'delete_nfs_export_policy',
4198 self._mock_api_error())
4200 self.client.prune_deleted_nfs_export_policies()
4202 def test__get_security_key_manager_nve_support_enabled(self):
4203 api_response = fake.SECUTITY_KEY_MANAGER_SUPPORT_RESPONSE_TRUE_REST
4204 self.mock_object(self.client,
4205 'send_request',
4206 mock.Mock(return_value=api_response))
4208 result = self.client._get_security_key_manager_nve_support()
4210 self.assertTrue(result)
4212 query = {'fields': 'volume_encryption.*'}
4213 self.client.send_request.assert_has_calls([
4214 mock.call('/security/key-managers', 'get', query=query)])
4216 def test__get_security_key_manager_nve_support_disabled(self):
4217 api_response = fake.SECUTITY_KEY_MANAGER_SUPPORT_RESPONSE_FALSE_REST
4218 self.mock_object(self.client,
4219 'send_request',
4220 mock.Mock(return_value=api_response))
4222 result = self.client._get_security_key_manager_nve_support()
4224 self.assertFalse(result)
4226 query = {'fields': 'volume_encryption.*'}
4227 self.client.send_request.assert_has_calls([
4228 mock.call('/security/key-managers', 'get', query=query)])
4230 def test__get_security_key_manager_nve_support_no_records(self):
4231 self.mock_object(self.client,
4232 'send_request',
4233 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST))
4235 result = self.client._get_security_key_manager_nve_support()
4237 self.assertFalse(result)
4239 query = {'fields': 'volume_encryption.*'}
4240 self.client.send_request.assert_has_calls([
4241 mock.call('/security/key-managers', 'get', query=query)])
4243 def test__get_security_key_manager_nve_support_no_license(self):
4244 self.mock_object(self.client,
4245 'send_request',
4246 self._mock_api_error())
4248 result = self.client._get_security_key_manager_nve_support()
4250 self.assertFalse(result)
4252 query = {'fields': 'volume_encryption.*'}
4253 self.client.send_request.assert_has_calls([
4254 mock.call('/security/key-managers', 'get', query=query)])
4256 def test_get_nfs_config_default(self):
4257 api_response = fake.NFS_CONFIG_DEFAULT_RESULT_REST
4258 self.mock_object(self.client,
4259 'send_request',
4260 mock.Mock(return_value=api_response))
4262 result = self.client.get_nfs_config_default(['tcp-max-xfer-size',
4263 'udp-max-xfer-size'])
4264 expected = {
4265 'tcp-max-xfer-size': '65536',
4266 'udp-max-xfer-size': '32768',
4267 }
4268 self.assertEqual(expected, result)
4270 query = {'fields': 'transport.*'}
4271 self.client.send_request.assert_called_once_with(
4272 '/protocols/nfs/services/', 'get', query=query)
4274 def test_get_kerberos_service_principal_name(self):
4276 spn = self.client._get_kerberos_service_principal_name(
4277 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME
4278 )
4279 self.assertEqual(fake.KERBEROS_SERVICE_PRINCIPAL_NAME, spn)
4281 def test_get_cifs_server_name(self):
4283 expected_return = 'FAKE-VSE-SERVER'
4285 cifs_server = self.client._get_cifs_server_name(fake.VSERVER_NAME)
4287 self.assertEqual(expected_return, cifs_server)
4289 def test_list_network_interfaces(self):
4291 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE
4292 expected_result = [fake.LIF_NAME]
4294 self.mock_object(self.client,
4295 'send_request',
4296 mock.Mock(return_value=api_response))
4297 self.mock_object(self.client, '_has_records',
4298 mock.Mock(return_value=True))
4300 fake_query = {
4301 'fields': 'name'
4302 }
4304 result = self.client.list_network_interfaces()
4306 self.client.send_request.assert_has_calls([
4307 mock.call('/network/ip/interfaces', 'get', query=fake_query)])
4308 self.assertEqual(expected_result, result)
4310 def test_create_kerberos_realm(self):
4312 fake_security = fake.KERBEROS_SECURITY_SERVICE
4314 fake_body = {
4315 'comment': '',
4316 'kdc.ip': fake_security['server'],
4317 'kdc.port': '88',
4318 'kdc.vendor': 'other',
4319 'name': fake_security['domain'].upper(),
4320 }
4322 self.mock_object(self.client, 'send_request')
4324 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
4326 self.client.send_request.assert_called_once_with(
4327 '/protocols/nfs/kerberos/realms', 'post', body=fake_body)
4329 def test_configure_kerberos(self):
4331 fake_api_response = fake.NFS_LIFS_REST
4332 fake_security = fake.KERBEROS_SECURITY_SERVICE
4333 fake_keberos_name = fake.KERBEROS_SERVICE_PRINCIPAL_NAME
4335 fake_body = {
4336 'password': fake_security['password'],
4337 'user': fake_security['user'],
4338 'interface.name': fake.LIF_NAME,
4339 'enabled': True,
4340 'spn': fake_keberos_name
4341 }
4343 self.mock_object(self.client, 'configure_dns')
4344 self_get_kerberos = self.mock_object(
4345 self.client, '_get_kerberos_service_principal_name',
4346 mock.Mock(return_value=fake_keberos_name))
4347 self.mock_object(self.client, 'get_network_interfaces',
4348 mock.Mock(return_value=fake_api_response))
4349 self.mock_object(self.client, 'send_request')
4351 self.client.configure_kerberos(fake.KERBEROS_SECURITY_SERVICE,
4352 fake.VSERVER_NAME)
4354 self.client.configure_dns.assert_called_once_with(
4355 fake.KERBEROS_SECURITY_SERVICE, vserver_name=fake.VSERVER_NAME)
4356 self_get_kerberos.assert_called_once_with(
4357 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)
4358 self.client.get_network_interfaces.assert_called_once_with()
4359 self.client.send_request.assert_has_calls([
4360 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_1',
4361 'patch', body=fake_body),
4362 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_2',
4363 'patch', body=fake_body),
4364 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_3',
4365 'patch', body=fake_body)
4366 ])
4368 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3)
4369 def test_configure_active_directory(self, security_service):
4371 fake_security = copy.deepcopy(security_service)
4373 fake_body1 = {
4374 'ad_domain.user': fake_security['user'],
4375 'ad_domain.password': fake_security['password'],
4376 'force': 'true',
4377 'name': 'FAKE-VSE-SERVER',
4378 'ad_domain.fqdn': fake_security['domain'],
4379 }
4381 self.mock_object(self.client, 'configure_dns')
4382 self.mock_object(self.client, 'set_preferred_dc')
4383 self.mock_object(self.client, 'configure_cifs_aes_encryption')
4384 self.mock_object(self.client, '_get_cifs_server_name',
4385 mock.Mock(return_value='FAKE-VSE-SERVER'))
4386 self.mock_object(self.client, 'send_request')
4388 self.client.configure_active_directory(fake_security,
4389 fake.VSERVER_NAME,
4390 False)
4392 self.client.configure_dns.assert_called_once_with(
4393 fake_security, vserver_name=fake.VSERVER_NAME)
4394 self.client.set_preferred_dc.assert_called_once_with(
4395 fake_security, fake.VSERVER_NAME)
4396 self.client.configure_cifs_aes_encryption.assert_called_once_with(
4397 fake.VSERVER_NAME, False)
4398 self.client._get_cifs_server_name.assert_called_once_with(
4399 fake.VSERVER_NAME)
4401 if fake_security['ou'] is not None: 4401 ↛ 4408line 4401 didn't jump to line 4408 because the condition on line 4401 was always true
4402 fake_body1['ad_domain.organizational_unit'] = fake_security['ou']
4403 fake_body2 = fake_body1
4405 self.client.send_request.assert_called_once_with(
4406 '/protocols/cifs/services', 'post', body=fake_body2)
4407 else:
4408 self.client.send_request.assert_called_once_with(
4409 '/protocols/cifs/services', 'post', body=fake_body1)
4411 def test__create_ldap_client_ad(self):
4412 mock_dns = self.mock_object(self.client, 'configure_dns')
4413 mock_sr = self.mock_object(self.client, 'send_request')
4414 security_service = {
4415 'domain': 'fake_domain',
4416 'user': 'fake_user',
4417 'ou': 'fake_ou',
4418 'dns_ip': 'fake_ip',
4419 'password': 'fake_password'
4420 }
4422 ad_domain = security_service.get('domain')
4423 body = {
4424 'port': '389',
4425 'schema': 'MS-AD-BIS',
4426 'bind_dn': (security_service.get('user') + '@' + ad_domain),
4427 'bind_password': security_service.get('password'),
4428 'svm.name': fake.VSERVER_NAME,
4429 'base_dn': security_service.get('ou'),
4430 'ad_domain': security_service.get('domain'),
4431 }
4433 self.client._create_ldap_client(security_service,
4434 vserver_name=fake.VSERVER_NAME)
4435 mock_dns.assert_called_once_with(security_service)
4436 mock_sr.assert_called_once_with('/name-services/ldap', 'post',
4437 body=body)
4439 def test__create_ldap_client_linux(self):
4440 mock_dns = self.mock_object(self.client, 'configure_dns')
4441 mock_sr = self.mock_object(self.client, 'send_request')
4442 security_service = {
4443 'server': 'fake_server',
4444 'user': 'fake_user',
4445 'ou': 'fake_ou',
4446 'dns_ip': 'fake_ip'
4447 }
4449 body = {
4450 'port': '389',
4451 'schema': 'RFC-2307',
4452 'bind_dn': security_service.get('user'),
4453 'bind_password': security_service.get('password'),
4454 'svm.name': fake.VSERVER_NAME,
4455 'base_dn': security_service.get('ou'),
4456 'servers': [security_service.get('server')]
4457 }
4459 self.client._create_ldap_client(security_service,
4460 vserver_name=fake.VSERVER_NAME)
4461 mock_dns.assert_called_once_with(security_service)
4462 mock_sr.assert_called_once_with('/name-services/ldap', 'post',
4463 body=body)
4465 def test_configure_dns_already_present(self):
4466 dns_config = {
4467 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']],
4468 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']],
4469 }
4470 self.mock_object(self.client, 'get_dns_config',
4471 mock.Mock(return_value=dns_config))
4472 self.mock_object(self.client, 'send_request',
4473 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS))
4475 security_service = copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE)
4476 self.client.configure_dns(security_service)
4478 net_dns_create_args = {
4479 'domains': [security_service['domain']],
4480 'servers': [security_service['dns_ip']],
4481 }
4483 uuid = fake.FAKE_VOL_MOVE_STATUS['records'][0]['uuid']
4484 self.client.send_request.assert_has_calls([
4485 mock.call('/svm/svms', 'get',
4486 query={'name': None, 'fields': 'uuid'}),
4487 mock.call(f'/name-services/dns/{uuid}', 'patch',
4488 body=net_dns_create_args)])
4490 def test_configure_dns_for_active_directory(self):
4492 self.mock_object(self.client, 'send_request',
4493 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS))
4494 self.mock_object(self.client, 'get_dns_config',
4495 mock.Mock(return_value={}))
4497 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
4498 self.client.configure_dns(security_service)
4500 net_dns_create_args = {
4501 'domains': [security_service['domain']],
4502 'servers': [security_service['dns_ip']],
4503 }
4505 self.client.send_request.assert_has_calls([
4506 mock.call('/svm/svms', 'get',
4507 query={'name': None, 'fields': 'uuid'}),
4508 mock.call('/name-services/dns', 'post', body=net_dns_create_args)])
4510 def test_configure_dns_multiple_dns_ip(self):
4512 self.mock_object(self.client, 'send_request',
4513 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS))
4514 self.mock_object(self.client, 'get_dns_config',
4515 mock.Mock(return_value={}))
4516 mock_dns_ips = '10.0.0.5, 10.0.0.6, 10.0.0.7'
4517 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
4518 security_service['dns_ip'] = mock_dns_ips
4520 args_dns = {'domains': [security_service['domain']],
4521 'servers': ['10.0.0.5',
4522 '10.0.0.6',
4523 '10.0.0.7']}
4524 self.client.configure_dns(security_service)
4526 self.client.send_request.assert_has_calls([
4527 mock.call('/svm/svms', 'get',
4528 query={'name': None, 'fields': 'uuid'}),
4529 mock.call('/name-services/dns', 'post', body=args_dns)])
4531 def test_configure_dns_for_kerberos(self):
4533 self.mock_object(self.client, 'send_request',
4534 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS))
4535 self.mock_object(self.client, 'get_dns_config',
4536 mock.Mock(return_value={}))
4538 security_service = copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE)
4539 self.client.configure_dns(security_service)
4541 net_dns_create_args = {
4542 'domains': [security_service['domain']],
4543 'servers': [security_service['dns_ip']],
4544 }
4546 self.client.send_request.assert_has_calls([
4547 mock.call('/svm/svms', 'get',
4548 query={'name': None, 'fields': 'uuid'}),
4549 mock.call('/name-services/dns', 'post', body=net_dns_create_args)])
4551 def test_configure_dns_api_error(self):
4552 self.mock_object(self.client, 'send_request', self._mock_api_error())
4553 self.mock_object(self.client, 'get_dns_config',
4554 mock.Mock(return_value={}))
4555 self.mock_object(self.client, '_get_unique_svm_by_name',
4556 mock.Mock(return_value={}))
4558 self.assertRaises(exception.NetAppException,
4559 self.client.configure_dns,
4560 copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE))
4562 def test_get_dns_config_no_response(self):
4563 self.mock_object(self.client, 'send_request',
4564 mock.Mock(side_effect=netapp_api.api.NaApiError))
4565 self.mock_object(self.client, '_get_unique_svm_by_name',
4566 mock.Mock(return_value={}))
4567 self.assertRaises(exception.NetAppException,
4568 self.client.get_dns_config)
4570 def test_get_dns_config(self):
4571 api_response = fake.DNS_REST_RESPONSE
4572 self.mock_object(self.client, 'send_request',
4573 mock.Mock(return_value=api_response))
4574 fake_uuid = fake.FAKE_VOL_MOVE_STATUS['records'][0]['svm']['uuid']
4575 self.mock_object(self.client, '_get_unique_svm_by_name',
4576 mock.Mock(return_value=fake_uuid))
4578 result = self.client.get_dns_config()
4580 expected_result = {
4581 'dns-state': 'true',
4582 'domains': ['example.com', 'example2.example3.com'],
4583 'dns-ips': ['10.224.65.20', '2001:db08:a0b:12f0::1']
4584 }
4585 self.assertEqual(expected_result, result)
4586 self.client.send_request.assert_called_once_with(
4587 f'/name-services/dns/{fake_uuid}', 'get')
4589 @ddt.data(fake.LDAP_AD_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3,
4590 fake.KERBEROS_SECURITY_SERVICE)
4591 def test_setup_security_services(self, security_service):
4592 fake_response = fake.FAKE_GET_CLUSTER_NODE_VERSION_REST
4593 mock_request = self.mock_object(self.client, 'send_request',
4594 mock.Mock(return_value=fake_response))
4595 self.mock_object(self.client, 'configure_ldap')
4596 self.mock_object(self.client, 'configure_active_directory')
4597 self.mock_object(self.client, 'configure_cifs_options')
4598 self.mock_object(self.client, 'create_kerberos_realm')
4599 self.mock_object(self.client, 'configure_kerberos')
4601 ss_copy = copy.deepcopy(security_service)
4602 self.client.setup_security_services([ss_copy], self.client,
4603 'fake_vservername', False)
4604 uuid = fake_response.get('records')[0].get('uuid')
4605 body = {
4606 'nsswitch.namemap': ['ldap', 'files'],
4607 'nsswitch.group': ['ldap', 'files'],
4608 'nsswitch.netgroup': ['ldap', 'files'],
4609 'nsswitch.passwd': ['ldap', 'files'],
4610 }
4611 mock_request.assert_has_calls([
4612 mock.call('/svm/svms', 'get',
4613 query={'name': 'fake_vservername', 'fields': 'uuid'}),
4614 mock.call(f'/svm/svms/{uuid}', 'patch', body=body)])
4616 def test_modify_ldap_ad(self):
4617 fake_svm_uuid = fake.FAKE_UUID
4618 mock_svm_uuid = self.mock_object(self.client,
4619 '_get_unique_svm_by_name',
4620 mock.Mock(return_value=fake_svm_uuid))
4621 mock_sr = self.mock_object(self.client, 'send_request')
4622 security_service = {
4623 'domain': 'fake_domain',
4624 'user': 'fake_user',
4625 'ou': 'fake_ou',
4626 'dns_ip': 'fake_ip',
4627 'password': 'fake_password'
4628 }
4630 ad_domain = security_service.get('domain')
4631 body = {
4632 'port': '389',
4633 'schema': 'MS-AD-BIS',
4634 'bind_dn': (security_service.get('user') + '@' + ad_domain),
4635 'bind_password': security_service.get('password'),
4636 'base_dn': security_service.get('ou'),
4637 'ad_domain': security_service.get('domain'),
4638 }
4640 self.client.modify_ldap(security_service, None)
4641 mock_svm_uuid.assert_called_once_with(None)
4642 mock_sr.assert_called_once_with(f'/name-services/ldap/{fake_svm_uuid}',
4643 'patch', body=body)
4645 def test_modify_ldap_linux(self):
4646 fake_svm_uuid = fake.FAKE_UUID
4647 mock_svm_uuid = self.mock_object(self.client,
4648 '_get_unique_svm_by_name',
4649 mock.Mock(return_value=fake_svm_uuid))
4650 mock_sr = self.mock_object(self.client, 'send_request')
4651 security_service = {
4652 'server': 'fake_server',
4653 'user': 'fake_user',
4654 'ou': 'fake_ou',
4655 'dns_ip': 'fake_ip'
4656 }
4658 body = {
4659 'port': '389',
4660 'schema': 'RFC-2307',
4661 'bind_dn': security_service.get('user'),
4662 'bind_password': security_service.get('password'),
4663 'base_dn': security_service.get('ou'),
4664 'servers': [security_service.get('server')]
4665 }
4667 self.client.modify_ldap(security_service, None)
4668 mock_svm_uuid.assert_called_once_with(None)
4669 mock_sr.assert_called_once_with(f'/name-services/ldap/{fake_svm_uuid}',
4670 'patch', body=body)
4672 def test_update_kerberos_realm(self):
4673 self.mock_object(self.client,
4674 '_get_unique_svm_by_name',
4675 mock.Mock(return_value=fake.FAKE_UUID))
4676 fake_uuid = fake.FAKE_UUID
4677 self.mock_object(self.client, 'send_request')
4678 self.client.update_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
4679 fake_domain = fake.KERBEROS_SECURITY_SERVICE['domain']
4680 body = {
4681 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
4682 }
4684 self.client.send_request.assert_has_calls([
4685 mock.call(
4686 f'/protocols/nfs/kerberos/realms/{fake_uuid}/{fake_domain}',
4687 'patch', body=body)])
4689 def test__get_unique_svm_by_name(self):
4690 response = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
4691 svm = fake.SVM_ITEM_SIMPLE_RESPONSE_REST['uuid']
4693 fake_query = {
4694 'name': fake.VSERVER_NAME,
4695 'fields': 'uuid'
4696 }
4698 self.mock_object(self.client, 'send_request',
4699 mock.Mock(return_value=response))
4701 result = self.client._get_unique_svm_by_name(
4702 fake.VSERVER_NAME)
4704 self.client.send_request.assert_called_once_with(
4705 '/svm/svms', 'get', query=fake_query)
4707 self.assertEqual(svm, result)
4709 def test_update_dns_configuration(self):
4710 dns_config = {
4711 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']],
4712 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']],
4713 }
4715 body = {
4716 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']],
4717 'servers': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']]
4718 }
4720 fake_uuid = 'fake_uuid'
4722 self.mock_object(self.client, 'get_dns_config',
4723 mock.Mock(return_value=dns_config))
4725 self.mock_object(self.client,
4726 '_get_unique_svm_by_name',
4727 mock.Mock(return_value=fake_uuid))
4729 self.mock_object(self.client, 'send_request',
4730 mock.Mock(return_value=fake.FAKE_VOL_MOVE_STATUS))
4732 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE)
4733 body = {
4734 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']],
4735 'servers': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']]
4736 }
4738 self.client.send_request.assert_called_once_with(
4739 f'/name-services/dns/{fake_uuid}', 'patch', body=body)
4741 def test_remove_preferred_dcs(self):
4742 svm_uuid = copy.deepcopy(fake.FAKE_UUID)
4743 fqdn = copy.deepcopy(fake.PREFERRED_DC_REST.get('fqdn'))
4744 server_ip = copy.deepcopy(fake.PREFERRED_DC_REST.get('server_ip'))
4745 fake_response = copy.deepcopy(fake.PREFERRED_DC_REST)
4746 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE)
4747 self.mock_object(self.client, 'send_request',
4748 mock.Mock(return_value=fake_response))
4749 self.client.remove_preferred_dcs(fake_ss, svm_uuid)
4750 query = {
4751 'fqdn': fake.LDAP_AD_SECURITY_SERVICE.get('domain'),
4752 }
4753 self.client.send_request.assert_has_calls([
4754 mock.call(f'/protocols/cifs/domains/{svm_uuid}/'
4755 f'preferred-domain-controllers/', 'get'),
4756 mock.call(f'/protocols/cifs/domains/{svm_uuid}/'
4757 f'preferred-domain-controllers/{fqdn}/{server_ip}',
4758 'delete', query=query)
4759 ])
4761 def test_remove_preferred_dcs_api_error(self):
4762 fake_response = copy.deepcopy(fake.PREFERRED_DC_REST)
4763 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE)
4764 self.mock_object(self.client, 'send_request',
4765 mock.Mock(return_value=fake_response))
4766 self.mock_object(self.client, 'send_request',
4767 mock.Mock(side_effect=netapp_api.api.NaApiError))
4768 self.assertRaises(netapp_api.api.NaApiError,
4769 self.client.remove_preferred_dcs,
4770 fake_ss, fake.FAKE_UUID)
4772 def test_configure_cifs_aes_encryption_enable(self):
4773 self.mock_object(self.client, 'send_request')
4774 self.mock_object(self.client, '_get_unique_svm_by_name',
4775 mock.Mock(return_value=fake.FAKE_UUID))
4777 self.client.configure_cifs_aes_encryption(fake.VSERVER_NAME, True)
4778 self.client._get_unique_svm_by_name.assert_called_once_with(
4779 fake.VSERVER_NAME)
4781 body = {
4782 'security.advertised_kdc_encryptions': ['aes-128', 'aes-256'],
4783 }
4784 self.client.send_request.assert_called_once_with(
4785 f'/protocols/cifs/services/{fake.FAKE_UUID}',
4786 'patch', body=body)
4788 def test_configure_cifs_aes_encryption_disable(self):
4789 self.mock_object(self.client, 'send_request')
4790 self.mock_object(self.client, '_get_unique_svm_by_name',
4791 mock.Mock(return_value=fake.FAKE_UUID))
4793 self.client.configure_cifs_aes_encryption(fake.VSERVER_NAME, False)
4794 self.client._get_unique_svm_by_name.assert_called_once_with(
4795 fake.VSERVER_NAME)
4797 body = {
4798 'security.advertised_kdc_encryptions': ['des', 'rc4'],
4799 }
4800 self.client.send_request.assert_called_once_with(
4801 f'/protocols/cifs/services/{fake.FAKE_UUID}',
4802 'patch', body=body)
4804 def test_set_preferred_dc(self):
4805 fake_ss = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE_WITH_SERVER)
4806 self.mock_object(self.client, 'send_request')
4807 self.mock_object(self.client, '_get_unique_svm_by_name',
4808 mock.Mock(return_value=fake.FAKE_UUID))
4810 self.client.set_preferred_dc(fake_ss, fake.VSERVER_NAME)
4812 self.client._get_unique_svm_by_name.assert_called_once_with(
4813 fake.VSERVER_NAME)
4815 query = {
4816 'fqdn': fake_ss['domain'],
4817 'skip_config_validation': 'false',
4818 'server_ip': ['10.10.10.1']
4819 }
4820 self.client.send_request.assert_called_once_with(
4821 f'/protocols/cifs/domains/{fake.FAKE_UUID}'
4822 '/preferred-domain-controllers', 'post', query=query)
4824 @ddt.data(None, 'cluster_name')
4825 def test_create_vserver_peer(self, cluster_name):
4827 self.mock_object(self.client, 'send_request')
4829 self.client.create_vserver_peer(fake.VSERVER_NAME,
4830 fake.VSERVER_PEER_NAME,
4831 peer_cluster_name=cluster_name)
4833 body = {
4834 'svm.name': fake.VSERVER_NAME,
4835 'peer.svm.name': fake.VSERVER_PEER_NAME,
4836 'applications': ['snapmirror'],
4837 }
4838 if cluster_name:
4839 body['peer.cluster.name'] = cluster_name
4841 self.client.send_request.assert_has_calls([
4842 mock.call('/svm/peers', 'post', body=body,
4843 enable_tunneling=False)])
4845 def test__get_svm_peer_uuid(self):
4846 response = {
4847 "records": [{
4848 "uuid": "fake-vserver-uuid",
4849 "name": fake.VSERVER_NAME,
4850 "svm": {
4851 "name": fake.VSERVER_NAME,
4852 },
4853 "peer": {
4854 "svm": {
4855 "name": fake.VSERVER_PEER_NAME,
4856 }
4857 }
4858 }],
4859 }
4860 expected_result = "fake-vserver-uuid"
4861 return_value = response['records'][0]['uuid']
4862 self.mock_object(self.client, '_get_svm_peer_uuid',
4863 mock.Mock(return_value=return_value))
4865 result = self.client._get_svm_peer_uuid(
4866 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME)
4868 self.client._get_svm_peer_uuid.assert_called_once_with(
4869 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME)
4871 self.assertEqual(expected_result, result)
4873 def test_accept_vserver_peer(self):
4875 fake_resp = {
4876 'records': [{'uuid': 'fake-vserver-uuid'}],
4877 'num_records': 1,
4878 }
4880 self.mock_object(
4881 self.client, 'send_request',
4882 mock.Mock(side_effect=[fake_resp, None]))
4883 self.client.accept_vserver_peer(
4884 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME)
4886 body = {'state': 'peered'}
4888 uuid = "fake-vserver-uuid"
4889 self.client.send_request.assert_has_calls([
4890 mock.call(f'/svm/peers/{uuid}', 'patch', body=body,
4891 enable_tunneling=False)])
4893 def test_get_vserver_peers(self):
4894 self.mock_object(self.client,
4895 'send_request',
4896 mock.Mock(return_value=fake.FAKE_PEER_GET_RESPONSE))
4898 result = self.client.get_vserver_peers(
4899 vserver_name=fake.VSERVER_NAME,
4900 peer_vserver_name=fake.VSERVER_NAME_2)
4902 query = {
4903 'name': fake.VSERVER_NAME_2,
4904 'svm.name': fake.VSERVER_NAME
4905 }
4906 query['fields'] = 'uuid,svm.name,peer.svm.name,state,peer.cluster.name'
4907 self.client.send_request.assert_has_calls([
4908 mock.call('/svm/peers', 'get', query=query)])
4910 expected = [{
4911 'uuid': fake.FAKE_UUID,
4912 'vserver': fake.VSERVER_NAME,
4913 'peer-vserver': fake.VSERVER_NAME_2,
4914 'peer-state': fake.VSERVER_PEER_STATE,
4915 'peer-cluster': fake.CLUSTER_NAME
4916 }]
4917 self.assertEqual(expected, result)
4919 def test_get_vserver_peers_not_found(self):
4921 self.mock_object(self.client,
4922 'send_request',
4923 mock.Mock(return_value=fake.NO_RECORDS_RESPONSE_REST))
4925 result = self.client.get_vserver_peers(
4926 vserver_name=fake.VSERVER_NAME,
4927 peer_vserver_name=fake.VSERVER_NAME_2)
4929 self.assertEqual([], result)
4930 self.assertTrue(self.client.send_request.called)
4932 def test_delete_vserver_peer(self):
4934 self.mock_object(self.client, 'get_vserver_peers',
4935 mock.Mock(return_value=fake.FAKE_VSERVER_PEERS))
4937 self.mock_object(self.client, 'send_request')
4939 self.client.delete_vserver_peer(fake.VSERVER_NAME,
4940 fake.VSERVER_PEER_NAME)
4942 self.client.get_vserver_peers.assert_called_once_with(
4943 fake.VSERVER_NAME, fake.VSERVER_PEER_NAME)
4944 self.client.send_request.assert_called_once_with(
4945 '/svm/peers/fake_uuid', 'delete', enable_tunneling=False)
4947 def test_update_showmount(self):
4948 query = {
4949 'name': fake.VSERVER_NAME,
4950 'fields': 'uuid'
4951 }
4952 response_svm = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
4953 self.client.vserver = fake.VSERVER_NAME
4954 self.mock_object(self.client,
4955 'send_request',
4956 mock.Mock(side_effect=[response_svm, None]))
4958 fake_showmount = 'true'
4959 self.client.update_showmount(fake_showmount)
4961 svm_id = response_svm.get('records')[0]['uuid']
4963 body = {
4964 'showmount_enabled': fake_showmount,
4965 }
4966 self.client.send_request.assert_has_calls([
4967 mock.call('/svm/svms', 'get', query=query),
4968 mock.call(f'/protocols/nfs/services/{svm_id}',
4969 'patch', body=body)
4970 ])
4972 @ddt.data({'tcp-max-xfer-size': 10000}, {}, None)
4973 def test_enable_nfs(self, nfs_config):
4974 self.mock_object(self.client, '_get_unique_svm_by_name',
4975 mock.Mock(return_value=fake.FAKE_UUID))
4976 self.mock_object(self.client, 'send_request')
4977 self.mock_object(self.client,
4978 '_enable_nfs_protocols')
4979 self.mock_object(self.client,
4980 '_configure_nfs')
4981 self.mock_object(self.client,
4982 '_create_default_nfs_export_rules')
4984 self.mock_object(self.client, '_enable_nfs_protocols')
4986 self.client.enable_nfs(fake.NFS_VERSIONS, nfs_config)
4987 body = {
4988 'svm.uuid': fake.FAKE_UUID,
4989 'enabled': 'true'
4990 }
4992 self.client.send_request.assert_called_once_with(
4993 '/protocols/nfs/services/', 'post', body=body)
4994 self.client._get_unique_svm_by_name.assert_called_once_with()
4995 self.client._enable_nfs_protocols.assert_called_once_with(
4996 fake.NFS_VERSIONS, fake.FAKE_UUID)
4997 if nfs_config:
4998 self.client._configure_nfs.assert_called_once_with(nfs_config,
4999 fake.FAKE_UUID)
5000 else:
5001 self.client._configure_nfs.assert_not_called()
5002 self.client._create_default_nfs_export_rules.assert_called_once_with()
5004 @ddt.data((True, True, True), (True, False, False), (False, True, True))
5005 @ddt.unpack
5006 def test_enable_nfs_protocols(self, v3, v40, v41):
5008 self.mock_object(self.client, 'send_request')
5010 versions = []
5011 if v3:
5012 versions.append('nfs3')
5013 if v40:
5014 versions.append('nfs4.0')
5015 if v41:
5016 versions.append('nfs4.1')
5018 self.client._enable_nfs_protocols(versions, fake.FAKE_UUID)
5020 body = {
5021 'protocol.v3_enabled': 'true' if v3 else 'false',
5022 'protocol.v40_enabled': 'true' if v40 else 'false',
5023 'protocol.v41_enabled': 'true' if v41 else 'false',
5024 'showmount_enabled': 'true',
5025 'windows.v3_ms_dos_client_enabled': 'true',
5026 'protocol.v3_features.connection_drop': 'false',
5027 'protocol.v3_features.ejukebox_enabled': 'false',
5028 }
5029 self.client.send_request.assert_called_once_with(
5030 f'/protocols/nfs/services/{fake.FAKE_UUID}',
5031 'patch', body=body)
5033 def test_configure_nfs(self):
5034 self.mock_object(self.client, 'send_request')
5036 fake_nfs = {
5037 'tcp-max-xfer-size': 10000,
5038 }
5039 self.client._configure_nfs(fake_nfs, fake.FAKE_UUID)
5041 body = {
5042 'transport.tcp_max_transfer_size': 10000
5043 }
5044 self.client.send_request.assert_called_once_with(
5045 f'/protocols/nfs/services/{fake.FAKE_UUID}',
5046 'patch', body=body)
5048 def test__create_default_nfs_export_rules(self):
5050 class CopyingMock(mock.Mock):
5051 def __call__(self, *args, **kwargs):
5052 args = copy.deepcopy(args)
5053 kwargs = copy.deepcopy(kwargs)
5054 return super(CopyingMock, self).__call__(*args, **kwargs)
5056 self.mock_object(self.client, 'send_request', CopyingMock())
5058 fake_uuid = fake.FAKE_UUID
5060 mock_id = self.mock_object(self.client, 'get_unique_export_policy_id',
5061 mock.Mock(return_value=fake_uuid))
5063 self.client._create_default_nfs_export_rules()
5065 body = {
5066 'clients': [{
5067 'match': '0.0.0.0/0'
5068 }],
5069 'ro_rule': [
5070 'any',
5071 ],
5072 'rw_rule': [
5073 'never'
5074 ],
5075 }
5076 body2 = body.copy()
5077 body2['clients'] = [{
5078 'match': '::/0'
5079 }]
5081 mock_id.assert_called_once_with('default')
5082 self.client.send_request.assert_has_calls([
5083 mock.call(f'/protocols/nfs/export-policies/{fake_uuid}/rules',
5084 "post", body=body),
5085 mock.call(f'/protocols/nfs/export-policies/{fake_uuid}/rules',
5086 "post", body=body2)])
5088 def test_get_node_data_ports(self):
5089 self.mock_object(
5090 self.client, 'send_request', mock.Mock(
5091 side_effect=[fake.REST_ETHERNET_PORTS,
5092 fake.REST_DATA_INTERFACES]))
5093 self.mock_object(
5094 self.client, '_sort_data_ports_by_speed', mock.Mock(
5095 return_value=fake.REST_SPEED_SORTED_PORTS))
5097 test_result = self.client.get_node_data_ports(fake.NODE_NAME)
5099 fake_query = {
5100 'node.name': fake.NODE_NAME,
5101 'state': 'up',
5102 'type': 'physical',
5103 'broadcast_domain.name': 'Default',
5104 'fields': 'node.name,speed,name'
5105 }
5107 query_interfaces = {
5108 'service_policy.name': '!default-management',
5109 'services': 'data_*',
5110 'fields': 'location.port.name'
5111 }
5113 self.client.send_request.assert_has_calls([
5114 mock.call('/network/ethernet/ports', 'get', query=fake_query),
5115 mock.call('/network/ip/interfaces', 'get',
5116 query=query_interfaces, enable_tunneling=False),
5117 ])
5118 self.client._sort_data_ports_by_speed.assert_called_once_with(
5119 fake.REST_SPEED_NOT_SORTED_PORTS)
5120 self.assertEqual(fake.REST_SPEED_SORTED_PORTS, test_result)
5122 def test_list_node_data_ports(self):
5124 expected_resulted = ['e0d', 'e0c', 'e0b']
5126 mock_ports = (
5127 self.mock_object(self.client, 'get_node_data_ports', mock.Mock(
5128 return_value=fake.REST_SPEED_SORTED_PORTS)))
5130 test_result = self.client.list_node_data_ports(fake.NODE_NAME)
5132 mock_ports.assert_called_once_with(fake.NODE_NAME)
5133 self.assertEqual(test_result, expected_resulted)
5135 def test_create_ipspace(self):
5136 fake_body = {'name': fake.IPSPACE_NAME}
5138 self.mock_object(self.client, 'send_request')
5140 self.client.create_ipspace(fake.IPSPACE_NAME)
5142 self.client.send_request.assert_called_once_with(
5143 '/network/ipspaces', 'post', body=fake_body)
5145 def test_get_ipspace_name_for_vlan_port(self):
5147 fake_query = {
5148 'node.name': fake.NODE_NAME,
5149 'name': fake.VLAN_PORT,
5150 'fields': 'broadcast_domain.ipspace.name',
5151 }
5153 expected_result = "Default"
5155 self.mock_object(
5156 self.client, 'send_request', mock.Mock(
5157 return_value=fake.REST_ETHERNET_PORTS))
5159 test_result = self.client.get_ipspace_name_for_vlan_port(
5160 fake.NODE_NAME, fake.PORT, fake.VLAN)
5162 self.client.send_request.assert_called_once_with(
5163 '/network/ethernet/ports/', 'get', query=fake_query)
5165 self.assertEqual(test_result, expected_result)
5167 def test__create_broadcast_domain(self):
5169 fake_body = {
5170 'ipspace.name': fake.IPSPACE_NAME,
5171 'name': fake.BROADCAST_DOMAIN,
5172 'mtu': fake.MTU,
5173 }
5175 self.mock_object(self.client, 'send_request')
5177 self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
5178 fake.IPSPACE_NAME,
5179 fake.MTU)
5181 self.client.send_request.assert_called_once_with(
5182 '/network/ethernet/broadcast-domains', 'post', body=fake_body)
5184 def test_ensure_broadcast_domain_for_port_domain_match(self):
5186 port_info = {
5187 'ipspace': fake.IPSPACE_NAME,
5188 'broadcast-domain': fake.BROADCAST_DOMAIN,
5189 }
5190 self.mock_object(self.client,
5191 '_get_broadcast_domain_for_port',
5192 mock.Mock(return_value=port_info))
5193 self.mock_object(self.client,
5194 '_broadcast_domain_exists',
5195 mock.Mock(return_value=True))
5196 self.mock_object(self.client, '_create_broadcast_domain')
5197 self.mock_object(self.client, '_modify_broadcast_domain')
5198 self.mock_object(self.client, '_add_port_to_broadcast_domain')
5200 self.client._ensure_broadcast_domain_for_port(
5201 fake.NODE_NAME, fake.PORT, fake.MTU, ipspace=fake.IPSPACE_NAME)
5203 self.client._get_broadcast_domain_for_port.assert_called_once_with(
5204 fake.NODE_NAME, fake.PORT)
5205 self.client._modify_broadcast_domain.assert_called_once_with(
5206 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
5207 self.assertFalse(self.client._broadcast_domain_exists.called)
5208 self.assertFalse(self.client._create_broadcast_domain.called)
5209 self.assertFalse(self.client._add_port_to_broadcast_domain.called)
5211 @ddt.data(fake.IPSPACE_NAME, client_cmode.DEFAULT_IPSPACE)
5212 def test_ensure_broadcast_domain_for_port_other_domain(self, ipspace):
5214 port_info = {
5215 'ipspace': ipspace,
5216 'broadcast-domain': 'other_domain',
5217 }
5218 self.mock_object(self.client,
5219 '_get_broadcast_domain_for_port',
5220 mock.Mock(return_value=port_info))
5221 self.mock_object(self.client,
5222 '_broadcast_domain_exists',
5223 mock.Mock(return_value=True))
5224 self.mock_object(self.client, '_create_broadcast_domain')
5225 self.mock_object(self.client, '_modify_broadcast_domain')
5226 self.mock_object(self.client, '_add_port_to_broadcast_domain')
5228 self.client._ensure_broadcast_domain_for_port(
5229 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
5231 self.client._get_broadcast_domain_for_port.assert_called_once_with(
5232 fake.NODE_NAME, fake.PORT)
5233 self.client._broadcast_domain_exists.assert_called_once_with(
5234 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
5235 self.assertFalse(self.client._create_broadcast_domain.called)
5236 self.client._modify_broadcast_domain.assert_called_once_with(
5237 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
5238 self.client._add_port_to_broadcast_domain.assert_called_once_with(
5239 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
5240 fake.IPSPACE_NAME)
5242 def test_ensure_broadcast_domain_for_port_no_domain(self):
5244 port_info = {
5245 'ipspace': fake.IPSPACE_NAME,
5246 'broadcast-domain': None,
5247 }
5248 self.mock_object(self.client,
5249 '_get_broadcast_domain_for_port',
5250 mock.Mock(return_value=port_info))
5251 self.mock_object(self.client,
5252 '_broadcast_domain_exists',
5253 mock.Mock(return_value=False))
5254 self.mock_object(self.client, '_create_broadcast_domain')
5255 self.mock_object(self.client, '_modify_broadcast_domain')
5256 self.mock_object(self.client, '_add_port_to_broadcast_domain')
5258 self.client._ensure_broadcast_domain_for_port(
5259 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
5261 self.client._get_broadcast_domain_for_port.assert_called_once_with(
5262 fake.NODE_NAME, fake.PORT)
5263 self.client._broadcast_domain_exists.assert_called_once_with(
5264 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
5265 self.client._create_broadcast_domain.assert_called_once_with(
5266 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
5267 self.assertFalse(self.client._modify_broadcast_domain.called)
5268 self.client._add_port_to_broadcast_domain.assert_called_once_with(
5269 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
5270 fake.IPSPACE_NAME)
5272 def test__add_port_to_broadcast_domain(self):
5273 query = {
5274 'name': fake.PORT,
5275 'node.name': fake.NODE_NAME,
5276 }
5277 body = {
5278 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME,
5279 'broadcast_domain.name': fake.BROADCAST_DOMAIN,
5280 }
5282 self.mock_object(self.client, 'send_request')
5283 self.client._add_port_to_broadcast_domain(fake.NODE_NAME,
5284 fake.PORT,
5285 fake.BROADCAST_DOMAIN,
5286 fake.IPSPACE_NAME)
5288 self.client.send_request.assert_called_once_with(
5289 '/network/ethernet/ports/', 'patch', query=query, body=body)
5291 def test__add_port_to_broadcast_domain_exists(self):
5292 query = {
5293 'name': fake.PORT,
5294 'node.name': fake.NODE_NAME,
5295 }
5296 body = {
5297 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME,
5298 'broadcast_domain.name': fake.BROADCAST_DOMAIN,
5299 }
5300 self.mock_object(
5301 self.client, 'send_request', self._mock_api_error(
5302 code=netapp_api.EREST_FAIL_ADD_PORT_BROADCAST))
5304 self.client._add_port_to_broadcast_domain(fake.NODE_NAME,
5305 fake.PORT,
5306 fake.BROADCAST_DOMAIN,
5307 fake.IPSPACE_NAME)
5309 self.client.send_request.assert_called_once_with(
5310 '/network/ethernet/ports/', 'patch', query=query, body=body)
5311 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
5313 def test__add_port_to_broadcast_domain_exception(self):
5314 self.mock_object(self.client, 'send_request',
5315 self._mock_api_error())
5316 self.assertRaises(
5317 exception.NetAppException,
5318 self.client._add_port_to_broadcast_domain,
5319 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
5320 fake.IPSPACE_NAME)
5322 def test_rename_vserver(self):
5323 svm_uuid = fake.SVM_ITEM_SIMPLE_RESPONSE_REST["uuid"]
5324 body = {
5325 'name': fake.VSERVER_NAME_2
5326 }
5328 self.mock_object(self.client, '_get_unique_svm_by_name',
5329 mock.Mock(return_value=svm_uuid))
5330 self.mock_object(self.client, 'send_request')
5332 self.client.rename_vserver(fake.VSERVER_NAME, fake.VSERVER_NAME_2)
5334 self.client._get_unique_svm_by_name.assert_called_once_with(
5335 fake.VSERVER_NAME)
5336 self.client.send_request.assert_called_once_with(
5337 f'/svm/svms/{svm_uuid}', 'patch', body=body)
5339 def test_create_network_interface(self):
5340 api_response = copy.deepcopy(fake.SERVICE_POLICIES_REST)
5341 self.mock_object(
5342 self.client, 'send_request',
5343 mock.Mock(side_effect=[api_response, None, None]))
5345 self.client.create_network_interface(fake.IP_ADDRESS,
5346 fake.NETMASK,
5347 fake.NODE_NAME,
5348 fake.VLAN_PORT,
5349 fake.VSERVER_NAME,
5350 fake.LIF_NAME)
5351 query = {
5352 'name': 'default-data-files',
5353 'svm.name': fake.VSERVER_NAME,
5354 'fields': 'uuid,name,services,svm.name'
5355 }
5357 policy = copy.deepcopy(fake.SERVICE_POLICIES_REST['records'][0])
5358 uuid = policy['uuid']
5360 policy['services'].append('data_nfs')
5361 policy['services'].append('data_cifs')
5362 body1 = {'services': policy['services']}
5364 body2 = {
5365 'ip.address': fake.IP_ADDRESS,
5366 'ip.netmask': fake.NETMASK,
5367 'enabled': 'true',
5368 'service_policy.name': 'default-data-files',
5369 'location.home_node.name': fake.NODE_NAME,
5370 'location.home_port.name': fake.VLAN_PORT,
5371 'name': fake.LIF_NAME,
5372 'svm.name': fake.VSERVER_NAME,
5373 }
5375 self.client.send_request.assert_has_calls([
5376 mock.call('/network/ip/service-policies/', 'get', query=query),
5377 mock.call(f'/network/ip/service-policies/{uuid}',
5378 'patch', body=body1),
5379 mock.call('/network/ip/interfaces', 'post', body=body2)
5380 ])
5382 def test_create_vserver(self):
5383 mock = self.mock_object(self.client, '_create_vserver')
5384 self.mock_object(self.client, '_modify_security_cert',
5385 mock.Mock(return_value=[]))
5386 self.client.create_vserver(fake.VSERVER_NAME, None, None,
5387 [fake.SHARE_AGGREGATE_NAME],
5388 fake.IPSPACE_NAME,
5389 fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS,
5390 fake.DELETE_RETENTION_HOURS,
5391 False)
5392 mock.assert_called_once_with(fake.VSERVER_NAME,
5393 [fake.SHARE_AGGREGATE_NAME],
5394 fake.IPSPACE_NAME,
5395 fake.DELETE_RETENTION_HOURS,
5396 name_server_switch=['files'],
5397 logical_space_reporting=False)
5398 self.client._modify_security_cert.assert_called_once_with(
5399 fake.VSERVER_NAME,
5400 fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
5402 def test__modify_security_cert(self):
5403 api_response = copy.deepcopy(fake.SECURITY_CERT_GET_RESPONSE_REST)
5404 api_response2 = copy.deepcopy(fake.SECURITY_CERT_POST_RESPONSE_REST)
5405 self.mock_object(
5406 self.client, 'send_request',
5407 mock.Mock(side_effect=[api_response, api_response2, None, None]))
5409 query = {
5410 'common-name': fake.VSERVER_NAME,
5411 'ca': fake.VSERVER_NAME,
5412 'type': 'server',
5413 'svm.name': fake.VSERVER_NAME,
5414 }
5415 old_cert_info = copy.deepcopy(
5416 fake.SECURITY_CERT_GET_RESPONSE_REST['records'][0])
5417 old_cert_uuid = old_cert_info['uuid']
5419 body1 = {
5420 'common-name': fake.VSERVER_NAME,
5421 'type': 'server',
5422 'svm.name': fake.VSERVER_NAME,
5423 'expiry_time': 'P' + str(
5424 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) + 'DT',
5425 }
5426 query1 = {
5427 'return_records': 'true'
5428 }
5429 new_cert_info = copy.deepcopy(
5430 fake.SECURITY_CERT_POST_RESPONSE_REST['records'][0])
5431 new_cert_uuid = new_cert_info['uuid']
5432 new_svm_uuid = new_cert_info['svm']['uuid']
5433 body2 = {
5434 'certificate': {
5435 'uuid': new_cert_uuid,
5436 },
5437 'client_enabled': 'false',
5438 }
5440 self.client._modify_security_cert(
5441 fake.VSERVER_NAME,
5442 fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
5444 self.client.send_request.assert_has_calls([
5445 mock.call('/security/certificates', 'get', query=query),
5446 mock.call('/security/certificates', 'post', body=body1,
5447 query=query1),
5448 mock.call(f'/svm/svms/{new_svm_uuid}', 'patch', body=body2),
5449 mock.call(f'/security/certificates/{old_cert_uuid}', 'delete'),
5450 ])
5452 def test__broadcast_domain_exists(self):
5453 response = fake.FAKE_GET_BROADCAST_DOMAIN
5454 self.mock_object(self.client, 'send_request',
5455 mock.Mock(return_value=response))
5456 self.mock_object(self.client, '_has_records',
5457 mock.Mock(return_value=True))
5458 query = {
5459 'ipspace.name': fake.IPSPACE_NAME,
5460 'name': fake.BROADCAST_DOMAIN,
5461 }
5462 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
5463 fake.IPSPACE_NAME)
5464 self.client.send_request.assert_called_once_with(
5465 '/network/ethernet/broadcast-domains',
5466 'get', query=query)
5467 self.assertTrue(result)
5469 def test___delete_port_by_ipspace_and_broadcast_domain(self):
5470 self.mock_object(self.client, 'send_request')
5471 query = {
5472 'broadcast_domain.ipspace.name': fake.IPSPACE_NAME,
5473 'broadcast_domain.name': fake.BROADCAST_DOMAIN,
5474 'name': fake.PORT
5475 }
5476 self.client._delete_port_by_ipspace_and_broadcast_domain(
5477 fake.PORT,
5478 fake.BROADCAST_DOMAIN,
5479 fake.IPSPACE_NAME)
5480 self.client.send_request.assert_called_once_with(
5481 '/network/ethernet/ports/', 'delete',
5482 query=query)
5484 def test_get_broadcast_domain_for_port(self):
5486 self.mock_object(self.client, 'send_request', mock.Mock(
5487 return_value=fake.REST_ETHERNET_PORTS))
5489 query = {
5490 'node.name': fake.NODE_NAME,
5491 'name': fake.PORT,
5492 'fields': 'broadcast_domain.name,broadcast_domain.ipspace.name'
5493 }
5495 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
5496 fake.PORT)
5498 expected = {
5499 'broadcast-domain': "fake_domain_1",
5500 'ipspace': "Default",
5501 }
5502 self.client.send_request.assert_has_calls([
5503 mock.call('/network/ethernet/ports', 'get', query=query)])
5504 self.assertEqual(expected, result)
5506 def test_modify_broadcast_domain(self):
5508 self.mock_object(self.client, 'send_request')
5510 result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN,
5511 fake.IPSPACE_NAME,
5512 fake.MTU)
5514 query = {
5515 'name': fake.BROADCAST_DOMAIN
5516 }
5518 body = {
5519 'ipspace.name': fake.IPSPACE_NAME,
5520 'mtu': fake.MTU,
5521 }
5522 self.assertIsNone(result)
5523 self.client.send_request.assert_called_once_with(
5524 '/network/ethernet/broadcast-domains', 'patch', body=body,
5525 query=query)
5527 @ddt.data(fake.NO_RECORDS_RESPONSE,
5528 fake.SVMS_LIST_SIMPLE_RESPONSE_REST)
5529 def test_get_vserver_info(self, api_response):
5530 self.mock_object(self.client, 'send_request',
5531 mock.Mock(return_value=api_response))
5533 result = self.client.get_vserver_info(fake.VSERVER_NAME)
5535 query = {
5536 'name': fake.VSERVER_NAME,
5537 'fields': 'state,subtype'
5538 }
5539 self.client.send_request.assert_called_once_with(
5540 '/svm/svms', 'get', query=query)
5541 if api_response == fake.NO_RECORDS_RESPONSE:
5542 self.assertIsNone(result)
5543 else:
5544 self.assertDictEqual(fake.VSERVER_INFO, result)
5546 def test_get_nfs_config(self):
5547 api_response = fake.NFS_CONFIG_RESULT_REST
5548 self.mock_object(self.client,
5549 'send_request',
5550 mock.Mock(return_value=api_response))
5552 result = self.client.get_nfs_config(['tcp-max-xfer-size',
5553 'udp-max-xfer-size'],
5554 fake.VSERVER_NAME)
5555 expected = {
5556 'tcp-max-xfer-size': '65536',
5557 'udp-max-xfer-size': '32768',
5558 }
5559 self.assertEqual(expected, result)
5561 query = {'fields': 'transport.*', 'svm.name': 'fake_vserver'}
5562 self.client.send_request.assert_called_once_with(
5563 '/protocols/nfs/services/', 'get', query=query)
5565 def test_get_vserver_ipspace(self):
5567 self.client.features.add_feature('IPSPACES')
5568 api_response = fake.REST_VSERVER_GET_IPSPACE_NAME_RESPONSE
5569 self.mock_object(self.client,
5570 'send_request',
5571 mock.Mock(return_value=api_response))
5573 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME)
5575 query = {
5576 'name': fake.VSERVER_NAME,
5577 'fields': 'ipspace.name'
5578 }
5579 expected = fake.IPSPACE_NAME
5580 self.client.send_request.assert_has_calls([
5581 mock.call('/svm/svms', 'get', query=query)])
5582 self.assertEqual(expected, result)
5584 def test_get_vserver_ipspace_not_found(self):
5585 api_response = fake.NO_RECORDS_RESPONSE_REST
5586 self.mock_object(self.client, 'send_request',
5587 mock.Mock(return_value=api_response))
5588 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME)
5589 self.assertIsNone(result)
5591 def test_get_vserver_ipspace_exception(self):
5592 self.mock_object(self.client, 'send_request',
5593 self._mock_api_error())
5594 self.assertRaises(exception.NetAppException,
5595 self.client.get_vserver_ipspace,
5596 fake.VSERVER_NAME)
5598 def test_get_snapmirror_policies(self):
5599 api_response = fake.GET_SNAPMIRROR_POLICIES_REST
5600 self.mock_object(self.client, 'send_request',
5601 mock.Mock(return_value=api_response))
5602 result_elem = [fake.SNAPMIRROR_POLICY_NAME]
5604 result = self.client.get_snapmirror_policies(
5605 fake.VSERVER_NAME)
5607 query = {
5608 'svm.name': fake.VSERVER_NAME,
5609 'fields': 'name'
5610 }
5612 self.client.send_request.assert_called_once_with(
5613 '/snapmirror/policies', 'get', query=query)
5614 self.assertEqual(result_elem, result)
5616 def test_delete_snapmirror_policy(self):
5617 api_response = fake.GET_SNAPMIRROR_POLICIES_REST
5618 self.mock_object(self.client, 'send_request',
5619 mock.Mock(return_value=api_response))
5621 self.client.delete_snapmirror_policy('fake_policy')
5623 query = {}
5624 query['name'] = 'fake_policy'
5625 query['fields'] = 'uuid,name'
5626 uuid = fake.FAKE_UUID
5627 self.client.send_request.assert_has_calls([
5628 mock.call('/snapmirror/policies', 'get', query=query),
5629 mock.call(f'/snapmirror/policies/{uuid}', 'delete')
5630 ])
5632 def test_delete_snapmirror_policy_exception(self):
5633 api_response = fake.GET_SNAPMIRROR_POLICIES_REST
5634 api_error = netapp_api.api.NaApiError()
5635 self.mock_object(self.client, 'send_request',
5636 mock.Mock(side_effect=[api_response, api_error]))
5637 self.assertRaises(netapp_api.api.NaApiError,
5638 self.client.delete_snapmirror_policy,
5639 'fake_policy')
5641 def test_delete_snapmirror_policy_no_records(self):
5642 api_response = fake.NO_RECORDS_RESPONSE_REST
5643 self.mock_object(self.client, 'send_request',
5644 mock.Mock(return_value=api_response))
5646 self.client.delete_snapmirror_policy('fake_policy')
5648 query = {}
5649 query['name'] = 'fake_policy'
5650 query['fields'] = 'uuid,name'
5651 self.client.send_request.assert_called_once_with(
5652 '/snapmirror/policies', 'get', query=query)
5654 def test_delete_vserver_one_volume(self):
5655 self.mock_object(self.client, 'get_vserver_info',
5656 mock.Mock(return_value=fake.VSERVER_INFO))
5657 self.mock_object(self.client, '_get_unique_svm_by_name',
5658 mock.Mock(return_value=fake.FAKE_UUID))
5659 self.mock_object(self.client, 'get_vserver_root_volume_name',
5660 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
5661 self.mock_object(self.client, 'get_vserver_volume_count',
5662 mock.Mock(return_value=1))
5663 self.mock_object(self.client, 'send_request')
5664 self.mock_object(self.client, 'offline_volume')
5665 self.mock_object(self.client, 'delete_volume')
5666 self.mock_object(self.client, '_terminate_vserver_services')
5668 self.client.delete_vserver(fake.VSERVER_NAME, self.client,
5669 fake.CIFS_SECURITY_SERVICE)
5671 self.client.offline_volume.assert_called_with(fake.ROOT_VOLUME_NAME)
5672 self.client.delete_volume.assert_called_with(fake.ROOT_VOLUME_NAME)
5673 self.client._terminate_vserver_services(
5674 fake.VSERVER_NAME, self.client, fake.CIFS_SECURITY_SERVICE)
5676 svm_uuid = fake.FAKE_UUID
5677 self.client.send_request.assert_has_calls([
5678 mock.call(f'/svm/svms/{svm_uuid}', 'delete')])
5680 def test_delete_vserver_one_volume_already_offline(self):
5682 self.mock_object(self.client,
5683 'get_vserver_info',
5684 mock.Mock(return_value=fake.VSERVER_INFO))
5685 self.mock_object(self.client,
5686 '_get_unique_svm_by_name',
5687 mock.Mock(return_value=fake.FAKE_UUID))
5688 self.mock_object(self.client,
5689 'get_vserver_root_volume_name',
5690 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
5691 self.mock_object(self.client,
5692 'get_vserver_volume_count',
5693 mock.Mock(return_value=1))
5694 self.mock_object(self.client,
5695 'offline_volume',
5696 self._mock_api_error(
5697 code=netapp_api.EREST_ENTRY_NOT_FOUND))
5698 self.mock_object(self.client, 'send_request')
5699 self.mock_object(self.client, 'delete_volume')
5701 self.client.delete_vserver(fake.VSERVER_NAME,
5702 self.client)
5704 self.client.offline_volume.assert_called_with(
5705 fake.ROOT_VOLUME_NAME)
5706 self.client.delete_volume.assert_called_with(
5707 fake.ROOT_VOLUME_NAME)
5709 svm_uuid = fake.FAKE_UUID
5710 self.client.send_request.assert_has_calls([
5711 mock.call(f'/svm/svms/{svm_uuid}', 'delete')])
5712 self.assertEqual(1, client_cmode_rest.LOG.error.call_count)
5714 def test_delete_vserver_one_volume_api_error(self):
5716 self.mock_object(self.client,
5717 'get_vserver_info',
5718 mock.Mock(return_value=fake.VSERVER_INFO))
5719 self.mock_object(self.client,
5720 '_get_unique_svm_by_name',
5721 mock.Mock(return_value=fake.FAKE_UUID))
5722 self.mock_object(self.client,
5723 'get_vserver_root_volume_name',
5724 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
5725 self.mock_object(self.client, 'send_request')
5726 self.mock_object(self.client,
5727 'get_vserver_volume_count',
5728 mock.Mock(return_value=1))
5729 self.mock_object(self.client,
5730 'offline_volume',
5731 self._mock_api_error())
5732 self.mock_object(self.client, 'delete_volume')
5734 self.assertRaises(netapp_api.api.NaApiError,
5735 self.client.delete_vserver,
5736 fake.VSERVER_NAME,
5737 self.client)
5739 def test_delete_vserver_multiple_volumes(self):
5741 self.mock_object(self.client,
5742 'get_vserver_info',
5743 mock.Mock(return_value=fake.VSERVER_INFO))
5744 self.mock_object(self.client,
5745 '_get_unique_svm_by_name',
5746 mock.Mock(return_value=fake.FAKE_UUID))
5747 self.mock_object(self.client,
5748 'get_vserver_root_volume_name',
5749 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
5750 self.mock_object(self.client,
5751 'get_vserver_volume_count',
5752 mock.Mock(return_value=2))
5754 self.assertRaises(exception.NetAppException,
5755 self.client.delete_vserver,
5756 fake.VSERVER_NAME,
5757 self.client)
5759 def test_delete_vserver_not_found(self):
5761 self.mock_object(self.client,
5762 'get_vserver_info',
5763 mock.Mock(return_value=None))
5764 self.mock_object(self.client,
5765 '_get_unique_svm_by_name',
5766 mock.Mock(return_value=fake.FAKE_UUID))
5768 self.client.delete_vserver(fake.VSERVER_NAME,
5769 self.client)
5771 self.assertEqual(1, client_cmode_rest.LOG.error.call_count)
5773 def test_get_vserver_volume_count(self):
5774 fake_response = fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE
5775 mock_request = self.mock_object(self.client, 'send_request',
5776 mock.Mock(return_value=fake_response))
5777 response = self.client.get_vserver_volume_count()
5779 self.assertEqual(response, 10)
5780 query = {'return_records': 'false'}
5781 mock_request.assert_called_once_with(
5782 '/storage/volumes', 'get', query=query)
5784 def test__terminate_vserver_services(self):
5786 fake_uuid = fake.FAKE_UUID
5788 self.mock_object(self.client, 'send_request')
5789 self.mock_object(self.client, 'disable_kerberos')
5790 self.mock_object(self.client, '_get_unique_svm_by_name',
5791 mock.Mock(return_value=fake_uuid))
5793 security_services = [
5794 copy.deepcopy(fake.CIFS_SECURITY_SERVICE),
5795 copy.deepcopy(fake.KERBEROS_SECURITY_SERVICE)
5796 ]
5797 self.client._terminate_vserver_services(
5798 fake.VSERVER_NAME, self.client, security_services)
5800 cifs_server_delete_body = {
5801 'ad_domain.password': security_services[0]['password'],
5802 'ad_domain.user': security_services[0]['user'],
5803 }
5804 self.client.send_request.assert_called_once_with(
5805 f'/protocols/cifs/services/{fake_uuid}', 'delete',
5806 body=cifs_server_delete_body)
5807 self.client.disable_kerberos.assert_called_once_with(
5808 security_services[1])
5810 def test_terminate_vserver_services_cifs_not_found(self):
5812 fake_uuid = fake.FAKE_UUID
5814 self.mock_object(
5815 self.client, 'send_request',
5816 self._mock_api_error(code=netapp_api.EREST_ENTRY_NOT_FOUND))
5817 self.mock_object(self.client, '_get_unique_svm_by_name',
5818 mock.Mock(return_value=fake_uuid))
5820 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
5821 self.client._terminate_vserver_services(fake.VSERVER_NAME,
5822 self.client,
5823 [security_service])
5825 cifs_server_delete_body = {
5826 'ad_domain.password': security_service['password'],
5827 'ad_domain.user': security_service['user'],
5828 }
5829 self.client.send_request.assert_called_once_with(
5830 f'/protocols/cifs/services/{fake_uuid}', 'delete',
5831 body=cifs_server_delete_body)
5832 self.assertEqual(1, client_cmode_rest.LOG.error.call_count)
5834 def test_terminate_vserver_services_api_error(self):
5836 fake_uuid = fake.FAKE_UUID
5837 side_effects = [netapp_api.api.NaApiError(code='fake'), None]
5839 self.mock_object(self.client,
5840 'send_request',
5841 mock.Mock(side_effect=side_effects))
5842 self.mock_object(self.client, '_get_unique_svm_by_name',
5843 mock.Mock(return_value=fake_uuid))
5845 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
5846 self.client._terminate_vserver_services(fake.VSERVER_NAME,
5847 self.client,
5848 [security_service])
5850 cifs_server_delete_body = {
5851 'ad_domain.password': security_service['password'],
5852 'ad_domain.user': security_service['user'],
5853 }
5854 cifs_server_delete_force_body = {
5855 'ad_domain.password': security_service['password'],
5856 'ad_domain.user': security_service['user'],
5857 'force': True
5858 }
5860 self.client.send_request.assert_has_calls([
5861 mock.call(f'/protocols/cifs/services/{fake_uuid}', 'delete',
5862 body=cifs_server_delete_body),
5863 mock.call(f'/protocols/cifs/services/{fake_uuid}', 'delete',
5864 body=cifs_server_delete_force_body)])
5865 self.assertEqual(0, client_cmode_rest.LOG.error.call_count)
5867 def test_disable_kerberos(self):
5868 fake_api_response = fake.NFS_LIFS_REST
5869 api_error = self._mock_api_error(
5870 code=netapp_api.EREST_KERBEROS_IS_ENABLED_DISABLED)
5871 self.mock_object(self.client, 'get_network_interfaces',
5872 mock.Mock(return_value=fake_api_response))
5873 self.mock_object(
5874 self.client, 'send_request',
5875 mock.Mock(side_effect=[None, api_error, None]))
5877 self.client.disable_kerberos(fake.KERBEROS_SECURITY_SERVICE)
5879 kerberos_config_modify_body = {
5880 'password': fake.KERBEROS_SECURITY_SERVICE['password'],
5881 'user': fake.KERBEROS_SECURITY_SERVICE['user'],
5882 'interface.name': fake.LIF_NAME,
5883 'enabled': False,
5884 }
5886 self.client.send_request.assert_has_calls([
5887 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_1',
5888 'patch', body=kerberos_config_modify_body),
5889 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_2',
5890 'patch', body=kerberos_config_modify_body),
5891 mock.call('/protocols/nfs/kerberos/interfaces/fake_uuid_3',
5892 'patch', body=kerberos_config_modify_body)
5893 ])
5894 self.client.get_network_interfaces.assert_called_once()
5896 def test_get_vserver_root_volume_name(self):
5897 response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
5898 self.mock_object(self.client, '_get_volume_by_args',
5899 mock.Mock(return_value=response))
5900 self.client.get_vserver_root_volume_name(fake.VSERVER_NAME)
5901 self.client._get_volume_by_args.assert_called_once_with(
5902 vserver=fake.VSERVER_NAME, is_root=True)
5904 def test_ipspace_has_data_vservers(self):
5905 api_response = fake.REST_VSERVER_GET_IPSPACE_NAME_RESPONSE
5906 self.mock_object(self.client,
5907 'send_request',
5908 mock.Mock(return_value=api_response))
5910 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
5912 query = {'ipspace.name': fake.IPSPACE_NAME}
5913 self.client.send_request.assert_has_calls([
5914 mock.call('/svm/svms', 'get', query=query)])
5915 self.assertTrue(result)
5917 def test_ipspace_has_data_vservers_not_supported(self):
5918 self.mock_object(self.client, 'send_request',
5919 mock.Mock(return_value='fake_response'))
5920 self.mock_object(self.client, '_has_records',
5921 mock.Mock(return_value=False))
5923 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
5925 self.assertFalse(result)
5926 query = {'ipspace.name': fake.IPSPACE_NAME}
5927 self.client.send_request.assert_called_once_with(
5928 '/svm/svms', 'get', query=query)
5929 self.client._has_records.assert_called_once_with('fake_response')
5931 def test_ipspace_has_data_vservers_not_found(self):
5932 api_response = fake.NO_RECORDS_RESPONSE_REST
5933 self.mock_object(self.client,
5934 'send_request',
5935 mock.Mock(return_value=api_response))
5937 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
5939 self.assertFalse(result)
5941 def test_delete_vlan(self):
5942 self.mock_object(self.client, 'send_request')
5944 query = {
5945 'vlan.base_port.name': fake.PORT,
5946 'node.name': fake.NODE_NAME,
5947 'vlan.tag': fake.VLAN
5948 }
5950 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
5952 self.client.send_request.assert_has_calls([
5953 mock.call('/network/ethernet/ports/', 'delete', query=query)])
5955 def test_delete_vlan_not_found(self):
5956 self.mock_object(
5957 self.client, 'send_request',
5958 self._mock_api_error(code=netapp_api.EREST_ENTRY_NOT_FOUND))
5960 query = {
5961 'vlan.base_port.name': fake.PORT,
5962 'node.name': fake.NODE_NAME,
5963 'vlan.tag': fake.VLAN
5964 }
5966 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
5968 self.client.send_request.assert_has_calls([
5969 mock.call('/network/ethernet/ports/', 'delete', query=query)])
5970 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
5972 def test_delete_vlan_still_used(self):
5973 self.mock_object(
5974 self.client, 'send_request',
5975 self._mock_api_error(code=netapp_api.EREST_PORT_IN_USE))
5977 query = {
5978 'vlan.base_port.name': fake.PORT,
5979 'node.name': fake.NODE_NAME,
5980 'vlan.tag': fake.VLAN
5981 }
5983 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
5985 self.client.send_request.assert_has_calls([
5986 mock.call('/network/ethernet/ports/', 'delete', query=query)])
5987 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
5989 def test_delete_vlan_api_error(self):
5990 self.mock_object(self.client, 'send_request', self._mock_api_error())
5991 self.assertRaises(exception.NetAppException,
5992 self.client.delete_vlan,
5993 fake.NODE_NAME,
5994 fake.PORT,
5995 fake.VLAN)
5997 @ddt.data(None, fake.IPSPACE_NAME)
5998 def test_svm_migration_start(self, dest_ipspace):
5999 check_only = True
6000 self.mock_object(self.client, 'send_request',
6001 mock.Mock(return_value='fake_migration'))
6003 res = self.client.svm_migration_start(
6004 fake.CLUSTER_NAME, fake.VSERVER_NAME, fake.SHARE_AGGREGATE_NAMES,
6005 dest_ipspace=dest_ipspace, check_only=check_only)
6007 self.assertEqual('fake_migration', res)
6008 expected_body = {
6009 "auto_cutover": False,
6010 "auto_source_cleanup": True,
6011 "check_only": True,
6012 "source": {
6013 "cluster": {"name": fake.CLUSTER_NAME},
6014 "svm": {"name": fake.VSERVER_NAME},
6015 },
6016 "destination": {
6017 "volume_placement": {
6018 "aggregates": fake.SHARE_AGGREGATE_NAMES,
6019 },
6020 },
6021 }
6022 if dest_ipspace is not None:
6023 ipspace_data = {
6024 "ipspace": {
6025 "name": dest_ipspace,
6026 }
6027 }
6028 expected_body["destination"].update(ipspace_data)
6029 self.client.send_request.assert_called_once_with(
6030 '/svm/migrations', 'post', body=expected_body,
6031 wait_on_accepted=False)
6033 def test_get_migration_check_job_state(self):
6034 self.mock_object(self.client, 'get_job',
6035 mock.Mock(return_value='fake_job'))
6037 res = self.client.get_migration_check_job_state(fake.JOB_ID)
6039 self.assertEqual('fake_job', res)
6040 self.client.get_job.assert_called_once_with(fake.JOB_ID)
6042 @ddt.data(netapp_api.api.ENFS_V4_0_ENABLED_MIGRATION_FAILURE,
6043 netapp_api.api.EVSERVER_MIGRATION_TO_NON_AFF_CLUSTER, 'none')
6044 def test_get_migration_check_job_state_raise_error(self, error_code):
6045 e = netapp_api.api.NaApiError(code=error_code)
6046 self.mock_object(self.client, 'get_job', mock.Mock(side_effect=e))
6048 self.assertRaises(
6049 exception.NetAppException,
6050 self.client.get_migration_check_job_state,
6051 fake.JOB_ID)
6053 def test_svm_migrate_complete(self):
6054 self.mock_object(self.client, 'send_request',
6055 mock.Mock(return_value='fake_migration'))
6057 res = self.client.svm_migrate_complete(fake.FAKE_MIGRATION_POST_ID)
6059 self.assertEqual('fake_migration', res)
6060 expected_body = {
6061 "action": "cutover"
6062 }
6063 self.client.send_request.assert_called_once_with(
6064 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'patch',
6065 body=expected_body, wait_on_accepted=False)
6067 def test_svm_migrate_cancel(self):
6068 self.mock_object(self.client, 'send_request',
6069 mock.Mock(return_value='fake_migration'))
6071 res = self.client.svm_migrate_cancel(fake.FAKE_MIGRATION_POST_ID)
6073 self.assertEqual('fake_migration', res)
6074 self.client.send_request.assert_called_once_with(
6075 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'delete',
6076 wait_on_accepted=False)
6078 def test_svm_migration_get(self):
6079 self.mock_object(self.client, 'send_request',
6080 mock.Mock(return_value='fake_migration'))
6082 res = self.client.svm_migration_get(fake.FAKE_MIGRATION_POST_ID)
6084 self.assertEqual('fake_migration', res)
6085 self.client.send_request.assert_called_once_with(
6086 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'get')
6088 def test_svm_migrate_pause(self):
6089 self.mock_object(self.client, 'send_request',
6090 mock.Mock(return_value='fake_migration'))
6092 res = self.client.svm_migrate_pause(fake.FAKE_MIGRATION_POST_ID)
6094 self.assertEqual('fake_migration', res)
6095 expected_body = {
6096 "action": "pause"
6097 }
6098 self.client.send_request.assert_called_once_with(
6099 f'/svm/migrations/{fake.FAKE_MIGRATION_POST_ID}', 'patch',
6100 body=expected_body, wait_on_accepted=False)
6102 def test_delete_network_interface(self):
6103 self.mock_object(self.client, 'disable_network_interface')
6104 self.mock_object(self.client, 'send_request')
6106 self.client.delete_network_interface(fake.VSERVER_NAME, fake.LIF_NAME)
6108 self.client.disable_network_interface.assert_called_once_with(
6109 fake.VSERVER_NAME, fake.LIF_NAME)
6110 expected_query = {
6111 'svm.name': fake.VSERVER_NAME,
6112 'name': fake.LIF_NAME
6113 }
6114 self.client.send_request.assert_called_once_with(
6115 '/network/ip/interfaces', 'delete', query=expected_query)
6117 def test_disable_network_interface(self):
6118 self.mock_object(self.client, 'send_request')
6120 self.client.disable_network_interface(fake.VSERVER_NAME, fake.LIF_NAME)
6122 expected_body = {
6123 'enabled': 'false'
6124 }
6125 expected_query = {
6126 'svm.name': fake.VSERVER_NAME,
6127 'name': fake.LIF_NAME
6128 }
6129 self.client.send_request.assert_called_once_with(
6130 '/network/ip/interfaces', 'patch', body=expected_body,
6131 query=expected_query)
6133 def test__delete_port_and_broadcast_domain(self):
6135 domain = copy.deepcopy(fake.BROADCAST_DOMAIN)
6136 ipspace = copy.deepcopy(fake.GET_IPSPACES_RESPONSE)
6138 query = {'name': domain, 'ipspace.name': ipspace['ipspace']}
6140 response_broadcast = copy.deepcopy(
6141 fake.BROADCAST_DOMAIN_LIST_SIMPLE_RESPONSE_REST)
6142 self.mock_object(self.client,
6143 'send_request',
6144 mock.Mock(side_effect=[response_broadcast, None]))
6146 self.mock_object(self.client,
6147 '_delete_port_by_ipspace_and_broadcast_domain')
6149 self.client._delete_port_and_broadcast_domain(domain, ipspace)
6150 self.client.send_request.assert_has_calls([
6151 mock.call('/network/ethernet/broadcast-domains',
6152 'delete', query=query)])
6154 def test_delete_ipspace(self):
6155 ipspace = copy.deepcopy(fake.IPSPACES[0])
6156 mock_del_brcst = self.mock_object(
6157 self.client, '_delete_port_and_broadcast_domains_for_ipspace')
6158 self.mock_object(self.client, 'ipspace_has_data_vservers',
6159 mock.Mock(return_value=[]))
6160 mock_send_request = self.mock_object(self.client, 'send_request')
6162 query = {'name': fake.IPSPACE_NAME}
6164 self.client.delete_ipspace(ipspace['ipspace'])
6166 mock_del_brcst.assert_called_once_with(fake.IPSPACE_NAME)
6168 mock_send_request.assert_called_once_with(
6169 '/network/ipspaces', 'delete', query=query)
6171 def test_get_ipspaces(self):
6172 expected = copy.deepcopy(fake.GET_IPSPACES_RESPONSE)
6173 sr_responses = [fake.IPSPACE_INFO,
6174 fake.REST_SINGLE_PORT,
6175 fake.SVMS_LIST_SIMPLE_RESPONSE_REST,
6176 fake.FAKE_GET_BROADCAST_DOMAIN]
6177 self.mock_object(self.client, 'send_request',
6178 mock.Mock(side_effect=sr_responses))
6179 self.mock_object(self.client, '_has_records',
6180 mock.Mock(return_value=True))
6181 result = self.client.get_ipspaces(fake.IPSPACE_NAME)
6182 self.assertEqual(expected, result)
6184 def test_get_ipspaces_no_records(self):
6185 api_response = fake.NO_RECORDS_RESPONSE_REST
6186 self.mock_object(self.client, 'send_request',
6187 mock.Mock(return_value=api_response))
6188 result = self.client.get_ipspaces(fake.IPSPACE_NAME)
6189 self.assertEqual([], result)
6191 def test_delete_port_and_broadcast_domains_for_ipspace_not_found(self):
6193 self.mock_object(self.client,
6194 'get_ipspaces',
6195 mock.Mock(return_value=[]))
6196 self.mock_object(self.client, '_delete_port_and_broadcast_domain')
6198 self.client._delete_port_and_broadcast_domains_for_ipspace(
6199 fake.IPSPACE_NAME)
6201 self.client.get_ipspaces.assert_called_once_with(
6202 fake.IPSPACE_NAME)
6203 self.assertFalse(self.client._delete_port_and_broadcast_domain.called)
6205 def test_delete_port_and_broadcast_domains_for_ipspace(self):
6207 self.mock_object(self.client,
6208 'get_ipspaces',
6209 mock.Mock(return_value=fake.IPSPACES[0]))
6210 self.mock_object(self.client, '_delete_port_and_broadcast_domain')
6212 self.client._delete_port_and_broadcast_domains_for_ipspace(
6213 fake.IPSPACE_NAME)
6215 self.client.get_ipspaces.assert_called_once_with(
6216 fake.IPSPACE_NAME)
6217 self.client._delete_port_and_broadcast_domain.assert_called_once_with(
6218 fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACES[0])
6220 @ddt.data(('10.10.10.0/24', '10.10.10.1', False),
6221 ('fc00::/7', 'fe80::1', False),
6222 ('0.0.0.0/0', '10.10.10.1', True),
6223 ('::/0', 'fe80::1', True))
6224 @ddt.unpack
6225 def test_create_route(self, subnet, gateway, omit_destination):
6227 address = None
6228 netmask = None
6229 destination = None if omit_destination else subnet
6230 if not destination:
6231 if netutils.is_valid_ipv6(destination): 6231 ↛ 6232line 6231 didn't jump to line 6232 because the condition on line 6231 was never true
6232 destination = '::/0'
6233 else:
6234 destination = '0.0.0.0/0'
6236 if '/' in destination: 6236 ↛ 6239line 6236 didn't jump to line 6239 because the condition on line 6236 was always true
6237 address, netmask = destination.split('/')
6238 else:
6239 address = destination
6241 body = {
6242 'destination.address': address,
6243 'gateway': gateway,
6244 }
6246 if netmask: 6246 ↛ 6249line 6246 didn't jump to line 6249 because the condition on line 6246 was always true
6247 body['destination.netmask'] = netmask
6249 self.mock_object(self.client, 'send_request')
6251 self.client.create_route(gateway, destination=destination)
6253 self.client.send_request.assert_called_once_with(
6254 '/network/ip/routes', 'post', body=body)
6256 def test_create_route_duplicate(self):
6257 self.mock_object(client_cmode_rest.LOG, 'debug')
6258 self.mock_object(
6259 self.client, 'send_request',
6260 self._mock_api_error(code=netapp_api.EREST_DUPLICATE_ROUTE))
6262 self.client.create_route(fake.GATEWAY, destination=fake.SUBNET)
6264 body = {
6265 'destination.address': fake.SUBNET[:-3],
6266 'gateway': fake.GATEWAY,
6267 'destination.netmask': fake.SUBNET[-2:],
6268 }
6269 self.client.send_request.assert_called_once_with(
6270 '/network/ip/routes', 'post', body=body)
6271 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
6273 def test_create_route_api_error(self):
6274 self.mock_object(client_cmode_rest.LOG, 'debug')
6275 self.mock_object(self.client, 'send_request', self._mock_api_error())
6277 body = {
6278 'destination.address': fake.SUBNET[:-3],
6279 'gateway': fake.GATEWAY,
6280 'destination.netmask': fake.SUBNET[-2:],
6281 }
6282 self.assertRaises(exception.NetAppException,
6283 self.client.create_route,
6284 fake.GATEWAY, destination=fake.SUBNET)
6285 self.client.send_request.assert_called_once_with(
6286 '/network/ip/routes', 'post', body=body)
6288 def test_create_route_without_gateway(self):
6289 self.mock_object(self.client, 'send_request')
6290 self.client.create_route(None, destination=fake.SUBNET)
6291 self.assertFalse(self.client.send_request.called)
6293 def test_network_interface_exists(self):
6294 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE
6295 self.mock_object(self.client, 'send_request',
6296 mock.Mock(return_value=api_response))
6297 result = self.client.network_interface_exists(
6298 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS,
6299 fake.NETMASK, fake.VLAN)
6300 query = {
6301 'ip.address': fake.IP_ADDRESS,
6302 'location.home_node.name': fake.NODE_NAME,
6303 'location.home_port.name': f'{fake.PORT}-{fake.VLAN}',
6304 'ip.netmask': fake.NETMASK,
6305 'svm.name': fake.VSERVER_NAME,
6306 'fields': 'name',
6307 }
6308 self.client.send_request.assert_called_once_with(
6309 '/network/ip/interfaces', 'get', query=query)
6310 self.assertTrue(result)
6312 def test_modify_active_directory_security_service(self):
6313 svm_uuid = fake.FAKE_UUID
6314 user_records = fake.FAKE_CIFS_LOCAL_USER.get('records')[0]
6315 sid = user_records.get('sid')
6316 self.mock_object(self.client, '_get_unique_svm_by_name',
6317 mock.Mock(return_value=svm_uuid))
6318 self.mock_object(self.client, 'send_request',
6319 mock.Mock(side_effect=[user_records,
6320 None, None]))
6321 self.mock_object(self.client, 'remove_preferred_dcs')
6322 self.mock_object(self.client, 'set_preferred_dc')
6323 new_security_service = {
6324 'user': 'new_user',
6325 'password': 'new_password',
6326 'server': 'fake_server'
6327 }
6329 current_security_service = {
6330 'server': 'fake_current_server'
6331 }
6332 keys = {'user', 'password', 'server'}
6334 self.client.modify_active_directory_security_service(
6335 fake.VSERVER_NAME, keys, new_security_service,
6336 current_security_service)
6338 self.client.send_request.assert_has_calls([
6339 mock.call(f'/protocols/cifs/local-users/{svm_uuid}', 'get'),
6340 mock.call(f'/protocols/cifs/local-users/{svm_uuid}/{sid}', 'patch',
6341 query={'password': new_security_service['password']}),
6342 mock.call(f'/protocols/cifs/local-users/{svm_uuid}/{sid}', 'patch',
6343 query={'name': new_security_service['user']})
6344 ])
6346 @ddt.data(True, False)
6347 def test__create_vserver(self, logical_space_reporting):
6348 mock_sr = self.mock_object(self.client, 'send_request')
6349 self.mock_object(self.client, '_get_unique_svm_by_name',
6350 mock.Mock(return_value=fake.FAKE_UUID))
6351 body_post = {
6352 'name': fake.VSERVER_NAME,
6353 'nsswitch.namemap': fake.FAKE_SERVER_SWITCH_NAME,
6354 'subtype': fake.FAKE_SUBTYPE,
6355 'ipspace.name': fake.IPSPACE_NAME,
6356 'aggregates': [{
6357 'name': fake.SHARE_AGGREGATE_NAME
6358 }],
6359 }
6361 if logical_space_reporting:
6362 body_post.update({
6363 'is_space_reporting_logical': 'true',
6364 'is_space_enforcement_logical': 'true',
6365 })
6366 else:
6367 body_post.update({
6368 'is_space_reporting_logical': 'false',
6369 'is_space_enforcement_logical': 'false',
6370 })
6372 body_patch = {
6373 'retention_period': fake.DELETE_RETENTION_HOURS,
6374 }
6376 self.client._create_vserver(
6377 fake.VSERVER_NAME,
6378 [fake.SHARE_AGGREGATE_NAME],
6379 fake.IPSPACE_NAME,
6380 fake.DELETE_RETENTION_HOURS,
6381 fake.FAKE_SERVER_SWITCH_NAME,
6382 fake.FAKE_SUBTYPE,
6383 logical_space_reporting=logical_space_reporting)
6385 mock_sr.assert_has_calls([
6386 mock.call('/svm/svms', 'post', body=body_post),
6387 mock.call(f'/svm/svms/{fake.FAKE_UUID}', 'patch', body=body_patch)
6388 ])
6390 @ddt.data(0, 65535, 270000)
6391 def test__create_vserver_delete_retention_hours(self,
6392 delete_retention_hours):
6393 mock_sr = self.mock_object(self.client, 'send_request')
6394 self.mock_object(self.client, '_get_unique_svm_by_name',
6395 mock.Mock(return_value=fake.FAKE_UUID))
6396 body_post = {
6397 'name': fake.VSERVER_NAME,
6398 'nsswitch.namemap': fake.FAKE_SERVER_SWITCH_NAME,
6399 'subtype': fake.FAKE_SUBTYPE,
6400 'ipspace.name': fake.IPSPACE_NAME,
6401 'is_space_reporting_logical': 'false',
6402 'is_space_enforcement_logical': 'false',
6403 'aggregates': [{
6404 'name': fake.SHARE_AGGREGATE_NAME
6405 }],
6406 }
6408 body_patch = {
6409 'retention_period': delete_retention_hours,
6410 }
6412 self.client._create_vserver(
6413 fake.VSERVER_NAME,
6414 [fake.SHARE_AGGREGATE_NAME],
6415 fake.IPSPACE_NAME,
6416 delete_retention_hours,
6417 fake.FAKE_SERVER_SWITCH_NAME,
6418 fake.FAKE_SUBTYPE)
6420 mock_sr.assert_has_calls([
6421 mock.call('/svm/svms', 'post', body=body_post),
6422 mock.call(f'/svm/svms/{fake.FAKE_UUID}', 'patch', body=body_patch)
6423 ])
6425 def test_create_barbican_kms_config_for_specified_vserver(self):
6426 mock_sr = self.mock_object(self.client, 'send_request')
6427 body = {
6428 'svm.name': fake.VSERVER_NAME,
6429 'configuration.name': fake.FAKE_CONFIG_NAME,
6430 'key_id': fake.FAKE_KEY_ID,
6431 'keystone_url': fake.FAKE_KEYSTONE_URL,
6432 'application_cred_id': fake.FAKE_APPLICATION_CRED_ID,
6433 'application_cred_secret': fake.FAKE_APPLICATION_CRED_SECRET,
6434 }
6436 self.client.create_barbican_kms_config_for_specified_vserver(
6437 fake.VSERVER_NAME,
6438 fake.FAKE_CONFIG_NAME,
6439 fake.FAKE_KEY_ID,
6440 fake.FAKE_KEYSTONE_URL,
6441 fake.FAKE_APPLICATION_CRED_ID,
6442 fake.FAKE_APPLICATION_CRED_SECRET)
6444 mock_sr.assert_called_once_with('/security/barbican-kms', 'post',
6445 body=body)
6447 def test_get_key_store_config_uuid(self):
6448 fake_query = {
6449 'configuration.name': fake.FAKE_CONFIG_NAME
6450 }
6452 self.mock_object(
6453 self.client, 'send_request', mock.Mock(
6454 return_value=fake.KEYSTORE_SIMPLE_RESPONSE_REST))
6456 actual_result = self.client.get_key_store_config_uuid(
6457 fake.FAKE_CONFIG_NAME)
6459 self.client.send_request.assert_called_once_with(
6460 '/security/key-stores', 'get', query=fake_query)
6462 expected_result = (
6463 fake.KEYSTORE_SIMPLE_RESPONSE_REST[
6464 'records'][0]['configuration']['uuid'])
6465 self.assertEqual(expected_result, actual_result)
6467 def test_get_key_store_config_uuid_no_response(self):
6469 self.mock_object(
6470 self.client, 'send_request', mock.Mock(
6471 return_value={}))
6473 actual_result = self.client.get_key_store_config_uuid(
6474 fake.FAKE_CONFIG_NAME)
6476 self.assertIsNone(actual_result)
6478 def test_enable_key_store_config(self):
6479 config_uuid = fake.FAKE_CONFIG_UUID
6480 mock_sr = self.mock_object(self.client, 'send_request')
6481 self.client.enable_key_store_config(config_uuid)
6482 body = {
6483 'enabled': True,
6484 }
6486 mock_sr.assert_called_once_with(
6487 f'/security/key-stores/{config_uuid}', 'patch', body=body)
6489 @ddt.data((f'/name-services/dns/{fake.FAKE_UUID}', 'patch',
6490 ['fake_domain'], ['fake_ip']),
6491 (f'/name-services/dns/{fake.FAKE_UUID}', 'delete', [], []),
6492 ('/name-services/dns', 'post', ['fake_domain'], ['fake_ip']))
6493 @ddt.unpack
6494 def test_update_dns_configuration_all_operations(self, endpoint,
6495 operation, domains, ips):
6496 return_value = fake.FAKE_DNS_CONFIG if operation != 'post' else {}
6497 self.mock_object(self.client, 'get_dns_config',
6498 mock.Mock(return_value=return_value))
6499 self.mock_object(self.client, '_get_unique_svm_by_name',
6500 mock.Mock(return_value=fake.FAKE_UUID))
6501 mock_sr = self.mock_object(self.client, 'send_request')
6502 body = {
6503 'domains': domains,
6504 'servers': ips
6505 }
6506 empty_dns_config = (not body['domains'] and not body['servers'])
6507 if empty_dns_config:
6508 body = {}
6509 self.client.update_dns_configuration(ips, domains)
6510 mock_sr.assert_called_once_with(endpoint, operation, body)
6512 @ddt.data(True, False)
6513 def test_delete_snapshot(self, ignore_owners):
6514 volume_id = fake.VOLUME.get('uuid')
6515 self.mock_object(self.client, '_get_volume_by_args',
6516 mock.Mock(return_value=fake.VOLUME))
6517 response = fake.SNAPSHOTS_REST_RESPONSE
6518 snapshot_id = response.get('records')[0].get('uuid')
6519 mock_sr = self.mock_object(self.client, 'send_request',
6520 mock.Mock(return_value=response))
6521 self.mock_object(self.client, '_has_records',
6522 mock.Mock(return_value=True))
6523 query = {
6524 'name': fake.SNAPSHOT_NAME,
6525 'fields': 'uuid'
6526 }
6527 calls = [mock.call(f'/storage/volumes/{volume_id}/snapshots', 'get',
6528 query=query)]
6529 if ignore_owners:
6530 query_cli = {
6531 'vserver': self.client.vserver,
6532 'volume': fake.VOLUME_NAMES[0],
6533 'snapshot': fake.SNAPSHOT_NAME,
6534 'ignore-owners': 'true'
6535 }
6536 calls.append(mock.call('/private/cli/snapshot', 'delete',
6537 query=query_cli))
6538 else:
6539 calls.append(mock.call(f'/storage/volumes/{volume_id}/'
6540 f'snapshots/{snapshot_id}', 'delete'))
6542 self.client.delete_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME,
6543 ignore_owners)
6544 mock_sr.assert_has_calls(calls)
6546 def test_soft_delete_snapshot(self):
6548 mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot')
6549 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
6551 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
6553 mock_delete_snapshot.assert_called_once_with(
6554 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
6555 self.assertFalse(mock_rename_snapshot.called)
6557 def test_volume_has_luns(self):
6558 mock_sr = self.mock_object(self.client, 'send_request')
6559 self.mock_object(self.client, '_has_records',
6560 mock.Mock(return_value=True))
6561 result = self.client.volume_has_luns(fake.VOLUME_NAMES[0])
6562 query = {
6563 'location.volume.name': fake.VOLUME_NAMES[0],
6564 }
6565 mock_sr.assert_called_once_with('/storage/luns/', 'get', query=query)
6566 self.assertTrue(result)
6568 @ddt.data(fake.VOLUME_JUNCTION_PATH, '')
6569 def test_volume_has_junctioned_volumes(self, junction_path):
6570 mock_sr = self.mock_object(self.client, 'send_request')
6571 return_records = True if junction_path else False
6572 self.mock_object(self.client, '_has_records',
6573 mock.Mock(return_value=return_records))
6574 result = self.client.volume_has_junctioned_volumes(junction_path)
6575 if junction_path:
6576 query = {
6577 'nas.path': junction_path + '/*',
6578 }
6580 mock_sr.assert_called_once_with('/storage/volumes/', 'get',
6581 query=query)
6582 self.assertTrue(result)
6583 else:
6584 self.assertFalse(result)
6586 @ddt.data(fake.VOLUME_JUNCTION_PATH, '')
6587 def test_get_volume_at_junction_path(self, junction_path):
6588 response = fake.VOLUME_LIST_SIMPLE_RESPONSE_REST
6589 return_records = True if junction_path else False
6590 mock_sr = self.mock_object(self.client, 'send_request',
6591 mock.Mock(return_value=response))
6592 self.mock_object(self.client, '_has_records',
6593 mock.Mock(return_value=return_records))
6594 query = {
6595 'nas.path': junction_path,
6596 'fields': 'name'
6597 }
6599 result = self.client.get_volume_at_junction_path(junction_path)
6600 expected = {
6601 'name': response.get('records')[0].get('name')
6602 }
6604 if junction_path:
6605 mock_sr.assert_called_once_with('/storage/volumes/', 'get',
6606 query=query)
6607 self.assertEqual(expected, result)
6608 else:
6609 self.assertIsNone(result)
6611 def test_get_aggregate_for_volume(self):
6612 response = fake.FAKE_SVM_AGGREGATES.get('records')[0]
6613 mock_sr = self.mock_object(self.client, 'send_request',
6614 mock.Mock(return_value=response))
6615 result = self.client.get_aggregate_for_volume(fake.VOLUME_NAMES[0])
6616 expected = fake.SHARE_AGGREGATE_NAMES_LIST
6617 query = {
6618 'name': fake.VOLUME_NAMES[0],
6619 'fields': 'aggregates'
6620 }
6621 mock_sr.assert_called_once_with('/storage/volumes/', 'get',
6622 query=query)
6623 self.assertEqual(expected, result)
6625 def test_get_volume_to_manage(self):
6626 response = fake.FAKE_VOLUME_MANAGE
6627 mock_sr = self.mock_object(self.client, 'send_request',
6628 mock.Mock(return_value=response))
6629 self.mock_object(self.client, '_has_records',
6630 mock.Mock(return_value=True))
6631 expected = {
6632 'aggregate': fake.SHARE_AGGREGATE_NAME,
6633 'aggr-list': [],
6634 'junction-path': fake.VOLUME_JUNCTION_PATH,
6635 'name': fake.VOLUME_NAMES[0],
6636 'type': 'fake_type',
6637 'style': 'flex',
6638 'owning-vserver-name': fake.VSERVER_NAME,
6639 'size': fake.SHARE_SIZE,
6640 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME
6641 }
6643 result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME,
6644 fake.VOLUME_NAMES[0])
6645 query = {
6646 'name': fake.VOLUME_NAMES[0],
6647 'fields': 'name,aggregates.name,nas.path,name,type,style,'
6648 'svm.name,qos.policy.name,space.size',
6649 'aggregates.name': fake.SHARE_AGGREGATE_NAME
6650 }
6651 mock_sr.assert_called_once_with('/storage/volumes', 'get',
6652 query=query)
6653 self.assertEqual(expected, result)
6655 def test_get_cifs_share_access(self):
6656 response = fake.FAKE_CIFS_RECORDS
6657 mock_sr = self.mock_object(self.client, 'send_request',
6658 mock.Mock(return_value=response))
6659 query = {
6660 'name': fake.SHARE_NAME
6661 }
6662 query_acls = {
6663 'fields': 'user_or_group,permission'
6664 }
6665 expected = {
6666 'Everyone': 'full_control',
6667 'root': 'no_access'
6668 }
6669 result = self.client.get_cifs_share_access(fake.SHARE_NAME)
6670 svm_uuid = response.get('records')[0].get('svm').get('uuid')
6671 mock_sr.assert_has_calls([
6672 mock.call('/protocols/cifs/shares', 'get', query=query),
6673 mock.call(f'/protocols/cifs/shares/{svm_uuid}/{fake.SHARE_NAME}/'
6674 'acls', 'get', query=query_acls)
6675 ])
6676 self.assertEqual(expected, result)
6678 @ddt.data((netapp_api.EREST_LICENSE_NOT_INSTALLED, False),
6679 (netapp_api.EREST_SNAPSHOT_NOT_SPECIFIED, True))
6680 @ddt.unpack
6681 def test_check_snaprestore_license(self, code, expected):
6682 self.mock_object(self.client, 'send_request',
6683 mock.Mock(side_effect=self._mock_api_error(code)))
6684 result = self.client.check_snaprestore_license()
6685 self.assertEqual(expected, result)
6686 body = {
6687 'restore_to.snapshot.name': ''
6688 }
6689 query = {
6690 'name': '*'
6691 }
6692 self.client.send_request.assert_called_once_with('/storage/volumes',
6693 'patch',
6694 body=body,
6695 query=query)
6697 def test_check_snaprestore_license_error(self):
6698 self.mock_object(self.client, 'send_request')
6699 self.assertRaises(exception.NetAppException,
6700 self.client.check_snaprestore_license)
6702 def test__sort_data_ports_by_speed(self):
6703 ports = fake.FAKE_PORTS
6704 result = self.client._sort_data_ports_by_speed(ports)
6705 expected = [{'speed': '4'},
6706 {'speed': 'auto'},
6707 {'speed': 'undef'},
6708 {'speed': 'fake_speed'},
6709 {'speed': ''}]
6710 self.assertEqual(expected, result)
6712 def test_create_port_and_broadcast_domain(self):
6713 self.mock_object(self.client, '_create_vlan')
6714 self.mock_object(self.client, '_ensure_broadcast_domain_for_port')
6715 res = self.client.create_port_and_broadcast_domain(fake.NODE_NAME,
6716 fake.PORT,
6717 fake.VLAN,
6718 fake.MTU,
6719 fake.IPSPACE_NAME)
6720 expected = f'{fake.PORT}-{fake.VLAN}'
6721 self.assertEqual(expected, res)
6723 @ddt.data(netapp_api.EREST_DUPLICATE_ENTRY, None)
6724 def test__create_vlan(self, code):
6725 self.mock_object(self.client, 'send_request',
6726 mock.Mock(side_effect=self._mock_api_error(code)))
6727 if not code:
6728 self.assertRaises(exception.NetAppException,
6729 self.client._create_vlan,
6730 fake.NODE_NAME,
6731 fake.PORT,
6732 fake.VLAN)
6734 else:
6735 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
6736 body = {
6737 'vlan.base_port.name': fake.PORT,
6738 'node.name': fake.NODE_NAME,
6739 'vlan.tag': fake.VLAN,
6740 'type': 'vlan'
6741 }
6742 self.client.send_request.assert_called_once_with(
6743 '/network/ethernet/ports', 'post', body=body)
6745 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None)
6746 def test_delete_fpolicy_event_error_not_found(self, code):
6747 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
6748 self.mock_object(self.client, '_get_volume_by_args',
6749 mock.Mock(return_value=volume))
6750 self.mock_object(self.client, 'send_request',
6751 mock.Mock(side_effect=self._mock_api_error(code)))
6752 if not code:
6753 self.assertRaises(exception.NetAppException,
6754 self.client.delete_fpolicy_event,
6755 fake.SHARE_NAME, 'fake_event')
6756 else:
6757 self.client.delete_fpolicy_event(fake.SHARE_NAME, 'fake_event')
6758 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
6760 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None)
6761 def test_delete_fpolicy_policy_request_error(self, code):
6762 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
6763 self.mock_object(self.client, '_get_volume_by_args',
6764 mock.Mock(return_value=volume))
6765 self.mock_object(self.client, 'send_request',
6766 mock.Mock(side_effect=self._mock_api_error(code)))
6767 if not code:
6768 self.assertRaises(exception.NetAppException,
6769 self.client.delete_fpolicy_policy,
6770 fake.SHARE_NAME, 'fake_policy')
6771 else:
6772 self.client.delete_fpolicy_policy(fake.SHARE_NAME, 'fake_policy')
6773 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
6775 def test_modify_fpolicy_scope(self):
6776 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
6777 svm_uuid = volume['svm']['uuid']
6778 self.mock_object(self.client, '_get_volume_by_args',
6779 mock.Mock(return_value=volume))
6780 mock_sr = self.mock_object(self.client, 'send_request')
6781 body = {
6782 'name': fake.FPOLICY_POLICY_NAME,
6783 'scope.include_shares': fake.SHARE_NAME,
6784 'scope.include_extension': 'fake_extension',
6785 'scope.exclude_extension': 'fake_extension'
6786 }
6787 self.client.modify_fpolicy_scope(fake.SHARE_NAME,
6788 fake.FPOLICY_POLICY_NAME,
6789 [fake.SHARE_NAME],
6790 ['fake_extension'],
6791 ['fake_extension'])
6792 mock_sr.assert_called_once_with(f'/protocols/fpolicy/{svm_uuid}/'
6793 'policies/', 'patch', body=body)
6795 def test_remove_cifs_share(self):
6796 response = fake.SVMS_LIST_SIMPLE_RESPONSE_REST
6797 svm_id = response.get('records')[0]['uuid']
6798 mock_sr = self.mock_object(self.client, 'send_request',
6799 mock.Mock(return_value=response))
6800 self.client.remove_cifs_share(fake.SHARE_NAME)
6801 query = {
6802 'name': self.client.vserver,
6803 'fields': 'uuid'
6804 }
6805 mock_sr.assert_has_calls([
6806 mock.call('/svm/svms', 'get', query=query),
6807 mock.call(f'/protocols/cifs/shares/{svm_id}'
6808 f'/{fake.SHARE_NAME}', 'delete')])
6810 def test_qos_policy_group_get_error(self):
6811 code = netapp_api.EREST_NOT_AUTHORIZED
6812 self.mock_object(self.client, 'send_request',
6813 mock.Mock(side_effect=self._mock_api_error(code)))
6814 self.assertRaises(exception.NetAppException,
6815 self.client.qos_policy_group_get,
6816 fake.QOS_POLICY_GROUP_NAME)
6818 def test_qos_policy_group_get_not_found(self):
6819 response = fake.NO_RECORDS_RESPONSE_REST
6820 self.mock_object(self.client, 'send_request',
6821 mock.Mock(return_value=response))
6822 self.assertRaises(exception.NetAppException,
6823 self.client.qos_policy_group_get,
6824 fake.QOS_POLICY_GROUP_NAME)
6826 def test_remove_unused_qos_policy_groups_error(self):
6827 res_list = [fake.QOS_POLICY_GROUP_REST, netapp_api.api.NaApiError]
6828 self.mock_object(self.client, 'send_request',
6829 mock.Mock(side_effect=res_list))
6830 self.client.remove_unused_qos_policy_groups()
6831 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
6833 def test_mount_volume_error(self):
6834 volume = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
6835 code = netapp_api.EREST_SNAPMIRROR_INITIALIZING
6836 self.mock_object(self.client, '_get_volume_by_args',
6837 mock.Mock(return_value=volume))
6838 self.mock_object(self.client, 'send_request',
6839 mock.Mock(side_effect=self._mock_api_error(code)))
6840 self.assertRaises(netapp_api.api.NaApiError,
6841 self.client.mount_volume,
6842 fake.VOLUME_NAMES[0])
6844 def test_get_aggregate_for_volume_empty(self):
6845 response = fake.NO_RECORDS_RESPONSE_REST
6846 self.mock_object(self.client, 'send_request',
6847 mock.Mock(return_value=response))
6848 self.assertRaises(exception.NetAppException,
6849 self.client.get_aggregate_for_volume,
6850 fake.VOLUME_NAMES[0])
6852 def test_get_nfs_export_policy_for_volume_empty(self):
6853 response = fake.NO_RECORDS_RESPONSE_REST
6854 self.mock_object(self.client, 'send_request',
6855 mock.Mock(return_value=response))
6856 self.mock_object(self.client, '_has_records',
6857 mock.Mock(return_value=False))
6858 self.assertRaises(exception.NetAppException,
6859 self.client.get_nfs_export_policy_for_volume,
6860 fake.VOLUME_NAMES[0])
6862 def test_get_unique_export_policy_id_empty(self):
6863 response = fake.NO_RECORDS_RESPONSE_REST
6864 self.mock_object(self.client, 'send_request',
6865 mock.Mock(return_value=response))
6866 self.mock_object(self.client, '_has_records',
6867 mock.Mock(return_value=False))
6868 self.assertRaises(exception.NetAppException,
6869 self.client.get_unique_export_policy_id,
6870 fake.FPOLICY_POLICY_NAME)
6872 def test__remove_nfs_export_rules_error(self):
6873 self.mock_object(self.client, 'get_unique_export_policy_id',
6874 mock.Mock(return_value=fake.FAKE_UUID))
6875 self.mock_object(self.client, 'send_request',
6876 mock.Mock(side_effect=self._mock_api_error()))
6877 self.assertRaises(netapp_api.api.NaApiError,
6878 self.client._remove_nfs_export_rules,
6879 fake.FPOLICY_POLICY_NAME,
6880 [1])
6882 def test_get_volume_move_status_error(self):
6883 response = fake.NO_RECORDS_RESPONSE_REST
6884 self.mock_object(self.client, 'send_request',
6885 mock.Mock(return_value=response))
6886 self.mock_object(self.client, '_has_records',
6887 mock.Mock(return_value=False))
6888 self.assertRaises(exception.NetAppException,
6889 self.client.get_volume_move_status,
6890 fake.VOLUME_NAMES[0],
6891 fake.VSERVER_NAME)
6893 def test__set_snapmirror_state_error(self):
6894 self.mock_object(self.client, 'get_snapmirrors',
6895 mock.Mock(return_value=[]))
6896 self.assertRaises(netapp_utils.NetAppDriverException,
6897 self.client._set_snapmirror_state,
6898 'fake_state', 'fake_source_path', 'fake_dest_path',
6899 'fake_source_vserver', 'fake_source_volume',
6900 'fake_dest_vserver', 'fake_dest_volume')
6902 def test__break_snapmirror_error(self):
6903 fake_snapmirror = fake.REST_GET_SNAPMIRRORS_RESPONSE
6904 self.mock_object(self.client, '_get_snapmirrors',
6905 mock.Mock(return_value=fake_snapmirror))
6906 self.mock_object(self.client, 'send_request',
6907 mock.Mock(side_effect=self._mock_api_error()))
6908 self.assertRaises(netapp_api.api.NaApiError,
6909 self.client._break_snapmirror)
6911 def test__resync_snapmirror_no_parameter(self):
6912 mock_snap = self.mock_object(self.client, '_resume_snapmirror')
6913 self.client._resync_snapmirror()
6914 mock_snap.assert_called_once_with(None, None, None, None, None, None)
6916 def test_add_nfs_export_rule_with_rule_created(self):
6917 self.mock_object(self.client, '_get_nfs_export_rule_indices',
6918 mock.Mock(return_value=[1]))
6919 update = self.mock_object(self.client, '_update_nfs_export_rule')
6920 remove = self.mock_object(self.client, '_remove_nfs_export_rules')
6921 self.client.add_nfs_export_rule(fake.FPOLICY_POLICY_NAME,
6922 'fake_client',
6923 True,
6924 'fake_auth')
6925 update.assert_called_once_with(fake.FPOLICY_POLICY_NAME,
6926 'fake_client', True, 1, 'fake_auth')
6927 remove.assert_called_once_with(fake.FPOLICY_POLICY_NAME, [])
6929 def test__update_snapmirror_no_snapmirrors(self):
6930 self.mock_object(self.client, '_get_snapmirrors',
6931 mock.Mock(return_value=[]))
6932 self.assertRaises(netapp_utils.NetAppDriverException,
6933 self.client._update_snapmirror)
6935 @ddt.data((netapp_api.EREST_SNAPMIRROR_NOT_INITIALIZED,
6936 'Another transfer is in progress'),
6937 (None, 'fake'))
6938 @ddt.unpack
6939 def test__update_snapmirror_error(self, code, message):
6940 snapmirrors = fake.REST_GET_SNAPMIRRORS_RESPONSE
6941 self.mock_object(self.client, '_get_snapmirrors',
6942 mock.Mock(return_value=snapmirrors))
6943 self.mock_object(self.client, 'send_request',
6944 mock.Mock(side_effect=self._mock_api_error(code,
6945 message)))
6946 self.assertRaises(netapp_api.api.NaApiError,
6947 self.client._update_snapmirror)
6949 @ddt.data(netapp_api.EREST_DUPLICATE_ENTRY, None)
6950 def test_create_kerberos_realm_error(self, code):
6951 self.mock_object(self.client, 'send_request',
6952 mock.Mock(side_effect=self._mock_api_error(code)))
6953 if code:
6954 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
6955 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
6956 else:
6957 self.assertRaises(exception.NetAppException,
6958 self.client.create_kerberos_realm,
6959 fake.KERBEROS_SECURITY_SERVICE)
6961 def test_configure_kerberos_error(self):
6962 self.mock_object(self.client, 'configure_dns')
6963 self.mock_object(self.client, '_get_kerberos_service_principal_name')
6964 self.mock_object(self.client, 'get_network_interfaces',
6965 mock.Mock(return_value=[]))
6966 self.assertRaises(exception.NetAppException,
6967 self.client.configure_kerberos,
6968 fake.KERBEROS_SECURITY_SERVICE,
6969 fake.VSERVER_NAME)
6971 def test_configure_ldap(self):
6972 mock_ldap = self.mock_object(self.client, '_create_ldap_client')
6973 self.client.configure_ldap(fake.LDAP_AD_SECURITY_SERVICE, 30,
6974 fake.VSERVER_NAME)
6975 mock_ldap.assert_called_once_with(fake.LDAP_AD_SECURITY_SERVICE,
6976 vserver_name=fake.VSERVER_NAME)
6978 def test_configure_active_directory_error(self):
6979 self.mock_object(self.client, 'configure_dns')
6980 self.mock_object(self.client, 'configure_cifs_aes_encryption')
6981 self.mock_object(self.client, 'set_preferred_dc')
6982 self.mock_object(self.client, '_get_cifs_server_name')
6983 self.mock_object(self.client, 'send_request',
6984 mock.Mock(side_effect=self._mock_api_error()))
6985 self.assertRaises(exception.NetAppException,
6986 self.client.configure_active_directory,
6987 fake.LDAP_AD_SECURITY_SERVICE,
6988 fake.VSERVER_NAME,
6989 False)
6991 def test__get_unique_svm_by_name_error(self):
6992 response = fake.NO_RECORDS_RESPONSE_REST
6993 self.mock_object(self.client, 'send_request',
6994 mock.Mock(return_value=response))
6995 self.assertRaises(exception.NetAppException,
6996 self.client._get_unique_svm_by_name,
6997 fake.VSERVER_NAME)
6999 def test_get_ontap_version_scoped(self):
7000 self.client.get_ontap_version = self.original_get_ontap_version
7001 e = netapp_api.api.NaApiError(code=netapp_api.EREST_NOT_AUTHORIZED)
7002 res_list = [e, fake.GET_VERSION_RESPONSE_REST]
7003 version = fake.GET_VERSION_RESPONSE_REST['records'][0]['version']
7004 expected = {
7005 'version': version['full'],
7006 'version-tuple': (9, 11, 1)
7007 }
7008 self.mock_object(self.client, 'send_request',
7009 mock.Mock(side_effect=res_list))
7010 result = self.client.get_ontap_version(self=self.client, cached=False)
7011 self.assertEqual(expected, result)
7013 def test_get_licenses_error(self):
7014 self.mock_object(self.client, 'send_request',
7015 mock.Mock(side_effect=self._mock_api_error()))
7016 self.assertRaises(netapp_api.api.NaApiError,
7017 self.client.get_licenses)
7019 def test__get_volume_by_args_error(self):
7020 res = fake.VOLUME_GET_ITER_RESPONSE_REST_PAGE
7021 self.mock_object(self.client, 'send_request',
7022 mock.Mock(return_value=res))
7023 self.assertRaises(exception.NetAppException,
7024 self.client._get_volume_by_args,
7025 is_root=True)
7027 def test_get_aggregate_no_name(self):
7028 expected = {}
7029 result = self.client.get_aggregate('')
7030 self.assertEqual(expected, result)
7032 def test_get_aggregate_error(self):
7033 self.mock_object(self.client, '_get_aggregates',
7034 mock.Mock(side_effect=self._mock_api_error()))
7035 result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME)
7036 expected = {}
7037 self.assertEqual(expected, result)
7039 def test_get_node_for_aggregate_no_name(self):
7040 result = self.client.get_node_for_aggregate('')
7041 self.assertIsNone(result)
7043 @ddt.data(netapp_api.EREST_NOT_AUTHORIZED, None)
7044 def test_get_node_for_aggregate_error(self, code):
7045 self.mock_object(self.client, '_get_aggregates',
7046 mock.Mock(side_effect=self._mock_api_error(code)))
7047 if code:
7048 r = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
7049 self.assertIsNone(r)
7050 else:
7051 self.assertRaises(netapp_api.api.NaApiError,
7052 self.client.get_node_for_aggregate,
7053 fake.SHARE_AGGREGATE_NAME)
7055 def test_get_vserver_aggregate_capabilities_no_response(self):
7056 response = fake.NO_RECORDS_RESPONSE_REST
7057 self.mock_object(self.client, 'send_request',
7058 mock.Mock(return_value=response))
7059 self.assertRaises(exception.NetAppException,
7060 self.client.get_vserver_aggregate_capacities,
7061 fake.SHARE_AGGREGATE_NAME)
7063 def test_get_vserver_aggregate_capacities_no_aggregate(self):
7064 response = fake.FAKE_AGGREGATES_RESPONSE
7065 share_name = fake.SHARE_AGGREGATE_NAME
7066 self.mock_object(self.client,
7067 'send_request',
7068 mock.Mock(return_value=response))
7069 res = self.client.get_vserver_aggregate_capacities(share_name)
7070 expected = {}
7071 self.assertEqual(expected, res)
7073 def test_rename_nfs_export_policy_error(self):
7074 self.mock_object(self.client, 'send_request')
7075 self.mock_object(self.client, '_has_records',
7076 mock.Mock(return_value=False))
7077 self.assertRaises(exception.NetAppException,
7078 self.client.rename_nfs_export_policy,
7079 'fake_policy_name',
7080 'fake_new_policy_name')
7082 @ddt.data((False, exception.StorageResourceNotFound),
7083 (True, exception.NetAppException))
7084 @ddt.unpack
7085 def test_get_volume_error(self, records, exception):
7086 res = copy.deepcopy(fake.FAKE_VOLUME_MANAGE)
7087 res['num_records'] = 2
7088 self.mock_object(self.client, 'send_request',
7089 mock.Mock(return_value=res))
7090 self.mock_object(self.client, '_has_records',
7091 mock.Mock(return_value=records))
7092 self.assertRaises(exception,
7093 self.client.get_volume,
7094 fake.VOLUME_NAMES[0])
7096 def test_get_volume_no_aggregate(self):
7097 res = copy.deepcopy(fake.FAKE_VOLUME_MANAGE)
7098 res.get('records')[0]['aggregates'] = []
7099 self.mock_object(self.client, 'send_request',
7100 mock.Mock(return_value=res))
7101 fake_volume = res.get('records', [])[0]
7103 expected = {
7104 'aggregate': '',
7105 'aggr-list': [],
7106 'junction-path': fake_volume.get('nas', {}).get('path', ''),
7107 'name': fake_volume.get('name', ''),
7108 'owning-vserver-name': fake_volume.get('svm', {}).get('name', ''),
7109 'type': fake_volume.get('type', ''),
7110 'style': fake_volume.get('style', ''),
7111 'size': fake_volume.get('space', {}).get('size', ''),
7112 'size-used': fake_volume.get('space', {}).get('used', ''),
7113 'qos-policy-group-name': fake_volume.get('qos', {})
7114 .get('policy', {})
7115 .get('name', ''),
7116 'style-extended': fake_volume.get('style', ''),
7117 'snaplock-type': fake_volume.get('snaplock', {}).get('type', '')
7118 }
7119 result = self.client.get_volume(fake.VOLUME_NAMES[0])
7120 self.assertEqual(expected, result)
7122 def test_get_job_state_error(self):
7123 response = {
7124 'records': [fake.JOB_SUCCESSFUL_REST,
7125 fake.JOB_SUCCESSFUL_REST]
7126 }
7127 self.mock_object(self.client, 'send_request',
7128 mock.Mock(return_value=response))
7129 self.mock_object(self.client, '_has_records',
7130 mock.Mock(return_value=True))
7131 self.assertRaises(exception.NetAppException,
7132 self.client.get_job_state,
7133 fake.JOB_ID)
7135 def test_get_volume_efficiency_status_error(self):
7136 self.mock_object(self.client, 'send_request',
7137 mock.Mock(side_effect=self._mock_api_error()))
7138 self.client.get_volume_efficiency_status(fake.VOLUME_NAMES[0])
7139 self.assertEqual(1, client_cmode_rest.LOG.error.call_count)
7141 def test_get_fpolicy_scopes_not_found(self):
7142 self.mock_object(self.client, '_get_volume_by_args',
7143 mock.Mock(side_effect=exception.NetAppException))
7144 result = self.client.get_fpolicy_scopes(fake.SHARE_NAME)
7145 expected = []
7146 self.assertEqual(expected, result)
7148 def test_delete_fpolicy_policy_error(self):
7149 self.mock_object(self.client, '_get_volume_by_args',
7150 mock.Mock(side_effect=exception.NetAppException))
7151 self.mock_object(self.client, 'send_request')
7152 res = self.client.delete_fpolicy_policy(fake.SHARE_NAME,
7153 fake.FPOLICY_POLICY_NAME)
7154 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
7155 self.assertIsNone(res)
7157 def test_delete_fpolicy_event_error(self):
7158 self.mock_object(self.client, '_get_volume_by_args',
7159 mock.Mock(side_effect=exception.NetAppException))
7160 self.mock_object(self.client, 'send_request')
7161 res = self.client.delete_fpolicy_event(fake.SHARE_NAME,
7162 fake.FPOLICY_EVENT_NAME)
7163 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
7164 self.assertIsNone(res)
7166 def test_delete_nfs_export_policy_no_records(self):
7167 response = fake.NO_RECORDS_RESPONSE_REST
7168 self.mock_object(self.client, 'send_request',
7169 mock.Mock(return_value=response))
7170 res = self.client.delete_nfs_export_policy(fake.FPOLICY_POLICY_NAME)
7171 self.assertIsNone(res)
7173 def test_remove_cifs_share_not_found(self):
7174 response = fake.NO_RECORDS_RESPONSE_REST
7175 self.mock_object(self.client, 'send_request',
7176 mock.Mock(return_value=response))
7177 self.assertRaises(exception.NetAppException,
7178 self.client.remove_cifs_share,
7179 fake.SHARE_NAME)
7181 @ddt.data(netapp_api.EREST_ENTRY_NOT_FOUND, None)
7182 def test_remove_cifs_share_error(self, code):
7183 responses = [fake.SVMS_LIST_SIMPLE_RESPONSE_REST,
7184 netapp_api.api.NaApiError(code=code)]
7185 self.mock_object(self.client, 'send_request',
7186 mock.Mock(side_effect=responses))
7187 if not code:
7188 self.assertRaises(netapp_api.api.NaApiError,
7189 self.client.remove_cifs_share,
7190 fake.SHARE_NAME)
7191 else:
7192 result = self.client.remove_cifs_share(fake.SHARE_NAME)
7193 self.assertIsNone(result)
7195 def test_qos_policy_group_does_not_exists(self):
7196 self.mock_object(self.client, 'qos_policy_group_get',
7197 mock.Mock(side_effect=exception.NetAppException))
7198 result = self.client.qos_policy_group_exists(fake.QOS_POLICY_GROUP)
7199 self.assertFalse(result)
7201 def test_qos_policy_group_rename_error(self):
7202 response = fake.NO_RECORDS_RESPONSE_REST
7203 self.mock_object(self.client, 'send_request',
7204 mock.Mock(return_value=response))
7205 self.assertRaises(exception.NetAppException,
7206 self.client.qos_policy_group_rename,
7207 fake.QOS_POLICY_GROUP_NAME,
7208 'fake_new_qos_policy_group_name')
7210 def test_qos_policy_group_rename_same_name(self):
7211 res = self.client.qos_policy_group_rename(fake.QOS_POLICY_GROUP_NAME,
7212 fake.QOS_POLICY_GROUP_NAME)
7213 self.assertIsNone(res)
7215 def test_qos_policy_group_modify_error(self):
7216 response = fake.NO_RECORDS_RESPONSE_REST
7217 self.mock_object(self.client, 'send_request',
7218 mock.Mock(return_value=response))
7219 self.assertRaises(exception.NetAppException,
7220 self.client.qos_policy_group_modify,
7221 fake.QOS_POLICY_GROUP_NAME,
7222 fake.QOS_MAX_THROUGHPUT)
7224 def test_update_kerberos_realm_error(self):
7225 self.mock_object(self.client,
7226 '_get_unique_svm_by_name',
7227 mock.Mock(return_value=fake.FAKE_UUID))
7228 self.mock_object(self.client, 'send_request',
7229 mock.Mock(side_effect=self._mock_api_error()))
7230 self.assertRaises(exception.NetAppException,
7231 self.client.update_kerberos_realm,
7232 fake.KERBEROS_SECURITY_SERVICE)
7234 @ddt.data(('fake_domain', 'fake_server'), (None, None))
7235 @ddt.unpack
7236 def test_modify_ldap_error(self, domain, server):
7237 security_service = {
7238 'domain': domain,
7239 'server': server,
7240 'user': 'fake_user',
7241 'ou': 'fake_ou',
7242 'dns_ip': 'fake_ip',
7243 'password': 'fake_password'
7244 }
7245 self.mock_object(self.client, '_get_unique_svm_by_name',
7246 mock.Mock(return_value=fake.FAKE_UUID))
7247 self.mock_object(self.client, 'send_request')
7248 self.assertRaises(exception.NetAppException,
7249 self.client.modify_ldap,
7250 security_service,
7251 fake.LDAP_AD_SECURITY_SERVICE)
7253 def test_update_dns_configuration_error(self):
7254 self.mock_object(self.client, '_get_unique_svm_by_name',
7255 mock.Mock(return_value=fake.FAKE_UUID))
7256 dns_config = {
7257 'domains': [fake.KERBEROS_SECURITY_SERVICE['domain']],
7258 'dns-ips': [fake.KERBEROS_SECURITY_SERVICE['dns_ip']],
7259 }
7260 self.mock_object(self.client, 'get_dns_config',
7261 mock.Mock(return_value=dns_config))
7262 self.mock_object(self.client, 'send_request',
7263 mock.Mock(side_effect=self._mock_api_error()))
7264 self.assertRaises(exception.NetAppException,
7265 self.client.update_dns_configuration,
7266 ['fake_ips'], ['fake_domain'])
7268 def test_remove_preferred_dcs_error(self):
7269 fake_response = [fake.PREFERRED_DC_REST,
7270 netapp_api.api.NaApiError]
7271 self.mock_object(self.client, 'send_request',
7272 mock.Mock(side_effect=fake_response))
7273 self.assertRaises(exception.NetAppException,
7274 self.client.remove_preferred_dcs,
7275 fake.LDAP_AD_SECURITY_SERVICE,
7276 fake.FAKE_UUID)
7278 def test_set_preferred_dc_error(self):
7279 security = copy.deepcopy(fake.LDAP_AD_SECURITY_SERVICE)
7280 security['server'] = 'fake_server'
7281 self.mock_object(self.client, '_get_unique_svm_by_name',
7282 mock.Mock(return_value=fake.FAKE_UUID))
7283 self.mock_object(self.client, 'send_request',
7284 mock.Mock(side_effect=self._mock_api_error()))
7285 self.assertRaises(exception.NetAppException,
7286 self.client.set_preferred_dc,
7287 security,
7288 fake.VSERVER_NAME)
7290 def test_set_preferred_dc_no_server(self):
7291 result = self.client.set_preferred_dc(fake.LDAP_AD_SECURITY_SERVICE,
7292 fake.VSERVER_NAME)
7293 self.assertIsNone(result)
7295 def test__get_svm_peer_uuid_error(self):
7296 response = fake.NO_RECORDS_RESPONSE_REST
7297 self.mock_object(self.client, 'send_request',
7298 mock.Mock(return_value=response))
7299 self.assertRaises(exception.NetAppException,
7300 self.client._get_svm_peer_uuid,
7301 fake.VSERVER_NAME,
7302 fake.VSERVER_PEER_NAME)
7304 def test_create_vserver_dp_destination(self):
7305 mock_vserver = self.mock_object(self.client, '_create_vserver')
7306 self.client.create_vserver_dp_destination(fake.VSERVER_NAME,
7307 fake.FAKE_AGGR_LIST,
7308 fake.IPSPACE_NAME,
7309 fake.DELETE_RETENTION_HOURS)
7310 mock_vserver.assert_called_once_with(fake.VSERVER_NAME,
7311 fake.FAKE_AGGR_LIST,
7312 fake.IPSPACE_NAME,
7313 fake.DELETE_RETENTION_HOURS,
7314 subtype='dp_destination')
7316 @ddt.data(':', '.')
7317 def test_create_route_no_destination(self, gateway):
7318 mock_sr = self.mock_object(self.client, 'send_request')
7319 body = {
7320 'gateway': gateway,
7321 'destination.address': ('::' if netutils.is_valid_ipv6(gateway)
7322 else '0.0.0.0'),
7323 'destination.netmask': '0'
7324 }
7325 self.client.create_route(gateway)
7326 mock_sr.assert_called_once_with('/network/ip/routes', 'post',
7327 body=body)
7329 def test_list_root_aggregates(self):
7330 return_value = fake.FAKE_ROOT_AGGREGATES_RESPONSE
7331 self.mock_object(self.client, 'send_request',
7332 mock.Mock(return_value=return_value))
7334 result = self.client.list_root_aggregates()
7336 expected = [fake.SHARE_AGGREGATE_NAME]
7337 self.assertEqual(expected, result)
7339 @ddt.data(("fake_server", "fake_domain"), (None, None))
7340 @ddt.unpack
7341 def test__create_ldap_client_error(self, server, domain):
7342 security_service = {
7343 'server': server,
7344 'domain': domain,
7345 'user': 'fake_user',
7346 'ou': 'fake_ou',
7347 'dns_ip': 'fake_ip',
7348 'password': 'fake_password'
7349 }
7351 self.assertRaises(exception.NetAppException,
7352 self.client._create_ldap_client,
7353 security_service)
7355 @ddt.data(["password"], ["user"])
7356 def test__modify_active_directory_security_service_error(self, keys):
7357 svm_uuid = fake.FAKE_UUID
7358 user_records = fake.FAKE_CIFS_LOCAL_USER.get('records')[0]
7359 self.mock_object(self.client, '_get_unique_svm_by_name',
7360 mock.Mock(return_value=svm_uuid))
7361 self.mock_object(self.client, 'send_request',
7362 mock.Mock(side_effect=[user_records,
7363 netapp_api.api.NaApiError]))
7364 self.mock_object(self.client, 'remove_preferred_dcs')
7365 self.mock_object(self.client, 'set_preferred_dc')
7366 new_security_service = {
7367 'user': 'new_user',
7368 'password': 'new_password',
7369 'server': 'fake_server'
7370 }
7372 current_security_service = {
7373 'server': 'fake_current_server'
7374 }
7376 self.assertRaises(
7377 exception.NetAppException,
7378 self.client.modify_active_directory_security_service,
7379 fake.VSERVER_NAME,
7380 keys,
7381 new_security_service,
7382 current_security_service)
7384 def test_disable_kerberos_error(self):
7385 fake_api_response = fake.NFS_LIFS_REST
7386 api_error = self._mock_api_error()
7387 self.mock_object(self.client, 'get_network_interfaces',
7388 mock.Mock(return_value=fake_api_response))
7389 self.mock_object(
7390 self.client, 'send_request',
7391 mock.Mock(side_effect=api_error))
7393 self.assertRaises(exception.NetAppException,
7394 self.client.disable_kerberos,
7395 fake.LDAP_AD_SECURITY_SERVICE)
7397 def test_set_volume_snapdir_access_exception(self):
7398 fake_hide_snapdir = 'fake-snapdir'
7400 self.mock_object(self.client, '_get_volume_by_args',
7401 mock.Mock(side_effect=exception.NetAppException))
7402 self.assertRaises(exception.SnapshotResourceNotFound,
7403 self.client.set_volume_snapdir_access,
7404 fake.VOLUME_NAMES[0],
7405 fake_hide_snapdir)
7407 def test__get_broadcast_domain_for_port_exception(self):
7408 fake_response_empty = {
7409 "records": [{}]
7410 }
7411 self.mock_object(self.client, 'send_request', mock.Mock(
7412 return_value=fake_response_empty))
7414 self.assertRaises(exception.NetAppException,
7415 self.client._get_broadcast_domain_for_port,
7416 fake.NODE_NAME,
7417 fake.PORT)
7419 def test__configure_nfs_exception(self):
7420 fake_nfs = {
7421 'udp-max-xfer-size': 10000,
7422 'tcp-max-xfer-size': 10000,
7423 }
7424 self.assertRaises(exception.NetAppException,
7425 self.client._configure_nfs,
7426 fake_nfs,
7427 fake.FAKE_UUID)
7429 def test_get_snapshot_exception(self):
7430 self.mock_object(self.client, '_get_volume_by_args',
7431 mock.Mock(side_effect=exception.NetAppException))
7432 self.assertRaises(exception.SnapshotResourceNotFound,
7433 self.client.get_snapshot,
7434 fake.VOLUME_NAMES[0],
7435 fake.SNAPSHOT_NAME)
7437 def test_delete_snapshot_exception(self):
7438 self.mock_object(self.client,
7439 '_get_volume_by_args',
7440 mock.Mock(side_effect=exception.NetAppException))
7441 self.client.delete_snapshot(fake.VOLUME_NAMES[0], fake.SNAPSHOT_NAME,
7442 True)
7444 self.assertEqual(1, client_cmode_rest.LOG.warning.call_count)
7446 def test_set_nfs_export_policy_for_volume_exception(self):
7447 return_code = netapp_api.EREST_CANNOT_MODITY_OFFLINE_VOLUME
7448 self.mock_object(self.client,
7449 'send_request',
7450 mock.Mock(side_effect=self._mock_api_error(
7451 code=return_code)))
7452 self.client.set_nfs_export_policy_for_volume(
7453 fake.VOLUME_NAMES[0], fake.EXPORT_POLICY_NAME)
7455 self.assertEqual(1, client_cmode_rest.LOG.debug.call_count)
7457 def test__break_snapmirror_exception(self):
7458 fake_snapmirror = copy.deepcopy(fake.REST_GET_SNAPMIRRORS_RESPONSE)
7459 fake_snapmirror[0]['transferring-state'] = 'error'
7461 self.mock_object(
7462 self.client, '_get_snapmirrors',
7463 mock.Mock(return_value=fake_snapmirror))
7465 self.assertRaises(netapp_utils.NetAppDriverException,
7466 self.client._break_snapmirror)
7468 def test_get_svm_volumes_total_size(self):
7469 expected = 1
7471 fake_query = {
7472 'svm.name': fake.VSERVER_NAME,
7473 'fields': 'size'
7474 }
7476 self.mock_object(self.client, 'send_request',
7477 mock.Mock(return_value=fake.FAKE_GET_VOLUME))
7479 result = self.client.get_svm_volumes_total_size(fake.VSERVER_NAME)
7481 self.client.send_request.assert_called_once_with(
7482 '/storage/volumes/', 'get', query=fake_query)
7484 self.assertEqual(expected, result)
7486 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3)
7487 def test_configure_active_directory_credential_error(self,
7488 security_service):
7489 msg = "could not authenticate"
7490 fake_security = copy.deepcopy(security_service)
7492 self.mock_object(self.client, 'configure_dns')
7493 self.mock_object(self.client, 'set_preferred_dc')
7494 self.mock_object(self.client, 'configure_cifs_aes_encryption')
7495 self.mock_object(self.client, '_get_cifs_server_name')
7496 self.mock_object(self.client, 'send_request',
7497 self._mock_api_error(code=netapp_api.api.EAPIERROR,
7498 message=msg))
7499 self.assertRaises(exception.SecurityServiceFailedAuth,
7500 self.client.configure_active_directory,
7501 fake_security,
7502 fake.VSERVER_NAME,
7503 False)
7505 @ddt.data(fake.CIFS_SECURITY_SERVICE, fake.CIFS_SECURITY_SERVICE_3)
7506 def test_configure_active_directory_user_privilege_error(self,
7507 security_service):
7508 msg = "insufficient access"
7509 fake_security = copy.deepcopy(security_service)
7511 self.mock_object(self.client, 'configure_dns')
7512 self.mock_object(self.client, 'set_preferred_dc')
7513 self.mock_object(self.client, 'configure_cifs_aes_encryption')
7514 self.mock_object(self.client, '_get_cifs_server_name')
7515 self.mock_object(self.client, 'send_request',
7516 self._mock_api_error(code=netapp_api.api.EAPIERROR,
7517 message=msg))
7518 self.assertRaises(exception.SecurityServiceFailedAuth,
7519 self.client.configure_active_directory,
7520 fake_security,
7521 fake.VSERVER_NAME,
7522 False)
7524 def test_snapmirror_restore_vol(self):
7525 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"]
7526 body = {
7527 "destination": {"path": fake.SM_DEST_PATH,
7528 "cluster": {"name": fake.CLUSTER_NAME}},
7529 "source_snapshot": fake.SNAPSHOT_NAME
7530 }
7531 snapmirror_info = [{'destination-vserver': "fake_des_vserver",
7532 'destination-volume': "fake_des_vol",
7533 'relationship-status': "idle",
7534 'uuid': uuid}]
7536 self.mock_object(self.client, 'get_snapmirrors',
7537 mock.Mock(return_value=snapmirror_info))
7538 self.mock_object(self.client, 'send_request')
7539 self.client.snapmirror_restore_vol(source_path=fake.SM_SOURCE_PATH,
7540 dest_path=fake.SM_DEST_PATH,
7541 source_snapshot=fake.SNAPSHOT_NAME,
7542 des_cluster=fake.CLUSTER_NAME)
7543 self.client.send_request.assert_called_once_with(
7544 f'/snapmirror/relationships/{uuid}/restore', 'post', body=body)
7546 @ddt.data({'snapmirror_label': None, 'newer_than': '2345'},
7547 {'snapmirror_label': "fake_backup", 'newer_than': None})
7548 @ddt.unpack
7549 def test_list_volume_snapshots(self, snapmirror_label, newer_than):
7550 fake_response = fake.SNAPSHOTS_REST_RESPONSE
7551 api_response = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST
7552 self.mock_object(self.client,
7553 '_get_volume_by_args',
7554 mock.Mock(return_value=api_response))
7555 mock_request = self.mock_object(self.client, 'send_request',
7556 mock.Mock(return_value=fake_response))
7557 self.client.list_volume_snapshots(fake.SHARE_NAME,
7558 snapmirror_label=snapmirror_label,
7559 newer_than=newer_than)
7560 uuid = fake.VOLUME_ITEM_SIMPLE_RESPONSE_REST["uuid"]
7561 query = {}
7562 if snapmirror_label:
7563 query = {
7564 'snapmirror_label': snapmirror_label,
7565 }
7566 if newer_than:
7567 query['create_time'] = '>' + newer_than
7569 mock_request.assert_called_once_with(
7570 f'/storage/volumes/{uuid}/snapshots/',
7571 'get', query=query)
7573 @ddt.data(('vault', False, True), (None, False, False))
7574 @ddt.unpack
7575 def test_create_snapmirror_policy_rest(self, policy_type,
7576 discard_network_info,
7577 preserve_snapshots):
7578 fake_response = fake.SNAPSHOTS_REST_RESPONSE
7579 self.mock_object(self.client, 'send_request',
7580 mock.Mock(return_value=fake_response))
7581 policy_name = fake.SNAPMIRROR_POLICY_NAME
7582 self.client.create_snapmirror_policy(
7583 policy_name, policy_type=policy_type,
7584 discard_network_info=discard_network_info,
7585 preserve_snapshots=preserve_snapshots,
7586 snapmirror_label='backup',
7587 keep=30)
7588 if policy_type == "vault":
7589 body = {"name": policy_name, "type": "async",
7590 "create_snapshot_on_source": False}
7591 else:
7592 body = {"name": policy_name, "type": policy_type}
7593 if discard_network_info: 7593 ↛ 7594line 7593 didn't jump to line 7594 because the condition on line 7593 was never true
7594 body["exclude_network_config"] = {'svmdr-config-obj': 'network'}
7595 if preserve_snapshots:
7596 body["retention"] = [{"label": 'backup', "count": 30}]
7597 self.client.send_request.assert_called_once_with(
7598 '/snapmirror/policies/', 'post', body=body)
7600 def test_is_snaplock_compliance_clock_configured(self):
7601 self.mock_object(self.client,
7602 '_get_cluster_node_uuid',
7603 mock.Mock(return_value="uuid"))
7604 api_response = {'time': 'Thu Aug 08 00:51:30 EDT 2024 -04:00'}
7605 self.mock_object(self.client,
7606 'send_request',
7607 mock.Mock(return_value=api_response))
7608 result = self.client.is_snaplock_compliance_clock_configured(
7609 "test_node"
7610 )
7611 self.assertIs(True, result)
7613 def test_is_snaplock_compliance_clock_configured_negative(self):
7614 self.mock_object(self.client,
7615 '_get_cluster_node_uuid',
7616 mock.Mock(return_value="uuid"))
7617 api_response = {'time': None}
7618 self.mock_object(self.client,
7619 'send_request',
7620 mock.Mock(return_value=api_response))
7621 result = self.client.is_snaplock_compliance_clock_configured(
7622 "test_node"
7623 )
7624 self.assertIs(False, result)
7626 @ddt.data({'options': {'snaplock_autocommit_period': "4hours",
7627 'snaplock_min_retention_period': "6days",
7628 'snaplock_max_retention_period': "8months",
7629 'snaplock_default_retention_period': "8days"},
7630 },
7631 {'options': {'snaplock_autocommit_period': "4hours",
7632 'snaplock_min_retention_period': "6days",
7633 'snaplock_max_retention_period': "8months",
7634 'snaplock_default_retention_period': "min"},
7635 },
7636 {'options': {'snaplock_autocommit_period': "4hours",
7637 'snaplock_min_retention_period': "6days",
7638 'snaplock_max_retention_period': "8months",
7639 'snaplock_default_retention_period': "max"},
7640 },
7641 )
7642 @ddt.unpack
7643 def test_set_snaplock_attributes(self, options):
7644 self.mock_object(self.client, 'send_request')
7646 body = {
7647 'snaplock.autocommit_period':
7648 utils.convert_time_duration_to_iso_format(
7649 options.get('snaplock_autocommit_period')),
7650 'snaplock.retention.minimum':
7651 utils.convert_time_duration_to_iso_format(
7652 options.get('snaplock_min_retention_period')),
7653 'snaplock.retention.maximum':
7654 utils.convert_time_duration_to_iso_format(
7655 options.get('snaplock_max_retention_period')),
7656 }
7657 if options.get('snaplock_default_retention_period') == "min":
7658 body['snaplock.retention.default'] = (
7659 utils.convert_time_duration_to_iso_format(
7660 options.get('snaplock_min_retention_period'))
7661 )
7662 elif options.get('snaplock_default_retention_period') == 'max':
7663 body['snaplock.retention.default'] = (
7664 utils.convert_time_duration_to_iso_format(
7665 options.get('snaplock_max_retention_period'))
7666 )
7667 else:
7668 body['snaplock.retention.default'] = (
7669 utils.convert_time_duration_to_iso_format(
7670 options.get('snaplock_default_retention_period'))
7671 )
7673 self.mock_object(self.client,
7674 '_get_volume_by_args',
7675 mock.Mock(return_value={'uuid': fake.FAKE_UUID}))
7676 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options)
7678 vol_uid = fake.FAKE_UUID
7679 self.client.send_request.assert_called_once_with(
7680 f'/storage/volumes/{vol_uid}', 'patch', body=body)
7682 def test_set_snaplock_attributes_none(self):
7683 self.mock_object(self.client, 'send_request')
7684 self.mock_object(self.client,
7685 '_get_volume_by_args',
7686 mock.Mock(return_value={'uuid': fake.FAKE_UUID}))
7687 options = {'snaplock_autocommit_period': None,
7688 'snaplock_min_retention_period': None,
7689 'snaplock_max_retention_period': None,
7690 'snaplock_default_retention_period': None,
7691 }
7692 self.client.set_snaplock_attributes(fake.SHARE_NAME, **options)
7693 self.client.send_request.assert_not_called()
7695 def test__get_cluster_node_uuid(self):
7696 response = {'records': [{'uuid': fake.FAKE_UUID}]}
7697 self.mock_object(self.client,
7698 'send_request',
7699 mock.Mock(return_value=response))
7701 result = self.client._get_cluster_node_uuid("fake_node")
7702 self.assertEqual(result, fake.FAKE_UUID)
7704 @ddt.data("compliance", "enterprise")
7705 def test__is_snaplock_enabled_volume_true(self, snaplock_type):
7706 vol_attr = {'snaplock-type': snaplock_type}
7707 self.mock_object(self.client,
7708 'get_volume',
7709 mock.Mock(return_value=vol_attr))
7710 result = self.client._is_snaplock_enabled_volume(
7711 fake.SHARE_AGGREGATE_NAMES
7712 )
7713 self.assertIs(True, result)
7715 def test__is_snaplock_enabled_volume_false(self):
7716 vol_attr = {'snaplock-type': "non-snaplock"}
7717 self.mock_object(self.client,
7718 'get_volume',
7719 mock.Mock(return_value=vol_attr))
7720 result = self.client._is_snaplock_enabled_volume(
7721 fake.SHARE_AGGREGATE_NAMES
7722 )
7723 self.assertIs(False, result)
7725 def test_get_storage_failover_partner(self):
7726 self.mock_object(self.client,
7727 '_get_cluster_node_uuid',
7728 mock.Mock(return_value=fake.FAKE_UUID))
7729 response = {'ha': {'partners': [{'name': 'partner_node'}]}}
7730 self.mock_object(self.client,
7731 'send_request',
7732 mock.Mock(return_value=response))
7733 result = self.client.get_storage_failover_partner("fake_node")
7734 self.assertEqual(result, "partner_node")
7736 def test_get_migratable_data_lif_for_node(self):
7737 api_response = fake.GENERIC_NETWORK_INTERFACES_GET_REPONSE
7738 expected_result = [fake.LIF_NAME]
7740 self.mock_object(self.client, '_has_records',
7741 mock.Mock(return_value=True))
7742 self.mock_object(
7743 self.client,
7744 'send_request',
7745 mock.Mock(side_effect=self._send_request_side_effect)
7746 )
7747 uuid = api_response['records'][0]['uuid']
7748 result = self.client.get_migratable_data_lif_for_node("fake_node")
7749 self.client.send_request.assert_any_call(
7750 '/network/ip/interfaces', 'get',
7751 query={
7752 'services': 'data_nfs|data_cifs',
7753 'location.home_node.name': 'fake_node',
7754 'fields': 'name',
7755 }
7756 )
7757 self.client.send_request.assert_any_call(
7758 f'/network/ip/interfaces/{uuid}', 'get'
7759 )
7760 self.assertEqual(expected_result, result)
7762 def _send_request_side_effect(self, endpoint, method, query=None):
7763 if (endpoint == '/network/ip/interfaces' and method == 'get'
7764 and query is not None):
7765 return {"records": [{"uuid": "fake_uuid", "name": fake.LIF_NAME}]}
7766 elif (endpoint.startswith('/network/ip/interfaces/') 7766 ↛ 7769line 7766 didn't jump to line 7769 because the condition on line 7766 was always true
7767 and method == 'get'):
7768 return {'location': {'failover': 'sfo_partners_only'}}
7769 return {}