Coverage for manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_multi_svm.py: 99%
1778 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
1# Copyright (c) 2015 Clinton Knight. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14"""
15Unit tests for the NetApp Data ONTAP cDOT multi-SVM storage driver library.
16"""
18import copy
19import time
20from unittest import mock
22import ddt
23from oslo_log import log
24from oslo_serialization import jsonutils
25from oslo_utils import units
27from manila.common import constants
28from manila import context
29from manila import exception
30from manila.share.drivers.netapp.dataontap.client import api as netapp_api
31from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion
32from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base
33from manila.share.drivers.netapp.dataontap.cluster_mode import lib_multi_svm
34from manila.share.drivers.netapp import utils as na_utils
35from manila.share import share_types
36from manila.share import utils as share_utils
37from manila import test
38from manila.tests.share.drivers.netapp.dataontap.client import fakes as c_fake
39from manila.tests.share.drivers.netapp.dataontap.cluster_mode.test_lib_base\
40 import _get_config
41from manila.tests.share.drivers.netapp.dataontap import fakes as fake
44@ddt.ddt
45class NetAppFileStorageLibraryTestCase(test.TestCase):
47 def setUp(self):
48 super(NetAppFileStorageLibraryTestCase, self).setUp()
50 self.mock_object(na_utils, 'validate_driver_instantiation')
52 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None)
53 self.sleep_patcher.start()
54 self.addCleanup(self.sleep_patcher.stop)
56 # Mock loggers as themselves to allow logger arg validation
57 mock_logger = log.getLogger('mock_logger')
58 self.mock_object(lib_multi_svm.LOG,
59 'warning',
60 mock.Mock(side_effect=mock_logger.warning))
61 self.mock_object(lib_multi_svm.LOG,
62 'error',
63 mock.Mock(side_effect=mock_logger.error))
65 kwargs = {
66 'configuration': fake.get_config_cmode(),
67 'private_storage': mock.Mock(),
68 'app_version': fake.APP_VERSION
69 }
71 self.library = lib_multi_svm.NetAppCmodeMultiSVMFileStorageLibrary(
72 fake.DRIVER_NAME, **kwargs)
73 self.library._client = mock.Mock()
74 self.library._client.get_ontapi_version.return_value = (1, 21)
75 self.client = self.library._client
76 self.fake_new_replica = copy.deepcopy(fake.SHARE)
77 self.fake_new_ss = copy.deepcopy(fake.SHARE_SERVER)
78 self.fake_new_vserver_name = 'fake_new_vserver'
79 self.fake_new_ss['backend_details']['vserver_name'] = (
80 self.fake_new_vserver_name
81 )
82 self.fake_new_replica['share_server'] = self.fake_new_ss
83 self.fake_new_replica_host = 'fake_new_host'
84 self.fake_replica = copy.deepcopy(fake.SHARE)
85 self.fake_replica['id'] = fake.SHARE_ID2
86 fake_ss = copy.deepcopy(fake.SHARE_SERVER)
87 self.fake_vserver = 'fake_vserver'
88 fake_ss['backend_details']['vserver_name'] = (
89 self.fake_vserver)
90 self.fake_replica['share_server'] = fake_ss
91 self.fake_replica_host = 'fake_host'
93 self.fake_new_client = mock.Mock()
94 self.fake_client = mock.Mock()
95 self.library._default_nfs_config = fake.NFS_CONFIG_DEFAULT
97 # Server migration
98 self.dm_session = data_motion.DataMotionSession()
99 self.fake_src_share = copy.deepcopy(fake.SHARE)
100 self.fake_src_share_server = copy.deepcopy(fake.SHARE_SERVER)
101 self.fake_src_vserver = 'source_vserver'
102 self.fake_src_backend_name = (
103 self.fake_src_share_server['host'].split('@')[1])
104 self.fake_src_share_server['backend_details']['vserver_name'] = (
105 self.fake_src_vserver
106 )
107 self.fake_src_share['share_server'] = self.fake_src_share_server
108 self.fake_src_share['id'] = 'fb9be037-8a75-4c2a-bb7d-f63dffe13015'
109 self.fake_src_vol_name = 'share_fb9be037_8a75_4c2a_bb7d_f63dffe13015'
110 self.fake_dest_share = copy.deepcopy(fake.SHARE)
111 self.fake_dest_share_server = copy.deepcopy(fake.SHARE_SERVER_2)
112 self.fake_dest_vserver = 'dest_vserver'
113 self.fake_dest_backend_name = (
114 self.fake_dest_share_server['host'].split('@')[1])
115 self.fake_dest_share_server['backend_details']['vserver_name'] = (
116 self.fake_dest_vserver
117 )
118 self.fake_dest_share['share_server'] = self.fake_dest_share_server
119 self.fake_dest_share['id'] = 'aa6a3941-f87f-4874-92ca-425d3df85457'
120 self.fake_dest_vol_name = 'share_aa6a3941_f87f_4874_92ca_425d3df85457'
122 self.mock_src_client = mock.Mock()
123 self.mock_dest_client = mock.Mock()
125 def test_check_for_setup_error_cluster_creds_no_vserver(self):
126 self.library._have_cluster_creds = True
127 mock_list_non_root_aggregates = self.mock_object(
128 self.client, 'list_non_root_aggregates',
129 mock.Mock(return_value=fake.AGGREGATES))
130 mock_init_flexgroup = self.mock_object(self.library,
131 '_initialize_flexgroup_pools')
132 self.mock_object(self.library,
133 'is_flexvol_pool_configured',
134 mock.Mock(return_value=True))
135 self.mock_object(self.library,
136 '_find_matching_aggregates',
137 mock.Mock(return_value=fake.AGGREGATES))
138 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
139 'check_for_setup_error')
141 self.library.check_for_setup_error()
143 mock_list_non_root_aggregates.assert_called_once_with()
144 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
145 self.assertTrue(self.library.is_flexvol_pool_configured.called)
146 self.assertTrue(self.library._find_matching_aggregates.called)
147 mock_super.assert_called_once_with()
149 def test_check_for_setup_error_cluster_creds_with_vserver(self):
150 self.library._have_cluster_creds = True
151 self.library.configuration.netapp_vserver = fake.VSERVER1
152 mock_list_non_root_aggregates = self.mock_object(
153 self.client, 'list_non_root_aggregates',
154 mock.Mock(return_value=fake.AGGREGATES))
155 mock_init_flexgroup = self.mock_object(self.library,
156 '_initialize_flexgroup_pools')
157 self.mock_object(self.library,
158 'is_flexvol_pool_configured',
159 mock.Mock(return_value=True))
160 self.mock_object(self.library,
161 '_find_matching_aggregates',
162 mock.Mock(return_value=fake.AGGREGATES))
163 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
164 'check_for_setup_error')
166 self.library.check_for_setup_error()
168 mock_super.assert_called_once_with()
169 mock_list_non_root_aggregates.assert_called_once_with()
170 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
171 self.assertTrue(self.library.is_flexvol_pool_configured.called)
172 self.assertTrue(self.library._find_matching_aggregates.called)
173 self.assertTrue(lib_multi_svm.LOG.warning.called)
175 def test_check_for_setup_error_no_aggregates_no_flexvol_pool(self):
176 self.library._have_cluster_creds = True
177 mock_list_non_root_aggregates = self.mock_object(
178 self.client, 'list_non_root_aggregates',
179 mock.Mock(return_value=fake.AGGREGATES))
180 mock_init_flexgroup = self.mock_object(self.library,
181 '_initialize_flexgroup_pools')
182 self.mock_object(self.library,
183 'is_flexvol_pool_configured',
184 mock.Mock(return_value=False))
185 self.mock_object(self.library,
186 '_find_matching_aggregates',
187 mock.Mock(return_value=[]))
189 self.library.check_for_setup_error()
191 mock_list_non_root_aggregates.assert_called_once_with()
192 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
193 self.assertTrue(self.library.is_flexvol_pool_configured.called)
194 self.assertTrue(self.library._find_matching_aggregates.called)
196 def test_check_for_setup_error_vserver_creds(self):
197 self.library._have_cluster_creds = False
199 self.assertRaises(exception.InvalidInput,
200 self.library.check_for_setup_error)
202 def test_check_for_setup_error_no_aggregates(self):
203 self.library._have_cluster_creds = True
204 mock_list_non_root_aggregates = self.mock_object(
205 self.client, 'list_non_root_aggregates',
206 mock.Mock(return_value=fake.AGGREGATES))
207 mock_init_flexgroup = self.mock_object(self.library,
208 '_initialize_flexgroup_pools')
209 self.mock_object(self.library,
210 'is_flexvol_pool_configured',
211 mock.Mock(return_value=True))
212 self.mock_object(self.library,
213 '_find_matching_aggregates',
214 mock.Mock(return_value=[]))
216 self.assertRaises(exception.NetAppException,
217 self.library.check_for_setup_error)
219 mock_list_non_root_aggregates.assert_called_once_with()
220 mock_init_flexgroup.assert_called_once_with(set(fake.AGGREGATES))
221 self.assertTrue(self.library.is_flexvol_pool_configured.called)
222 self.assertTrue(self.library._find_matching_aggregates.called)
224 def test_get_vserver_no_share_server(self):
226 self.assertRaises(exception.InvalidInput,
227 self.library._get_vserver)
229 def test_get_vserver_no_share_server_with_vserver_name(self):
230 fake_vserver_client = mock.Mock()
232 mock_vserver_exists = self.mock_object(
233 fake_vserver_client, 'vserver_exists',
234 mock.Mock(return_value=True))
235 self.mock_object(self.library,
236 '_get_api_client',
237 mock.Mock(return_value=fake_vserver_client))
239 result_vserver, result_vserver_client = self.library._get_vserver(
240 share_server=None, vserver_name=fake.VSERVER1)
242 mock_vserver_exists.assert_called_once_with(
243 fake.VSERVER1
244 )
245 self.assertEqual(fake.VSERVER1, result_vserver)
246 self.assertEqual(fake_vserver_client, result_vserver_client)
248 def test_get_vserver_no_backend_details(self):
250 fake_share_server = copy.deepcopy(fake.SHARE_SERVER)
251 fake_share_server.pop('backend_details')
252 kwargs = {'share_server': fake_share_server}
254 self.assertRaises(exception.VserverNotSpecified,
255 self.library._get_vserver,
256 **kwargs)
258 def test_get_vserver_none_backend_details(self):
260 fake_share_server = copy.deepcopy(fake.SHARE_SERVER)
261 fake_share_server['backend_details'] = None
262 kwargs = {'share_server': fake_share_server}
264 self.assertRaises(exception.VserverNotSpecified,
265 self.library._get_vserver,
266 **kwargs)
268 def test_get_vserver_no_vserver(self):
270 fake_share_server = copy.deepcopy(fake.SHARE_SERVER)
271 fake_share_server['backend_details'].pop('vserver_name')
272 kwargs = {'share_server': fake_share_server}
274 self.assertRaises(exception.VserverNotSpecified,
275 self.library._get_vserver,
276 **kwargs)
278 def test_get_vserver_none_vserver(self):
280 fake_share_server = copy.deepcopy(fake.SHARE_SERVER)
281 fake_share_server['backend_details']['vserver_name'] = None
282 kwargs = {'share_server': fake_share_server}
284 self.assertRaises(exception.VserverNotSpecified,
285 self.library._get_vserver,
286 **kwargs)
288 def test_get_vserver_not_found(self):
290 mock_client = mock.Mock()
291 mock_client.vserver_exists.return_value = False
292 self.mock_object(self.library,
293 '_get_api_client',
294 mock.Mock(return_value=mock_client))
295 kwargs = {'share_server': fake.SHARE_SERVER}
297 self.assertRaises(exception.VserverNotFound,
298 self.library._get_vserver,
299 **kwargs)
301 def test_get_vserver(self):
303 mock_client = mock.Mock()
304 mock_client.vserver_exists.return_value = True
305 self.mock_object(self.library,
306 '_get_api_client',
307 mock.Mock(return_value=mock_client))
309 result = self.library._get_vserver(share_server=fake.SHARE_SERVER)
311 self.assertTupleEqual((fake.VSERVER1, mock_client), result)
313 def test_get_ems_pool_info(self):
315 self.mock_object(self.library,
316 '_find_matching_aggregates',
317 mock.Mock(return_value=['aggr1', 'aggr2']))
318 self.library._flexgroup_pools = {'fg': ['aggr1', 'aggr2']}
320 result = self.library._get_ems_pool_info()
322 expected = {
323 'pools': {
324 'vserver': None,
325 'aggregates': ['aggr1', 'aggr2'],
326 'flexgroup_aggregates': {'fg': ['aggr1', 'aggr2']},
327 },
328 }
329 self.assertEqual(expected, result)
331 @ddt.data({'fake_vserver_name': fake, 'nfs_config_support': False},
332 {'fake_vserver_name': fake.IDENTIFIER,
333 'nfs_config_support': True})
334 @ddt.unpack
335 def test_manage_server(self, fake_vserver_name, nfs_config_support):
337 self.mock_object(context,
338 'get_admin_context',
339 mock.Mock(return_value='fake_admin_context'))
340 mock_get_vserver_name = self.mock_object(
341 self.library, '_get_vserver_name',
342 mock.Mock(return_value=fake_vserver_name))
343 self.library.is_nfs_config_supported = nfs_config_support
344 mock_get_nfs_config = self.mock_object(
345 self.library._client, 'get_nfs_config',
346 mock.Mock(return_value=fake.NFS_CONFIG_DEFAULT))
348 new_identifier, new_details = self.library.manage_server(
349 context, fake.SHARE_SERVER, fake.IDENTIFIER, {})
351 mock_get_vserver_name.assert_called_once_with(fake.SHARE_SERVER['id'])
352 self.assertEqual(fake_vserver_name, new_details['vserver_name'])
353 self.assertEqual(fake_vserver_name, new_identifier)
354 if nfs_config_support:
355 mock_get_nfs_config.assert_called_once_with(
356 list(self.library.NFS_CONFIG_EXTRA_SPECS_MAP.values()),
357 fake_vserver_name)
358 self.assertEqual(jsonutils.dumps(fake.NFS_CONFIG_DEFAULT),
359 new_details['nfs_config'])
360 else:
361 mock_get_nfs_config.assert_not_called()
363 def test_get_share_server_network_info(self):
365 fake_vserver_client = mock.Mock()
367 self.mock_object(context,
368 'get_admin_context',
369 mock.Mock(return_value='fake_admin_context'))
370 mock_get_vserver = self.mock_object(
371 self.library, '_get_vserver',
372 mock.Mock(return_value=['fake', fake_vserver_client]))
374 net_interfaces = copy.deepcopy(c_fake.NETWORK_INTERFACES_MULTIPLE)
376 self.mock_object(fake_vserver_client,
377 'get_network_interfaces',
378 mock.Mock(return_value=net_interfaces))
380 result = self.library.get_share_server_network_info(context,
381 fake.SHARE_SERVER,
382 fake.IDENTIFIER,
383 {})
384 mock_get_vserver.assert_called_once_with(
385 vserver_name=fake.IDENTIFIER
386 )
387 reference_allocations = []
388 for lif in net_interfaces:
389 reference_allocations.append(lif['address'])
391 self.assertEqual(reference_allocations, result)
393 @ddt.data((True, fake.IDENTIFIER),
394 (False, fake.IDENTIFIER))
395 @ddt.unpack
396 def test__verify_share_server_name(self, vserver_exists, identifier):
398 mock_exists = self.mock_object(self.client, 'vserver_exists',
399 mock.Mock(return_value=vserver_exists))
400 expected_result = identifier
401 if not vserver_exists:
402 expected_result = self.library._get_vserver_name(identifier)
404 result = self.library._get_correct_vserver_old_name(identifier)
406 self.assertEqual(result, expected_result)
407 mock_exists.assert_called_once_with(identifier)
409 def test_handle_housekeeping_tasks(self):
411 self.mock_object(self.client, 'prune_deleted_nfs_export_policies')
412 self.mock_object(self.client, 'prune_deleted_snapshots')
413 self.mock_object(self.client, 'prune_deleted_volumes')
414 mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
415 '_handle_housekeeping_tasks')
417 self.library._handle_housekeeping_tasks()
419 self.assertTrue(self.client.prune_deleted_nfs_export_policies.called)
420 self.assertTrue(self.client.prune_deleted_snapshots.called)
421 self.assertTrue(self.client.prune_deleted_volumes.called)
422 self.assertTrue(mock_super.called)
424 def test_find_matching_aggregates(self):
426 mock_is_flexvol_pool_configured = self.mock_object(
427 self.library, 'is_flexvol_pool_configured',
428 mock.Mock(return_value=True))
429 mock_list_non_root_aggregates = self.mock_object(
430 self.client, 'list_non_root_aggregates',
431 mock.Mock(return_value=fake.AGGREGATES))
432 self.library.configuration.netapp_aggregate_name_search_pattern = (
433 '.*_aggr_1')
435 result = self.library._find_matching_aggregates()
437 self.assertListEqual([fake.AGGREGATES[0]], result)
438 mock_is_flexvol_pool_configured.assert_called_once_with()
439 mock_list_non_root_aggregates.assert_called_once_with()
440 mock_list_non_root_aggregates.assert_called_once_with()
442 def test_find_matching_aggregates_no_flexvol_pool(self):
444 self.mock_object(self.library,
445 'is_flexvol_pool_configured',
446 mock.Mock(return_value=False))
448 result = self.library._find_matching_aggregates()
450 self.assertListEqual([], result)
452 def test__set_network_with_metadata(self):
453 net_info_1 = copy.deepcopy(fake.NETWORK_INFO)
454 net_info_2 = copy.deepcopy(fake.NETWORK_INFO)
455 net_info_2['subnet_metadata'] = {'fake_key': 'fake_value'}
456 net_info_3 = copy.deepcopy(fake.NETWORK_INFO)
457 metadata_vlan = 1
458 net_info_3['subnet_metadata'] = {
459 'set_vlan': metadata_vlan,
460 'set_mtu': '1'
461 }
462 net_info_4 = copy.deepcopy(fake.NETWORK_INFO)
463 metadata_vlan = 1
464 net_info_4['subnet_metadata'] = {
465 'set_vlan': metadata_vlan
466 }
468 net_list = [net_info_1, net_info_2, net_info_3, net_info_4]
469 self.library._set_network_with_metadata(net_list)
471 net_info = copy.deepcopy(fake.NETWORK_INFO)
472 self.assertEqual(net_info, net_list[0])
473 net_info['subnet_metadata'] = {'fake_key': 'fake_value'}
474 self.assertEqual(net_info, net_list[1])
475 self.assertEqual(metadata_vlan, net_list[2]['segmentation_id'])
476 for allocation in net_list[2]['network_allocations']:
477 self.assertEqual(metadata_vlan, allocation['segmentation_id'])
478 self.assertEqual(1, allocation['mtu'])
479 self.assertEqual(metadata_vlan, net_list[3]['segmentation_id'])
480 for allocation in net_list[3]['network_allocations']:
481 self.assertEqual(metadata_vlan, allocation['segmentation_id'])
482 self.assertEqual(fake.MTU, allocation['mtu'])
484 @ddt.data({'set_vlan': '0', 'set_mtu': '1500'},
485 {'set_vlan': '1000', 'set_mtu': '1bla'})
486 def test__set_network_with_metadata_exception(self, metadata):
487 net_info = copy.deepcopy(fake.NETWORK_INFO)
488 net_info['subnet_metadata'] = metadata
490 self.assertRaises(
491 exception.NetworkBadConfigurationException,
492 self.library._set_network_with_metadata,
493 [net_info])
495 @ddt.data({'nfs_config_support': False, 'with_encryption': True},
496 {'nfs_config_support': True,
497 'nfs_config': fake.NFS_CONFIG_UDP_MAX,
498 'with_encryption': False},
499 {'nfs_config_support': True,
500 'nfs_config': fake.NFS_CONFIG_DEFAULT, 'with_encryption': True})
501 @ddt.unpack
502 def test_setup_server(self, nfs_config_support, nfs_config=None,
503 with_encryption=False):
504 mock_get_vserver_name = self.mock_object(
505 self.library,
506 '_get_vserver_name',
507 mock.Mock(return_value=fake.VSERVER1))
509 mock_create_vserver = self.mock_object(self.library, '_create_vserver')
510 mock_validate_network_type = self.mock_object(
511 self.library,
512 '_validate_network_type')
513 mock_validate_share_network_subnets = self.mock_object(
514 self.library,
515 '_validate_share_network_subnets')
516 self.library.is_nfs_config_supported = nfs_config_support
517 mock_get_extra_spec = self.mock_object(
518 share_types, "get_share_type_extra_specs",
519 mock.Mock(return_value=fake.EXTRA_SPEC))
520 mock_check_extra_spec = self.mock_object(
521 self.library,
522 '_check_nfs_config_extra_specs_validity',
523 mock.Mock())
524 self.library.configuration.netapp_restrict_lif_creation_per_ha_pair = (
525 True
526 )
527 check_lif_limit = self.mock_object(
528 self.library,
529 '_check_data_lif_count_limit_reached_for_ha_pair',
530 )
531 mock_get_nfs_config = self.mock_object(
532 self.library,
533 "_get_nfs_config_provisioning_options",
534 mock.Mock(return_value=nfs_config))
535 mock_set_with_meta = self.mock_object(
536 self.library, '_set_network_with_metadata')
537 mock_barbican_kms_config = self.mock_object(
538 self.library, '_create_barbican_kms_config_for_specified_vserver')
540 fake_server_metadata = (
541 fake.SERVER_METADATA_WITH_ENCRYPTION
542 if with_encryption else fake.SERVER_METADATA)
543 result = self.library.setup_server(fake.NETWORK_INFO_LIST,
544 fake_server_metadata)
546 ports = {}
547 for network_allocation in fake.NETWORK_INFO['network_allocations']:
548 ports[network_allocation['id']] = network_allocation['ip_address']
550 mock_set_with_meta.assert_called_once_with(fake.NETWORK_INFO_LIST)
551 self.assertTrue(mock_validate_network_type.called)
552 self.assertTrue(mock_validate_share_network_subnets.called)
553 self.assertTrue(mock_get_vserver_name.called)
554 self.assertTrue(mock_create_vserver.called)
555 self.assertTrue(check_lif_limit.called)
556 if nfs_config_support:
557 mock_get_extra_spec.assert_called_once_with(
558 fake_server_metadata['share_type_id'])
559 mock_check_extra_spec.assert_called_once_with(
560 fake.EXTRA_SPEC)
561 mock_get_nfs_config.assert_called_once_with(
562 fake.EXTRA_SPEC)
563 else:
564 mock_get_extra_spec.assert_not_called()
565 mock_check_extra_spec.assert_not_called()
566 mock_get_nfs_config.assert_not_called()
568 expected = {
569 'vserver_name': fake.VSERVER1,
570 'ports': jsonutils.dumps(ports),
571 }
572 if nfs_config_support:
573 expected.update({'nfs_config': jsonutils.dumps(nfs_config)})
574 self.assertDictEqual(expected, result)
575 if with_encryption:
576 mock_barbican_kms_config.assert_called_once_with(
577 fake.VSERVER1, fake_server_metadata)
578 else:
579 mock_barbican_kms_config.assert_not_called()
581 def test_setup_server_with_error(self):
582 self.library.is_nfs_config_supported = False
583 mock_get_vserver_name = self.mock_object(
584 self.library,
585 '_get_vserver_name',
586 mock.Mock(return_value=fake.VSERVER1))
588 fake_exception = exception.ManilaException("fake")
589 mock_create_vserver = self.mock_object(
590 self.library,
591 '_create_vserver',
592 mock.Mock(side_effect=fake_exception))
594 mock_validate_network_type = self.mock_object(
595 self.library,
596 '_validate_network_type')
598 mock_validate_share_network_subnets = self.mock_object(
599 self.library,
600 '_validate_share_network_subnets')
601 self.mock_object(self.library, '_set_network_with_metadata')
603 self.assertRaises(
604 exception.ManilaException,
605 self.library.setup_server,
606 fake.NETWORK_INFO_LIST,
607 fake.SERVER_METADATA)
609 ports = {}
610 for network_allocation in fake.NETWORK_INFO['network_allocations']:
611 ports[network_allocation['id']] = network_allocation['ip_address']
613 self.assertTrue(mock_validate_network_type.called)
614 self.assertTrue(mock_validate_share_network_subnets.called)
615 self.assertTrue(mock_get_vserver_name.called)
616 self.assertTrue(mock_create_vserver.called)
618 self.assertDictEqual(
619 {'server_details': {
620 'vserver_name': fake.VSERVER1,
621 'ports': jsonutils.dumps(ports),
622 }},
623 fake_exception.detail_data)
625 def test_setup_server_invalid_subnet(self):
626 invalid_subnet_exception = exception.NetworkBadConfigurationException(
627 reason='This is a fake message')
628 self.mock_object(self.library, '_get_vserver_name',
629 mock.Mock(return_value=fake.VSERVER1))
630 self.mock_object(self.library, '_validate_network_type')
631 self.mock_object(self.library, '_validate_share_network_subnets',
632 mock.Mock(side_effect=invalid_subnet_exception))
633 self.mock_object(self.library, '_set_network_with_metadata')
635 self.assertRaises(
636 exception.NetworkBadConfigurationException,
637 self.library.setup_server,
638 fake.NETWORK_INFO_LIST)
640 self.library._validate_share_network_subnets.assert_called_once_with(
641 fake.NETWORK_INFO_LIST)
643 def test_validate_share_network_subnets(self):
644 fake_vlan = fake.NETWORK_INFO['segmentation_id']
645 network_info_different_seg_id = copy.deepcopy(fake.NETWORK_INFO)
646 network_info_different_seg_id['segmentation_id'] = fake_vlan
647 allocations = network_info_different_seg_id['network_allocations']
648 allocations[0]['segmentation_id'] = fake_vlan
649 fake.NETWORK_INFO_LIST.append(network_info_different_seg_id)
651 result = self.library._validate_share_network_subnets(
652 fake.NETWORK_INFO_LIST)
654 self.assertIsNone(result)
656 def test_validate_share_network_subnets_invalid_vlan_config(self):
657 network_info_different_seg_id = copy.deepcopy(fake.NETWORK_INFO)
658 network_info_different_seg_id['segmentation_id'] = 4004
659 allocations = network_info_different_seg_id['network_allocations']
660 allocations[0]['segmentation_id'] = 4004
661 fake.NETWORK_INFO_LIST.append(network_info_different_seg_id)
663 self.assertRaises(
664 exception.NetworkBadConfigurationException,
665 self.library._validate_share_network_subnets,
666 fake.NETWORK_INFO_LIST)
668 @ddt.data(
669 {'network_info': [{'network_type': 'vlan', 'segmentation_id': 1000}]},
670 {'network_info': [{'network_type': None, 'segmentation_id': None}]},
671 {'network_info': [{'network_type': 'flat', 'segmentation_id': None}]})
672 @ddt.unpack
673 def test_validate_network_type_with_valid_network_types(self,
674 network_info):
675 result = self.library._validate_network_type(network_info)
676 self.assertIsNone(result)
678 @ddt.data(
679 {'network_info': [{'network_type': 'vxlan', 'segmentation_id': 1000}]},
680 {'network_info': [{'network_type': 'gre', 'segmentation_id': 100}]})
681 @ddt.unpack
682 def test_validate_network_type_with_invalid_network_types(self,
683 network_info):
684 self.assertRaises(exception.NetworkBadConfigurationException,
685 self.library._validate_network_type,
686 network_info)
688 def test_get_vserver_name(self):
689 vserver_id = fake.NETWORK_INFO['server_id']
690 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
692 actual_result = self.library._get_vserver_name(vserver_id)
694 self.assertEqual(vserver_name, actual_result)
696 @ddt.data({'existing_ipspace': None,
697 'nfs_config': fake.NFS_CONFIG_TCP_UDP_MAX},
698 {'existing_ipspace': fake.IPSPACE, 'nfs_config': None})
699 @ddt.unpack
700 def test_create_vserver(self, existing_ipspace, nfs_config):
702 versions = ['fake_v1', 'fake_v2']
703 self.library.configuration.netapp_enabled_share_protocols = versions
704 self.library.configuration.netapp_cifs_aes_encryption = False
705 vserver_id = fake.NETWORK_INFO['server_id']
706 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
707 fake_lif_home_ports = {fake.CLUSTER_NODES[0]: 'fake_port',
708 fake.CLUSTER_NODES[1]: 'another_fake_port'}
710 vserver_client = mock.Mock()
711 self.mock_object(self.library._client,
712 'list_cluster_nodes',
713 mock.Mock(return_value=fake.CLUSTER_NODES))
714 self.mock_object(self.library,
715 '_get_node_data_port',
716 mock.Mock(return_value='fake_port'))
717 self.mock_object(context,
718 'get_admin_context',
719 mock.Mock(return_value='fake_admin_context'))
720 self.mock_object(self.library,
721 '_get_api_client',
722 mock.Mock(return_value=vserver_client))
723 self.mock_object(self.library._client,
724 'vserver_exists',
725 mock.Mock(return_value=False))
726 self.mock_object(self.library,
727 '_find_matching_aggregates',
728 mock.Mock(return_value=fake.AGGREGATES))
729 self.mock_object(self.library,
730 '_get_flexgroup_aggr_set',
731 mock.Mock(return_value=fake.AGGREGATES))
732 self.mock_object(self.library,
733 '_create_ipspace',
734 mock.Mock(return_value=fake.IPSPACE))
735 self.mock_object(self.library,
736 '_create_vserver_lifs')
737 self.mock_object(self.library,
738 '_create_vserver_routes')
739 self.mock_object(self.library,
740 '_create_vserver_admin_lif')
741 self.mock_object(self.library._client,
742 'create_port_and_broadcast_domain',
743 mock.Mock(side_effect=['fake_port',
744 'another_fake_port']))
745 get_ipspace_name_for_vlan_port = self.mock_object(
746 self.library._client,
747 'get_ipspace_name_for_vlan_port',
748 mock.Mock(return_value=existing_ipspace))
750 self.library._create_vserver(vserver_name, fake.NETWORK_INFO_LIST,
751 fake.NFS_CONFIG_TCP_UDP_MAX,
752 nfs_config=nfs_config)
754 get_ipspace_name_for_vlan_port.assert_called_once_with(
755 fake.CLUSTER_NODES[0],
756 'fake_port',
757 fake.NETWORK_INFO['segmentation_id'])
758 if not existing_ipspace:
759 self.library._create_ipspace.assert_called_once_with(
760 fake.NETWORK_INFO)
761 self.library._client.create_vserver.assert_called_once_with(
762 vserver_name, fake.ROOT_VOLUME_AGGREGATE, fake.ROOT_VOLUME,
763 set(fake.AGGREGATES), fake.IPSPACE,
764 fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS,
765 fake.DELETE_RETENTION_HOURS,
766 False)
767 self.library._get_api_client.assert_called_once_with(
768 vserver=vserver_name)
769 self.library._create_vserver_lifs.assert_called_once_with(
770 vserver_name, vserver_client, fake.NETWORK_INFO, fake.IPSPACE,
771 lif_home_ports=fake_lif_home_ports)
772 self.library._create_vserver_routes.assert_called_once_with(
773 vserver_client, fake.NETWORK_INFO)
774 self.library._create_vserver_admin_lif.assert_called_once_with(
775 vserver_name, vserver_client, fake.NETWORK_INFO, fake.IPSPACE,
776 lif_home_ports=fake_lif_home_ports)
777 vserver_client.enable_nfs.assert_called_once_with(
778 versions, nfs_config=nfs_config)
779 self.library._client.setup_security_services.assert_called_once_with(
780 fake.NETWORK_INFO['security_services'], vserver_client,
781 vserver_name, False)
782 self.library._get_flexgroup_aggr_set.assert_called_once_with()
784 @ddt.data(None, fake.IPSPACE)
785 def test_create_vserver_dp_destination(self, existing_ipspace):
786 versions = ['fake_v1', 'fake_v2']
787 self.library.configuration.netapp_enabled_share_protocols = versions
788 vserver_id = fake.NETWORK_INFO['server_id']
789 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
791 self.mock_object(self.library._client,
792 'vserver_exists',
793 mock.Mock(return_value=False))
794 self.mock_object(self.library._client,
795 'list_cluster_nodes',
796 mock.Mock(return_value=fake.CLUSTER_NODES))
797 self.mock_object(self.library,
798 '_get_node_data_port',
799 mock.Mock(return_value='fake_port'))
800 self.mock_object(context,
801 'get_admin_context',
802 mock.Mock(return_value='fake_admin_context'))
803 self.mock_object(self.library,
804 '_find_matching_aggregates',
805 mock.Mock(return_value=fake.AGGREGATES))
806 self.mock_object(self.library,
807 '_get_flexgroup_aggr_set',
808 mock.Mock(return_value=fake.AGGREGATES))
809 self.mock_object(self.library,
810 '_create_ipspace',
811 mock.Mock(return_value=fake.IPSPACE))
813 get_ipspace_name_for_vlan_port = self.mock_object(
814 self.library._client,
815 'get_ipspace_name_for_vlan_port',
816 mock.Mock(return_value=existing_ipspace))
817 self.mock_object(self.library, '_create_port_and_broadcast_domain')
819 self.library._create_vserver(vserver_name, fake.NETWORK_INFO_LIST,
820 metadata={'migration_destination': True})
822 get_ipspace_name_for_vlan_port.assert_called_once_with(
823 fake.CLUSTER_NODES[0],
824 'fake_port',
825 fake.NETWORK_INFO['segmentation_id'])
826 if not existing_ipspace:
827 self.library._create_ipspace.assert_called_once_with(
828 fake.NETWORK_INFO)
829 create_server_mock = self.library._client.create_vserver_dp_destination
830 create_server_mock.assert_called_once_with(
831 vserver_name, fake.AGGREGATES, fake.IPSPACE,
832 fake.DELETE_RETENTION_HOURS, False)
833 self.library._create_port_and_broadcast_domain.assert_called_once_with(
834 fake.IPSPACE, fake.NETWORK_INFO)
835 self.library._get_flexgroup_aggr_set.assert_not_called()
837 def test_create_vserver_already_present(self):
839 vserver_id = fake.NETWORK_INFO['server_id']
840 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
842 self.mock_object(context,
843 'get_admin_context',
844 mock.Mock(return_value='fake_admin_context'))
845 self.mock_object(self.library._client,
846 'vserver_exists',
847 mock.Mock(return_value=True))
849 self.assertRaises(exception.NetAppException,
850 self.library._create_vserver,
851 vserver_name,
852 fake.NETWORK_INFO,
853 fake.NFS_CONFIG_TCP_UDP_MAX)
855 @ddt.data(
856 {'network_exception': netapp_api.NaApiError,
857 'existing_ipspace': fake.IPSPACE},
858 {'network_exception': netapp_api.NaApiError,
859 'existing_ipspace': None},
860 {'network_exception': exception.NetAppException,
861 'existing_ipspace': None},
862 {'network_exception': exception.NetAppException,
863 'existing_ipspace': fake.IPSPACE})
864 @ddt.unpack
865 def test_create_vserver_lif_creation_failure(self,
866 network_exception,
867 existing_ipspace):
869 vserver_id = fake.NETWORK_INFO['server_id']
870 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
871 vserver_client = mock.Mock()
872 security_service = fake.NETWORK_INFO['security_services']
874 self.mock_object(self.library._client,
875 'list_cluster_nodes',
876 mock.Mock(return_value=fake.CLUSTER_NODES))
877 self.mock_object(self.library,
878 '_get_node_data_port',
879 mock.Mock(return_value='fake_port'))
880 self.mock_object(context,
881 'get_admin_context',
882 mock.Mock(return_value='fake_admin_context'))
883 self.mock_object(self.library,
884 '_get_api_client',
885 mock.Mock(return_value=vserver_client))
886 self.mock_object(self.library._client,
887 'vserver_exists',
888 mock.Mock(return_value=False))
889 self.mock_object(self.library,
890 '_find_matching_aggregates',
891 mock.Mock(return_value=fake.AGGREGATES))
892 self.mock_object(self.library,
893 '_get_flexgroup_aggr_set',
894 mock.Mock(return_value=fake.AGGREGATES))
895 self.mock_object(self.library._client,
896 'get_ipspace_name_for_vlan_port',
897 mock.Mock(return_value=existing_ipspace))
898 self.mock_object(self.library,
899 '_create_ipspace',
900 mock.Mock(return_value=fake.IPSPACE))
901 self.mock_object(self.library,
902 '_setup_network_for_vserver',
903 mock.Mock(side_effect=network_exception))
904 self.mock_object(self.library, '_delete_vserver')
906 self.assertRaises(network_exception,
907 self.library._create_vserver,
908 vserver_name,
909 fake.NETWORK_INFO_LIST,
910 fake.NFS_CONFIG_TCP_UDP_MAX)
912 self.library._get_api_client.assert_called_with(vserver=vserver_name)
913 self.assertTrue(self.library._client.create_vserver.called)
914 self.library._setup_network_for_vserver.assert_called_with(
915 vserver_name,
916 vserver_client,
917 fake.NETWORK_INFO_LIST,
918 fake.IPSPACE,
919 security_services=security_service,
920 nfs_config=None)
921 self.library._delete_vserver.assert_called_once_with(
922 vserver_name,
923 needs_lock=False,
924 security_services=security_service)
925 self.assertFalse(vserver_client.enable_nfs.called)
926 self.assertEqual(1, lib_multi_svm.LOG.error.call_count)
928 def test__create_barbican_kms_config_for_specified_vserver(self):
930 vserver_id = fake.NETWORK_INFO['server_id']
931 vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
932 fake_config_uuid = "fake_uuid"
934 self.mock_object(
935 share_utils, 'extract_host',
936 mock.Mock(
937 return_value=fake.SERVER_METADATA_WITH_ENCRYPTION[
938 'request_host']))
939 self.mock_object(data_motion, 'get_client_for_backend',
940 mock.Mock(return_value=self.fake_client))
941 self.mock_object(self.fake_client,
942 'create_barbican_kms_config_for_specified_vserver')
943 self.mock_object(self.fake_client,
944 'get_key_store_config_uuid',
945 mock.Mock(return_value=fake_config_uuid))
946 self.mock_object(self.fake_client,
947 'enable_key_store_config')
949 self.library._create_barbican_kms_config_for_specified_vserver(
950 vserver_name, fake.SERVER_METADATA_WITH_ENCRYPTION)
952 share_utils.extract_host.assert_called_once_with(
953 fake.SERVER_METADATA_WITH_ENCRYPTION['request_host'],
954 level='backend_name')
955 data_motion.get_client_for_backend.assert_called_once_with(
956 fake.SERVER_METADATA_WITH_ENCRYPTION['request_host'],
957 vserver_name=None,
958 force_rest_client=True)
959 self.fake_client.create_barbican_kms_config_for_specified_vserver.\
960 assert_called_once_with(
961 vserver_name, mock.ANY,
962 fake.SERVER_METADATA_WITH_ENCRYPTION['encryption_key_ref'],
963 fake.SERVER_METADATA_WITH_ENCRYPTION['keystone_url'],
964 fake.SERVER_METADATA_WITH_ENCRYPTION
965 ['application_credential_id'],
966 fake.SERVER_METADATA_WITH_ENCRYPTION
967 ['application_credential_secret'])
968 self.fake_client.enable_key_store_config(fake_config_uuid)
970 def test_get_valid_ipspace_name(self):
972 result = self.library._get_valid_ipspace_name(fake.IPSPACE_ID)
974 expected = 'ipspace_' + fake.IPSPACE_ID.replace('-', '_')
975 self.assertEqual(expected, result)
977 def test_create_ipspace_not_supported(self):
979 self.library._client.features.IPSPACES = False
981 result = self.library._create_ipspace(fake.NETWORK_INFO)
983 self.assertIsNone(result)
985 @ddt.data(None, 'flat')
986 def test_create_ipspace_not_vlan(self, network_type):
988 self.library._client.features.IPSPACES = True
989 network_info = copy.deepcopy(fake.NETWORK_INFO)
990 network_info['network_allocations'][0]['segmentation_id'] = None
991 network_info['network_allocations'][0]['network_type'] = network_type
993 result = self.library._create_ipspace(network_info)
995 self.assertEqual('Default', result)
997 def test_create_ipspace(self):
999 self.library._client.features.IPSPACES = True
1000 self.mock_object(self.library._client,
1001 'create_ipspace',
1002 mock.Mock(return_value=False))
1004 result = self.library._create_ipspace(fake.NETWORK_INFO)
1006 expected = self.library._get_valid_ipspace_name(
1007 fake.NETWORK_INFO['neutron_net_id'])
1008 self.assertEqual(expected, result)
1009 self.library._client.create_ipspace.assert_called_once_with(expected)
1011 def test_create_vserver_lifs(self):
1013 self.mock_object(self.library._client,
1014 'list_cluster_nodes',
1015 mock.Mock(return_value=fake.CLUSTER_NODES))
1016 self.mock_object(self.library,
1017 '_get_lif_name',
1018 mock.Mock(side_effect=['fake_lif1', 'fake_lif2']))
1019 self.mock_object(self.library, '_create_lif')
1021 self.library._create_vserver_lifs(fake.VSERVER1,
1022 'fake_vserver_client',
1023 fake.NETWORK_INFO,
1024 fake.IPSPACE)
1026 self.library._create_lif.assert_has_calls([
1027 mock.call('fake_vserver_client', fake.VSERVER1, fake.IPSPACE,
1028 fake.CLUSTER_NODES[0], 'fake_lif1',
1029 fake.NETWORK_INFO['network_allocations'][0],
1030 lif_home_port=None),
1031 mock.call('fake_vserver_client', fake.VSERVER1, fake.IPSPACE,
1032 fake.CLUSTER_NODES[1], 'fake_lif2',
1033 fake.NETWORK_INFO['network_allocations'][1],
1034 lif_home_port=None)])
1036 def test_create_vserver_lifs_pre_configured_home_ports(self):
1038 self.mock_object(self.library._client,
1039 'list_cluster_nodes',
1040 mock.Mock(return_value=fake.CLUSTER_NODES))
1041 self.mock_object(self.library,
1042 '_get_lif_name',
1043 mock.Mock(side_effect=['fake_lif1', 'fake_lif2']))
1044 self.mock_object(self.library, '_create_lif')
1046 lif_home_ports = {
1047 fake.CLUSTER_NODES[0]: 'fake_port1',
1048 fake.CLUSTER_NODES[1]: 'fake_port2'
1049 }
1051 self.library._create_vserver_lifs(fake.VSERVER1,
1052 'fake_vserver_client',
1053 fake.NETWORK_INFO,
1054 fake.IPSPACE,
1055 lif_home_ports=lif_home_ports)
1057 self.library._create_lif.assert_has_calls([
1058 mock.call('fake_vserver_client', fake.VSERVER1, fake.IPSPACE,
1059 fake.CLUSTER_NODES[0], 'fake_lif1',
1060 fake.NETWORK_INFO['network_allocations'][0],
1061 lif_home_port=lif_home_ports[fake.CLUSTER_NODES[0]]),
1062 mock.call('fake_vserver_client', fake.VSERVER1, fake.IPSPACE,
1063 fake.CLUSTER_NODES[1], 'fake_lif2',
1064 fake.NETWORK_INFO['network_allocations'][1],
1065 lif_home_port=lif_home_ports[fake.CLUSTER_NODES[1]])])
1067 def test_create_vserver_admin_lif(self):
1069 self.mock_object(self.library._client,
1070 'list_cluster_nodes',
1071 mock.Mock(return_value=fake.CLUSTER_NODES))
1072 self.mock_object(self.library,
1073 '_get_lif_name',
1074 mock.Mock(return_value='fake_admin_lif'))
1075 self.mock_object(self.library, '_create_lif')
1077 self.library._create_vserver_admin_lif(fake.VSERVER1,
1078 'fake_vserver_client',
1079 fake.NETWORK_INFO,
1080 fake.IPSPACE)
1082 self.library._create_lif.assert_has_calls([
1083 mock.call('fake_vserver_client', fake.VSERVER1, fake.IPSPACE,
1084 fake.CLUSTER_NODES[0], 'fake_admin_lif',
1085 fake.NETWORK_INFO['admin_network_allocations'][0],
1086 lif_home_port=None)])
1088 def test_create_vserver_admin_lif_no_admin_network(self):
1090 fake_network_info = copy.deepcopy(fake.NETWORK_INFO)
1091 fake_network_info['admin_network_allocations'] = []
1093 self.mock_object(self.library._client,
1094 'list_cluster_nodes',
1095 mock.Mock(return_value=fake.CLUSTER_NODES))
1096 self.mock_object(self.library,
1097 '_get_lif_name',
1098 mock.Mock(return_value='fake_admin_lif'))
1099 self.mock_object(self.library, '_create_lif')
1101 self.library._create_vserver_admin_lif(fake.VSERVER1,
1102 'fake_vserver_client',
1103 fake_network_info,
1104 fake.IPSPACE)
1106 self.assertFalse(self.library._create_lif.called)
1108 @ddt.data(
1109 fake.get_network_info(fake.USER_NETWORK_ALLOCATIONS,
1110 fake.ADMIN_NETWORK_ALLOCATIONS),
1111 fake.get_network_info(fake.USER_NETWORK_ALLOCATIONS_IPV6,
1112 fake.ADMIN_NETWORK_ALLOCATIONS))
1113 def test_create_vserver_routes(self, network_info):
1114 expected_gateway = network_info['network_allocations'][0]['gateway']
1115 vserver_client = mock.Mock()
1116 self.mock_object(vserver_client, 'create_route')
1118 retval = self.library._create_vserver_routes(
1119 vserver_client, network_info)
1121 self.assertIsNone(retval)
1122 vserver_client.create_route.assert_called_once_with(expected_gateway)
1124 def test_get_node_data_port(self):
1126 self.mock_object(self.client,
1127 'list_node_data_ports',
1128 mock.Mock(return_value=fake.NODE_DATA_PORTS))
1129 self.library.configuration.netapp_port_name_search_pattern = 'e0c'
1131 result = self.library._get_node_data_port(fake.CLUSTER_NODE)
1133 self.assertEqual('e0c', result)
1134 self.library._client.list_node_data_ports.assert_has_calls([
1135 mock.call(fake.CLUSTER_NODE)])
1137 def test_get_node_data_port_no_match(self):
1139 self.mock_object(self.client,
1140 'list_node_data_ports',
1141 mock.Mock(return_value=fake.NODE_DATA_PORTS))
1142 self.library.configuration.netapp_port_name_search_pattern = 'ifgroup1'
1144 self.assertRaises(exception.NetAppException,
1145 self.library._get_node_data_port,
1146 fake.CLUSTER_NODE)
1148 def test_get_lif_name(self):
1150 result = self.library._get_lif_name(
1151 'fake_node', fake.NETWORK_INFO['network_allocations'][0])
1153 self.assertEqual('os_132dbb10-9a36-46f2-8d89-3d909830c356', result)
1155 @ddt.data(fake.MTU, None, 'not-present')
1156 def test_create_lif(self, mtu):
1157 """Tests cases where MTU is a valid value, None or not present."""
1159 expected_mtu = (mtu if mtu not in (None, 'not-present') else
1160 fake.DEFAULT_MTU)
1162 network_allocations = copy.deepcopy(
1163 fake.NETWORK_INFO['network_allocations'][0])
1164 network_allocations['mtu'] = mtu
1166 if mtu == 'not-present':
1167 network_allocations.pop('mtu')
1169 vserver_client = mock.Mock()
1171 self.mock_object(self.library, '_get_node_data_port',
1172 mock.Mock(return_value='fake_port'))
1174 vserver_client.network_interface_exists = mock.Mock(
1175 return_value=False)
1177 self.library._client.create_port_and_broadcast_domain = (
1178 mock.Mock(return_value='fake_port'))
1180 self.library._create_lif(vserver_client,
1181 'fake_vserver',
1182 'fake_ipspace',
1183 'fake_node',
1184 'fake_lif',
1185 network_allocations,
1186 lif_home_port=None)
1188 self.library._get_node_data_port.assert_called_once_with(
1189 'fake_node')
1191 (vserver_client.network_interface_exists
1192 .assert_called_once_with('fake_vserver', 'fake_node', 'fake_port',
1193 '10.10.10.10', '255.255.255.0', '1000',
1194 home_port=None))
1196 (self.library._client.create_port_and_broadcast_domain
1197 .assert_called_once_with('fake_node', 'fake_port', '1000',
1198 expected_mtu, 'fake_ipspace'))
1200 (self.library._client.create_network_interface
1201 .assert_called_once_with('10.10.10.10', '255.255.255.0',
1202 'fake_node', 'fake_port',
1203 'fake_vserver', 'fake_lif'))
1205 def test_create_lif_existent_home_port(self):
1206 """Tests case where a existent port is passed to the function"""
1208 network_allocations = copy.deepcopy(
1209 fake.NETWORK_INFO['network_allocations'][0])
1211 vserver_client = mock.Mock()
1212 mock_get_node_data_port = self.mock_object(
1213 self.library, '_get_node_data_port')
1215 vserver_client.network_interface_exists = mock.Mock(
1216 return_value=False)
1218 mock_create_port_and_broadcast_domain = (
1219 self.library._client.create_port_and_broadcast_domain)
1221 self.library._create_lif(vserver_client,
1222 'fake_vserver',
1223 'fake_ipspace',
1224 'fake_node',
1225 'fake_lif',
1226 network_allocations,
1227 lif_home_port='fake_port_from_param')
1229 (vserver_client.network_interface_exists
1230 .assert_called_once_with('fake_vserver', 'fake_node',
1231 'fake_port_from_param',
1232 '10.10.10.10', '255.255.255.0', '1000',
1233 home_port='fake_port_from_param'))
1235 mock_get_node_data_port.assert_not_called()
1236 mock_create_port_and_broadcast_domain.assert_not_called()
1238 (self.library._client.create_network_interface
1239 .assert_called_once_with('10.10.10.10', '255.255.255.0',
1240 'fake_node', 'fake_port_from_param',
1241 'fake_vserver', 'fake_lif'))
1243 def test_create_lif_if_nonexistent_already_present(self):
1245 vserver_client = mock.Mock()
1246 vserver_client.network_interface_exists = mock.Mock(
1247 return_value=True)
1248 self.mock_object(self.library,
1249 '_get_node_data_port',
1250 mock.Mock(return_value='fake_port'))
1252 self.library._create_lif(vserver_client,
1253 'fake_vserver',
1254 fake.IPSPACE,
1255 'fake_node',
1256 'fake_lif',
1257 fake.NETWORK_INFO['network_allocations'][0],
1258 lif_home_port=None)
1260 self.assertFalse(self.library._client.create_network_interface.called)
1262 def test_get_network_allocations_number(self):
1264 self.library._client.list_cluster_nodes.return_value = (
1265 fake.CLUSTER_NODES)
1267 result = self.library.get_network_allocations_number()
1269 self.assertEqual(len(fake.CLUSTER_NODES), result)
1271 def test_get_admin_network_allocations_number(self):
1273 result = self.library.get_admin_network_allocations_number(
1274 'fake_admin_network_api')
1276 self.assertEqual(1, result)
1278 def test_get_admin_network_allocations_number_no_admin_network(self):
1280 result = self.library.get_admin_network_allocations_number(None)
1282 self.assertEqual(0, result)
1284 def test_teardown_server(self):
1286 self.library._client.vserver_exists.return_value = True
1287 mock_delete_vserver = self.mock_object(self.library,
1288 '_delete_vserver')
1290 self.library.teardown_server(
1291 fake.SHARE_SERVER['backend_details'],
1292 security_services=fake.NETWORK_INFO['security_services'])
1294 self.library._client.vserver_exists.assert_called_once_with(
1295 fake.VSERVER1)
1296 mock_delete_vserver.assert_called_once_with(
1297 fake.VSERVER1,
1298 security_services=fake.NETWORK_INFO['security_services'])
1300 @ddt.data(None, {}, {'vserver_name': None})
1301 def test_teardown_server_no_share_server(self, server_details):
1303 mock_delete_vserver = self.mock_object(self.library,
1304 '_delete_vserver')
1306 self.library.teardown_server(server_details)
1308 self.assertFalse(mock_delete_vserver.called)
1309 self.assertTrue(lib_multi_svm.LOG.warning.called)
1311 def test_teardown_server_no_vserver(self):
1313 self.library._client.vserver_exists.return_value = False
1314 mock_delete_vserver = self.mock_object(self.library,
1315 '_delete_vserver')
1317 self.library.teardown_server(
1318 fake.SHARE_SERVER['backend_details'],
1319 security_services=fake.NETWORK_INFO['security_services'])
1321 self.library._client.vserver_exists.assert_called_once_with(
1322 fake.VSERVER1)
1323 self.assertFalse(mock_delete_vserver.called)
1324 self.assertTrue(lib_multi_svm.LOG.warning.called)
1326 @ddt.data(True, False)
1327 def test_delete_vserver_no_ipspace(self, lock):
1329 self.mock_object(self.library._client,
1330 'get_ipspaces',
1331 mock.Mock(return_value=[]))
1332 vserver_client = mock.Mock()
1333 self.mock_object(self.library,
1334 '_get_api_client',
1335 mock.Mock(return_value=vserver_client))
1336 self.mock_object(self.library._client,
1337 'get_snapmirror_policies',
1338 mock.Mock(return_value=[]))
1340 net_interfaces = copy.deepcopy(c_fake.NETWORK_INTERFACES_MULTIPLE)
1342 self.mock_object(vserver_client,
1343 'get_network_interfaces',
1344 mock.Mock(return_value=net_interfaces))
1345 security_services = fake.NETWORK_INFO['security_services']
1346 self.mock_object(self.library, '_delete_vserver_peers')
1347 self.mock_object(self.library, '_delete_port_vlans')
1349 self.library._delete_vserver(fake.VSERVER1,
1350 security_services=security_services,
1351 needs_lock=lock)
1353 self.library._client.get_ipspaces.assert_called_once_with(
1354 vserver_name=fake.VSERVER1)
1355 self.library._delete_vserver_peers.assert_called_once_with(
1356 fake.VSERVER1)
1357 self.library._client.delete_vserver.assert_called_once_with(
1358 fake.VSERVER1, vserver_client, security_services=security_services)
1359 self.library._client.delete_ipspace.assert_not_called()
1360 self.library._delete_port_vlans.assert_not_called()
1361 self.library._client.delete_vlan.assert_not_called()
1363 @ddt.data(True, False)
1364 def test_delete_vserver_ipspace_has_data_vservers(self, lock):
1366 self.library._client.features.IPSPACES = True
1367 self.mock_object(self.library._client,
1368 'get_ipspaces',
1369 mock.Mock(return_value=c_fake.IPSPACES))
1370 vserver_client = mock.Mock()
1371 self.mock_object(self.library,
1372 '_get_api_client',
1373 mock.Mock(return_value=vserver_client))
1374 self.mock_object(self.library._client,
1375 'ipspace_has_data_vservers',
1376 mock.Mock(return_value=True))
1377 self.mock_object(self.library._client,
1378 'get_snapmirror_policies',
1379 mock.Mock(return_value=[]))
1380 self.mock_object(self.library, '_delete_vserver_peers')
1381 self.mock_object(
1382 vserver_client, 'get_network_interfaces',
1383 mock.Mock(return_value=c_fake.NETWORK_INTERFACES))
1384 self.mock_object(self.library._client,
1385 'delete_ipspace',
1386 mock.Mock(return_value=False))
1387 self.mock_object(self.library._client,
1388 'get_degraded_ports',
1389 mock.Mock(return_value=[]))
1390 self.mock_object(self.library, '_delete_port_vlans')
1391 security_services = fake.NETWORK_INFO['security_services']
1393 self.library._delete_vserver(fake.VSERVER1,
1394 security_services=security_services,
1395 needs_lock=lock)
1397 self.library._client.get_ipspaces.assert_called_once_with(
1398 vserver_name=fake.VSERVER1)
1399 self.library._client.delete_vserver.assert_called_once_with(
1400 fake.VSERVER1, vserver_client, security_services=security_services)
1401 self.library._delete_vserver_peers.assert_called_once_with(
1402 fake.VSERVER1)
1403 self.library._client.delete_ipspace.assert_called_once_with(
1404 c_fake.IPSPACE_NAME
1405 )
1406 self.library._client.get_degraded_ports.assert_called_once_with(
1407 [c_fake.BROADCAST_DOMAIN], c_fake.IPSPACE_NAME
1408 )
1409 # not NETWORK_QUALIFIED_PORTS2, which would be given by get_ipspaces()
1410 self.library._delete_port_vlans.assert_called_once_with(
1411 self.library._client, set(c_fake.NETWORK_QUALIFIED_PORTS))
1413 @ddt.data([], c_fake.NETWORK_INTERFACES)
1414 def test_delete_vserver_with_ipspace(self, interfaces):
1416 self.mock_object(self.library._client,
1417 'get_ipspaces',
1418 mock.Mock(return_value=c_fake.IPSPACES))
1419 vserver_client = mock.Mock()
1420 self.mock_object(self.library,
1421 '_get_api_client',
1422 mock.Mock(return_value=vserver_client))
1423 self.mock_object(self.library._client,
1424 'ipspace_has_data_vservers',
1425 mock.Mock(return_value=False))
1426 self.mock_object(self.library, '_delete_vserver_peers')
1427 self.mock_object(vserver_client,
1428 'get_network_interfaces',
1429 mock.Mock(return_value=interfaces))
1430 self.mock_object(self.library._client,
1431 'get_snapmirror_policies',
1432 mock.Mock(return_value=['fake_policy']))
1434 security_services = fake.NETWORK_INFO['security_services']
1436 self.library._delete_vserver(fake.VSERVER1,
1437 security_services=security_services)
1438 vserver_client.delete_snapmirror_policy.assert_called_once_with(
1439 'fake_policy')
1440 self.library._delete_vserver_peers.assert_called_once_with(
1441 fake.VSERVER1
1442 )
1443 self.library._client.get_ipspaces.assert_called_once_with(
1444 vserver_name=fake.VSERVER1)
1445 self.library._client.delete_vserver.assert_called_once_with(
1446 fake.VSERVER1, vserver_client, security_services=security_services)
1447 self.library._client.delete_ipspace.assert_called_once_with(
1448 c_fake.IPSPACE_NAME)
1449 self.library._client.get_degraded_ports.assert_not_called()
1450 self.library._client.delete_vlan.assert_called_once_with(
1451 c_fake.NODE_NAME2, c_fake.PORT, c_fake.VLAN)
1453 def test__delete_vserver_peers(self):
1455 self.mock_object(self.library,
1456 '_get_vserver_peers',
1457 mock.Mock(return_value=fake.VSERVER_PEER))
1458 self.mock_object(self.library, '_delete_vserver_peer')
1460 self.library._delete_vserver_peers(fake.VSERVER1)
1462 self.library._get_vserver_peers.assert_called_once_with(
1463 vserver=fake.VSERVER1
1464 )
1465 self.library._delete_vserver_peer.assert_called_once_with(
1466 fake.VSERVER_PEER[0]['vserver'],
1467 fake.VSERVER_PEER[0]['peer-vserver']
1468 )
1470 def test_delete_port_vlans(self):
1472 self.library._delete_port_vlans(self.library._client,
1473 c_fake.NETWORK_QUALIFIED_PORTS)
1474 for port_name in c_fake.NETWORK_QUALIFIED_PORTS:
1475 node, port = port_name.split(':')
1476 port, vlan = port.split('-')
1477 self.library._client.delete_vlan.assert_called_once_with(
1478 node, port, vlan)
1480 def test_delete_port_vlans_client_error(self):
1482 mock_exception_log = self.mock_object(lib_multi_svm.LOG, 'exception')
1483 self.mock_object(
1484 self.library._client,
1485 'delete_vlan',
1486 mock.Mock(side_effect=exception.NetAppException("fake error")))
1488 self.library._delete_port_vlans(self.library._client,
1489 c_fake.NETWORK_QUALIFIED_PORTS)
1490 for port_name in c_fake.NETWORK_QUALIFIED_PORTS:
1491 node, port = port_name.split(':')
1492 port, vlan = port.split('-')
1493 self.library._client.delete_vlan.assert_called_once_with(
1494 node, port, vlan)
1495 self.assertEqual(1, mock_exception_log.call_count)
1497 @ddt.data([], [{'vserver': c_fake.VSERVER_NAME,
1498 'peer-vserver': c_fake.VSERVER_PEER_NAME,
1499 'applications': [
1500 {'vserver-peer-application': 'snapmirror'}]
1501 }])
1502 def test_create_replica(self, vserver_peers):
1503 fake_cluster_name = 'fake_cluster'
1504 self.mock_object(self.library, '_get_vservers_from_replicas',
1505 mock.Mock(return_value=(self.fake_vserver,
1506 self.fake_new_vserver_name)))
1507 self.mock_object(self.library, 'find_active_replica',
1508 mock.Mock(return_value=self.fake_replica))
1509 self.mock_object(share_utils, 'extract_host',
1510 mock.Mock(side_effect=[self.fake_new_replica_host,
1511 self.fake_replica_host]))
1512 self.mock_object(data_motion, 'get_client_for_backend',
1513 mock.Mock(side_effect=[self.fake_new_client,
1514 self.fake_client]))
1515 self.mock_object(self.library, '_get_vserver_peers',
1516 mock.Mock(return_value=vserver_peers))
1517 self.mock_object(self.fake_new_client, 'get_cluster_name',
1518 mock.Mock(return_value=fake_cluster_name))
1519 self.mock_object(self.fake_client, 'create_vserver_peer')
1520 self.mock_object(self.fake_new_client, 'accept_vserver_peer')
1521 lib_base_model_update = {
1522 'export_locations': [],
1523 'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC,
1524 'access_rules_status': constants.STATUS_ACTIVE,
1525 }
1526 self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
1527 'create_replica',
1528 mock.Mock(return_value=lib_base_model_update))
1530 model_update = self.library.create_replica(
1531 None, [self.fake_replica], self.fake_new_replica, [], [],
1532 share_server=None)
1534 self.assertDictEqual(lib_base_model_update, model_update)
1535 self.library._get_vservers_from_replicas.assert_called_once_with(
1536 None, [self.fake_replica], self.fake_new_replica
1537 )
1538 self.library.find_active_replica.assert_called_once_with(
1539 [self.fake_replica]
1540 )
1541 self.assertEqual(2, share_utils.extract_host.call_count)
1542 self.assertEqual(2, data_motion.get_client_for_backend.call_count)
1543 self.library._get_vserver_peers.assert_called_once_with(
1544 self.fake_new_vserver_name, self.fake_vserver
1545 )
1546 self.fake_new_client.get_cluster_name.assert_called_once_with()
1547 if not vserver_peers:
1548 self.fake_client.create_vserver_peer.assert_called_once_with(
1549 self.fake_new_vserver_name, self.fake_vserver,
1550 peer_cluster_name=fake_cluster_name
1551 )
1552 self.fake_new_client.accept_vserver_peer.assert_called_once_with(
1553 self.fake_vserver, self.fake_new_vserver_name
1554 )
1555 base_class = lib_base.NetAppCmodeFileStorageLibrary
1556 base_class.create_replica.assert_called_once_with(
1557 None, [self.fake_replica], self.fake_new_replica, [], []
1558 )
1560 def test_delete_replica(self):
1561 base_class = lib_base.NetAppCmodeFileStorageLibrary
1562 vserver_peers = copy.deepcopy(fake.VSERVER_PEER)
1563 vserver_peers[0]['vserver'] = self.fake_vserver
1564 vserver_peers[0]['peer-vserver'] = self.fake_new_vserver_name
1565 self.mock_object(self.library, '_get_vservers_from_replicas',
1566 mock.Mock(return_value=(self.fake_vserver,
1567 self.fake_new_vserver_name)))
1568 self.mock_object(base_class, 'delete_replica')
1569 self.mock_object(self.library, '_get_snapmirrors_destinations',
1570 mock.Mock(return_value=[]))
1571 self.mock_object(self.library, '_get_snapmirrors',
1572 mock.Mock(return_value=[]))
1573 self.mock_object(self.library, '_get_vserver_peers',
1574 mock.Mock(return_value=vserver_peers))
1575 self.mock_object(self.library, '_delete_vserver_peer')
1577 self.library.delete_replica(None, [self.fake_replica],
1578 self.fake_new_replica, [],
1579 share_server=None)
1581 self.library._get_vservers_from_replicas.assert_called_once_with(
1582 None, [self.fake_replica], self.fake_new_replica
1583 )
1584 self.library._get_snapmirrors_destinations.assert_has_calls(
1585 [mock.call(self.fake_vserver, self.fake_new_vserver_name),
1586 mock.call(self.fake_new_vserver_name, self.fake_vserver)]
1587 )
1588 base_class.delete_replica.assert_called_once_with(
1589 None, [self.fake_replica], self.fake_new_replica, []
1590 )
1591 self.library._get_snapmirrors.assert_has_calls(
1592 [mock.call(self.fake_vserver, self.fake_new_vserver_name),
1593 mock.call(self.fake_new_vserver_name, self.fake_vserver)]
1594 )
1595 self.library._get_vserver_peers.assert_called_once_with(
1596 self.fake_new_vserver_name, self.fake_vserver
1597 )
1598 self.library._delete_vserver_peer.assert_called_once_with(
1599 self.fake_new_vserver_name, self.fake_vserver
1600 )
1602 def test_get_vservers_from_replicas(self):
1603 self.mock_object(self.library, 'find_active_replica',
1604 mock.Mock(return_value=self.fake_replica))
1606 vserver, peer_vserver = self.library._get_vservers_from_replicas(
1607 None, [self.fake_replica], self.fake_new_replica)
1609 self.library.find_active_replica.assert_called_once_with(
1610 [self.fake_replica]
1611 )
1612 self.assertEqual(self.fake_vserver, vserver)
1613 self.assertEqual(self.fake_new_vserver_name, peer_vserver)
1615 def test_get_vserver_peers(self):
1616 self.mock_object(self.library._client, 'get_vserver_peers')
1618 self.library._get_vserver_peers(
1619 vserver=self.fake_vserver, peer_vserver=self.fake_new_vserver_name)
1621 self.library._client.get_vserver_peers.assert_called_once_with(
1622 self.fake_vserver, self.fake_new_vserver_name
1623 )
1625 def test_create_vserver_peer(self):
1626 self.mock_object(self.library._client, 'create_vserver_peer')
1628 self.library._create_vserver_peer(
1629 None, vserver=self.fake_vserver,
1630 peer_vserver=self.fake_new_vserver_name)
1632 self.library._client.create_vserver_peer.assert_called_once_with(
1633 self.fake_vserver, self.fake_new_vserver_name
1634 )
1636 def test_delete_vserver_peer(self):
1637 self.mock_object(self.library._client, 'delete_vserver_peer')
1639 self.library._delete_vserver_peer(
1640 vserver=self.fake_vserver, peer_vserver=self.fake_new_vserver_name)
1642 self.library._client.delete_vserver_peer.assert_called_once_with(
1643 self.fake_vserver, self.fake_new_vserver_name
1644 )
1646 def test_create_share_from_snapshot(self):
1647 fake_parent_share = copy.deepcopy(fake.SHARE)
1648 fake_parent_share['id'] = fake.SHARE_ID2
1649 mock_create_from_snap = self.mock_object(
1650 lib_base.NetAppCmodeFileStorageLibrary,
1651 'create_share_from_snapshot')
1653 self.library.create_share_from_snapshot(
1654 None, fake.SHARE, fake.SNAPSHOT, share_server=fake.SHARE_SERVER,
1655 parent_share=fake_parent_share)
1657 mock_create_from_snap.assert_called_once_with(
1658 None, fake.SHARE, fake.SNAPSHOT, share_server=fake.SHARE_SERVER,
1659 parent_share=fake_parent_share
1660 )
1662 def test_create_share_from_snapshot_group(self):
1663 share = copy.deepcopy(fake.SHARE)
1664 share['source_share_group_snapshot_member_id'] = (
1665 fake.CG_SNAPSHOT_MEMBER_ID1)
1666 fake_parent_share = copy.deepcopy(fake.SHARE)
1667 fake_parent_share['id'] = fake.SHARE_ID2
1668 fake_parent_share['host'] = fake.MANILA_HOST_NAME_2
1669 mock_create_from_snap = self.mock_object(
1670 lib_base.NetAppCmodeFileStorageLibrary,
1671 'create_share_from_snapshot')
1672 mock_data_session = self.mock_object(data_motion, 'DataMotionSession')
1674 self.library.create_share_from_snapshot(
1675 None, share, fake.SNAPSHOT, share_server=fake.SHARE_SERVER,
1676 parent_share=fake_parent_share)
1678 mock_create_from_snap.assert_called_once_with(
1679 None, share, fake.SNAPSHOT, share_server=fake.SHARE_SERVER,
1680 parent_share=fake_parent_share
1681 )
1682 mock_data_session.assert_not_called()
1684 @ddt.data(
1685 {'src_cluster_name': fake.CLUSTER_NAME,
1686 'dest_cluster_name': fake.CLUSTER_NAME, 'has_vserver_peers': None},
1687 {'src_cluster_name': fake.CLUSTER_NAME,
1688 'dest_cluster_name': fake.CLUSTER_NAME_2, 'has_vserver_peers': False},
1689 {'src_cluster_name': fake.CLUSTER_NAME,
1690 'dest_cluster_name': fake.CLUSTER_NAME_2, 'has_vserver_peers': True}
1691 )
1692 @ddt.unpack
1693 def test_create_share_from_snaphot_different_hosts(self, src_cluster_name,
1694 dest_cluster_name,
1695 has_vserver_peers):
1696 class FakeDBObj(dict):
1697 def to_dict(self):
1698 return self
1700 fake_parent_share = copy.deepcopy(fake.SHARE)
1701 fake_parent_share['id'] = fake.SHARE_ID2
1702 fake_parent_share['host'] = fake.MANILA_HOST_NAME_2
1703 fake_share = FakeDBObj(fake.SHARE)
1704 fake_share_server = FakeDBObj(fake.SHARE_SERVER)
1705 src_vserver = fake.VSERVER2
1706 dest_vserver = fake.VSERVER1
1707 src_backend = fake.BACKEND_NAME
1708 dest_backend = fake.BACKEND_NAME_2
1709 mock_dm_session = mock.Mock()
1711 mock_dm_constr = self.mock_object(
1712 data_motion, "DataMotionSession",
1713 mock.Mock(return_value=mock_dm_session))
1714 mock_get_vserver = self.mock_object(
1715 mock_dm_session, 'get_vserver_from_share',
1716 mock.Mock(return_value=src_vserver))
1717 mock_get_vserver_from_share_server = self.mock_object(
1718 mock_dm_session, 'get_vserver_from_share_server',
1719 mock.Mock(return_value=dest_vserver))
1720 src_vserver_client = mock.Mock()
1721 dest_vserver_client = mock.Mock()
1722 mock_extract_host = self.mock_object(
1723 share_utils, 'extract_host',
1724 mock.Mock(side_effect=[src_backend, dest_backend]))
1725 mock_dm_get_client = self.mock_object(
1726 data_motion, 'get_client_for_backend',
1727 mock.Mock(side_effect=[src_vserver_client, dest_vserver_client]))
1728 mock_get_src_cluster_name = self.mock_object(
1729 src_vserver_client, 'get_cluster_name',
1730 mock.Mock(return_value=src_cluster_name))
1731 mock_get_dest_cluster_name = self.mock_object(
1732 dest_vserver_client, 'get_cluster_name',
1733 mock.Mock(return_value=dest_cluster_name))
1734 mock_get_vserver_peers = self.mock_object(
1735 self.library, '_get_vserver_peers',
1736 mock.Mock(return_value=has_vserver_peers))
1737 mock_create_vserver_peer = self.mock_object(dest_vserver_client,
1738 'create_vserver_peer')
1739 mock_accept_peer = self.mock_object(src_vserver_client,
1740 'accept_vserver_peer')
1741 mock_create_from_snap = self.mock_object(
1742 lib_base.NetAppCmodeFileStorageLibrary,
1743 'create_share_from_snapshot')
1745 self.library.create_share_from_snapshot(
1746 None, fake_share, fake.SNAPSHOT, share_server=fake_share_server,
1747 parent_share=fake_parent_share)
1749 internal_share = copy.deepcopy(fake.SHARE)
1750 internal_share['share_server'] = copy.deepcopy(fake.SHARE_SERVER)
1752 mock_dm_constr.assert_called_once()
1753 mock_get_vserver.assert_called_once_with(fake_parent_share)
1754 mock_get_vserver_from_share_server.assert_called_once_with(
1755 fake_share_server)
1756 mock_extract_host.assert_has_calls([
1757 mock.call(fake_parent_share['host'], level='backend_name'),
1758 mock.call(internal_share['host'], level='backend_name')])
1759 mock_dm_get_client.assert_has_calls([
1760 mock.call(src_backend, vserver_name=src_vserver),
1761 mock.call(dest_backend, vserver_name=dest_vserver)
1762 ])
1763 mock_get_src_cluster_name.assert_called_once()
1764 mock_get_dest_cluster_name.assert_called_once()
1765 if src_cluster_name != dest_cluster_name:
1766 mock_get_vserver_peers.assert_called_once_with(dest_vserver,
1767 src_vserver)
1768 if not has_vserver_peers:
1769 mock_create_vserver_peer.assert_called_once_with(
1770 dest_vserver, src_vserver,
1771 peer_cluster_name=src_cluster_name)
1772 mock_accept_peer.assert_called_once_with(src_vserver,
1773 dest_vserver)
1774 mock_create_from_snap.assert_called_once_with(
1775 None, fake.SHARE, fake.SNAPSHOT, share_server=fake.SHARE_SERVER,
1776 parent_share=fake_parent_share)
1778 def test_check_if_extra_spec_is_positive_with_negative_integer(self):
1779 self.assertRaises(exception.NetAppException,
1780 self.library._check_if_max_files_is_valid,
1781 fake.SHARE, -1)
1783 def test_check_if_extra_spec_is_positive_with_string(self):
1784 self.assertRaises(ValueError,
1785 self.library._check_if_max_files_is_valid,
1786 fake.SHARE, 'abc')
1788 def test_check_nfs_config_extra_specs_validity(self):
1789 result = self.library._check_nfs_config_extra_specs_validity(
1790 fake.EXTRA_SPEC)
1792 self.assertIsNone(result)
1794 def test_check_nfs_config_extra_specs_validity_empty_spec(self):
1795 result = self.library._check_nfs_config_extra_specs_validity({})
1797 self.assertIsNone(result)
1799 @ddt.data(fake.INVALID_TCP_MAX_XFER_SIZE_EXTRA_SPEC,
1800 fake.INVALID_UDP_MAX_XFER_SIZE_EXTRA_SPEC)
1801 def test_check_nfs_config_extra_specs_validity_invalid_value(self,
1802 extra_specs):
1803 self.assertRaises(
1804 exception.NetAppException,
1805 self.library._check_nfs_config_extra_specs_validity,
1806 extra_specs)
1808 @ddt.data({}, fake.STRING_EXTRA_SPEC)
1809 def test_get_nfs_config_provisioning_options_empty(self, extra_specs):
1810 result = self.library._get_nfs_config_provisioning_options(
1811 extra_specs)
1813 self.assertDictEqual(result, fake.NFS_CONFIG_DEFAULT)
1815 @ddt.data(
1816 {'extra_specs': fake.NFS_CONFIG_TCP_MAX_DDT['extra_specs'],
1817 'expected': fake.NFS_CONFIG_TCP_MAX_DDT['expected']},
1818 {'extra_specs': fake.NFS_CONFIG_UDP_MAX_DDT['extra_specs'],
1819 'expected': fake.NFS_CONFIG_UDP_MAX_DDT['expected']},
1820 {'extra_specs': fake.NFS_CONFIG_TCP_UDP_MAX_DDT['extra_specs'],
1821 'expected': fake.NFS_CONFIG_TCP_UDP_MAX_DDT['expected']},
1822 )
1823 @ddt.unpack
1824 def test_get_nfs_config_provisioning_options_valid(self, extra_specs,
1825 expected):
1826 result = self.library._get_nfs_config_provisioning_options(
1827 extra_specs)
1829 self.assertDictEqual(expected, result)
1831 @ddt.data({'fake_share_server': fake.SHARE_SERVER_NFS_TCP,
1832 'expected_nfs_config': fake.NFS_CONFIG_TCP_MAX},
1833 {'fake_share_server': fake.SHARE_SERVER_NFS_UDP,
1834 'expected_nfs_config': fake.NFS_CONFIG_UDP_MAX},
1835 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1836 'expected_nfs_config': fake.NFS_CONFIG_TCP_UDP_MAX},
1837 {'fake_share_server': fake.SHARE_SERVER_NO_DETAILS,
1838 'expected_nfs_config': fake.NFS_CONFIG_DEFAULT},
1839 {'fake_share_server': fake.SHARE_SERVER_NFS_DEFAULT,
1840 'expected_nfs_config': None},
1841 {'fake_share_server': fake.SHARE_SERVER_NO_NFS_NONE,
1842 'expected_nfs_config': fake.NFS_CONFIG_DEFAULT})
1843 @ddt.unpack
1844 def test_is_share_server_compatible_true(self, fake_share_server,
1845 expected_nfs_config):
1846 is_same = self.library._is_share_server_compatible(
1847 fake_share_server, expected_nfs_config)
1848 self.assertTrue(is_same)
1850 @ddt.data({'fake_share_server': fake.SHARE_SERVER_NFS_TCP,
1851 'expected_nfs_config': fake.NFS_CONFIG_UDP_MAX},
1852 {'fake_share_server': fake.SHARE_SERVER_NFS_UDP,
1853 'expected_nfs_config': fake.NFS_CONFIG_TCP_MAX},
1854 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1855 'expected_nfs_config': fake.NFS_CONFIG_TCP_MAX},
1856 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1857 'expected_nfs_config': fake.NFS_CONFIG_UDP_MAX},
1858 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1859 'expected_nfs_config': None},
1860 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1861 'expected_nfs_config': {}},
1862 {'fake_share_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1863 'expected_nfs_config': fake.NFS_CONFIG_DEFAULT},
1864 {'fake_share_server': fake.SHARE_SERVER_NO_DETAILS,
1865 'expected_nfs_config': fake.NFS_CONFIG_UDP_MAX},
1866 {'fake_share_server': fake.SHARE_SERVER_NFS_DEFAULT,
1867 'expected_nfs_config': fake.NFS_CONFIG_UDP_MAX},
1868 {'fake_share_server': fake.SHARE_SERVER_NO_NFS_NONE,
1869 'expected_nfs_config': fake.NFS_CONFIG_TCP_MAX})
1870 @ddt.unpack
1871 def test_is_share_server_compatible_false(self, fake_share_server,
1872 expected_nfs_config):
1873 is_same = self.library._is_share_server_compatible(
1874 fake_share_server, expected_nfs_config)
1875 self.assertFalse(is_same)
1877 @ddt.data(
1878 {'expected_server': fake.SHARE_SERVER_NFS_TCP,
1879 'share_group': {'share_server_id': fake.SHARE_SERVER_NFS_TCP['id']},
1880 'nfs_config': fake.NFS_CONFIG_TCP_MAX},
1881 {'expected_server': fake.SHARE_SERVER_NFS_UDP,
1882 'share_group': {'share_server_id': fake.SHARE_SERVER_NFS_UDP['id']},
1883 'nfs_config': fake.NFS_CONFIG_UDP_MAX},
1884 {'expected_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1885 'share_group': {
1886 'share_server_id': fake.SHARE_SERVER_NFS_TCP_UDP['id']},
1887 'nfs_config': fake.NFS_CONFIG_TCP_UDP_MAX},
1888 {'expected_server': fake.SHARE_SERVER_NFS_DEFAULT,
1889 'share_group': {
1890 'share_server_id': fake.SHARE_SERVER_NFS_DEFAULT['id']},
1891 'nfs_config': fake.NFS_CONFIG_DEFAULT},
1892 {'expected_server': None,
1893 'share_group': {'share_server_id': 'invalid_id'},
1894 'nfs_config': fake.NFS_CONFIG_TCP_MAX})
1895 @ddt.unpack
1896 def test_choose_share_server_compatible_with_share_group_and_nfs_config(
1897 self, expected_server, share_group, nfs_config):
1898 self.library.is_nfs_config_supported = True
1899 mock_get_extra_spec = self.mock_object(
1900 share_types, "get_extra_specs_from_share",
1901 mock.Mock(return_value=fake.EXTRA_SPEC))
1902 mock_get_nfs_config = self.mock_object(
1903 self.library,
1904 "_get_nfs_config_provisioning_options",
1905 mock.Mock(return_value=nfs_config))
1906 mock_client = mock.Mock()
1907 self.mock_object(self.library, '_get_vserver',
1908 mock.Mock(return_value=('fake_name',
1909 mock_client)))
1910 self.mock_object(mock_client, 'get_vserver_info',
1911 mock.Mock(return_value=fake.VSERVER_INFO))
1912 self.mock_object(mock_client, 'list_vserver_aggregates',
1913 mock.Mock(return_value=fake.AGGREGATES))
1915 server = self.library.choose_share_server_compatible_with_share(
1916 None, fake.SHARE_SERVERS, fake.SHARE_2, None, share_group)
1918 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
1919 mock_get_nfs_config.assert_called_once_with(fake.EXTRA_SPEC)
1920 self.assertEqual(expected_server, server)
1922 @ddt.data(
1923 {'expected_server': fake.SHARE_SERVER_NO_NFS_NONE,
1924 'share_group': {
1925 'share_server_id': fake.SHARE_SERVER_NO_NFS_NONE['id']}},
1926 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
1927 'share_group': {
1928 'share_server_id': fake.SHARE_SERVER_NO_DETAILS['id']}},
1929 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
1930 'share_group': {
1931 'share_server_id': fake.SHARE_SERVER_NO_DETAILS['id']},
1932 'nfs_config_support': False},
1933 {'expected_server': None,
1934 'share_group': {'share_server_id': 'invalid_id'}})
1935 @ddt.unpack
1936 def test_choose_share_server_compatible_with_share_group_only(
1937 self, expected_server, share_group, nfs_config_support=True):
1938 self.library.is_nfs_config_supported = nfs_config_support
1939 mock_get_extra_spec = self.mock_object(
1940 share_types, "get_extra_specs_from_share",
1941 mock.Mock(return_value=fake.EMPTY_EXTRA_SPEC))
1942 mock_get_nfs_config = self.mock_object(
1943 self.library,
1944 "_get_nfs_config_provisioning_options",
1945 mock.Mock(return_value=fake.NFS_CONFIG_DEFAULT))
1946 mock_client = mock.Mock()
1947 self.mock_object(self.library, '_get_vserver',
1948 mock.Mock(return_value=('fake_name',
1949 mock_client)))
1950 self.mock_object(mock_client, 'get_vserver_info',
1951 mock.Mock(return_value=fake.VSERVER_INFO))
1952 self.mock_object(mock_client, 'list_vserver_aggregates',
1953 mock.Mock(return_value=fake.AGGREGATES))
1955 server = self.library.choose_share_server_compatible_with_share(
1956 None, fake.SHARE_SERVERS, fake.SHARE_2, None, share_group)
1958 self.assertEqual(expected_server, server)
1959 if nfs_config_support:
1960 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
1961 mock_get_nfs_config.assert_called_once_with(fake.EMPTY_EXTRA_SPEC)
1963 @ddt.data(
1964 {'expected_server': fake.SHARE_SERVER_NFS_TCP,
1965 'nfs_config': fake.NFS_CONFIG_TCP_MAX},
1966 {'expected_server': fake.SHARE_SERVER_NFS_UDP,
1967 'nfs_config': fake.NFS_CONFIG_UDP_MAX},
1968 {'expected_server': fake.SHARE_SERVER_NFS_TCP_UDP,
1969 'nfs_config': fake.NFS_CONFIG_TCP_UDP_MAX},
1970 {'expected_server': fake.SHARE_SERVER_NFS_DEFAULT,
1971 'nfs_config': fake.NFS_CONFIG_DEFAULT},
1972 {'expected_server': None,
1973 'nfs_config': {'invalid': 'invalid'}},
1974 {'expected_server': fake.SHARE_SERVER_NFS_TCP,
1975 'nfs_config': None, 'nfs_config_support': False},
1976 )
1977 @ddt.unpack
1978 def test_choose_share_server_compatible_with_share_nfs_config_only(
1979 self, expected_server, nfs_config, nfs_config_support=True):
1980 self.library.is_nfs_config_supported = nfs_config_support
1981 mock_get_extra_spec = self.mock_object(
1982 share_types, "get_extra_specs_from_share",
1983 mock.Mock(return_value=fake.EXTRA_SPEC))
1984 mock_get_nfs_config = self.mock_object(
1985 self.library,
1986 "_get_nfs_config_provisioning_options",
1987 mock.Mock(return_value=nfs_config))
1988 mock_client = mock.Mock()
1989 self.mock_object(self.library, '_get_vserver',
1990 mock.Mock(return_value=('fake_name',
1991 mock_client)))
1992 self.mock_object(mock_client, 'get_vserver_info',
1993 mock.Mock(return_value=fake.VSERVER_INFO))
1994 self.mock_object(mock_client, 'list_vserver_aggregates',
1995 mock.Mock(return_value=fake.AGGREGATES))
1997 server = self.library.choose_share_server_compatible_with_share(
1998 None, fake.SHARE_SERVERS, fake.SHARE_2)
2000 self.assertEqual(expected_server, server)
2001 if nfs_config_support:
2002 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
2003 mock_get_nfs_config.assert_called_once_with(fake.EXTRA_SPEC)
2005 @ddt.data(
2006 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
2007 'share_servers': [
2008 fake.SHARE_SERVER_NFS_TCP, fake.SHARE_SERVER_NO_DETAILS]},
2009 {'expected_server': fake.SHARE_SERVER_NO_NFS_NONE,
2010 'share_servers': [
2011 fake.SHARE_SERVER_NFS_UDP, fake.SHARE_SERVER_NO_NFS_NONE]},
2012 {'expected_server': fake.SHARE_SERVER_NFS_DEFAULT,
2013 'share_servers': [
2014 fake.SHARE_SERVER_NFS_UDP, fake.SHARE_SERVER_NFS_DEFAULT]},
2015 {'expected_server': None,
2016 'share_servers': [
2017 fake.SHARE_SERVER_NFS_TCP, fake.SHARE_SERVER_NFS_UDP]},
2018 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
2019 'share_servers': [fake.SHARE_SERVER_NO_DETAILS],
2020 'nfs_config_support': False}
2021 )
2022 @ddt.unpack
2023 def test_choose_share_server_compatible_with_share_no_specification(
2024 self, expected_server, share_servers, nfs_config_support=True):
2025 self.library.is_nfs_config_supported = nfs_config_support
2026 mock_get_extra_spec = self.mock_object(
2027 share_types, "get_extra_specs_from_share",
2028 mock.Mock(return_value=fake.EMPTY_EXTRA_SPEC))
2029 mock_get_nfs_config = self.mock_object(
2030 self.library,
2031 "_get_nfs_config_provisioning_options",
2032 mock.Mock(return_value=fake.NFS_CONFIG_DEFAULT))
2033 mock_client = mock.Mock()
2034 self.mock_object(self.library, '_get_vserver',
2035 mock.Mock(return_value=('fake_name',
2036 mock_client)))
2037 self.mock_object(mock_client, 'get_vserver_info',
2038 mock.Mock(return_value=fake.VSERVER_INFO))
2039 self.mock_object(mock_client, 'list_vserver_aggregates',
2040 mock.Mock(return_value=fake.AGGREGATES))
2042 server = self.library.choose_share_server_compatible_with_share(
2043 None, share_servers, fake.SHARE_2)
2045 self.assertEqual(expected_server, server)
2046 if nfs_config_support:
2047 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
2048 mock_get_nfs_config.assert_called_once_with(fake.EMPTY_EXTRA_SPEC)
2050 def test_manage_existing_error(self):
2051 fake_server = {'id': 'id'}
2052 fake_nfs_config = 'fake_nfs_config'
2053 self.library.is_nfs_config_supported = True
2055 mock_get_extra_spec = self.mock_object(
2056 share_types, "get_extra_specs_from_share",
2057 mock.Mock(return_value=fake.EXTRA_SPEC))
2058 mock_get_nfs_config = self.mock_object(
2059 self.library,
2060 "_get_nfs_config_provisioning_options",
2061 mock.Mock(return_value=fake_nfs_config))
2062 mock_is_compatible = self.mock_object(
2063 self.library,
2064 "_is_share_server_compatible",
2065 mock.Mock(return_value=False))
2067 self.assertRaises(exception.NetAppException,
2068 self.library.manage_existing,
2069 fake.SHARE, 'opts', fake_server)
2071 mock_get_extra_spec.assert_called_once_with(fake.SHARE)
2072 mock_get_nfs_config.assert_called_once_with(fake.EXTRA_SPEC)
2073 mock_is_compatible.assert_called_once_with(fake_server,
2074 fake_nfs_config)
2076 def test_choose_share_server_compatible_with_share_group_no_share_server(
2077 self):
2078 server = self.library.choose_share_server_compatible_with_share_group(
2079 None, [], fake.SHARE_GROUP_REF)
2081 self.assertIsNone(server)
2083 @ddt.data(
2084 [fake.NFS_CONFIG_DEFAULT, fake.NFS_CONFIG_TCP_MAX],
2085 [fake.NFS_CONFIG_TCP_MAX, fake.NFS_CONFIG_UDP_MAX],
2086 [fake.NFS_CONFIG_TCP_UDP_MAX, fake.NFS_CONFIG_TCP_MAX],
2087 [fake.NFS_CONFIG_DEFAULT, fake.NFS_CONFIG_TCP_UDP_MAX])
2088 def test_choose_share_server_compatible_with_share_group_nfs_conflict(
2089 self, nfs_config_list):
2090 self.library.is_nfs_config_supported = True
2091 self.mock_object(
2092 share_types, "get_share_type_extra_specs",
2093 mock.Mock(return_value=fake.EXTRA_SPEC))
2094 mock_get_nfs_config = self.mock_object(
2095 self.library,
2096 "_get_nfs_config_provisioning_options",
2097 mock.Mock(side_effect=nfs_config_list))
2098 mock_check_extra_spec = self.mock_object(
2099 self.library,
2100 '_check_nfs_config_extra_specs_validity',
2101 mock.Mock())
2103 self.assertRaises(exception.InvalidInput,
2104 self.library.
2105 choose_share_server_compatible_with_share_group,
2106 None, fake.SHARE_SERVERS, fake.SHARE_GROUP_REF)
2108 mock_get_nfs_config.assert_called_with(fake.EXTRA_SPEC)
2109 mock_check_extra_spec.assert_called_once_with(fake.EXTRA_SPEC)
2111 @ddt.data(
2112 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
2113 'nfs_config': fake.NFS_CONFIG_DEFAULT,
2114 'share_servers': [
2115 fake.SHARE_SERVER_NFS_TCP, fake.SHARE_SERVER_NO_DETAILS]},
2116 {'expected_server': fake.SHARE_SERVER_NO_NFS_NONE,
2117 'nfs_config': fake.NFS_CONFIG_DEFAULT,
2118 'share_servers': [
2119 fake.SHARE_SERVER_NFS_UDP, fake.SHARE_SERVER_NO_NFS_NONE]},
2120 {'expected_server': fake.SHARE_SERVER_NFS_DEFAULT,
2121 'nfs_config': fake.NFS_CONFIG_DEFAULT,
2122 'share_servers': [
2123 fake.SHARE_SERVER_NFS_UDP, fake.SHARE_SERVER_NFS_DEFAULT]},
2124 {'expected_server': None,
2125 'nfs_config': fake.NFS_CONFIG_DEFAULT,
2126 'share_servers': [
2127 fake.SHARE_SERVER_NFS_TCP, fake.SHARE_SERVER_NFS_UDP,
2128 fake.SHARE_SERVER_NFS_TCP_UDP]},
2129 {'expected_server': fake.SHARE_SERVER_NFS_TCP_UDP,
2130 'nfs_config': fake.NFS_CONFIG_TCP_UDP_MAX,
2131 'share_servers': [
2132 fake.SHARE_SERVER_NFS_TCP, fake.SHARE_SERVER_NFS_UDP,
2133 fake.SHARE_SERVER_NFS_DEFAULT, fake.SHARE_SERVER_NFS_TCP_UDP]},
2134 {'expected_server': fake.SHARE_SERVER_NO_DETAILS,
2135 'nfs_config': None,
2136 'share_servers': [fake.SHARE_SERVER_NO_DETAILS],
2137 'nfs_config_supported': False}
2138 )
2139 @ddt.unpack
2140 def test_choose_share_server_compatible_with_share_group_nfs(
2141 self, expected_server, nfs_config, share_servers,
2142 nfs_config_supported=True):
2143 self.library.is_nfs_config_supported = nfs_config_supported
2144 mock_client = mock.Mock()
2145 self.mock_object(
2146 share_types, "get_share_type_extra_specs",
2147 mock.Mock(return_value=fake.EXTRA_SPEC))
2148 mock_get_nfs_config = self.mock_object(
2149 self.library,
2150 "_get_nfs_config_provisioning_options",
2151 mock.Mock(return_value=nfs_config))
2152 mock_check_extra_spec = self.mock_object(
2153 self.library,
2154 '_check_nfs_config_extra_specs_validity',
2155 mock.Mock())
2156 self.mock_object(self.library, '_get_vserver',
2157 mock.Mock(return_value=('fake_name',
2158 mock_client)))
2159 self.mock_object(mock_client, 'get_vserver_info',
2160 mock.Mock(return_value=fake.VSERVER_INFO))
2162 server = self.library.choose_share_server_compatible_with_share_group(
2163 None, share_servers, fake.SHARE_GROUP_REF)
2165 if nfs_config_supported:
2166 mock_get_nfs_config.assert_called_with(fake.EXTRA_SPEC)
2167 mock_check_extra_spec.assert_called_once_with(fake.EXTRA_SPEC)
2168 else:
2169 mock_get_nfs_config.assert_not_called()
2170 mock_check_extra_spec.assert_not_called()
2171 self.assertEqual(expected_server, server)
2173 def test_share_server_migration_check_compatibility_same_backend(
2174 self):
2175 not_compatible = fake.SERVER_MIGRATION_CHECK_NOT_COMPATIBLE
2176 self.library._have_cluster_creds = True
2177 self.mock_object(self.library, '_get_vserver',
2178 mock.Mock(return_value=(None, None)))
2180 result = self.library.share_server_migration_check_compatibility(
2181 None, self.fake_src_share_server,
2182 self.fake_src_share_server['host'],
2183 None, None, None)
2185 self.assertEqual(not_compatible, result)
2187 def _init_mocks_for_svm_dr_check_compatibility(
2188 self, src_svm_dr_supported=True, dest_svm_dr_supported=True,
2189 check_capacity_result=True, flexgroup_support=False,
2190 is_flexgroup_destination_host=False):
2191 self.mock_object(self.mock_src_client, 'is_svm_dr_supported',
2192 mock.Mock(return_value=src_svm_dr_supported))
2193 self.mock_object(self.mock_dest_client, 'is_svm_dr_supported',
2194 mock.Mock(return_value=dest_svm_dr_supported))
2195 self.mock_object(self.library, '_check_capacity_compatibility',
2196 mock.Mock(return_value=check_capacity_result))
2197 self.mock_object(self.mock_src_client, 'is_flexgroup_supported',
2198 mock.Mock(return_value=flexgroup_support))
2199 self.mock_object(data_motion, 'DataMotionSession')
2200 self.mock_object(self.library, 'is_flexgroup_destination_host',
2201 mock.Mock(return_value=is_flexgroup_destination_host))
2203 def _configure_mocks_share_server_migration_check_compatibility(
2204 self, have_cluster_creds=True,
2205 src_cluster_name=fake.CLUSTER_NAME,
2206 dest_cluster_name=fake.CLUSTER_NAME_2,
2207 pools=fake.POOLS, is_svm_dr=True, failure_scenario=False):
2208 migration_method = 'svm_dr' if is_svm_dr else 'svm_migrate'
2210 self.library._have_cluster_creds = have_cluster_creds
2211 self.mock_object(self.library, '_get_vserver',
2212 mock.Mock(return_value=(self.fake_src_vserver,
2213 self.mock_src_client)))
2214 self.mock_object(self.mock_src_client, 'get_cluster_name',
2215 mock.Mock(return_value=src_cluster_name))
2216 self.mock_object(self.client, 'get_cluster_name',
2217 mock.Mock(return_value=dest_cluster_name))
2218 self.mock_object(data_motion, 'get_client_for_backend',
2219 mock.Mock(return_value=self.mock_dest_client))
2220 self.mock_object(self.library, '_check_for_migration_support',
2221 mock.Mock(return_value=(
2222 migration_method, not failure_scenario)))
2223 self.mock_object(self.library, '_get_pools',
2224 mock.Mock(return_value=pools))
2226 def test_share_server_migration_check_compatibility_dest_with_pool(
2227 self):
2228 not_compatible = fake.SERVER_MIGRATION_CHECK_NOT_COMPATIBLE
2229 self.library._have_cluster_creds = True
2231 result = self.library.share_server_migration_check_compatibility(
2232 None, self.fake_src_share_server, fake.MANILA_HOST_NAME,
2233 None, None, None)
2235 self.assertEqual(not_compatible, result)
2237 def test_share_server_migration_check_compatibility_same_cluster(
2238 self):
2239 not_compatible = fake.SERVER_MIGRATION_CHECK_NOT_COMPATIBLE
2240 self._configure_mocks_share_server_migration_check_compatibility(
2241 src_cluster_name=fake.CLUSTER_NAME,
2242 dest_cluster_name=fake.CLUSTER_NAME,
2243 )
2245 result = self.library.share_server_migration_check_compatibility(
2246 None, self.fake_src_share_server,
2247 self.fake_dest_share_server['host'],
2248 None, None, None)
2250 self.assertEqual(not_compatible, result)
2251 self.library._get_vserver.assert_called_once_with(
2252 self.fake_src_share_server,
2253 backend_name=self.fake_src_backend_name
2254 )
2255 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2256 self.assertTrue(self.client.get_cluster_name.called)
2258 @ddt.data(
2259 {'src_svm_dr_supported': False,
2260 'dest_svm_dr_supported': False,
2261 'check_capacity_result': False,
2262 'is_flexgroup_destination_host': False,
2263 },
2264 {'src_svm_dr_supported': True,
2265 'dest_svm_dr_supported': True,
2266 'check_capacity_result': False,
2267 'is_flexgroup_destination_host': False,
2268 },
2269 {'src_svm_dr_supported': True,
2270 'dest_svm_dr_supported': True,
2271 'check_capacity_result': True,
2272 'is_flexgroup_destination_host': True,
2273 },
2274 )
2275 @ddt.unpack
2276 def test__check_compatibility_svm_dr_not_compatible(
2277 self, src_svm_dr_supported, dest_svm_dr_supported,
2278 check_capacity_result, is_flexgroup_destination_host):
2279 server_total_size = (fake.SHARE_REQ_SPEC.get('shares_size', 0) +
2280 fake.SHARE_REQ_SPEC.get('snapshots_size', 0))
2282 self._init_mocks_for_svm_dr_check_compatibility(
2283 src_svm_dr_supported=src_svm_dr_supported,
2284 dest_svm_dr_supported=dest_svm_dr_supported,
2285 check_capacity_result=check_capacity_result,
2286 flexgroup_support=is_flexgroup_destination_host,
2287 is_flexgroup_destination_host=is_flexgroup_destination_host)
2289 method, result = self.library._check_compatibility_using_svm_dr(
2290 self.mock_src_client, self.mock_dest_client,
2291 fake.SERVER_MIGRATION_REQUEST_SPEC, fake.POOLS)
2293 self.assertEqual(method, 'svm_dr')
2294 self.assertEqual(result, False)
2295 self.assertTrue(self.mock_src_client.is_svm_dr_supported.called)
2297 if (src_svm_dr_supported and dest_svm_dr_supported and
2298 is_flexgroup_destination_host):
2299 self.assertTrue(self.mock_src_client.is_flexgroup_supported.called)
2300 self.assertTrue(self.library.is_flexgroup_destination_host.called)
2302 if (check_capacity_result and not is_flexgroup_destination_host and 2302 ↛ 2304line 2302 didn't jump to line 2304 because the condition on line 2302 was never true
2303 not src_svm_dr_supported):
2304 self.assertFalse(self.mock_dest_client.is_svm_dr_supported.called)
2305 self.library._check_capacity_compatibility.assert_called_once_with(
2306 fake.POOLS, True, server_total_size)
2308 def test_share_server_migration_check_compatibility_different_sec_service(
2309 self):
2310 not_compatible = fake.SERVER_MIGRATION_CHECK_NOT_COMPATIBLE
2311 self._configure_mocks_share_server_migration_check_compatibility()
2312 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
2313 new_sec_service['id'] = 'new_sec_serv_id'
2314 new_share_network = copy.deepcopy(fake.SHARE_NETWORK)
2315 new_share_network['id'] = 'fake_share_network_id_2'
2316 new_share_network['security_services'] = [new_sec_service]
2318 result = self.library.share_server_migration_check_compatibility(
2319 None, self.fake_src_share_server,
2320 self.fake_dest_share_server['host'],
2321 fake.SHARE_NETWORK, new_share_network, None)
2323 self.assertEqual(not_compatible, result)
2324 self.library._get_vserver.assert_called_once_with(
2325 self.fake_src_share_server,
2326 backend_name=self.fake_src_backend_name
2327 )
2328 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2329 self.assertTrue(self.client.get_cluster_name.called)
2330 data_motion.get_client_for_backend.assert_called_once_with(
2331 self.fake_dest_backend_name, vserver_name=None
2332 )
2334 @ddt.data('netapp_flexvol_encryption', 'revert_to_snapshot_support')
2335 def test_share_server_migration_check_compatibility_invalid_capabilities(
2336 self, capability):
2337 not_compatible = fake.SERVER_MIGRATION_CHECK_NOT_COMPATIBLE
2338 pools_without_capability = copy.deepcopy(fake.POOLS)
2339 for pool in pools_without_capability:
2340 pool[capability] = False
2341 self._configure_mocks_share_server_migration_check_compatibility(
2342 pools=pools_without_capability
2343 )
2345 result = self.library.share_server_migration_check_compatibility(
2346 None, self.fake_src_share_server,
2347 self.fake_dest_share_server['host'],
2348 fake.SHARE_NETWORK, fake.SHARE_NETWORK,
2349 fake.SERVER_MIGRATION_REQUEST_SPEC)
2351 self.assertEqual(not_compatible, result)
2352 self.library._get_vserver.assert_called_once_with(
2353 self.fake_src_share_server,
2354 backend_name=self.fake_src_backend_name
2355 )
2356 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2357 self.assertTrue(self.client.get_cluster_name.called)
2358 data_motion.get_client_for_backend.assert_called_once_with(
2359 self.fake_dest_backend_name, vserver_name=None
2360 )
2362 @ddt.data((True, "svm_migrate"), (False, "svm_dr"))
2363 @ddt.unpack
2364 def test__check_for_migration_support(
2365 self, svm_migrate_supported, expected_migration_method):
2366 mock_dest_is_svm_migrate_supported = self.mock_object(
2367 self.mock_dest_client, 'is_svm_migrate_supported',
2368 mock.Mock(return_value=svm_migrate_supported))
2369 mock_src_is_svm_migrate_supported = self.mock_object(
2370 self.mock_src_client, 'is_svm_migrate_supported',
2371 mock.Mock(return_value=svm_migrate_supported))
2372 mock_find_matching_aggregates = self.mock_object(
2373 self.library, '_find_matching_aggregates',
2374 mock.Mock(return_value=fake.AGGREGATES))
2375 mock_get_vserver_name = self.mock_object(
2376 self.library, '_get_vserver_name',
2377 mock.Mock(return_value=fake.VSERVER1))
2378 mock_svm_migration_check_svm_mig = self.mock_object(
2379 self.library, '_check_compatibility_for_svm_migrate',
2380 mock.Mock(return_value=True))
2381 mock_svm_migration_check_svm_dr = self.mock_object(
2382 self.library, '_check_compatibility_using_svm_dr',
2383 mock.Mock(side_effect=[('svm_dr', True)]))
2385 migration_method, result = self.library._check_for_migration_support(
2386 self.mock_src_client, self.mock_dest_client, fake.SHARE_SERVER,
2387 fake.SHARE_REQ_SPEC, fake.CLUSTER_NAME, fake.POOLS)
2389 self.assertIs(True, result)
2390 self.assertEqual(migration_method, expected_migration_method)
2392 mock_dest_is_svm_migrate_supported.assert_called_once()
2393 if svm_migrate_supported:
2394 mock_src_is_svm_migrate_supported.assert_called_once()
2395 mock_find_matching_aggregates.assert_called_once()
2396 mock_get_vserver_name.assert_not_called()
2397 mock_svm_migration_check_svm_mig.assert_called_once_with(
2398 fake.CLUSTER_NAME, fake.VSERVER1, fake.SHARE_SERVER,
2399 fake.AGGREGATES, self.mock_dest_client)
2400 else:
2401 mock_svm_migration_check_svm_dr.assert_called_once_with(
2402 self.mock_src_client, self.mock_dest_client,
2403 fake.SHARE_REQ_SPEC, fake.POOLS)
2405 def test__check_for_migration_support_svm_migrate_exception(self):
2406 svm_migrate_supported = True
2407 expected_migration_method = 'svm_migrate'
2408 mock_dest_is_svm_migrate_supported = self.mock_object(
2409 self.mock_dest_client, 'is_svm_migrate_supported',
2410 mock.Mock(return_value=svm_migrate_supported))
2411 mock_src_is_svm_migrate_supported = self.mock_object(
2412 self.mock_src_client, 'is_svm_migrate_supported',
2413 mock.Mock(return_value=svm_migrate_supported))
2414 mock_find_matching_aggregates = self.mock_object(
2415 self.library, '_find_matching_aggregates',
2416 mock.Mock(return_value=fake.AGGREGATES))
2417 mock_get_vserver_name = self.mock_object(
2418 self.library, '_get_vserver_name',
2419 mock.Mock(return_value=fake.VSERVER1))
2420 mock_svm_migration_check_svm_mig = self.mock_object(
2421 self.library, '_check_compatibility_for_svm_migrate',
2422 mock.Mock(side_effect=exception.NetAppException()))
2424 migration_method, result = self.library._check_for_migration_support(
2425 self.mock_src_client, self.mock_dest_client, fake.SHARE_SERVER,
2426 fake.SHARE_REQ_SPEC, fake.CLUSTER_NAME, fake.POOLS)
2428 self.assertIs(False, result)
2429 self.assertEqual(migration_method, expected_migration_method)
2431 mock_dest_is_svm_migrate_supported.assert_called_once()
2432 mock_src_is_svm_migrate_supported.assert_called_once()
2433 mock_find_matching_aggregates.assert_called_once()
2434 mock_get_vserver_name.assert_not_called()
2435 mock_svm_migration_check_svm_mig.assert_called_once_with(
2436 fake.CLUSTER_NAME, fake.VSERVER1, fake.SHARE_SERVER,
2437 fake.AGGREGATES, self.mock_dest_client)
2439 @ddt.data(
2440 (mock.Mock, True),
2441 (exception.NetAppException, False)
2442 )
2443 @ddt.unpack
2444 def test__check_compatibility_for_svm_migrate(self, expected_exception,
2445 expected_compatibility):
2446 network_info = {
2447 'network_allocations':
2448 self.fake_src_share_server['network_allocations'],
2449 'neutron_subnet_id':
2450 self.fake_src_share_server['share_network_subnets'][0].get(
2451 'neutron_subnet_id')
2452 }
2453 self.library.configuration.netapp_restrict_lif_creation_per_ha_pair = (
2454 True
2455 )
2456 check_lif_limit = self.mock_object(
2457 self.library,
2458 '_check_data_lif_count_limit_reached_for_ha_pair',
2459 )
2460 self.mock_object(self.library._client, 'list_cluster_nodes',
2461 mock.Mock(return_value=fake.CLUSTER_NODES))
2462 self.mock_object(self.library, '_get_node_data_port',
2463 mock.Mock(return_value=fake.NODE_DATA_PORT))
2464 self.mock_object(
2465 self.library._client, 'get_ipspace_name_for_vlan_port',
2466 mock.Mock(return_value=fake.IPSPACE))
2467 self.mock_object(self.library, '_create_port_and_broadcast_domain')
2468 self.mock_object(self.mock_dest_client, 'get_ipspaces',
2469 mock.Mock(return_value=[{'uuid': fake.IPSPACE_ID}]))
2470 self.mock_object(
2471 self.mock_dest_client, 'svm_migration_start',
2472 mock.Mock(return_value=c_fake.FAKE_MIGRATION_RESPONSE_WITH_JOB))
2473 self.mock_object(self.library, '_get_job_uuid',
2474 mock.Mock(return_value=c_fake.FAKE_JOB_ID))
2475 self.mock_object(self.library, '_wait_for_operation_status',
2476 mock.Mock(side_effect=expected_exception))
2477 self.mock_object(self.mock_dest_client, 'list_cluster_nodes',
2478 mock.Mock(return_value=fake.CLUSTER_NODES))
2480 compatibility = self.library._check_compatibility_for_svm_migrate(
2481 fake.CLUSTER_NAME, fake.VSERVER1, self.fake_src_share_server,
2482 fake.AGGREGATES, self.mock_dest_client)
2484 self.assertIs(expected_compatibility, compatibility)
2485 self.mock_dest_client.svm_migration_start.assert_called_once_with(
2486 fake.CLUSTER_NAME, fake.VSERVER1, fake.AGGREGATES, check_only=True,
2487 dest_ipspace=fake.IPSPACE)
2488 self.library._get_job_uuid.assert_called_once_with(
2489 c_fake.FAKE_MIGRATION_RESPONSE_WITH_JOB)
2490 self.library._client.list_cluster_nodes.assert_called_once()
2491 self.library._get_node_data_port.assert_called_with(
2492 fake.CLUSTER_NODES[0])
2493 (self.library._client.get_ipspace_name_for_vlan_port
2494 .assert_called_once_with(
2495 fake.CLUSTER_NODES[0], fake.NODE_DATA_PORT,
2496 self.fake_src_share_server['network_allocations'][0][
2497 'segmentation_id']))
2498 self.library._create_port_and_broadcast_domain.assert_called_once_with(
2499 fake.IPSPACE, network_info)
2500 self.assertTrue(check_lif_limit.called)
2502 def test__check_compatibility_for_svm_migrate_check_failure(self):
2503 network_info = {
2504 'network_allocations':
2505 self.fake_src_share_server['network_allocations'],
2506 'neutron_subnet_id':
2507 self.fake_src_share_server['share_network_subnets'][0].get(
2508 'neutron_subnet_id')
2509 }
2511 self.mock_object(self.library._client, 'list_cluster_nodes',
2512 mock.Mock(return_value=fake.CLUSTER_NODES))
2513 self.mock_object(self.library, '_get_node_data_port',
2514 mock.Mock(return_value=fake.NODE_DATA_PORT))
2515 self.mock_object(
2516 self.library._client, 'get_ipspace_name_for_vlan_port',
2517 mock.Mock(return_value=fake.IPSPACE))
2518 self.mock_object(self.library, '_create_port_and_broadcast_domain')
2519 self.mock_object(self.mock_dest_client, 'get_ipspaces',
2520 mock.Mock(return_value=[{'uuid': fake.IPSPACE_ID}]))
2521 self.mock_object(
2522 self.mock_dest_client, 'svm_migration_start',
2523 mock.Mock(side_effect=exception.NetAppException()))
2524 self.mock_object(self.mock_dest_client, 'delete_ipspace')
2525 self.mock_object(self.mock_dest_client, 'list_cluster_nodes',
2526 mock.Mock(return_value=fake.CLUSTER_NODES))
2528 self.assertRaises(
2529 exception.NetAppException,
2530 self.library._check_compatibility_for_svm_migrate,
2531 fake.CLUSTER_NAME,
2532 fake.VSERVER1,
2533 self.fake_src_share_server,
2534 fake.AGGREGATES,
2535 self.mock_dest_client)
2537 self.library._client.list_cluster_nodes.assert_called_once()
2538 self.library._get_node_data_port.assert_called_with(
2539 fake.CLUSTER_NODES[0])
2540 (self.library._client.get_ipspace_name_for_vlan_port
2541 .assert_called_once_with(
2542 fake.CLUSTER_NODES[0], fake.NODE_DATA_PORT,
2543 self.fake_src_share_server['network_allocations'][0][
2544 'segmentation_id']))
2545 self.library._create_port_and_broadcast_domain.assert_called_once_with(
2546 fake.IPSPACE, network_info)
2547 self.mock_dest_client.delete_ipspace.assert_called_once_with(
2548 fake.IPSPACE)
2550 def test_share_server_migration_check_compatibility_compatible(self):
2551 compatible = {
2552 'compatible': True,
2553 'writable': True,
2554 'nondisruptive': False,
2555 'preserve_snapshots': True,
2556 'migration_cancel': True,
2557 'migration_get_progress': False,
2558 'share_network_id': fake.SHARE_NETWORK['id'],
2559 }
2560 self._configure_mocks_share_server_migration_check_compatibility(
2561 is_svm_dr=True)
2563 result = self.library.share_server_migration_check_compatibility(
2564 None, self.fake_src_share_server,
2565 self.fake_dest_share_server['host'],
2566 fake.SHARE_NETWORK, fake.SHARE_NETWORK,
2567 fake.SERVER_MIGRATION_REQUEST_SPEC)
2569 self.assertEqual(compatible, result)
2570 self.library._get_vserver.assert_called_once_with(
2571 self.fake_src_share_server,
2572 backend_name=self.fake_src_backend_name
2573 )
2574 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2575 self.assertTrue(self.client.get_cluster_name.called)
2576 data_motion.get_client_for_backend.assert_called_once_with(
2577 self.fake_dest_backend_name, vserver_name=None
2578 )
2580 def test__get_job_uuid(self):
2581 self.assertEqual(
2582 self.library._get_job_uuid(
2583 c_fake.FAKE_MIGRATION_RESPONSE_WITH_JOB),
2584 c_fake.FAKE_JOB_ID
2585 )
2587 def test__wait_for_operation_status(self):
2588 job_starting_state = copy.copy(c_fake.FAKE_JOB_SUCCESS_STATE)
2589 job_starting_state['state'] = 'starting'
2590 returned_jobs = [
2591 job_starting_state,
2592 c_fake.FAKE_JOB_SUCCESS_STATE,
2593 ]
2595 self.mock_object(self.mock_dest_client, 'get_job',
2596 mock.Mock(side_effect=returned_jobs))
2598 self.library._wait_for_operation_status(
2599 c_fake.FAKE_JOB_ID, self.mock_dest_client.get_job
2600 )
2602 self.assertEqual(
2603 self.mock_dest_client.get_job.call_count, len(returned_jobs))
2605 def test__wait_for_operation_status_error(self):
2606 starting_job = copy.copy(c_fake.FAKE_JOB_SUCCESS_STATE)
2607 starting_job['state'] = 'starting'
2608 errored_job = copy.copy(c_fake.FAKE_JOB_SUCCESS_STATE)
2609 errored_job['state'] = constants.STATUS_ERROR
2610 returned_jobs = [starting_job, errored_job]
2612 self.mock_object(self.mock_dest_client, 'get_job',
2613 mock.Mock(side_effect=returned_jobs))
2615 self.assertRaises(
2616 exception.NetAppException,
2617 self.library._wait_for_operation_status,
2618 c_fake.FAKE_JOB_ID,
2619 self.mock_dest_client.get_job
2620 )
2622 @ddt.data(
2623 {'src_supports_svm_migrate': True, 'dest_supports_svm_migrate': True},
2624 {'src_supports_svm_migrate': True, 'dest_supports_svm_migrate': False},
2625 {'src_supports_svm_migrate': False, 'dest_supports_svm_migrate': True},
2626 {'src_supports_svm_migrate': False, 'dest_supports_svm_migrate': False}
2627 )
2628 @ddt.unpack
2629 def test_share_server_migration_start(self, src_supports_svm_migrate,
2630 dest_supports_svm_migrate):
2631 fake_migration_data = {'fake_migration_key': 'fake_migration_value'}
2632 self.mock_object(
2633 self.library, '_get_vserver',
2634 mock.Mock(
2635 side_effect=[(self.fake_src_vserver, self.mock_src_client)]))
2636 self.mock_object(data_motion, 'get_client_for_backend',
2637 mock.Mock(return_value=self.mock_dest_client))
2638 mock_start_using_svm_migrate = self.mock_object(
2639 self.library, '_migration_start_using_svm_migrate',
2640 mock.Mock(return_value=fake_migration_data))
2641 mock_start_using_svm_dr = self.mock_object(
2642 self.library, '_migration_start_using_svm_dr',
2643 mock.Mock(return_value=fake_migration_data))
2645 self.mock_src_client.is_svm_migrate_supported.return_value = (
2646 src_supports_svm_migrate)
2647 self.mock_dest_client.is_svm_migrate_supported.return_value = (
2648 dest_supports_svm_migrate)
2649 src_and_dest_support_svm_migrate = all(
2650 [src_supports_svm_migrate, dest_supports_svm_migrate])
2652 result = self.library.share_server_migration_start(
2653 None, self.fake_src_share_server, self.fake_dest_share_server,
2654 [fake.SHARE_INSTANCE], [])
2656 self.library._get_vserver.assert_called_once_with(
2657 share_server=self.fake_src_share_server,
2658 backend_name=self.fake_src_backend_name)
2659 if src_and_dest_support_svm_migrate:
2660 mock_start_using_svm_migrate.assert_called_once_with(
2661 None, self.fake_src_share_server, self.fake_dest_share_server,
2662 self.mock_src_client, self.mock_dest_client)
2663 else:
2664 mock_start_using_svm_dr.assert_called_once_with(
2665 self.fake_src_share_server, self.fake_dest_share_server
2666 )
2667 self.assertEqual(result, fake_migration_data)
2669 @ddt.data({'vserver_peered': True, 'src_cluster': fake.CLUSTER_NAME},
2670 {'vserver_peered': False, 'src_cluster': fake.CLUSTER_NAME},
2671 {'vserver_peered': False, 'src_cluster': fake.CLUSTER_NAME_2})
2672 @ddt.unpack
2673 def test__migration_start_using_svm_dr(self, vserver_peered, src_cluster):
2674 dest_cluster = fake.CLUSTER_NAME
2675 dm_session_mock = mock.Mock()
2676 self.mock_object(self.library, '_get_vserver',
2677 mock.Mock(side_effect=[
2678 (self.fake_src_vserver, self.mock_src_client),
2679 (self.fake_dest_vserver,
2680 self.mock_dest_client)]))
2681 self.mock_object(self.mock_src_client, 'get_cluster_name',
2682 mock.Mock(return_value=src_cluster))
2683 self.mock_object(self.mock_dest_client, 'get_cluster_name',
2684 mock.Mock(return_value=dest_cluster))
2685 self.mock_object(self.library, '_get_vserver_peers',
2686 mock.Mock(return_value=vserver_peered))
2687 self.mock_object(data_motion, "DataMotionSession",
2688 mock.Mock(return_value=dm_session_mock))
2690 self.library._migration_start_using_svm_dr(
2691 self.fake_src_share_server, self.fake_dest_share_server)
2693 self.library._get_vserver.assert_has_calls([
2694 mock.call(share_server=self.fake_src_share_server,
2695 backend_name=self.fake_src_backend_name),
2696 mock.call(share_server=self.fake_dest_share_server,
2697 backend_name=self.fake_dest_backend_name)])
2698 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2699 self.assertTrue(self.mock_dest_client.get_cluster_name.called)
2700 self.library._get_vserver_peers.assert_called_once_with(
2701 self.fake_dest_vserver, self.fake_src_vserver
2702 )
2703 mock_vserver_peer = self.mock_dest_client.create_vserver_peer
2704 if vserver_peered:
2705 self.assertFalse(mock_vserver_peer.called)
2706 else:
2707 mock_vserver_peer.assert_called_once_with(
2708 self.fake_dest_vserver, self.fake_src_vserver,
2709 peer_cluster_name=src_cluster
2710 )
2711 accept_peer_mock = self.mock_src_client.accept_vserver_peer
2712 if src_cluster != dest_cluster:
2713 accept_peer_mock.assert_called_once_with(
2714 self.fake_src_vserver, self.fake_dest_vserver
2715 )
2716 else:
2717 self.assertFalse(accept_peer_mock.called)
2718 dm_session_mock.create_snapmirror_svm.assert_called_once_with(
2719 self.fake_src_share_server, self.fake_dest_share_server
2720 )
2722 def test_share_server_migration_start_snapmirror_start_failure(self):
2723 self.mock_object(self.library, '_get_vserver',
2724 mock.Mock(side_effect=[
2725 (self.fake_src_vserver, self.mock_src_client),
2726 (self.fake_dest_vserver,
2727 self.mock_dest_client)]))
2728 self.mock_object(self.mock_src_client, 'get_cluster_name')
2729 self.mock_object(self.mock_dest_client, 'get_cluster_name')
2730 self.mock_object(self.library, '_get_vserver_peers',
2731 mock.Mock(return_value=True))
2732 dm_session_mock = mock.Mock()
2733 self.mock_object(data_motion, "DataMotionSession",
2734 mock.Mock(return_value=dm_session_mock))
2735 create_snapmirror_mock = self.mock_object(
2736 dm_session_mock, 'create_snapmirror_svm',
2737 mock.Mock(
2738 side_effect=exception.NetAppException(message='fake')))
2740 self.assertRaises(exception.NetAppException,
2741 self.library._migration_start_using_svm_dr,
2742 self.fake_src_share_server,
2743 self.fake_dest_share_server)
2745 self.library._get_vserver.assert_has_calls([
2746 mock.call(share_server=self.fake_src_share_server,
2747 backend_name=self.fake_src_backend_name),
2748 mock.call(share_server=self.fake_dest_share_server,
2749 backend_name=self.fake_dest_backend_name)])
2750 self.assertTrue(self.mock_src_client.get_cluster_name.called)
2751 self.assertTrue(self.mock_dest_client.get_cluster_name.called)
2752 self.library._get_vserver_peers.assert_called_once_with(
2753 self.fake_dest_vserver, self.fake_src_vserver
2754 )
2755 self.assertFalse(self.mock_dest_client.create_vserver_peer.called)
2757 create_snapmirror_mock.assert_called_once_with(
2758 self.fake_src_share_server, self.fake_dest_share_server
2759 )
2760 dm_session_mock.cancel_snapmirror_svm.assert_called_once_with(
2761 self.fake_src_share_server, self.fake_dest_share_server
2762 )
2764 @ddt.data(
2765 {'network_change_during_migration': True},
2766 {'network_change_during_migration': False})
2767 @ddt.unpack
2768 def test__migration_start_using_svm_migrate(
2769 self, network_change_during_migration):
2771 self.fake_src_share_server['share_network_subnet_id'] = 'fake_sns_id'
2772 self.fake_dest_share_server['share_network_subnet_id'] = 'fake_sns_id'
2773 node_name = fake.CLUSTER_NODES[0]
2774 expected_server_info = {
2775 'backend_details': {
2776 'migration_operation_id': c_fake.FAKE_MIGRATION_POST_ID
2777 }
2778 }
2780 if not network_change_during_migration:
2781 self.fake_dest_share_server['network_allocations'] = None
2782 server_to_get_network_info = (
2783 self.fake_dest_share_server
2784 if network_change_during_migration else self.fake_src_share_server)
2786 if network_change_during_migration:
2787 self.fake_dest_share_server['share_network_subnet_id'] = (
2788 'different_sns_id')
2790 segmentation_id = (
2791 server_to_get_network_info['network_allocations'][0][
2792 'segmentation_id'])
2794 network_info = {
2795 'network_allocations':
2796 server_to_get_network_info['network_allocations'],
2797 'neutron_subnet_id':
2798 server_to_get_network_info['share_network_subnets'][0].get(
2799 'neutron_subnet_id')
2800 }
2802 mock_list_cluster_nodes = self.mock_object(
2803 self.library._client, 'list_cluster_nodes',
2804 mock.Mock(return_value=fake.CLUSTER_NODES))
2805 mock_get_data_port = self.mock_object(
2806 self.library, '_get_node_data_port',
2807 mock.Mock(return_value=fake.NODE_DATA_PORT))
2808 mock_get_ipspace = self.mock_object(
2809 self.library._client, 'get_ipspace_name_for_vlan_port',
2810 mock.Mock(return_value=fake.IPSPACE))
2811 mock_create_port = self.mock_object(
2812 self.library, '_create_port_and_broadcast_domain')
2813 mock_get_cluster_name = self.mock_object(
2814 self.mock_src_client, 'get_cluster_name',
2815 mock.Mock(return_value=fake.CLUSTER_NAME))
2816 mock_get_aggregates = self.mock_object(
2817 self.library, '_find_matching_aggregates',
2818 mock.Mock(return_value=fake.AGGREGATES))
2819 mock_svm_migration_start = self.mock_object(
2820 self.mock_dest_client, 'svm_migration_start',
2821 mock.Mock(return_value=c_fake.FAKE_MIGRATION_RESPONSE_WITH_JOB))
2822 mock_get_job = self.mock_object(
2823 self.mock_dest_client, 'get_job',
2824 mock.Mock(return_value=c_fake.FAKE_JOB_SUCCESS_STATE))
2826 server_info = self.library._migration_start_using_svm_migrate(
2827 None, self.fake_src_share_server, self.fake_dest_share_server,
2828 self.mock_src_client, self.mock_dest_client)
2830 self.assertTrue(mock_list_cluster_nodes.called)
2831 mock_get_data_port.assert_called_once_with(node_name)
2832 mock_get_ipspace.assert_called_once_with(
2833 node_name, fake.NODE_DATA_PORT, segmentation_id)
2834 mock_create_port.assert_called_once_with(
2835 fake.IPSPACE, network_info)
2836 self.assertTrue(mock_get_cluster_name.called)
2837 mock_svm_migration_start.assert_called_once_with(
2838 fake.CLUSTER_NAME, self.fake_src_vserver, fake.AGGREGATES,
2839 dest_ipspace=fake.IPSPACE)
2840 self.assertTrue(mock_get_aggregates.called)
2841 self.assertEqual(expected_server_info, server_info)
2842 mock_get_job.assert_called_once_with(c_fake.FAKE_JOB_ID)
2844 def test__migration_start_using_svm_migrate_exception(self):
2846 self.fake_src_share_server['share_network_subnet_id'] = 'fake_sns_id'
2847 self.fake_dest_share_server['share_network_subnet_id'] = 'fake_sns_id'
2848 node_name = fake.CLUSTER_NODES[0]
2850 server_to_get_network_info = self.fake_dest_share_server
2852 segmentation_id = (
2853 server_to_get_network_info['network_allocations'][0][
2854 'segmentation_id'])
2856 network_info = {
2857 'network_allocations':
2858 server_to_get_network_info['network_allocations'],
2859 'neutron_subnet_id':
2860 server_to_get_network_info['share_network_subnets'][0].get(
2861 'neutron_subnet_id')
2862 }
2864 mock_list_cluster_nodes = self.mock_object(
2865 self.library._client, 'list_cluster_nodes',
2866 mock.Mock(return_value=fake.CLUSTER_NODES))
2867 mock_get_data_port = self.mock_object(
2868 self.library, '_get_node_data_port',
2869 mock.Mock(return_value=fake.NODE_DATA_PORT))
2870 mock_get_ipspace = self.mock_object(
2871 self.library._client, 'get_ipspace_name_for_vlan_port',
2872 mock.Mock(return_value=fake.IPSPACE))
2873 mock_create_port = self.mock_object(
2874 self.library, '_create_port_and_broadcast_domain')
2875 mock_get_vserver_name = self.mock_object(
2876 self.library, '_get_vserver_name',
2877 mock.Mock(return_value=fake.VSERVER1))
2878 mock_get_cluster_name = self.mock_object(
2879 self.mock_src_client, 'get_cluster_name',
2880 mock.Mock(return_value=fake.CLUSTER_NAME))
2881 mock_get_aggregates = self.mock_object(
2882 self.library, '_find_matching_aggregates',
2883 mock.Mock(return_value=fake.AGGREGATES))
2884 mock_svm_migration_start = self.mock_object(
2885 self.mock_dest_client, 'svm_migration_start',
2886 mock.Mock(side_effect=exception.NetAppException()))
2887 mock_delete_ipspace = self.mock_object(
2888 self.mock_dest_client, 'delete_ipspace')
2890 self.assertRaises(
2891 exception.NetAppException,
2892 self.library._migration_start_using_svm_migrate,
2893 None,
2894 self.fake_src_share_server, self.fake_dest_share_server,
2895 self.mock_src_client, self.mock_dest_client)
2897 self.assertTrue(mock_list_cluster_nodes.called)
2898 mock_get_data_port.assert_called_once_with(node_name)
2899 mock_get_ipspace.assert_called_once_with(
2900 node_name, fake.NODE_DATA_PORT, segmentation_id)
2901 mock_create_port.assert_called_once_with(
2902 fake.IPSPACE, network_info)
2903 mock_get_vserver_name.assert_not_called()
2904 self.assertTrue(mock_get_cluster_name.called)
2905 mock_svm_migration_start.assert_called_once_with(
2906 fake.CLUSTER_NAME, self.fake_src_vserver, fake.AGGREGATES,
2907 dest_ipspace=fake.IPSPACE)
2908 self.assertTrue(mock_get_aggregates.called)
2909 mock_delete_ipspace.assert_called_once_with(fake.IPSPACE)
2911 def test__get_snapmirror_svm(self):
2912 dm_session_mock = mock.Mock()
2913 self.mock_object(data_motion, "DataMotionSession",
2914 mock.Mock(return_value=dm_session_mock))
2915 fake_snapmirrors = ['mirror1']
2916 self.mock_object(dm_session_mock, 'get_snapmirrors_svm',
2917 mock.Mock(return_value=fake_snapmirrors))
2919 result = self.library._get_snapmirror_svm(
2920 self.fake_src_share_server, self.fake_dest_share_server)
2922 dm_session_mock.get_snapmirrors_svm.assert_called_once_with(
2923 self.fake_src_share_server, self.fake_dest_share_server
2924 )
2925 self.assertEqual(fake_snapmirrors, result)
2927 def test__get_snapmirror_svm_fail_to_get_snapmirrors(self):
2928 dm_session_mock = mock.Mock()
2929 self.mock_object(data_motion, "DataMotionSession",
2930 mock.Mock(return_value=dm_session_mock))
2931 self.mock_object(dm_session_mock, 'get_snapmirrors_svm',
2932 mock.Mock(
2933 side_effect=netapp_api.NaApiError(code=0)))
2935 self.assertRaises(exception.NetAppException,
2936 self.library._get_snapmirror_svm,
2937 self.fake_src_share_server,
2938 self.fake_dest_share_server)
2940 dm_session_mock.get_snapmirrors_svm.assert_called_once_with(
2941 self.fake_src_share_server, self.fake_dest_share_server
2942 )
2944 def test_share_server_migration_continue_svm_dr_no_snapmirror(self):
2945 self.mock_object(self.library, '_get_snapmirror_svm',
2946 mock.Mock(return_value=[]))
2948 self.assertRaises(exception.NetAppException,
2949 self.library._share_server_migration_continue_svm_dr,
2950 self.fake_src_share_server,
2951 self.fake_dest_share_server)
2953 self.library._get_snapmirror_svm.assert_called_once_with(
2954 self.fake_src_share_server, self.fake_dest_share_server
2955 )
2957 @ddt.data({'mirror_state': 'snapmirrored', 'status': 'idle'},
2958 {'mirror_state': 'uninitialized', 'status': 'transferring'},
2959 {'mirror_state': 'snapmirrored', 'status': 'quiescing'}, )
2960 @ddt.unpack
2961 def test_share_server_migration_continue_svm_dr(self, mirror_state,
2962 status):
2963 fake_snapmirror = {
2964 'mirror-state': mirror_state,
2965 'relationship-status': status,
2966 }
2967 self.mock_object(self.library, '_get_snapmirror_svm',
2968 mock.Mock(return_value=[fake_snapmirror]))
2969 expected = mirror_state == 'snapmirrored' and status == 'idle'
2971 result = self.library._share_server_migration_continue_svm_dr(
2972 self.fake_src_share_server,
2973 self.fake_dest_share_server
2974 )
2976 self.assertEqual(expected, result)
2977 self.library._get_snapmirror_svm.assert_called_once_with(
2978 self.fake_src_share_server, self.fake_dest_share_server
2979 )
2981 @ddt.data(
2982 ('ready_for_cutover', True),
2983 ('transferring', False)
2984 )
2985 @ddt.unpack
2986 def test_share_server_migration_continue_svm_migrate(
2987 self, job_state, first_phase_completed):
2988 c_fake.FAKE_MIGRATION_JOB_SUCCESS.update({"state": job_state})
2990 self.mock_object(data_motion, 'get_client_for_host',
2991 mock.Mock(return_value=self.mock_dest_client))
2992 self.mock_object(
2993 self.mock_dest_client, 'svm_migration_get',
2994 mock.Mock(return_value=c_fake.FAKE_MIGRATION_JOB_SUCCESS))
2996 result = self.library._share_server_migration_continue_svm_migrate(
2997 self.fake_dest_share_server, c_fake.FAKE_MIGRATION_POST_ID)
2999 self.assertEqual(first_phase_completed, result)
3000 data_motion.get_client_for_host.assert_called_once_with(
3001 self.fake_dest_share_server['host'])
3002 self.mock_dest_client.svm_migration_get.assert_called_once_with(
3003 c_fake.FAKE_MIGRATION_POST_ID)
3005 def test_share_server_migration_continue_svm_migrate_exception(self):
3007 self.mock_object(data_motion, 'get_client_for_host',
3008 mock.Mock(return_value=self.mock_dest_client))
3009 self.mock_object(self.mock_dest_client, 'svm_migration_get',
3010 mock.Mock(side_effect=netapp_api.NaApiError()))
3012 self.assertRaises(
3013 exception.NetAppException,
3014 self.library._share_server_migration_continue_svm_migrate,
3015 self.fake_dest_share_server, c_fake.FAKE_MIGRATION_POST_ID)
3017 data_motion.get_client_for_host.assert_called_once_with(
3018 self.fake_dest_share_server['host'])
3019 self.mock_dest_client.svm_migration_get.assert_called_once_with(
3020 c_fake.FAKE_MIGRATION_POST_ID)
3022 @ddt.data(None, 'fake_migration_id')
3023 def test_share_server_migration_continue(self, migration_id):
3024 expected_result = True
3025 self.mock_object(
3026 self.library, '_get_share_server_migration_id',
3027 mock.Mock(return_value=migration_id))
3028 self.mock_object(
3029 self.library, '_share_server_migration_continue_svm_migrate',
3030 mock.Mock(return_value=expected_result))
3031 self.mock_object(
3032 self.library, '_share_server_migration_continue_svm_dr',
3033 mock.Mock(return_value=expected_result))
3035 result = self.library.share_server_migration_continue(
3036 None, self.fake_src_share_server, self.fake_dest_share_server,
3037 [], []
3038 )
3040 self.assertEqual(expected_result, result)
3042 def test__setup_networking_for_destination_vserver(self):
3043 self.mock_object(self.mock_dest_client, 'get_vserver_ipspace',
3044 mock.Mock(return_value=fake.IPSPACE))
3045 self.mock_object(self.library, '_setup_network_for_vserver')
3047 self.library._setup_networking_for_destination_vserver(
3048 self.mock_dest_client, self.fake_vserver,
3049 fake.NETWORK_INFO_LIST)
3051 self.mock_dest_client.get_vserver_ipspace.assert_called_once_with(
3052 self.fake_vserver)
3053 self.library._setup_network_for_vserver.assert_called_once_with(
3054 self.fake_vserver, self.mock_dest_client, fake.NETWORK_INFO_LIST,
3055 fake.IPSPACE, enable_nfs=False, security_services=None)
3057 def test__migration_complete_svm_dr(self):
3058 dm_session_mock = mock.Mock()
3059 self.mock_object(self.library, '_get_vserver',
3060 mock.Mock(return_value=(self.fake_dest_vserver,
3061 self.mock_dest_client)))
3062 self.mock_object(data_motion, "DataMotionSession",
3063 mock.Mock(return_value=dm_session_mock))
3064 self.mock_object(
3065 self.library, '_setup_networking_for_destination_vserver')
3067 self.library._share_server_migration_complete_svm_dr(
3068 self.fake_src_share_server, self.fake_dest_share_server,
3069 self.fake_src_vserver, self.mock_src_client,
3070 [fake.SHARE_INSTANCE], fake.NETWORK_INFO_LIST
3071 )
3073 self.library._get_vserver.assert_called_once_with(
3074 share_server=self.fake_dest_share_server,
3075 backend_name=self.fake_dest_backend_name
3076 )
3077 dm_session_mock.update_snapmirror_svm.assert_called_once_with(
3078 self.fake_src_share_server, self.fake_dest_share_server
3079 )
3080 quiesce_break_mock = dm_session_mock.quiesce_and_break_snapmirror_svm
3081 quiesce_break_mock.assert_called_once_with(
3082 self.fake_src_share_server, self.fake_dest_share_server
3083 )
3084 dm_session_mock.wait_for_vserver_state.assert_called_once_with(
3085 self.fake_dest_vserver, self.mock_dest_client, subtype='default',
3086 state='running', operational_state='stopped',
3087 timeout=(self.library.configuration.
3088 netapp_server_migration_state_change_timeout)
3089 )
3090 self.mock_src_client.stop_vserver.assert_called_once_with(
3091 self.fake_src_vserver
3092 )
3093 (self.library._setup_networking_for_destination_vserver
3094 .assert_called_once_with(
3095 self.mock_dest_client, self.fake_dest_vserver,
3096 fake.NETWORK_INFO_LIST))
3097 self.mock_dest_client.start_vserver.assert_called_once_with(
3098 self.fake_dest_vserver
3099 )
3100 dm_session_mock.delete_snapmirror_svm.assert_called_once_with(
3101 self.fake_src_share_server, self.fake_dest_share_server
3102 )
3104 @ddt.data(
3105 {'is_svm_dr': True, 'network_change': True},
3106 {'is_svm_dr': False, 'network_change': True},
3107 {'is_svm_dr': False, 'network_change': False},
3108 )
3109 @ddt.unpack
3110 def test_share_server_migration_complete(self, is_svm_dr, network_change):
3111 current_interfaces = ['interface_1', 'interface_2']
3112 self.mock_object(self.library, '_get_vserver',
3113 mock.Mock(side_effect=[
3114 (self.fake_src_vserver, self.mock_src_client),
3115 (self.fake_dest_vserver, self.mock_dest_client)]))
3116 mock_complete_svm_migrate = self.mock_object(
3117 self.library, '_share_server_migration_complete_svm_migrate')
3118 mock_complete_svm_dr = self.mock_object(
3119 self.library, '_share_server_migration_complete_svm_dr')
3120 fake_share_name = self.library._get_backend_share_name(
3121 fake.SHARE_INSTANCE['id'])
3122 fake_volume = copy.deepcopy(fake.CLIENT_GET_VOLUME_RESPONSE)
3123 self.mock_object(self.mock_dest_client, 'get_volume',
3124 mock.Mock(return_value=fake_volume))
3125 self.mock_object(self.library, '_create_export',
3126 mock.Mock(return_value=fake.NFS_EXPORTS))
3127 self.mock_object(self.library, '_delete_share')
3128 mock_update_share_attrs = self.mock_object(
3129 self.library, '_update_share_attributes_after_server_migration')
3130 self.mock_object(data_motion, 'get_client_for_host',
3131 mock.Mock(return_value=self.mock_dest_client))
3132 self.mock_object(self.mock_dest_client, 'list_network_interfaces',
3133 mock.Mock(return_value=current_interfaces))
3134 self.mock_object(self.mock_dest_client, 'delete_network_interface')
3135 self.mock_object(self.library,
3136 '_setup_networking_for_destination_vserver')
3138 sns_id = 'fake_sns_id'
3139 new_sns_id = 'fake_sns_id_2'
3140 self.fake_src_share_server['share_network_subnet_id'] = sns_id
3141 self.fake_dest_share_server['share_network_subnet_id'] = (
3142 sns_id if not network_change else new_sns_id)
3143 share_instances = [fake.SHARE_INSTANCE]
3144 migration_id = 'fake_migration_id'
3145 share_host = fake.SHARE_INSTANCE['host']
3146 self.fake_src_share_server['backend_details']['ports'] = []
3148 if not is_svm_dr:
3149 self.fake_dest_share_server['backend_details'][
3150 'migration_operation_id'] = (
3151 migration_id)
3152 share_host = share_host.replace(
3153 share_host.split('#')[1], fake_volume['aggregate'])
3154 should_recreate_export = is_svm_dr or network_change
3155 share_server_to_get_vserver_name = (
3156 self.fake_dest_share_server
3157 if is_svm_dr else self.fake_src_share_server)
3159 result = self.library.share_server_migration_complete(
3160 None,
3161 self.fake_src_share_server,
3162 self.fake_dest_share_server,
3163 share_instances, [],
3164 fake.NETWORK_INFO_LIST
3165 )
3167 expected_share_updates = {
3168 fake.SHARE_INSTANCE['id']: {
3169 'pool_name': fake_volume['aggregate']
3170 }
3171 }
3172 expected_share_updates[fake.SHARE_INSTANCE['id']].update(
3173 {'export_locations': fake.NFS_EXPORTS})
3174 expected_backend_details = (
3175 {} if is_svm_dr else self.fake_src_share_server['backend_details'])
3176 expected_result = {
3177 'share_updates': expected_share_updates,
3178 'server_backend_details': expected_backend_details
3179 }
3181 self.assertEqual(expected_result, result)
3182 self.library._get_vserver.assert_has_calls([
3183 mock.call(share_server=self.fake_src_share_server,
3184 backend_name=self.fake_src_backend_name),
3185 mock.call(share_server=share_server_to_get_vserver_name,
3186 backend_name=self.fake_dest_backend_name)])
3187 if is_svm_dr:
3188 mock_complete_svm_dr.assert_called_once_with(
3189 self.fake_src_share_server, self.fake_dest_share_server,
3190 self.fake_src_vserver, self.mock_src_client,
3191 share_instances, fake.NETWORK_INFO_LIST
3192 )
3193 self.library._delete_share.assert_called_once_with(
3194 fake.SHARE_INSTANCE, self.fake_src_vserver,
3195 self.mock_src_client, remove_export=True)
3196 mock_update_share_attrs.assert_called_once_with(
3197 fake.SHARE_INSTANCE, self.mock_src_client,
3198 fake_volume['aggregate'], self.mock_dest_client)
3199 else:
3200 mock_complete_svm_migrate.assert_called_once_with(
3201 migration_id, self.fake_dest_share_server)
3202 self.mock_dest_client.list_network_interfaces.assert_called_once()
3203 data_motion.get_client_for_host.assert_has_calls([
3204 mock.call(self.fake_dest_share_server['host']),
3205 mock.call(self.fake_src_share_server['host']),
3206 ])
3208 self.mock_dest_client.delete_network_interface.assert_has_calls(
3209 [mock.call(self.fake_src_vserver, interface_name)
3210 for interface_name in current_interfaces])
3211 (self.library._setup_networking_for_destination_vserver.
3212 assert_called_once_with(self.mock_dest_client,
3213 self.fake_src_vserver,
3214 fake.NETWORK_INFO_LIST))
3215 if should_recreate_export:
3216 create_export_calls = [
3217 mock.call(
3218 instance, self.fake_dest_share_server,
3219 self.fake_dest_vserver, self.mock_dest_client,
3220 clear_current_export_policy=False,
3221 ensure_share_already_exists=True,
3222 share_host=share_host)
3223 for instance in share_instances
3224 ]
3225 self.library._create_export.assert_has_calls(create_export_calls)
3226 self.mock_dest_client.get_volume.assert_called_once_with(
3227 fake_share_name)
3229 def test_share_server_migration_complete_failure_breaking(self):
3230 dm_session_mock = mock.Mock()
3231 self.mock_object(data_motion, "DataMotionSession",
3232 mock.Mock(return_value=dm_session_mock))
3233 self.mock_object(
3234 self.library, '_get_vserver',
3235 mock.Mock(return_value=(self.fake_dest_vserver,
3236 self.mock_dest_client)))
3237 self.mock_object(dm_session_mock, 'quiesce_and_break_snapmirror_svm',
3238 mock.Mock(side_effect=exception.NetAppException))
3239 self.mock_object(self.library, '_delete_share')
3241 self.assertRaises(exception.NetAppException,
3242 self.library._share_server_migration_complete_svm_dr,
3243 self.fake_src_share_server,
3244 self.fake_dest_share_server,
3245 self.fake_src_vserver,
3246 self.mock_src_client, [fake.SHARE_INSTANCE],
3247 [fake.NETWORK_INFO])
3249 dm_session_mock.update_snapmirror_svm.assert_called_once_with(
3250 self.fake_src_share_server, self.fake_dest_share_server
3251 )
3252 self.library._get_vserver.assert_called_once_with(
3253 share_server=self.fake_dest_share_server,
3254 backend_name=self.fake_dest_backend_name)
3255 quiesce_break_mock = dm_session_mock.quiesce_and_break_snapmirror_svm
3256 quiesce_break_mock.assert_called_once_with(
3257 self.fake_src_share_server, self.fake_dest_share_server
3258 )
3259 self.mock_src_client.start_vserver.assert_called_once_with(
3260 self.fake_src_vserver
3261 )
3262 dm_session_mock.cancel_snapmirror_svm.assert_called_once_with(
3263 self.fake_src_share_server, self.fake_dest_share_server
3264 )
3265 self.library._delete_share.assert_called_once_with(
3266 fake.SHARE_INSTANCE, self.fake_dest_vserver, self.mock_dest_client,
3267 remove_export=False)
3269 def test_share_server_migration_complete_failure_get_new_volume(self):
3270 dm_session_mock = mock.Mock()
3271 fake_share_name = self.library._get_backend_share_name(
3272 fake.SHARE_INSTANCE['id'])
3273 self.mock_object(data_motion, "DataMotionSession",
3274 mock.Mock(return_value=dm_session_mock))
3275 self.mock_object(self.library, '_get_vserver',
3276 mock.Mock(side_effect=[
3277 (self.fake_src_vserver, self.mock_src_client),
3278 (self.fake_dest_vserver, self.mock_dest_client)]))
3279 self.mock_object(self.library,
3280 '_share_server_migration_complete_svm_dr')
3281 self.mock_object(self.library, '_get_share_server_migration_id',
3282 mock.Mock(return_value=None))
3283 self.mock_object(self.mock_dest_client, 'get_volume',
3284 mock.Mock(side_effect=exception.NetAppException))
3286 self.assertRaises(exception.NetAppException,
3287 self.library.share_server_migration_complete,
3288 None,
3289 self.fake_src_share_server,
3290 self.fake_dest_share_server,
3291 [fake.SHARE_INSTANCE], [],
3292 fake.NETWORK_INFO_LIST)
3294 self.library._get_vserver.assert_has_calls([
3295 mock.call(share_server=self.fake_src_share_server,
3296 backend_name=self.fake_src_backend_name),
3297 mock.call(share_server=self.fake_dest_share_server,
3298 backend_name=self.fake_dest_backend_name)])
3299 self.mock_dest_client.get_volume.assert_called_once_with(
3300 fake_share_name)
3302 def test__share_server_migration_complete_svm_migrate(self):
3303 completion_status = na_utils.MIGRATION_STATE_MIGRATE_COMPLETE
3304 migration_id = 'fake_migration_id'
3305 fake_complete_job_uuid = 'fake_uuid'
3306 fake_complete_job = {
3307 'job': {
3308 'state': 'cutover_triggered',
3309 'uuid': fake_complete_job_uuid
3310 }
3311 }
3312 self.mock_object(data_motion, 'get_client_for_host',
3313 mock.Mock(return_value=self.mock_dest_client))
3314 self.mock_object(self.mock_dest_client, 'svm_migrate_complete',
3315 mock.Mock(return_value=fake_complete_job))
3316 self.mock_object(self.library, '_get_job_uuid',
3317 mock.Mock(return_value=fake_complete_job_uuid))
3318 self.mock_object(self.library, '_wait_for_operation_status')
3320 self.library._share_server_migration_complete_svm_migrate(
3321 migration_id, self.fake_dest_share_server)
3323 data_motion.get_client_for_host.assert_called_once_with(
3324 self.fake_dest_share_server['host'])
3325 self.mock_dest_client.svm_migrate_complete.assert_called_once_with(
3326 migration_id)
3327 self.library._get_job_uuid.assert_called_once_with(fake_complete_job)
3328 self.library._wait_for_operation_status.assert_has_calls(
3329 [mock.call(fake_complete_job_uuid, self.mock_dest_client.get_job),
3330 mock.call(migration_id, self.mock_dest_client.svm_migration_get,
3331 desired_status=completion_status)
3332 ]
3333 )
3335 def test__share_server_migration_complete_svm_migrate_failed_to_complete(
3336 self):
3337 migration_id = 'fake_migration_id'
3339 self.mock_object(data_motion, 'get_client_for_host',
3340 mock.Mock(return_value=self.mock_dest_client))
3341 self.mock_object(self.mock_dest_client, 'svm_migrate_complete',
3342 mock.Mock(side_effect=exception.NetAppException()))
3344 self.assertRaises(
3345 exception.NetAppException,
3346 self.library._share_server_migration_complete_svm_migrate,
3347 migration_id, self.fake_dest_share_server)
3349 data_motion.get_client_for_host.assert_called_once_with(
3350 self.fake_dest_share_server['host'])
3351 self.mock_dest_client.svm_migrate_complete.assert_called_once_with(
3352 migration_id)
3354 @ddt.data([], ['fake_snapmirror'])
3355 def test_share_server_migration_cancel_svm_dr(self, snapmirrors):
3356 dm_session_mock = mock.Mock()
3357 self.mock_object(data_motion, "DataMotionSession",
3358 mock.Mock(return_value=dm_session_mock))
3359 self.mock_object(self.library, '_get_vserver',
3360 mock.Mock(return_value=(self.fake_dest_vserver,
3361 self.mock_dest_client)))
3362 self.mock_object(self.library, '_get_snapmirror_svm',
3363 mock.Mock(return_value=snapmirrors))
3364 self.mock_object(self.library, '_delete_share')
3366 self.library._migration_cancel_using_svm_dr(
3367 self.fake_src_share_server,
3368 self.fake_dest_share_server,
3369 [fake.SHARE_INSTANCE]
3370 )
3372 self.library._get_vserver.assert_called_once_with(
3373 share_server=self.fake_dest_share_server,
3374 backend_name=self.fake_dest_backend_name)
3375 self.library._get_snapmirror_svm.assert_called_once_with(
3376 self.fake_src_share_server, self.fake_dest_share_server
3377 )
3378 if snapmirrors:
3379 dm_session_mock.cancel_snapmirror_svm.assert_called_once_with(
3380 self.fake_src_share_server, self.fake_dest_share_server
3381 )
3382 self.library._delete_share.assert_called_once_with(
3383 fake.SHARE_INSTANCE, self.fake_dest_vserver, self.mock_dest_client,
3384 remove_export=False)
3386 @ddt.data(True, False)
3387 def test__migration_cancel_using_svm_migrate(self, has_ipspace):
3388 pause_job_uuid = 'fake_pause_job_id'
3389 cancel_job_uuid = 'fake_cancel_job_id'
3390 ipspace_name = 'fake_ipspace_name'
3391 migration_id = 'fake_migration_id'
3392 pause_job = {
3393 'uuid': pause_job_uuid
3394 }
3395 cancel_job = {
3396 'uuid': cancel_job_uuid
3397 }
3398 migration_information = {
3399 "destination": {
3400 "ipspace": {
3401 "name": ipspace_name
3402 }
3403 }
3404 }
3406 if has_ipspace:
3407 migration_information["destination"]["ipspace"]["name"] = (
3408 ipspace_name)
3410 self.mock_object(self.library, '_get_job_uuid',
3411 mock.Mock(
3412 side_effect=[pause_job_uuid, cancel_job_uuid]))
3413 self.mock_object(data_motion, 'get_client_for_host',
3414 mock.Mock(return_value=self.mock_dest_client))
3415 self.mock_object(self.mock_dest_client, 'svm_migration_get',
3416 mock.Mock(return_value=migration_information))
3417 self.mock_object(self.mock_dest_client, 'svm_migrate_pause',
3418 mock.Mock(return_value=pause_job))
3419 self.mock_object(self.library, '_wait_for_operation_status')
3420 self.mock_object(self.mock_dest_client, 'svm_migrate_cancel',
3421 mock.Mock(return_value=cancel_job))
3422 self.mock_object(self.mock_dest_client, 'ipspace_has_data_vservers',
3423 mock.Mock(return_value=False))
3424 self.mock_object(self.mock_dest_client, 'delete_ipspace')
3425 self.mock_object(self.mock_dest_client,
3426 'list_cluster_nodes',
3427 mock.Mock(return_value=fake.CLUSTER_NODES))
3428 self.mock_object(self.library,
3429 '_get_node_data_port',
3430 mock.Mock(return_value='fake_port'))
3432 self.library._migration_cancel_using_svm_migrate(
3433 migration_id, self.fake_dest_share_server)
3435 self.library._get_job_uuid.assert_has_calls(
3436 [mock.call(pause_job), mock.call(cancel_job)]
3437 )
3438 data_motion.get_client_for_host.assert_called_once_with(
3439 self.fake_dest_share_server['host'])
3440 self.mock_dest_client.svm_migration_get.assert_called_once_with(
3441 migration_id)
3442 self.mock_dest_client.svm_migrate_pause.assert_called_once_with(
3443 migration_id)
3444 self.library._wait_for_operation_status.assert_has_calls(
3445 [mock.call(pause_job_uuid, self.mock_dest_client.get_job),
3446 mock.call(migration_id, self.mock_dest_client.svm_migration_get,
3447 desired_status=na_utils.MIGRATION_STATE_MIGRATE_PAUSED),
3448 mock.call(cancel_job_uuid, self.mock_dest_client.get_job)]
3449 )
3450 self.mock_dest_client.svm_migrate_cancel.assert_called_once_with(
3451 migration_id)
3453 if has_ipspace:
3454 self.mock_dest_client.delete_ipspace.assert_called_once_with(
3455 ipspace_name)
3457 @ddt.data(
3458 (mock.Mock(side_effect=exception.NetAppException()), mock.Mock()),
3459 (mock.Mock(), mock.Mock(side_effect=exception.NetAppException()))
3460 )
3461 @ddt.unpack
3462 def test__migration_cancel_using_svm_migrate_error(
3463 self, mock_pause, mock_cancel):
3464 pause_job_uuid = 'fake_pause_job_id'
3465 cancel_job_uuid = 'fake_cancel_job_id'
3466 migration_id = 'fake_migration_id'
3467 migration_information = {
3468 "destination": {
3469 "ipspace": {
3470 "name": "ipspace_name"
3471 }
3472 }
3473 }
3475 self.mock_object(self.library, '_get_job_uuid',
3476 mock.Mock(
3477 side_effect=[pause_job_uuid, cancel_job_uuid]))
3478 self.mock_object(data_motion, 'get_client_for_host',
3479 mock.Mock(return_value=self.mock_dest_client))
3480 self.mock_object(self.mock_dest_client, 'svm_migration_get',
3481 mock.Mock(return_value=migration_information))
3482 self.mock_object(self.mock_dest_client, 'svm_migrate_pause',
3483 mock_pause)
3484 self.mock_object(self.library, '_wait_for_operation_status')
3485 self.mock_object(self.mock_dest_client, 'svm_migrate_cancel',
3486 mock_cancel)
3488 self.assertRaises(
3489 exception.NetAppException,
3490 self.library._migration_cancel_using_svm_migrate,
3491 migration_id,
3492 self.fake_dest_share_server
3493 )
3495 def test_share_server_migration_cancel_svm_dr_snapmirror_failure(self):
3496 dm_session_mock = mock.Mock()
3497 self.mock_object(data_motion, "DataMotionSession",
3498 mock.Mock(return_value=dm_session_mock))
3499 self.mock_object(self.library, '_get_vserver',
3500 mock.Mock(return_value=(self.fake_dest_vserver,
3501 self.mock_dest_client)))
3502 self.mock_object(self.library, '_get_snapmirror_svm',
3503 mock.Mock(return_value=['fake_snapmirror']))
3504 self.mock_object(dm_session_mock, 'cancel_snapmirror_svm',
3505 mock.Mock(side_effect=exception.NetAppException))
3507 self.assertRaises(exception.NetAppException,
3508 self.library._migration_cancel_using_svm_dr,
3509 self.fake_src_share_server,
3510 self.fake_dest_share_server,
3511 [fake.SHARE_INSTANCE])
3513 self.library._get_vserver.assert_called_once_with(
3514 share_server=self.fake_dest_share_server,
3515 backend_name=self.fake_dest_backend_name)
3516 self.library._get_snapmirror_svm.assert_called_once_with(
3517 self.fake_src_share_server, self.fake_dest_share_server
3518 )
3519 dm_session_mock.cancel_snapmirror_svm.assert_called_once_with(
3520 self.fake_src_share_server, self.fake_dest_share_server
3521 )
3523 @ddt.data(None, 'fake_migration_id')
3524 def test_share_server_migration_cancel(self, migration_id):
3525 self.mock_object(self.library, '_get_share_server_migration_id',
3526 mock.Mock(return_value=migration_id))
3527 self.mock_object(self.library, '_migration_cancel_using_svm_migrate')
3528 self.mock_object(self.library, '_migration_cancel_using_svm_dr')
3530 self.library.share_server_migration_cancel(
3531 None, self.fake_src_share_server, self.fake_dest_share_server,
3532 [], [])
3534 if migration_id:
3535 (self.library._migration_cancel_using_svm_migrate
3536 .assert_called_once_with(
3537 migration_id, self.fake_dest_share_server))
3538 else:
3539 (self.library._migration_cancel_using_svm_dr
3540 .assert_called_once_with(
3541 self.fake_src_share_server, self.fake_dest_share_server,
3542 []))
3544 def test_share_server_migration_get_progress(self):
3545 fake_vserver_name = fake.VSERVER1
3546 expected_result = {'total_progress': 50}
3548 self.mock_object(self.library._client, 'get_svm_volumes_total_size',
3549 mock.Mock(return_value=5))
3551 self.mock_object(self.library, '_get_vserver_name',
3552 mock.Mock(return_value=fake_vserver_name))
3554 result = self.library.share_server_migration_get_progress(
3555 None, self.fake_src_share_server, self.fake_dest_share_server,
3556 [self.fake_src_share], None
3557 )
3559 self.library._client.get_svm_volumes_total_size.assert_called_once_with
3560 (fake_vserver_name)
3561 self.library._get_vserver_name.assert_called_once_with
3562 (self.fake_dest_share_server['source_share_server_id'])
3563 self.assertEqual(expected_result, result)
3565 @ddt.data({'subtype': 'default',
3566 'share_group': None,
3567 'compatible': True},
3568 {'subtype': 'default',
3569 'share_group': {'share_server_id': fake.SHARE_SERVER['id']},
3570 'compatible': True},
3571 {'subtype': 'dp_destination',
3572 'share_group': None,
3573 'compatible': False},
3574 {'subtype': 'default',
3575 'share_group': {'share_server_id': 'another_fake_id'},
3576 'compatible': False})
3577 @ddt.unpack
3578 def test_choose_share_server_compatible_with_share_vserver_info(
3579 self, subtype, share_group, compatible):
3580 self.library.is_nfs_config_supported = False
3581 mock_client = mock.Mock()
3582 self.mock_object(self.library, '_get_vserver',
3583 mock.Mock(return_value=(fake.VSERVER1,
3584 mock_client)))
3585 fake_vserver_info = {
3586 'operational_state': 'running',
3587 'state': 'running',
3588 'subtype': subtype
3589 }
3590 self.mock_object(mock_client, 'get_vserver_info',
3591 mock.Mock(return_value=fake_vserver_info))
3592 mock_get_extra_spec = self.mock_object(
3593 share_types, 'get_extra_specs_from_share',
3594 mock.Mock(return_value='fake_extra_specs'))
3595 mock_get_provisioning_opts = self.mock_object(
3596 self.library, '_get_provisioning_options',
3597 mock.Mock(return_value={}))
3598 self.mock_object(mock_client, 'list_vserver_aggregates',
3599 mock.Mock(return_value=fake.AGGREGATES))
3601 result = self.library.choose_share_server_compatible_with_share(
3602 None, [fake.SHARE_SERVER], fake.SHARE_2,
3603 None, share_group
3604 )
3605 expected_result = fake.SHARE_SERVER if compatible else None
3606 self.assertEqual(expected_result, result)
3607 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
3608 mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
3609 if (share_group and
3610 share_group['share_server_id'] != fake.SHARE_SERVER['id']):
3611 mock_client.get_vserver_info.assert_not_called()
3612 self.library._get_vserver.assert_not_called()
3613 else:
3614 mock_client.get_vserver_info.assert_called_once_with(
3615 fake.VSERVER1,
3616 )
3617 self.library._get_vserver.assert_called_once_with(
3618 fake.SHARE_SERVER, backend_name=fake.BACKEND_NAME
3619 )
3621 @ddt.data(
3622 {'policies': [], 'reusable_scope': None, 'compatible': True},
3623 {'policies': "0123456789", 'reusable_scope': {'scope'},
3624 'compatible': True},
3625 {'policies': "0123456789", 'reusable_scope': None,
3626 'compatible': False})
3627 @ddt.unpack
3628 def test_choose_share_server_compatible_with_share_fpolicy(
3629 self, policies, reusable_scope, compatible):
3630 self.library.is_nfs_config_supported = False
3631 mock_client = mock.Mock()
3632 fake_extra_spec = copy.deepcopy(fake.EXTRA_SPEC_WITH_FPOLICY)
3633 mock_get_extra_spec = self.mock_object(
3634 share_types, 'get_extra_specs_from_share',
3635 mock.Mock(return_value=fake_extra_spec))
3636 self.mock_object(self.library, '_get_vserver',
3637 mock.Mock(return_value=(fake.VSERVER1,
3638 mock_client)))
3639 self.mock_object(mock_client, 'get_vserver_info',
3640 mock.Mock(return_value=fake.VSERVER_INFO))
3641 self.mock_object(mock_client, 'list_vserver_aggregates',
3642 mock.Mock(return_value=fake.AGGREGATES))
3643 mock_get_policies = self.mock_object(
3644 mock_client, 'get_fpolicy_policies_status',
3645 mock.Mock(return_value=policies))
3646 mock_reusable_scope = self.mock_object(
3647 self.library, '_find_reusable_fpolicy_scope',
3648 mock.Mock(return_value=reusable_scope))
3650 result = self.library.choose_share_server_compatible_with_share(
3651 None, [fake.SHARE_SERVER], fake.SHARE_2,
3652 None, None
3653 )
3655 expected_result = fake.SHARE_SERVER if compatible else None
3656 self.assertEqual(expected_result, result)
3657 mock_get_extra_spec.assert_called_once_with(fake.SHARE_2)
3658 mock_client.get_vserver_info.assert_called_once_with(
3659 fake.VSERVER1,
3660 )
3661 self.library._get_vserver.assert_called_once_with(
3662 fake.SHARE_SERVER, backend_name=fake.BACKEND_NAME
3663 )
3664 mock_get_policies.assert_called_once()
3665 if len(policies) >= self.library.FPOLICY_MAX_VSERVER_POLICIES:
3666 mock_reusable_scope.assert_called_once_with(
3667 fake.SHARE_2, mock_client,
3668 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
3669 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
3670 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
3672 @ddt.data({'subtype': 'default', 'compatible': True},
3673 {'subtype': 'dp_destination', 'compatible': False})
3674 @ddt.unpack
3675 def test_choose_share_server_compatible_with_share_group_vserver_info(
3676 self, subtype, compatible):
3677 self.library.is_nfs_config_supported = False
3678 mock_client = mock.Mock()
3679 self.mock_object(self.library, '_get_vserver',
3680 mock.Mock(return_value=(fake.VSERVER1,
3681 mock_client)))
3682 fake_vserver_info = {
3683 'operational_state': 'running',
3684 'state': 'running',
3685 'subtype': subtype
3686 }
3687 self.mock_object(mock_client, 'get_vserver_info',
3688 mock.Mock(return_value=fake_vserver_info))
3690 result = self.library.choose_share_server_compatible_with_share_group(
3691 None, [fake.SHARE_SERVER], None
3692 )
3693 expected_result = fake.SHARE_SERVER if compatible else None
3694 self.assertEqual(expected_result, result)
3695 self.library._get_vserver.assert_called_once_with(
3696 fake.SHARE_SERVER, backend_name=fake.BACKEND_NAME
3697 )
3698 mock_client.get_vserver_info.assert_called_once_with(
3699 fake.VSERVER1,
3700 )
3702 def test_choose_share_server_compatible_with_different_aggrs(self):
3703 self.library.is_nfs_config_supported = False
3704 mock_client = mock.Mock()
3705 self.mock_object(self.library, '_get_vserver',
3706 mock.Mock(return_value=(fake.VSERVER1,
3707 mock_client)))
3708 fake_vserver_info = {
3709 'operational_state': 'running',
3710 'state': 'running',
3711 'subtype': 'default'
3712 }
3713 self.mock_object(mock_client, 'get_vserver_info',
3714 mock.Mock(return_value=fake_vserver_info))
3715 mock_get_extra_spec = self.mock_object(
3716 share_types, 'get_extra_specs_from_share',
3717 mock.Mock(return_value='fake_extra_specs'))
3718 mock_get_provisioning_opts = self.mock_object(
3719 self.library, '_get_provisioning_options',
3720 mock.Mock(return_value={}))
3721 self.mock_object(mock_client, 'list_vserver_aggregates',
3722 mock.Mock(return_value=fake.AGGREGATES))
3723 result = self.library.choose_share_server_compatible_with_share(
3724 None, [fake.SHARE_SERVER], fake.SHARE_INSTANCE, None)
3725 self.assertIsNone(result)
3726 mock_get_extra_spec.assert_called_once_with(fake.SHARE_INSTANCE)
3727 mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
3729 def test_choose_share_server_compatible_with_flexgroups(self):
3730 self.library.is_nfs_config_supported = False
3731 mock_client = mock.Mock()
3732 self.mock_object(self.library, '_get_vserver',
3733 mock.Mock(return_value=(fake.VSERVER1,
3734 mock_client)))
3735 fake_vserver_info = {
3736 'operational_state': 'running',
3737 'state': 'running',
3738 'subtype': 'default'
3739 }
3740 self.mock_object(mock_client, 'get_vserver_info',
3741 mock.Mock(return_value=fake_vserver_info))
3742 mock_get_extra_spec = self.mock_object(
3743 share_types, 'get_extra_specs_from_share',
3744 mock.Mock(return_value='fake_extra_specs'))
3745 mock_get_provisioning_opts = self.mock_object(
3746 self.library, '_get_provisioning_options',
3747 mock.Mock(return_value={}))
3748 self.mock_object(mock_client, 'list_vserver_aggregates',
3749 mock.Mock(return_value=fake.FLEXGROUP_POOL_AGGR))
3750 self.mock_object(self.library, '_is_flexgroup_pool',
3751 mock.Mock(return_value=True))
3752 self.mock_object(self.library, '_get_flexgroup_aggregate_list',
3753 mock.Mock(return_value=fake.FLEXGROUP_POOL_AGGR))
3754 result = self.library.choose_share_server_compatible_with_share(
3755 None, [fake.SHARE_SERVER], fake.SHARE_FLEXGROUP, None)
3756 expected_result = fake.SHARE_SERVER
3757 self.assertEqual(expected_result, result)
3758 self.library._get_vserver.assert_called_once_with(
3759 fake.SHARE_SERVER, backend_name=fake.BACKEND_NAME
3760 )
3761 mock_client.get_vserver_info.assert_called_once_with(
3762 fake.VSERVER1,
3763 )
3764 mock_get_extra_spec.assert_called_once_with(fake.SHARE_FLEXGROUP)
3765 mock_get_provisioning_opts.assert_called_once_with('fake_extra_specs')
3767 def test__create_port_and_broadcast_domain(self):
3768 self.mock_object(self.library._client,
3769 'list_cluster_nodes',
3770 mock.Mock(return_value=fake.CLUSTER_NODES))
3771 self.mock_object(self.library,
3772 '_get_node_data_port',
3773 mock.Mock(return_value='fake_port'))
3775 self.library._create_port_and_broadcast_domain(fake.IPSPACE,
3776 fake.NETWORK_INFO)
3777 node_network_info = zip(fake.CLUSTER_NODES,
3778 fake.NETWORK_INFO['network_allocations'])
3779 get_node_port_calls = []
3780 create_port_calls = []
3781 for node, alloc in node_network_info:
3782 get_node_port_calls.append(mock.call(node))
3783 create_port_calls.append(mock.call(
3784 node, 'fake_port', alloc['segmentation_id'], alloc['mtu'],
3785 fake.IPSPACE
3786 ))
3788 self.library._get_node_data_port.assert_has_calls(get_node_port_calls)
3789 self.library._client.create_port_and_broadcast_domain.assert_has_calls(
3790 create_port_calls)
3792 def test___update_share_attributes_after_server_migration(self):
3793 fake_aggregate = 'fake_aggr_0'
3794 mock_get_extra_spec = self.mock_object(
3795 share_types, "get_extra_specs_from_share",
3796 mock.Mock(return_value=fake.EXTRA_SPEC))
3797 mock__get_provisioning_opts = self.mock_object(
3798 self.library, '_get_provisioning_options',
3799 mock.Mock(return_value=copy.deepcopy(fake.PROVISIONING_OPTIONS)))
3800 fake_share_name = self.library._get_backend_share_name(
3801 fake.SHARE_INSTANCE['id'])
3802 mock_get_vol_autosize_attrs = self.mock_object(
3803 self.mock_src_client, 'get_volume_autosize_attributes',
3804 mock.Mock(return_value=fake.VOLUME_AUTOSIZE_ATTRS)
3805 )
3806 fake_provisioning_opts = copy.copy(fake.PROVISIONING_OPTIONS)
3807 fake_autosize_attrs = copy.copy(fake.VOLUME_AUTOSIZE_ATTRS)
3808 for key in ('minimum-size', 'maximum-size'):
3809 fake_autosize_attrs[key] = int(fake_autosize_attrs[key]) * units.Ki
3810 fake_provisioning_opts['autosize_attributes'] = fake_autosize_attrs
3811 mock_modify_volume = self.mock_object(self.mock_dest_client,
3812 'modify_volume')
3813 fake_provisioning_opts.pop('snapshot_policy', None)
3815 self.library._update_share_attributes_after_server_migration(
3816 fake.SHARE_INSTANCE, self.mock_src_client, fake_aggregate,
3817 self.mock_dest_client)
3819 mock_get_extra_spec.assert_called_once_with(fake.SHARE_INSTANCE)
3820 mock__get_provisioning_opts.assert_called_once_with(fake.EXTRA_SPEC)
3821 mock_get_vol_autosize_attrs.assert_called_once_with(fake_share_name)
3822 mock_modify_volume.assert_called_once_with(
3823 fake_aggregate, fake_share_name, **fake_provisioning_opts)
3825 def test_validate_provisioning_options_for_share(self):
3826 mock_create_from_snap = self.mock_object(
3827 lib_base.NetAppCmodeFileStorageLibrary,
3828 'validate_provisioning_options_for_share')
3830 self.library.validate_provisioning_options_for_share(
3831 fake.PROVISIONING_OPTIONS, extra_specs=fake.EXTRA_SPEC,
3832 qos_specs=fake.QOS_NORMALIZED_SPEC)
3834 mock_create_from_snap.assert_called_once_with(
3835 fake.PROVISIONING_OPTIONS, extra_specs=fake.EXTRA_SPEC,
3836 qos_specs=fake.QOS_NORMALIZED_SPEC)
3838 def test_validate_provisioning_options_for_share_aqos_not_supported(self):
3839 self.assertRaises(
3840 exception.NetAppException,
3841 self.library.validate_provisioning_options_for_share,
3842 fake.PROVISIONING_OPTS_WITH_ADAPT_QOS, qos_specs=None)
3844 def test__get_different_keys_for_equal_ss_type(self):
3845 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
3846 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_2)
3847 new_sec_service2 = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_3)
3849 expected_keys = ['password', 'user', 'ou',
3850 'domain', 'dns_ip', 'server']
3852 result = self.library._get_different_keys_for_equal_ss_type(
3853 curr_sec_service, new_sec_service)
3855 self.assertEqual(expected_keys, result)
3857 expected_keys = ['password', 'user', 'ou',
3858 'domain', 'dns_ip', 'server', 'default_ad_site']
3859 result = self.library._get_different_keys_for_equal_ss_type(
3860 curr_sec_service, new_sec_service2)
3862 self.assertEqual(expected_keys, result)
3864 @ddt.data(
3865 {'current': None,
3866 'new': fake.CIFS_SECURITY_SERVICE,
3867 'existing': []},
3869 {'current': fake.CIFS_SECURITY_SERVICE,
3870 'new': fake.CIFS_SECURITY_SERVICE_2,
3871 'existing': [fake.CIFS_SECURITY_SERVICE,
3872 fake.KERBEROS_SECURITY_SERVICE]},
3874 {'current': fake.KERBEROS_SECURITY_SERVICE,
3875 'new': fake.KERBEROS_SECURITY_SERVICE_2,
3876 'existing': [fake.CIFS_SECURITY_SERVICE,
3877 fake.KERBEROS_SECURITY_SERVICE]},
3879 {'current': fake.CIFS_SECURITY_SERVICE,
3880 'new': fake.CIFS_SECURITY_SERVICE,
3881 'existing': [fake.CIFS_SECURITY_SERVICE]},
3882 )
3883 @ddt.unpack
3884 def test_update_share_server_security_service(self, current, new,
3885 existing):
3886 fake_context = mock.Mock()
3887 fake_net_info = copy.deepcopy(fake.NETWORK_INFO_LIST)
3888 new_sec_service = copy.deepcopy(new)
3889 curr_sec_service = copy.deepcopy(current) if current else None
3890 new_type = new_sec_service['type'].lower()
3891 fake_net_info[0]['security_services'] = existing
3893 if curr_sec_service:
3894 # domain modification aren't support
3895 new_sec_service['domain'] = curr_sec_service['domain']
3897 different_keys = []
3898 if curr_sec_service != new_sec_service:
3899 different_keys = ['dns_ip', 'server', 'domain', 'user', 'password']
3900 if new_sec_service.get('ou') is not None:
3901 different_keys.append('ou')
3903 fake_vserver_client = mock.Mock()
3904 mock_get_vserver = self.mock_object(
3905 self.library, '_get_vserver',
3906 mock.Mock(return_value=[fake.VSERVER1, fake_vserver_client]))
3907 mock_check_update = self.mock_object(
3908 self.library, 'check_update_share_server_security_service',
3909 mock.Mock(return_value=True))
3910 mock_setup_sec_serv = self.mock_object(
3911 self.library._client, 'setup_security_services')
3912 mock_diff_keys = self.mock_object(
3913 self.library, '_get_different_keys_for_equal_ss_type',
3914 mock.Mock(return_value=different_keys))
3915 mock_dns_update = self.mock_object(
3916 fake_vserver_client, 'update_dns_configuration')
3917 mock_update_krealm = self.mock_object(
3918 fake_vserver_client, 'update_kerberos_realm')
3919 mock_modify_ad = self.mock_object(
3920 fake_vserver_client, 'modify_active_directory_security_service')
3922 self.library.update_share_server_security_service(
3923 fake_context, fake.SHARE_SERVER, fake_net_info,
3924 new_sec_service, current_security_service=curr_sec_service)
3926 dns_ips = set()
3927 domains = set()
3928 # we don't need to split and strip since we know that fake have only
3929 # on dns-ip and domain configured
3930 for ss in existing:
3931 if ss['type'] != new_sec_service['type']:
3932 dns_ips.add(ss['dns_ip'])
3933 domains.add(ss['domain'])
3934 dns_ips.add(new_sec_service['dns_ip'])
3935 domains.add(new_sec_service['domain'])
3937 mock_get_vserver.assert_called_once_with(
3938 share_server=fake.SHARE_SERVER)
3939 mock_check_update.assert_called_once_with(
3940 fake_context, fake.SHARE_SERVER, fake_net_info, new_sec_service,
3941 current_security_service=curr_sec_service)
3943 if curr_sec_service is None:
3944 mock_setup_sec_serv.assert_called_once_with(
3945 [new_sec_service], fake_vserver_client, fake.VSERVER1, False)
3946 else:
3947 mock_diff_keys.assert_called_once_with(curr_sec_service,
3948 new_sec_service)
3949 if different_keys:
3950 mock_dns_update.assert_called_once_with(dns_ips, domains)
3951 if new_type == 'kerberos':
3952 mock_update_krealm.assert_called_once_with(new_sec_service)
3953 elif new_type == 'active_directory': 3953 ↛ exitline 3953 didn't return from function 'test_update_share_server_security_service' because the condition on line 3953 was always true
3954 mock_modify_ad.assert_called_once_with(
3955 fake.VSERVER1, different_keys, new_sec_service,
3956 curr_sec_service)
3958 def test_update_share_server_security_service_check_error(self):
3959 curr_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE)
3960 new_sec_service = copy.deepcopy(fake.CIFS_SECURITY_SERVICE_2)
3961 fake_vserver_client = mock.Mock()
3962 fake_context = mock.Mock()
3963 fake_net_info = mock.Mock()
3965 mock_get_vserver = self.mock_object(
3966 self.library, '_get_vserver',
3967 mock.Mock(return_value=[fake.VSERVER1, fake_vserver_client]))
3968 mock_check_update = self.mock_object(
3969 self.library, 'check_update_share_server_security_service',
3970 mock.Mock(return_value=False))
3972 self.assertRaises(
3973 exception.NetAppException,
3974 self.library.update_share_server_security_service,
3975 fake_context, fake.SHARE_SERVER, fake_net_info,
3976 new_sec_service, current_security_service=curr_sec_service)
3978 mock_get_vserver.assert_called_once_with(
3979 share_server=fake.SHARE_SERVER)
3980 mock_check_update.assert_called_once_with(
3981 fake_context, fake.SHARE_SERVER, fake_net_info,
3982 new_sec_service, current_security_service=curr_sec_service)
3984 @ddt.data(
3985 {'new': fake.LDAP_AD_SECURITY_SERVICE,
3986 'current': fake.LDAP_LINUX_SECURITY_SERVICE,
3987 'expected': True},
3989 {'new': fake.CIFS_SECURITY_SERVICE,
3990 'current': fake.KERBEROS_SECURITY_SERVICE,
3991 'expected': False},
3993 {'new': fake.CIFS_SECURITY_SERVICE,
3994 'current': fake.CIFS_SECURITY_SERVICE,
3995 'expected': True},
3997 {'new': fake.KERBEROS_SECURITY_SERVICE,
3998 'current': fake.KERBEROS_SECURITY_SERVICE,
3999 'expected': True},
4001 {'new': fake.CIFS_SECURITY_SERVICE,
4002 'current': None,
4003 'expected': True},
4004 )
4005 @ddt.unpack
4006 def test_check_update_share_server_security_service(self, new, current,
4007 expected):
4008 result = self.library.check_update_share_server_security_service(
4009 None, None, None, new, current_security_service=current)
4011 self.assertEqual(expected, result)
4013 def test_check_update_share_server_network_allocations(self):
4014 net_alloc_seg_id = fake.USER_NETWORK_ALLOCATIONS[0]['segmentation_id']
4015 network_segments = [
4016 {'segmentation_id': net_alloc_seg_id},
4017 {'segmentation_id': fake.SHARE_NETWORK_SUBNET['segmentation_id']}
4018 ]
4020 mock__validate_network_type = self.mock_object(
4021 self.library, '_validate_network_type')
4022 mock__validate_share_network_subnets = self.mock_object(
4023 self.library, '_validate_share_network_subnets')
4025 result = self.library.check_update_share_server_network_allocations(
4026 None, fake.SHARE_SERVER, fake.CURRENT_NETWORK_ALLOCATIONS,
4027 fake.SHARE_NETWORK_SUBNET, None, None,
4028 None)
4030 self.assertTrue(result)
4031 mock__validate_network_type.assert_called_once_with(
4032 [fake.SHARE_NETWORK_SUBNET])
4033 mock__validate_share_network_subnets.assert_called_once_with(
4034 network_segments)
4036 def test_check_update_share_server_network_allocations_fail_on_type(self):
4037 network_exception = exception.NetworkBadConfigurationException(
4038 reason='fake exception message')
4040 mock_validate_network_type = self.mock_object(
4041 self.library, '_validate_network_type',
4042 mock.Mock(side_effect=network_exception))
4044 mock_validate_share_network_subnets = self.mock_object(
4045 self.library, '_validate_share_network_subnets')
4047 result = self.library.check_update_share_server_network_allocations(
4048 None, fake.SHARE_SERVER, fake.CURRENT_NETWORK_ALLOCATIONS,
4049 fake.SHARE_NETWORK_SUBNET, None, None, None)
4051 self.assertFalse(result)
4052 mock_validate_network_type.assert_called_once_with(
4053 [fake.SHARE_NETWORK_SUBNET])
4054 mock_validate_share_network_subnets.assert_not_called()
4056 def test_check_update_share_server_network_allocations_subnets_error(self):
4057 net_alloc_seg_id = fake.USER_NETWORK_ALLOCATIONS[0]['segmentation_id']
4058 network_segments = [
4059 {'segmentation_id': net_alloc_seg_id},
4060 {'segmentation_id': fake.SHARE_NETWORK_SUBNET['segmentation_id']}
4061 ]
4062 network_exception = exception.NetworkBadConfigurationException(
4063 reason='fake exception message')
4065 mock__validate_network_type = self.mock_object(
4066 self.library, '_validate_network_type')
4067 mock__validate_share_network_subnets = self.mock_object(
4068 self.library, '_validate_share_network_subnets',
4069 mock.Mock(side_effect=network_exception))
4071 result = self.library.check_update_share_server_network_allocations(
4072 None, fake.SHARE_SERVER, fake.CURRENT_NETWORK_ALLOCATIONS,
4073 fake.SHARE_NETWORK_SUBNET, None, None,
4074 None)
4076 self.assertFalse(result)
4077 mock__validate_network_type.assert_called_once_with(
4078 [fake.SHARE_NETWORK_SUBNET])
4079 mock__validate_share_network_subnets.assert_called_once_with(
4080 network_segments)
4082 @ddt.data(True, False)
4083 def test_build_model_update(self, has_export_locations):
4084 server_model_update = copy.deepcopy(fake.SERVER_MODEL_UPDATE)
4086 export_locations = server_model_update['share_updates']
4087 if not has_export_locations:
4088 export_locations = None
4089 del server_model_update['share_updates']
4091 result = self.library._build_model_update(
4092 fake.CURRENT_NETWORK_ALLOCATIONS, fake.NEW_NETWORK_ALLOCATIONS,
4093 export_locations=export_locations)
4095 self.assertEqual(server_model_update, result)
4097 @ddt.data('active', 'dr')
4098 def test_update_share_server_network_allocations(self, replica_state):
4099 fake_context = mock.Mock()
4100 fake_share_server = fake.SHARE_SERVER
4101 fake_current_network_allocations = fake.USER_NETWORK_ALLOCATIONS
4102 fake_new_network_allocations = fake.USER_NETWORK_ALLOCATIONS
4103 fake_share_instances = [copy.deepcopy(fake.SHARE_INSTANCE)]
4104 fake_share_instances[0]['replica_state'] = replica_state
4105 fake_vserver_name = fake.VSERVER1
4106 fake_vserver_client = mock.Mock()
4107 fake_ipspace_name = fake.IPSPACE
4108 fake_export_locations = fake.NFS_EXPORTS[0]
4109 fake_updates = fake.SERVER_MODEL_UPDATE
4110 fake_updated_export_locations = {
4111 fake_share_instances[0]['id']: fake_export_locations,
4112 }
4114 self.mock_object(self.library, '_get_vserver_name',
4115 mock.Mock(return_value=fake_vserver_name))
4116 self.mock_object(self.library, '_get_api_client',
4117 mock.Mock(return_value=fake_vserver_client))
4118 self.mock_object(self.library._client, 'get_vserver_ipspace',
4119 mock.Mock(return_value=fake_ipspace_name))
4120 self.mock_object(self.library, '_setup_network_for_vserver')
4121 self.mock_object(self.library, '_create_export',
4122 mock.Mock(return_value=fake_export_locations))
4123 self.mock_object(self.library, '_build_model_update',
4124 mock.Mock(return_value=fake_updates))
4126 self.assertEqual(
4127 fake_updates,
4128 self.library.update_share_server_network_allocations(
4129 fake_context, fake_share_server,
4130 fake_current_network_allocations, fake_new_network_allocations,
4131 None, fake_share_instances, None))
4132 self.library._get_vserver_name.assert_called_once_with(
4133 fake_share_server['id'])
4134 self.library._get_api_client.assert_called_once_with(
4135 vserver=fake_vserver_name)
4136 self.library._client.get_vserver_ipspace.assert_called_once_with(
4137 fake_vserver_name)
4138 self.library._setup_network_for_vserver.assert_called_once_with(
4139 fake_vserver_name, fake_vserver_client,
4140 [fake_new_network_allocations], fake_ipspace_name,
4141 enable_nfs=False, security_services=None, nfs_config=None)
4142 if replica_state == 'active':
4143 self.library._create_export.assert_called_once_with(
4144 fake_share_instances[0], fake_share_server,
4145 fake_vserver_name, fake_vserver_client,
4146 clear_current_export_policy=False,
4147 ensure_share_already_exists=True,
4148 share_host=fake_share_instances[0]['host'])
4149 else:
4150 self.library._create_export.assert_not_called()
4151 fake_updated_export_locations = {}
4153 self.library._build_model_update.assert_called_once_with(
4154 fake_current_network_allocations, fake_new_network_allocations,
4155 fake_updated_export_locations)
4157 def test_update_share_server_network_allocations_setup_network_fail(self):
4158 fake_context = mock.Mock()
4159 fake_share_server = fake.SHARE_SERVER
4160 fake_current_network_allocations = fake.USER_NETWORK_ALLOCATIONS
4161 fake_new_network_allocations = fake.USER_NETWORK_ALLOCATIONS
4162 fake_share_instances = [fake.SHARE_INSTANCE]
4163 fake_updates = fake.SERVER_MODEL_UPDATE
4165 self.mock_object(self.library, '_get_vserver_name')
4166 self.mock_object(self.library, '_get_api_client')
4167 self.mock_object(self.library._client, 'get_vserver_ipspace')
4168 self.mock_object(self.library, '_setup_network_for_vserver',
4169 mock.Mock(side_effect=netapp_api.NaApiError))
4170 self.mock_object(self.library, '_build_model_update',
4171 mock.Mock(return_value=fake_updates))
4173 self.assertRaises(netapp_api.NaApiError,
4174 self.library.update_share_server_network_allocations,
4175 fake_context, fake_share_server,
4176 fake_current_network_allocations,
4177 fake_new_network_allocations, None,
4178 fake_share_instances, None)
4179 self.library._build_model_update.assert_called_once_with(
4180 fake_current_network_allocations, fake_new_network_allocations,
4181 export_locations=None)
4183 def test__get_backup_vserver(self):
4184 mock_dest_client = mock.Mock()
4185 self.mock_object(self.library,
4186 '_get_backend',
4187 mock.Mock(return_value=fake.BACKEND_NAME))
4188 self.mock_object(data_motion,
4189 'get_backend_configuration',
4190 mock.Mock(return_value=_get_config()))
4191 self.mock_object(self.library,
4192 '_get_api_client_for_backend',
4193 mock.Mock(return_value=mock_dest_client))
4194 self.mock_object(mock_dest_client,
4195 'list_non_root_aggregates',
4196 mock.Mock(return_value=['aggr1', 'aggr2']))
4197 self.mock_object(mock_dest_client,
4198 'create_vserver',
4199 mock.Mock(side_effect=netapp_api.NaApiError(
4200 message='Vserver name is already used by another'
4201 ' Vserver')))
4202 self.library._get_backup_vserver(fake.SHARE_BACKUP, fake.SHARE_SERVER)
4204 def test__delete_backup_vserver(self):
4205 mock_api_client = mock.Mock()
4206 self.mock_object(self.library,
4207 '_get_backend',
4208 mock.Mock(return_value=fake.BACKEND_NAME))
4209 self.mock_object(self.library,
4210 '_get_api_client_for_backend',
4211 mock.Mock(return_value=mock_api_client))
4212 des_vserver = fake.VSERVER2
4213 msg = (f"Cannot delete Vserver. Vserver {des_vserver} "
4214 f"has shares.")
4215 self.mock_object(mock_api_client,
4216 'delete_vserver',
4217 mock.Mock(
4218 side_effect=exception.NetAppException(
4219 message=msg)))
4220 self.library._delete_backup_vserver(fake.SHARE_BACKUP, des_vserver)
4222 def test__check_data_lif_count_limit_reached_for_ha_pair_false(self):
4223 nodes = ["node1", "node2"]
4224 lif_detail = [{'node': "node1",
4225 'count-for-node': '44',
4226 'limit-for-node': '512'},
4227 {'node': "node2",
4228 'count-for-node': '50',
4229 'limit-for-node': '512'}]
4231 self.mock_object(self.client,
4232 'get_storage_failover_partner',
4233 mock.Mock(return_value="node2"))
4234 self.mock_object(self.client,
4235 'list_cluster_nodes',
4236 mock.Mock(return_value=nodes))
4238 self.mock_object(self.client,
4239 'get_data_lif_details_for_nodes',
4240 mock.Mock(return_value=lif_detail))
4241 self.mock_object(self.client,
4242 'get_migratable_data_lif_for_node',
4243 mock.Mock(return_value=["data_lif_1", "data_lif_2"]))
4244 self.library._check_data_lif_count_limit_reached_for_ha_pair(
4245 self.client)
4247 def test__check_data_lif_count_limit_reached_for_ha_pair_true(self):
4248 nodes = ["node1", "node2"]
4249 lif_detail = [{'node': "node1",
4250 'count-for-node': '511',
4251 'limit-for-node': '512'},
4252 {'node': "node2",
4253 'count-for-node': '250',
4254 'limit-for-node': '512'}]
4255 self.mock_object(self.client,
4256 'get_storage_failover_partner',
4257 mock.Mock(return_value="node2"))
4258 self.mock_object(self.client,
4259 'list_cluster_nodes',
4260 mock.Mock(return_value=nodes))
4262 self.mock_object(self.client,
4263 'get_data_lif_details_for_nodes',
4264 mock.Mock(return_value=lif_detail))
4265 self.mock_object(self.client,
4266 'get_migratable_data_lif_for_node',
4267 mock.Mock(return_value=["data_lif_1", "data_lif_2"]))
4269 self.assertRaises(
4270 exception.NetAppException,
4271 self.library._check_data_lif_count_limit_reached_for_ha_pair,
4272 self.client,
4273 )