"Fossies" - the Fresh Open Source Software Archive 
Member "manila-8.1.4/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py" (19 Nov 2020, 250104 Bytes) of package /linux/misc/openstack/manila-8.1.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "test_client_cmode.py":
8.1.3_vs_8.1.4.
1 # Copyright (c) 2014 Alex Meade. All rights reserved.
2 # Copyright (c) 2015 Clinton Knight. All rights reserved.
3 # Copyright (c) 2015 Tom Barron. All rights reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16
17 import copy
18 import hashlib
19 import time
20
21 import ddt
22 import mock
23 from oslo_log import log
24 import six
25
26 from manila import exception
27 from manila.share.drivers.netapp.dataontap.client import api as netapp_api
28 from manila.share.drivers.netapp.dataontap.client import client_base
29 from manila.share.drivers.netapp.dataontap.client import client_cmode
30 from manila import test
31 from manila.tests.share.drivers.netapp.dataontap.client import fakes as fake
32
33
34 @ddt.ddt
35 class NetAppClientCmodeTestCase(test.TestCase):
36
37 def setUp(self):
38 super(NetAppClientCmodeTestCase, self).setUp()
39
40 # Mock loggers as themselves to allow logger arg validation
41 mock_logger = log.getLogger('mock_logger')
42 self.mock_object(client_cmode.LOG,
43 'error',
44 mock.Mock(side_effect=mock_logger.error))
45 self.mock_object(client_cmode.LOG,
46 'warning',
47 mock.Mock(side_effect=mock_logger.warning))
48 self.mock_object(client_cmode.LOG,
49 'debug',
50 mock.Mock(side_effect=mock_logger.debug))
51
52 self.mock_object(client_base.NetAppBaseClient,
53 'get_ontapi_version',
54 mock.Mock(return_value=(1, 20)))
55
56 self.mock_object(client_base.NetAppBaseClient,
57 'get_system_version',
58 mock.Mock(return_value={
59 'version-tuple': (8, 3, 0),
60 'version': fake.VERSION,
61 }))
62
63 self.client = client_cmode.NetAppCmodeClient(**fake.CONNECTION_INFO)
64 self.client.connection = mock.MagicMock()
65
66 self.vserver_client = client_cmode.NetAppCmodeClient(
67 **fake.CONNECTION_INFO)
68 self.vserver_client.set_vserver(fake.VSERVER_NAME)
69 self.vserver_client.connection = mock.MagicMock()
70
71 def _mock_api_error(self, code='fake', message='fake'):
72 return mock.Mock(side_effect=netapp_api.NaApiError(code=code,
73 message=message))
74
75 def test_init_features_ontapi_1_21(self):
76
77 self.mock_object(client_base.NetAppBaseClient,
78 'get_ontapi_version',
79 mock.Mock(return_value=(1, 21)))
80
81 self.client._init_features()
82
83 self.assertFalse(self.client.features.BROADCAST_DOMAINS)
84 self.assertFalse(self.client.features.IPSPACES)
85 self.assertFalse(self.client.features.SUBNETS)
86 self.assertFalse(self.client.features.FLEXVOL_ENCRYPTION)
87
88 @ddt.data((1, 30), (1, 40), (2, 0))
89 def test_init_features_ontapi_1_30(self, ontapi_version):
90
91 self.mock_object(client_base.NetAppBaseClient,
92 'get_ontapi_version',
93 mock.Mock(return_value=ontapi_version))
94
95 self.client._init_features()
96
97 self.assertTrue(self.client.features.BROADCAST_DOMAINS)
98 self.assertTrue(self.client.features.IPSPACES)
99 self.assertTrue(self.client.features.SUBNETS)
100
101 @ddt.data((1, 110), (2, 0))
102 def test_init_features_ontap_1_110(self, ontapi_version):
103
104 self.mock_object(client_base.NetAppBaseClient,
105 'get_ontapi_version',
106 mock.Mock(return_value=ontapi_version))
107
108 self.client._init_features()
109
110 self.assertTrue(self.client.features.BROADCAST_DOMAINS)
111 self.assertTrue(self.client.features.IPSPACES)
112 self.assertTrue(self.client.features.SUBNETS)
113 self.assertTrue(self.client.features.FLEXVOL_ENCRYPTION)
114
115 @ddt.data(((9, 1, 0), fake.VERSION_NO_DARE), ((8, 3, 2), fake.VERSION))
116 @ddt.unpack
117 def test_is_nve_supported_unsupported_release_or_platform(self, gen, ver):
118
119 system_version = {'version-tuple': gen, 'version': ver}
120 self.mock_object(client_base.NetAppBaseClient,
121 'get_system_version',
122 mock.Mock(return_value=system_version))
123 self.mock_object(self.client,
124 'get_security_key_manager_nve_support',
125 mock.Mock(return_value=True))
126 self.mock_object(self.client,
127 'list_cluster_nodes',
128 mock.Mock(return_value=fake.NODE_NAMES))
129
130 result = self.client.is_nve_supported()
131
132 self.assertFalse(result)
133
134 def test_is_nve_supported_valid_platform_and_supported_release(self):
135
136 system_version = {
137 'version-tuple': (9, 1, 0),
138 'version': fake.VERSION,
139 }
140 self.mock_object(client_base.NetAppBaseClient,
141 'get_system_version',
142 mock.Mock(return_value=system_version))
143 self.mock_object(self.client,
144 'get_security_key_manager_nve_support',
145 mock.Mock(return_value=True))
146 self.mock_object(self.client,
147 'list_cluster_nodes',
148 mock.Mock(return_value=fake.NODE_NAMES))
149
150 result = self.client.is_nve_supported()
151 self.assertTrue(result)
152
153 def test_is_nve_supported_key_manager_not_enabled(self):
154
155 system_version = {
156 'version-tuple': (9, 1, 0),
157 'version': fake.VERSION,
158 }
159 self.mock_object(client_base.NetAppBaseClient,
160 'get_system_version',
161 mock.Mock(return_value=system_version))
162 self.mock_object(self.client,
163 'get_security_key_manager_nve_support',
164 mock.Mock(return_value=False))
165 self.mock_object(self.client,
166 'list_cluster_nodes',
167 mock.Mock(return_value=fake.NODE_NAMES))
168
169 result = self.client.is_nve_supported()
170
171 self.assertFalse(result)
172
173 def test_get_security_key_manager_nve_support_enabled(self):
174 api_response = netapp_api.NaElement(
175 fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_TRUE)
176 self.mock_object(self.client,
177 'send_request',
178 mock.Mock(return_value=api_response))
179
180 result = self.client.get_security_key_manager_nve_support(
181 fake.NODE_NAME)
182
183 self.assertTrue(result)
184 api_args = {'node': fake.NODE_NAME}
185 self.client.send_request.assert_has_calls([
186 mock.call('security-key-manager-volume-encryption-supported',
187 api_args)])
188
189 def test_get_security_key_manager_nve_support_disabled(self):
190 api_response = netapp_api.NaElement(
191 fake.SECUTITY_KEY_MANAGER_NVE_SUPPORT_RESPONSE_FALSE)
192 self.mock_object(self.client,
193 'send_request',
194 mock.Mock(return_value=api_response))
195
196 result = self.client.get_security_key_manager_nve_support(
197 fake.NODE_NAME)
198
199 self.assertFalse(result)
200 api_args = {'node': fake.NODE_NAME}
201 self.client.send_request.assert_has_calls([
202 mock.call('security-key-manager-volume-encryption-supported',
203 api_args)])
204
205 def test_get_security_key_manager_nve_support_disabled_no_license(self):
206 self.mock_object(self.client,
207 'send_request',
208 self._mock_api_error())
209
210 result = self.client.get_security_key_manager_nve_support(
211 fake.NODE_NAME)
212
213 self.assertFalse(result)
214
215 api_args = {'node': fake.NODE_NAME}
216 self.client.send_request.assert_has_calls([
217 mock.call('security-key-manager-volume-encryption-supported',
218 api_args)])
219
220 @ddt.data((True, True, True), (False, None, False))
221 @ddt.unpack
222 def test_send_volume_move_request_success(self, validation_only,
223 encrypt_dst, fv_encryption):
224 self.mock_object(self.client, 'features',
225 mock.Mock(FLEXVOL_ENCRYPTION=fv_encryption))
226 self.client._send_volume_move_request(fake.ROOT_VOLUME_NAME,
227 fake.NODE_VSERVER_NAME,
228 fake.SHARE_AGGREGATE_NAME,
229 validation_only=validation_only,
230 encrypt_destination=encrypt_dst)
231
232 @ddt.data((True, True, False))
233 @ddt.unpack
234 def test_send_volume_move_request_failure(self, validation_only,
235 encrypt_dst, fv_encrypt):
236 self.mock_object(self.client, 'features',
237 mock.Mock(FLEXVOL_ENCRYPTION=fv_encrypt))
238 self.assertRaises(exception.NetAppException,
239 self.client._send_volume_move_request,
240 fake.ROOT_VOLUME_NAME,
241 fake.NODE_VSERVER_NAME,
242 fake.SHARE_AGGREGATE_NAME,
243 validation_only=validation_only,
244 encrypt_destination=encrypt_dst)
245
246 def test_invoke_vserver_api(self):
247
248 self.client._invoke_vserver_api('fake-api', 'fake_vserver')
249
250 self.client.connection.set_vserver.assert_has_calls(
251 [mock.call('fake_vserver')])
252 self.client.connection.invoke_successfully.assert_has_calls(
253 [mock.call('fake-api', True)])
254
255 def test_has_records(self):
256 self.assertTrue(self.client._has_records(
257 netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)))
258
259 def test_has_records_not_found(self):
260 self.assertFalse(self.client._has_records(
261 netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)))
262
263 @ddt.data((fake.VSERVER_GET_ITER_RESPONSE, 1),
264 (fake.NO_RECORDS_RESPONSE, 0))
265 @ddt.unpack
266 def test_get_record_count(self, response, expected):
267
268 api_response = netapp_api.NaElement(response)
269
270 result = self.client._get_record_count(api_response)
271
272 self.assertEqual(expected, result)
273
274 def test_get_records_count_invalid(self):
275
276 api_response = netapp_api.NaElement(
277 fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS)
278
279 self.assertRaises(exception.NetAppException,
280 self.client._get_record_count,
281 api_response)
282
283 def test_send_iter_request(self):
284
285 api_responses = [
286 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1),
287 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_2),
288 netapp_api.NaElement(fake.STORAGE_DISK_GET_ITER_RESPONSE_PAGE_3),
289 ]
290 mock_send_request = self.mock_object(
291 self.client, 'send_request',
292 mock.Mock(side_effect=api_responses))
293
294 storage_disk_get_iter_args = {
295 'desired-attributes': {
296 'storage-disk-info': {
297 'disk-name': None,
298 }
299 }
300 }
301 result = self.client.send_iter_request(
302 'storage-disk-get-iter', api_args=storage_disk_get_iter_args,
303 max_page_length=10)
304
305 num_records = result.get_child_content('num-records')
306 self.assertEqual('28', num_records)
307 next_tag = result.get_child_content('next-tag')
308 self.assertEqual('', next_tag)
309
310 args1 = copy.deepcopy(storage_disk_get_iter_args)
311 args1['max-records'] = 10
312 args2 = copy.deepcopy(storage_disk_get_iter_args)
313 args2['max-records'] = 10
314 args2['tag'] = 'next_tag_1'
315 args3 = copy.deepcopy(storage_disk_get_iter_args)
316 args3['max-records'] = 10
317 args3['tag'] = 'next_tag_2'
318
319 mock_send_request.assert_has_calls([
320 mock.call('storage-disk-get-iter', args1),
321 mock.call('storage-disk-get-iter', args2),
322 mock.call('storage-disk-get-iter', args3),
323 ])
324
325 def test_send_iter_request_single_page(self):
326
327 api_response = netapp_api.NaElement(
328 fake.STORAGE_DISK_GET_ITER_RESPONSE)
329 mock_send_request = self.mock_object(
330 self.client, 'send_request',
331 mock.Mock(return_value=api_response))
332
333 storage_disk_get_iter_args = {
334 'desired-attributes': {
335 'storage-disk-info': {
336 'disk-name': None,
337 }
338 }
339 }
340 result = self.client.send_iter_request(
341 'storage-disk-get-iter', api_args=storage_disk_get_iter_args,
342 max_page_length=10)
343
344 num_records = result.get_child_content('num-records')
345 self.assertEqual('4', num_records)
346
347 args = copy.deepcopy(storage_disk_get_iter_args)
348 args['max-records'] = 10
349
350 mock_send_request.assert_has_calls([
351 mock.call('storage-disk-get-iter', args),
352 ])
353
354 def test_send_iter_request_not_found(self):
355
356 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
357 mock_send_request = self.mock_object(
358 self.client, 'send_request',
359 mock.Mock(return_value=api_response))
360
361 result = self.client.send_iter_request('storage-disk-get-iter')
362
363 num_records = result.get_child_content('num-records')
364 self.assertEqual('0', num_records)
365
366 args = {'max-records': client_cmode.DEFAULT_MAX_PAGE_LENGTH}
367
368 mock_send_request.assert_has_calls([
369 mock.call('storage-disk-get-iter', args),
370 ])
371
372 @ddt.data(fake.INVALID_GET_ITER_RESPONSE_NO_ATTRIBUTES,
373 fake.INVALID_GET_ITER_RESPONSE_NO_RECORDS)
374 def test_send_iter_request_invalid(self, fake_response):
375
376 api_response = netapp_api.NaElement(fake_response)
377 self.mock_object(self.client,
378 'send_request',
379 mock.Mock(return_value=api_response))
380
381 self.assertRaises(exception.NetAppException,
382 self.client.send_iter_request,
383 'storage-disk-get-iter')
384
385 def test_set_vserver(self):
386 self.client.set_vserver(fake.VSERVER_NAME)
387 self.client.connection.set_vserver.assert_has_calls(
388 [mock.call('fake_vserver')])
389
390 def test_vserver_exists(self):
391
392 api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)
393 self.mock_object(self.client,
394 'send_iter_request',
395 mock.Mock(return_value=api_response))
396
397 vserver_get_args = {
398 'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}},
399 'desired-attributes': {'vserver-info': {'vserver-name': None}}
400 }
401
402 result = self.client.vserver_exists(fake.VSERVER_NAME)
403
404 self.client.send_iter_request.assert_has_calls([
405 mock.call('vserver-get-iter', vserver_get_args)])
406 self.assertTrue(result)
407
408 def test_vserver_exists_not_found(self):
409
410 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
411 self.mock_object(self.client,
412 'send_request',
413 mock.Mock(return_value=api_response))
414
415 result = self.client.vserver_exists(fake.VSERVER_NAME)
416
417 self.assertFalse(result)
418
419 def test_create_vserver_no_ipspace(self):
420
421 self.mock_object(self.client, 'send_request')
422
423 vserver_create_args = {
424 'vserver-name': fake.VSERVER_NAME,
425 'root-volume-security-style': 'unix',
426 'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME,
427 'root-volume': fake.ROOT_VOLUME_NAME,
428 'name-server-switch': {'nsswitch': 'file'}
429 }
430 vserver_modify_args = {
431 'aggr-list': [{'aggr-name': aggr_name} for aggr_name
432 in fake.SHARE_AGGREGATE_NAMES],
433 'vserver-name': fake.VSERVER_NAME
434 }
435
436 self.client.create_vserver(fake.VSERVER_NAME,
437 fake.ROOT_VOLUME_AGGREGATE_NAME,
438 fake.ROOT_VOLUME_NAME,
439 fake.SHARE_AGGREGATE_NAMES,
440 None)
441
442 self.client.send_request.assert_has_calls([
443 mock.call('vserver-create', vserver_create_args),
444 mock.call('vserver-modify', vserver_modify_args)])
445
446 def test_create_vserver_with_ipspace(self):
447
448 self.client.features.add_feature('IPSPACES')
449 self.mock_object(self.client, 'send_request')
450
451 vserver_create_args = {
452 'vserver-name': fake.VSERVER_NAME,
453 'root-volume-security-style': 'unix',
454 'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME,
455 'root-volume': fake.ROOT_VOLUME_NAME,
456 'name-server-switch': {'nsswitch': 'file'},
457 'ipspace': fake.IPSPACE_NAME,
458 }
459 vserver_modify_args = {
460 'aggr-list': [{'aggr-name': aggr_name} for aggr_name
461 in fake.SHARE_AGGREGATE_NAMES],
462 'vserver-name': fake.VSERVER_NAME
463 }
464
465 self.client.create_vserver(fake.VSERVER_NAME,
466 fake.ROOT_VOLUME_AGGREGATE_NAME,
467 fake.ROOT_VOLUME_NAME,
468 fake.SHARE_AGGREGATE_NAMES,
469 fake.IPSPACE_NAME)
470
471 self.client.send_request.assert_has_calls([
472 mock.call('vserver-create', vserver_create_args),
473 mock.call('vserver-modify', vserver_modify_args)])
474
475 def test_create_vserver_ipspaces_not_supported(self):
476
477 self.assertRaises(exception.NetAppException,
478 self.client.create_vserver,
479 fake.VSERVER_NAME,
480 fake.ROOT_VOLUME_AGGREGATE_NAME,
481 fake.ROOT_VOLUME_NAME,
482 fake.SHARE_AGGREGATE_NAMES,
483 fake.IPSPACE_NAME)
484
485 def test_get_vserver_root_volume_name(self):
486
487 api_response = netapp_api.NaElement(
488 fake.VSERVER_GET_ROOT_VOLUME_NAME_RESPONSE)
489 self.mock_object(self.client,
490 'send_iter_request',
491 mock.Mock(return_value=api_response))
492
493 vserver_get_args = {
494 'query': {'vserver-info': {'vserver-name': fake.VSERVER_NAME}},
495 'desired-attributes': {'vserver-info': {'root-volume': None}}
496 }
497
498 result = self.client.get_vserver_root_volume_name(fake.VSERVER_NAME)
499
500 self.client.send_iter_request.assert_has_calls([
501 mock.call('vserver-get-iter', vserver_get_args)])
502 self.assertEqual(fake.ROOT_VOLUME_NAME, result)
503
504 def test_get_vserver_root_volume_name_not_found(self):
505
506 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
507 self.mock_object(self.client,
508 'send_iter_request',
509 mock.Mock(return_value=api_response))
510
511 self.assertRaises(exception.NetAppException,
512 self.client.get_vserver_root_volume_name,
513 fake.VSERVER_NAME)
514
515 def test_get_vserver_ipspace(self):
516
517 self.client.features.add_feature('IPSPACES')
518 api_response = netapp_api.NaElement(
519 fake.VSERVER_GET_IPSPACE_NAME_RESPONSE)
520 self.mock_object(self.client,
521 'send_iter_request',
522 mock.Mock(return_value=api_response))
523
524 result = self.client.get_vserver_ipspace(fake.VSERVER_NAME)
525
526 vserver_get_iter_args = {
527 'query': {
528 'vserver-info': {
529 'vserver-name': fake.VSERVER_NAME,
530 },
531 },
532 'desired-attributes': {
533 'vserver-info': {
534 'ipspace': None,
535 },
536 },
537 }
538 self.client.send_iter_request.assert_has_calls([
539 mock.call('vserver-get-iter', vserver_get_iter_args)])
540 self.assertEqual(fake.IPSPACE_NAME, result)
541
542 def test_get_vserver_ipspace_not_supported(self):
543
544 result = self.client.get_vserver_ipspace(fake.IPSPACE_NAME)
545
546 self.assertIsNone(result)
547
548 def test_get_vserver_ipspace_not_found(self):
549
550 self.client.features.add_feature('IPSPACES')
551 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
552 self.mock_object(self.client,
553 'send_iter_request',
554 mock.Mock(return_value=api_response))
555
556 self.assertRaises(exception.NetAppException,
557 self.client.get_vserver_ipspace,
558 fake.IPSPACE_NAME)
559
560 def test_ipspace_has_data_vservers(self):
561
562 self.client.features.add_feature('IPSPACES')
563 api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)
564 self.mock_object(self.client,
565 'send_iter_request',
566 mock.Mock(return_value=api_response))
567
568 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
569
570 vserver_get_iter_args = {
571 'query': {
572 'vserver-info': {
573 'ipspace': fake.IPSPACE_NAME,
574 'vserver-type': 'data'
575 },
576 },
577 'desired-attributes': {
578 'vserver-info': {
579 'vserver-name': None,
580 },
581 },
582 }
583 self.client.send_iter_request.assert_has_calls([
584 mock.call('vserver-get-iter', vserver_get_iter_args)])
585 self.assertTrue(result)
586
587 def test_ipspace_has_data_vservers_not_supported(self):
588
589 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
590
591 self.assertFalse(result)
592
593 def test_ipspace_has_data_vservers_not_found(self):
594
595 self.client.features.add_feature('IPSPACES')
596 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
597 self.mock_object(self.client,
598 'send_request',
599 mock.Mock(return_value=api_response))
600
601 result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
602
603 self.assertFalse(result)
604
605 def test_list_vservers(self):
606
607 api_response = netapp_api.NaElement(
608 fake.VSERVER_DATA_LIST_RESPONSE)
609 self.mock_object(self.client,
610 'send_iter_request',
611 mock.Mock(return_value=api_response))
612
613 result = self.client.list_vservers()
614
615 vserver_get_iter_args = {
616 'query': {
617 'vserver-info': {
618 'vserver-type': 'data'
619 }
620 },
621 'desired-attributes': {
622 'vserver-info': {
623 'vserver-name': None
624 }
625 }
626 }
627 self.client.send_iter_request.assert_has_calls([
628 mock.call('vserver-get-iter', vserver_get_iter_args)])
629 self.assertListEqual([fake.VSERVER_NAME], result)
630
631 def test_list_vservers_node_type(self):
632
633 api_response = netapp_api.NaElement(
634 fake.VSERVER_DATA_LIST_RESPONSE)
635 self.mock_object(self.client,
636 'send_iter_request',
637 mock.Mock(return_value=api_response))
638
639 result = self.client.list_vservers(vserver_type='node')
640
641 vserver_get_iter_args = {
642 'query': {
643 'vserver-info': {
644 'vserver-type': 'node'
645 }
646 },
647 'desired-attributes': {
648 'vserver-info': {
649 'vserver-name': None
650 }
651 }
652 }
653 self.client.send_iter_request.assert_has_calls([
654 mock.call('vserver-get-iter', vserver_get_iter_args)])
655 self.assertListEqual([fake.VSERVER_NAME], result)
656
657 def test_list_vservers_not_found(self):
658
659 api_response = netapp_api.NaElement(
660 fake.NO_RECORDS_RESPONSE)
661 self.mock_object(self.client,
662 'send_request',
663 mock.Mock(return_value=api_response))
664
665 result = self.client.list_vservers(vserver_type='data')
666
667 self.assertListEqual([], result)
668
669 def test_get_vserver_volume_count(self):
670
671 api_response = netapp_api.NaElement(fake.VOLUME_COUNT_RESPONSE)
672 self.mock_object(self.client,
673 'send_iter_request',
674 mock.Mock(return_value=api_response))
675
676 result = self.client.get_vserver_volume_count()
677
678 self.assertEqual(2, result)
679
680 def test_delete_vserver_no_volumes(self):
681
682 self.mock_object(self.client,
683 'vserver_exists',
684 mock.Mock(return_value=True))
685 self.mock_object(self.client,
686 'get_vserver_root_volume_name',
687 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
688 self.mock_object(self.vserver_client,
689 'get_vserver_volume_count',
690 mock.Mock(return_value=0))
691 self.mock_object(self.client, '_terminate_vserver_services')
692 self.mock_object(self.client, 'send_request')
693
694 self.client.delete_vserver(
695 fake.VSERVER_NAME,
696 self.vserver_client,
697 security_services=[fake.CIFS_SECURITY_SERVICE])
698
699 self.client._terminate_vserver_services.assert_called_with(
700 fake.VSERVER_NAME, self.vserver_client,
701 [fake.CIFS_SECURITY_SERVICE])
702
703 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
704 self.client.send_request.assert_has_calls([
705 mock.call('vserver-destroy', vserver_destroy_args)])
706
707 def test_delete_vserver_one_volume(self):
708
709 self.mock_object(self.client,
710 'vserver_exists',
711 mock.Mock(return_value=True))
712 self.mock_object(self.client,
713 'get_vserver_root_volume_name',
714 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
715 self.mock_object(self.vserver_client,
716 'get_vserver_volume_count',
717 mock.Mock(return_value=1))
718 self.mock_object(self.client, 'send_request')
719 self.mock_object(self.vserver_client, 'offline_volume')
720 self.mock_object(self.vserver_client, 'delete_volume')
721
722 self.client.delete_vserver(fake.VSERVER_NAME,
723 self.vserver_client)
724
725 self.vserver_client.offline_volume.assert_called_with(
726 fake.ROOT_VOLUME_NAME)
727 self.vserver_client.delete_volume.assert_called_with(
728 fake.ROOT_VOLUME_NAME)
729
730 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
731 self.client.send_request.assert_has_calls([
732 mock.call('vserver-destroy', vserver_destroy_args)])
733
734 def test_delete_vserver_one_volume_already_offline(self):
735
736 self.mock_object(self.client,
737 'vserver_exists',
738 mock.Mock(return_value=True))
739 self.mock_object(self.client,
740 'get_vserver_root_volume_name',
741 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
742 self.mock_object(self.vserver_client,
743 'get_vserver_volume_count',
744 mock.Mock(return_value=1))
745 self.mock_object(self.client, 'send_request')
746 self.mock_object(self.vserver_client,
747 'offline_volume',
748 self._mock_api_error(code=netapp_api.EVOLUMEOFFLINE))
749
750 self.mock_object(self.vserver_client, 'delete_volume')
751
752 self.client.delete_vserver(fake.VSERVER_NAME,
753 self.vserver_client)
754
755 self.vserver_client.offline_volume.assert_called_with(
756 fake.ROOT_VOLUME_NAME)
757 self.vserver_client.delete_volume.assert_called_with(
758 fake.ROOT_VOLUME_NAME)
759
760 vserver_destroy_args = {'vserver-name': fake.VSERVER_NAME}
761 self.client.send_request.assert_has_calls([
762 mock.call('vserver-destroy', vserver_destroy_args)])
763 self.assertEqual(1, client_cmode.LOG.error.call_count)
764
765 def test_delete_vserver_one_volume_api_error(self):
766
767 self.mock_object(self.client,
768 'vserver_exists',
769 mock.Mock(return_value=True))
770 self.mock_object(self.client,
771 'get_vserver_root_volume_name',
772 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
773 self.mock_object(self.vserver_client,
774 'get_vserver_volume_count',
775 mock.Mock(return_value=1))
776 self.mock_object(self.client, 'send_request')
777 self.mock_object(self.vserver_client,
778 'offline_volume',
779 self._mock_api_error())
780 self.mock_object(self.vserver_client, 'delete_volume')
781
782 self.assertRaises(netapp_api.NaApiError,
783 self.client.delete_vserver,
784 fake.VSERVER_NAME,
785 self.vserver_client)
786
787 def test_delete_vserver_multiple_volumes(self):
788
789 self.mock_object(self.client,
790 'vserver_exists',
791 mock.Mock(return_value=True))
792 self.mock_object(self.client,
793 'get_vserver_root_volume_name',
794 mock.Mock(return_value=fake.ROOT_VOLUME_NAME))
795 self.mock_object(self.vserver_client,
796 'get_vserver_volume_count',
797 mock.Mock(return_value=2))
798
799 self.assertRaises(exception.NetAppException,
800 self.client.delete_vserver,
801 fake.VSERVER_NAME,
802 self.vserver_client)
803
804 def test_delete_vserver_not_found(self):
805
806 self.mock_object(self.client,
807 'vserver_exists',
808 mock.Mock(return_value=False))
809
810 self.client.delete_vserver(fake.VSERVER_NAME,
811 self.vserver_client)
812
813 self.assertEqual(1, client_cmode.LOG.error.call_count)
814
815 def test_terminate_vserver_services(self):
816
817 self.mock_object(self.vserver_client, 'send_request')
818
819 self.client._terminate_vserver_services(fake.VSERVER_NAME,
820 self.vserver_client,
821 [fake.CIFS_SECURITY_SERVICE])
822
823 cifs_server_delete_args = {
824 'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
825 'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
826 }
827 self.vserver_client.send_request.assert_has_calls([
828 mock.call('cifs-server-delete', cifs_server_delete_args)])
829
830 def test_terminate_vserver_services_cifs_not_found(self):
831
832 self.mock_object(self.vserver_client,
833 'send_request',
834 self._mock_api_error(
835 code=netapp_api.EOBJECTNOTFOUND))
836
837 self.client._terminate_vserver_services(fake.VSERVER_NAME,
838 self.vserver_client,
839 [fake.CIFS_SECURITY_SERVICE])
840
841 cifs_server_delete_args = {
842 'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
843 'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
844 }
845 self.vserver_client.send_request.assert_has_calls([
846 mock.call('cifs-server-delete', cifs_server_delete_args)])
847 self.assertEqual(1, client_cmode.LOG.error.call_count)
848
849 def test_terminate_vserver_services_api_error(self):
850
851 side_effects = [netapp_api.NaApiError(code='fake'), None]
852 self.mock_object(self.vserver_client,
853 'send_request',
854 mock.Mock(side_effect=side_effects))
855
856 self.client._terminate_vserver_services(fake.VSERVER_NAME,
857 self.vserver_client,
858 [fake.CIFS_SECURITY_SERVICE])
859
860 cifs_server_delete_args = {
861 'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
862 'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
863 }
864 self.vserver_client.send_request.assert_has_calls([
865 mock.call('cifs-server-delete', cifs_server_delete_args),
866 mock.call('cifs-server-delete')])
867 self.assertEqual(0, client_cmode.LOG.error.call_count)
868
869 def test_list_cluster_nodes(self):
870
871 api_response = netapp_api.NaElement(
872 fake.SYSTEM_NODE_GET_ITER_RESPONSE)
873 self.mock_object(self.client,
874 'send_request',
875 mock.Mock(return_value=api_response))
876
877 result = self.client.list_cluster_nodes()
878
879 self.assertListEqual([fake.NODE_NAME], result)
880
881 def test_list_cluster_nodes_not_found(self):
882
883 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
884 self.mock_object(self.client,
885 'send_request',
886 mock.Mock(return_value=api_response))
887
888 result = self.client.list_cluster_nodes()
889
890 self.assertListEqual([], result)
891
892 def test_list_node_data_ports(self):
893
894 self.mock_object(self.client,
895 'get_node_data_ports',
896 mock.Mock(return_value=fake.SPEED_SORTED_PORTS))
897
898 result = self.client.list_node_data_ports(fake.NODE_NAME)
899
900 self.assertSequenceEqual(fake.SPEED_SORTED_PORT_NAMES, result)
901
902 def test_get_node_data_ports(self):
903
904 api_response = netapp_api.NaElement(fake.NET_PORT_GET_ITER_RESPONSE)
905 self.mock_object(self.client,
906 'send_iter_request',
907 mock.Mock(return_value=api_response))
908
909 result = self.client.get_node_data_ports(fake.NODE_NAME)
910
911 net_port_get_iter_args = {
912 'query': {
913 'net-port-info': {
914 'node': fake.NODE_NAME,
915 'link-status': 'up',
916 'port-type': 'physical|if_group',
917 'role': 'data',
918 },
919 },
920 'desired-attributes': {
921 'net-port-info': {
922 'port': None,
923 'node': None,
924 'operational-speed': None,
925 'ifgrp-port': None,
926 },
927 },
928 }
929
930 self.assertSequenceEqual(fake.SPEED_SORTED_PORTS, result)
931 self.client.send_iter_request.assert_has_calls([
932 mock.call('net-port-get-iter', net_port_get_iter_args)])
933
934 def test_get_node_data_ports_not_found(self):
935
936 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
937 self.mock_object(self.client,
938 'send_iter_request',
939 mock.Mock(return_value=api_response))
940
941 result = self.client.get_node_data_ports(fake.NODE_NAME)
942
943 self.assertSequenceEqual([], result)
944
945 def test_sort_data_ports_by_speed(self):
946
947 result = self.client._sort_data_ports_by_speed(
948 fake.UNSORTED_PORTS_ALL_SPEEDS)
949
950 self.assertSequenceEqual(fake.SORTED_PORTS_ALL_SPEEDS, result)
951
952 def test_list_root_aggregates(self):
953
954 api_response = netapp_api.NaElement(
955 fake.AGGR_GET_ITER_ROOT_AGGR_RESPONSE)
956 self.mock_object(self.client,
957 'send_iter_request',
958 mock.Mock(return_value=api_response))
959
960 result = self.client.list_root_aggregates()
961
962 aggr_get_iter_args = {
963 'desired-attributes': {
964 'aggr-attributes': {
965 'aggregate-name': None,
966 'aggr-raid-attributes': {
967 'has-local-root': None,
968 'has-partner-root': None,
969 },
970 },
971 }
972 }
973 self.assertSequenceEqual(fake.ROOT_AGGREGATE_NAMES, result)
974 self.client.send_iter_request.assert_has_calls([
975 mock.call('aggr-get-iter', aggr_get_iter_args)])
976
977 def test_list_non_root_aggregates(self):
978
979 api_response = netapp_api.NaElement(
980 fake.AGGR_GET_ITER_NON_ROOT_AGGR_RESPONSE)
981 self.mock_object(self.client,
982 'send_iter_request',
983 mock.Mock(return_value=api_response))
984
985 result = self.client.list_non_root_aggregates()
986
987 aggr_get_iter_args = {
988 'query': {
989 'aggr-attributes': {
990 'aggr-raid-attributes': {
991 'has-local-root': 'false',
992 'has-partner-root': 'false',
993 }
994 },
995 },
996 'desired-attributes': {
997 'aggr-attributes': {
998 'aggregate-name': None,
999 },
1000 },
1001 }
1002 self.assertSequenceEqual(fake.SHARE_AGGREGATE_NAMES, result)
1003 self.client.send_iter_request.assert_has_calls([
1004 mock.call('aggr-get-iter', aggr_get_iter_args)])
1005
1006 def test_list_aggregates(self):
1007
1008 api_response = netapp_api.NaElement(fake.AGGR_GET_NAMES_RESPONSE)
1009 self.mock_object(self.client,
1010 'send_iter_request',
1011 mock.Mock(return_value=api_response))
1012
1013 result = self.client._list_aggregates()
1014
1015 aggr_get_iter_args = {
1016 'desired-attributes': {
1017 'aggr-attributes': {
1018 'aggregate-name': None,
1019 },
1020 },
1021 }
1022 self.assertSequenceEqual(
1023 fake.ROOT_AGGREGATE_NAMES + fake.SHARE_AGGREGATE_NAMES, result)
1024 self.client.send_iter_request.assert_has_calls([
1025 mock.call('aggr-get-iter', aggr_get_iter_args)])
1026
1027 def test_list_aggregates_not_found(self):
1028
1029 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1030 self.mock_object(self.client,
1031 'send_request',
1032 mock.Mock(return_value=api_response))
1033
1034 self.assertRaises(exception.NetAppException,
1035 self.client._list_aggregates)
1036
1037 def test_list_vserver_aggregates(self):
1038
1039 self.mock_object(self.vserver_client,
1040 'get_vserver_aggregate_capacities',
1041 mock.Mock(return_value=fake.VSERVER_AGGREGATES))
1042
1043 result = self.vserver_client.list_vserver_aggregates()
1044
1045 self.assertListEqual(list(fake.VSERVER_AGGREGATES.keys()), result)
1046
1047 def test_list_vserver_aggregates_none_found(self):
1048
1049 self.mock_object(self.vserver_client,
1050 'get_vserver_aggregate_capacities',
1051 mock.Mock(return_value={}))
1052
1053 result = self.vserver_client.list_vserver_aggregates()
1054
1055 self.assertListEqual([], result)
1056
1057 @ddt.data((True, True), (True, False), (False, True), (False, False))
1058 @ddt.unpack
1059 def test_create_network_interface(self, broadcast_domains_supported,
1060 use_vlans):
1061
1062 self.client.features.add_feature('BROADCAST_DOMAINS',
1063 broadcast_domains_supported)
1064 self.mock_object(self.client, '_ensure_broadcast_domain_for_port')
1065 self.mock_object(self.client, '_create_vlan')
1066 self.mock_object(self.client, 'send_request')
1067
1068 lif_create_args = {
1069 'address': fake.IP_ADDRESS,
1070 'administrative-status': 'up',
1071 'data-protocols': [
1072 {'data-protocol': 'nfs'},
1073 {'data-protocol': 'cifs'}
1074 ],
1075 'home-node': fake.NODE_NAME,
1076 'home-port': fake.VLAN_PORT if use_vlans else fake.PORT,
1077 'netmask': fake.NETMASK,
1078 'interface-name': fake.LIF_NAME,
1079 'role': 'data',
1080 'vserver': fake.VSERVER_NAME,
1081 }
1082 self.client.create_network_interface(fake.IP_ADDRESS,
1083 fake.NETMASK,
1084 fake.VLAN if use_vlans else None,
1085 fake.NODE_NAME,
1086 fake.PORT,
1087 fake.VSERVER_NAME,
1088 fake.LIF_NAME,
1089 fake.IPSPACE_NAME,
1090 fake.MTU)
1091
1092 if use_vlans:
1093 self.client._create_vlan.assert_called_with(
1094 fake.NODE_NAME, fake.PORT, fake.VLAN)
1095 else:
1096 self.assertFalse(self.client._create_vlan.called)
1097
1098 if broadcast_domains_supported:
1099 self.client._ensure_broadcast_domain_for_port.assert_called_with(
1100 fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT,
1101 fake.MTU, ipspace=fake.IPSPACE_NAME)
1102 else:
1103 self.assertFalse(
1104 self.client._ensure_broadcast_domain_for_port.called)
1105
1106 self.client.send_request.assert_has_calls([
1107 mock.call('net-interface-create', lif_create_args)])
1108
1109 def test_create_vlan(self):
1110
1111 self.mock_object(self.client, 'send_request')
1112
1113 vlan_create_args = {
1114 'vlan-info': {
1115 'parent-interface': fake.PORT,
1116 'node': fake.NODE_NAME,
1117 'vlanid': fake.VLAN
1118 }
1119 }
1120 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
1121
1122 self.client.send_request.assert_has_calls([
1123 mock.call('net-vlan-create', vlan_create_args)])
1124
1125 def test_create_vlan_already_present(self):
1126
1127 self.mock_object(self.client,
1128 'send_request',
1129 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
1130
1131 vlan_create_args = {
1132 'vlan-info': {
1133 'parent-interface': fake.PORT,
1134 'node': fake.NODE_NAME,
1135 'vlanid': fake.VLAN
1136 }
1137 }
1138 self.client._create_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
1139
1140 self.client.send_request.assert_has_calls([
1141 mock.call('net-vlan-create', vlan_create_args)])
1142 self.assertEqual(1, client_cmode.LOG.debug.call_count)
1143
1144 def test_create_vlan_api_error(self):
1145
1146 self.mock_object(self.client, 'send_request', self._mock_api_error())
1147
1148 self.assertRaises(exception.NetAppException,
1149 self.client._create_vlan,
1150 fake.NODE_NAME,
1151 fake.PORT,
1152 fake.VLAN)
1153
1154 def test_delete_vlan(self):
1155
1156 self.mock_object(self.client, 'send_request')
1157
1158 vlan_delete_args = {
1159 'vlan-info': {
1160 'parent-interface': fake.PORT,
1161 'node': fake.NODE_NAME,
1162 'vlanid': fake.VLAN
1163 }
1164 }
1165 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
1166
1167 self.client.send_request.assert_has_calls([
1168 mock.call('net-vlan-delete', vlan_delete_args)])
1169
1170 def test_delete_vlan_still_used(self):
1171
1172 self.mock_object(self.client,
1173 'send_request',
1174 self._mock_api_error(code=netapp_api.EAPIERROR,
1175 message='Port already has a '
1176 'lif bound. '))
1177
1178 vlan_delete_args = {
1179 'vlan-info': {
1180 'parent-interface': fake.PORT,
1181 'node': fake.NODE_NAME,
1182 'vlanid': fake.VLAN
1183 }
1184 }
1185 self.client.delete_vlan(fake.NODE_NAME, fake.PORT, fake.VLAN)
1186
1187 self.client.send_request.assert_has_calls([
1188 mock.call('net-vlan-delete', vlan_delete_args)])
1189 self.assertEqual(1, client_cmode.LOG.debug.call_count)
1190
1191 def test_delete_vlan_api_error(self):
1192
1193 self.mock_object(self.client, 'send_request', self._mock_api_error())
1194
1195 self.assertRaises(exception.NetAppException,
1196 self.client.delete_vlan,
1197 fake.NODE_NAME,
1198 fake.PORT,
1199 fake.VLAN)
1200
1201 @ddt.data(('10.10.10.0/24', '10.10.10.1', False),
1202 ('fc00::/7', 'fe80::1', False),
1203 ('0.0.0.0/0', '10.10.10.1', True),
1204 ('::/0', 'fe80::1', True))
1205 @ddt.unpack
1206 def test_create_route(self, subnet, gateway, omit_destination):
1207 api_response = netapp_api.NaElement(
1208 fake.NET_ROUTES_CREATE_RESPONSE)
1209 expected_api_args = {
1210 'destination': subnet,
1211 'gateway': gateway,
1212 'return-record': 'true',
1213 }
1214 self.mock_object(
1215 self.client, 'send_request', mock.Mock(return_value=api_response))
1216
1217 destination = None if omit_destination else subnet
1218 self.client.create_route(gateway, destination=destination)
1219
1220 self.client.send_request.assert_called_once_with(
1221 'net-routes-create', expected_api_args)
1222
1223 def test_create_route_duplicate(self):
1224 self.mock_object(client_cmode.LOG, 'debug')
1225 expected_api_args = {
1226 'destination': fake.SUBNET,
1227 'gateway': fake.GATEWAY,
1228 'return-record': 'true',
1229 }
1230 self.mock_object(
1231 self.client, 'send_request',
1232 mock.Mock(side_effect=self._mock_api_error(
1233 code=netapp_api.EAPIERROR, message='Duplicate route exists.')))
1234
1235 self.client.create_route(fake.GATEWAY, destination=fake.SUBNET)
1236
1237 self.client.send_request.assert_called_once_with(
1238 'net-routes-create', expected_api_args)
1239 self.assertEqual(1, client_cmode.LOG.debug.call_count)
1240
1241 def test_create_route_api_error(self):
1242 expected_api_args = {
1243 'destination': fake.SUBNET,
1244 'gateway': fake.GATEWAY,
1245 'return-record': 'true',
1246 }
1247 self.mock_object(
1248 self.client, 'send_request',
1249 mock.Mock(side_effect=self._mock_api_error()))
1250
1251 self.assertRaises(exception.NetAppException,
1252 self.client.create_route,
1253 fake.GATEWAY, destination=fake.SUBNET)
1254
1255 self.client.send_request.assert_called_once_with(
1256 'net-routes-create', expected_api_args)
1257
1258 def test_create_route_without_gateway(self):
1259 self.mock_object(self.client, 'send_request')
1260 self.client.create_route(None, destination=fake.SUBNET)
1261 self.assertFalse(self.client.send_request.called)
1262
1263 def test_ensure_broadcast_domain_for_port_domain_match(self):
1264
1265 port_info = {
1266 'ipspace': fake.IPSPACE_NAME,
1267 'broadcast-domain': fake.BROADCAST_DOMAIN,
1268 }
1269 self.mock_object(self.client,
1270 '_get_broadcast_domain_for_port',
1271 mock.Mock(return_value=port_info))
1272 self.mock_object(self.client,
1273 '_broadcast_domain_exists',
1274 mock.Mock(return_value=True))
1275 self.mock_object(self.client, '_create_broadcast_domain')
1276 self.mock_object(self.client, '_modify_broadcast_domain')
1277 self.mock_object(self.client, '_add_port_to_broadcast_domain')
1278
1279 self.client._ensure_broadcast_domain_for_port(
1280 fake.NODE_NAME, fake.PORT, fake.MTU, ipspace=fake.IPSPACE_NAME)
1281
1282 self.client._get_broadcast_domain_for_port.assert_called_once_with(
1283 fake.NODE_NAME, fake.PORT)
1284 self.client._modify_broadcast_domain.assert_called_once_with(
1285 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
1286 self.assertFalse(self.client._broadcast_domain_exists.called)
1287 self.assertFalse(self.client._create_broadcast_domain.called)
1288 self.assertFalse(self.client._add_port_to_broadcast_domain.called)
1289
1290 @ddt.data(fake.IPSPACE_NAME, client_cmode.DEFAULT_IPSPACE)
1291 def test_ensure_broadcast_domain_for_port_other_domain(self, ipspace):
1292
1293 port_info = {
1294 'ipspace': ipspace,
1295 'broadcast-domain': 'other_domain',
1296 }
1297 self.mock_object(self.client,
1298 '_get_broadcast_domain_for_port',
1299 mock.Mock(return_value=port_info))
1300 self.mock_object(self.client,
1301 '_broadcast_domain_exists',
1302 mock.Mock(return_value=True))
1303 self.mock_object(self.client, '_create_broadcast_domain')
1304 self.mock_object(self.client, '_modify_broadcast_domain')
1305 self.mock_object(self.client, '_remove_port_from_broadcast_domain')
1306 self.mock_object(self.client, '_add_port_to_broadcast_domain')
1307
1308 self.client._ensure_broadcast_domain_for_port(
1309 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
1310
1311 self.client._get_broadcast_domain_for_port.assert_called_once_with(
1312 fake.NODE_NAME, fake.PORT)
1313 self.client._remove_port_from_broadcast_domain.assert_called_once_with(
1314 fake.NODE_NAME, fake.PORT, 'other_domain', ipspace)
1315 self.client._broadcast_domain_exists.assert_called_once_with(
1316 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
1317 self.assertFalse(self.client._create_broadcast_domain.called)
1318 self.client._modify_broadcast_domain.assert_called_once_with(
1319 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
1320 self.client._add_port_to_broadcast_domain.assert_called_once_with(
1321 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
1322 fake.IPSPACE_NAME)
1323
1324 def test_ensure_broadcast_domain_for_port_no_domain(self):
1325
1326 port_info = {
1327 'ipspace': fake.IPSPACE_NAME,
1328 'broadcast-domain': None,
1329 }
1330 self.mock_object(self.client,
1331 '_get_broadcast_domain_for_port',
1332 mock.Mock(return_value=port_info))
1333 self.mock_object(self.client,
1334 '_broadcast_domain_exists',
1335 mock.Mock(return_value=False))
1336 self.mock_object(self.client, '_create_broadcast_domain')
1337 self.mock_object(self.client, '_modify_broadcast_domain')
1338 self.mock_object(self.client, '_remove_port_from_broadcast_domain')
1339 self.mock_object(self.client, '_add_port_to_broadcast_domain')
1340
1341 self.client._ensure_broadcast_domain_for_port(
1342 fake.NODE_NAME, fake.PORT, ipspace=fake.IPSPACE_NAME, mtu=fake.MTU)
1343
1344 self.client._get_broadcast_domain_for_port.assert_called_once_with(
1345 fake.NODE_NAME, fake.PORT)
1346 self.assertFalse(self.client._remove_port_from_broadcast_domain.called)
1347 self.client._broadcast_domain_exists.assert_called_once_with(
1348 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)
1349 self.client._create_broadcast_domain.assert_called_once_with(
1350 fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME, fake.MTU)
1351 self.assertFalse(self.client._modify_broadcast_domain.called)
1352 self.client._add_port_to_broadcast_domain.assert_called_once_with(
1353 fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
1354 fake.IPSPACE_NAME)
1355
1356 def test_get_broadcast_domain_for_port(self):
1357
1358 api_response = netapp_api.NaElement(
1359 fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE)
1360 self.mock_object(self.client,
1361 'send_iter_request',
1362 mock.Mock(return_value=api_response))
1363
1364 net_port_get_iter_args = {
1365 'query': {
1366 'net-port-info': {
1367 'node': fake.NODE_NAME,
1368 'port': fake.PORT,
1369 },
1370 },
1371 'desired-attributes': {
1372 'net-port-info': {
1373 'broadcast-domain': None,
1374 'ipspace': None,
1375 },
1376 },
1377 }
1378 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
1379 fake.PORT)
1380
1381 expected = {
1382 'broadcast-domain': fake.BROADCAST_DOMAIN,
1383 'ipspace': fake.IPSPACE_NAME,
1384 }
1385 self.client.send_iter_request.assert_has_calls([
1386 mock.call('net-port-get-iter', net_port_get_iter_args)])
1387 self.assertEqual(expected, result)
1388
1389 def test_get_broadcast_domain_for_port_port_not_found(self):
1390
1391 api_response = netapp_api.NaElement(
1392 fake.NO_RECORDS_RESPONSE)
1393 self.mock_object(self.client,
1394 'send_iter_request',
1395 mock.Mock(return_value=api_response))
1396
1397 self.assertRaises(exception.NetAppException,
1398 self.client._get_broadcast_domain_for_port,
1399 fake.NODE_NAME,
1400 fake.PORT)
1401
1402 def test_get_broadcast_domain_for_port_domain_not_found(self):
1403
1404 api_response = netapp_api.NaElement(
1405 fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE)
1406 self.mock_object(self.client,
1407 'send_iter_request',
1408 mock.Mock(return_value=api_response))
1409
1410 result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
1411 fake.PORT)
1412
1413 expected = {
1414 'broadcast-domain': None,
1415 'ipspace': fake.IPSPACE_NAME,
1416 }
1417 self.assertEqual(expected, result)
1418
1419 def test_broadcast_domain_exists(self):
1420
1421 api_response = netapp_api.NaElement(
1422 fake.NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE)
1423 self.mock_object(self.client,
1424 'send_iter_request',
1425 mock.Mock(return_value=api_response))
1426
1427 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
1428 fake.IPSPACE_NAME)
1429
1430 net_port_broadcast_domain_get_iter_args = {
1431 'query': {
1432 'net-port-broadcast-domain-info': {
1433 'ipspace': fake.IPSPACE_NAME,
1434 'broadcast-domain': fake.BROADCAST_DOMAIN,
1435 },
1436 },
1437 'desired-attributes': {
1438 'net-port-broadcast-domain-info': None,
1439 },
1440 }
1441 self.client.send_iter_request.assert_has_calls([
1442 mock.call('net-port-broadcast-domain-get-iter',
1443 net_port_broadcast_domain_get_iter_args)])
1444 self.assertTrue(result)
1445
1446 def test_broadcast_domain_exists_not_found(self):
1447
1448 api_response = netapp_api.NaElement(
1449 fake.NO_RECORDS_RESPONSE)
1450 self.mock_object(self.client,
1451 'send_request',
1452 mock.Mock(return_value=api_response))
1453
1454 result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
1455 fake.IPSPACE_NAME)
1456
1457 self.assertFalse(result)
1458
1459 def test_create_broadcast_domain(self):
1460
1461 self.mock_object(self.client, 'send_request')
1462
1463 result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
1464 fake.IPSPACE_NAME,
1465 fake.MTU)
1466
1467 net_port_broadcast_domain_create_args = {
1468 'ipspace': fake.IPSPACE_NAME,
1469 'broadcast-domain': fake.BROADCAST_DOMAIN,
1470 'mtu': fake.MTU,
1471 }
1472 self.assertIsNone(result)
1473 self.client.send_request.assert_has_calls([
1474 mock.call('net-port-broadcast-domain-create',
1475 net_port_broadcast_domain_create_args)])
1476
1477 def test_modify_broadcast_domain(self):
1478
1479 self.mock_object(self.client, 'send_request')
1480
1481 result = self.client._modify_broadcast_domain(fake.BROADCAST_DOMAIN,
1482 fake.IPSPACE_NAME,
1483 fake.MTU)
1484
1485 net_port_broadcast_domain_modify_args = {
1486 'ipspace': fake.IPSPACE_NAME,
1487 'broadcast-domain': fake.BROADCAST_DOMAIN,
1488 'mtu': fake.MTU,
1489 }
1490 self.assertIsNone(result)
1491 self.client.send_request.assert_called_once_with(
1492 'net-port-broadcast-domain-modify',
1493 net_port_broadcast_domain_modify_args)
1494
1495 def test_delete_broadcast_domain(self):
1496
1497 self.mock_object(self.client, 'send_request')
1498
1499 result = self.client._delete_broadcast_domain(fake.BROADCAST_DOMAIN,
1500 fake.IPSPACE_NAME)
1501
1502 net_port_broadcast_domain_delete_args = {
1503 'ipspace': fake.IPSPACE_NAME,
1504 'broadcast-domain': fake.BROADCAST_DOMAIN,
1505 }
1506 self.assertIsNone(result)
1507 self.client.send_request.assert_has_calls([
1508 mock.call('net-port-broadcast-domain-destroy',
1509 net_port_broadcast_domain_delete_args)])
1510
1511 def test_delete_broadcast_domains_for_ipspace_not_found(self):
1512
1513 self.mock_object(self.client,
1514 'get_ipspaces',
1515 mock.Mock(return_value=[]))
1516 self.mock_object(self.client, '_delete_broadcast_domain')
1517
1518 self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
1519
1520 self.client.get_ipspaces.assert_called_once_with(
1521 ipspace_name=fake.IPSPACE_NAME)
1522 self.assertFalse(self.client._delete_broadcast_domain.called)
1523
1524 def test_delete_broadcast_domains_for_ipspace(self):
1525
1526 self.mock_object(self.client,
1527 'get_ipspaces',
1528 mock.Mock(return_value=fake.IPSPACES))
1529 self.mock_object(self.client, '_delete_broadcast_domain')
1530
1531 self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
1532
1533 self.client.get_ipspaces.assert_called_once_with(
1534 ipspace_name=fake.IPSPACE_NAME)
1535 self.client._delete_broadcast_domain.assert_called_once_with(
1536 fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACE_NAME)
1537
1538 def test_add_port_to_broadcast_domain(self):
1539
1540 self.mock_object(self.client, 'send_request')
1541
1542 add_port_to_broadcast_domain_args = {
1543 'ipspace': fake.IPSPACE_NAME,
1544 'broadcast-domain': fake.BROADCAST_DOMAIN,
1545 'ports': {
1546 'net-qualified-port-name': ':'.join([fake.NODE_NAME,
1547 fake.VLAN_PORT])
1548 }
1549 }
1550 result = self.client._add_port_to_broadcast_domain(
1551 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
1552 fake.IPSPACE_NAME)
1553
1554 self.assertIsNone(result)
1555 self.client.send_request.assert_has_calls([
1556 mock.call('net-port-broadcast-domain-add-ports',
1557 add_port_to_broadcast_domain_args)])
1558
1559 def test_add_port_to_broadcast_domain_already_present(self):
1560
1561 self.mock_object(self.client, 'send_request', self._mock_api_error(
1562 code=netapp_api.
1563 E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN))
1564
1565 result = self.client._add_port_to_broadcast_domain(
1566 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
1567 fake.IPSPACE_NAME)
1568
1569 self.assertIsNone(result)
1570
1571 def test_add_port_to_broadcast_domain_api_error(self):
1572
1573 self.mock_object(self.client, 'send_request', self._mock_api_error())
1574
1575 self.assertRaises(exception.NetAppException,
1576 self.client._add_port_to_broadcast_domain,
1577 fake.NODE_NAME,
1578 fake.VLAN_PORT,
1579 fake.BROADCAST_DOMAIN,
1580 fake.IPSPACE_NAME)
1581
1582 def test_remove_port_from_broadcast_domain(self):
1583
1584 self.mock_object(self.client, 'send_request')
1585
1586 result = self.client._remove_port_from_broadcast_domain(
1587 fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
1588 fake.IPSPACE_NAME)
1589
1590 net_port_broadcast_domain_remove_ports_args = {
1591 'ipspace': fake.IPSPACE_NAME,
1592 'broadcast-domain': fake.BROADCAST_DOMAIN,
1593 'ports': {
1594 'net-qualified-port-name': ':'.join([fake.NODE_NAME,
1595 fake.VLAN_PORT])
1596 }
1597 }
1598 self.assertIsNone(result)
1599 self.client.send_request.assert_has_calls([
1600 mock.call('net-port-broadcast-domain-remove-ports',
1601 net_port_broadcast_domain_remove_ports_args)])
1602
1603 def test_network_interface_exists(self):
1604
1605 api_response = netapp_api.NaElement(
1606 fake.NET_INTERFACE_GET_ONE_RESPONSE)
1607 self.mock_object(self.client,
1608 'send_iter_request',
1609 mock.Mock(return_value=api_response))
1610
1611 net_interface_get_args = {
1612 'query': {
1613 'net-interface-info': {
1614 'address': fake.IP_ADDRESS,
1615 'home-node': fake.NODE_NAME,
1616 'home-port': fake.VLAN_PORT,
1617 'netmask': fake.NETMASK,
1618 'vserver': fake.VSERVER_NAME}
1619 },
1620 'desired-attributes': {
1621 'net-interface-info': {
1622 'interface-name': None,
1623 }
1624 }
1625 }
1626 result = self.client.network_interface_exists(
1627 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS,
1628 fake.NETMASK, fake.VLAN)
1629
1630 self.client.send_iter_request.assert_has_calls([
1631 mock.call('net-interface-get-iter', net_interface_get_args)])
1632 self.assertTrue(result)
1633
1634 def test_network_interface_exists_not_found(self):
1635
1636 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1637 self.mock_object(self.client,
1638 'send_iter_request',
1639 mock.Mock(return_value=api_response))
1640
1641 net_interface_get_args = {
1642 'query': {
1643 'net-interface-info': {
1644 'address': fake.IP_ADDRESS,
1645 'home-node': fake.NODE_NAME,
1646 'home-port': fake.PORT,
1647 'netmask': fake.NETMASK,
1648 'vserver': fake.VSERVER_NAME}
1649 },
1650 'desired-attributes': {
1651 'net-interface-info': {
1652 'interface-name': None,
1653 }
1654 }
1655 }
1656 result = self.client.network_interface_exists(
1657 fake.VSERVER_NAME, fake.NODE_NAME, fake.PORT, fake.IP_ADDRESS,
1658 fake.NETMASK, None)
1659 self.client.send_iter_request.assert_has_calls([
1660 mock.call('net-interface-get-iter', net_interface_get_args)])
1661 self.assertFalse(result)
1662
1663 def test_list_network_interfaces(self):
1664
1665 api_response = netapp_api.NaElement(
1666 fake.NET_INTERFACE_GET_ITER_RESPONSE)
1667 self.mock_object(self.client,
1668 'send_iter_request',
1669 mock.Mock(return_value=api_response))
1670
1671 net_interface_get_args = {
1672 'desired-attributes': {
1673 'net-interface-info': {
1674 'interface-name': None,
1675 }
1676 }
1677 }
1678
1679 result = self.client.list_network_interfaces()
1680
1681 self.client.send_iter_request.assert_has_calls([
1682 mock.call('net-interface-get-iter', net_interface_get_args)])
1683 self.assertSequenceEqual(fake.LIF_NAMES, result)
1684
1685 def test_list_network_interfaces_not_found(self):
1686
1687 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1688 self.mock_object(self.client,
1689 'send_request',
1690 mock.Mock(return_value=api_response))
1691
1692 result = self.client.list_network_interfaces()
1693
1694 self.assertListEqual([], result)
1695
1696 def test_get_network_interfaces(self):
1697
1698 api_response = netapp_api.NaElement(
1699 fake.NET_INTERFACE_GET_ITER_RESPONSE)
1700 self.mock_object(self.client,
1701 'send_iter_request',
1702 mock.Mock(return_value=api_response))
1703
1704 result = self.client.get_network_interfaces()
1705
1706 self.client.send_iter_request.assert_has_calls([
1707 mock.call('net-interface-get-iter', None)])
1708 self.assertSequenceEqual(fake.LIFS, result)
1709
1710 def test_get_network_interfaces_filtered_by_protocol(self):
1711
1712 api_response = netapp_api.NaElement(
1713 fake.NET_INTERFACE_GET_ITER_RESPONSE_NFS)
1714 self.mock_object(self.client,
1715 'send_iter_request',
1716 mock.Mock(return_value=api_response))
1717
1718 result = self.client.get_network_interfaces(protocols=['NFS'])
1719
1720 net_interface_get_args = {
1721 'query': {
1722 'net-interface-info': {
1723 'data-protocols': {
1724 'data-protocol': 'nfs',
1725 }
1726 }
1727 }
1728 }
1729
1730 self.client.send_iter_request.assert_has_calls([
1731 mock.call('net-interface-get-iter', net_interface_get_args)])
1732 self.assertListEqual(fake.NFS_LIFS, result)
1733
1734 def test_get_network_interfaces_not_found(self):
1735
1736 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1737 self.mock_object(self.client,
1738 'send_iter_request',
1739 mock.Mock(return_value=api_response))
1740
1741 result = self.client.get_network_interfaces()
1742
1743 self.client.send_iter_request.assert_has_calls([
1744 mock.call('net-interface-get-iter', None)])
1745 self.assertListEqual([], result)
1746
1747 def test_get_ipspaces(self):
1748
1749 self.client.features.add_feature('IPSPACES')
1750 api_response = netapp_api.NaElement(
1751 fake.NET_IPSPACES_GET_ITER_RESPONSE)
1752 self.mock_object(self.client,
1753 'send_iter_request',
1754 mock.Mock(return_value=api_response))
1755
1756 result = self.client.get_ipspaces(ipspace_name=fake.IPSPACE_NAME)
1757
1758 net_ipspaces_get_iter_args = {
1759 'query': {
1760 'net-ipspaces-info': {
1761 'ipspace': fake.IPSPACE_NAME,
1762 },
1763 },
1764 }
1765 self.client.send_iter_request.assert_has_calls([
1766 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
1767 self.assertEqual(fake.IPSPACES, result)
1768
1769 def test_get_ipspaces_not_found(self):
1770
1771 self.client.features.add_feature('IPSPACES')
1772 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1773 self.mock_object(self.client,
1774 'send_iter_request',
1775 mock.Mock(return_value=api_response))
1776
1777 result = self.client.get_ipspaces()
1778
1779 net_ipspaces_get_iter_args = {}
1780 self.client.send_iter_request.assert_has_calls([
1781 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
1782 self.assertEqual([], result)
1783
1784 def test_get_ipspaces_not_supported(self):
1785
1786 self.mock_object(self.client, 'send_iter_request')
1787
1788 result = self.client.get_ipspaces()
1789
1790 self.assertFalse(self.client.send_iter_request.called)
1791 self.assertEqual([], result)
1792
1793 @ddt.data((fake.NET_IPSPACES_GET_ITER_RESPONSE, True),
1794 (fake.NO_RECORDS_RESPONSE, False))
1795 @ddt.unpack
1796 def test_ipspace_exists(self, api_response, expected):
1797
1798 self.client.features.add_feature('IPSPACES')
1799 api_response = netapp_api.NaElement(api_response)
1800 self.mock_object(self.client,
1801 'send_iter_request',
1802 mock.Mock(return_value=api_response))
1803
1804 result = self.client.ipspace_exists(fake.IPSPACE_NAME)
1805
1806 net_ipspaces_get_iter_args = {
1807 'query': {
1808 'net-ipspaces-info': {
1809 'ipspace': fake.IPSPACE_NAME,
1810 },
1811 },
1812 'desired-attributes': {
1813 'net-ipspaces-info': {
1814 'ipspace': None,
1815 },
1816 },
1817 }
1818 self.client.send_iter_request.assert_has_calls([
1819 mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
1820 self.assertEqual(expected, result)
1821
1822 def test_ipspace_exists_not_supported(self):
1823
1824 result = self.client.ipspace_exists(fake.IPSPACE_NAME)
1825
1826 self.assertFalse(result)
1827
1828 def test_create_ipspace(self):
1829
1830 self.mock_object(self.client, 'send_request')
1831
1832 self.client.create_ipspace(fake.IPSPACE_NAME)
1833
1834 net_ipspaces_create_args = {'ipspace': fake.IPSPACE_NAME}
1835 self.client.send_request.assert_has_calls([
1836 mock.call('net-ipspaces-create', net_ipspaces_create_args)])
1837
1838 def test_delete_ipspace(self):
1839
1840 mock_delete_broadcast_domains_for_ipspace = self.mock_object(
1841 self.client, '_delete_broadcast_domains_for_ipspace')
1842 self.mock_object(self.client, 'send_request')
1843
1844 self.client.delete_ipspace(fake.IPSPACE_NAME)
1845
1846 net_ipspaces_destroy_args = {'ipspace': fake.IPSPACE_NAME}
1847 mock_delete_broadcast_domains_for_ipspace.assert_called_once_with(
1848 fake.IPSPACE_NAME)
1849 self.client.send_request.assert_has_calls([
1850 mock.call('net-ipspaces-destroy', net_ipspaces_destroy_args)])
1851
1852 def test_get_ipspace_name_for_vlan_port(self):
1853 self.client.features.add_feature('IPSPACES')
1854 api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE)
1855 self.mock_object(self.client,
1856 'send_request',
1857 mock.Mock(return_value=api_response))
1858
1859 ipspace = self.client.get_ipspace_name_for_vlan_port(
1860 fake.NODE_NAME, fake.PORT, fake.VLAN)
1861
1862 port = '%(port)s-%(id)s' % {'port': fake.PORT, 'id': fake.VLAN}
1863 self.client.send_request.assert_called_once_with(
1864 'net-port-get',
1865 {'node': fake.NODE_NAME, 'port': port})
1866 self.assertEqual(fake.IPSPACE_NAME, ipspace)
1867
1868 def test_get_ipspace_name_for_vlan_port_no_ipspace_feature(self):
1869 self.mock_object(self.client, 'send_request')
1870
1871 ipspace = self.client.get_ipspace_name_for_vlan_port(
1872 fake.NODE_NAME, fake.PORT, fake.VLAN)
1873
1874 self.client.send_request.assert_not_called()
1875 self.assertIsNone(ipspace)
1876
1877 def test_get_ipspace_name_for_vlan_port_no_ipspace_found(self):
1878 self.client.features.add_feature('IPSPACES')
1879 self.mock_object(
1880 self.client,
1881 'send_request',
1882 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
1883
1884 ipspace = self.client.get_ipspace_name_for_vlan_port(
1885 fake.NODE_NAME, fake.PORT, fake.VLAN)
1886
1887 self.assertIsNone(ipspace)
1888
1889 def test_get_ipspace_name_for_vlan_port_no_vlan(self):
1890 self.client.features.add_feature('IPSPACES')
1891 api_response = netapp_api.NaElement(fake.NET_PORT_GET_RESPONSE_NO_VLAN)
1892 self.mock_object(self.client,
1893 'send_request',
1894 mock.Mock(return_value=api_response))
1895
1896 ipspace = self.client.get_ipspace_name_for_vlan_port(
1897 fake.NODE_NAME, fake.PORT, None)
1898
1899 self.client.send_request.assert_called_once_with(
1900 'net-port-get',
1901 {'node': fake.NODE_NAME, 'port': fake.PORT})
1902 self.assertEqual(fake.IPSPACE_NAME, ipspace)
1903
1904 def test_get_ipspace_name_for_vlan_port_raises_api_error(self):
1905 self.client.features.add_feature('IPSPACES')
1906 self.mock_object(self.client,
1907 'send_request',
1908 mock.Mock(side_effect=self._mock_api_error()))
1909
1910 self.assertRaises(netapp_api.NaApiError,
1911 self.client.get_ipspace_name_for_vlan_port,
1912 fake.NODE_NAME, fake.VLAN_PORT, None)
1913
1914 def test_add_vserver_to_ipspace(self):
1915
1916 self.mock_object(self.client, 'send_request')
1917
1918 self.client.add_vserver_to_ipspace(fake.IPSPACE_NAME,
1919 fake.VSERVER_NAME)
1920
1921 net_ipspaces_assign_vserver_args = {
1922 'ipspace': fake.IPSPACE_NAME,
1923 'vserver': fake.VSERVER_NAME
1924 }
1925 self.client.send_request.assert_has_calls([
1926 mock.call('net-ipspaces-assign-vserver',
1927 net_ipspaces_assign_vserver_args)])
1928
1929 def test_get_node_for_aggregate(self):
1930
1931 api_response = netapp_api.NaElement(
1932 fake.AGGR_GET_NODE_RESPONSE).get_child_by_name(
1933 'attributes-list').get_children()
1934 self.mock_object(self.client,
1935 '_get_aggregates',
1936 mock.Mock(return_value=api_response))
1937
1938 result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
1939
1940 desired_attributes = {
1941 'aggr-attributes': {
1942 'aggregate-name': None,
1943 'aggr-ownership-attributes': {
1944 'home-name': None,
1945 },
1946 },
1947 }
1948
1949 self.client._get_aggregates.assert_has_calls([
1950 mock.call(
1951 aggregate_names=[fake.SHARE_AGGREGATE_NAME],
1952 desired_attributes=desired_attributes)])
1953
1954 self.assertEqual(fake.NODE_NAME, result)
1955
1956 def test_get_node_for_aggregate_none_requested(self):
1957
1958 result = self.client.get_node_for_aggregate(None)
1959
1960 self.assertIsNone(result)
1961
1962 def test_get_node_for_aggregate_api_not_found(self):
1963
1964 self.mock_object(self.client,
1965 'send_iter_request',
1966 mock.Mock(side_effect=self._mock_api_error(
1967 netapp_api.EAPINOTFOUND)))
1968
1969 result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
1970
1971 self.assertIsNone(result)
1972
1973 def test_get_node_for_aggregate_api_error(self):
1974
1975 self.mock_object(self.client,
1976 'send_iter_request',
1977 self._mock_api_error())
1978
1979 self.assertRaises(netapp_api.NaApiError,
1980 self.client.get_node_for_aggregate,
1981 fake.SHARE_AGGREGATE_NAME)
1982
1983 def test_get_node_for_aggregate_not_found(self):
1984
1985 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
1986 self.mock_object(self.client,
1987 'send_iter_request',
1988 mock.Mock(return_value=api_response))
1989
1990 result = self.client.get_node_for_aggregate(fake.SHARE_AGGREGATE_NAME)
1991
1992 self.assertIsNone(result)
1993
1994 def test_get_cluster_aggregate_capacities(self):
1995
1996 api_response = netapp_api.NaElement(
1997 fake.AGGR_GET_SPACE_RESPONSE).get_child_by_name(
1998 'attributes-list').get_children()
1999 self.mock_object(self.client,
2000 '_get_aggregates',
2001 mock.Mock(return_value=api_response))
2002
2003 result = self.client.get_cluster_aggregate_capacities(
2004 fake.SHARE_AGGREGATE_NAMES)
2005
2006 desired_attributes = {
2007 'aggr-attributes': {
2008 'aggregate-name': None,
2009 'aggr-space-attributes': {
2010 'size-available': None,
2011 'size-total': None,
2012 'size-used': None,
2013 }
2014 }
2015 }
2016
2017 self.client._get_aggregates.assert_has_calls([
2018 mock.call(
2019 aggregate_names=fake.SHARE_AGGREGATE_NAMES,
2020 desired_attributes=desired_attributes)])
2021
2022 expected = {
2023 fake.SHARE_AGGREGATE_NAMES[0]: {
2024 'available': 45670400,
2025 'total': 943718400,
2026 'used': 898048000,
2027 },
2028 fake.SHARE_AGGREGATE_NAMES[1]: {
2029 'available': 4267659264,
2030 'total': 7549747200,
2031 'used': 3282087936,
2032 },
2033 }
2034 self.assertDictEqual(expected, result)
2035
2036 def test_get_cluster_aggregate_capacities_not_found(self):
2037
2038 api_response = netapp_api.NaElement('none').get_children()
2039 self.mock_object(self.client,
2040 '_get_aggregates',
2041 mock.Mock(return_value=api_response))
2042
2043 result = self.client.get_cluster_aggregate_capacities(
2044 fake.SHARE_AGGREGATE_NAMES)
2045
2046 self.assertEqual({}, result)
2047
2048 def test_get_cluster_aggregate_capacities_none_requested(self):
2049
2050 result = self.client.get_cluster_aggregate_capacities([])
2051
2052 self.assertEqual({}, result)
2053
2054 def test_get_vserver_aggregate_capacities(self):
2055
2056 api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE)
2057 self.mock_object(self.vserver_client,
2058 'send_request',
2059 mock.Mock(return_value=api_response))
2060
2061 result = self.vserver_client.get_vserver_aggregate_capacities()
2062
2063 vserver_args = {
2064 'desired-attributes': {
2065 'vserver-info': {
2066 'vserver-name': None,
2067 'vserver-aggr-info-list': {
2068 'vserver-aggr-info': {
2069 'aggr-name': None,
2070 'aggr-availsize': None
2071 }
2072 }
2073 }
2074 }
2075 }
2076
2077 self.vserver_client.send_request.assert_has_calls([
2078 mock.call('vserver-get', vserver_args)])
2079 self.assertDictEqual(fake.VSERVER_AGGREGATES, result)
2080
2081 def test_get_vserver_aggregate_capacities_partial_request(self):
2082
2083 api_response = netapp_api.NaElement(fake.VSERVER_GET_RESPONSE)
2084 self.mock_object(self.vserver_client,
2085 'send_request',
2086 mock.Mock(return_value=api_response))
2087
2088 result = self.vserver_client.get_vserver_aggregate_capacities(
2089 fake.SHARE_AGGREGATE_NAMES[0])
2090
2091 expected = {fake.SHARE_AGGREGATE_NAMES[0]:
2092 fake.VSERVER_AGGREGATES[fake.SHARE_AGGREGATE_NAMES[0]]}
2093 self.assertDictEqual(expected, result)
2094
2095 def test_get_vserver_aggregate_capacities_aggregate_not_found(self):
2096
2097 api_response = netapp_api.NaElement(
2098 fake.VSERVER_GET_RESPONSE_NO_AGGREGATES)
2099 self.mock_object(self.vserver_client,
2100 'send_request',
2101 mock.Mock(return_value=api_response))
2102
2103 result = self.vserver_client.get_vserver_aggregate_capacities()
2104
2105 self.assertDictEqual({}, result)
2106 self.assertEqual(1, client_cmode.LOG.warning.call_count)
2107
2108 def test_get_vserver_aggregate_capacities_vserver_not_found(self):
2109
2110 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
2111 self.mock_object(self.vserver_client,
2112 'send_request',
2113 mock.Mock(return_value=api_response))
2114
2115 self.assertRaises(exception.NetAppException,
2116 self.vserver_client.get_vserver_aggregate_capacities)
2117
2118 def test_get_vserver_aggregate_capacities_none_requested(self):
2119
2120 result = self.client.get_vserver_aggregate_capacities([])
2121
2122 self.assertEqual({}, result)
2123
2124 def test_get_aggregates(self):
2125
2126 api_response = netapp_api.NaElement(fake.AGGR_GET_ITER_RESPONSE)
2127 self.mock_object(self.client,
2128 'send_iter_request',
2129 mock.Mock(return_value=api_response))
2130
2131 result = self.client._get_aggregates()
2132
2133 self.client.send_iter_request.assert_has_calls([
2134 mock.call('aggr-get-iter', {})])
2135 self.assertListEqual(
2136 [aggr.to_string() for aggr in api_response.get_child_by_name(
2137 'attributes-list').get_children()],
2138 [aggr.to_string() for aggr in result])
2139
2140 def test_get_aggregates_with_filters(self):
2141
2142 api_response = netapp_api.NaElement(fake.AGGR_GET_SPACE_RESPONSE)
2143 self.mock_object(self.client,
2144 'send_iter_request',
2145 mock.Mock(return_value=api_response))
2146
2147 desired_attributes = {
2148 'aggr-attributes': {
2149 'aggregate-name': None,
2150 'aggr-space-attributes': {
2151 'size-total': None,
2152 'size-available': None,
2153 }
2154 }
2155 }
2156
2157 result = self.client._get_aggregates(
2158 aggregate_names=fake.SHARE_AGGREGATE_NAMES,
2159 desired_attributes=desired_attributes)
2160
2161 aggr_get_iter_args = {
2162 'query': {
2163 'aggr-attributes': {
2164 'aggregate-name': '|'.join(fake.SHARE_AGGREGATE_NAMES),
2165 }
2166 },
2167 'desired-attributes': desired_attributes
2168 }
2169
2170 self.client.send_iter_request.assert_has_calls([
2171 mock.call('aggr-get-iter', aggr_get_iter_args)])
2172 self.assertListEqual(
2173 [aggr.to_string() for aggr in api_response.get_child_by_name(
2174 'attributes-list').get_children()],
2175 [aggr.to_string() for aggr in result])
2176
2177 def test_get_aggregates_not_found(self):
2178
2179 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
2180 self.mock_object(self.client,
2181 'send_iter_request',
2182 mock.Mock(return_value=api_response))
2183
2184 result = self.client._get_aggregates()
2185
2186 self.client.send_iter_request.assert_has_calls([
2187 mock.call('aggr-get-iter', {})])
2188 self.assertListEqual([], result)
2189
2190 def test_get_performance_instance_uuids(self):
2191
2192 api_response = netapp_api.NaElement(
2193 fake.PERF_OBJECT_INSTANCE_LIST_INFO_ITER_RESPONSE)
2194 self.mock_object(self.client,
2195 'send_request',
2196 mock.Mock(return_value=api_response))
2197
2198 result = self.client.get_performance_instance_uuids(
2199 'system', fake.NODE_NAME)
2200
2201 expected = [fake.NODE_NAME + ':kernel:system']
2202 self.assertEqual(expected, result)
2203
2204 perf_object_instance_list_info_iter_args = {
2205 'objectname': 'system',
2206 'query': {
2207 'instance-info': {
2208 'uuid': fake.NODE_NAME + ':*',
2209 }
2210 }
2211 }
2212 self.client.send_request.assert_called_once_with(
2213 'perf-object-instance-list-info-iter',
2214 perf_object_instance_list_info_iter_args)
2215
2216 def test_get_performance_counter_info(self):
2217
2218 api_response = netapp_api.NaElement(
2219 fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE)
2220 self.mock_object(self.client,
2221 'send_request',
2222 mock.Mock(return_value=api_response))
2223
2224 result = self.client.get_performance_counter_info('wafl',
2225 'cp_phase_times')
2226
2227 expected = {
2228 'name': 'cp_phase_times',
2229 'base-counter': 'total_cp_msecs',
2230 'labels': fake.PERF_OBJECT_COUNTER_TOTAL_CP_MSECS_LABELS,
2231 }
2232 self.assertEqual(expected, result)
2233
2234 perf_object_counter_list_info_args = {'objectname': 'wafl'}
2235 self.client.send_request.assert_called_once_with(
2236 'perf-object-counter-list-info',
2237 perf_object_counter_list_info_args)
2238
2239 def test_get_performance_counter_info_not_found(self):
2240
2241 api_response = netapp_api.NaElement(
2242 fake.PERF_OBJECT_COUNTER_LIST_INFO_WAFL_RESPONSE)
2243 self.mock_object(self.client,
2244 'send_request',
2245 mock.Mock(return_value=api_response))
2246
2247 self.assertRaises(exception.NotFound,
2248 self.client.get_performance_counter_info,
2249 'wafl',
2250 'invalid')
2251
2252 def test_get_performance_counters(self):
2253
2254 api_response = netapp_api.NaElement(
2255 fake.PERF_OBJECT_GET_INSTANCES_SYSTEM_RESPONSE_CMODE)
2256 self.mock_object(self.client,
2257 'send_request',
2258 mock.Mock(return_value=api_response))
2259
2260 instance_uuids = [
2261 fake.NODE_NAMES[0] + ':kernel:system',
2262 fake.NODE_NAMES[1] + ':kernel:system',
2263 ]
2264 counter_names = ['avg_processor_busy']
2265 result = self.client.get_performance_counters('system',
2266 instance_uuids,
2267 counter_names)
2268
2269 expected = [
2270 {
2271 'avg_processor_busy': '5674745133134',
2272 'instance-name': 'system',
2273 'instance-uuid': instance_uuids[0],
2274 'node-name': fake.NODE_NAMES[0],
2275 'timestamp': '1453412013',
2276 }, {
2277 'avg_processor_busy': '4077649009234',
2278 'instance-name': 'system',
2279 'instance-uuid': instance_uuids[1],
2280 'node-name': fake.NODE_NAMES[1],
2281 'timestamp': '1453412013'
2282 },
2283 ]
2284 self.assertEqual(expected, result)
2285
2286 perf_object_get_instances_args = {
2287 'objectname': 'system',
2288 'instance-uuids': [
2289 {'instance-uuid': instance_uuid}
2290 for instance_uuid in instance_uuids
2291 ],
2292 'counters': [
2293 {'counter': counter} for counter in counter_names
2294 ],
2295 }
2296 self.client.send_request.assert_called_once_with(
2297 'perf-object-get-instances', perf_object_get_instances_args)
2298
2299 def test_setup_security_services_ldap(self):
2300
2301 self.mock_object(self.client, 'send_request')
2302 self.mock_object(self.vserver_client, 'configure_ldap')
2303
2304 self.client.setup_security_services([fake.LDAP_SECURITY_SERVICE],
2305 self.vserver_client,
2306 fake.VSERVER_NAME)
2307
2308 vserver_modify_args = {
2309 'name-mapping-switch': [
2310 {'nmswitch': 'ldap'},
2311 {'nmswitch': 'file'},
2312 ],
2313 'name-server-switch': [
2314 {'nsswitch': 'ldap'},
2315 {'nsswitch': 'file'},
2316 ],
2317 'vserver-name': fake.VSERVER_NAME
2318 }
2319 self.client.send_request.assert_has_calls([
2320 mock.call('vserver-modify', vserver_modify_args)])
2321 self.vserver_client.configure_ldap.assert_has_calls([
2322 mock.call(fake.LDAP_SECURITY_SERVICE)])
2323
2324 def test_setup_security_services_active_directory(self):
2325
2326 self.mock_object(self.client, 'send_request')
2327 self.mock_object(self.vserver_client, 'configure_active_directory')
2328
2329 self.client.setup_security_services([fake.CIFS_SECURITY_SERVICE],
2330 self.vserver_client,
2331 fake.VSERVER_NAME)
2332
2333 vserver_modify_args = {
2334 'name-mapping-switch': [
2335 {'nmswitch': 'ldap'},
2336 {'nmswitch': 'file'},
2337 ],
2338 'name-server-switch': [
2339 {'nsswitch': 'ldap'},
2340 {'nsswitch': 'file'},
2341 ],
2342 'vserver-name': fake.VSERVER_NAME
2343 }
2344 self.client.send_request.assert_has_calls([
2345 mock.call('vserver-modify', vserver_modify_args)])
2346 self.vserver_client.configure_active_directory.assert_has_calls([
2347 mock.call(fake.CIFS_SECURITY_SERVICE, fake.VSERVER_NAME)])
2348
2349 def test_setup_security_services_kerberos(self):
2350
2351 self.mock_object(self.client, 'send_request')
2352 self.mock_object(self.client, 'create_kerberos_realm')
2353 self.mock_object(self.vserver_client, 'configure_kerberos')
2354
2355 self.client.setup_security_services([fake.KERBEROS_SECURITY_SERVICE],
2356 self.vserver_client,
2357 fake.VSERVER_NAME)
2358
2359 vserver_modify_args = {
2360 'name-mapping-switch': [
2361 {'nmswitch': 'ldap'},
2362 {'nmswitch': 'file'},
2363 ],
2364 'name-server-switch': [
2365 {'nsswitch': 'ldap'},
2366 {'nsswitch': 'file'},
2367 ],
2368 'vserver-name': fake.VSERVER_NAME
2369 }
2370 self.client.send_request.assert_has_calls([
2371 mock.call('vserver-modify', vserver_modify_args)])
2372 self.client.create_kerberos_realm.assert_has_calls([
2373 mock.call(fake.KERBEROS_SECURITY_SERVICE)])
2374 self.vserver_client.configure_kerberos.assert_has_calls([
2375 mock.call(fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)])
2376
2377 def test_setup_security_services_invalid(self):
2378
2379 self.mock_object(self.client, 'send_request')
2380
2381 self.assertRaises(exception.NetAppException,
2382 self.client.setup_security_services,
2383 [fake.INVALID_SECURITY_SERVICE],
2384 self.vserver_client,
2385 fake.VSERVER_NAME)
2386
2387 vserver_modify_args = {
2388 'name-mapping-switch': [
2389 {'nmswitch': 'ldap'},
2390 {'nmswitch': 'file'},
2391 ],
2392 'name-server-switch': [
2393 {'nsswitch': 'ldap'},
2394 {'nsswitch': 'file'},
2395 ],
2396 'vserver-name': fake.VSERVER_NAME
2397 }
2398 self.client.send_request.assert_has_calls([
2399 mock.call('vserver-modify', vserver_modify_args)])
2400
2401 def test_enable_nfs(self):
2402
2403 self.mock_object(self.client, 'send_request')
2404 self.mock_object(self.client, '_enable_nfs_protocols')
2405 self.mock_object(self.client, '_create_default_nfs_export_rules')
2406
2407 self.client.enable_nfs(fake.NFS_VERSIONS)
2408
2409 self.client.send_request.assert_called_once_with('nfs-enable')
2410 self.client._enable_nfs_protocols.assert_called_once_with(
2411 fake.NFS_VERSIONS)
2412 self.client._create_default_nfs_export_rules.assert_called_once_with()
2413
2414 @ddt.data((True, True, True), (True, False, False), (False, True, True))
2415 @ddt.unpack
2416 def test_enable_nfs_protocols(self, v3, v40, v41):
2417
2418 self.mock_object(self.client, 'send_request')
2419
2420 versions = []
2421 if v3:
2422 versions.append('nfs3')
2423 if v40:
2424 versions.append('nfs4.0')
2425 if v41:
2426 versions.append('nfs4.1')
2427
2428 self.client._enable_nfs_protocols(versions)
2429
2430 nfs_service_modify_args = {
2431 'is-nfsv3-enabled': 'true' if v3 else 'false',
2432 'is-nfsv40-enabled': 'true' if v40 else 'false',
2433 'is-nfsv41-enabled': 'true' if v41 else 'false',
2434 }
2435 self.client.send_request.assert_called_once_with(
2436 'nfs-service-modify', nfs_service_modify_args)
2437
2438 def test_create_default_nfs_export_rules(self):
2439
2440 class CopyingMock(mock.Mock):
2441 def __call__(self, *args, **kwargs):
2442 args = copy.deepcopy(args)
2443 kwargs = copy.deepcopy(kwargs)
2444 return super(CopyingMock, self).__call__(*args, **kwargs)
2445
2446 self.mock_object(self.client, 'send_request', CopyingMock())
2447
2448 self.client._create_default_nfs_export_rules()
2449
2450 export_rule_create_args = {
2451 'client-match': '0.0.0.0/0',
2452 'policy-name': 'default',
2453 'ro-rule': {
2454 'security-flavor': 'any'
2455 },
2456 'rw-rule': {
2457 'security-flavor': 'never'
2458 }
2459 }
2460 export_rule_create_args2 = export_rule_create_args.copy()
2461 export_rule_create_args2['client-match'] = '::/0'
2462 self.client.send_request.assert_has_calls([
2463 mock.call('export-rule-create', export_rule_create_args),
2464 mock.call('export-rule-create', export_rule_create_args2)])
2465
2466 def test_configure_ldap(self):
2467
2468 self.mock_object(self.client, 'send_request')
2469
2470 self.client.configure_ldap(fake.LDAP_SECURITY_SERVICE)
2471
2472 config_name = hashlib.md5(
2473 six.b(fake.LDAP_SECURITY_SERVICE['id'])).hexdigest()
2474
2475 ldap_client_create_args = {
2476 'ldap-client-config': config_name,
2477 'servers': {'ip-address': fake.LDAP_SECURITY_SERVICE['server']},
2478 'tcp-port': '389',
2479 'schema': 'RFC-2307',
2480 'bind-password': fake.LDAP_SECURITY_SERVICE['password']
2481 }
2482 ldap_config_create_args = {
2483 'client-config': config_name,
2484 'client-enabled': 'true'
2485 }
2486
2487 self.client.send_request.assert_has_calls([
2488 mock.call('ldap-client-create', ldap_client_create_args),
2489 mock.call('ldap-config-create', ldap_config_create_args)])
2490
2491 def test_configure_active_directory(self):
2492
2493 self.mock_object(self.client, 'send_request')
2494 self.mock_object(self.client, 'configure_dns')
2495 self.mock_object(self.client, 'set_preferred_dc')
2496
2497 self.client.configure_active_directory(fake.CIFS_SECURITY_SERVICE,
2498 fake.VSERVER_NAME)
2499
2500 cifs_server = (fake.VSERVER_NAME[0:8] +
2501 '-' +
2502 fake.VSERVER_NAME[-6:]).replace('_', '-').upper()
2503
2504 cifs_server_create_args = {
2505 'admin-username': fake.CIFS_SECURITY_SERVICE['user'],
2506 'admin-password': fake.CIFS_SECURITY_SERVICE['password'],
2507 'force-account-overwrite': 'true',
2508 'cifs-server': cifs_server,
2509 'organizational-unit': fake.CIFS_SECURITY_SERVICE['ou'],
2510 'domain': fake.CIFS_SECURITY_SERVICE['domain'],
2511 }
2512
2513 self.client.configure_dns.assert_called_with(
2514 fake.CIFS_SECURITY_SERVICE)
2515 self.client.set_preferred_dc.assert_called_with(
2516 fake.CIFS_SECURITY_SERVICE)
2517 self.client.send_request.assert_has_calls([
2518 mock.call('cifs-server-create', cifs_server_create_args)])
2519
2520 def test_configure_active_directory_api_error(self):
2521
2522 self.mock_object(self.client, 'send_request', self._mock_api_error())
2523 self.mock_object(self.client, 'configure_dns')
2524
2525 self.assertRaises(exception.NetAppException,
2526 self.client.configure_active_directory,
2527 fake.CIFS_SECURITY_SERVICE,
2528 fake.VSERVER_NAME)
2529
2530 def test_create_kerberos_realm(self):
2531
2532 self.mock_object(self.client, 'send_request')
2533
2534 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
2535
2536 kerberos_realm_create_args = {
2537 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2538 'admin-server-port': '749',
2539 'clock-skew': '5',
2540 'comment': '',
2541 'config-name': fake.KERBEROS_SECURITY_SERVICE['id'],
2542 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2543 'kdc-port': '88',
2544 'kdc-vendor': 'other',
2545 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2546 'password-server-port': '464',
2547 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper()
2548 }
2549
2550 self.client.send_request.assert_has_calls([
2551 mock.call('kerberos-realm-create', kerberos_realm_create_args)])
2552
2553 def test_create_kerberos_realm_already_present(self):
2554
2555 self.mock_object(self.client,
2556 'send_request',
2557 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
2558
2559 self.client.create_kerberos_realm(fake.KERBEROS_SECURITY_SERVICE)
2560
2561 kerberos_realm_create_args = {
2562 'admin-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2563 'admin-server-port': '749',
2564 'clock-skew': '5',
2565 'comment': '',
2566 'config-name': fake.KERBEROS_SECURITY_SERVICE['id'],
2567 'kdc-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2568 'kdc-port': '88',
2569 'kdc-vendor': 'other',
2570 'password-server-ip': fake.KERBEROS_SECURITY_SERVICE['server'],
2571 'password-server-port': '464',
2572 'realm': fake.KERBEROS_SECURITY_SERVICE['domain'].upper()
2573 }
2574
2575 self.client.send_request.assert_has_calls([
2576 mock.call('kerberos-realm-create', kerberos_realm_create_args)])
2577 self.assertEqual(1, client_cmode.LOG.debug.call_count)
2578
2579 def test_create_kerberos_realm_api_error(self):
2580
2581 self.mock_object(self.client, 'send_request', self._mock_api_error())
2582
2583 self.assertRaises(exception.NetAppException,
2584 self.client.create_kerberos_realm,
2585 fake.KERBEROS_SECURITY_SERVICE)
2586
2587 def test_configure_kerberos(self):
2588
2589 self.mock_object(self.client, 'send_request')
2590 self.mock_object(self.client, 'configure_dns')
2591 self.mock_object(self.client,
2592 'list_network_interfaces',
2593 mock.Mock(return_value=['lif1', 'lif2']))
2594
2595 self.client.configure_kerberos(
2596 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)
2597
2598 spn = self.client._get_kerberos_service_principal_name(
2599 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME)
2600
2601 kerberos_config_modify_args1 = {
2602 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'],
2603 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'],
2604 'interface-name': 'lif1',
2605 'is-kerberos-enabled': 'true',
2606 'service-principal-name': spn
2607 }
2608 kerberos_config_modify_args2 = {
2609 'admin-password': fake.KERBEROS_SECURITY_SERVICE['password'],
2610 'admin-user-name': fake.KERBEROS_SECURITY_SERVICE['user'],
2611 'interface-name': 'lif2',
2612 'is-kerberos-enabled': 'true',
2613 'service-principal-name': spn
2614 }
2615
2616 self.client.configure_dns.assert_called_with(
2617 fake.KERBEROS_SECURITY_SERVICE)
2618 self.client.send_request.assert_has_calls([
2619 mock.call('kerberos-config-modify',
2620 kerberos_config_modify_args1),
2621 mock.call('kerberos-config-modify',
2622 kerberos_config_modify_args2)])
2623
2624 def test_configure_kerberos_no_network_interfaces(self):
2625
2626 self.mock_object(self.client, 'send_request')
2627 self.mock_object(self.client, 'configure_dns')
2628 self.mock_object(self.client,
2629 'list_network_interfaces',
2630 mock.Mock(return_value=[]))
2631
2632 self.assertRaises(exception.NetAppException,
2633 self.client.configure_kerberos,
2634 fake.KERBEROS_SECURITY_SERVICE,
2635 fake.VSERVER_NAME)
2636
2637 self.client.configure_dns.assert_called_with(
2638 fake.KERBEROS_SECURITY_SERVICE)
2639
2640 def test_get_kerberos_service_principal_name(self):
2641
2642 spn = self.client._get_kerberos_service_principal_name(
2643 fake.KERBEROS_SECURITY_SERVICE, fake.VSERVER_NAME
2644 )
2645 self.assertEqual(fake.KERBEROS_SERVICE_PRINCIPAL_NAME, spn)
2646
2647 def test_configure_dns_for_active_directory(self):
2648
2649 self.mock_object(self.client, 'send_request')
2650
2651 self.client.configure_dns(fake.CIFS_SECURITY_SERVICE)
2652
2653 net_dns_create_args = {
2654 'domains': {'string': fake.CIFS_SECURITY_SERVICE['domain']},
2655 'name-servers': [{
2656 'ip-address': fake.CIFS_SECURITY_SERVICE['dns_ip']
2657 }],
2658 'dns-state': 'enabled'
2659 }
2660
2661 self.client.send_request.assert_has_calls([
2662 mock.call('net-dns-create', net_dns_create_args)])
2663
2664 def test_configure_dns_multiple_dns_ip(self):
2665
2666 self.mock_object(self.client, 'send_request')
2667 mock_dns_ips = ['10.0.0.1', '10.0.0.2', '10.0.0.3']
2668 security_service = fake.CIFS_SECURITY_SERVICE
2669 security_service['dns_ip'] = ', '.join(mock_dns_ips)
2670
2671 self.client.configure_dns(security_service)
2672
2673 net_dns_create_args = {
2674 'domains': {'string': security_service['domain']},
2675 'dns-state': 'enabled',
2676 'name-servers': [{'ip-address': dns_ip} for dns_ip in mock_dns_ips]
2677 }
2678
2679 self.client.send_request.assert_has_calls([
2680 mock.call('net-dns-create', net_dns_create_args)])
2681
2682 def test_configure_dns_for_kerberos(self):
2683
2684 self.mock_object(self.client, 'send_request')
2685
2686 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE)
2687
2688 net_dns_create_args = {
2689 'domains': {'string': fake.KERBEROS_SECURITY_SERVICE['domain']},
2690 'name-servers': [{
2691 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip']
2692 }],
2693 'dns-state': 'enabled'
2694 }
2695
2696 self.client.send_request.assert_has_calls([
2697 mock.call('net-dns-create', net_dns_create_args)])
2698
2699 def test_configure_dns_already_present(self):
2700
2701 self.mock_object(self.client,
2702 'send_request',
2703 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
2704
2705 self.client.configure_dns(fake.KERBEROS_SECURITY_SERVICE)
2706
2707 net_dns_create_args = {
2708 'domains': {'string': fake.KERBEROS_SECURITY_SERVICE['domain']},
2709 'name-servers': [{
2710 'ip-address': fake.KERBEROS_SECURITY_SERVICE['dns_ip']
2711 }],
2712 'dns-state': 'enabled'
2713 }
2714
2715 self.client.send_request.assert_has_calls([
2716 mock.call('net-dns-create', net_dns_create_args)])
2717 self.assertEqual(1, client_cmode.LOG.error.call_count)
2718
2719 def test_configure_dns_api_error(self):
2720
2721 self.mock_object(self.client, 'send_request', self._mock_api_error())
2722
2723 self.assertRaises(exception.NetAppException,
2724 self.client.configure_dns,
2725 fake.KERBEROS_SECURITY_SERVICE)
2726
2727 @ddt.data(
2728 {
2729 'server': '',
2730 'check_feature': False
2731 },
2732 {
2733 'server': ['10.0.0.2', '10.0.0.3'],
2734 'check_feature': False
2735 },
2736 {
2737 'server': '10.0.0.1',
2738 'check_feature': False
2739 },
2740 {
2741 'server': '10.0.0.1',
2742 'check_feature': True
2743 }
2744 )
2745 @ddt.unpack
2746 def test_set_preferred_dc(self, server, check_feature):
2747 if check_feature:
2748 self.client.features.add_feature('CIFS_DC_ADD_SKIP_CHECK')
2749
2750 self.mock_object(self.client, 'send_request')
2751 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
2752 security_service['server'] = ', '.join(server)
2753
2754 self.client.set_preferred_dc(security_service)
2755
2756 if server is '':
2757 self.client.send_request.assert_not_called()
2758 else:
2759 preferred_dc_add_args = {
2760 'domain': fake.CIFS_SECURITY_SERVICE['domain'],
2761 'preferred-dc': [{'string': dc_ip} for dc_ip in server]
2762 }
2763
2764 if check_feature:
2765 preferred_dc_add_args['skip-config-validation'] = 'false'
2766
2767 self.client.send_request.assert_has_calls([
2768 mock.call('cifs-domain-preferred-dc-add',
2769 preferred_dc_add_args)])
2770
2771 def test_set_preferred_dc_api_error(self):
2772
2773 self.mock_object(self.client, 'send_request', self._mock_api_error())
2774 security_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
2775 security_service['server'] = 'fake_server'
2776
2777 self.assertRaises(exception.NetAppException,
2778 self.client.set_preferred_dc,
2779 security_service)
2780
2781 def test_create_volume(self):
2782
2783 self.mock_object(self.client, 'send_request')
2784 self.mock_object(self.client, 'update_volume_efficiency_attributes')
2785
2786 self.client.create_volume(
2787 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100)
2788
2789 volume_create_args = {
2790 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
2791 'size': '100g',
2792 'volume': fake.SHARE_NAME,
2793 'volume-type': 'rw',
2794 'junction-path': '/%s' % fake.SHARE_NAME,
2795 }
2796
2797 self.client.send_request.assert_called_once_with('volume-create',
2798 volume_create_args)
2799
2800 @ddt.data(None, fake.QOS_POLICY_GROUP_NAME)
2801 def test_create_volume_with_extra_specs(self, qos_policy_group_name):
2802
2803 self.mock_object(self.client, 'set_volume_max_files')
2804 self.mock_object(self.client, 'enable_dedup')
2805 self.mock_object(self.client, 'enable_compression')
2806 self.mock_object(self.client, 'send_request')
2807 self.mock_object(
2808 self.client,
2809 'get_volume_efficiency_status',
2810 mock.Mock(return_value={'dedupe': False, 'compression': False}))
2811
2812 self.client.create_volume(
2813 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100,
2814 thin_provisioned=True, language='en-US',
2815 snapshot_policy='default', dedup_enabled=True,
2816 compression_enabled=True, max_files=5000, snapshot_reserve=15,
2817 qos_policy_group=qos_policy_group_name)
2818
2819 volume_create_args = {
2820 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
2821 'size': '100g',
2822 'volume': fake.SHARE_NAME,
2823 'junction-path': '/%s' % fake.SHARE_NAME,
2824 'space-reserve': 'none',
2825 'language-code': 'en-US',
2826 'volume-type': 'rw',
2827 'snapshot-policy': 'default',
2828 'percentage-snapshot-reserve': '15',
2829 }
2830
2831 if qos_policy_group_name:
2832 volume_create_args.update(
2833 {'qos-policy-group-name': qos_policy_group_name})
2834
2835 self.client.send_request.assert_called_with('volume-create',
2836 volume_create_args)
2837 self.client.set_volume_max_files.assert_called_once_with(
2838 fake.SHARE_NAME, fake.MAX_FILES)
2839 self.client.enable_dedup.assert_called_once_with(fake.SHARE_NAME)
2840 self.client.enable_compression.assert_called_once_with(fake.SHARE_NAME)
2841
2842 def test_create_encrypted_volume(self):
2843
2844 self.mock_object(self.client, 'send_request')
2845 self.mock_object(self.client, 'update_volume_efficiency_attributes')
2846 self.client.features.add_feature('FLEXVOL_ENCRYPTION')
2847
2848 self.client.create_volume(
2849 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, encrypt=True)
2850
2851 volume_create_args = {
2852 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
2853 'size': '100g',
2854 'volume': fake.SHARE_NAME,
2855 'volume-type': 'rw',
2856 'junction-path': '/%s' % fake.SHARE_NAME,
2857 'encrypt': 'true',
2858 }
2859
2860 self.client.send_request.assert_called_once_with('volume-create',
2861 volume_create_args)
2862
2863 def test_create_non_encrypted_volume(self):
2864
2865 self.mock_object(self.client, 'send_request')
2866 self.mock_object(self.client, 'update_volume_efficiency_attributes')
2867 self.client.features.add_feature('FLEXVOL_ENCRYPTION')
2868
2869 self.client.create_volume(
2870 fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME, 100, encrypt=False)
2871
2872 volume_create_args = {
2873 'containing-aggr-name': fake.SHARE_AGGREGATE_NAME,
2874 'size': '100g',
2875 'volume': fake.SHARE_NAME,
2876 'volume-type': 'rw',
2877 'junction-path': '/%s' % fake.SHARE_NAME,
2878 }
2879
2880 self.client.send_request.assert_called_once_with('volume-create',
2881 volume_create_args)
2882
2883 def test_create_encrypted_volume_not_supported(self):
2884
2885 self.assertRaises(exception.NetAppException,
2886 self.client.create_volume,
2887 fake.SHARE_AGGREGATE_NAME,
2888 fake.SHARE_NAME,
2889 100,
2890 encrypt=True)
2891
2892 def test_is_flexvol_encrypted_unsupported(self):
2893
2894 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=False)
2895
2896 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
2897 fake.VSERVER_NAME)
2898
2899 self.assertFalse(result)
2900
2901 def test_is_flexvol_encrypted_no_records_found(self):
2902
2903 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
2904 self.mock_object(self.client,
2905 'send_iter_request',
2906 mock.Mock(return_value=api_response))
2907
2908 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
2909 fake.VSERVER_NAME)
2910
2911 self.assertFalse(result)
2912
2913 def test_is_flexvol_encrypted(self):
2914
2915 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True)
2916 api_response = netapp_api.NaElement(
2917 fake.GET_VOLUME_FOR_ENCRYPTED_RESPONSE)
2918 self.mock_object(self.client,
2919 'send_iter_request',
2920 mock.Mock(return_value=api_response))
2921
2922 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
2923 fake.VSERVER_NAME)
2924
2925 volume_get_iter_args = {
2926 'query': {
2927 'volume-attributes': {
2928 'encrypt': 'true',
2929 'volume-id-attributes': {
2930 'name': fake.SHARE_NAME,
2931 'owning-vserver-name': fake.VSERVER_NAME,
2932 }
2933 }
2934 },
2935 'desired-attributes': {
2936 'volume-attributes': {
2937 'encrypt': None,
2938 }
2939 }
2940 }
2941
2942 self.client.send_iter_request.assert_called_once_with(
2943 'volume-get-iter', volume_get_iter_args)
2944
2945 self.assertTrue(result)
2946
2947 def test_is_flexvol_encrypted_8_x_system_version_response(self):
2948
2949 self.client.features.add_feature('FLEXVOL_ENCRYPTION', supported=True)
2950 api_response = netapp_api.NaElement(
2951 fake.GET_VOLUME_FOR_ENCRYPTED_OLD_SYS_VERSION_RESPONSE)
2952 self.mock_object(self.client,
2953 'send_iter_request',
2954 mock.Mock(return_value=api_response))
2955
2956 result = self.client.is_flexvol_encrypted(fake.SHARE_NAME,
2957 fake.VSERVER_NAME)
2958
2959 volume_get_iter_args = {
2960 'query': {
2961 'volume-attributes': {
2962 'encrypt': 'true',
2963 'volume-id-attributes': {
2964 'name': fake.SHARE_NAME,
2965 'owning-vserver-name': fake.VSERVER_NAME,
2966 }
2967 }
2968 },
2969 'desired-attributes': {
2970 'volume-attributes': {
2971 'encrypt': None,
2972 }
2973 }
2974 }
2975
2976 self.client.send_iter_request.assert_called_once_with(
2977 'volume-get-iter', volume_get_iter_args)
2978
2979 self.assertFalse(result)
2980
2981 def test_enable_dedup(self):
2982
2983 self.mock_object(self.client, 'send_request')
2984
2985 self.client.enable_dedup(fake.SHARE_NAME)
2986
2987 sis_enable_args = {'path': '/vol/%s' % fake.SHARE_NAME}
2988
2989 self.client.send_request.assert_called_once_with('sis-enable',
2990 sis_enable_args)
2991
2992 def test_disable_dedup(self):
2993
2994 self.mock_object(self.client, 'send_request')
2995
2996 self.client.disable_dedup(fake.SHARE_NAME)
2997
2998 sis_disable_args = {'path': '/vol/%s' % fake.SHARE_NAME}
2999
3000 self.client.send_request.assert_called_once_with('sis-disable',
3001 sis_disable_args)
3002
3003 def test_enable_compression(self):
3004
3005 self.mock_object(self.client, 'send_request')
3006
3007 self.client.enable_compression(fake.SHARE_NAME)
3008
3009 sis_set_config_args = {
3010 'path': '/vol/%s' % fake.SHARE_NAME,
3011 'enable-compression': 'true'
3012 }
3013
3014 self.client.send_request.assert_called_once_with('sis-set-config',
3015 sis_set_config_args)
3016
3017 def test_disable_compression(self):
3018
3019 self.mock_object(self.client, 'send_request')
3020
3021 self.client.disable_compression(fake.SHARE_NAME)
3022
3023 sis_set_config_args = {
3024 'path': '/vol/%s' % fake.SHARE_NAME,
3025 'enable-compression': 'false'
3026 }
3027
3028 self.client.send_request.assert_called_once_with('sis-set-config',
3029 sis_set_config_args)
3030
3031 def test_get_volume_efficiency_status(self):
3032
3033 api_response = netapp_api.NaElement(fake.SIS_GET_ITER_RESPONSE)
3034 self.mock_object(self.client,
3035 'send_iter_request',
3036 mock.Mock(return_value=api_response))
3037
3038 result = self.client.get_volume_efficiency_status(fake.SHARE_NAME)
3039
3040 sis_get_iter_args = {
3041 'query': {
3042 'sis-status-info': {
3043 'path': '/vol/%s' % fake.SHARE_NAME,
3044 },
3045 },
3046 'desired-attributes': {
3047 'sis-status-info': {
3048 'state': None,
3049 'is-compression-enabled': None,
3050 },
3051 },
3052 }
3053 self.client.send_iter_request.assert_has_calls([
3054 mock.call('sis-get-iter', sis_get_iter_args)])
3055
3056 expected = {'dedupe': True, 'compression': True}
3057 self.assertDictEqual(expected, result)
3058
3059 def test_get_volume_efficiency_status_not_found(self):
3060
3061 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3062 self.mock_object(self.client,
3063 'send_iter_request',
3064 mock.Mock(return_value=api_response))
3065
3066 result = self.client.get_volume_efficiency_status(fake.SHARE_NAME)
3067
3068 expected = {'dedupe': False, 'compression': False}
3069 self.assertDictEqual(expected, result)
3070
3071 def test_set_volume_max_files(self):
3072
3073 self.mock_object(self.client, 'send_request')
3074
3075 self.client.set_volume_max_files(fake.SHARE_NAME, fake.MAX_FILES)
3076
3077 volume_modify_iter_api_args = {
3078 'query': {
3079 'volume-attributes': {
3080 'volume-id-attributes': {
3081 'name': fake.SHARE_NAME,
3082 },
3083 },
3084 },
3085 'attributes': {
3086 'volume-attributes': {
3087 'volume-inode-attributes': {
3088 'files-total': fake.MAX_FILES,
3089 },
3090 },
3091 },
3092 }
3093
3094 self.client.send_request.assert_called_once_with(
3095 'volume-modify-iter', volume_modify_iter_api_args)
3096
3097 def test_set_volume_name(self):
3098
3099 self.mock_object(self.client, 'send_request')
3100
3101 self.client.set_volume_name(fake.SHARE_NAME, 'new_name')
3102
3103 volume_rename_api_args = {
3104 'volume': fake.SHARE_NAME,
3105 'new-volume-name': 'new_name',
3106 }
3107
3108 self.client.send_request.assert_called_once_with(
3109 'volume-rename', volume_rename_api_args)
3110
3111 def test_rename_vserver(self):
3112
3113 vserver_api_args = {
3114 'vserver-name': fake.VSERVER_NAME,
3115 'new-name': fake.VSERVER_NAME_2,
3116 }
3117 self.mock_object(self.client, 'send_request')
3118
3119 self.client.rename_vserver(fake.VSERVER_NAME, fake.VSERVER_NAME_2)
3120
3121 self.client.send_request.assert_called_once_with(
3122 'vserver-rename', vserver_api_args
3123 )
3124
3125 def test_modify_volume_no_optional_args(self):
3126
3127 self.mock_object(self.client, 'send_request')
3128 mock_update_volume_efficiency_attributes = self.mock_object(
3129 self.client, 'update_volume_efficiency_attributes')
3130
3131 self.client.modify_volume(fake.SHARE_AGGREGATE_NAME, fake.SHARE_NAME)
3132
3133 volume_modify_iter_api_args = {
3134 'query': {
3135 'volume-attributes': {
3136 'volume-id-attributes': {
3137 'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
3138 'name': fake.SHARE_NAME,
3139 },
3140 },
3141 },
3142 'attributes': {
3143 'volume-attributes': {
3144 'volume-inode-attributes': {},
3145 'volume-language-attributes': {},
3146 'volume-snapshot-attributes': {},
3147 'volume-space-attributes': {
3148 'space-guarantee': 'volume',
3149 },
3150 },
3151 },
3152 }
3153
3154 self.client.send_request.assert_called_once_with(
3155 'volume-modify-iter', volume_modify_iter_api_args)
3156 mock_update_volume_efficiency_attributes.assert_called_once_with(
3157 fake.SHARE_NAME, False, False)
3158
3159 def test_modify_volume_all_optional_args(self):
3160
3161 self.mock_object(self.client, 'send_request')
3162 mock_update_volume_efficiency_attributes = self.mock_object(
3163 self.client, 'update_volume_efficiency_attributes')
3164
3165 self.client.modify_volume(fake.SHARE_AGGREGATE_NAME,
3166 fake.SHARE_NAME,
3167 thin_provisioned=True,
3168 snapshot_policy=fake.SNAPSHOT_POLICY_NAME,
3169 language=fake.LANGUAGE,
3170 dedup_enabled=True,
3171 compression_enabled=False,
3172 max_files=fake.MAX_FILES,
3173 qos_policy_group=fake.QOS_POLICY_GROUP_NAME,
3174 hide_snapdir=True)
3175
3176 volume_modify_iter_api_args = {
3177 'query': {
3178 'volume-attributes': {
3179 'volume-id-attributes': {
3180 'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
3181 'name': fake.SHARE_NAME,
3182 },
3183 },
3184 },
3185 'attributes': {
3186 'volume-attributes': {
3187 'volume-inode-attributes': {
3188 'files-total': fake.MAX_FILES,
3189 },
3190 'volume-language-attributes': {
3191 'language': fake.LANGUAGE,
3192 },
3193 'volume-snapshot-attributes': {
3194 'snapshot-policy': fake.SNAPSHOT_POLICY_NAME,
3195 'snapdir-access-enabled': 'false'
3196 },
3197 'volume-space-attributes': {
3198 'space-guarantee': 'none',
3199 },
3200 'volume-qos-attributes': {
3201 'policy-group-name': fake.QOS_POLICY_GROUP_NAME,
3202 },
3203
3204 },
3205 },
3206 }
3207
3208 self.client.send_request.assert_called_once_with(
3209 'volume-modify-iter', volume_modify_iter_api_args)
3210 mock_update_volume_efficiency_attributes.assert_called_once_with(
3211 fake.SHARE_NAME, True, False)
3212
3213 @ddt.data(
3214 {'existing': (True, True), 'desired': (True, True)},
3215 {'existing': (True, True), 'desired': (False, False)},
3216 {'existing': (True, True), 'desired': (True, False)},
3217 {'existing': (True, False), 'desired': (True, False)},
3218 {'existing': (True, False), 'desired': (False, False)},
3219 {'existing': (True, False), 'desired': (True, True)},
3220 {'existing': (False, False), 'desired': (False, False)},
3221 {'existing': (False, False), 'desired': (True, False)},
3222 {'existing': (False, False), 'desired': (True, True)},
3223 )
3224 @ddt.unpack
3225 def test_update_volume_efficiency_attributes(self, existing, desired):
3226
3227 existing_dedupe = existing[0]
3228 existing_compression = existing[1]
3229 desired_dedupe = desired[0]
3230 desired_compression = desired[1]
3231
3232 self.mock_object(
3233 self.client,
3234 'get_volume_efficiency_status',
3235 mock.Mock(return_value={'dedupe': existing_dedupe,
3236 'compression': existing_compression}))
3237 mock_enable_compression = self.mock_object(self.client,
3238 'enable_compression')
3239 mock_disable_compression = self.mock_object(self.client,
3240 'disable_compression')
3241 mock_enable_dedup = self.mock_object(self.client, 'enable_dedup')
3242 mock_disable_dedup = self.mock_object(self.client, 'disable_dedup')
3243
3244 self.client.update_volume_efficiency_attributes(
3245 fake.SHARE_NAME, desired_dedupe, desired_compression)
3246
3247 if existing_dedupe == desired_dedupe:
3248 self.assertFalse(mock_enable_dedup.called)
3249 self.assertFalse(mock_disable_dedup.called)
3250 elif existing_dedupe and not desired_dedupe:
3251 self.assertFalse(mock_enable_dedup.called)
3252 self.assertTrue(mock_disable_dedup.called)
3253 elif not existing_dedupe and desired_dedupe:
3254 self.assertTrue(mock_enable_dedup.called)
3255 self.assertFalse(mock_disable_dedup.called)
3256
3257 if existing_compression == desired_compression:
3258 self.assertFalse(mock_enable_compression.called)
3259 self.assertFalse(mock_disable_compression.called)
3260 elif existing_compression and not desired_compression:
3261 self.assertFalse(mock_enable_compression.called)
3262 self.assertTrue(mock_disable_compression.called)
3263 elif not existing_compression and desired_compression:
3264 self.assertTrue(mock_enable_compression.called)
3265 self.assertFalse(mock_disable_compression.called)
3266
3267 def test_set_volume_size(self):
3268
3269 api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE)
3270 self.mock_object(self.client,
3271 'send_request',
3272 mock.Mock(return_value=api_response))
3273
3274 self.client.set_volume_size(fake.SHARE_NAME, 10)
3275
3276 volume_modify_iter_args = {
3277 'query': {
3278 'volume-attributes': {
3279 'volume-id-attributes': {
3280 'name': fake.SHARE_NAME
3281 }
3282 }
3283 },
3284 'attributes': {
3285 'volume-attributes': {
3286 'volume-space-attributes': {
3287 'size': 10737418240,
3288 },
3289 },
3290 },
3291 }
3292 self.client.send_request.assert_has_calls([
3293 mock.call('volume-modify-iter', volume_modify_iter_args)])
3294
3295 @ddt.data(True, False)
3296 def test_set_volume_snapdir_access(self, hide_snapdir):
3297 api_response = netapp_api.NaElement(
3298 fake.VOLUME_MODIFY_ITER_RESPONSE)
3299 self.mock_object(self.client,
3300 'send_request',
3301 mock.Mock(return_value=api_response))
3302
3303 self.client.set_volume_snapdir_access(fake.SHARE_NAME, hide_snapdir)
3304
3305 api_args = {
3306 'query': {
3307 'volume-attributes': {
3308 'volume-id-attributes': {
3309 'name': fake.SHARE_NAME
3310 }
3311 }
3312 },
3313 'attributes': {
3314 'volume-attributes': {
3315 'volume-snapshot-attributes': {
3316 'snapdir-access-enabled': six.text_type(
3317 not hide_snapdir).lower(),
3318 },
3319 },
3320 },
3321 }
3322 self.client.send_request.assert_called_once_with(
3323 'volume-modify-iter', api_args)
3324
3325 def test_set_volume_snapdir_access_api_error(self):
3326
3327 api_response = netapp_api.NaElement(
3328 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
3329 self.mock_object(self.client,
3330 'send_request',
3331 mock.Mock(return_value=api_response))
3332
3333 self.assertRaises(netapp_api.NaApiError,
3334 self.client.set_volume_size,
3335 fake.SHARE_NAME,
3336 10)
3337
3338 @ddt.data(True, False)
3339 def test_set_volume_filesys_size_fixed(self, filesys_size_fixed):
3340 api_response = netapp_api.NaElement(
3341 fake.VOLUME_MODIFY_ITER_RESPONSE)
3342 self.mock_object(self.client,
3343 'send_request',
3344 mock.Mock(return_value=api_response))
3345
3346 self.client.set_volume_filesys_size_fixed(fake.SHARE_NAME,
3347 filesys_size_fixed)
3348
3349 api_args = {
3350 'query': {
3351 'volume-attributes': {
3352 'volume-id-attributes': {
3353 'name': fake.SHARE_NAME
3354 }
3355 }
3356 },
3357 'attributes': {
3358 'volume-attributes': {
3359 'volume-space-attributes': {
3360 'is-filesys-size-fixed': six.text_type(
3361 filesys_size_fixed).lower(),
3362 },
3363 },
3364 },
3365 }
3366 self.client.send_request.assert_called_once_with(
3367 'volume-modify-iter', api_args)
3368
3369 def test_set_volume_size_api_error(self):
3370
3371 api_response = netapp_api.NaElement(
3372 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
3373 self.mock_object(self.client,
3374 'send_request',
3375 mock.Mock(return_value=api_response))
3376
3377 self.assertRaises(netapp_api.NaApiError,
3378 self.client.set_volume_size,
3379 fake.SHARE_NAME,
3380 10)
3381
3382 @ddt.data(None, 'ntfs')
3383 def test_set_volume_security_style(self, security_style):
3384
3385 api_response = netapp_api.NaElement(fake.VOLUME_MODIFY_ITER_RESPONSE)
3386 self.mock_object(self.client,
3387 'send_request',
3388 mock.Mock(return_value=api_response))
3389 kwargs = {'security_style': security_style} if security_style else {}
3390
3391 self.client.set_volume_security_style(fake.SHARE_NAME, **kwargs)
3392
3393 volume_modify_iter_args = {
3394 'query': {
3395 'volume-attributes': {
3396 'volume-id-attributes': {
3397 'name': fake.SHARE_NAME
3398 }
3399 }
3400 },
3401 'attributes': {
3402 'volume-attributes': {
3403 'volume-security-attributes': {
3404 'style': security_style or 'unix',
3405 },
3406 },
3407 },
3408 }
3409 self.client.send_request.assert_called_once_with(
3410 'volume-modify-iter', volume_modify_iter_args)
3411
3412 def test_set_volume_security_style_api_error(self):
3413
3414 api_response = netapp_api.NaElement(
3415 fake.VOLUME_MODIFY_ITER_ERROR_RESPONSE)
3416 self.mock_object(self.client,
3417 'send_request',
3418 mock.Mock(return_value=api_response))
3419
3420 self.assertRaises(netapp_api.NaApiError,
3421 self.client.set_volume_security_style,
3422 fake.SHARE_NAME,
3423 'ntfs')
3424
3425 def test_volume_exists(self):
3426
3427 api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE)
3428 self.mock_object(self.client,
3429 'send_iter_request',
3430 mock.Mock(return_value=api_response))
3431
3432 result = self.client.volume_exists(fake.SHARE_NAME)
3433
3434 volume_get_iter_args = {
3435 'query': {
3436 'volume-attributes': {
3437 'volume-id-attributes': {
3438 'name': fake.SHARE_NAME
3439 }
3440 }
3441 },
3442 'desired-attributes': {
3443 'volume-attributes': {
3444 'volume-id-attributes': {
3445 'name': None
3446 }
3447 }
3448 }
3449 }
3450
3451 self.client.send_iter_request.assert_has_calls([
3452 mock.call('volume-get-iter', volume_get_iter_args)])
3453 self.assertTrue(result)
3454
3455 def test_volume_exists_not_found(self):
3456
3457 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3458 self.mock_object(self.client,
3459 'send_request',
3460 mock.Mock(return_value=api_response))
3461
3462 self.assertFalse(self.client.volume_exists(fake.SHARE_NAME))
3463
3464 def test_snapshot_exists(self):
3465
3466 api_response = netapp_api.NaElement(fake.VOLUME_GET_NAME_RESPONSE)
3467 self.mock_object(self.client,
3468 'send_request',
3469 mock.Mock(return_value=api_response))
3470
3471 result = self.client.snapshot_exists(fake.SNAPSHOT_NAME,
3472 fake.SHARE_NAME)
3473
3474 snapshot_get_iter_args = {
3475 'query': {
3476 'snapshot-info': {
3477 'name': fake.SNAPSHOT_NAME,
3478 'volume': fake.SHARE_NAME,
3479 }
3480 },
3481 'desired-attributes': {
3482 'snapshot-info': {
3483 'name': None,
3484 'volume': None,
3485 'busy': None,
3486 'snapshot-owners-list': {
3487 'snapshot-owner': None,
3488 }
3489 }
3490 }
3491 }
3492
3493 self.client.send_request.assert_has_calls([
3494 mock.call('snapshot-get-iter', snapshot_get_iter_args)])
3495 self.assertTrue(result)
3496
3497 def test_snapshot_exists_not_found(self):
3498 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3499 self.mock_object(self.client,
3500 'send_request',
3501 mock.Mock(return_value=api_response))
3502
3503 self.assertFalse(self.client.snapshot_exists(fake.SNAPSHOT_NAME,
3504 fake.SHARE_NAME))
3505
3506 @ddt.data({
3507 'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE,
3508 'raised_exception': exception.SnapshotUnavailable,
3509 }, {
3510 'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE,
3511 'raised_exception': exception.NetAppException,
3512 })
3513 @ddt.unpack
3514 def test_snapshot_exists_error(self, api_response_xml, raised_exception):
3515
3516 api_response = netapp_api.NaElement(api_response_xml)
3517 self.mock_object(self.client,
3518 'send_request',
3519 mock.Mock(return_value=api_response))
3520
3521 self.assertRaises(raised_exception,
3522 self.client.snapshot_exists,
3523 fake.SNAPSHOT_NAME,
3524 fake.SHARE_NAME)
3525
3526 def test_get_aggregate_for_volume(self):
3527
3528 api_response = netapp_api.NaElement(
3529 fake.GET_AGGREGATE_FOR_VOLUME_RESPONSE)
3530 self.mock_object(self.client,
3531 'send_iter_request',
3532 mock.Mock(return_value=api_response))
3533
3534 result = self.client.get_aggregate_for_volume(fake.SHARE_NAME)
3535
3536 volume_get_iter_args = {
3537 'query': {
3538 'volume-attributes': {
3539 'volume-id-attributes': {
3540 'name': fake.SHARE_NAME
3541 }
3542 }
3543 },
3544 'desired-attributes': {
3545 'volume-attributes': {
3546 'volume-id-attributes': {
3547 'containing-aggregate-name': None,
3548 'name': None
3549 }
3550 }
3551 }
3552 }
3553
3554 self.client.send_iter_request.assert_has_calls([
3555 mock.call('volume-get-iter', volume_get_iter_args)])
3556 self.assertEqual(fake.SHARE_AGGREGATE_NAME, result)
3557
3558 def test_get_aggregate_for_volume_not_found(self):
3559
3560 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3561 self.mock_object(self.client,
3562 'send_iter_request',
3563 mock.Mock(return_value=api_response))
3564
3565 self.assertRaises(exception.NetAppException,
3566 self.client.get_aggregate_for_volume,
3567 fake.SHARE_NAME)
3568
3569 def test_volume_has_luns(self):
3570
3571 api_response = netapp_api.NaElement(fake.LUN_GET_ITER_RESPONSE)
3572 self.mock_object(self.client,
3573 'send_iter_request',
3574 mock.Mock(return_value=api_response))
3575
3576 result = self.client.volume_has_luns(fake.SHARE_NAME)
3577
3578 lun_get_iter_args = {
3579 'query': {
3580 'lun-info': {
3581 'volume': fake.SHARE_NAME,
3582 },
3583 },
3584 'desired-attributes': {
3585 'lun-info': {
3586 'path': None,
3587 },
3588 },
3589 }
3590
3591 self.client.send_iter_request.assert_has_calls([
3592 mock.call('lun-get-iter', lun_get_iter_args)])
3593 self.assertTrue(result)
3594
3595 def test_volume_has_luns_not_found(self):
3596
3597 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3598 self.mock_object(self.client,
3599 'send_request',
3600 mock.Mock(return_value=api_response))
3601
3602 result = self.client.volume_has_luns(fake.SHARE_NAME)
3603
3604 self.assertFalse(result)
3605
3606 def test_volume_has_junctioned_volumes(self):
3607
3608 api_response = netapp_api.NaElement(
3609 fake.VOLUME_GET_ITER_JUNCTIONED_VOLUMES_RESPONSE)
3610 self.mock_object(self.client,
3611 'send_iter_request',
3612 mock.Mock(return_value=api_response))
3613
3614 fake_junction_path = '/%s' % fake.SHARE_NAME
3615 self.mock_object(self.client,
3616 'get_volume_junction_path',
3617 mock.Mock(return_value=fake_junction_path))
3618
3619 result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
3620
3621 volume_get_iter_args = {
3622 'query': {
3623 'volume-attributes': {
3624 'volume-id-attributes': {
3625 'junction-path': fake_junction_path + '/*',
3626 },
3627 },
3628 },
3629 'desired-attributes': {
3630 'volume-attributes': {
3631 'volume-id-attributes': {
3632 'name': None,
3633 },
3634 },
3635 },
3636 }
3637 self.client.send_iter_request.assert_has_calls([
3638 mock.call('volume-get-iter', volume_get_iter_args)])
3639 self.assertTrue(result)
3640
3641 def test_volume_has_junctioned_volumes_no_junction_path(self):
3642
3643 self.mock_object(self.client,
3644 'get_volume_junction_path',
3645 mock.Mock(return_value=''))
3646
3647 result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
3648
3649 self.assertFalse(result)
3650
3651 def test_volume_has_junctioned_volumes_not_found(self):
3652
3653 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3654 self.mock_object(self.client,
3655 'send_request',
3656 mock.Mock(return_value=api_response))
3657
3658 fake_junction_path = '/%s' % fake.SHARE_NAME
3659 self.mock_object(self.client,
3660 'get_volume_junction_path',
3661 mock.Mock(return_value=fake_junction_path))
3662
3663 result = self.client.volume_has_junctioned_volumes(fake.SHARE_NAME)
3664
3665 self.assertFalse(result)
3666
3667 def test_get_volume(self):
3668
3669 api_response = netapp_api.NaElement(
3670 fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
3671 self.mock_object(self.client,
3672 'send_request',
3673 mock.Mock(return_value=api_response))
3674
3675 result = self.client.get_volume(fake.SHARE_NAME)
3676
3677 volume_get_iter_args = {
3678 'query': {
3679 'volume-attributes': {
3680 'volume-id-attributes': {
3681 'name': fake.SHARE_NAME,
3682 },
3683 },
3684 },
3685 'desired-attributes': {
3686 'volume-attributes': {
3687 'volume-id-attributes': {
3688 'containing-aggregate-name': None,
3689 'junction-path': None,
3690 'name': None,
3691 'owning-vserver-name': None,
3692 'type': None,
3693 'style': None,
3694 },
3695 'volume-space-attributes': {
3696 'size': None,
3697 },
3698 'volume-qos-attributes': {
3699 'policy-group-name': None,
3700 },
3701 },
3702 },
3703 }
3704
3705 expected = {
3706 'aggregate': fake.SHARE_AGGREGATE_NAME,
3707 'junction-path': '/%s' % fake.SHARE_NAME,
3708 'name': fake.SHARE_NAME,
3709 'type': 'rw',
3710 'style': 'flex',
3711 'size': fake.SHARE_SIZE,
3712 'owning-vserver-name': fake.VSERVER_NAME,
3713 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME,
3714 }
3715 self.client.send_request.assert_has_calls([
3716 mock.call('volume-get-iter', volume_get_iter_args)])
3717 self.assertDictEqual(expected, result)
3718
3719 def test_get_volume_no_qos(self):
3720 api_response = netapp_api.NaElement(
3721 fake.VOLUME_GET_ITER_NO_QOS_RESPONSE)
3722 self.mock_object(self.client,
3723 'send_request',
3724 mock.Mock(return_value=api_response))
3725
3726 result = self.client.get_volume(fake.SHARE_NAME)
3727
3728 volume_get_iter_args = {
3729 'query': {
3730 'volume-attributes': {
3731 'volume-id-attributes': {
3732 'name': fake.SHARE_NAME,
3733 },
3734 },
3735 },
3736 'desired-attributes': {
3737 'volume-attributes': {
3738 'volume-id-attributes': {
3739 'containing-aggregate-name': None,
3740 'junction-path': None,
3741 'name': None,
3742 'owning-vserver-name': None,
3743 'type': None,
3744 'style': None,
3745 },
3746 'volume-space-attributes': {
3747 'size': None,
3748 },
3749 'volume-qos-attributes': {
3750 'policy-group-name': None,
3751 },
3752 },
3753 },
3754 }
3755
3756 expected = {
3757 'aggregate': fake.SHARE_AGGREGATE_NAME,
3758 'junction-path': '/%s' % fake.SHARE_NAME,
3759 'name': fake.SHARE_NAME,
3760 'type': 'rw',
3761 'style': 'flex',
3762 'size': fake.SHARE_SIZE,
3763 'owning-vserver-name': fake.VSERVER_NAME,
3764 'qos-policy-group-name': None,
3765 }
3766 self.client.send_request.assert_has_calls([
3767 mock.call('volume-get-iter', volume_get_iter_args)])
3768 self.assertDictEqual(expected, result)
3769
3770 def test_get_volume_not_found(self):
3771
3772 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3773 self.mock_object(self.client,
3774 'send_request',
3775 mock.Mock(return_value=api_response))
3776
3777 self.assertRaises(exception.StorageResourceNotFound,
3778 self.client.get_volume,
3779 fake.SHARE_NAME)
3780
3781 def test_get_volume_not_unique(self):
3782
3783 api_response = netapp_api.NaElement(
3784 fake.VOLUME_GET_ITER_NOT_UNIQUE_RESPONSE)
3785 self.mock_object(self.client,
3786 'send_request',
3787 mock.Mock(return_value=api_response))
3788
3789 self.assertRaises(exception.NetAppException,
3790 self.client.get_volume,
3791 fake.SHARE_NAME)
3792
3793 def test_get_volume_at_junction_path(self):
3794
3795 api_response = netapp_api.NaElement(
3796 fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
3797 self.mock_object(self.client,
3798 'send_iter_request',
3799 mock.Mock(return_value=api_response))
3800 fake_junction_path = '/%s' % fake.SHARE_NAME
3801
3802 result = self.client.get_volume_at_junction_path(fake_junction_path)
3803
3804 volume_get_iter_args = {
3805 'query': {
3806 'volume-attributes': {
3807 'volume-id-attributes': {
3808 'junction-path': fake_junction_path,
3809 },
3810 },
3811 },
3812 'desired-attributes': {
3813 'volume-attributes': {
3814 'volume-id-attributes': {
3815 'containing-aggregate-name': None,
3816 'junction-path': None,
3817 'name': None,
3818 'type': None,
3819 'style': None,
3820 },
3821 'volume-space-attributes': {
3822 'size': None,
3823 }
3824 },
3825 },
3826 }
3827 expected = {
3828 'aggregate': fake.SHARE_AGGREGATE_NAME,
3829 'junction-path': fake_junction_path,
3830 'name': fake.SHARE_NAME,
3831 'type': 'rw',
3832 'style': 'flex',
3833 'size': fake.SHARE_SIZE,
3834 }
3835 self.client.send_iter_request.assert_has_calls([
3836 mock.call('volume-get-iter', volume_get_iter_args)])
3837 self.assertDictEqual(expected, result)
3838
3839 def test_get_volume_at_junction_path_not_specified(self):
3840
3841 result = self.client.get_volume_at_junction_path(None)
3842
3843 self.assertIsNone(result)
3844
3845 def test_get_volume_at_junction_path_not_found(self):
3846
3847 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3848 self.mock_object(self.client,
3849 'send_iter_request',
3850 mock.Mock(return_value=api_response))
3851 fake_junction_path = '/%s' % fake.SHARE_NAME
3852
3853 result = self.client.get_volume_at_junction_path(fake_junction_path)
3854
3855 self.assertIsNone(result)
3856
3857 def test_get_volume_to_manage(self):
3858
3859 api_response = netapp_api.NaElement(
3860 fake.VOLUME_GET_ITER_VOLUME_TO_MANAGE_RESPONSE)
3861 self.mock_object(self.client,
3862 'send_iter_request',
3863 mock.Mock(return_value=api_response))
3864
3865 result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME,
3866 fake.SHARE_NAME)
3867
3868 volume_get_iter_args = {
3869 'query': {
3870 'volume-attributes': {
3871 'volume-id-attributes': {
3872 'containing-aggregate-name': fake.SHARE_AGGREGATE_NAME,
3873 'name': fake.SHARE_NAME,
3874 },
3875 },
3876 },
3877 'desired-attributes': {
3878 'volume-attributes': {
3879 'volume-id-attributes': {
3880 'containing-aggregate-name': None,
3881 'junction-path': None,
3882 'name': None,
3883 'type': None,
3884 'style': None,
3885 'owning-vserver-name': None,
3886 },
3887 'volume-space-attributes': {
3888 'size': None,
3889 },
3890 'volume-qos-attributes': {
3891 'policy-group-name': None,
3892 },
3893 },
3894 },
3895 }
3896 expected = {
3897 'aggregate': fake.SHARE_AGGREGATE_NAME,
3898 'junction-path': '/%s' % fake.SHARE_NAME,
3899 'name': fake.SHARE_NAME,
3900 'type': 'rw',
3901 'style': 'flex',
3902 'size': fake.SHARE_SIZE,
3903 'owning-vserver-name': fake.VSERVER_NAME,
3904 'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME,
3905 }
3906 self.client.send_iter_request.assert_has_calls([
3907 mock.call('volume-get-iter', volume_get_iter_args)])
3908 self.assertDictEqual(expected, result)
3909
3910 def test_get_volume_to_manage_not_found(self):
3911
3912 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
3913 self.mock_object(self.client,
3914 'send_iter_request',
3915 mock.Mock(return_value=api_response))
3916
3917 result = self.client.get_volume_to_manage(fake.SHARE_AGGREGATE_NAME,
3918 fake.SHARE_NAME)
3919
3920 self.assertIsNone(result)
3921
3922 @ddt.data(None, fake.QOS_POLICY_GROUP_NAME)
3923 def test_create_volume_clone(self, qos_policy_group_name):
3924
3925 self.mock_object(self.client, 'send_request')
3926 self.mock_object(self.client, 'split_volume_clone')
3927
3928 self.client.create_volume_clone(fake.SHARE_NAME,
3929 fake.PARENT_SHARE_NAME,
3930 fake.PARENT_SNAPSHOT_NAME,
3931 qos_policy_group=qos_policy_group_name)
3932
3933 volume_clone_create_args = {
3934 'volume': fake.SHARE_NAME,
3935 'parent-volume': fake.PARENT_SHARE_NAME,
3936 'parent-snapshot': fake.PARENT_SNAPSHOT_NAME,
3937 'junction-path': '/%s' % fake.SHARE_NAME
3938 }
3939
3940 if qos_policy_group_name:
3941 volume_clone_create_args.update(
3942 {'qos-policy-group-name': fake.QOS_POLICY_GROUP_NAME})
3943
3944 self.client.send_request.assert_has_calls([
3945 mock.call('volume-clone-create', volume_clone_create_args)])
3946 self.assertFalse(self.client.split_volume_clone.called)
3947
3948 @ddt.data(True, False)
3949 def test_create_volume_clone_split(self, split):
3950
3951 self.mock_object(self.client, 'send_request')
3952 self.mock_object(self.client, 'split_volume_clone')
3953
3954 self.client.create_volume_clone(fake.SHARE_NAME,
3955 fake.PARENT_SHARE_NAME,
3956 fake.PARENT_SNAPSHOT_NAME,
3957 split=split)
3958
3959 volume_clone_create_args = {
3960 'volume': fake.SHARE_NAME,
3961 'parent-volume': fake.PARENT_SHARE_NAME,
3962 'parent-snapshot': fake.PARENT_SNAPSHOT_NAME,
3963 'junction-path': '/%s' % fake.SHARE_NAME
3964 }
3965
3966 self.client.send_request.assert_has_calls([
3967 mock.call('volume-clone-create', volume_clone_create_args)])
3968 if split:
3969 self.client.split_volume_clone.assert_called_once_with(
3970 fake.SHARE_NAME)
3971 else:
3972 self.assertFalse(self.client.split_volume_clone.called)
3973
3974 @ddt.data(None,
3975 mock.Mock(side_effect=netapp_api.NaApiError(
3976 code=netapp_api.EVOL_CLONE_BEING_SPLIT)))
3977 def test_split_volume_clone(self, side_effect):
3978
3979 self.mock_object(
3980 self.client, 'send_request',
3981 mock.Mock(side_effect=side_effect))
3982
3983 self.client.split_volume_clone(fake.SHARE_NAME)
3984
3985 volume_clone_split_args = {'volume': fake.SHARE_NAME}
3986
3987 self.client.send_request.assert_has_calls([
3988 mock.call('volume-clone-split-start', volume_clone_split_args)])
3989
3990 def test_split_volume_clone_api_error(self):
3991
3992 self.mock_object(self.client,
3993 'send_request',
3994 mock.Mock(side_effect=self._mock_api_error()))
3995
3996 self.assertRaises(netapp_api.NaApiError,
3997 self.client.split_volume_clone,
3998 fake.SHARE_NAME)
3999
4000 def test_get_clone_children_for_snapshot(self):
4001
4002 api_response = netapp_api.NaElement(
4003 fake.VOLUME_GET_ITER_CLONE_CHILDREN_RESPONSE)
4004 self.mock_object(self.client,
4005 'send_iter_request',
4006 mock.Mock(return_value=api_response))
4007
4008 result = self.client.get_clone_children_for_snapshot(
4009 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4010
4011 volume_get_iter_args = {
4012 'query': {
4013 'volume-attributes': {
4014 'volume-clone-attributes': {
4015 'volume-clone-parent-attributes': {
4016 'name': fake.SHARE_NAME,
4017 'snapshot-name': fake.SNAPSHOT_NAME,
4018 },
4019 },
4020 },
4021 },
4022 'desired-attributes': {
4023 'volume-attributes': {
4024 'volume-id-attributes': {
4025 'name': None,
4026 },
4027 },
4028 },
4029 }
4030 self.client.send_iter_request.assert_has_calls([
4031 mock.call('volume-get-iter', volume_get_iter_args)])
4032
4033 expected = [
4034 {'name': fake.CLONE_CHILD_1},
4035 {'name': fake.CLONE_CHILD_2},
4036 ]
4037 self.assertEqual(expected, result)
4038
4039 def test_get_clone_children_for_snapshot_not_found(self):
4040
4041 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
4042 self.mock_object(self.client,
4043 'send_iter_request',
4044 mock.Mock(return_value=api_response))
4045
4046 result = self.client.get_clone_children_for_snapshot(
4047 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4048
4049 self.assertEqual([], result)
4050
4051 def test_get_volume_junction_path(self):
4052
4053 api_response = netapp_api.NaElement(
4054 fake.VOLUME_GET_VOLUME_PATH_RESPONSE)
4055 self.mock_object(self.client,
4056 'send_request',
4057 mock.Mock(return_value=api_response))
4058
4059 result = self.client.get_volume_junction_path(fake.SHARE_NAME)
4060
4061 volume_get_volume_path_args = {
4062 'volume': fake.SHARE_NAME,
4063 'is-style-cifs': 'false'
4064 }
4065
4066 self.client.send_request.assert_has_calls([
4067 mock.call('volume-get-volume-path', volume_get_volume_path_args)])
4068 self.assertEqual(fake.VOLUME_JUNCTION_PATH, result)
4069
4070 def test_get_volume_junction_path_cifs(self):
4071
4072 api_response = netapp_api.NaElement(
4073 fake.VOLUME_GET_VOLUME_PATH_CIFS_RESPONSE)
4074 self.mock_object(self.client,
4075 'send_request',
4076 mock.Mock(return_value=api_response))
4077
4078 result = self.client.get_volume_junction_path(fake.SHARE_NAME,
4079 is_style_cifs=True)
4080
4081 volume_get_volume_path_args = {
4082 'volume': fake.SHARE_NAME,
4083 'is-style-cifs': 'true'
4084 }
4085
4086 self.client.send_request.assert_has_calls([
4087 mock.call('volume-get-volume-path', volume_get_volume_path_args)])
4088 self.assertEqual(fake.VOLUME_JUNCTION_PATH_CIFS, result)
4089
4090 def test_mount_volume_default_junction_path(self):
4091
4092 self.mock_object(self.client, 'send_request')
4093
4094 self.client.mount_volume(fake.SHARE_NAME)
4095
4096 volume_mount_args = {
4097 'volume-name': fake.SHARE_NAME,
4098 'junction-path': '/%s' % fake.SHARE_NAME,
4099 }
4100
4101 self.client.send_request.assert_has_calls([
4102 mock.call('volume-mount', volume_mount_args)])
4103
4104 def test_mount_volume(self):
4105
4106 self.mock_object(self.client, 'send_request')
4107 fake_path = '/fake_path'
4108
4109 self.client.mount_volume(fake.SHARE_NAME, junction_path=fake_path)
4110
4111 volume_mount_args = {
4112 'volume-name': fake.SHARE_NAME,
4113 'junction-path': fake_path,
4114 }
4115
4116 self.client.send_request.assert_has_calls([
4117 mock.call('volume-mount', volume_mount_args)])
4118
4119 def test_offline_volume(self):
4120
4121 self.mock_object(self.client, 'send_request')
4122
4123 self.client.offline_volume(fake.SHARE_NAME)
4124
4125 volume_offline_args = {'name': fake.SHARE_NAME}
4126
4127 self.client.send_request.assert_has_calls([
4128 mock.call('volume-offline', volume_offline_args)])
4129
4130 def test_offline_volume_already_offline(self):
4131
4132 self.mock_object(self.client,
4133 'send_request',
4134 mock.Mock(side_effect=self._mock_api_error(
4135 netapp_api.EVOLUMEOFFLINE)))
4136
4137 self.client.offline_volume(fake.SHARE_NAME)
4138
4139 volume_offline_args = {'name': fake.SHARE_NAME}
4140
4141 self.client.send_request.assert_has_calls([
4142 mock.call('volume-offline', volume_offline_args)])
4143
4144 def test_offline_volume_api_error(self):
4145
4146 self.mock_object(self.client,
4147 'send_request',
4148 mock.Mock(side_effect=self._mock_api_error()))
4149
4150 self.assertRaises(netapp_api.NaApiError,
4151 self.client.offline_volume,
4152 fake.SHARE_NAME)
4153
4154 def test__unmount_volume(self):
4155
4156 self.mock_object(self.client, 'send_request')
4157
4158 self.client._unmount_volume(fake.SHARE_NAME)
4159
4160 volume_unmount_args = {
4161 'volume-name': fake.SHARE_NAME,
4162 'force': 'false'
4163 }
4164
4165 self.client.send_request.assert_has_calls([
4166 mock.call('volume-unmount', volume_unmount_args)])
4167
4168 def test__unmount_volume_force(self):
4169
4170 self.mock_object(self.client, 'send_request')
4171
4172 self.client._unmount_volume(fake.SHARE_NAME, force=True)
4173
4174 volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'}
4175
4176 self.client.send_request.assert_has_calls([
4177 mock.call('volume-unmount', volume_unmount_args)])
4178
4179 def test__unmount_volume_already_unmounted(self):
4180
4181 self.mock_object(self.client,
4182 'send_request',
4183 mock.Mock(side_effect=self._mock_api_error(
4184 netapp_api.EVOL_NOT_MOUNTED)))
4185
4186 self.client._unmount_volume(fake.SHARE_NAME, force=True)
4187
4188 volume_unmount_args = {'volume-name': fake.SHARE_NAME, 'force': 'true'}
4189
4190 self.client.send_request.assert_has_calls([
4191 mock.call('volume-unmount', volume_unmount_args)])
4192
4193 def test__unmount_volume_api_error(self):
4194
4195 self.mock_object(self.client,
4196 'send_request',
4197 mock.Mock(side_effect=self._mock_api_error()))
4198
4199 self.assertRaises(netapp_api.NaApiError,
4200 self.client._unmount_volume,
4201 fake.SHARE_NAME,
4202 force=True)
4203
4204 def test_unmount_volume(self):
4205
4206 self.mock_object(self.client, '_unmount_volume')
4207
4208 self.client.unmount_volume(fake.SHARE_NAME)
4209
4210 self.client._unmount_volume.assert_called_once_with(fake.SHARE_NAME,
4211 force=False)
4212 self.assertEqual(1, client_cmode.LOG.debug.call_count)
4213 self.assertEqual(0, client_cmode.LOG.warning.call_count)
4214
4215 def test_unmount_volume_api_error(self):
4216
4217 self.mock_object(self.client,
4218 '_unmount_volume',
4219 self._mock_api_error())
4220
4221 self.assertRaises(netapp_api.NaApiError,
4222 self.client.unmount_volume,
4223 fake.SHARE_NAME)
4224
4225 self.assertEqual(1, self.client._unmount_volume.call_count)
4226 self.assertEqual(0, client_cmode.LOG.debug.call_count)
4227 self.assertEqual(0, client_cmode.LOG.warning.call_count)
4228
4229 def test_unmount_volume_with_retries(self):
4230
4231 side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR,
4232 message='...job ID...')] * 5
4233 side_effect.append(None)
4234 self.mock_object(self.client,
4235 '_unmount_volume',
4236 mock.Mock(side_effect=side_effect))
4237 self.mock_object(time, 'sleep')
4238
4239 self.client.unmount_volume(fake.SHARE_NAME)
4240
4241 self.assertEqual(6, self.client._unmount_volume.call_count)
4242 self.assertEqual(1, client_cmode.LOG.debug.call_count)
4243 self.assertEqual(5, client_cmode.LOG.warning.call_count)
4244
4245 def test_unmount_volume_with_max_retries(self):
4246
4247 side_effect = [netapp_api.NaApiError(code=netapp_api.EAPIERROR,
4248 message='...job ID...')] * 30
4249 self.mock_object(self.client,
4250 '_unmount_volume',
4251 mock.Mock(side_effect=side_effect))
4252 self.mock_object(time, 'sleep')
4253
4254 self.assertRaises(exception.NetAppException,
4255 self.client.unmount_volume,
4256 fake.SHARE_NAME)
4257
4258 self.assertEqual(10, self.client._unmount_volume.call_count)
4259 self.assertEqual(0, client_cmode.LOG.debug.call_count)
4260 self.assertEqual(10, client_cmode.LOG.warning.call_count)
4261
4262 def test_delete_volume(self):
4263
4264 self.mock_object(self.client, 'send_request')
4265
4266 self.client.delete_volume(fake.SHARE_NAME)
4267
4268 volume_destroy_args = {'name': fake.SHARE_NAME}
4269
4270 self.client.send_request.assert_has_calls([
4271 mock.call('volume-destroy', volume_destroy_args)])
4272
4273 def test_create_snapshot(self):
4274
4275 self.mock_object(self.client, 'send_request')
4276
4277 self.client.create_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4278
4279 snapshot_create_args = {
4280 'volume': fake.SHARE_NAME,
4281 'snapshot': fake.SNAPSHOT_NAME
4282 }
4283
4284 self.client.send_request.assert_has_calls([
4285 mock.call('snapshot-create', snapshot_create_args)])
4286
4287 @ddt.data({
4288 'mock_return': fake.SNAPSHOT_GET_ITER_NOT_BUSY_RESPONSE,
4289 'expected': {
4290 'access-time': fake.SNAPSHOT_ACCESS_TIME,
4291 'name': fake.SNAPSHOT_NAME,
4292 'volume': fake.SHARE_NAME,
4293 'busy': False,
4294 'owners': set(),
4295 }
4296 }, {
4297 'mock_return': fake.SNAPSHOT_GET_ITER_BUSY_RESPONSE,
4298 'expected': {
4299 'access-time': fake.SNAPSHOT_ACCESS_TIME,
4300 'name': fake.SNAPSHOT_NAME,
4301 'volume': fake.SHARE_NAME,
4302 'busy': True,
4303 'owners': {'volume clone'},
4304 }
4305 })
4306 @ddt.unpack
4307 def test_get_snapshot(self, mock_return, expected):
4308
4309 api_response = netapp_api.NaElement(mock_return)
4310 self.mock_object(self.client,
4311 'send_request',
4312 mock.Mock(return_value=api_response))
4313
4314 result = self.client.get_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4315
4316 snapshot_get_iter_args = {
4317 'query': {
4318 'snapshot-info': {
4319 'name': fake.SNAPSHOT_NAME,
4320 'volume': fake.SHARE_NAME,
4321 },
4322 },
4323 'desired-attributes': {
4324 'snapshot-info': {
4325 'access-time': None,
4326 'name': None,
4327 'volume': None,
4328 'busy': None,
4329 'snapshot-owners-list': {
4330 'snapshot-owner': None,
4331 }
4332 },
4333 },
4334 }
4335 self.client.send_request.assert_has_calls([
4336 mock.call('snapshot-get-iter', snapshot_get_iter_args)])
4337 self.assertDictEqual(expected, result)
4338
4339 @ddt.data({
4340 'api_response_xml': fake.NO_RECORDS_RESPONSE,
4341 'raised_exception': exception.SnapshotResourceNotFound,
4342 }, {
4343 'api_response_xml': fake.SNAPSHOT_GET_ITER_NOT_UNIQUE_RESPONSE,
4344 'raised_exception': exception.NetAppException,
4345 }, {
4346 'api_response_xml': fake.SNAPSHOT_GET_ITER_UNAVAILABLE_RESPONSE,
4347 'raised_exception': exception.SnapshotUnavailable,
4348 }, {
4349 'api_response_xml': fake.SNAPSHOT_GET_ITER_OTHER_ERROR_RESPONSE,
4350 'raised_exception': exception.NetAppException,
4351 })
4352 @ddt.unpack
4353 def test_get_snapshot_error(self, api_response_xml, raised_exception):
4354
4355 api_response = netapp_api.NaElement(api_response_xml)
4356 self.mock_object(self.client,
4357 'send_request',
4358 mock.Mock(return_value=api_response))
4359
4360 self.assertRaises(raised_exception,
4361 self.client.get_snapshot,
4362 fake.SHARE_NAME,
4363 fake.SNAPSHOT_NAME)
4364
4365 def test_rename_snapshot(self):
4366
4367 self.mock_object(self.client, 'send_request')
4368
4369 self.client.rename_snapshot(fake.SHARE_NAME,
4370 fake.SNAPSHOT_NAME,
4371 'new_snapshot_name')
4372
4373 snapshot_rename_args = {
4374 'volume': fake.SHARE_NAME,
4375 'current-name': fake.SNAPSHOT_NAME,
4376 'new-name': 'new_snapshot_name'
4377 }
4378 self.client.send_request.assert_has_calls([
4379 mock.call('snapshot-rename', snapshot_rename_args)])
4380
4381 def test_restore_snapshot(self):
4382
4383 self.mock_object(self.client, 'send_request')
4384
4385 self.client.restore_snapshot(fake.SHARE_NAME,
4386 fake.SNAPSHOT_NAME)
4387
4388 snapshot_restore_args = {
4389 'volume': fake.SHARE_NAME,
4390 'snapshot': fake.SNAPSHOT_NAME,
4391 }
4392 self.client.send_request.assert_has_calls([
4393 mock.call('snapshot-restore-volume', snapshot_restore_args)])
4394
4395 @ddt.data(True, False)
4396 def test_delete_snapshot(self, ignore_owners):
4397
4398 self.mock_object(self.client, 'send_request')
4399
4400 self.client.delete_snapshot(
4401 fake.SHARE_NAME, fake.SNAPSHOT_NAME, ignore_owners=ignore_owners)
4402
4403 snapshot_delete_args = {
4404 'volume': fake.SHARE_NAME,
4405 'snapshot': fake.SNAPSHOT_NAME,
4406 'ignore-owners': 'true' if ignore_owners else 'false',
4407 }
4408
4409 self.client.send_request.assert_has_calls([
4410 mock.call('snapshot-delete', snapshot_delete_args)])
4411
4412 def test_soft_delete_snapshot(self):
4413
4414 mock_delete_snapshot = self.mock_object(self.client, 'delete_snapshot')
4415 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
4416
4417 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4418
4419 mock_delete_snapshot.assert_called_once_with(
4420 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4421 self.assertFalse(mock_rename_snapshot.called)
4422
4423 def test_soft_delete_snapshot_api_error(self):
4424
4425 mock_delete_snapshot = self.mock_object(
4426 self.client, 'delete_snapshot', self._mock_api_error())
4427 mock_rename_snapshot = self.mock_object(self.client, 'rename_snapshot')
4428
4429 self.client.soft_delete_snapshot(fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4430
4431 mock_delete_snapshot.assert_called_once_with(
4432 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
4433 mock_rename_snapshot.assert_called_once_with(
4434 fake.SHARE_NAME, fake.SNAPSHOT_NAME,
4435 'deleted_manila_' + fake.SNAPSHOT_NAME)
4436
4437 def test_prune_deleted_snapshots(self):
4438
4439 deleted_snapshots_map = {
4440 'vserver1': [{
4441 'name': 'deleted_snap_1',
4442 'volume': 'fake_volume_1',
4443 'vserver': 'vserver1',
4444 }],
4445 'vserver2': [{
4446 'name': 'deleted_snap_2',
4447 'volume': 'fake_volume_2',
4448 'vserver': 'vserver2',
4449 }],
4450 }
4451 mock_get_deleted_snapshots = self.mock_object(
4452 self.client, '_get_deleted_snapshots',
4453 mock.Mock(return_value=deleted_snapshots_map))
4454 mock_delete_snapshot = self.mock_object(
4455 self.client, 'delete_snapshot',
4456 mock.Mock(side_effect=[None, netapp_api.NaApiError]))
4457 self.mock_object(
4458 copy, 'deepcopy', mock.Mock(return_value=self.client))
4459
4460 self.client.prune_deleted_snapshots()
4461
4462 mock_get_deleted_snapshots.assert_called_once_with()
4463 mock_delete_snapshot.assert_has_calls([
4464 mock.call('fake_volume_1', 'deleted_snap_1'),
4465 mock.call('fake_volume_2', 'deleted_snap_2'),
4466 ], any_order=True)
4467
4468 def test_get_deleted_snapshots(self):
4469
4470 api_response = netapp_api.NaElement(
4471 fake.SNAPSHOT_GET_ITER_DELETED_RESPONSE)
4472 self.mock_object(self.client,
4473 'send_iter_request',
4474 mock.Mock(return_value=api_response))
4475
4476 result = self.client._get_deleted_snapshots()
4477
4478 snapshot_get_iter_args = {
4479 'query': {
4480 'snapshot-info': {
4481 'name': 'deleted_manila_*',
4482 'busy': 'false',
4483 },
4484 },
4485 'desired-attributes': {
4486 'snapshot-info': {
4487 'name': None,
4488 'vserver': None,
4489 'volume': None,
4490 },
4491 },
4492 }
4493 self.client.send_iter_request.assert_has_calls([
4494 mock.call('snapshot-get-iter', snapshot_get_iter_args)])
4495
4496 expected = {
4497 fake.VSERVER_NAME: [{
4498 'name': 'deleted_manila_' + fake.SNAPSHOT_NAME,
4499 'volume': fake.SHARE_NAME,
4500 'vserver': fake.VSERVER_NAME,
4501 }],
4502 }
4503 self.assertDictEqual(expected, result)
4504
4505 def test_create_cg_snapshot(self):
4506
4507 mock_start_cg_snapshot = self.mock_object(
4508 self.client, '_start_cg_snapshot',
4509 mock.Mock(return_value=fake.CG_SNAPSHOT_ID))
4510 mock_commit_cg_snapshot = self.mock_object(
4511 self.client, '_commit_cg_snapshot')
4512
4513 self.client.create_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2],
4514 fake.SNAPSHOT_NAME)
4515
4516 mock_start_cg_snapshot.assert_called_once_with(
4517 [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME)
4518 mock_commit_cg_snapshot.assert_called_once_with(fake.CG_SNAPSHOT_ID)
4519
4520 def test_create_cg_snapshot_no_id(self):
4521
4522 mock_start_cg_snapshot = self.mock_object(
4523 self.client, '_start_cg_snapshot', mock.Mock(return_value=None))
4524 mock_commit_cg_snapshot = self.mock_object(
4525 self.client, '_commit_cg_snapshot')
4526
4527 self.assertRaises(exception.NetAppException,
4528 self.client.create_cg_snapshot,
4529 [fake.SHARE_NAME, fake.SHARE_NAME_2],
4530 fake.SNAPSHOT_NAME)
4531
4532 mock_start_cg_snapshot.assert_called_once_with(
4533 [fake.SHARE_NAME, fake.SHARE_NAME_2], fake.SNAPSHOT_NAME)
4534 self.assertFalse(mock_commit_cg_snapshot.called)
4535
4536 def test_start_cg_snapshot(self):
4537
4538 self.mock_object(self.client, 'send_request')
4539
4540 self.client._start_cg_snapshot([fake.SHARE_NAME, fake.SHARE_NAME_2],
4541 fake.SNAPSHOT_NAME)
4542
4543 cg_start_args = {
4544 'snapshot': fake.SNAPSHOT_NAME,
4545 'timeout': 'relaxed',
4546 'volumes': [
4547 {'volume-name': fake.SHARE_NAME},
4548 {'volume-name': fake.SHARE_NAME_2},
4549 ],
4550 }
4551
4552 self.client.send_request.assert_has_calls([
4553 mock.call('cg-start', cg_start_args)])
4554
4555 def test_commit_cg_snapshot(self):
4556
4557 self.mock_object(self.client, 'send_request')
4558
4559 self.client._commit_cg_snapshot(fake.CG_SNAPSHOT_ID)
4560
4561 cg_commit_args = {'cg-id': fake.CG_SNAPSHOT_ID}
4562
4563 self.client.send_request.assert_has_calls([
4564 mock.call('cg-commit', cg_commit_args)])
4565
4566 def test_create_cifs_share(self):
4567
4568 self.mock_object(self.client, 'send_request')
4569
4570 self.client.create_cifs_share(fake.SHARE_NAME)
4571
4572 cifs_share_create_args = {
4573 'path': '/%s' % fake.SHARE_NAME,
4574 'share-name': fake.SHARE_NAME
4575 }
4576
4577 self.client.send_request.assert_has_calls([
4578 mock.call('cifs-share-create', cifs_share_create_args)])
4579
4580 def test_get_cifs_share_access(self):
4581
4582 api_response = netapp_api.NaElement(
4583 fake.CIFS_SHARE_ACCESS_CONTROL_GET_ITER)
4584 self.mock_object(self.client,
4585 'send_iter_request',
4586 mock.Mock(return_value=api_response))
4587
4588 result = self.client.get_cifs_share_access(fake.SHARE_NAME)
4589
4590 cifs_share_access_control_get_iter_args = {
4591 'query': {
4592 'cifs-share-access-control': {
4593 'share': fake.SHARE_NAME,
4594 },
4595 },
4596 'desired-attributes': {
4597 'cifs-share-access-control': {
4598 'user-or-group': None,
4599 'permission': None,
4600 },
4601 },
4602 }
4603 self.client.send_iter_request.assert_has_calls([
4604 mock.call('cifs-share-access-control-get-iter',
4605 cifs_share_access_control_get_iter_args)])
4606
4607 expected = {
4608 'Administrator': 'full_control',
4609 'Administrators': 'change',
4610 'Power Users': 'read',
4611 'Users': 'no_access',
4612 }
4613 self.assertDictEqual(expected, result)
4614
4615 def test_get_cifs_share_access_not_found(self):
4616
4617 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
4618 self.mock_object(self.client,
4619 'send_iter_request',
4620 mock.Mock(return_value=api_response))
4621
4622 result = self.client.get_cifs_share_access(fake.SHARE_NAME)
4623
4624 self.assertEqual({}, result)
4625
4626 @ddt.data(True, False)
4627 def test_add_cifs_share_access(self, readonly):
4628
4629 self.mock_object(self.client, 'send_request')
4630
4631 self.client.add_cifs_share_access(fake.SHARE_NAME,
4632 fake.USER_NAME,
4633 readonly)
4634
4635 cifs_share_access_control_create_args = {
4636 'permission': 'read' if readonly else 'full_control',
4637 'share': fake.SHARE_NAME,
4638 'user-or-group': fake.USER_NAME
4639 }
4640
4641 self.client.send_request.assert_has_calls([
4642 mock.call(
4643 'cifs-share-access-control-create',
4644 cifs_share_access_control_create_args)])
4645
4646 @ddt.data(True, False)
4647 def test_modify_cifs_share_access(self, readonly):
4648
4649 self.mock_object(self.client, 'send_request')
4650
4651 self.client.modify_cifs_share_access(fake.SHARE_NAME,
4652 fake.USER_NAME,
4653 readonly)
4654
4655 cifs_share_access_control_modify_args = {
4656 'permission': 'read' if readonly else 'full_control',
4657 'share': fake.SHARE_NAME,
4658 'user-or-group': fake.USER_NAME
4659 }
4660
4661 self.client.send_request.assert_has_calls([
4662 mock.call(
4663 'cifs-share-access-control-modify',
4664 cifs_share_access_control_modify_args)])
4665
4666 def test_remove_cifs_share_access(self):
4667
4668 self.mock_object(self.client, 'send_request')
4669
4670 self.client.remove_cifs_share_access(fake.SHARE_NAME, fake.USER_NAME)
4671
4672 cifs_share_access_control_delete_args = {
4673 'user-or-group': fake.USER_NAME,
4674 'share': fake.SHARE_NAME
4675 }
4676
4677 self.client.send_request.assert_has_calls([
4678 mock.call(
4679 'cifs-share-access-control-delete',
4680 cifs_share_access_control_delete_args)])
4681
4682 def test_remove_cifs_share(self):
4683
4684 self.mock_object(self.client, 'send_request')
4685
4686 self.client.remove_cifs_share(fake.SHARE_NAME)
4687
4688 cifs_share_delete_args = {'share-name': fake.SHARE_NAME}
4689
4690 self.client.send_request.assert_has_calls([
4691 mock.call('cifs-share-delete', cifs_share_delete_args)])
4692
4693 def test_add_nfs_export_rule(self):
4694
4695 mock_get_nfs_export_rule_indices = self.mock_object(
4696 self.client, '_get_nfs_export_rule_indices',
4697 mock.Mock(return_value=[]))
4698 mock_add_nfs_export_rule = self.mock_object(
4699 self.client, '_add_nfs_export_rule')
4700 mock_update_nfs_export_rule = self.mock_object(
4701 self.client, '_update_nfs_export_rule')
4702
4703 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4704 fake.IP_ADDRESS,
4705 False)
4706
4707 mock_get_nfs_export_rule_indices.assert_called_once_with(
4708 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
4709 mock_add_nfs_export_rule.assert_called_once_with(
4710 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False)
4711 self.assertFalse(mock_update_nfs_export_rule.called)
4712
4713 def test_add_nfs_export_rule_single_existing(self):
4714
4715 mock_get_nfs_export_rule_indices = self.mock_object(
4716 self.client, '_get_nfs_export_rule_indices',
4717 mock.Mock(return_value=['1']))
4718 mock_add_nfs_export_rule = self.mock_object(
4719 self.client, '_add_nfs_export_rule')
4720 mock_update_nfs_export_rule = self.mock_object(
4721 self.client, '_update_nfs_export_rule')
4722 mock_remove_nfs_export_rules = self.mock_object(
4723 self.client, '_remove_nfs_export_rules')
4724
4725 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4726 fake.IP_ADDRESS,
4727 False)
4728
4729 mock_get_nfs_export_rule_indices.assert_called_once_with(
4730 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
4731 self.assertFalse(mock_add_nfs_export_rule.called)
4732 mock_update_nfs_export_rule.assert_called_once_with(
4733 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '1')
4734 mock_remove_nfs_export_rules.assert_called_once_with(
4735 fake.EXPORT_POLICY_NAME, [])
4736
4737 def test_add_nfs_export_rule_multiple_existing(self):
4738
4739 mock_get_nfs_export_rule_indices = self.mock_object(
4740 self.client, '_get_nfs_export_rule_indices',
4741 mock.Mock(return_value=['2', '4', '6']))
4742 mock_add_nfs_export_rule = self.mock_object(
4743 self.client, '_add_nfs_export_rule')
4744 mock_update_nfs_export_rule = self.mock_object(
4745 self.client, '_update_nfs_export_rule')
4746 mock_remove_nfs_export_rules = self.mock_object(
4747 self.client, '_remove_nfs_export_rules')
4748
4749 self.client.add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4750 fake.IP_ADDRESS,
4751 False)
4752
4753 mock_get_nfs_export_rule_indices.assert_called_once_with(
4754 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
4755 self.assertFalse(mock_add_nfs_export_rule.called)
4756 mock_update_nfs_export_rule.assert_called_once_with(
4757 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS, False, '2')
4758 mock_remove_nfs_export_rules.assert_called_once_with(
4759 fake.EXPORT_POLICY_NAME, ['4', '6'])
4760
4761 @ddt.data({'readonly': False, 'rw_security_flavor': 'sys'},
4762 {'readonly': True, 'rw_security_flavor': 'never'})
4763 @ddt.unpack
4764 def test__add_nfs_export_rule(self, readonly, rw_security_flavor):
4765
4766 self.mock_object(self.client, 'send_request')
4767
4768 self.client._add_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4769 fake.IP_ADDRESS,
4770 readonly)
4771
4772 export_rule_create_args = {
4773 'policy-name': fake.EXPORT_POLICY_NAME,
4774 'client-match': fake.IP_ADDRESS,
4775 'ro-rule': {
4776 'security-flavor': 'sys',
4777 },
4778 'rw-rule': {
4779 'security-flavor': rw_security_flavor,
4780 },
4781 'super-user-security': {
4782 'security-flavor': 'sys',
4783 },
4784 }
4785 self.client.send_request.assert_has_calls(
4786 [mock.call('export-rule-create', export_rule_create_args)])
4787
4788 @ddt.data({'readonly': False, 'rw_security_flavor': 'sys', 'index': '2'},
4789 {'readonly': True, 'rw_security_flavor': 'never', 'index': '4'})
4790 @ddt.unpack
4791 def test_update_nfs_export_rule(self, readonly, rw_security_flavor, index):
4792
4793 self.mock_object(self.client, 'send_request')
4794 self.client._update_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4795 fake.IP_ADDRESS,
4796 readonly,
4797 index)
4798
4799 export_rule_modify_args = {
4800 'policy-name': fake.EXPORT_POLICY_NAME,
4801 'rule-index': index,
4802 'client-match': fake.IP_ADDRESS,
4803 'ro-rule': {
4804 'security-flavor': 'sys',
4805 },
4806 'rw-rule': {
4807 'security-flavor': rw_security_flavor,
4808 },
4809 'super-user-security': {
4810 'security-flavor': 'sys',
4811 },
4812 }
4813
4814 self.client.send_request.assert_has_calls(
4815 [mock.call('export-rule-modify', export_rule_modify_args)])
4816
4817 def test_get_nfs_export_rule_indices(self):
4818
4819 api_response = netapp_api.NaElement(fake.EXPORT_RULE_GET_ITER_RESPONSE)
4820 self.mock_object(self.client,
4821 'send_iter_request',
4822 mock.Mock(return_value=api_response))
4823
4824 result = self.client._get_nfs_export_rule_indices(
4825 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
4826
4827 export_rule_get_iter_args = {
4828 'query': {
4829 'export-rule-info': {
4830 'policy-name': fake.EXPORT_POLICY_NAME,
4831 'client-match': fake.IP_ADDRESS,
4832 },
4833 },
4834 'desired-attributes': {
4835 'export-rule-info': {
4836 'vserver-name': None,
4837 'policy-name': None,
4838 'client-match': None,
4839 'rule-index': None,
4840 },
4841 },
4842 }
4843 self.assertListEqual(['1', '3'], result)
4844 self.client.send_iter_request.assert_has_calls([
4845 mock.call('export-rule-get-iter', export_rule_get_iter_args)])
4846
4847 def test_remove_nfs_export_rule(self):
4848
4849 fake_indices = ['1', '3', '4']
4850 mock_get_nfs_export_rule_indices = self.mock_object(
4851 self.client, '_get_nfs_export_rule_indices',
4852 mock.Mock(return_value=fake_indices))
4853 mock_remove_nfs_export_rules = self.mock_object(
4854 self.client, '_remove_nfs_export_rules')
4855
4856 self.client.remove_nfs_export_rule(fake.EXPORT_POLICY_NAME,
4857 fake.IP_ADDRESS)
4858
4859 mock_get_nfs_export_rule_indices.assert_called_once_with(
4860 fake.EXPORT_POLICY_NAME, fake.IP_ADDRESS)
4861 mock_remove_nfs_export_rules.assert_called_once_with(
4862 fake.EXPORT_POLICY_NAME, fake_indices)
4863
4864 def test_remove_nfs_export_rules(self):
4865
4866 fake_indices = ['1', '3']
4867 self.mock_object(self.client, 'send_request')
4868
4869 self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME,
4870 fake_indices)
4871
4872 self.client.send_request.assert_has_calls([
4873 mock.call(
4874 'export-rule-destroy',
4875 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'}),
4876 mock.call(
4877 'export-rule-destroy',
4878 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '3'})])
4879
4880 def test_remove_nfs_export_rules_not_found(self):
4881
4882 self.mock_object(self.client,
4883 'send_request',
4884 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
4885
4886 self.client._remove_nfs_export_rules(fake.EXPORT_POLICY_NAME, ['1'])
4887
4888 self.client.send_request.assert_has_calls([
4889 mock.call(
4890 'export-rule-destroy',
4891 {'policy-name': fake.EXPORT_POLICY_NAME, 'rule-index': '1'})])
4892
4893 def test_remove_nfs_export_rules_api_error(self):
4894
4895 self.mock_object(self.client, 'send_request', self._mock_api_error())
4896
4897 self.assertRaises(netapp_api.NaApiError,
4898 self.client._remove_nfs_export_rules,
4899 fake.EXPORT_POLICY_NAME,
4900 ['1'])
4901
4902 def test_clear_nfs_export_policy_for_volume(self):
4903
4904 mock_set_nfs_export_policy_for_volume = self.mock_object(
4905 self.client, 'set_nfs_export_policy_for_volume')
4906
4907 self.client.clear_nfs_export_policy_for_volume(fake.SHARE_NAME)
4908
4909 mock_set_nfs_export_policy_for_volume.assert_called_once_with(
4910 fake.SHARE_NAME, 'default')
4911
4912 def test_set_nfs_export_policy_for_volume(self):
4913
4914 self.mock_object(self.client, 'send_request')
4915
4916 self.client.set_nfs_export_policy_for_volume(fake.SHARE_NAME,
4917 fake.EXPORT_POLICY_NAME)
4918
4919 volume_modify_iter_args = {
4920 'query': {
4921 'volume-attributes': {
4922 'volume-id-attributes': {
4923 'name': fake.SHARE_NAME,
4924 },
4925 },
4926 },
4927 'attributes': {
4928 'volume-attributes': {
4929 'volume-export-attributes': {
4930 'policy': fake.EXPORT_POLICY_NAME,
4931 },
4932 },
4933 },
4934 }
4935 self.client.send_request.assert_has_calls([
4936 mock.call('volume-modify-iter', volume_modify_iter_args)])
4937
4938 def test_set_qos_policy_group_for_volume(self):
4939
4940 self.mock_object(self.client, 'send_request')
4941
4942 self.client.set_qos_policy_group_for_volume(fake.SHARE_NAME,
4943 fake.QOS_POLICY_GROUP_NAME)
4944
4945 volume_modify_iter_args = {
4946 'query': {
4947 'volume-attributes': {
4948 'volume-id-attributes': {
4949 'name': fake.SHARE_NAME,
4950 },
4951 },
4952 },
4953 'attributes': {
4954 'volume-attributes': {
4955 'volume-qos-attributes': {
4956 'policy-group-name': fake.QOS_POLICY_GROUP_NAME,
4957 },
4958 },
4959 },
4960 }
4961 self.client.send_request.assert_called_once_with(
4962 'volume-modify-iter', volume_modify_iter_args)
4963
4964 def test_get_nfs_export_policy_for_volume(self):
4965
4966 api_response = netapp_api.NaElement(
4967 fake.VOLUME_GET_EXPORT_POLICY_RESPONSE)
4968 self.mock_object(self.client,
4969 'send_iter_request',
4970 mock.Mock(return_value=api_response))
4971
4972 result = self.client.get_nfs_export_policy_for_volume(fake.SHARE_NAME)
4973
4974 volume_get_iter_args = {
4975 'query': {
4976 'volume-attributes': {
4977 'volume-id-attributes': {
4978 'name': fake.SHARE_NAME,
4979 },
4980 },
4981 },
4982 'desired-attributes': {
4983 'volume-attributes': {
4984 'volume-export-attributes': {
4985 'policy': None,
4986 },
4987 },
4988 },
4989 }
4990 self.assertEqual(fake.EXPORT_POLICY_NAME, result)
4991 self.client.send_iter_request.assert_has_calls([
4992 mock.call('volume-get-iter', volume_get_iter_args)])
4993
4994 def test_get_nfs_export_policy_for_volume_not_found(self):
4995
4996 api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
4997 self.mock_object(self.client,
4998 'send_iter_request',
4999 mock.Mock(return_value=api_response))
5000
5001 self.assertRaises(exception.NetAppException,
5002 self.client.get_nfs_export_policy_for_volume,
5003 fake.SHARE_NAME)
5004
5005 def test_create_nfs_export_policy(self):
5006
5007 self.mock_object(self.client, 'send_request')
5008
5009 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5010
5011 export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME}
5012 self.client.send_request.assert_has_calls([
5013 mock.call('export-policy-create', export_policy_create_args)])
5014
5015 def test_create_nfs_export_policy_already_present(self):
5016
5017 self.mock_object(self.client,
5018 'send_request',
5019 self._mock_api_error(code=netapp_api.EDUPLICATEENTRY))
5020
5021 self.client.create_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5022
5023 export_policy_create_args = {'policy-name': fake.EXPORT_POLICY_NAME}
5024 self.client.send_request.assert_has_calls([
5025 mock.call('export-policy-create', export_policy_create_args)])
5026
5027 def test_create_nfs_export_policy_api_error(self):
5028
5029 self.mock_object(self.client, 'send_request', self._mock_api_error())
5030
5031 self.assertRaises(netapp_api.NaApiError,
5032 self.client.create_nfs_export_policy,
5033 fake.EXPORT_POLICY_NAME)
5034
5035 def test_soft_delete_nfs_export_policy(self):
5036
5037 self.mock_object(self.client, 'delete_nfs_export_policy')
5038 self.mock_object(self.client, 'rename_nfs_export_policy')
5039
5040 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5041
5042 self.client.delete_nfs_export_policy.assert_has_calls([
5043 mock.call(fake.EXPORT_POLICY_NAME)])
5044 self.assertFalse(self.client.rename_nfs_export_policy.called)
5045
5046 def test_soft_delete_nfs_export_policy_api_error(self):
5047
5048 self.mock_object(self.client,
5049 'delete_nfs_export_policy',
5050 self._mock_api_error())
5051 self.mock_object(self.client, 'rename_nfs_export_policy')
5052
5053 self.client.soft_delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5054
5055 self.client.delete_nfs_export_policy.assert_has_calls([
5056 mock.call(fake.EXPORT_POLICY_NAME)])
5057 self.assertTrue(self.client.rename_nfs_export_policy.called)
5058
5059 def test_delete_nfs_export_policy(self):
5060
5061 self.mock_object(self.client, 'send_request')
5062
5063 self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5064
5065 export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME}
5066 self.client.send_request.assert_has_calls([
5067 mock.call('export-policy-destroy', export_policy_destroy_args)])
5068
5069 def test_delete_nfs_export_policy_not_found(self):
5070
5071 self.mock_object(self.client,
5072 'send_request',
5073 self._mock_api_error(code=netapp_api.EOBJECTNOTFOUND))
5074
5075 self.client.delete_nfs_export_policy(fake.EXPORT_POLICY_NAME)
5076
5077 export_policy_destroy_args = {'policy-name': fake.EXPORT_POLICY_NAME}
5078 self.client.send_request.assert_has_calls([
5079 mock.call('export-policy-destroy', export_policy_destroy_args)])
5080
5081 def test_delete_nfs_export_policy_api_error(self):
5082
5083 self.mock_object(self.client, 'send_request', self._mock_api_error())
5084
5085 self.assertRaises(netapp_api.NaApiError,
5086 self.client.delete_nfs_export_policy,
5087 fake.EXPORT_POLICY_NAME)
5088
5089 def test_rename_nfs_export_policy(self):
5090
5091 self.mock_object(self.client, 'send_request')
5092
5093 self.client.rename_nfs_export_policy(fake.EXPORT_POLICY_NAME,
5094 'new_policy_name')
5095
5096 export_policy_rename_args = {
5097 'policy-name': fake.EXPORT_POLICY_NAME,
5098 'new-policy-name': 'new_policy_name'
5099 }
5100 self.client.send_request.assert_has_calls([
5101 mock.call('export-policy-rename', export_policy_rename_args)])
5102
5103 def test_prune_deleted_nfs_export_policies(self):
5104 # Mock client lest we not be able to see calls on its copy.
5105 self.mock_object(copy,
5106 'deepcopy',
5107 mock.Mock(return_value=self.client))
5108 self.mock_object(self.client,
5109 '_get_deleted_nfs_export_policies',
5110 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
5111 self.mock_object(self.client, 'delete_nfs_export_policy')
5112
5113 self.client.prune_deleted_nfs_export_policies()
5114
5115 self.assertTrue(self.client.delete_nfs_export_policy.called)
5116 self.client.delete_nfs_export_policy.assert_has_calls(
5117 [mock.call(policy) for policy in
5118 fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]])
5119
5120 def test_prune_deleted_nfs_export_policies_api_error(self):
5121 self.mock_object(copy,
5122 'deepcopy',
5123 mock.Mock(return_value=self.client))
5124 self.mock_object(self.client,
5125 '_get_deleted_nfs_export_policies',
5126 mock.Mock(return_value=fake.DELETED_EXPORT_POLICIES))
5127 self.mock_object(self.client,
5128 'delete_nfs_export_policy',
5129 self._mock_api_error())
5130
5131 self.client.prune_deleted_nfs_export_policies()
5132
5133 self.assertTrue(self.client.delete_nfs_export_policy.called)
5134 self.client.delete_nfs_export_policy.assert_has_calls(
5135 [mock.call(policy) for policy in
5136 fake.DELETED_EXPORT_POLICIES[fake.VSERVER_NAME]])
5137
5138 def test_get_deleted_nfs_export_policies(self):
5139
5140 api_response = netapp_api.NaElement(
5141 fake.DELETED_EXPORT_POLICY_GET_ITER_RESPONSE)
5142 self.mock_object(self.client,
5143 'send_iter_request',
5144 mock.Mock(return_value=api_response))
5145
5146 result = self.client._get_deleted_nfs_export_policies()
5147
5148 export_policy_get_iter_args = {
5149 'query': {
5150 'export-policy-info': {
5151 'policy-name': 'deleted_manila_*',
5152 },
5153 },
5154 'desired-attributes': {
5155 'export-policy-info': {
5156 'policy-name': None,
5157 'vserver': None,
5158 },
5159 },
5160 }
5161 self.assertSequenceEqual(fake.DELETED_EXPORT_POLICIES, result)
5162 self.client.send_iter_request.assert_has_calls([
5163 mock.call('export-policy-get-iter', export_policy_get_iter_args)])
5164
5165 def test_get_ems_log_destination_vserver(self):
5166
5167 self.mock_object(self.client,
5168 'get_ontapi_version',
5169 mock.Mock(return_value=(1, 21)))
5170 mock_list_vservers = self.mock_object(
5171 self.client,
5172 'list_vservers',
5173 mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME]))
5174
5175 result = self.client._get_ems_log_destination_vserver()
5176
5177 mock_list_vservers.assert_called_once_with(vserver_type='admin')
5178 self.assertEqual(fake.ADMIN_VSERVER_NAME, result)
5179
5180 def test_get_ems_log_destination_vserver_future(self):
5181
5182 self.mock_object(self.client,
5183 'get_ontapi_version',
5184 mock.Mock(return_value=(2, 0)))
5185 mock_list_vservers = self.mock_object(
5186 self.client,
5187 'list_vservers',
5188 mock.Mock(return_value=[fake.ADMIN_VSERVER_NAME]))
5189
5190 result = self.client._get_ems_log_destination_vserver()
5191
5192 mock_list_vservers.assert_called_once_with(vserver_type='admin')
5193 self.assertEqual(fake.ADMIN_VSERVER_NAME, result)
5194
5195 def test_get_ems_log_destination_vserver_legacy(self):
5196
5197 self.mock_object(self.client,
5198 'get_ontapi_version',
5199 mock.Mock(return_value=(1,