Coverage for manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_base.py: 99%
4271 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# Copyright (c) 2015 Tom Barron. All rights reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15"""
16Unit tests for the NetApp Data ONTAP cDOT base storage driver library.
17"""
19import copy
20import json
21import math
22import socket
23import time
24from unittest import mock
26import ddt
27from oslo_config import cfg
28from oslo_log import log
29from oslo_service import loopingcall
30from oslo_utils import timeutils
31from oslo_utils import units
32from oslo_utils import uuidutils
34from manila.common import constants
35from manila import exception
36from manila.share import configuration
37from manila.share import driver
38from manila.share.drivers.netapp.dataontap.client import api as netapp_api
39from manila.share.drivers.netapp.dataontap.client import client_cmode
40from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion
41from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base
42from manila.share.drivers.netapp.dataontap.cluster_mode import performance
43from manila.share.drivers.netapp.dataontap.protocols import cifs_cmode
44from manila.share.drivers.netapp.dataontap.protocols import nfs_cmode
45from manila.share.drivers.netapp import options as na_opts
46from manila.share.drivers.netapp import utils as na_utils
47from manila.share import share_types
48from manila.share import utils as share_utils
49from manila import test
50from manila.tests import fake_share
51from manila.tests.share.drivers.netapp.dataontap import fakes as fake
52from manila.tests.share.drivers.netapp import fakes as na_fakes
53from manila.tests import utils
55CONF = cfg.CONF
58def fake_replica(**kwargs):
59 return fake_share.fake_replica(for_manager=True, **kwargs)
62def _get_config():
63 backup_config = 'backup_config'
64 config = configuration.Configuration(driver.share_opts,
65 config_group=backup_config)
66 config.append_config_values(na_opts.netapp_backup_opts)
67 config.append_config_values(na_opts.netapp_proxy_opts)
68 config.append_config_values(na_opts.netapp_connection_opts)
69 config.append_config_values(na_opts.netapp_basicauth_opts)
70 config.append_config_values(na_opts.netapp_certificateauth_opts)
71 config.append_config_values(na_opts.netapp_provisioning_opts)
72 config.append_config_values(na_opts.netapp_support_opts)
73 config.append_config_values(na_opts.netapp_data_motion_opts)
74 config.append_config_values(na_opts.netapp_cluster_opts)
76 CONF.set_override("netapp_enabled_backup_types",
77 [fake.BACKUP_TYPE, "backup2"],
78 group=backup_config)
79 CONF.set_override("netapp_backup_backend_section_name",
80 fake.BACKEND_NAME,
81 group=backup_config)
82 CONF.set_override("netapp_backup_vserver",
83 "fake_backup_share",
84 group=backup_config)
85 CONF.set_override("netapp_backup_volume",
86 "fake_share_server",
87 group=backup_config)
88 return config
91@ddt.ddt
92class NetAppFileStorageLibraryTestCase(test.TestCase):
94 def setUp(self):
95 super(NetAppFileStorageLibraryTestCase, self).setUp()
97 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None)
98 self.sleep_patcher.start()
99 self.addCleanup(self.sleep_patcher.stop)
101 self.mock_object(na_utils, 'validate_driver_instantiation')
102 self.mock_object(na_utils, 'setup_tracing')
104 # Mock loggers as themselves to allow logger arg validation
105 mock_logger = log.getLogger('mock_logger')
106 self.mock_object(lib_base.LOG,
107 'info',
108 mock.Mock(side_effect=mock_logger.info))
109 self.mock_object(lib_base.LOG,
110 'warning',
111 mock.Mock(side_effect=mock_logger.warning))
112 self.mock_object(lib_base.LOG,
113 'error',
114 mock.Mock(side_effect=mock_logger.error))
115 self.mock_object(lib_base.LOG,
116 'debug',
117 mock.Mock(side_effect=mock_logger.debug))
119 kwargs = {
120 'configuration': fake.get_config_cmode(),
121 'private_storage': mock.Mock(),
122 'app_version': fake.APP_VERSION
123 }
124 self.library = lib_base.NetAppCmodeFileStorageLibrary(fake.DRIVER_NAME,
125 **kwargs)
126 self.library._client = mock.Mock()
127 self.library._perf_library = mock.Mock()
128 self.client = self.library._client
129 self.context = mock.Mock()
130 self.fake_replica = copy.deepcopy(fake.SHARE)
131 self.fake_replica_2 = copy.deepcopy(fake.SHARE)
132 self.fake_replica_2['id'] = fake.SHARE_ID2
133 self.fake_replica_2['replica_state'] = (
134 constants.REPLICA_STATE_OUT_OF_SYNC)
135 self.mock_dm_session = mock.Mock()
136 self.mock_object(data_motion, "DataMotionSession",
137 mock.Mock(return_value=self.mock_dm_session))
138 self.mock_object(data_motion, 'get_client_for_backend')
140 def _mock_api_error(self, code='fake', message='fake'):
141 return mock.Mock(side_effect=netapp_api.NaApiError(code=code,
142 message=message))
144 def test_init(self):
145 self.assertEqual(fake.DRIVER_NAME, self.library.driver_name)
146 self.assertEqual(1, na_utils.validate_driver_instantiation.call_count)
147 self.assertEqual(1, na_utils.setup_tracing.call_count)
148 self.assertListEqual([], self.library._licenses)
149 self.assertDictEqual({}, self.library._clients)
150 self.assertDictEqual({}, self.library._ssc_stats)
151 self.assertIsNotNone(self.library._app_version)
153 def test_do_setup(self):
154 mock_get_api_client = self.mock_object(self.library, '_get_api_client')
155 self.mock_object(
156 performance, 'PerformanceLibrary',
157 mock.Mock(return_value='fake_perf_library'))
158 self.mock_object(
159 self.library._client, 'check_for_cluster_credentials',
160 mock.Mock(return_value=True))
161 self.mock_object(
162 self.library._client, 'get_nfs_config_default',
163 mock.Mock(return_value=fake.NFS_CONFIG_DEFAULT))
164 self.mock_object(self.library._client,
165 'list_cluster_nodes',
166 mock.Mock(return_value=['node1', 'node2']))
167 self.mock_object(
168 self.library, '_check_snaprestore_license',
169 mock.Mock(return_value=True))
170 self.mock_object(
171 self.library,
172 '_get_licenses',
173 mock.Mock(return_value=fake.LICENSES))
175 mock_get_api_client.features.TRANSFER_LIMIT_NFS_CONFIG = True
176 self.library.do_setup(self.context)
177 self.assertEqual(fake.LICENSES, self.library._licenses)
178 mock_get_api_client.assert_called_once_with()
179 (self.library._client.check_for_cluster_credentials.
180 assert_called_once_with())
181 (self.library._client.get_nfs_config_default.
182 assert_called_once_with(
183 list(self.library.NFS_CONFIG_EXTRA_SPECS_MAP.values())))
184 self.assertEqual('fake_perf_library', self.library._perf_library)
185 self.mock_object(self.library._client,
186 'check_for_cluster_credentials',
187 mock.Mock(return_value=True))
188 self.mock_object(self.library._client,
189 'list_cluster_nodes',
190 mock.Mock(return_value=['node1', 'node2']))
191 self.mock_object(
192 self.library, '_check_snaprestore_license',
193 mock.Mock(return_value=True))
194 mock_set_cluster_info = self.mock_object(
195 self.library, '_set_cluster_info')
196 self.library.do_setup(self.context)
197 mock_set_cluster_info.assert_called_once()
199 def test_set_cluster_info(self):
200 self.library._client.is_nve_supported.return_value = True
201 self.library._client.features.FLEXVOL_ENCRYPTION = True
202 self.library._set_cluster_info()
203 self.assertTrue(self.library._cluster_info['nve_support'])
205 def test_check_for_setup_error(self):
206 mock_start_periodic_tasks = self.mock_object(self.library,
207 '_start_periodic_tasks')
208 self.library.check_for_setup_error()
210 mock_start_periodic_tasks.assert_called_once_with()
212 def test_get_vserver(self):
213 self.assertRaises(NotImplementedError, self.library._get_vserver)
215 def test_get_api_client(self):
217 client_kwargs = fake.CLIENT_KWARGS.copy()
219 # First call should proceed normally.
220 mock_client_constructor = self.mock_object(client_cmode,
221 'NetAppCmodeClient')
222 client1 = self.library._get_api_client()
223 self.assertIsNotNone(client1)
224 mock_client_constructor.assert_called_once_with(**client_kwargs)
226 # Second call should yield the same object.
227 mock_client_constructor = self.mock_object(client_cmode,
228 'NetAppCmodeClient')
229 client2 = self.library._get_api_client()
230 self.assertEqual(client1, client2)
231 self.assertFalse(mock_client_constructor.called)
233 def test_get_api_client_with_vserver(self):
235 client_kwargs = fake.CLIENT_KWARGS.copy()
236 client_kwargs['vserver'] = fake.VSERVER1
238 # First call should proceed normally.
239 mock_client_constructor = self.mock_object(client_cmode,
240 'NetAppCmodeClient')
241 client1 = self.library._get_api_client(vserver=fake.VSERVER1)
242 self.assertIsNotNone(client1)
243 mock_client_constructor.assert_called_once_with(**client_kwargs)
245 # Second call should yield the same object.
246 mock_client_constructor = self.mock_object(client_cmode,
247 'NetAppCmodeClient')
248 client2 = self.library._get_api_client(vserver=fake.VSERVER1)
249 self.assertEqual(client1, client2)
250 self.assertFalse(mock_client_constructor.called)
252 # A different vserver should work normally without caching.
253 mock_client_constructor = self.mock_object(client_cmode,
254 'NetAppCmodeClient')
255 client3 = self.library._get_api_client(vserver=fake.VSERVER2)
256 self.assertNotEqual(client1, client3)
257 client_kwargs['vserver'] = fake.VSERVER2
258 mock_client_constructor.assert_called_once_with(**client_kwargs)
260 def test_get_licenses_both_protocols(self):
261 self.library._have_cluster_creds = True
262 self.mock_object(self.client,
263 'get_licenses',
264 mock.Mock(return_value=fake.LICENSES))
266 result = self.library._get_licenses()
268 self.assertSequenceEqual(fake.LICENSES, result)
269 self.assertEqual(0, lib_base.LOG.error.call_count)
270 self.assertEqual(1, lib_base.LOG.info.call_count)
272 def test_get_licenses_one_protocol(self):
273 self.library._have_cluster_creds = True
274 licenses = list(fake.LICENSES)
275 licenses.remove('nfs')
276 self.mock_object(self.client,
277 'get_licenses',
278 mock.Mock(return_value=licenses))
280 result = self.library._get_licenses()
282 self.assertListEqual(licenses, result)
283 self.assertEqual(0, lib_base.LOG.error.call_count)
284 self.assertEqual(1, lib_base.LOG.info.call_count)
286 def test_get_licenses_no_protocols(self):
287 self.library._have_cluster_creds = True
288 licenses = list(fake.LICENSES)
289 licenses.remove('nfs')
290 licenses.remove('cifs')
291 self.mock_object(self.client,
292 'get_licenses',
293 mock.Mock(return_value=licenses))
295 result = self.library._get_licenses()
297 self.assertListEqual(licenses, result)
298 self.assertEqual(1, lib_base.LOG.error.call_count)
299 self.assertEqual(1, lib_base.LOG.info.call_count)
301 def test_get_licenses_no_cluster_creds(self):
302 self.library._have_cluster_creds = False
304 result = self.library._get_licenses()
306 self.assertListEqual([], result)
307 self.assertEqual(1, lib_base.LOG.debug.call_count)
309 def test_start_periodic_tasks(self):
311 mock_update_ssc_info = self.mock_object(self.library,
312 '_update_ssc_info')
313 mock_handle_ems_logging = self.mock_object(self.library,
314 '_handle_ems_logging')
315 mock_handle_housekeeping_tasks = self.mock_object(
316 self.library, '_handle_housekeeping_tasks')
317 mock_ssc_periodic_task = mock.Mock()
318 mock_ems_periodic_task = mock.Mock()
319 mock_housekeeping_periodic_task = mock.Mock()
320 mock_loopingcall = self.mock_object(
321 loopingcall,
322 'FixedIntervalLoopingCall',
323 mock.Mock(side_effect=[mock_ssc_periodic_task,
324 mock_ems_periodic_task,
325 mock_housekeeping_periodic_task]))
327 self.library._start_periodic_tasks()
329 self.assertTrue(mock_update_ssc_info.called)
330 self.assertFalse(mock_handle_ems_logging.called)
331 self.assertFalse(mock_housekeeping_periodic_task.called)
332 mock_loopingcall.assert_has_calls(
333 [mock.call(mock_update_ssc_info),
334 mock.call(mock_handle_ems_logging),
335 mock.call(mock_handle_housekeeping_tasks)])
336 self.assertTrue(mock_ssc_periodic_task.start.called)
337 self.assertTrue(mock_ems_periodic_task.start.called)
338 self.assertTrue(mock_housekeeping_periodic_task.start.called)
340 def test_get_backend_share_name(self):
342 result = self.library._get_backend_share_name(fake.SHARE_ID)
343 expected = (fake.VOLUME_NAME_TEMPLATE %
344 {'share_id': fake.SHARE_ID.replace('-', '_')})
346 self.assertEqual(expected, result)
348 def test_get_backend_snapshot_name(self):
350 result = self.library._get_backend_snapshot_name(fake.SNAPSHOT_ID)
351 expected = 'share_snapshot_' + fake.SNAPSHOT_ID.replace('-', '_')
353 self.assertEqual(expected, result)
355 def test_get_backend_cg_snapshot_name(self):
357 result = self.library._get_backend_cg_snapshot_name(fake.SNAPSHOT_ID)
358 expected = 'share_cg_snapshot_' + fake.SNAPSHOT_ID.replace('-', '_')
360 self.assertEqual(expected, result)
362 def test__get_backend_snapmirror_policy_name_svm(self):
363 result = self.library._get_backend_snapmirror_policy_name_svm(
364 fake.SERVER_ID)
365 expected = 'snapmirror_policy_' + fake.SERVER_ID.replace('-', '_')
367 self.assertEqual(expected, result)
369 def test_get_aggregate_space_cluster_creds(self):
371 self.library._have_cluster_creds = True
372 self.mock_object(self.library._client,
373 'get_cluster_aggregate_capacities',
374 mock.Mock(return_value=fake.AGGREGATE_CAPACITIES))
376 result = self.library._get_aggregate_space(fake.AGGREGATES)
378 (self.library._client.get_cluster_aggregate_capacities.
379 assert_called_once_with(fake.AGGREGATES))
380 self.assertDictEqual(fake.AGGREGATE_CAPACITIES, result)
382 def test_get_aggregate_space_no_cluster_creds(self):
384 self.library._have_cluster_creds = False
385 self.mock_object(self.library._client,
386 'get_vserver_aggregate_capacities',
387 mock.Mock(return_value=fake.AGGREGATE_CAPACITIES))
389 result = self.library._get_aggregate_space(fake.AGGREGATES)
391 (self.library._client.get_vserver_aggregate_capacities.
392 assert_called_once_with(fake.AGGREGATES))
393 self.assertDictEqual(fake.AGGREGATE_CAPACITIES, result)
395 def test_check_snaprestore_license_admin_notfound(self):
396 self.library._have_cluster_creds = True
397 licenses = list(fake.LICENSES)
398 licenses.remove('snaprestore')
399 self.mock_object(self.client,
400 'get_licenses',
401 mock.Mock(return_value=licenses))
402 result = self.library._check_snaprestore_license()
403 self.assertIs(False, result)
405 def test_check_snaprestore_license_admin_found(self):
406 self.library._have_cluster_creds = True
407 self.library._licenses = fake.LICENSES
408 result = self.library._check_snaprestore_license()
409 self.assertIs(True, result)
411 def test_check_snaprestore_license_svm_scoped(self):
412 self.library._have_cluster_creds = False
413 self.mock_object(self.library._client,
414 'check_snaprestore_license',
415 mock.Mock(return_value=True))
417 result = self.library._check_snaprestore_license()
419 self.assertIs(True, result)
421 def test_get_aggregate_node_cluster_creds(self):
423 self.library._have_cluster_creds = True
424 self.mock_object(self.library._client,
425 'get_node_for_aggregate',
426 mock.Mock(return_value=fake.CLUSTER_NODE))
428 result = self.library._get_aggregate_node(fake.AGGREGATE)
430 (self.library._client.get_node_for_aggregate.
431 assert_called_once_with(fake.AGGREGATE))
432 self.assertEqual(fake.CLUSTER_NODE, result)
434 def test_get_aggregate_node_no_cluster_creds(self):
436 self.library._have_cluster_creds = False
437 self.mock_object(self.library._client, 'get_node_for_aggregate')
439 result = self.library._get_aggregate_node(fake.AGGREGATE)
441 self.assertFalse(self.library._client.get_node_for_aggregate.called)
442 self.assertIsNone(result)
444 def test_get_default_filter_function(self):
446 result = self.library.get_default_filter_function()
448 self.assertEqual(self.library.DEFAULT_FILTER_FUNCTION, result)
450 def test_get_default_filter_function_flexgroup(self):
451 mock_is_flexgroup = self.mock_object(
452 self.library, '_is_flexgroup_pool',
453 mock.Mock(return_value=True))
454 mock_get_min = self.mock_object(
455 self.library, '_get_minimum_flexgroup_size',
456 mock.Mock(return_value=self.library.FLEXGROUP_MIN_SIZE_PER_AGGR))
458 result = self.library.get_default_filter_function(pool=fake.POOL_NAME)
460 expected_filer = (self.library.DEFAULT_FLEXGROUP_FILTER_FUNCTION %
461 self.library.FLEXGROUP_MIN_SIZE_PER_AGGR)
462 self.assertEqual(expected_filer, result)
463 mock_is_flexgroup.assert_called_once_with(fake.POOL_NAME)
464 mock_get_min.assert_called_once_with(fake.POOL_NAME)
466 def test_get_default_goodness_function(self):
468 result = self.library.get_default_goodness_function()
470 self.assertEqual(self.library.DEFAULT_GOODNESS_FUNCTION, result)
472 @ddt.data(
473 {'replication': True, 'flexgroup': False},
474 {'replication': True, 'flexgroup': True},
475 {'replication': False, 'flexgroup': False},
476 {'replication': False, 'flexgroup': True},
477 )
478 @ddt.unpack
479 def test_get_share_stats(self, replication, flexgroup):
481 if replication:
482 self.library.configuration.replication_domain = "fake_domain"
483 if flexgroup:
484 self.library._flexgroup_pools = {'pool': ['aggr']}
486 mock_get_pools = self.mock_object(
487 self.library, '_get_pools',
488 mock.Mock(return_value=fake.POOLS))
490 result = self.library.get_share_stats(get_filter_function='filter',
491 goodness_function='goodness')
493 expected = {
494 'share_backend_name': fake.BACKEND_NAME,
495 'driver_name': fake.DRIVER_NAME,
496 'vendor_name': 'NetApp',
497 'driver_version': '1.0',
498 'netapp_storage_family': 'ontap_cluster',
499 'storage_protocol': 'NFS_CIFS',
500 'pools': fake.POOLS,
501 'share_group_stats': {'consistent_snapshot_support': 'host'},
502 }
503 if flexgroup:
504 expected['share_group_stats']['consistent_snapshot_support'] = None
505 if replication:
506 expected['replication_type'] = ['dr', 'readable']
507 expected['replication_domain'] = 'fake_domain'
509 self.assertDictEqual(expected, result)
510 mock_get_pools.assert_called_once_with(get_filter_function='filter',
511 goodness_function='goodness')
513 def test_get_share_server_pools(self):
515 self.mock_object(self.library,
516 '_get_pools',
517 mock.Mock(return_value=fake.POOLS))
518 self.library._cache_pool_status = na_utils.DataCache(60)
520 result = self.library.get_share_server_pools(fake.SHARE_SERVER)
522 self.assertListEqual(fake.POOLS, result)
524 def test_get_pools(self):
526 fake_total = 1.0
527 fake_free = 1.0
528 fake_used = 1.0
529 fake_pool = copy.deepcopy(fake.POOLS)
530 fake_pool.append(fake.FLEXGROUP_POOL)
531 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
532 mock_find_aggr = self.mock_object(
533 self.library, '_find_matching_aggregates',
534 mock.Mock(return_value=fake.AGGREGATES))
535 mock_get_flexgroup_aggr = self.mock_object(
536 self.library, '_get_flexgroup_aggr_set',
537 mock.Mock(return_value=fake.FLEXGROUP_AGGR_SET))
538 mock_get_aggregate_space = self.mock_object(
539 self.library, '_get_aggregate_space',
540 mock.Mock(return_value=fake.AGGREGATE_CAPACITIES))
541 mock_get_flexvol_space = self.mock_object(
542 self.library, '_get_flexvol_pool_space',
543 mock.Mock(return_value=(fake_total, fake_free, fake_used)))
544 mock_get_pool = self.mock_object(
545 self.library, '_get_pool',
546 mock.Mock(side_effect=fake_pool))
547 mock_get_flexgroup_space = self.mock_object(
548 self.library, '_get_flexgroup_pool_space',
549 mock.Mock(return_value=(fake_total, fake_free, fake_used)))
550 mock_get_cluster_name = self.mock_object(
551 self.library._client, 'get_cluster_name',
552 mock.Mock(return_value='fake_cluster_name'))
554 self.library._cache_pool_status = na_utils.DataCache(60)
555 self.library._have_cluster_creds = True
556 result = self.library._get_pools(
557 get_filter_function=fake.fake_get_filter_function,
558 goodness_function='goodness')
559 self.assertListEqual(fake_pool, result)
560 mock_find_aggr.assert_called_once_with()
561 mock_get_flexgroup_aggr.assert_called_once_with()
562 mock_get_aggregate_space.assert_called_once_with(set(fake.AGGREGATES))
563 mock_get_flexvol_space.assert_has_calls([
564 mock.call(fake.AGGREGATE_CAPACITIES, fake.AGGREGATES[0]),
565 mock.call(fake.AGGREGATE_CAPACITIES, fake.AGGREGATES[1])])
566 mock_get_flexgroup_space.assert_has_calls([
567 mock.call(fake.AGGREGATE_CAPACITIES,
568 fake.FLEXGROUP_POOL_OPT[fake.FLEXGROUP_POOL_NAME])])
569 mock_get_cluster_name.assert_called_once_with()
570 mock_get_pool.assert_has_calls([
571 mock.call(fake.AGGREGATES[0], fake_total, fake_free, fake_used),
572 mock.call(fake.AGGREGATES[1], fake_total, fake_free, fake_used),
573 mock.call(fake.FLEXGROUP_POOL_NAME, fake_total, fake_free,
574 fake_used)])
576 def test_get_pool_vserver_creds(self):
578 fake_pool = fake.POOLS_VSERVER_CREDS[0]
579 self.library._have_cluster_creds = False
580 self.library._revert_to_snapshot_support = True
581 self.library._cluster_info = fake.CLUSTER_INFO
582 self.library._ssc_stats = fake.SSC_INFO_VSERVER_CREDS
583 self.library._perf_library.get_node_utilization_for_pool = (
584 mock.Mock(return_value=50.0))
585 self.mock_object(self.library,
586 '_get_aggregate_snaplock_type',
587 mock.Mock(return_value="compliance"))
588 result = self.library._get_pool(
589 fake_pool['pool_name'], fake_pool['total_capacity_gb'],
590 fake_pool['free_capacity_gb'], fake_pool['allocated_capacity_gb'])
592 self.assertEqual(fake_pool, result)
594 def test_get_pool_cluster_creds(self):
596 fake_pool = copy.deepcopy(fake.POOLS[0])
597 fake_pool['filter_function'] = None
598 fake_pool['goodness_function'] = None
599 fake_pool['netapp_cluster_name'] = ''
600 self.library._have_cluster_creds = True
601 self.library._revert_to_snapshot_support = True
602 self.library._cluster_info = fake.CLUSTER_INFO
603 self.library._ssc_stats = fake.SSC_INFO
604 self.library._perf_library.get_node_utilization_for_pool = (
605 mock.Mock(return_value=30.0))
606 self.mock_object(self.library,
607 '_get_aggregate_snaplock_type',
608 mock.Mock(return_value="compliance"))
610 result = self.library._get_pool(
611 fake_pool['pool_name'], fake_pool['total_capacity_gb'],
612 fake_pool['free_capacity_gb'], fake_pool['allocated_capacity_gb'])
614 self.assertEqual(fake_pool, result)
616 def test_get_flexvol_pool_space(self):
618 total_gb, free_gb, used_gb = self.library._get_flexvol_pool_space(
619 fake.AGGREGATE_CAPACITIES, fake.AGGREGATES[0])
620 self.mock_object(self.library,
621 '_get_aggregate_snaplock_type',
622 mock.Mock(return_value="compliance"))
624 self.assertEqual(total_gb, fake.POOLS[0]['total_capacity_gb'])
625 self.assertEqual(free_gb, fake.POOLS[0]['free_capacity_gb'])
626 self.assertEqual(used_gb, fake.POOLS[0]['allocated_capacity_gb'])
628 def test_get_flexgroup_pool_space(self):
630 total_gb, free_gb, used_gb = self.library._get_flexgroup_pool_space(
631 fake.AGGREGATE_CAPACITIES, fake.FLEXGROUP_POOL_AGGR)
633 self.assertEqual(total_gb, fake.FLEXGROUP_POOL['total_capacity_gb'])
634 self.assertEqual(free_gb, fake.FLEXGROUP_POOL['free_capacity_gb'])
635 self.assertEqual(used_gb, fake.FLEXGROUP_POOL['allocated_capacity_gb'])
637 @ddt.data(
638 {'aggr_space': fake.AGGREGATE_CAPACITIES, 'aggr_pool': []},
639 {'aggr_space': fake.AGGREGATE_CAPACITIES, 'aggr_pool': ['fake']},
640 {'aggr_space': {fake.AGGREGATES[0]: {}},
641 'aggr_pool': [fake.AGGREGATES[0]]})
642 @ddt.unpack
643 def test_get_flexgroup_pool_space_zero(self, aggr_space, aggr_pool):
645 total_gb, free_gb, used_gb = self.library._get_flexgroup_pool_space(
646 aggr_space, aggr_pool)
648 self.assertEqual(total_gb, 0.0)
649 self.assertEqual(free_gb, 0.0)
650 self.assertEqual(used_gb, 0.0)
652 def test_get_flexgroup_aggr_set(self):
654 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
656 result = self.library._get_flexgroup_aggr_set()
658 self.assertSetEqual(result, set(fake.FLEXGROUP_POOL_AGGR))
660 def test_handle_ems_logging(self):
662 self.mock_object(self.library,
663 '_build_ems_log_message_0',
664 mock.Mock(return_value=fake.EMS_MESSAGE_0))
665 self.mock_object(self.library,
666 '_build_ems_log_message_1',
667 mock.Mock(return_value=fake.EMS_MESSAGE_1))
669 self.library._handle_ems_logging()
671 self.library._client.send_ems_log_message.assert_has_calls([
672 mock.call(fake.EMS_MESSAGE_0),
673 mock.call(fake.EMS_MESSAGE_1),
674 ])
676 def test_build_ems_log_message_0(self):
678 self.mock_object(socket,
679 'gethostname',
680 mock.Mock(return_value=fake.HOST_NAME))
682 result = self.library._build_ems_log_message_0()
684 self.assertDictEqual(fake.EMS_MESSAGE_0, result)
686 def test_build_ems_log_message_1(self):
688 pool_info = {
689 'pools': {
690 'vserver': 'fake_vserver',
691 'aggregates': ['aggr1', 'aggr2'],
692 },
693 }
694 self.mock_object(socket,
695 'gethostname',
696 mock.Mock(return_value=fake.HOST_NAME))
697 self.mock_object(self.library,
698 '_get_ems_pool_info',
699 mock.Mock(return_value=pool_info))
701 result = self.library._build_ems_log_message_1()
703 self.assertDictEqual(pool_info,
704 json.loads(result['event-description']))
705 result['event-description'] = ''
706 self.assertDictEqual(fake.EMS_MESSAGE_1, result)
708 def test_get_ems_pool_info(self):
709 self.assertRaises(NotImplementedError,
710 self.library._get_ems_pool_info)
712 def test_find_matching_aggregates(self):
713 self.assertRaises(NotImplementedError,
714 self.library._find_matching_aggregates)
716 @ddt.data(('NFS', nfs_cmode.NetAppCmodeNFSHelper),
717 ('nfs', nfs_cmode.NetAppCmodeNFSHelper),
718 ('CIFS', cifs_cmode.NetAppCmodeCIFSHelper),
719 ('cifs', cifs_cmode.NetAppCmodeCIFSHelper))
720 @ddt.unpack
721 def test_get_helper(self, protocol, helper_type):
723 fake_share = fake.SHARE.copy()
724 fake_share['share_proto'] = protocol
725 mock_check_license_for_protocol = self.mock_object(
726 self.library, '_check_license_for_protocol')
728 result = self.library._get_helper(fake_share)
730 mock_check_license_for_protocol.assert_called_once_with(
731 protocol.lower())
732 self.assertEqual(helper_type, type(result))
734 def test_get_helper_invalid_protocol(self):
736 fake_share = fake.SHARE.copy()
737 fake_share['share_proto'] = 'iSCSI'
738 self.mock_object(self.library, '_check_license_for_protocol')
740 self.assertRaises(exception.NetAppException,
741 self.library._get_helper,
742 fake_share)
744 def test_check_license_for_protocol_no_cluster_creds(self):
746 self.library._have_cluster_creds = False
748 result = self.library._check_license_for_protocol('fake_protocol')
750 self.assertIsNone(result)
752 def test_check_license_for_protocol_have_license(self):
754 self.library._have_cluster_creds = True
755 self.library._licenses = ['base', 'fake_protocol']
757 result = self.library._check_license_for_protocol('FAKE_PROTOCOL')
759 self.assertIsNone(result)
761 def test_check_license_for_protocol_newly_licensed_protocol(self):
763 self.library._have_cluster_creds = True
764 self.mock_object(self.library,
765 '_get_licenses',
766 mock.Mock(return_value=['base', 'nfs']))
767 self.library._licenses = ['base']
769 result = self.library._check_license_for_protocol('NFS')
771 self.assertIsNone(result)
772 self.assertTrue(self.library._get_licenses.called)
774 def test_check_license_for_protocol_unlicensed_protocol(self):
776 self.library._have_cluster_creds = True
777 self.mock_object(self.library,
778 '_get_licenses',
779 mock.Mock(return_value=['base']))
780 self.library._licenses = ['base']
782 self.assertRaises(exception.NetAppException,
783 self.library._check_license_for_protocol,
784 'NFS')
786 def test_get_pool_has_pool(self):
787 result = self.library.get_pool(fake.SHARE)
788 self.assertEqual(fake.POOL_NAME, result)
789 self.assertFalse(self.client.get_aggregate_for_volume.called)
791 @ddt.data(True, False)
792 def test_get_pool_no_pool(self, is_flexgroup):
794 fake_share = copy.deepcopy(fake.SHARE)
795 fake_share['host'] = '%(host)s@%(backend)s' % {
796 'host': fake.HOST_NAME, 'backend': fake.BACKEND_NAME}
797 self.mock_object(self.library,
798 '_get_flexgroup_pool_name',
799 mock.Mock(return_value=fake.POOL_NAME))
800 if is_flexgroup:
801 self.client.get_aggregate_for_volume.return_value = [
802 fake.POOL_NAME]
803 else:
804 self.client.get_aggregate_for_volume.return_value = fake.POOL_NAME
806 result = self.library.get_pool(fake_share)
808 self.assertEqual(fake.POOL_NAME, result)
809 self.assertTrue(self.client.get_aggregate_for_volume.called)
810 self.assertEqual(is_flexgroup,
811 self.library._get_flexgroup_pool_name.called)
813 @ddt.data(True, False)
814 def test_get_pool_raises(self, is_flexgroup):
816 fake_share = copy.deepcopy(fake.SHARE)
817 fake_share['host'] = '%(host)s@%(backend)s' % {
818 'host': fake.HOST_NAME, 'backend': fake.BACKEND_NAME}
819 self.mock_object(self.library,
820 '_get_flexgroup_pool_name',
821 mock.Mock(return_value=None))
822 if is_flexgroup:
823 self.client.get_aggregate_for_volume.return_value = []
824 else:
825 self.client.get_aggregate_for_volume.return_value = None
827 self.assertRaises(exception.NetAppException,
828 self.library.get_pool,
829 fake_share)
831 def test_create_share(self):
833 vserver_client = mock.Mock()
834 self.mock_object(self.library,
835 '_get_vserver',
836 mock.Mock(return_value=(fake.VSERVER1,
837 vserver_client)))
838 mock_allocate_container = self.mock_object(self.library,
839 '_allocate_container')
840 mock_create_export = self.mock_object(
841 self.library,
842 '_create_export',
843 mock.Mock(return_value='fake_export_location'))
845 result = self.library.create_share(self.context,
846 fake.SHARE,
847 share_server=fake.SHARE_SERVER)
849 mock_allocate_container.assert_called_once_with(fake.SHARE,
850 fake.VSERVER1,
851 vserver_client)
852 mock_create_export.assert_called_once_with(fake.SHARE,
853 fake.SHARE_SERVER,
854 fake.VSERVER1,
855 vserver_client)
856 self.assertEqual('fake_export_location', result)
858 @ddt.data(None, fake.CG_SNAPSHOT_MEMBER_ID1)
859 def test_create_share_from_snapshot(self, share_group_id):
861 share = copy.deepcopy(fake.SHARE)
862 share['source_share_group_snapshot_member_id'] = share_group_id
863 vserver_client = mock.Mock()
864 self.mock_object(self.library,
865 '_get_vserver',
866 mock.Mock(return_value=(fake.VSERVER1,
867 vserver_client)))
868 mock_allocate_container_from_snapshot = self.mock_object(
869 self.library,
870 '_allocate_container_from_snapshot')
871 mock_create_export = self.mock_object(
872 self.library,
873 '_create_export',
874 mock.Mock(return_value='fake_export_location'))
876 result = self.library.create_share_from_snapshot(
877 self.context,
878 share,
879 fake.SNAPSHOT,
880 share_server=fake.SHARE_SERVER,
881 parent_share=share)
883 mock_allocate_container_from_snapshot.assert_called_once_with(
884 share,
885 fake.SNAPSHOT,
886 fake.VSERVER1,
887 vserver_client)
888 mock_create_export.assert_called_once_with(share,
889 fake.SHARE_SERVER,
890 fake.VSERVER1,
891 vserver_client)
892 self.assertEqual('fake_export_location', result)
894 def _setup_mocks_for_create_share_from_snapshot(
895 self, allocate_attr=None, dest_cluster=fake.CLUSTER_NAME,
896 is_flexgroup=False, flexgroup_error=False):
897 class FakeDBObj(dict):
898 def to_dict(self):
899 return self
901 if allocate_attr is None:
902 allocate_attr = mock.Mock()
904 self.src_vserver_client = mock.Mock()
905 self.mock_dm_session = mock.Mock()
906 self.fake_share = FakeDBObj(fake.SHARE)
907 self.fake_share_server = FakeDBObj(fake.SHARE_SERVER)
909 self.mock_dm_constr = self.mock_object(
910 data_motion, "DataMotionSession",
911 mock.Mock(return_value=self.mock_dm_session))
912 self.mock_dm_backend = self.mock_object(
913 self.mock_dm_session, 'get_backend_info_for_share',
914 mock.Mock(return_value=(None,
915 fake.VSERVER1, fake.BACKEND_NAME)))
916 self.mock_dm_get_src_client = self.mock_object(
917 data_motion, 'get_client_for_backend',
918 mock.Mock(return_value=self.src_vserver_client))
919 self.mock_get_src_cluster = self.mock_object(
920 self.src_vserver_client, 'get_cluster_name',
921 mock.Mock(return_value=fake.CLUSTER_NAME))
922 self.dest_vserver_client = mock.Mock()
923 self.mock_get_vserver = self.mock_object(
924 self.library, '_get_vserver',
925 mock.Mock(return_value=(fake.VSERVER2, self.dest_vserver_client)))
926 self.mock_get_dest_cluster = self.mock_object(
927 self.dest_vserver_client, 'get_cluster_name',
928 mock.Mock(return_value=dest_cluster))
929 self.mock_extract_host = self.mock_object(
930 share_utils, 'extract_host',
931 mock.Mock(return_value=fake.POOL_NAME))
932 self.mock_is_flexgroup_share = self.mock_object(
933 self.library, '_is_flexgroup_share',
934 mock.Mock(return_value=is_flexgroup))
935 self.mock_is_flexgroup_pool = self.mock_object(
936 self.library, '_is_flexgroup_pool',
937 mock.Mock(return_value=(not is_flexgroup if flexgroup_error
938 else is_flexgroup)))
939 self.mock_get_aggregate_for_volume = self.mock_object(
940 self.src_vserver_client, 'get_aggregate_for_volume',
941 mock.Mock(return_value=[fake.POOL_NAME]))
942 self.mock_get_flexgroup_aggregate_list = self.mock_object(
943 self.library, '_get_flexgroup_aggregate_list',
944 mock.Mock(return_value=[fake.POOL_NAME]))
945 self.mock_allocate_container_from_snapshot = self.mock_object(
946 self.library, '_allocate_container_from_snapshot', allocate_attr)
947 self.mock_allocate_container = self.mock_object(
948 self.library, '_allocate_container')
949 self.mock_get_relationship_type = self.mock_object(
950 na_utils, 'get_relationship_type',
951 mock.Mock(return_value=(na_utils.EXTENDED_DATA_PROTECTION_TYPE
952 if is_flexgroup
953 else na_utils.DATA_PROTECTION_TYPE)))
954 self.mock_dm_create_snapmirror = self.mock_object(
955 self.mock_dm_session, 'create_snapmirror')
956 self.mock_storage_update = self.mock_object(
957 self.library.private_storage, 'update')
958 self.mock_generate_uuid = self.mock_object(
959 uuidutils, 'generate_uuid', mock.Mock(return_value=fake.SHARE_ID5))
961 # Parent share on MANILA_HOST_2
962 self.parent_share = copy.copy(fake.SHARE)
963 self.parent_share['share_server'] = fake.SHARE_SERVER_2
964 self.parent_share['host'] = fake.MANILA_HOST_NAME_2
965 self.parent_share_server = {}
966 ss_keys = ['id', 'identifier', 'backend_details', 'host']
967 for key in ss_keys:
968 self.parent_share_server[key] = (
969 self.parent_share['share_server'].get(key, None))
970 self.temp_src_share = {
971 'id': self.fake_share['id'],
972 'host': self.parent_share['host'],
973 'share_server': self.parent_share_server or None
974 }
976 @ddt.data({'dest_cluster': fake.CLUSTER_NAME, 'is_flexgroup': False,
977 'have_cluster_creds': False},
978 {'dest_cluster': fake.CLUSTER_NAME, 'is_flexgroup': False,
979 'have_cluster_creds': True},
980 {'dest_cluster': fake.CLUSTER_NAME, 'is_flexgroup': True,
981 'have_cluster_creds': False},
982 {'dest_cluster': fake.CLUSTER_NAME_2, 'is_flexgroup': False,
983 'have_cluster_creds': False},
984 {'dest_cluster': fake.CLUSTER_NAME_2, 'is_flexgroup': False,
985 'have_cluster_creds': True},
986 )
987 @ddt.unpack
988 def test_create_share_from_snapshot_another_host(self, dest_cluster,
989 is_flexgroup,
990 have_cluster_creds):
991 self.library._have_cluster_creds = have_cluster_creds
992 self._setup_mocks_for_create_share_from_snapshot(
993 dest_cluster=dest_cluster, is_flexgroup=is_flexgroup)
994 mock_get_backend_shr_name = self.mock_object(
995 self.library, '_get_backend_share_name',
996 mock.Mock(return_value=fake.SHARE_NAME))
997 result = self.library.create_share_from_snapshot(
998 self.context,
999 self.fake_share,
1000 fake.SNAPSHOT,
1001 share_server=self.fake_share_server,
1002 parent_share=self.parent_share)
1004 self.fake_share['share_server'] = self.fake_share_server
1006 self.mock_dm_constr.assert_called_once()
1007 self.mock_dm_backend.assert_called_once_with(self.parent_share)
1008 self.mock_dm_get_src_client.assert_called_once_with(
1009 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1011 self.mock_get_vserver.assert_called_once_with(self.fake_share_server)
1012 if have_cluster_creds:
1013 self.mock_get_dest_cluster.assert_called_once()
1014 self.mock_get_src_cluster.assert_called_once()
1015 else:
1016 self.mock_get_dest_cluster.assert_not_called()
1017 self.mock_get_src_cluster.assert_not_called()
1018 mock_get_backend_shr_name.assert_called_once()
1019 self.mock_is_flexgroup_share.assert_called_once()
1020 self.mock_is_flexgroup_pool.assert_called_once()
1021 self.assertEqual(is_flexgroup,
1022 self.mock_get_aggregate_for_volume.called)
1023 self.assertEqual(is_flexgroup,
1024 self.mock_get_flexgroup_aggregate_list.called)
1026 if (dest_cluster != fake.CLUSTER_NAME
1027 or is_flexgroup or not have_cluster_creds):
1028 temp_share = copy.deepcopy(self.fake_share)
1029 temp_share["id"] = fake.SHARE_ID5
1030 self.mock_allocate_container_from_snapshot.assert_called_once_with(
1031 temp_share, fake.SNAPSHOT, fake.VSERVER1,
1032 self.src_vserver_client, split=False, create_fpolicy=False)
1033 self.mock_allocate_container.assert_called_once_with(
1034 self.fake_share, fake.VSERVER2,
1035 self.dest_vserver_client, replica=True, set_qos=False)
1036 self.mock_dm_create_snapmirror.assert_called_once()
1037 self.temp_src_share['replica_state'] = (
1038 constants.REPLICA_STATE_ACTIVE)
1039 state = self.library.STATE_SNAPMIRROR_DATA_COPYING
1040 else:
1041 self.mock_allocate_container_from_snapshot.assert_called_once_with(
1042 self.fake_share, fake.SNAPSHOT, fake.VSERVER1,
1043 self.src_vserver_client, split=True)
1044 state = self.library.STATE_SPLITTING_VOLUME_CLONE
1046 self.temp_src_share['aggregate'] = ([fake.POOL_NAME]
1047 if is_flexgroup
1048 else fake.POOL_NAME)
1049 self.temp_src_share['internal_state'] = state
1050 self.temp_src_share['status'] = constants.STATUS_ACTIVE
1051 str_temp_src_share = json.dumps(self.temp_src_share)
1052 self.mock_storage_update.assert_called_once_with(
1053 self.fake_share['id'], {
1054 'source_share': str_temp_src_share
1055 })
1056 expected_return = {'status':
1057 constants.STATUS_CREATING_FROM_SNAPSHOT}
1058 self.assertEqual(expected_return, result)
1060 @ddt.data(True, False)
1061 def test_create_share_from_snapshot_another_host_driver_error(
1062 self, have_cluster_creds):
1063 self.library._have_cluster_creds = have_cluster_creds
1064 self._setup_mocks_for_create_share_from_snapshot(
1065 allocate_attr=mock.Mock(side_effect=exception.NetAppException))
1066 mock_delete_snapmirror = self.mock_object(
1067 self.mock_dm_session, 'delete_snapmirror')
1069 mock_delete_share = self.mock_object(
1070 self.library, '_delete_share')
1072 self.assertRaises(exception.NetAppException,
1073 self.library.create_share_from_snapshot,
1074 self.context,
1075 self.fake_share,
1076 fake.SNAPSHOT,
1077 share_server=self.fake_share_server,
1078 parent_share=self.parent_share)
1080 self.fake_share['share_server'] = self.fake_share_server
1082 self.mock_dm_constr.assert_called_once()
1083 self.mock_dm_backend.assert_called_once_with(self.parent_share)
1084 self.mock_dm_get_src_client.assert_called_once_with(
1085 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1086 self.mock_get_vserver.assert_called_once_with(self.fake_share_server)
1087 if have_cluster_creds:
1088 self.mock_get_dest_cluster.assert_called_once()
1089 self.mock_get_src_cluster.assert_called_once()
1090 else:
1091 self.mock_get_dest_cluster.assert_not_called()
1092 self.mock_get_src_cluster.assert_not_called()
1094 if have_cluster_creds:
1095 self.mock_allocate_container_from_snapshot.assert_called_once_with(
1096 self.fake_share, fake.SNAPSHOT, fake.VSERVER1,
1097 self.src_vserver_client, split=True)
1098 else:
1099 self.mock_generate_uuid.assert_called_once()
1100 temp_share = copy.deepcopy(self.fake_share)
1101 temp_share["id"] = fake.SHARE_ID5
1102 self.mock_allocate_container_from_snapshot.assert_called_once_with(
1103 temp_share, fake.SNAPSHOT, fake.VSERVER1,
1104 self.src_vserver_client, split=False, create_fpolicy=False)
1106 mock_delete_snapmirror.assert_called_once_with(
1107 self.temp_src_share, self.fake_share)
1109 mock_delete_share.assert_called_once_with(
1110 self.temp_src_share, fake.VSERVER1, self.src_vserver_client,
1111 remove_export=False)
1113 def test_create_share_from_snapshot_different_pool_types(self):
1115 self._setup_mocks_for_create_share_from_snapshot(
1116 dest_cluster=fake.CLUSTER_NAME_2, is_flexgroup=True,
1117 flexgroup_error=True)
1118 self.assertRaises(exception.NetAppException,
1119 self.library.create_share_from_snapshot,
1120 self.context,
1121 self.fake_share,
1122 fake.SNAPSHOT,
1123 share_server=self.fake_share_server,
1124 parent_share=self.parent_share)
1126 def test_create_share_from_snapshot_mismatch_flexgroup_pools_len(self):
1128 self._setup_mocks_for_create_share_from_snapshot(
1129 dest_cluster=fake.CLUSTER_NAME_2, is_flexgroup=True)
1130 self.mock_object(
1131 self.library, '_get_flexgroup_aggregate_list',
1132 mock.Mock(return_value=[]))
1133 self.library._is_flexgroup_auto = False
1134 self.assertRaises(exception.NetAppException,
1135 self.library.create_share_from_snapshot,
1136 self.context,
1137 self.fake_share,
1138 fake.SNAPSHOT,
1139 share_server=self.fake_share_server,
1140 parent_share=self.parent_share)
1142 def test__update_create_from_snapshot_status(self):
1143 fake_result = mock.Mock()
1144 mock_pvt_storage_get = self.mock_object(
1145 self.library.private_storage, 'get',
1146 mock.Mock(return_value=fake.SHARE))
1147 mock__create_continue = self.mock_object(
1148 self.library, '_create_from_snapshot_continue',
1149 mock.Mock(return_value=fake_result))
1151 result = self.library._update_create_from_snapshot_status(
1152 fake.SHARE, fake.SHARE_SERVER)
1154 mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1155 'source_share')
1156 mock__create_continue.assert_called_once_with(fake.SHARE,
1157 fake.SHARE_SERVER)
1158 self.assertEqual(fake_result, result)
1160 def test__update_create_from_snapshot_status_missing_source_share(self):
1161 mock_pvt_storage_get = self.mock_object(
1162 self.library.private_storage, 'get',
1163 mock.Mock(return_value=None))
1164 expected_result = {'status': constants.STATUS_ERROR}
1165 result = self.library._update_create_from_snapshot_status(
1166 fake.SHARE, fake.SHARE_SERVER)
1167 mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1168 'source_share')
1169 self.assertEqual(expected_result, result)
1171 def test__update_create_from_snapshot_status_driver_error(self):
1172 fake_src_share = {
1173 'id': fake.SHARE['id'],
1174 'host': fake.SHARE['host'],
1175 'internal_state': 'fake_internal_state',
1176 }
1177 copy_fake_src_share = copy.deepcopy(fake_src_share)
1178 src_vserver_client = mock.Mock()
1179 mock_dm_session = mock.Mock()
1180 mock_pvt_storage_get = self.mock_object(
1181 self.library.private_storage, 'get',
1182 mock.Mock(return_value=json.dumps(copy_fake_src_share)))
1183 mock__create_continue = self.mock_object(
1184 self.library, '_create_from_snapshot_continue',
1185 mock.Mock(side_effect=exception.NetAppException))
1186 mock_dm_constr = self.mock_object(
1187 data_motion, "DataMotionSession",
1188 mock.Mock(return_value=mock_dm_session))
1189 mock_delete_snapmirror = self.mock_object(
1190 mock_dm_session, 'delete_snapmirror')
1191 mock_dm_backend = self.mock_object(
1192 mock_dm_session, 'get_backend_info_for_share',
1193 mock.Mock(return_value=(None,
1194 fake.VSERVER1, fake.BACKEND_NAME)))
1195 mock_dm_get_src_client = self.mock_object(
1196 data_motion, 'get_client_for_backend',
1197 mock.Mock(return_value=src_vserver_client))
1198 mock_get_backend_shr_name = self.mock_object(
1199 self.library, '_get_backend_share_name',
1200 mock.Mock(return_value=fake.SHARE_NAME))
1201 mock_share_exits = self.mock_object(
1202 self.library, '_share_exists',
1203 mock.Mock(return_value=True))
1204 mock_deallocate_container = self.mock_object(
1205 self.library, '_deallocate_container')
1206 mock_pvt_storage_delete = self.mock_object(
1207 self.library.private_storage, 'delete')
1208 mock_delete_policy = self.mock_object(self.library,
1209 '_delete_fpolicy_for_share')
1211 result = self.library._update_create_from_snapshot_status(
1212 fake.SHARE, fake.SHARE_SERVER)
1213 expected_result = {'status': constants.STATUS_ERROR}
1215 mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1216 'source_share')
1217 mock__create_continue.assert_called_once_with(fake.SHARE,
1218 fake.SHARE_SERVER)
1219 mock_dm_constr.assert_called_once()
1220 mock_delete_snapmirror.assert_called_once_with(fake_src_share,
1221 fake.SHARE)
1222 mock_dm_backend.assert_called_once_with(fake_src_share)
1223 mock_dm_get_src_client.assert_called_once_with(
1224 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1225 mock_get_backend_shr_name.assert_called_once_with(fake_src_share['id'])
1226 mock_share_exits.assert_called_once_with(fake.SHARE_NAME,
1227 src_vserver_client)
1228 mock_deallocate_container.assert_called_once_with(fake.SHARE_NAME,
1229 src_vserver_client)
1230 mock_pvt_storage_delete.assert_called_once_with(fake.SHARE['id'])
1231 mock_delete_policy.assert_called_once_with(fake_src_share,
1232 fake.VSERVER1,
1233 src_vserver_client)
1234 self.assertEqual(expected_result, result)
1236 def _setup_mocks_for_create_from_snapshot_continue(
1237 self, src_host=fake.MANILA_HOST_NAME,
1238 dest_host=fake.MANILA_HOST_NAME, split_completed_result=True,
1239 move_completed_result=True, share_internal_state='fake_state',
1240 replica_state='in_sync', is_flexgroup=False):
1241 self.fake_export_location = 'fake_export_location'
1242 self.fake_src_share = {
1243 'id': fake.SHARE['id'],
1244 'host': src_host,
1245 'aggregate': src_host.split('#')[1],
1246 'internal_state': share_internal_state,
1247 }
1248 self.copy_fake_src_share = copy.deepcopy(self.fake_src_share)
1249 dest_pool = dest_host.split('#')[1]
1250 self.src_vserver_client = mock.Mock()
1251 self.dest_vserver_client = mock.Mock()
1252 self.mock_dm_session = mock.Mock()
1254 self.mock_dm_constr = self.mock_object(
1255 data_motion, "DataMotionSession",
1256 mock.Mock(return_value=self.mock_dm_session))
1257 self.mock_pvt_storage_get = self.mock_object(
1258 self.library.private_storage, 'get',
1259 mock.Mock(return_value=json.dumps(self.copy_fake_src_share)))
1260 self.mock_dm_backend = self.mock_object(
1261 self.mock_dm_session, 'get_backend_info_for_share',
1262 mock.Mock(return_value=(None,
1263 fake.VSERVER1, fake.BACKEND_NAME)))
1264 self.mock_extract_host = self.mock_object(
1265 share_utils, 'extract_host',
1266 mock.Mock(return_value=dest_pool))
1267 self.mock_is_flexgroup_pool = self.mock_object(
1268 self.library, '_is_flexgroup_pool',
1269 mock.Mock(return_value=is_flexgroup))
1270 self.mock_get_flexgroup_aggregate_list = self.mock_object(
1271 self.library, '_get_flexgroup_aggregate_list',
1272 mock.Mock(return_value=dest_pool))
1273 self.mock_dm_get_src_client = self.mock_object(
1274 data_motion, 'get_client_for_backend',
1275 mock.Mock(return_value=self.src_vserver_client))
1276 self.mock_get_vserver = self.mock_object(
1277 self.library, '_get_vserver',
1278 mock.Mock(return_value=(fake.VSERVER2, self.dest_vserver_client)))
1279 self.mock_split_completed = self.mock_object(
1280 self.library, '_check_volume_clone_split_completed',
1281 mock.Mock(return_value=split_completed_result))
1282 self.mock_rehost_vol = self.mock_object(
1283 self.library, '_rehost_and_mount_volume')
1284 self.mock_move_vol = self.mock_object(self.library,
1285 '_move_volume_after_splitting')
1286 self.mock_move_completed = self.mock_object(
1287 self.library, '_check_volume_move_completed',
1288 mock.Mock(return_value=move_completed_result))
1289 self.mock_update_rep_state = self.mock_object(
1290 self.library, 'update_replica_state',
1291 mock.Mock(return_value=replica_state)
1292 )
1293 self.mock_update_snapmirror = self.mock_object(
1294 self.mock_dm_session, 'update_snapmirror')
1295 self.mock_break_snapmirror = self.mock_object(
1296 self.mock_dm_session, 'break_snapmirror')
1297 self.mock_delete_snapmirror = self.mock_object(
1298 self.mock_dm_session, 'delete_snapmirror')
1299 self.mock_get_backend_shr_name = self.mock_object(
1300 self.library, '_get_backend_share_name',
1301 mock.Mock(return_value=fake.SHARE_NAME))
1302 self.mock__delete_share = self.mock_object(self.library,
1303 '_delete_share')
1304 self.mock_set_vol_size_fixes = self.mock_object(
1305 self.dest_vserver_client, 'set_volume_filesys_size_fixed')
1306 self.mock_create_export = self.mock_object(
1307 self.library, '_create_export',
1308 mock.Mock(return_value=self.fake_export_location))
1309 self.mock_pvt_storage_update = self.mock_object(
1310 self.library.private_storage, 'update')
1311 self.mock_pvt_storage_delete = self.mock_object(
1312 self.library.private_storage, 'delete')
1313 self.mock_get_extra_specs_qos = self.mock_object(
1314 share_types, 'get_extra_specs_from_share',
1315 mock.Mock(return_value=fake.EXTRA_SPEC_WITH_QOS))
1316 self.mock__get_provisioning_opts = self.mock_object(
1317 self.library, '_get_provisioning_options',
1318 mock.Mock(return_value=copy.deepcopy(fake.PROVISIONING_OPTIONS))
1319 )
1320 self.mock_modify_create_qos = self.mock_object(
1321 self.library, '_modify_or_create_qos_for_existing_share',
1322 mock.Mock(return_value=fake.QOS_POLICY_GROUP_NAME))
1323 self.mock_modify_vol = self.mock_object(self.dest_vserver_client,
1324 'modify_volume')
1325 self.mock_get_backend_qos_name = self.mock_object(
1326 self.library, '_get_backend_qos_policy_group_name',
1327 mock.Mock(return_value=fake.QOS_POLICY_GROUP_NAME))
1328 self.mock_mark_qos_deletion = self.mock_object(
1329 self.src_vserver_client, 'mark_qos_policy_group_for_deletion')
1331 @ddt.data(fake.MANILA_HOST_NAME, fake.MANILA_HOST_NAME_2)
1332 def test__create_from_snapshot_continue_state_splitting(self, src_host):
1333 self._setup_mocks_for_create_from_snapshot_continue(
1334 src_host=src_host,
1335 share_internal_state=self.library.STATE_SPLITTING_VOLUME_CLONE)
1337 result = self.library._create_from_snapshot_continue(fake.SHARE,
1338 fake.SHARE_SERVER)
1339 fake.SHARE['share_server'] = fake.SHARE_SERVER
1340 self.mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1341 'source_share')
1342 self.mock_dm_backend.assert_called_once_with(self.fake_src_share)
1343 self.mock_extract_host.assert_has_calls([
1344 mock.call(fake.SHARE['host'], level='pool')])
1345 self.mock_dm_get_src_client.assert_called_once_with(
1346 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1347 self.mock_get_vserver.assert_called_once_with(fake.SHARE_SERVER)
1348 self.mock_split_completed.assert_called_once_with(
1349 self.fake_src_share, self.src_vserver_client)
1350 self.mock_get_backend_qos_name.assert_called_once_with(fake.SHARE_ID)
1351 self.mock_mark_qos_deletion.assert_called_once_with(
1352 fake.QOS_POLICY_GROUP_NAME)
1353 self.mock_rehost_vol.assert_called_once_with(
1354 fake.SHARE, fake.VSERVER1, self.src_vserver_client,
1355 fake.VSERVER2, self.dest_vserver_client)
1356 if src_host != fake.MANILA_HOST_NAME:
1357 expected_result = {
1358 'status': constants.STATUS_CREATING_FROM_SNAPSHOT
1359 }
1360 self.mock_move_vol.assert_called_once_with(
1361 self.fake_src_share, fake.SHARE, fake.SHARE_SERVER,
1362 cutover_action='defer')
1363 self.fake_src_share['internal_state'] = (
1364 self.library.STATE_MOVING_VOLUME)
1365 self.mock_pvt_storage_update.assert_called_once_with(
1366 fake.SHARE['id'],
1367 {'source_share': json.dumps(self.fake_src_share)}
1368 )
1369 self.assertEqual(expected_result, result)
1370 else:
1371 self.mock_get_extra_specs_qos.assert_called_once_with(fake.SHARE)
1372 self.mock__get_provisioning_opts.assert_called_once_with(
1373 fake.EXTRA_SPEC_WITH_QOS)
1374 self.mock_modify_create_qos.assert_called_once_with(
1375 fake.SHARE, fake.EXTRA_SPEC_WITH_QOS, fake.VSERVER2,
1376 self.dest_vserver_client)
1377 self.mock_get_backend_shr_name.assert_called_once_with(
1378 fake.SHARE_ID)
1379 self.mock_modify_vol.assert_called_once_with(
1380 fake.POOL_NAME, fake.SHARE_NAME,
1381 **fake.PROVISIONING_OPTIONS_WITH_QOS)
1382 self.mock_pvt_storage_delete.assert_called_once_with(
1383 fake.SHARE['id'])
1384 self.mock_create_export.assert_called_once_with(
1385 fake.SHARE, fake.SHARE_SERVER, fake.VSERVER2,
1386 self.dest_vserver_client, clear_current_export_policy=False)
1387 expected_result = {
1388 'status': constants.STATUS_AVAILABLE,
1389 'export_locations': self.fake_export_location,
1390 }
1391 self.assertEqual(expected_result, result)
1393 @ddt.data(True, False)
1394 def test__create_from_snapshot_continue_state_moving(self, move_completed):
1395 self._setup_mocks_for_create_from_snapshot_continue(
1396 share_internal_state=self.library.STATE_MOVING_VOLUME,
1397 move_completed_result=move_completed)
1399 result = self.library._create_from_snapshot_continue(fake.SHARE,
1400 fake.SHARE_SERVER)
1401 expect_result = {
1402 'status': constants.STATUS_CREATING_FROM_SNAPSHOT
1403 }
1404 fake.SHARE['share_server'] = fake.SHARE_SERVER
1405 self.mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1406 'source_share')
1407 self.mock_dm_backend.assert_called_once_with(self.fake_src_share)
1408 self.mock_extract_host.assert_has_calls([
1409 mock.call(fake.SHARE['host'], level='pool'),
1410 ])
1411 self.mock_dm_get_src_client.assert_called_once_with(
1412 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1413 self.mock_get_vserver.assert_called_once_with(fake.SHARE_SERVER)
1415 self.mock_move_completed.assert_called_once_with(
1416 fake.SHARE, fake.SHARE_SERVER)
1417 if move_completed:
1418 expect_result['status'] = constants.STATUS_AVAILABLE
1419 self.mock_pvt_storage_delete.assert_called_once_with(
1420 fake.SHARE['id'])
1421 self.mock_create_export.assert_called_once_with(
1422 fake.SHARE, fake.SHARE_SERVER, fake.VSERVER2,
1423 self.dest_vserver_client, clear_current_export_policy=False)
1424 expect_result['export_locations'] = self.fake_export_location
1425 self.assertEqual(expect_result, result)
1426 else:
1427 self.mock_pvt_storage_update.assert_called_once_with(
1428 fake.SHARE['id'],
1429 {'source_share': json.dumps(self.fake_src_share)}
1430 )
1431 self.assertEqual(expect_result, result)
1433 @ddt.data({'replica_state': 'in_sync', 'is_flexgroup': False},
1434 {'replica_state': 'out_of_sync', 'is_flexgroup': False},
1435 {'replica_state': 'out_of_sync', 'is_flexgroup': True})
1436 @ddt.unpack
1437 def test__create_from_snapshot_continue_state_snapmirror(self,
1438 replica_state,
1439 is_flexgroup):
1440 self._setup_mocks_for_create_from_snapshot_continue(
1441 share_internal_state=self.library.STATE_SNAPMIRROR_DATA_COPYING,
1442 replica_state=replica_state, is_flexgroup=is_flexgroup)
1444 result = self.library._create_from_snapshot_continue(fake.SHARE,
1445 fake.SHARE_SERVER)
1446 expect_result = {
1447 'status': constants.STATUS_CREATING_FROM_SNAPSHOT
1448 }
1449 fake.SHARE['share_server'] = fake.SHARE_SERVER
1450 self.mock_pvt_storage_get.assert_called_once_with(fake.SHARE['id'],
1451 'source_share')
1452 self.mock_dm_backend.assert_called_once_with(self.fake_src_share)
1453 self.mock_extract_host.assert_has_calls([
1454 mock.call(fake.SHARE['host'], level='pool')])
1455 self.mock_dm_get_src_client.assert_called_once_with(
1456 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
1457 self.mock_get_vserver.assert_called_once_with(fake.SHARE_SERVER)
1459 self.mock_update_rep_state.assert_called_once_with(
1460 None, [self.fake_src_share], fake.SHARE, [], [], fake.SHARE_SERVER,
1461 replication=False
1462 )
1463 self.assertEqual(is_flexgroup,
1464 self.mock_get_flexgroup_aggregate_list.called)
1465 if replica_state == constants.REPLICA_STATE_IN_SYNC:
1466 self.mock_update_snapmirror.assert_called_once_with(
1467 self.fake_src_share, fake.SHARE)
1468 self.mock_break_snapmirror.assert_called_once_with(
1469 self.fake_src_share, fake.SHARE)
1470 self.mock_delete_snapmirror.assert_called_once_with(
1471 self.fake_src_share, fake.SHARE)
1472 self.mock_get_backend_shr_name.assert_has_calls(
1473 [mock.call(self.fake_src_share['id']),
1474 mock.call(fake.SHARE_ID)])
1475 self.mock__delete_share.assert_called_once_with(
1476 self.fake_src_share, fake.VSERVER1, self.src_vserver_client,
1477 remove_export=False)
1478 self.mock_set_vol_size_fixes.assert_called_once_with(
1479 fake.SHARE_NAME, filesys_size_fixed=False)
1480 self.mock_get_extra_specs_qos.assert_called_once_with(fake.SHARE)
1481 self.mock__get_provisioning_opts.assert_called_once_with(
1482 fake.EXTRA_SPEC_WITH_QOS)
1483 self.mock_modify_create_qos.assert_called_once_with(
1484 fake.SHARE, fake.EXTRA_SPEC_WITH_QOS, fake.VSERVER2,
1485 self.dest_vserver_client)
1486 self.mock_modify_vol.assert_called_once_with(
1487 fake.POOL_NAME, fake.SHARE_NAME,
1488 **fake.PROVISIONING_OPTIONS_WITH_QOS)
1489 expect_result['status'] = constants.STATUS_AVAILABLE
1490 self.mock_pvt_storage_delete.assert_called_once_with(
1491 fake.SHARE['id'])
1492 self.mock_create_export.assert_called_once_with(
1493 fake.SHARE, fake.SHARE_SERVER, fake.VSERVER2,
1494 self.dest_vserver_client, clear_current_export_policy=False)
1495 expect_result['export_locations'] = self.fake_export_location
1496 self.assertEqual(expect_result, result)
1497 elif replica_state not in [constants.STATUS_ERROR, None]: 1497 ↛ exitline 1497 didn't return from function 'test__create_from_snapshot_continue_state_snapmirror' because the condition on line 1497 was always true
1498 self.mock_pvt_storage_update.assert_called_once_with(
1499 fake.SHARE['id'],
1500 {'source_share': json.dumps(self.fake_src_share)}
1501 )
1502 self.assertEqual(expect_result, result)
1504 def test__create_from_snapshot_continue_state_unknown(self):
1505 self._setup_mocks_for_create_from_snapshot_continue(
1506 share_internal_state='unknown_state')
1508 self.assertRaises(exception.NetAppException,
1509 self.library._create_from_snapshot_continue,
1510 fake.SHARE,
1511 fake.SHARE_SERVER)
1513 self.mock_pvt_storage_delete.assert_called_once_with(fake.SHARE_ID)
1515 @ddt.data({'hide_snapdir': False, 'create_fpolicy': True, 'is_fg': True,
1516 'with_encryption': True},
1517 {'hide_snapdir': True, 'create_fpolicy': False, 'is_fg': True,
1518 'with_encryption': False},
1519 {'hide_snapdir': False, 'create_fpolicy': True, 'is_fg': False,
1520 'with_encryption': True},
1521 {'hide_snapdir': True, 'create_fpolicy': False, 'is_fg': False,
1522 'with_encryption': False})
1523 @ddt.unpack
1524 def test_allocate_container(self, hide_snapdir, create_fpolicy, is_fg,
1525 with_encryption):
1527 provisioning_options = copy.deepcopy(
1528 fake.PROVISIONING_OPTIONS_WITH_FPOLICY)
1529 provisioning_options['hide_snapdir'] = hide_snapdir
1530 provisioning_options['snaplock_type'] = "compliance"
1531 self.mock_object(self.library, '_get_backend_share_name', mock.Mock(
1532 return_value=fake.SHARE_NAME))
1533 self.mock_object(share_utils, 'extract_host', mock.Mock(
1534 return_value=fake.POOL_NAME))
1535 mock_get_provisioning_opts = self.mock_object(
1536 self.library, '_get_provisioning_options_for_share',
1537 mock.Mock(return_value=provisioning_options))
1538 mock_create_fpolicy = self.mock_object(
1539 self.library, '_create_fpolicy_for_share')
1540 self.mock_object(
1541 self.library, '_is_flexgroup_pool', mock.Mock(return_value=is_fg))
1542 mock_create_flexgroup = self.mock_object(self.library,
1543 '_create_flexgroup_share')
1544 mock_get_aggr_flexgroup = self.mock_object(
1545 self.library, '_get_flexgroup_aggregate_list',
1546 mock.Mock(return_value=[fake.AGGREGATE]))
1547 vserver_client = mock.Mock()
1549 fake_share = (
1550 fake.SHARE_INSTANCE_WITH_ENCRYPTION
1551 if with_encryption else fake.SHARE_INSTANCE)
1553 self.library._allocate_container(fake_share,
1554 fake.VSERVER1,
1555 vserver_client,
1556 create_fpolicy=create_fpolicy)
1558 mock_get_provisioning_opts.assert_called_once_with(
1559 fake_share, fake.VSERVER1, vserver_client=vserver_client,
1560 set_qos=True)
1562 if is_fg:
1563 mock_get_aggr_flexgroup.assert_called_once_with(fake.POOL_NAME)
1564 mock_create_flexgroup.assert_called_once_with(
1565 vserver_client, [fake.AGGREGATE], fake.SHARE_NAME,
1566 fake.SHARE['size'], 8, mount_point_name=fake.MOUNT_POINT_NAME,
1567 **provisioning_options)
1568 else:
1569 mock_get_aggr_flexgroup.assert_not_called()
1570 vserver_client.create_volume.assert_called_once_with(
1571 fake.POOL_NAME, fake.SHARE_NAME, fake.SHARE['size'],
1572 snapshot_reserve=8, mount_point_name=fake.MOUNT_POINT_NAME,
1573 **provisioning_options)
1575 if hide_snapdir:
1576 vserver_client.set_volume_snapdir_access.assert_called_once_with(
1577 fake.SHARE_NAME, hide_snapdir)
1578 else:
1579 vserver_client.set_volume_snapdir_access.assert_not_called()
1581 if create_fpolicy:
1582 mock_create_fpolicy.assert_called_once_with(
1583 fake_share, fake.VSERVER1, vserver_client,
1584 **provisioning_options)
1585 else:
1586 mock_create_fpolicy.assert_not_called()
1588 def test_remap_standard_boolean_extra_specs(self):
1590 extra_specs = copy.deepcopy(fake.OVERLAPPING_EXTRA_SPEC)
1592 result = self.library._remap_standard_boolean_extra_specs(extra_specs)
1594 self.assertDictEqual(fake.REMAPPED_OVERLAPPING_EXTRA_SPEC, result)
1596 def test_allocate_container_as_replica(self):
1597 self.mock_object(self.library, '_get_backend_share_name', mock.Mock(
1598 return_value=fake.SHARE_NAME))
1599 self.mock_object(share_utils, 'extract_host', mock.Mock(
1600 return_value=fake.POOL_NAME))
1601 mock_get_provisioning_opts = self.mock_object(
1602 self.library, '_get_provisioning_options_for_share',
1603 mock.Mock(return_value=copy.deepcopy(fake.PROVISIONING_OPTIONS)))
1604 vserver_client = mock.Mock()
1606 self.library._allocate_container(fake.SHARE_INSTANCE, fake.VSERVER1,
1607 vserver_client, replica=True)
1609 mock_get_provisioning_opts.assert_called_once_with(
1610 fake.SHARE_INSTANCE, fake.VSERVER1, vserver_client=vserver_client,
1611 set_qos=True)
1613 vserver_client.create_volume.assert_called_once_with(
1614 fake.POOL_NAME, fake.SHARE_NAME, fake.SHARE['size'],
1615 thin_provisioned=True, snapshot_policy='default',
1616 language='en-US', dedup_enabled=True, split=True,
1617 compression_enabled=False, max_files=5000, encrypt=False,
1618 snapshot_reserve=8, mount_point_name=fake.MOUNT_POINT_NAME,
1619 volume_type='dp', adaptive_qos_policy_group=None)
1621 def test_allocate_container_no_pool_name(self):
1622 self.mock_object(self.library, '_get_backend_share_name', mock.Mock(
1623 return_value=fake.SHARE_NAME))
1624 self.mock_object(share_utils, 'extract_host', mock.Mock(
1625 return_value=None))
1626 self.mock_object(self.library, '_check_extra_specs_validity')
1627 self.mock_object(self.library, '_get_provisioning_options')
1628 vserver_client = mock.Mock()
1630 self.assertRaises(exception.InvalidHost,
1631 self.library._allocate_container,
1632 fake.SHARE_INSTANCE, fake.VSERVER1, vserver_client)
1634 self.library._get_backend_share_name.assert_called_once_with(
1635 fake.SHARE_INSTANCE['id'])
1636 share_utils.extract_host.assert_called_once_with(
1637 fake.SHARE_INSTANCE['host'], level='pool')
1638 self.assertEqual(0,
1639 self.library._check_extra_specs_validity.call_count)
1640 self.assertEqual(0, self.library._get_provisioning_options.call_count)
1642 @ddt.data(None, 1000)
1643 def test_create_flexgroup_share(self, max_files):
1644 self.library.configuration.netapp_flexgroup_volume_online_timeout = 2
1645 vserver_client = mock.Mock()
1646 vserver_client.get_job_state.return_value = "success"
1647 mock_wait_for_start = self.mock_object(
1648 self.library, 'wait_for_start_create_flexgroup',
1649 mock.Mock(return_value={'jobid': fake.JOB_ID, 'error-code': None}))
1650 mock_wait_for_flexgroup_deployment = self.mock_object(
1651 self.library, 'wait_for_flexgroup_deployment')
1652 aggr_list = [fake.AGGREGATE]
1653 options = {'efficiency_policy': fake.VOLUME_EFFICIENCY_POLICY_NAME}
1654 self.library._create_flexgroup_share(vserver_client, aggr_list,
1655 fake.SHARE_NAME, 100, 10,
1656 max_files=max_files,
1657 snaplock_type="compliance",
1658 **options)
1659 start_timeout = (self.library.configuration.
1660 netapp_flexgroup_aggregate_not_busy_timeout)
1661 mock_wait_for_start.assert_called_once_with(
1662 start_timeout, vserver_client, aggr_list, fake.SHARE_NAME, 100,
1663 10, None, "compliance",
1664 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME)
1665 mock_wait_for_flexgroup_deployment.assert_called_once_with(
1666 vserver_client, fake.JOB_ID, 2)
1667 vserver_client.update_volume_efficiency_attributes.assert_called_once_with( # noqa
1668 fake.SHARE_NAME, False, False,
1669 is_flexgroup=True,
1670 efficiency_policy=fake.VOLUME_EFFICIENCY_POLICY_NAME
1671 )
1672 if max_files:
1673 vserver_client.set_volume_max_files.assert_called_once_with(
1674 fake.SHARE_NAME, max_files)
1675 else:
1676 self.assertFalse(vserver_client.set_volume_max_files.called)
1678 @ddt.data(
1679 {'jobid': fake.JOB_ID, 'error-code': 'fake', 'error-message': 'fake'},
1680 {'jobid': None, 'error-code': None, 'error-message': 'fake'})
1681 def test_create_flexgroup_share_raise_error_job(self, job):
1682 vserver_client = mock.Mock()
1683 self.mock_object(self.library, 'wait_for_start_create_flexgroup',
1684 mock.Mock(return_value=job))
1685 aggr_list = [fake.AGGREGATE]
1687 self.assertRaises(
1688 exception.NetAppException, self.library._create_flexgroup_share,
1689 vserver_client, aggr_list, fake.SHARE_NAME, 100, 10)
1691 def test_wait_for_start_create_flexgroup(self):
1692 vserver_client = mock.Mock()
1693 job = {'jobid': fake.JOB_ID, 'error-code': None}
1694 vserver_client.create_volume_async.return_value = job
1695 aggr_list = [fake.AGGREGATE]
1697 result = self.library.wait_for_start_create_flexgroup(
1698 20, vserver_client, aggr_list, fake.SHARE_NAME, 1, 10,
1699 fake.MOUNT_POINT_NAME, "compliance")
1701 self.assertEqual(job, result)
1702 vserver_client.create_volume_async.assert_called_once_with(
1703 aggr_list, fake.SHARE_NAME, 1, is_flexgroup=True,
1704 snapshot_reserve=10,
1705 auto_provisioned=self.library._is_flexgroup_auto,
1706 mount_point_name=fake.MOUNT_POINT_NAME,
1707 snaplock_type="compliance")
1709 def test_wait_for_start_create_flexgroup_timeout(self):
1710 vserver_client = mock.Mock()
1711 vserver_client.create_volume_async.side_effect = (
1712 netapp_api.NaApiError(code=netapp_api.EAPIERROR,
1713 message="try the command again"))
1714 aggr_list = [fake.AGGREGATE]
1716 self.assertRaises(
1717 exception.NetAppException,
1718 self.library.wait_for_start_create_flexgroup, 10,
1719 vserver_client, aggr_list, fake.SHARE_NAME, 1, 10,
1720 fake.MOUNT_POINT_NAME, "compliance")
1722 def test_wait_for_flexgroup_deployment(self):
1723 vserver_client = mock.Mock()
1724 vserver_client.get_job_state.return_value = 'success'
1726 result = self.library.wait_for_flexgroup_deployment(
1727 vserver_client, fake.JOB_ID, 20)
1729 self.assertIsNone(result)
1730 vserver_client.get_job_state.assert_called_once_with(fake.JOB_ID)
1732 def test_wait_for_flexgroup_deployment_timeout(self):
1733 vserver_client = mock.Mock()
1734 vserver_client.get_job_state.return_value = 'queued'
1736 self.assertRaises(
1737 exception.NetAppException,
1738 self.library.wait_for_flexgroup_deployment,
1739 vserver_client, fake.JOB_ID, 10)
1741 @ddt.data('failure', 'error')
1742 def test_wai_for_flexgroup_deployment_job_error(self, error_state):
1743 vserver_client = mock.Mock()
1744 vserver_client.get_job_state.return_value = error_state
1746 self.assertRaises(
1747 exception.NetAppException,
1748 self.library.wait_for_flexgroup_deployment,
1749 vserver_client, fake.JOB_ID, 10)
1751 def test_check_extra_specs_validity(self):
1752 boolean_extra_spec_keys = list(
1753 self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP)
1754 mock_bool_check = self.mock_object(
1755 self.library, '_check_boolean_extra_specs_validity')
1756 mock_string_check = self.mock_object(
1757 self.library, '_check_string_extra_specs_validity')
1759 self.library._check_extra_specs_validity(
1760 fake.SHARE_INSTANCE, fake.EXTRA_SPEC)
1762 mock_bool_check.assert_called_once_with(
1763 fake.SHARE_INSTANCE, fake.EXTRA_SPEC, boolean_extra_spec_keys)
1764 mock_string_check.assert_called_once_with(
1765 fake.SHARE_INSTANCE, fake.EXTRA_SPEC)
1767 def test_check_extra_specs_validity_empty_spec(self):
1768 result = self.library._check_extra_specs_validity(
1769 fake.SHARE_INSTANCE, fake.EMPTY_EXTRA_SPEC)
1771 self.assertIsNone(result)
1773 def test_check_extra_specs_validity_invalid_value(self):
1774 self.assertRaises(
1775 exception.Invalid, self.library._check_extra_specs_validity,
1776 fake.SHARE_INSTANCE, fake.INVALID_EXTRA_SPEC)
1778 def test_check_string_extra_specs_validity(self):
1779 result = self.library._check_string_extra_specs_validity(
1780 fake.SHARE_INSTANCE, fake.EXTRA_SPEC_WITH_FPOLICY)
1782 self.assertIsNone(result)
1784 def test_check_string_extra_specs_validity_empty_spec(self):
1785 result = self.library._check_string_extra_specs_validity(
1786 fake.SHARE_INSTANCE, fake.EMPTY_EXTRA_SPEC)
1788 self.assertIsNone(result)
1790 def test_check_string_extra_specs_validity_invalid_value(self):
1791 self.assertRaises(
1792 exception.NetAppException,
1793 self.library._check_string_extra_specs_validity,
1794 fake.SHARE_INSTANCE, fake.INVALID_MAX_FILE_EXTRA_SPEC)
1796 def test_check_boolean_extra_specs_validity_invalid_value(self):
1797 self.assertRaises(
1798 exception.Invalid,
1799 self.library._check_boolean_extra_specs_validity,
1800 fake.SHARE_INSTANCE, fake.INVALID_EXTRA_SPEC,
1801 list(self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP))
1803 def test_check_extra_specs_validity_invalid_combination(self):
1804 self.assertRaises(
1805 exception.Invalid,
1806 self.library._check_boolean_extra_specs_validity,
1807 fake.SHARE_INSTANCE, fake.INVALID_EXTRA_SPEC_COMBO,
1808 list(self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP))
1810 @ddt.data({'extra_specs': fake.EXTRA_SPEC, 'set_qos': True},
1811 {'extra_specs': fake.EXTRA_SPEC_WITH_QOS, 'set_qos': False},
1812 {'extra_specs': fake.EXTRA_SPEC, 'set_qos': True},
1813 {'extra_specs': fake.EXTRA_SPEC_WITH_QOS, 'set_qos': False})
1814 @ddt.unpack
1815 def test_get_provisioning_options_for_share(self, extra_specs, set_qos):
1817 qos = True if fake.QOS_MAX_EXTRA_SPEC in extra_specs else False
1818 vserver_client = mock.Mock()
1819 self.library._have_cluster_creds = True
1820 mock_get_extra_specs_from_share = self.mock_object(
1821 share_types, 'get_extra_specs_from_share',
1822 mock.Mock(return_value=extra_specs))
1823 mock_remap_standard_boolean_extra_specs = self.mock_object(
1824 self.library, '_remap_standard_boolean_extra_specs',
1825 mock.Mock(return_value=extra_specs))
1826 mock_check_extra_specs_validity = self.mock_object(
1827 self.library, '_check_extra_specs_validity')
1828 mock_get_provisioning_options = self.mock_object(
1829 self.library, '_get_provisioning_options',
1830 mock.Mock(return_value=fake.PROVISIONING_OPTIONS))
1831 mock_get_normalized_qos_specs = self.mock_object(
1832 self.library, '_get_normalized_qos_specs',
1833 mock.Mock(return_value={fake.QOS_NORMALIZED_SPEC: 3000}))
1834 mock_create_qos_policy_group = self.mock_object(
1835 self.library, '_create_qos_policy_group', mock.Mock(
1836 return_value=fake.QOS_POLICY_GROUP_NAME))
1838 result = self.library._get_provisioning_options_for_share(
1839 fake.SHARE_INSTANCE, fake.VSERVER1, vserver_client=vserver_client,
1840 set_qos=set_qos)
1842 if qos and not set_qos:
1843 expected_provisioning_opts = fake.PROVISIONING_OPTIONS
1844 self.assertFalse(mock_create_qos_policy_group.called)
1845 else:
1846 expected_provisioning_opts = fake.PROVISIONING_OPTIONS_WITH_QOS
1847 mock_create_qos_policy_group.assert_called_once_with(
1848 fake.SHARE_INSTANCE, fake.VSERVER1,
1849 {fake.QOS_NORMALIZED_SPEC: 3000}, vserver_client)
1851 self.assertEqual(expected_provisioning_opts, result)
1852 mock_get_extra_specs_from_share.assert_called_once_with(
1853 fake.SHARE_INSTANCE)
1854 mock_remap_standard_boolean_extra_specs.assert_called_once_with(
1855 extra_specs)
1856 mock_check_extra_specs_validity.assert_called_once_with(
1857 fake.SHARE_INSTANCE, extra_specs)
1858 mock_get_provisioning_options.assert_called_once_with(extra_specs)
1859 mock_get_normalized_qos_specs.assert_called_once_with(extra_specs)
1861 def test_get_provisioning_options_for_share_qos_conflict(self):
1862 vserver_client = mock.Mock()
1863 extra_specs = fake.EXTRA_SPEC_WITH_QOS
1864 mock_get_extra_specs_from_share = self.mock_object(
1865 share_types, 'get_extra_specs_from_share',
1866 mock.Mock(return_value=extra_specs))
1867 mock_remap_standard_boolean_extra_specs = self.mock_object(
1868 self.library, '_remap_standard_boolean_extra_specs',
1869 mock.Mock(return_value=extra_specs))
1870 mock_check_extra_specs_validity = self.mock_object(
1871 self.library, '_check_extra_specs_validity')
1872 mock_get_provisioning_options = self.mock_object(
1873 self.library, '_get_provisioning_options',
1874 mock.Mock(return_value=fake.PROVISIONING_OPTS_WITH_ADAPT_QOS))
1875 mock_get_normalized_qos_specs = self.mock_object(
1876 self.library, '_get_normalized_qos_specs',
1877 mock.Mock(return_value={fake.QOS_NORMALIZED_SPEC: 3000}))
1879 self.assertRaises(exception.NetAppException,
1880 self.library._get_provisioning_options_for_share,
1881 fake.SHARE_INSTANCE, fake.VSERVER1,
1882 vserver_client=vserver_client,
1883 set_qos=True)
1885 mock_get_extra_specs_from_share.assert_called_once_with(
1886 fake.SHARE_INSTANCE)
1887 mock_remap_standard_boolean_extra_specs.assert_called_once_with(
1888 extra_specs)
1889 mock_check_extra_specs_validity.assert_called_once_with(
1890 fake.SHARE_INSTANCE, extra_specs)
1891 mock_get_provisioning_options.assert_called_once_with(extra_specs)
1892 mock_get_normalized_qos_specs.assert_called_once_with(extra_specs)
1894 def test_get_provisioning_options_implicit_false(self):
1895 result = self.library._get_provisioning_options(
1896 fake.EMPTY_EXTRA_SPEC)
1898 expected = {
1899 'adaptive_qos_policy_group': None,
1900 'language': None,
1901 'max_files': None,
1902 'max_files_multiplier': None,
1903 'snapshot_policy': None,
1904 'thin_provisioned': False,
1905 'compression_enabled': False,
1906 'dedup_enabled': False,
1907 'split': False,
1908 'encrypt': False,
1909 'hide_snapdir': False,
1910 'fpolicy_extensions_to_exclude': None,
1911 'fpolicy_extensions_to_include': None,
1912 'fpolicy_file_operations': None,
1913 'efficiency_policy': None,
1914 'snaplock_type': None,
1915 'snaplock_autocommit_period': None,
1916 'snaplock_min_retention_period': None,
1917 'snaplock_max_retention_period': None,
1918 'snaplock_default_retention_period': None,
1919 }
1921 self.assertEqual(expected, result)
1923 def test_get_boolean_provisioning_options(self):
1924 result = self.library._get_boolean_provisioning_options(
1925 fake.SHORT_BOOLEAN_EXTRA_SPEC,
1926 self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP)
1928 self.assertEqual(fake.PROVISIONING_OPTIONS_BOOLEAN, result)
1930 def test_get_boolean_provisioning_options_missing_spec(self):
1931 result = self.library._get_boolean_provisioning_options(
1932 fake.SHORT_BOOLEAN_EXTRA_SPEC,
1933 self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP)
1935 self.assertEqual(fake.PROVISIONING_OPTIONS_BOOLEAN, result)
1937 def test_get_boolean_provisioning_options_implicit_false(self):
1938 expected = {
1939 'thin_provisioned': False,
1940 'dedup_enabled': False,
1941 'compression_enabled': False,
1942 'split': False,
1943 'hide_snapdir': False,
1944 }
1946 result = self.library._get_boolean_provisioning_options(
1947 fake.EMPTY_EXTRA_SPEC,
1948 self.library.BOOLEAN_QUALIFIED_EXTRA_SPECS_MAP)
1950 self.assertEqual(expected, result)
1952 def test_get_string_provisioning_options(self):
1953 result = self.library.get_string_provisioning_options(
1954 fake.STRING_EXTRA_SPEC,
1955 self.library.STRING_QUALIFIED_EXTRA_SPECS_MAP)
1957 self.assertEqual(fake.PROVISIONING_OPTIONS_STRING, result)
1959 def test_get_string_provisioning_options_missing_spec(self):
1960 result = self.library.get_string_provisioning_options(
1961 fake.SHORT_STRING_EXTRA_SPEC,
1962 self.library.STRING_QUALIFIED_EXTRA_SPECS_MAP)
1964 self.assertEqual(fake.PROVISIONING_OPTIONS_STRING_MISSING_SPECS,
1965 result)
1967 def test_get_string_provisioning_options_implicit_false(self):
1968 result = self.library.get_string_provisioning_options(
1969 fake.EMPTY_EXTRA_SPEC,
1970 self.library.STRING_QUALIFIED_EXTRA_SPECS_MAP)
1972 self.assertEqual(fake.PROVISIONING_OPTIONS_STRING_DEFAULT, result)
1974 @ddt.data({}, {'foo': 'bar'}, {'netapp:maxiops': '3000'},
1975 {'qos': True, 'netapp:absiops': '3000'},
1976 {'qos': True, 'netapp:maxiops:': '3000'})
1977 def test_get_normalized_qos_specs_no_qos_specs(self, extra_specs):
1978 if 'qos' in extra_specs:
1979 self.assertRaises(exception.NetAppException,
1980 self.library._get_normalized_qos_specs,
1981 extra_specs)
1982 else:
1983 self.assertDictEqual(
1984 {}, self.library._get_normalized_qos_specs(extra_specs))
1986 @ddt.data({'qos': True, 'netapp:maxiops': '3000', 'netapp:maxbps': '9000'},
1987 {'qos': True, 'netapp:maxiopspergib': '1000',
1988 'netapp:maxiops': '1000'})
1989 def test_get_normalized_qos_specs_multiple_max_qos_specs(self,
1990 extra_specs):
1991 self.assertRaises(exception.NetAppException,
1992 self.library._get_normalized_qos_specs,
1993 extra_specs)
1995 @ddt.data({'qos': True, 'netapp:miniops': '1000', 'netapp:minbps': '1000'},
1996 {'qos': True, 'netapp:miniopspergib': '1000',
1997 'netapp:miniops': '1000'})
1998 def test_get_normalized_qos_specs_multiple_min_qos_specs(self,
1999 extra_specs):
2000 self.assertRaises(exception.NetAppException,
2001 self.library._get_normalized_qos_specs,
2002 extra_specs)
2004 @ddt.data({'qos': True, 'netapp:maxIOPS': '3000'},
2005 {'qos': True, 'netapp:MAxBPs': '3000', 'clem': 'son'},
2006 {'qos': True, 'netapp:maxbps': '3000', 'tig': 'ers'},
2007 {'qos': True, 'netapp:MAXiopSPerGib': '3000', 'kin': 'gsof'},
2008 {'qos': True, 'netapp:maxiopspergib': '3000', 'coll': 'ege'},
2009 {'qos': True, 'netapp:maxBPSperGiB': '3000', 'foot': 'ball'},
2010 {'qos': True, 'netapp:minIOPS': '3000'},
2011 {'qos': True, 'netapp:MinBPs': '3000', 'clem': 'son'},
2012 {'qos': True, 'netapp:Minbps': '3000', 'tig': 'ers'},
2013 {'qos': True, 'netapp:MINiopSPerGib': '3000', 'kin': 'gsof'},
2014 {'qos': True, 'netapp:MINbpSPerGib': '3000', 'kin': 'gsof'})
2015 def test_get_normalized_qos_specs(self, extra_specs):
2016 expected_normalized_spec = {
2017 key.lower().split('netapp:')[1]: value
2018 for key, value in extra_specs.items() if 'netapp:' in key
2019 }
2021 qos_specs = self.library._get_normalized_qos_specs(extra_specs)
2023 self.assertDictEqual(expected_normalized_spec, qos_specs)
2024 self.assertEqual(1, len(qos_specs))
2026 @ddt.data({'qos': {'maxiops': '3000'}, 'expected': '3000iops'},
2027 {'qos': {'maxbps': '3000'}, 'expected': '3000B/s'},
2028 {'qos': {'maxbpspergib': '3000'}, 'expected': '12000B/s'},
2029 {'qos': {'maxiopspergib': '3000'}, 'expected': '12000iops'})
2030 @ddt.unpack
2031 def test_get_max_throughput(self, qos, expected):
2033 throughput = self.library._get_max_throughput(4, qos)
2035 self.assertEqual(expected, throughput)
2037 @ddt.data({'qos': {'miniops': '1000'}, 'expected': '1000iops'},
2038 {'qos': {'minbps': '1000'}, 'expected': '1000B/s'},
2039 {'qos': {'minbpspergib': '1000'}, 'expected': '4000B/s'},
2040 {'qos': {'miniopspergib': '1000'}, 'expected': '4000iops'})
2041 @ddt.unpack
2042 def test_get_min_throughput(self, qos, expected):
2044 throughput = self.library._get_min_throughput(4, qos)
2046 self.assertEqual(expected, throughput)
2048 def test_create_qos_policy_group(self):
2049 mock_qos_policy_create = self.mock_object(
2050 self.library._client, 'qos_policy_group_create')
2052 self.library._create_qos_policy_group(
2053 fake.SHARE, fake.VSERVER1, {'maxiops': '3000'})
2055 expected_policy_name = 'qos_share_' + fake.SHARE['id'].replace(
2056 '-', '_')
2057 mock_qos_policy_create.assert_called_once_with(
2058 expected_policy_name, fake.VSERVER1, max_throughput='3000iops',
2059 min_throughput=None)
2061 def test_check_if_max_files_is_valid_with_negative_integer(self):
2062 self.assertRaises(exception.NetAppException,
2063 self.library._check_if_max_files_is_valid,
2064 fake.SHARE, -1)
2066 def test_check_if_max_files_is_valid_with_string(self):
2067 self.assertRaises(ValueError,
2068 self.library._check_if_max_files_is_valid,
2069 fake.SHARE, 'abc')
2071 def test__check_fpolicy_file_operations(self):
2072 result = self.library._check_fpolicy_file_operations(
2073 fake.SHARE, fake.FPOLICY_FILE_OPERATIONS)
2075 self.assertIsNone(result)
2077 def test__check_fpolicy_file_operations_invalid_operation(self):
2078 invalid_ops = copy.deepcopy(fake.FPOLICY_FILE_OPERATIONS)
2079 invalid_ops += ',fake_op'
2081 self.assertRaises(exception.NetAppException,
2082 self.library._check_fpolicy_file_operations,
2083 fake.SHARE,
2084 invalid_ops)
2086 @ddt.data('15minutes', '4hours', "8days", "5months", "2years")
2087 def test__check_snaplock_attributes_autocommit_period(self, duration):
2088 result = self.library._check_snaplock_attributes(
2089 fake.SHARE, "netapp:snaplock_autocommit_period", duration)
2090 self.assertIsNone(result)
2092 @ddt.data('15minutes', '4hours', "8days", "5months", "2years")
2093 def test__check_snaplock_attributes_min_retention_period(self, duration):
2094 result = self.library._check_snaplock_attributes(
2095 fake.SHARE, "netapp:snaplock_min_retention_period", duration)
2096 self.assertIsNone(result)
2098 @ddt.data('15minutes', '4hours', "8days", "5months", "2years",
2099 "infinite")
2100 def test__check_snaplock_attributes_max_retention_period(self, duration):
2101 result = self.library._check_snaplock_attributes(
2102 fake.SHARE, "netapp:snaplock_max_retention_period", duration)
2103 self.assertIsNone(result)
2105 @ddt.data('15minutes', '4hours', "8days", "5months", "2years",
2106 "infinite", "min", "max")
2107 def test__check_snaplock_attributes_default_retention_period(self,
2108 duration):
2109 result = self.library._check_snaplock_attributes(
2110 fake.SHARE, "netapp:snaplock_default_retention_period", duration)
2111 self.assertIsNone(result)
2113 def test__check_snaplock_attributes_autocommit_period_negative(self):
2114 self.assertRaises(exception.NetAppException,
2115 self.library._check_snaplock_attributes,
2116 fake.SHARE,
2117 "netapp:snaplock_autocommit_period",
2118 "invalid_period",
2119 )
2121 def test__check_snaplock_attributes_min_retention_period_negative(self):
2122 self.assertRaises(exception.NetAppException,
2123 self.library._check_snaplock_attributes,
2124 fake.SHARE,
2125 "netapp:snaplock_min_retention_period",
2126 "invalid_period",
2127 )
2129 def test__check_snaplock_attributes_max_retention_period_negative(self):
2130 self.assertRaises(exception.NetAppException,
2131 self.library._check_snaplock_attributes,
2132 fake.SHARE,
2133 "netapp:snaplock_max_retention_period",
2134 "invalid_period",
2135 )
2137 def test__check_snaplock_attributes_default_retention_period_neg(self):
2138 self.assertRaises(exception.NetAppException,
2139 self.library._check_snaplock_attributes,
2140 fake.SHARE,
2141 "netapp:snaplock_default_retention_period",
2142 "invalid_period",
2143 )
2145 def test__check_snaplock_compatibility_true(self):
2146 self.library._have_cluster_creds = True
2147 self.library._is_snaplock_compliance_configured = True
2148 self.mock_object(self.client,
2149 'list_cluster_nodes',
2150 mock.Mock(return_value=(["node1", "node2"])))
2151 result = self.library._check_snaplock_compatibility()
2152 self.assertIsNone(result)
2154 def test__check_snaplock_compatibility_false(self):
2155 self.library._have_cluster_creds = True
2156 self.library._is_snaplock_compliance_configured = False
2157 self.mock_object(self.client,
2158 'list_cluster_nodes',
2159 mock.Mock(return_value=(["node1", "node2"])))
2160 self.assertRaises(exception.NetAppException,
2161 self.library._check_snaplock_compatibility)
2163 def test__check_snaplock_compatibility_not_cluster_scope(self):
2164 self.library._have_cluster_creds = False
2165 self.library._check_snaplock_compatibility()
2167 def test_allocate_container_no_pool(self):
2169 vserver_client = mock.Mock()
2170 fake_share_inst = copy.deepcopy(fake.SHARE_INSTANCE)
2171 fake_share_inst['host'] = fake_share_inst['host'].split('#')[0]
2173 self.assertRaises(exception.InvalidHost,
2174 self.library._allocate_container,
2175 fake_share_inst,
2176 fake.VSERVER1,
2177 vserver_client)
2179 def test_check_aggregate_extra_specs_validity(self):
2181 self.library._have_cluster_creds = True
2182 self.library._ssc_stats = fake.SSC_INFO
2184 result = self.library._check_aggregate_extra_specs_validity(
2185 fake.AGGREGATES[0], fake.EXTRA_SPEC)
2187 self.assertIsNone(result)
2189 def test_check_aggregate_extra_specs_validity_no_match(self):
2191 self.library._have_cluster_creds = True
2192 self.library._ssc_stats = fake.SSC_INFO
2194 self.assertRaises(exception.NetAppException,
2195 self.library._check_aggregate_extra_specs_validity,
2196 fake.AGGREGATES[1],
2197 fake.EXTRA_SPEC)
2199 @ddt.data({'provider_location': None, 'size': 50, 'hide_snapdir': True,
2200 'split': None, 'create_fpolicy': False},
2201 {'provider_location': 'fake_location', 'size': 30,
2202 'hide_snapdir': False, 'split': True, 'create_fpolicy': True},
2203 {'provider_location': 'fake_location', 'size': 20,
2204 'hide_snapdir': True, 'split': False, 'create_fpolicy': True})
2205 @ddt.unpack
2206 def test_allocate_container_from_snapshot(
2207 self, provider_location, size, hide_snapdir, split,
2208 create_fpolicy):
2209 provisioning_options = copy.deepcopy(
2210 fake.PROVISIONING_OPTIONS_WITH_FPOLICY)
2211 provisioning_options['hide_snapdir'] = hide_snapdir
2212 mock_get_provisioning_opts = self.mock_object(
2213 self.library, '_get_provisioning_options_for_share',
2214 mock.Mock(return_value=provisioning_options))
2215 mock_create_fpolicy = self.mock_object(
2216 self.library, '_create_fpolicy_for_share')
2218 vserver = fake.VSERVER1
2219 vserver_client = mock.Mock()
2220 original_snapshot_size = 20
2222 fake_share_inst = copy.deepcopy(fake.SHARE_INSTANCE)
2223 fake_share_inst['size'] = size
2224 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
2225 fake_snapshot['provider_location'] = provider_location
2226 fake_snapshot['size'] = original_snapshot_size
2227 mock_rename_snapshot_and_split_clones = self.mock_object(
2228 vserver_client,
2229 'rename_snapshot_and_split_clones'
2230 )
2232 self.library._allocate_container_from_snapshot(
2233 fake_share_inst,
2234 fake_snapshot,
2235 vserver,
2236 vserver_client,
2237 split=split,
2238 create_fpolicy=create_fpolicy)
2240 share_name = self.library._get_backend_share_name(
2241 fake_share_inst['id'])
2242 parent_share_name = self.library._get_backend_share_name(
2243 fake_snapshot['share_id'])
2244 parent_snapshot_name = self.library._get_backend_snapshot_name(
2245 fake_snapshot['id']) if not provider_location else 'fake_location'
2246 mock_get_provisioning_opts.assert_called_once_with(
2247 fake_share_inst, fake.VSERVER1, vserver_client=vserver_client)
2248 vserver_client.create_volume_clone.assert_called_once_with(
2249 share_name, parent_share_name, parent_snapshot_name,
2250 mount_point_name=fake_share_inst["mount_point_name"],
2251 **provisioning_options)
2252 if size > original_snapshot_size:
2253 vserver_client.set_volume_size.assert_called_once_with(
2254 share_name, size)
2255 else:
2256 vserver_client.set_volume_size.assert_not_called()
2258 if hide_snapdir:
2259 vserver_client.set_volume_snapdir_access.assert_called_once_with(
2260 fake.SHARE_INSTANCE_NAME, hide_snapdir)
2261 else:
2262 vserver_client.set_volume_snapdir_access.assert_not_called()
2264 if create_fpolicy:
2265 mock_create_fpolicy.assert_called_once_with(
2266 fake_share_inst, vserver, vserver_client,
2267 **provisioning_options)
2268 else:
2269 mock_create_fpolicy.assert_not_called()
2271 if split or split is None:
2272 mock_rename_snapshot_and_split_clones.assert_called_once_with(
2273 fake.SHARE_INSTANCE_NAME,
2274 parent_snapshot_name,
2275 )
2276 vserver_client.volume_clone_split_start.assert_called_once_with(
2277 fake.SHARE_INSTANCE_NAME)
2278 if split is False:
2279 vserver_client.volume_clone_split_start.assert_not_called()
2281 def test_share_exists(self):
2283 vserver_client = mock.Mock()
2284 vserver_client.volume_exists.return_value = True
2286 result = self.library._share_exists(fake.SHARE_NAME, vserver_client)
2288 self.assertTrue(result)
2290 def test_share_exists_not_found(self):
2292 vserver_client = mock.Mock()
2293 vserver_client.volume_exists.return_value = False
2295 result = self.library._share_exists(fake.SHARE_NAME, vserver_client)
2297 self.assertFalse(result)
2299 def test_delete_share(self):
2301 vserver_client = mock.Mock()
2302 self.mock_object(self.library,
2303 '_get_vserver',
2304 mock.Mock(return_value=(fake.VSERVER1,
2305 vserver_client)))
2306 mock_share_exists = self.mock_object(self.library,
2307 '_share_exists',
2308 mock.Mock(return_value=True))
2309 mock_remove_export = self.mock_object(self.library, '_remove_export')
2310 mock_deallocate_container = self.mock_object(self.library,
2311 '_deallocate_container')
2312 mock_delete_policy = self.mock_object(self.library,
2313 '_delete_fpolicy_for_share')
2315 self.library.delete_share(self.context,
2316 fake.SHARE,
2317 share_server=fake.SHARE_SERVER)
2319 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
2320 qos_policy_name = self.library._get_backend_qos_policy_group_name(
2321 fake.SHARE['id'])
2322 mock_share_exists.assert_called_once_with(share_name, vserver_client)
2323 mock_remove_export.assert_called_once_with(fake.SHARE, vserver_client)
2324 mock_deallocate_container.assert_called_once_with(share_name,
2325 vserver_client)
2326 mock_delete_policy.assert_called_once_with(fake.SHARE, fake.VSERVER1,
2327 vserver_client)
2328 (vserver_client.mark_qos_policy_group_for_deletion
2329 .assert_called_once_with(qos_policy_name))
2330 self.assertEqual(0, lib_base.LOG.info.call_count)
2332 def test__delete_share_no_remove_qos_and_export(self):
2334 vserver_client = mock.Mock()
2335 mock_share_exists = self.mock_object(self.library,
2336 '_share_exists',
2337 mock.Mock(return_value=True))
2338 mock_remove_export = self.mock_object(self.library, '_remove_export')
2339 mock_deallocate_container = self.mock_object(self.library,
2340 '_deallocate_container')
2341 mock_delete_policy = self.mock_object(self.library,
2342 '_delete_fpolicy_for_share')
2343 mock_get_backend_qos = self.mock_object(
2344 self.library, '_get_backend_qos_policy_group_name')
2345 mock_get_share_name = self.mock_object(
2346 self.library, '_get_backend_share_name',
2347 mock.Mock(return_value=fake.SHARE_NAME))
2349 self.library._delete_share(fake.SHARE,
2350 fake.VSERVER1,
2351 vserver_client,
2352 remove_export=False,
2353 remove_qos=False)
2355 mock_get_share_name.assert_called_once_with(fake.SHARE_ID)
2356 mock_delete_policy.assert_called_once_with(fake.SHARE, fake.VSERVER1,
2357 vserver_client)
2358 mock_share_exists.assert_called_once_with(fake.SHARE_NAME,
2359 vserver_client)
2361 mock_deallocate_container.assert_called_once_with(fake.SHARE_NAME,
2362 vserver_client)
2363 mock_remove_export.assert_not_called()
2364 mock_get_backend_qos.assert_not_called()
2365 vserver_client.mark_qos_policy_group_for_deletion.assert_not_called()
2367 @ddt.data(exception.InvalidInput(reason='fake_reason'),
2368 exception.VserverNotSpecified(),
2369 exception.VserverNotFound(vserver='fake_vserver'))
2370 def test_delete_share_no_share_server(self, get_vserver_exception):
2372 self.mock_object(self.library,
2373 '_get_vserver',
2374 mock.Mock(side_effect=get_vserver_exception))
2375 mock_share_exists = self.mock_object(self.library,
2376 '_share_exists',
2377 mock.Mock(return_value=False))
2378 mock_remove_export = self.mock_object(self.library, '_remove_export')
2379 mock_deallocate_container = self.mock_object(self.library,
2380 '_deallocate_container')
2382 self.library.delete_share(self.context,
2383 fake.SHARE,
2384 share_server=fake.SHARE_SERVER)
2386 self.assertFalse(mock_share_exists.called)
2387 self.assertFalse(mock_remove_export.called)
2388 self.assertFalse(mock_deallocate_container.called)
2389 self.assertFalse(
2390 self.library._client.mark_qos_policy_group_for_deletion.called)
2391 self.assertEqual(1, lib_base.LOG.warning.call_count)
2393 def test_delete_share_not_found(self):
2395 vserver_client = mock.Mock()
2396 self.mock_object(self.library,
2397 '_get_vserver',
2398 mock.Mock(return_value=(fake.VSERVER1,
2399 vserver_client)))
2400 mock_share_exists = self.mock_object(self.library,
2401 '_share_exists',
2402 mock.Mock(return_value=False))
2403 mock_remove_export = self.mock_object(self.library, '_remove_export')
2404 mock_deallocate_container = self.mock_object(self.library,
2405 '_deallocate_container')
2406 mock_delete_fpolicy = self.mock_object(self.library,
2407 '_delete_fpolicy_for_share')
2409 self.library.delete_share(self.context,
2410 fake.SHARE,
2411 share_server=fake.SHARE_SERVER)
2413 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
2414 mock_share_exists.assert_called_once_with(share_name, vserver_client)
2415 mock_delete_fpolicy.assert_called_once_with(fake.SHARE, fake.VSERVER1,
2416 vserver_client)
2417 self.assertFalse(mock_remove_export.called)
2418 self.assertFalse(mock_deallocate_container.called)
2419 self.assertFalse(
2420 self.library._client.mark_qos_policy_group_for_deletion.called)
2421 self.assertEqual(1, lib_base.LOG.info.call_count)
2423 def test_delete_share_clears_private_storage(self):
2424 vserver_client = mock.Mock()
2425 self.mock_object(
2426 self.library,
2427 '_get_vserver',
2428 mock.Mock(return_value=(fake.VSERVER1,
2429 vserver_client))
2430 )
2431 mock_share_exists = self.mock_object(
2432 self.library,
2433 '_share_exists',
2434 mock.Mock(return_value=True)
2435 )
2436 mock_remove_export = self.mock_object(self.library, '_remove_export')
2437 mock_deallocate_container = self.mock_object(self.library,
2438 '_deallocate_container')
2439 mock_delete_fpolicy = self.mock_object(
2440 self.library, '_delete_fpolicy_for_share')
2441 mock_get_qos = self.mock_object(
2442 self.library,
2443 '_get_backend_qos_policy_group_name',
2444 mock.Mock(return_value='fake_qos_policy')
2445 )
2446 mock_mark_qos = self.mock_object(
2447 vserver_client,
2448 'mark_qos_policy_group_for_deletion'
2449 )
2450 mock_private_storage_delete = self.mock_object(
2451 self.library.private_storage,
2452 'delete',
2453 )
2454 self.library.delete_share(self.context, fake.SHARE,
2455 share_server=fake.SHARE_SERVER)
2457 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
2458 mock_share_exists.assert_called_once_with(share_name, vserver_client)
2459 mock_remove_export.assert_called_once_with(fake.SHARE, vserver_client)
2460 mock_deallocate_container.assert_called_once_with(share_name,
2461 vserver_client)
2462 mock_delete_fpolicy.assert_called_once_with(
2463 fake.SHARE, fake.VSERVER1, vserver_client)
2464 mock_get_qos.assert_called_once_with(
2465 fake.SHARE['id'])
2466 mock_mark_qos.assert_called_once_with('fake_qos_policy')
2467 mock_private_storage_delete.assert_called_once_with(fake.SHARE['id'])
2469 self.assertEqual(0, lib_base.LOG.info.call_count)
2471 def test_delete_share_nonexistent_does_not_delete_private_storage(self):
2472 vserver_client = mock.Mock()
2473 self.mock_object(
2474 self.library,
2475 '_get_vserver',
2476 mock.Mock(return_value=(fake.VSERVER1, vserver_client))
2477 )
2478 mock_share_exists = self.mock_object(
2479 self.library,
2480 '_share_exists',
2481 mock.Mock(return_value=False)
2482 )
2483 mock_delete_fpolicy = self.mock_object(
2484 self.library,
2485 '_delete_fpolicy_for_share'
2486 )
2487 mock_private_storage_delete = self.mock_object(
2488 self.library.private_storage, 'delete'
2489 )
2490 self.library.delete_share(
2491 self.context, fake.SHARE, share_server=fake.SHARE_SERVER)
2492 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
2493 mock_share_exists.assert_called_once_with(
2494 share_name, vserver_client)
2495 mock_delete_fpolicy.assert_called_once_with(
2496 fake.SHARE, fake.VSERVER1, vserver_client)
2497 mock_private_storage_delete.assert_called_once_with(
2498 fake.SHARE['id'])
2500 def test_deallocate_container(self):
2502 vserver_client = mock.Mock()
2504 self.library._deallocate_container(fake.SHARE_NAME, vserver_client)
2506 vserver_client.unmount_volume.assert_called_with(fake.SHARE_NAME,
2507 force=True)
2508 vserver_client.offline_volume.assert_called_with(fake.SHARE_NAME)
2509 vserver_client.delete_volume.assert_called_with(fake.SHARE_NAME)
2511 @ddt.data(None, fake.MANILA_HOST_NAME_2)
2512 def test_create_export(self, share_host):
2514 protocol_helper = mock.Mock()
2515 callback = (lambda export_address, export_path='fake_export_path':
2516 ':'.join([export_address, export_path]))
2517 protocol_helper.create_share.return_value = callback
2518 expected_host = share_host if share_host else fake.SHARE['host']
2519 self.mock_object(self.library,
2520 '_get_helper',
2521 mock.Mock(return_value=protocol_helper))
2522 self.mock_object(self.library,
2523 '_is_flexgroup_pool', mock.Mock(return_value=False))
2524 vserver_client = mock.Mock()
2525 cluster_client = mock.Mock()
2526 vserver_client.get_network_interfaces.return_value = fake.LIFS
2527 fake_interface_addresses_with_metadata = copy.deepcopy(
2528 fake.INTERFACE_ADDRESSES_WITH_METADATA)
2529 mock_get_export_addresses_with_metadata = self.mock_object(
2530 self.library, '_get_export_addresses_with_metadata',
2531 mock.Mock(return_value=fake_interface_addresses_with_metadata))
2533 result = self.library._create_export(fake.SHARE,
2534 fake.SHARE_SERVER,
2535 fake.VSERVER1,
2536 vserver_client,
2537 cluster_client=cluster_client,
2538 share_host=share_host)
2540 self.assertEqual(fake.NFS_EXPORTS, result)
2541 mock_get_export_addresses_with_metadata.assert_called_once_with(
2542 fake.SHARE, fake.SHARE_SERVER, fake.LIFS, expected_host,
2543 cluster_client)
2544 protocol_helper.create_share.assert_called_once_with(
2545 fake.SHARE, fake.SHARE_NAME, clear_current_export_policy=True,
2546 ensure_share_already_exists=False, replica=False,
2547 is_flexgroup=False)
2549 def test_create_export_lifs_not_found(self):
2551 self.mock_object(self.library, '_get_helper')
2552 vserver_client = mock.Mock()
2553 vserver_client.get_network_interfaces.return_value = []
2555 self.assertRaises(exception.NetAppException,
2556 self.library._create_export,
2557 fake.SHARE,
2558 fake.SHARE_SERVER,
2559 fake.VSERVER1,
2560 vserver_client)
2562 @ddt.data(True, False)
2563 def test_get_export_addresses_with_metadata(self, is_flexgroup):
2565 self.mock_object(
2566 self.library, '_is_flexgroup_pool',
2567 mock.Mock(return_value=is_flexgroup))
2568 mock_get_aggr_flexgroup = self.mock_object(
2569 self.library, '_get_flexgroup_aggregate_list',
2570 mock.Mock(return_value=[fake.AGGREGATE]))
2571 mock_get_aggregate_node = self.mock_object(
2572 self.library, '_get_aggregate_node',
2573 mock.Mock(return_value=fake.CLUSTER_NODES[0]))
2574 mock_get_admin_addresses_for_share_server = self.mock_object(
2575 self.library, '_get_admin_addresses_for_share_server',
2576 mock.Mock(return_value=[fake.LIF_ADDRESSES[1]]))
2578 result = self.library._get_export_addresses_with_metadata(
2579 fake.SHARE, fake.SHARE_SERVER, fake.LIFS, fake.SHARE['host'])
2581 self.assertEqual(fake.INTERFACE_ADDRESSES_WITH_METADATA, result)
2582 mock_get_admin_addresses_for_share_server.assert_called_once_with(
2583 fake.SHARE_SERVER)
2584 if is_flexgroup:
2585 mock_get_aggr_flexgroup.assert_called_once_with(fake.POOL_NAME)
2586 mock_get_aggregate_node.assert_called_once_with(
2587 fake.AGGREGATE, None)
2588 else:
2589 mock_get_aggregate_node.assert_called_once_with(
2590 fake.POOL_NAME, None)
2592 def test_get_export_addresses_with_metadata_node_unknown(self):
2594 self.mock_object(
2595 self.library, '_is_flexgroup_pool', mock.Mock(return_value=False))
2596 mock_get_aggregate_node = self.mock_object(
2597 self.library, '_get_aggregate_node',
2598 mock.Mock(return_value=None))
2599 mock_get_admin_addresses_for_share_server = self.mock_object(
2600 self.library, '_get_admin_addresses_for_share_server',
2601 mock.Mock(return_value=[fake.LIF_ADDRESSES[1]]))
2603 result = self.library._get_export_addresses_with_metadata(
2604 fake.SHARE, fake.SHARE_SERVER, fake.LIFS, fake.SHARE['host'])
2606 expected = copy.deepcopy(fake.INTERFACE_ADDRESSES_WITH_METADATA)
2607 for key, value in expected.items():
2608 value['preferred'] = False
2610 self.assertEqual(expected, result)
2611 mock_get_aggregate_node.assert_called_once_with(fake.POOL_NAME, None)
2612 mock_get_admin_addresses_for_share_server.assert_called_once_with(
2613 fake.SHARE_SERVER)
2615 def test_get_admin_addresses_for_share_server(self):
2617 result = self.library._get_admin_addresses_for_share_server(
2618 fake.SHARE_SERVER)
2620 self.assertEqual([fake.ADMIN_NETWORK_ALLOCATIONS[0]['ip_address']],
2621 result)
2623 def test_get_admin_addresses_for_share_server_no_share_server(self):
2625 result = self.library._get_admin_addresses_for_share_server(None)
2627 self.assertEqual([], result)
2629 @ddt.data(True, False)
2630 def test_sort_export_locations_by_preferred_paths(self, reverse):
2632 export_locations = copy.copy(fake.NFS_EXPORTS)
2633 if reverse:
2634 export_locations.reverse()
2636 result = self.library._sort_export_locations_by_preferred_paths(
2637 export_locations)
2639 self.assertEqual(fake.NFS_EXPORTS, result)
2641 def test_remove_export(self):
2643 protocol_helper = mock.Mock()
2644 protocol_helper.get_target.return_value = 'fake_target'
2645 self.mock_object(self.library,
2646 '_get_helper',
2647 mock.Mock(return_value=protocol_helper))
2648 vserver_client = mock.Mock()
2650 self.library._remove_export(fake.SHARE, vserver_client)
2652 protocol_helper.set_client.assert_called_once_with(vserver_client)
2653 protocol_helper.get_target.assert_called_once_with(fake.SHARE)
2654 protocol_helper.delete_share.assert_called_once_with(fake.SHARE,
2655 fake.SHARE_NAME)
2657 def test_remove_export_target_not_found(self):
2659 protocol_helper = mock.Mock()
2660 protocol_helper.get_target.return_value = None
2661 self.mock_object(self.library,
2662 '_get_helper',
2663 mock.Mock(return_value=protocol_helper))
2664 vserver_client = mock.Mock()
2666 self.library._remove_export(fake.SHARE, vserver_client)
2668 protocol_helper.set_client.assert_called_once_with(vserver_client)
2669 protocol_helper.get_target.assert_called_once_with(fake.SHARE)
2670 self.assertFalse(protocol_helper.delete_share.called)
2672 def test_create_snapshot(self):
2674 vserver_client = mock.Mock()
2675 self.mock_object(self.library,
2676 '_get_vserver',
2677 mock.Mock(return_value=(fake.VSERVER1,
2678 vserver_client)))
2680 model_update = self.library.create_snapshot(
2681 self.context, fake.SNAPSHOT, share_server=fake.SHARE_SERVER)
2683 share_name = self.library._get_backend_share_name(
2684 fake.SNAPSHOT['share_id'])
2685 snapshot_name = self.library._get_backend_snapshot_name(
2686 fake.SNAPSHOT['id'])
2687 vserver_client.create_snapshot.assert_called_once_with(share_name,
2688 snapshot_name)
2689 self.assertEqual(snapshot_name, model_update['provider_location'])
2691 @ddt.data(True, False)
2692 def test_revert_to_snapshot(self, use_snap_provider_location):
2694 vserver_client = mock.Mock()
2695 self.mock_object(self.library,
2696 '_get_vserver',
2697 mock.Mock(return_value=(fake.VSERVER1,
2698 vserver_client)))
2699 vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
2700 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
2701 if use_snap_provider_location:
2702 fake_snapshot['provider_location'] = 'fake-provider-location'
2703 else:
2704 del fake_snapshot['provider_location']
2706 result = self.library.revert_to_snapshot(
2707 self.context, fake_snapshot, share_server=fake.SHARE_SERVER)
2709 self.assertIsNotNone(result)
2710 share_name = self.library._get_backend_share_name(
2711 fake_snapshot['share_id'])
2712 snapshot_name = (self.library._get_backend_snapshot_name(
2713 fake_snapshot['id']) if not use_snap_provider_location
2714 else 'fake-provider-location')
2715 vserver_client.restore_snapshot.assert_called_once_with(share_name,
2716 snapshot_name)
2718 def test_delete_snapshot(self):
2720 vserver_client = mock.Mock()
2721 self.mock_object(self.library,
2722 '_get_vserver',
2723 mock.Mock(return_value=(fake.VSERVER1,
2724 vserver_client)))
2725 mock_is_flexgroup_share = self.mock_object(
2726 self.library, '_is_flexgroup_share', mock.Mock(return_value=False))
2727 mock_delete_snapshot = self.mock_object(self.library,
2728 '_delete_snapshot')
2730 self.library.delete_snapshot(self.context,
2731 fake.SNAPSHOT,
2732 share_server=fake.SHARE_SERVER)
2734 share_name = self.library._get_backend_share_name(
2735 fake.SNAPSHOT['share_id'])
2736 snapshot_name = self.library._get_backend_snapshot_name(
2737 fake.SNAPSHOT['id'])
2738 mock_is_flexgroup_share.assert_called_once_with(vserver_client,
2739 share_name)
2740 mock_delete_snapshot.assert_called_once_with(
2741 vserver_client, share_name, snapshot_name, is_flexgroup=False)
2743 def test_delete_snapshot_with_provider_location(self):
2744 vserver_client = mock.Mock()
2745 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
2746 self.mock_object(self.library,
2747 '_get_vserver',
2748 mock.Mock(return_value=(fake.VSERVER1,
2749 vserver_client)))
2750 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
2751 fake_snapshot['provider_location'] = 'fake_provider_location'
2753 self.library.delete_snapshot(self.context,
2754 fake_snapshot,
2755 share_server=fake.SHARE_SERVER)
2757 share_name = self.library._get_backend_share_name(
2758 fake_snapshot['share_id'])
2759 vserver_client.delete_snapshot.assert_called_once_with(
2760 share_name, fake_snapshot['provider_location'])
2762 @ddt.data(exception.InvalidInput(reason='fake_reason'),
2763 exception.VserverNotSpecified(),
2764 exception.VserverNotFound(vserver='fake_vserver'))
2765 def test_delete_snapshot_no_share_server(self, get_vserver_exception):
2767 self.mock_object(self.library,
2768 '_get_vserver',
2769 mock.Mock(side_effect=get_vserver_exception))
2770 mock_is_flexgroup_share = self.mock_object(
2771 self.library, '_is_flexgroup_share', mock.Mock(return_value=False))
2772 mock_delete_snapshot = self.mock_object(self.library,
2773 '_delete_snapshot')
2775 self.library.delete_snapshot(self.context,
2776 fake.SNAPSHOT,
2777 share_server=fake.SHARE_SERVER)
2779 self.assertFalse(mock_is_flexgroup_share.called)
2780 self.assertFalse(mock_delete_snapshot.called)
2782 def test_delete_snapshot_not_found(self):
2784 vserver_client = mock.Mock()
2785 self.mock_object(self.library,
2786 '_get_vserver',
2787 mock.Mock(return_value=(fake.VSERVER1,
2788 vserver_client)))
2789 mock_is_flexgroup_share = self.mock_object(
2790 self.library, '_is_flexgroup_share', mock.Mock(return_value=False))
2791 mock_delete_snapshot = self.mock_object(
2792 self.library, '_delete_snapshot',
2793 mock.Mock(side_effect=exception.SnapshotResourceNotFound(
2794 name=fake.SNAPSHOT_NAME)))
2796 self.library.delete_snapshot(self.context,
2797 fake.SNAPSHOT,
2798 share_server=fake.SHARE_SERVER)
2800 share_name = self.library._get_backend_share_name(
2801 fake.SNAPSHOT['share_id'])
2802 snapshot_name = self.library._get_backend_snapshot_name(
2803 fake.SNAPSHOT['id'])
2804 mock_is_flexgroup_share.assert_called_once_with(
2805 vserver_client, share_name)
2806 mock_delete_snapshot.assert_called_once_with(
2807 vserver_client, share_name, snapshot_name, is_flexgroup=False)
2809 def test_delete_snapshot_not_unique(self):
2811 vserver_client = mock.Mock()
2812 self.mock_object(self.library,
2813 '_get_vserver',
2814 mock.Mock(return_value=(fake.VSERVER1,
2815 vserver_client)))
2816 mock_is_flexgroup_share = self.mock_object(
2817 self.library, '_is_flexgroup_share', mock.Mock(return_value=False))
2818 mock_delete_snapshot = self.mock_object(
2819 self.library, '_delete_snapshot',
2820 mock.Mock(side_effect=exception.NetAppException()))
2822 self.assertRaises(exception.NetAppException,
2823 self.library.delete_snapshot,
2824 self.context,
2825 fake.SNAPSHOT,
2826 share_server=fake.SHARE_SERVER)
2828 share_name = self.library._get_backend_share_name(
2829 fake.SNAPSHOT['share_id'])
2830 snapshot_name = self.library._get_backend_snapshot_name(
2831 fake.SNAPSHOT['id'])
2832 mock_is_flexgroup_share.assert_called_once_with(
2833 vserver_client, share_name)
2834 mock_delete_snapshot.assert_called_once_with(
2835 vserver_client, share_name, snapshot_name, is_flexgroup=False)
2837 def test__delete_snapshot(self):
2839 vserver_client = mock.Mock()
2840 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
2842 self.library._delete_snapshot(vserver_client,
2843 fake.SHARE_NAME,
2844 fake.SNAPSHOT_NAME)
2846 vserver_client.delete_snapshot.assert_called_once_with(
2847 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2848 self.assertFalse(vserver_client.get_clone_children_for_snapshot.called)
2849 self.assertFalse(vserver_client.volume_clone_split_start.called)
2850 self.assertFalse(vserver_client.soft_delete_snapshot.called)
2852 @ddt.data(True, False)
2853 def test__delete_snapshot_busy_volume_clone(self, is_flexgroup):
2855 vserver_client = mock.Mock()
2856 vserver_client.get_snapshot.return_value = (
2857 fake.CDOT_SNAPSHOT_BUSY_VOLUME_CLONE)
2858 vserver_client.get_clone_children_for_snapshot.return_value = (
2859 fake.CDOT_CLONE_CHILDREN)
2860 mock_is_flexgroup_share = self.mock_object(
2861 self.library, '_delete_busy_snapshot')
2863 self.library._delete_snapshot(vserver_client,
2864 fake.SHARE_NAME,
2865 fake.SNAPSHOT_NAME,
2866 is_flexgroup=is_flexgroup)
2868 self.assertFalse(vserver_client.delete_snapshot.called)
2869 if is_flexgroup:
2870 (vserver_client.
2871 get_clone_children_for_snapshot.assert_called_once_with(
2872 fake.SHARE_NAME, fake.SNAPSHOT_NAME))
2873 vserver_client.volume_clone_split_start.assert_has_calls([
2874 mock.call(fake.CDOT_CLONE_CHILD_1),
2875 mock.call(fake.CDOT_CLONE_CHILD_2),
2876 ])
2877 mock_is_flexgroup_share.assert_called_once_with(
2878 vserver_client, fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2879 vserver_client.soft_delete_snapshot.assert_not_called()
2880 else:
2881 mock_is_flexgroup_share.assert_not_called()
2882 vserver_client.soft_delete_snapshot.assert_called_once_with(
2883 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2885 def test__delete_snapshot_busy_snapmirror(self):
2887 vserver_client = mock.Mock()
2888 vserver_client.get_snapshot.return_value = (
2889 fake.CDOT_SNAPSHOT_BUSY_SNAPMIRROR)
2890 mock_is_flexgroup_share = self.mock_object(
2891 self.library, '_delete_busy_snapshot')
2893 self.assertRaises(exception.ShareSnapshotIsBusy,
2894 self.library._delete_snapshot,
2895 vserver_client,
2896 fake.SHARE_NAME,
2897 fake.SNAPSHOT_NAME)
2899 self.assertFalse(vserver_client.delete_snapshot.called)
2900 self.assertFalse(vserver_client.get_clone_children_for_snapshot.called)
2901 self.assertFalse(vserver_client.volume_clone_split_start.called)
2902 self.assertFalse(mock_is_flexgroup_share.called)
2903 self.assertFalse(vserver_client.soft_delete_snapshot.called)
2905 def test_delete_busy_snapshot(self):
2906 (self.library.configuration.
2907 netapp_delete_busy_flexgroup_snapshot_timeout) = 2
2908 vserver_client = mock.Mock()
2909 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
2911 self.library._delete_busy_snapshot(vserver_client,
2912 fake.SHARE_NAME,
2913 fake.SNAPSHOT_NAME)
2915 vserver_client.get_snapshot.assert_called_once_with(
2916 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2917 vserver_client.delete_snapshot.assert_called_once_with(
2918 fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2920 def test_delete_busy_snapshot_raise_timeout(self):
2921 (self.library.configuration.
2922 netapp_delete_busy_flexgroup_snapshot_timeout) = 2
2923 vserver_client = mock.Mock()
2924 vserver_client.get_snapshot.return_value = (
2925 fake.CDOT_SNAPSHOT_BUSY_VOLUME_CLONE)
2927 self.assertRaises(
2928 exception.NetAppException, self.library._delete_busy_snapshot,
2929 vserver_client, fake.SHARE_NAME, fake.SNAPSHOT_NAME)
2931 @ddt.data(None, fake.VSERVER1)
2932 def test_manage_existing(self, fake_vserver):
2934 vserver_client = mock.Mock()
2935 mock__get_vserver = self.mock_object(
2936 self.library, '_get_vserver',
2937 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
2938 mock_manage_container = self.mock_object(
2939 self.library,
2940 '_manage_container',
2941 mock.Mock(return_value=fake.SHARE_SIZE))
2942 mock_create_export = self.mock_object(
2943 self.library,
2944 '_create_export',
2945 mock.Mock(return_value=fake.NFS_EXPORTS))
2947 result = self.library.manage_existing(fake.SHARE, {},
2948 share_server=fake_vserver)
2950 expected = {
2951 'size': fake.SHARE_SIZE,
2952 'export_locations': fake.NFS_EXPORTS
2953 }
2955 mock__get_vserver.assert_called_once_with(share_server=fake_vserver)
2956 mock_manage_container.assert_called_once_with(fake.SHARE,
2957 fake.VSERVER1,
2958 vserver_client)
2960 mock_create_export.assert_called_once_with(fake.SHARE,
2961 fake_vserver,
2962 fake.VSERVER1,
2963 vserver_client)
2964 self.assertDictEqual(expected, result)
2966 @ddt.data(None, fake.VSERVER1)
2967 def test_unmanage(self, fake_vserver):
2969 result = self.library.unmanage(fake.SHARE, share_server=fake_vserver)
2971 self.assertIsNone(result)
2973 @ddt.data({'qos': True, 'fpolicy': False, 'is_flexgroup': False},
2974 {'qos': False, 'fpolicy': True, 'is_flexgroup': False},
2975 {'qos': True, 'fpolicy': False, 'is_flexgroup': True},
2976 {'qos': False, 'fpolicy': True, 'is_flexgroup': True})
2977 @ddt.unpack
2978 def test_manage_container(self, qos, fpolicy, is_flexgroup):
2980 vserver_client = mock.Mock()
2981 self.library._have_cluster_creds = True
2982 qos_policy_group_name = fake.QOS_POLICY_GROUP_NAME if qos else None
2983 if qos:
2984 extra_specs = copy.deepcopy(fake.EXTRA_SPEC_WITH_QOS)
2985 elif fpolicy: 2985 ↛ 2988line 2985 didn't jump to line 2988 because the condition on line 2985 was always true
2986 extra_specs = copy.deepcopy(fake.EXTRA_SPEC_WITH_FPOLICY)
2987 else:
2988 extra_specs = copy.deepcopy(fake.EXTRA_SPEC)
2989 provisioning_opts = self.library._get_provisioning_options(extra_specs)
2990 if qos:
2991 provisioning_opts['qos_policy_group'] = fake.QOS_POLICY_GROUP_NAME
2993 share_to_manage = copy.deepcopy(fake.SHARE)
2994 share_to_manage['export_location'] = fake.EXPORT_LOCATION
2996 mock_helper = mock.Mock()
2997 mock_helper.get_share_name_for_share.return_value = fake.FLEXVOL_NAME
2998 self.mock_object(self.library,
2999 '_get_helper',
3000 mock.Mock(return_value=mock_helper))
3002 fake_aggr = [fake.POOL_NAME] if is_flexgroup else fake.POOL_NAME
3003 mock_is_flexgroup_pool = self.mock_object(
3004 self.library, '_is_flexgroup_pool',
3005 mock.Mock(return_value=is_flexgroup))
3006 mock_get_flexgroup_aggregate_list = self.mock_object(
3007 self.library, '_get_flexgroup_aggregate_list',
3008 mock.Mock(return_value=fake_aggr))
3009 mock_is_flexgroup_share = self.mock_object(
3010 self.library, '_is_flexgroup_share',
3011 mock.Mock(return_value=is_flexgroup))
3013 mock_get_volume_to_manage = self.mock_object(
3014 vserver_client,
3015 'get_volume_to_manage',
3016 mock.Mock(return_value=fake.FLEXVOL_TO_MANAGE))
3017 mock_validate_volume_for_manage = self.mock_object(
3018 self.library,
3019 '_validate_volume_for_manage')
3020 self.mock_object(share_types,
3021 'get_extra_specs_from_share',
3022 mock.Mock(return_value=extra_specs))
3023 mock_check_extra_specs_validity = self.mock_object(
3024 self.library,
3025 '_check_extra_specs_validity')
3026 mock_check_aggregate_extra_specs_validity = self.mock_object(
3027 self.library,
3028 '_check_aggregate_extra_specs_validity')
3029 mock_modify_or_create_qos_policy = self.mock_object(
3030 self.library, '_modify_or_create_qos_for_existing_share',
3031 mock.Mock(return_value=qos_policy_group_name))
3032 mock_get_volume_snapshot_attributes = self.mock_object(
3033 vserver_client, 'get_volume_snapshot_attributes',
3034 mock.Mock(return_value={'snapshot-policy': 'fake_policy'}))
3035 fake_fpolicy_scope = {
3036 'policy-name': fake.FPOLICY_POLICY_NAME,
3037 'shares-to-include': [fake.FLEXVOL_NAME]
3038 }
3039 mock_find_scope = self.mock_object(
3040 self.library, '_find_reusable_fpolicy_scope',
3041 mock.Mock(return_value=fake_fpolicy_scope))
3042 mock_modify_fpolicy = self.mock_object(
3043 vserver_client, 'modify_fpolicy_scope')
3045 result = self.library._manage_container(share_to_manage,
3046 fake.VSERVER1,
3047 vserver_client)
3049 mock_is_flexgroup_pool.assert_called_once_with(fake.POOL_NAME)
3050 if is_flexgroup:
3051 mock_get_flexgroup_aggregate_list.assert_called_once_with(
3052 fake.POOL_NAME)
3053 else:
3054 mock_get_flexgroup_aggregate_list.assert_not_called()
3055 mock_is_flexgroup_share.assert_called_once_with(vserver_client,
3056 fake.FLEXVOL_NAME)
3057 mock_get_volume_to_manage.assert_called_once_with(
3058 fake_aggr, fake.FLEXVOL_NAME)
3059 mock_check_extra_specs_validity.assert_called_once_with(
3060 share_to_manage, extra_specs)
3061 mock_check_aggregate_extra_specs_validity.assert_called_once_with(
3062 fake.POOL_NAME, extra_specs)
3063 vserver_client.unmount_volume.assert_called_once_with(
3064 fake.FLEXVOL_NAME)
3065 vserver_client.set_volume_name.assert_called_once_with(
3066 fake.FLEXVOL_NAME, fake.SHARE_NAME)
3067 vserver_client.mount_volume.assert_called_once_with(
3068 fake.SHARE_NAME, fake.MOUNT_POINT_NAME)
3069 vserver_client.modify_volume.assert_called_once_with(
3070 fake_aggr, fake.SHARE_NAME, **provisioning_opts)
3071 mock_modify_or_create_qos_policy.assert_called_once_with(
3072 share_to_manage, extra_specs, fake.VSERVER1, vserver_client)
3073 mock_get_volume_snapshot_attributes.assert_called_once_with(
3074 fake.SHARE_NAME)
3075 mock_validate_volume_for_manage.assert_called()
3076 if fpolicy:
3077 mock_find_scope.assert_called_once_with(
3078 share_to_manage, vserver_client,
3079 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
3080 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
3081 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS,
3082 shares_to_include=[fake.FLEXVOL_NAME])
3083 mock_modify_fpolicy.assert_called_once_with(
3084 fake.SHARE_NAME,
3085 fake.FPOLICY_POLICY_NAME, shares_to_include=[fake.SHARE_NAME])
3086 else:
3087 mock_find_scope.assert_not_called()
3088 mock_modify_fpolicy.assert_not_called()
3090 original_data = {
3091 'original_name': fake.FLEXVOL_TO_MANAGE['name'],
3092 'original_junction_path': fake.FLEXVOL_TO_MANAGE['junction-path'],
3093 }
3094 self.library.private_storage.update.assert_called_once_with(
3095 fake.SHARE['id'], original_data)
3097 expected_size = int(
3098 math.ceil(float(fake.FLEXVOL_TO_MANAGE['size']) / units.Gi))
3099 self.assertEqual(expected_size, result)
3101 def test_manage_container_invalid_export_location(self):
3103 vserver_client = mock.Mock()
3105 share_to_manage = copy.deepcopy(fake.SHARE)
3106 share_to_manage['export_location'] = fake.EXPORT_LOCATION
3108 mock_helper = mock.Mock()
3109 mock_helper.get_share_name_for_share.return_value = None
3110 self.mock_object(self.library,
3111 '_get_helper',
3112 mock.Mock(return_value=mock_helper))
3114 self.assertRaises(exception.ManageInvalidShare,
3115 self.library._manage_container,
3116 share_to_manage,
3117 fake.VSERVER1,
3118 vserver_client)
3120 def test_manage_container_not_found(self):
3122 vserver_client = mock.Mock()
3124 share_to_manage = copy.deepcopy(fake.SHARE)
3125 share_to_manage['export_location'] = fake.EXPORT_LOCATION
3127 mock_helper = mock.Mock()
3128 mock_helper.get_share_name_for_share.return_value = fake.FLEXVOL_NAME
3129 self.mock_object(self.library,
3130 '_get_helper',
3131 mock.Mock(return_value=mock_helper))
3133 self.mock_object(self.library, '_is_flexgroup_pool',
3134 mock.Mock(return_value=False))
3135 self.mock_object(self.library, '_is_flexgroup_share',
3136 mock.Mock(return_value=False))
3138 self.mock_object(vserver_client,
3139 'get_volume_to_manage',
3140 mock.Mock(return_value=None))
3142 self.assertRaises(exception.ManageInvalidShare,
3143 self.library._manage_container,
3144 share_to_manage,
3145 fake.VSERVER1,
3146 vserver_client)
3148 def test_manage_container_invalid_extra_specs(self):
3150 vserver_client = mock.Mock()
3152 share_to_manage = copy.deepcopy(fake.SHARE)
3153 share_to_manage['export_location'] = fake.EXPORT_LOCATION
3155 mock_helper = mock.Mock()
3156 mock_helper.get_share_name_for_share.return_value = fake.FLEXVOL_NAME
3157 self.mock_object(self.library,
3158 '_get_helper',
3159 mock.Mock(return_value=mock_helper))
3161 self.mock_object(self.library, '_is_flexgroup_pool',
3162 mock.Mock(return_value=False))
3163 self.mock_object(self.library, '_is_flexgroup_share',
3164 mock.Mock(return_value=False))
3166 self.mock_object(vserver_client,
3167 'get_volume_to_manage',
3168 mock.Mock(return_value=fake.FLEXVOL_TO_MANAGE))
3169 self.mock_object(self.library, '_validate_volume_for_manage')
3170 self.mock_object(share_types,
3171 'get_extra_specs_from_share',
3172 mock.Mock(return_value=fake.EXTRA_SPEC))
3173 self.mock_object(self.library,
3174 '_check_extra_specs_validity',
3175 mock.Mock(side_effect=exception.NetAppException))
3177 self.assertRaises(exception.ManageExistingShareTypeMismatch,
3178 self.library._manage_container,
3179 share_to_manage,
3180 fake.VSERVER1,
3181 vserver_client)
3183 def test_manage_container_invalid_fpolicy(self):
3184 vserver_client = mock.Mock()
3185 extra_spec = copy.deepcopy(fake.EXTRA_SPEC_WITH_FPOLICY)
3186 share_to_manage = copy.deepcopy(fake.SHARE)
3187 share_to_manage['export_location'] = fake.EXPORT_LOCATION
3189 mock_helper = mock.Mock()
3190 mock_helper.get_share_name_for_share.return_value = fake.FLEXVOL_NAME
3191 self.mock_object(self.library,
3192 '_get_helper',
3193 mock.Mock(return_value=mock_helper))
3195 self.mock_object(self.library, '_is_flexgroup_pool',
3196 mock.Mock(return_value=False))
3197 self.mock_object(self.library, '_is_flexgroup_share',
3198 mock.Mock(return_value=False))
3200 self.mock_object(vserver_client,
3201 'get_volume_to_manage',
3202 mock.Mock(return_value=fake.FLEXVOL_TO_MANAGE))
3203 self.mock_object(self.library, '_validate_volume_for_manage')
3204 self.mock_object(share_types,
3205 'get_extra_specs_from_share',
3206 mock.Mock(return_value=extra_spec))
3207 self.mock_object(self.library, '_check_extra_specs_validity')
3208 self.mock_object(self.library, '_find_reusable_fpolicy_scope',
3209 mock.Mock(return_value=None))
3211 self.assertRaises(exception.ManageExistingShareTypeMismatch,
3212 self.library._manage_container,
3213 share_to_manage,
3214 fake.VSERVER1,
3215 vserver_client)
3217 def test_manage_container_wrong_pool_style(self):
3219 vserver_client = mock.Mock()
3221 share_to_manage = copy.deepcopy(fake.SHARE)
3222 share_to_manage['export_location'] = fake.EXPORT_LOCATION
3224 mock_helper = mock.Mock()
3225 mock_helper.get_share_name_for_share.return_value = fake.FLEXVOL_NAME
3226 self.mock_object(self.library,
3227 '_get_helper',
3228 mock.Mock(return_value=mock_helper))
3230 self.mock_object(self.library, '_is_flexgroup_pool',
3231 mock.Mock(return_value=False))
3232 self.mock_object(self.library, '_is_flexgroup_share',
3233 mock.Mock(return_value=True))
3235 self.assertRaises(exception.ManageInvalidShare,
3236 self.library._manage_container,
3237 share_to_manage,
3238 fake.VSERVER1,
3239 vserver_client)
3241 def test_validate_volume_for_manage(self):
3243 vserver_client = mock.Mock()
3244 vserver_client.volume_has_luns = mock.Mock(return_value=False)
3245 vserver_client.volume_has_junctioned_volumes = mock.Mock(
3246 return_value=False)
3247 vserver_client.volume_has_snapmirror_relationships = mock.Mock(
3248 return_value=False)
3250 result = self.library._validate_volume_for_manage(
3251 fake.FLEXVOL_TO_MANAGE, vserver_client)
3253 self.assertIsNone(result)
3255 @ddt.data({
3256 'attribute': 'type',
3257 'value': 'dp',
3258 }, {
3259 'attribute': 'style',
3260 'value': 'infinitevol',
3261 })
3262 @ddt.unpack
3263 def test_validate_volume_for_manage_invalid_volume(self, attribute, value):
3265 flexvol_to_manage = copy.deepcopy(fake.FLEXVOL_TO_MANAGE)
3266 flexvol_to_manage[attribute] = value
3268 vserver_client = mock.Mock()
3269 vserver_client.volume_has_luns = mock.Mock(return_value=False)
3270 vserver_client.volume_has_junctioned_volumes = mock.Mock(
3271 return_value=False)
3272 vserver_client.volume_has_snapmirror_relationships = mock.Mock(
3273 return_value=False)
3275 self.assertRaises(exception.ManageInvalidShare,
3276 self.library._validate_volume_for_manage,
3277 flexvol_to_manage,
3278 vserver_client)
3280 def test_validate_volume_for_manage_luns_present(self):
3282 vserver_client = mock.Mock()
3283 vserver_client.volume_has_luns = mock.Mock(return_value=True)
3284 vserver_client.volume_has_junctioned_volumes = mock.Mock(
3285 return_value=False)
3286 vserver_client.volume_has_snapmirror_relationships = mock.Mock(
3287 return_value=False)
3289 self.assertRaises(exception.ManageInvalidShare,
3290 self.library._validate_volume_for_manage,
3291 fake.FLEXVOL_TO_MANAGE,
3292 vserver_client)
3294 def test_validate_volume_for_manage_junctioned_volumes_present(self):
3296 vserver_client = mock.Mock()
3297 vserver_client.volume_has_luns = mock.Mock(return_value=False)
3298 vserver_client.volume_has_junctioned_volumes = mock.Mock(
3299 return_value=True)
3300 vserver_client.volume_has_snapmirror_relationships = mock.Mock(
3301 return_value=False)
3303 self.assertRaises(exception.ManageInvalidShare,
3304 self.library._validate_volume_for_manage,
3305 fake.FLEXVOL_TO_MANAGE,
3306 vserver_client)
3308 @ddt.data(
3309 {'fake_vserver': None, 'is_flexgroup': False},
3310 {'fake_vserver': fake.VSERVER1, 'is_flexgroup': False},
3311 {'fake_vserver': None, 'is_flexgroup': True},
3312 {'fake_vserver': fake.VSERVER1, 'is_flexgroup': True})
3313 @ddt.unpack
3314 def test_manage_existing_snapshot(self, fake_vserver, is_flexgroup):
3316 vserver_client = mock.Mock()
3317 mock_get_vserver = self.mock_object(
3318 self.library, '_get_vserver',
3319 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3320 vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
3321 vserver_client.snapshot_exists.return_value = True
3322 vserver_client.volume_has_snapmirror_relationships.return_value = False
3324 result = self.library.manage_existing_snapshot(
3325 fake.SNAPSHOT_TO_MANAGE, {}, share_server=fake_vserver)
3327 share_name = self.library._get_backend_share_name(
3328 fake.SNAPSHOT['share_id'])
3329 mock_get_vserver.assert_called_once_with(share_server=fake_vserver)
3330 vserver_client.snapshot_exists.assert_called_once_with(
3331 fake.SNAPSHOT_NAME, share_name)
3332 (vserver_client.volume_has_snapmirror_relationships.
3333 assert_called_once_with(fake.FLEXVOL_TO_MANAGE))
3334 expected_result = {'size': 2}
3335 self.assertEqual(expected_result, result)
3337 def test_manage_existing_snapshot_no_snapshot_name(self):
3339 vserver_client = mock.Mock()
3340 self.mock_object(self.library,
3341 '_get_vserver',
3342 mock.Mock(return_value=(fake.VSERVER1,
3343 vserver_client)))
3344 vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
3345 vserver_client.snapshot_exists.return_value = True
3346 vserver_client.volume_has_snapmirror_relationships.return_value = False
3347 fake_snapshot = copy.deepcopy(fake.SNAPSHOT_TO_MANAGE)
3348 fake_snapshot['provider_location'] = ''
3350 self.assertRaises(exception.ManageInvalidShareSnapshot,
3351 self.library.manage_existing_snapshot,
3352 fake_snapshot, {})
3354 @ddt.data(netapp_api.NaApiError,
3355 exception.NetAppException)
3356 def test_manage_existing_snapshot_get_volume_error(self, exception_type):
3358 vserver_client = mock.Mock()
3359 self.mock_object(self.library,
3360 '_get_vserver',
3361 mock.Mock(return_value=(fake.VSERVER1,
3362 vserver_client)))
3363 vserver_client.get_volume.side_effect = exception_type
3364 self.mock_object(self.client,
3365 'volume_has_snapmirror_relationships',
3366 mock.Mock(return_value=False))
3368 self.assertRaises(exception.ShareNotFound,
3369 self.library.manage_existing_snapshot,
3370 fake.SNAPSHOT_TO_MANAGE, {})
3372 def test_manage_existing_snapshot_not_from_share(self):
3374 vserver_client = mock.Mock()
3375 self.mock_object(self.library,
3376 '_get_vserver',
3377 mock.Mock(return_value=(fake.VSERVER1,
3378 vserver_client)))
3379 vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
3380 vserver_client.snapshot_exists.return_value = False
3382 self.assertRaises(exception.ManageInvalidShareSnapshot,
3383 self.library.manage_existing_snapshot,
3384 fake.SNAPSHOT_TO_MANAGE, {})
3386 def test_manage_existing_snapshot_mirrors_present(self):
3388 vserver_client = mock.Mock()
3389 self.mock_object(self.library,
3390 '_get_vserver',
3391 mock.Mock(return_value=(fake.VSERVER1,
3392 vserver_client)))
3393 vserver_client.get_volume.return_value = fake.FLEXVOL_TO_MANAGE
3394 vserver_client.snapshot_exists.return_value = True
3395 vserver_client.volume_has_snapmirror_relationships.return_value = True
3397 self.assertRaises(exception.ManageInvalidShareSnapshot,
3398 self.library.manage_existing_snapshot,
3399 fake.SNAPSHOT_TO_MANAGE, {})
3401 @ddt.data(None, fake.VSERVER1)
3402 def test_unmanage_snapshot(self, fake_vserver):
3404 result = self.library.unmanage_snapshot(fake.SNAPSHOT, fake_vserver)
3406 self.assertIsNone(result)
3408 def test_validate_volume_for_manage_snapmirror_relationships_present(self):
3410 vserver_client = mock.Mock()
3411 vserver_client.volume_has_luns.return_value = False
3412 vserver_client.volume_has_junctioned_volumes.return_value = False
3413 vserver_client.volume_has_snapmirror_relationships.return_value = True
3415 self.assertRaises(exception.ManageInvalidShare,
3416 self.library._validate_volume_for_manage,
3417 fake.FLEXVOL_TO_MANAGE,
3418 vserver_client)
3420 def test_create_consistency_group_from_cgsnapshot(self):
3422 vserver_client = mock.Mock()
3423 mock_get_vserver = self.mock_object(
3424 self.library, '_get_vserver',
3425 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3426 mock_allocate_container_from_snapshot = self.mock_object(
3427 self.library, '_allocate_container_from_snapshot')
3428 mock_create_export = self.mock_object(
3429 self.library, '_create_export',
3430 mock.Mock(side_effect=[['loc3'], ['loc4']]))
3432 result = self.library.create_consistency_group_from_cgsnapshot(
3433 self.context,
3434 fake.CONSISTENCY_GROUP_DEST,
3435 fake.CG_SNAPSHOT,
3436 share_server=fake.SHARE_SERVER)
3438 share_update_list = [
3439 {'id': fake.SHARE_ID3, 'export_locations': ['loc3']},
3440 {'id': fake.SHARE_ID4, 'export_locations': ['loc4']}
3441 ]
3442 expected = (None, share_update_list)
3443 self.assertEqual(expected, result)
3445 mock_allocate_container_from_snapshot.assert_has_calls([
3446 mock.call(fake.COLLATED_CGSNAPSHOT_INFO[0]['share'],
3447 fake.COLLATED_CGSNAPSHOT_INFO[0]['snapshot'],
3448 fake.VSERVER1,
3449 vserver_client,
3450 mock.ANY),
3451 mock.call(fake.COLLATED_CGSNAPSHOT_INFO[1]['share'],
3452 fake.COLLATED_CGSNAPSHOT_INFO[1]['snapshot'],
3453 fake.VSERVER1,
3454 vserver_client,
3455 mock.ANY),
3456 ])
3457 mock_create_export.assert_has_calls([
3458 mock.call(fake.COLLATED_CGSNAPSHOT_INFO[0]['share'],
3459 fake.SHARE_SERVER,
3460 fake.VSERVER1,
3461 vserver_client),
3462 mock.call(fake.COLLATED_CGSNAPSHOT_INFO[1]['share'],
3463 fake.SHARE_SERVER,
3464 fake.VSERVER1,
3465 vserver_client),
3466 ])
3467 mock_get_vserver.assert_called_once_with(
3468 share_server=fake.SHARE_SERVER)
3470 def test_create_consistency_group_from_cgsnapshot_no_members(self):
3472 vserver_client = mock.Mock()
3473 mock_get_vserver = self.mock_object(
3474 self.library, '_get_vserver',
3475 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3476 mock_allocate_container_from_snapshot = self.mock_object(
3477 self.library, '_allocate_container_from_snapshot')
3478 mock_create_export = self.mock_object(
3479 self.library, '_create_export',
3480 mock.Mock(side_effect=[['loc3'], ['loc4']]))
3482 fake_cg_snapshot = copy.deepcopy(fake.CG_SNAPSHOT)
3483 fake_cg_snapshot['share_group_snapshot_members'] = []
3485 result = self.library.create_consistency_group_from_cgsnapshot(
3486 self.context,
3487 fake.CONSISTENCY_GROUP_DEST,
3488 fake_cg_snapshot,
3489 share_server=fake.SHARE_SERVER)
3491 self.assertEqual((None, None), result)
3493 self.assertFalse(mock_allocate_container_from_snapshot.called)
3494 self.assertFalse(mock_create_export.called)
3495 mock_get_vserver.assert_called_once_with(
3496 share_server=fake.SHARE_SERVER)
3498 def test_collate_cg_snapshot_info(self):
3500 result = self.library._collate_cg_snapshot_info(
3501 fake.CONSISTENCY_GROUP_DEST, fake.CG_SNAPSHOT)
3503 self.assertEqual(fake.COLLATED_CGSNAPSHOT_INFO, result)
3505 def test_collate_cg_snapshot_info_invalid(self):
3507 fake_cg_snapshot = copy.deepcopy(fake.CG_SNAPSHOT)
3508 fake_cg_snapshot['share_group_snapshot_members'] = []
3510 self.assertRaises(exception.InvalidShareGroup,
3511 self.library._collate_cg_snapshot_info,
3512 fake.CONSISTENCY_GROUP_DEST, fake_cg_snapshot)
3514 def test_create_cgsnapshot(self):
3516 vserver_client = mock.Mock()
3517 mock_get_vserver = self.mock_object(
3518 self.library, '_get_vserver',
3519 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3521 result = self.library.create_cgsnapshot(
3522 self.context,
3523 fake.CG_SNAPSHOT,
3524 share_server=fake.SHARE_SERVER)
3526 share_names = [
3527 self.library._get_backend_share_name(
3528 fake.CG_SNAPSHOT_MEMBER_1['share_id']),
3529 self.library._get_backend_share_name(
3530 fake.CG_SNAPSHOT_MEMBER_2['share_id'])
3531 ]
3532 snapshot_name = self.library._get_backend_cg_snapshot_name(
3533 fake.CG_SNAPSHOT['id'])
3534 vserver_client.create_cg_snapshot.assert_called_once_with(
3535 share_names, snapshot_name)
3536 self.assertEqual((None, None), result)
3537 mock_get_vserver.assert_called_once_with(
3538 share_server=fake.SHARE_SERVER)
3540 def test_create_cgsnapshot_no_members(self):
3542 vserver_client = mock.Mock()
3543 mock_get_vserver = self.mock_object(
3544 self.library, '_get_vserver',
3545 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3547 fake_cg_snapshot = copy.deepcopy(fake.CG_SNAPSHOT)
3548 fake_cg_snapshot['share_group_snapshot_members'] = []
3550 result = self.library.create_cgsnapshot(
3551 self.context,
3552 fake_cg_snapshot,
3553 share_server=fake.SHARE_SERVER)
3555 self.assertFalse(vserver_client.create_cg_snapshot.called)
3556 self.assertEqual((None, None), result)
3557 mock_get_vserver.assert_called_once_with(
3558 share_server=fake.SHARE_SERVER)
3560 def test_delete_cgsnapshot(self):
3562 vserver_client = mock.Mock()
3563 mock_get_vserver = self.mock_object(
3564 self.library, '_get_vserver',
3565 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3566 mock_delete_snapshot = self.mock_object(self.library,
3567 '_delete_snapshot')
3569 result = self.library.delete_cgsnapshot(
3570 self.context,
3571 fake.CG_SNAPSHOT,
3572 share_server=fake.SHARE_SERVER)
3574 share_names = [
3575 self.library._get_backend_share_name(
3576 fake.CG_SNAPSHOT_MEMBER_1['share_id']),
3577 self.library._get_backend_share_name(
3578 fake.CG_SNAPSHOT_MEMBER_2['share_id'])
3579 ]
3580 snapshot_name = self.library._get_backend_cg_snapshot_name(
3581 fake.CG_SNAPSHOT['id'])
3583 mock_delete_snapshot.assert_has_calls([
3584 mock.call(vserver_client, share_names[0], snapshot_name),
3585 mock.call(vserver_client, share_names[1], snapshot_name)
3586 ])
3587 self.assertEqual((None, None), result)
3588 mock_get_vserver.assert_called_once_with(
3589 share_server=fake.SHARE_SERVER)
3591 def test_delete_cgsnapshot_no_members(self):
3593 vserver_client = mock.Mock()
3594 mock_get_vserver = self.mock_object(
3595 self.library, '_get_vserver',
3596 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3597 mock_delete_snapshot = self.mock_object(self.library,
3598 '_delete_snapshot')
3600 fake_cg_snapshot = copy.deepcopy(fake.CG_SNAPSHOT)
3601 fake_cg_snapshot['share_group_snapshot_members'] = []
3603 result = self.library.delete_cgsnapshot(
3604 self.context,
3605 fake_cg_snapshot,
3606 share_server=fake.SHARE_SERVER)
3608 self.assertFalse(mock_delete_snapshot.called)
3609 self.assertEqual((None, None), result)
3610 mock_get_vserver.assert_called_once_with(
3611 share_server=fake.SHARE_SERVER)
3613 def test_delete_cgsnapshot_snapshots_not_found(self):
3615 vserver_client = mock.Mock()
3616 mock_get_vserver = self.mock_object(
3617 self.library, '_get_vserver',
3618 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3619 mock_delete_snapshot = self.mock_object(
3620 self.library, '_delete_snapshot',
3621 mock.Mock(side_effect=exception.SnapshotResourceNotFound(
3622 name='fake')))
3624 result = self.library.delete_cgsnapshot(
3625 self.context,
3626 fake.CG_SNAPSHOT,
3627 share_server=fake.SHARE_SERVER)
3629 share_names = [
3630 self.library._get_backend_share_name(
3631 fake.CG_SNAPSHOT_MEMBER_1['share_id']),
3632 self.library._get_backend_share_name(
3633 fake.CG_SNAPSHOT_MEMBER_2['share_id'])
3634 ]
3635 snapshot_name = self.library._get_backend_cg_snapshot_name(
3636 fake.CG_SNAPSHOT['id'])
3638 mock_delete_snapshot.assert_has_calls([
3639 mock.call(vserver_client, share_names[0], snapshot_name),
3640 mock.call(vserver_client, share_names[1], snapshot_name)
3641 ])
3642 self.assertEqual((None, None), result)
3643 mock_get_vserver.assert_called_once_with(
3644 share_server=fake.SHARE_SERVER)
3646 @ddt.data(exception.InvalidInput(reason='fake_reason'),
3647 exception.VserverNotSpecified(),
3648 exception.VserverNotFound(vserver='fake_vserver'))
3649 def test_delete_cgsnapshot_no_share_server(self,
3650 get_vserver_exception):
3652 mock_get_vserver = self.mock_object(
3653 self.library, '_get_vserver',
3654 mock.Mock(side_effect=get_vserver_exception))
3656 result = self.library.delete_cgsnapshot(
3657 self.context,
3658 fake.EMPTY_CONSISTENCY_GROUP,
3659 share_server=fake.SHARE_SERVER)
3661 self.assertEqual((None, None), result)
3662 self.assertEqual(1, lib_base.LOG.warning.call_count)
3663 mock_get_vserver.assert_called_once_with(
3664 share_server=fake.SHARE_SERVER)
3666 def test_adjust_qos_policy_with_volume_resize_no_cluster_creds(self):
3667 self.library._have_cluster_creds = False
3668 self.mock_object(share_types, 'get_extra_specs_from_share')
3670 retval = self.library._adjust_qos_policy_with_volume_resize(
3671 fake.SHARE, 10, mock.Mock())
3673 self.assertIsNone(retval)
3674 share_types.get_extra_specs_from_share.assert_not_called()
3676 def test_adjust_qos_policy_with_volume_resize_no_qos_on_share(self):
3677 self.library._have_cluster_creds = True
3678 self.mock_object(share_types, 'get_extra_specs_from_share')
3679 vserver_client = mock.Mock()
3680 self.mock_object(vserver_client, 'get_volume',
3681 mock.Mock(return_value=fake.FLEXVOL_WITHOUT_QOS))
3683 retval = self.library._adjust_qos_policy_with_volume_resize(
3684 fake.SHARE, 10, vserver_client)
3686 self.assertIsNone(retval)
3687 share_types.get_extra_specs_from_share.assert_not_called()
3689 def test_adjust_qos_policy_with_volume_resize_no_size_dependent_qos(self):
3690 self.library._have_cluster_creds = True
3691 self.mock_object(share_types, 'get_extra_specs_from_share',
3692 mock.Mock(return_value=fake.EXTRA_SPEC_WITH_QOS))
3693 vserver_client = mock.Mock()
3694 self.mock_object(vserver_client, 'get_volume',
3695 mock.Mock(return_value=fake.FLEXVOL_WITH_QOS))
3696 self.mock_object(self.library, '_get_max_throughput')
3697 self.mock_object(self.library._client, 'qos_policy_group_modify')
3699 retval = self.library._adjust_qos_policy_with_volume_resize(
3700 fake.SHARE, 10, vserver_client)
3702 self.assertIsNone(retval)
3703 share_types.get_extra_specs_from_share.assert_called_once_with(
3704 fake.SHARE)
3705 self.library._get_max_throughput.assert_not_called()
3706 self.library._client.qos_policy_group_modify.assert_not_called()
3708 def test_adjust_qos_policy_with_volume_resize(self):
3709 self.library._have_cluster_creds = True
3710 self.mock_object(
3711 share_types, 'get_extra_specs_from_share',
3712 mock.Mock(return_value=fake.EXTRA_SPEC_WITH_SIZE_DEPENDENT_QOS))
3713 vserver_client = mock.Mock()
3714 self.mock_object(vserver_client, 'get_volume',
3715 mock.Mock(return_value=fake.FLEXVOL_WITH_QOS))
3716 self.mock_object(self.library._client, 'qos_policy_group_modify')
3718 retval = self.library._adjust_qos_policy_with_volume_resize(
3719 fake.SHARE, 10, vserver_client)
3721 expected_max_throughput = '10000B/s'
3722 self.assertIsNone(retval)
3723 share_types.get_extra_specs_from_share.assert_called_once_with(
3724 fake.SHARE)
3725 self.library._client.qos_policy_group_modify.assert_called_once_with(
3726 fake.QOS_POLICY_GROUP_NAME, expected_max_throughput, None)
3728 def test_extend_share(self):
3730 vserver_client = mock.Mock()
3731 self.mock_object(self.library,
3732 '_get_vserver',
3733 mock.Mock(return_value=(fake.VSERVER1,
3734 vserver_client)))
3735 self.mock_object(
3736 share_types, 'get_extra_specs_from_share',
3737 mock.Mock(return_value=fake.EXTRA_SPEC))
3738 mock_adjust_qos_policy = self.mock_object(
3739 self.library, '_adjust_qos_policy_with_volume_resize')
3741 mock_set_volume_size = self.mock_object(vserver_client,
3742 'set_volume_size')
3743 new_size = fake.SHARE['size'] * 2
3745 self.library.extend_share(fake.SHARE, new_size)
3747 mock_set_volume_size.assert_called_once_with(fake.SHARE_NAME, new_size)
3748 mock_adjust_qos_policy.assert_called_once_with(
3749 fake.SHARE, new_size, vserver_client)
3751 def test_shrink_share(self):
3753 vserver_client = mock.Mock()
3754 self.mock_object(self.library,
3755 '_get_vserver',
3756 mock.Mock(return_value=(fake.VSERVER1,
3757 vserver_client)))
3758 self.mock_object(share_types, 'get_extra_specs_from_share')
3759 self.mock_object(self.library, '_get_provisioning_options',
3760 mock.Mock(return_value={}))
3761 mock_adjust_qos_policy = self.mock_object(
3762 self.library, '_adjust_qos_policy_with_volume_resize')
3763 mock_set_volume_size = self.mock_object(vserver_client,
3764 'set_volume_size')
3765 new_size = fake.SHARE['size'] - 1
3767 self.library.shrink_share(fake.SHARE, new_size)
3769 mock_set_volume_size.assert_called_once_with(fake.SHARE_NAME, new_size)
3770 mock_adjust_qos_policy.assert_called_once_with(
3771 fake.SHARE, new_size, vserver_client)
3773 def test_shrinking_possible_data_loss(self):
3775 naapi_error = self._mock_api_error(code=netapp_api.EVOLOPNOTSUPP,
3776 message='Possible data loss')
3778 vserver_client = mock.Mock()
3779 self.mock_object(self.library,
3780 '_get_vserver',
3781 mock.Mock(return_value=(fake.VSERVER1,
3782 vserver_client)))
3784 mock_set_volume_size = self.mock_object(
3785 vserver_client, 'set_volume_size', naapi_error)
3786 self.mock_object(share_types, 'get_extra_specs_from_share')
3787 self.mock_object(self.library, '_get_provisioning_options',
3788 mock.Mock(return_value={}))
3790 new_size = fake.SHARE['size'] - 1
3792 self.assertRaises(exception.ShareShrinkingPossibleDataLoss,
3793 self.library.shrink_share,
3794 fake.SHARE, new_size)
3796 self.library._get_vserver.assert_called_once_with(share_server=None)
3797 mock_set_volume_size.assert_called_once_with(fake.SHARE_NAME, new_size)
3799 def test_update_access(self):
3801 vserver_client = mock.Mock()
3802 mock_get_vserver = self.mock_object(
3803 self.library, '_get_vserver',
3804 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3805 protocol_helper = mock.Mock()
3806 protocol_helper.update_access.return_value = None
3807 self.mock_object(self.library,
3808 '_get_helper',
3809 mock.Mock(return_value=protocol_helper))
3810 self.mock_object(self.library,
3811 '_is_readable_replica',
3812 mock.Mock(return_value=True))
3813 mock_share_exists = self.mock_object(self.library,
3814 '_share_exists',
3815 mock.Mock(return_value=True))
3817 self.library.update_access(self.context,
3818 fake.SHARE,
3819 [fake.SHARE_ACCESS],
3820 [],
3821 [],
3822 [],
3823 share_server=fake.SHARE_SERVER)
3825 mock_get_vserver.assert_called_once_with(
3826 share_server=fake.SHARE_SERVER)
3827 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
3828 mock_share_exists.assert_called_once_with(share_name, vserver_client)
3829 protocol_helper.set_client.assert_called_once_with(vserver_client)
3830 protocol_helper.update_access.assert_called_once_with(
3831 fake.SHARE, fake.SHARE_NAME, [fake.SHARE_ACCESS])
3833 @ddt.data(exception.InvalidInput(reason='fake_reason'),
3834 exception.VserverNotSpecified(),
3835 exception.VserverNotFound(vserver='fake_vserver'))
3836 def test_update_access_no_share_server(self, get_vserver_exception):
3838 mock_get_vserver = self.mock_object(
3839 self.library, '_get_vserver',
3840 mock.Mock(side_effect=get_vserver_exception))
3841 protocol_helper = mock.Mock()
3842 protocol_helper.update_access.return_value = None
3843 self.mock_object(self.library,
3844 '_get_helper',
3845 mock.Mock(return_value=protocol_helper))
3846 self.mock_object(self.library,
3847 '_is_readable_replica',
3848 mock.Mock(return_value=True))
3849 mock_share_exists = self.mock_object(self.library, '_share_exists')
3851 self.library.update_access(self.context,
3852 fake.SHARE,
3853 [fake.SHARE_ACCESS],
3854 [],
3855 [],
3856 [],
3857 share_server=fake.SHARE_SERVER)
3859 mock_get_vserver.assert_called_once_with(
3860 share_server=fake.SHARE_SERVER)
3861 self.assertFalse(mock_share_exists.called)
3862 self.assertFalse(protocol_helper.set_client.called)
3863 self.assertFalse(protocol_helper.update_access.called)
3865 def test_update_access_share_not_found(self):
3867 vserver_client = mock.Mock()
3868 mock_get_vserver = self.mock_object(
3869 self.library, '_get_vserver',
3870 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3871 protocol_helper = mock.Mock()
3872 protocol_helper.update_access.return_value = None
3873 self.mock_object(self.library,
3874 '_get_helper',
3875 mock.Mock(return_value=protocol_helper))
3876 self.mock_object(self.library,
3877 '_is_readable_replica',
3878 mock.Mock(return_value=True))
3879 mock_share_exists = self.mock_object(self.library,
3880 '_share_exists',
3881 mock.Mock(return_value=False))
3883 self.assertRaises(exception.ShareResourceNotFound,
3884 self.library.update_access,
3885 self.context,
3886 fake.SHARE,
3887 [fake.SHARE_ACCESS],
3888 [],
3889 [],
3890 [],
3891 share_server=fake.SHARE_SERVER)
3893 mock_get_vserver.assert_called_once_with(
3894 share_server=fake.SHARE_SERVER)
3895 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
3896 mock_share_exists.assert_called_once_with(share_name, vserver_client)
3897 self.assertFalse(protocol_helper.set_client.called)
3898 self.assertFalse(protocol_helper.update_access.called)
3900 def test_update_access_to_active_replica(self):
3901 fake_share_copy = copy.deepcopy(fake.SHARE)
3902 fake_share_copy['replica_state'] = constants.REPLICA_STATE_ACTIVE
3903 vserver_client = mock.Mock()
3904 mock_get_vserver = self.mock_object(
3905 self.library, '_get_vserver',
3906 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3907 self.mock_object(self.library,
3908 '_is_readable_replica',
3909 mock.Mock(return_value=True))
3910 protocol_helper = mock.Mock()
3911 protocol_helper.update_access.return_value = None
3912 self.mock_object(self.library,
3913 '_get_helper',
3914 mock.Mock(return_value=protocol_helper))
3915 mock_share_exists = self.mock_object(self.library,
3916 '_share_exists',
3917 mock.Mock(return_value=True))
3919 self.library.update_access(self.context,
3920 fake_share_copy,
3921 [fake.SHARE_ACCESS],
3922 [],
3923 [],
3924 [],
3925 share_server=fake.SHARE_SERVER)
3927 mock_get_vserver.assert_called_once_with(
3928 share_server=fake.SHARE_SERVER)
3929 share_name = self.library._get_backend_share_name(fake.SHARE['id'])
3930 mock_share_exists.assert_called_once_with(share_name, vserver_client)
3931 protocol_helper.set_client.assert_called_once_with(vserver_client)
3932 protocol_helper.update_access.assert_called_once_with(
3933 fake.SHARE, fake.SHARE_NAME, [fake.SHARE_ACCESS])
3935 @ddt.data(True, False)
3936 def test_update_access_to_in_sync_replica(self, is_readable):
3938 fake_share_copy = copy.deepcopy(fake.SHARE)
3939 self.mock_object(self.library,
3940 '_is_readable_replica',
3941 mock.Mock(return_value=is_readable))
3942 fake_share_copy['replica_state'] = constants.REPLICA_STATE_IN_SYNC
3943 vserver_client = mock.Mock()
3944 mock_get_vserver = self.mock_object(
3945 self.library, '_get_vserver',
3946 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
3947 protocol_helper = mock.Mock()
3948 protocol_helper.update_access.return_value = None
3949 self.mock_object(self.library,
3950 '_get_helper',
3951 mock.Mock(return_value=protocol_helper))
3952 self.mock_object(self.library, '_share_exists',
3953 mock.Mock(return_value=True))
3955 self.library.update_access(self.context,
3956 fake_share_copy,
3957 [fake.SHARE_ACCESS],
3958 [],
3959 [],
3960 [],
3961 share_server=fake.SHARE_SERVER)
3963 if is_readable:
3964 mock_get_vserver.assert_called_once_with(
3965 share_server=fake.SHARE_SERVER)
3966 else:
3967 mock_get_vserver.assert_not_called()
3969 def test_setup_server(self):
3970 self.assertRaises(NotImplementedError,
3971 self.library.setup_server,
3972 fake.NETWORK_INFO)
3974 def test_teardown_server(self):
3975 self.assertRaises(NotImplementedError,
3976 self.library.teardown_server,
3977 fake.SHARE_SERVER['backend_details'])
3979 def test_get_network_allocations_number(self):
3980 self.assertRaises(NotImplementedError,
3981 self.library.get_network_allocations_number)
3983 def test_update_ssc_info(self):
3985 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
3986 self.library._have_cluster_creds = True
3987 self.mock_object(self.library,
3988 '_find_matching_aggregates',
3989 mock.Mock(return_value=fake.AGGREGATES))
3990 self.mock_object(self.library,
3991 '_get_flexgroup_aggr_set',
3992 mock.Mock(return_value=fake.FLEXGROUP_AGGR_SET))
3993 self.mock_object(self.library,
3994 '_get_aggregate_info',
3995 mock.Mock(return_value=fake.SSC_INFO_MAP))
3997 self.library._update_ssc_info()
3999 expected = {
4000 fake.AGGREGATES[0]: {
4001 'netapp_aggregate': fake.AGGREGATES[0],
4002 'netapp_flexgroup': False,
4003 'netapp_raid_type': 'raid4',
4004 'netapp_disk_type': ['FCAL'],
4005 'netapp_hybrid_aggregate': 'false',
4006 'netapp_snaplock_type': ['compliance', 'enterprise'],
4007 },
4008 fake.AGGREGATES[1]: {
4009 'netapp_aggregate': fake.AGGREGATES[1],
4010 'netapp_flexgroup': False,
4011 'netapp_raid_type': 'raid_dp',
4012 'netapp_disk_type': ['SATA', 'SSD'],
4013 'netapp_hybrid_aggregate': 'true',
4014 'netapp_snaplock_type': ['compliance', 'enterprise'],
4015 },
4016 fake.FLEXGROUP_POOL_NAME: {
4017 'netapp_aggregate': fake.FLEXGROUP_POOL['netapp_aggregate'],
4018 'netapp_flexgroup': True,
4019 'netapp_raid_type': 'raid4 raid_dp',
4020 'netapp_disk_type': ['FCAL', 'SATA', 'SSD'],
4021 'netapp_hybrid_aggregate': 'false true',
4022 'netapp_snaplock_type': fake.FLEXGROUP_POOL[
4023 'netapp_snaplock_type']
4024 },
4025 }
4027 self.assertEqual(expected, self.library._ssc_stats)
4029 def test_update_ssc_info_non_unified_aggr(self):
4031 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
4032 self.library._client.features.UNIFIED_AGGR = False
4033 self.library._have_cluster_creds = True
4034 self.mock_object(self.library,
4035 '_find_matching_aggregates',
4036 mock.Mock(return_value=fake.AGGREGATES))
4037 self.mock_object(self.library,
4038 '_get_flexgroup_aggr_set',
4039 mock.Mock(return_value=fake.FLEXGROUP_AGGR_SET))
4040 self.mock_object(self.library,
4041 '_get_aggregate_info',
4042 mock.Mock(return_value=fake.SSC_INFO_MAP))
4044 self.library._update_ssc_info()
4046 expected = {
4047 fake.AGGREGATES[0]: {
4048 'netapp_aggregate': fake.AGGREGATES[0],
4049 'netapp_flexgroup': False,
4050 'netapp_raid_type': 'raid4',
4051 'netapp_disk_type': ['FCAL'],
4052 'netapp_hybrid_aggregate': 'false',
4053 'netapp_snaplock_type': 'compliance',
4054 },
4055 fake.AGGREGATES[1]: {
4056 'netapp_aggregate': fake.AGGREGATES[1],
4057 'netapp_flexgroup': False,
4058 'netapp_raid_type': 'raid_dp',
4059 'netapp_disk_type': ['SATA', 'SSD'],
4060 'netapp_hybrid_aggregate': 'true',
4061 'netapp_snaplock_type': 'enterprise',
4062 },
4063 fake.FLEXGROUP_POOL_NAME: {
4064 'netapp_aggregate': fake.FLEXGROUP_POOL['netapp_aggregate'],
4065 'netapp_flexgroup': True,
4066 'netapp_raid_type': 'raid4 raid_dp',
4067 'netapp_disk_type': ['FCAL', 'SATA', 'SSD'],
4068 'netapp_hybrid_aggregate': 'false true',
4069 'netapp_snaplock_type': 'compliance enterprise',
4070 },
4071 }
4072 self.assertEqual(expected, self.library._ssc_stats)
4074 def test_update_ssc_info_no_aggregates(self):
4076 self.library._flexgroup_pools = {}
4077 self.mock_object(self.library,
4078 '_find_matching_aggregates',
4079 mock.Mock(return_value=[]))
4081 self.library._update_ssc_info()
4083 self.assertDictEqual({}, self.library._ssc_stats)
4085 def test_update_ssc_info_no_cluster_creds(self):
4087 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
4088 self.library._have_cluster_creds = False
4089 self.mock_object(self.library,
4090 '_find_matching_aggregates',
4091 mock.Mock(return_value=fake.AGGREGATES))
4092 self.mock_object(self.library,
4093 '_get_flexgroup_aggr_set',
4094 mock.Mock(return_value=fake.FLEXGROUP_AGGR_SET))
4095 self.mock_object(self.library,
4096 '_get_aggregate_info',
4097 mock.Mock(return_value=fake.SSC_INFO_MAP))
4098 self.mock_object(self.client,
4099 'get_vserver_aggr_snaplock_type',
4100 mock.Mock(return_value='compliance'))
4102 self.library._update_ssc_info()
4104 expected = {
4105 fake.AGGREGATES[0]: {
4106 'netapp_aggregate': fake.AGGREGATES[0],
4107 'netapp_flexgroup': False,
4108 'netapp_snaplock_type': ['compliance', 'enterprise'],
4109 },
4110 fake.AGGREGATES[1]: {
4111 'netapp_aggregate': fake.AGGREGATES[1],
4112 'netapp_flexgroup': False,
4113 'netapp_snaplock_type': ['compliance', 'enterprise'],
4114 },
4115 fake.FLEXGROUP_POOL_NAME: {
4116 'netapp_aggregate': fake.FLEXGROUP_POOL['netapp_aggregate'],
4117 'netapp_flexgroup': True,
4118 },
4119 }
4121 self.assertDictEqual(self.library._ssc_stats, expected)
4123 def test_get_aggregate_info(self):
4124 mock_get_aggregate = self.mock_object(
4125 self.client, 'get_aggregate',
4126 mock.Mock(side_effect=fake.SSC_AGGREGATES))
4127 mock_get_aggregate_disk_types = self.mock_object(
4128 self.client, 'get_aggregate_disk_types',
4129 mock.Mock(side_effect=fake.SSC_DISK_TYPES))
4131 result = self.library._get_aggregate_info(fake.AGGREGATES)
4133 expected = {
4134 fake.AGGREGATES[0]: {
4135 'netapp_raid_type': 'raid4',
4136 'netapp_disk_type': 'FCAL',
4137 'netapp_hybrid_aggregate': 'false',
4138 'netapp_is_home': False,
4139 'netapp_snaplock_type': 'compliance',
4140 },
4141 fake.AGGREGATES[1]: {
4142 'netapp_raid_type': 'raid_dp',
4143 'netapp_disk_type': ['SATA', 'SSD'],
4144 'netapp_hybrid_aggregate': 'true',
4145 'netapp_is_home': True,
4146 'netapp_snaplock_type': 'enterprise',
4147 },
4148 }
4150 self.assertDictEqual(result, expected)
4151 mock_get_aggregate.assert_has_calls([
4152 mock.call(fake.AGGREGATES[0]),
4153 mock.call(fake.AGGREGATES[1]),
4154 ])
4155 mock_get_aggregate_disk_types.assert_has_calls([
4156 mock.call(fake.AGGREGATES[0]),
4157 mock.call(fake.AGGREGATES[1]),
4158 ])
4160 @ddt.data(
4161 {'is_readable': True, 'rules_status': constants.STATUS_ACTIVE},
4162 {'is_readable': True, 'rules_status': (
4163 constants.SHARE_INSTANCE_RULES_ERROR)},
4164 {'is_readable': False, 'rules_status': constants.STATUS_ACTIVE})
4165 @ddt.unpack
4166 def test_create_replica(self, is_readable, rules_status):
4168 vserver_client = mock.Mock()
4169 self.mock_object(self.library,
4170 '_allocate_container')
4171 mock_dm_session = mock.Mock()
4172 self.mock_object(data_motion, "DataMotionSession",
4173 mock.Mock(return_value=mock_dm_session))
4174 self.mock_object(data_motion, 'get_client_for_backend',
4175 mock.Mock(return_value=vserver_client))
4176 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4177 mock.Mock(return_value=fake.VSERVER1))
4178 self.mock_object(self.library, '_get_backend_share_name',
4179 mock.Mock(return_value=fake.SHARE_NAME))
4180 mock_is_readable = self.mock_object(
4181 self.library, '_is_readable_replica',
4182 mock.Mock(return_value=is_readable))
4184 mock_create_export = self.mock_object(
4185 self.library, '_create_export', mock.Mock(return_value=[]))
4186 protocol_helper = mock.Mock()
4187 if rules_status == constants.STATUS_ACTIVE:
4188 protocol_helper.update_access.return_value = None
4189 else:
4190 protocol_helper.update_access.side_effect = (
4191 netapp_api.NaApiError(code=0))
4192 mock_get_helper = self.mock_object(
4193 self.library, '_get_helper',
4194 mock.Mock(return_value=protocol_helper))
4195 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
4196 mock.Mock(return_value=(fake.SHARE_NAME,
4197 fake.VSERVER1,
4198 fake.BACKEND_NAME)))
4199 self.mock_object(self.library, '_is_flexgroup_share',
4200 mock.Mock(return_value=False))
4201 self.mock_object(self.library, '_is_flexgroup_pool',
4202 mock.Mock(return_value=False))
4203 self.mock_object(na_utils, 'get_relationship_type',
4204 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE))
4205 expected_model_update = {
4206 'export_locations': [],
4207 'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC,
4208 'access_rules_status': rules_status,
4209 }
4211 model_update = self.library.create_replica(
4212 None, [fake.SHARE], fake.SHARE, [fake.SHARE_ACCESS], [],
4213 share_server=None)
4215 self.assertDictEqual(expected_model_update, model_update)
4216 mock_dm_session.create_snapmirror.assert_called_once_with(
4217 fake.SHARE, fake.SHARE, na_utils.DATA_PROTECTION_TYPE,
4218 mount=is_readable)
4219 mock_is_readable.assert_called_once_with(fake.SHARE)
4220 if is_readable:
4221 mock_create_export.assert_called_once_with(
4222 fake.SHARE, None, fake.VSERVER1, vserver_client, replica=True)
4223 mock_get_helper.assert_called_once_with(fake.SHARE)
4224 protocol_helper.update_access.assert_called_once_with(
4225 fake.SHARE, fake.SHARE_NAME, [fake.SHARE_ACCESS])
4226 else:
4227 mock_create_export.assert_not_called()
4228 mock_get_helper.assert_not_called()
4229 protocol_helper.update_access.assert_not_called()
4231 data_motion.get_client_for_backend.assert_has_calls(
4232 [mock.call(fake.BACKEND_NAME, vserver_name=fake.VSERVER1),
4233 mock.call(fake.BACKEND_NAME, vserver_name=fake.VSERVER1)])
4234 self.library._is_flexgroup_pool.assert_called_once_with(fake.POOL_NAME)
4235 na_utils.get_relationship_type.assert_called_once_with(False)
4237 def test_create_replica_with_share_server(self):
4238 self.mock_object(self.library,
4239 '_allocate_container',
4240 mock.Mock())
4241 mock_dm_session = mock.Mock()
4242 self.mock_object(data_motion, "DataMotionSession",
4243 mock.Mock(return_value=mock_dm_session))
4244 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
4245 mock.Mock(return_value=(fake.SHARE_NAME,
4246 fake.VSERVER1,
4247 fake.BACKEND_NAME)))
4248 self.mock_object(self.library, '_is_flexgroup_share',
4249 mock.Mock(return_value=False))
4250 self.mock_object(self.library, '_is_flexgroup_pool',
4251 mock.Mock(return_value=False))
4252 self.mock_object(data_motion, 'get_client_for_backend')
4253 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4254 mock.Mock(return_value=fake.VSERVER1))
4255 self.mock_object(self.library,
4256 '_is_readable_replica',
4257 mock.Mock(return_value=False))
4258 expected_model_update = {
4259 'export_locations': [],
4260 'replica_state': constants.REPLICA_STATE_OUT_OF_SYNC,
4261 'access_rules_status': constants.STATUS_ACTIVE,
4262 }
4264 model_update = self.library.create_replica(
4265 None, [fake.SHARE], fake.SHARE, [], [],
4266 share_server=fake.SHARE_SERVER)
4268 self.assertDictEqual(expected_model_update, model_update)
4269 mock_dm_session.create_snapmirror.assert_called_once_with(
4270 fake.SHARE, fake.SHARE, na_utils.DATA_PROTECTION_TYPE,
4271 mount=False)
4272 data_motion.get_client_for_backend.assert_has_calls(
4273 [mock.call(fake.BACKEND_NAME, vserver_name=fake.VSERVER1),
4274 mock.call(fake.BACKEND_NAME, vserver_name=fake.VSERVER1)])
4275 self.library._is_flexgroup_pool.assert_called_once_with(fake.POOL_NAME)
4277 def test_create_replica_raise_different_type(self):
4279 mock_dm_session = mock.Mock()
4280 self.mock_object(data_motion, "DataMotionSession",
4281 mock.Mock(return_value=mock_dm_session))
4282 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
4283 mock.Mock(return_value=(fake.SHARE_NAME,
4284 fake.VSERVER1,
4285 fake.BACKEND_NAME)))
4286 self.mock_object(self.library, '_is_flexgroup_share',
4287 mock.Mock(return_value=True))
4288 self.mock_object(self.library, '_is_flexgroup_pool',
4289 mock.Mock(return_value=False))
4290 self.mock_object(data_motion, 'get_client_for_backend')
4292 self.assertRaises(exception.NetAppException,
4293 self.library.create_replica,
4294 None, [fake.SHARE], fake.SHARE, [], [],
4295 share_server=None)
4297 def test_create_replica_raise_flexgroup_no_fan_out_limit(self):
4299 mock_dm_session = mock.Mock()
4300 self.mock_object(data_motion, "DataMotionSession",
4301 mock.Mock(return_value=mock_dm_session))
4302 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
4303 mock.Mock(return_value=(fake.SHARE_NAME,
4304 fake.VSERVER1,
4305 fake.BACKEND_NAME)))
4306 self.mock_object(self.library, '_is_flexgroup_share',
4307 mock.Mock(return_value=True))
4308 self.mock_object(self.library, '_is_flexgroup_pool',
4309 mock.Mock(return_value=True))
4311 mock_src_client = mock.Mock()
4312 self.mock_object(mock_src_client,
4313 'is_flexgroup_fan_out_supported',
4314 mock.Mock(return_value=False))
4315 self.mock_object(self.library._client,
4316 'is_flexgroup_fan_out_supported',
4317 mock.Mock(return_value=False))
4318 self.mock_object(data_motion, 'get_client_for_backend',
4319 mock.Mock(return_value=mock_src_client))
4321 self.assertRaises(exception.NetAppException,
4322 self.library.create_replica,
4323 None, [fake.SHARE, fake.SHARE, fake.SHARE],
4324 fake.SHARE, [], [], share_server=None)
4326 def test_delete_replica(self):
4328 active_replica = fake_replica(
4329 replica_state=constants.REPLICA_STATE_ACTIVE)
4330 replica_1 = fake_replica(
4331 replica_state=constants.REPLICA_STATE_IN_SYNC,
4332 host=fake.MANILA_HOST_NAME)
4333 replica_2 = fake_replica(
4334 replica_state=constants.REPLICA_STATE_OUT_OF_SYNC)
4335 replica_list = [active_replica, replica_1, replica_2]
4337 self.mock_object(self.library,
4338 '_delete_share',
4339 mock.Mock())
4340 mock_dm_session = mock.Mock()
4341 self.mock_object(data_motion, "DataMotionSession",
4342 mock.Mock(return_value=mock_dm_session))
4343 self.mock_object(data_motion, 'get_client_for_backend')
4344 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4345 mock.Mock(return_value=fake.VSERVER1))
4346 self.mock_object(self.library,
4347 '_is_readable_replica',
4348 mock.Mock(return_value=False))
4350 result = self.library.delete_replica(None,
4351 replica_list,
4352 replica_1,
4353 [],
4354 share_server=None)
4355 self.assertIsNone(result)
4356 mock_dm_session.delete_snapmirror.assert_has_calls([
4357 mock.call(active_replica, replica_1),
4358 mock.call(replica_2, replica_1),
4359 mock.call(replica_1, replica_2),
4360 mock.call(replica_1, active_replica)],
4361 any_order=True)
4362 self.assertEqual(4, mock_dm_session.delete_snapmirror.call_count)
4363 data_motion.get_client_for_backend.assert_called_with(
4364 fake.BACKEND_NAME, vserver_name=mock.ANY)
4365 self.assertEqual(1, data_motion.get_client_for_backend.call_count)
4367 def test_delete_replica_with_share_server(self):
4369 active_replica = fake_replica(
4370 replica_state=constants.REPLICA_STATE_ACTIVE)
4371 replica = fake_replica(replica_state=constants.REPLICA_STATE_IN_SYNC,
4372 host=fake.MANILA_HOST_NAME)
4373 replica_list = [active_replica, replica]
4375 self.mock_object(self.library,
4376 '_is_readable_replica',
4377 mock.Mock(return_value=False))
4378 self.mock_object(self.library,
4379 '_delete_share',
4380 mock.Mock())
4381 mock_dm_session = mock.Mock()
4382 self.mock_object(data_motion, "DataMotionSession",
4383 mock.Mock(return_value=mock_dm_session))
4384 self.mock_object(data_motion, 'get_client_for_backend')
4385 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4386 mock.Mock(return_value=fake.VSERVER1))
4388 result = self.library.delete_replica(None,
4389 replica_list,
4390 replica,
4391 [],
4392 share_server=fake.SHARE_SERVER)
4393 self.assertIsNone(result)
4394 mock_dm_session.delete_snapmirror.assert_has_calls([
4395 mock.call(active_replica, replica),
4396 mock.call(replica, active_replica)],
4397 any_order=True)
4398 data_motion.get_client_for_backend.assert_called_once_with(
4399 fake.BACKEND_NAME, vserver_name=fake.VSERVER1)
4401 @ddt.data({'seconds': 3600, 'schedule': 'hourly'},
4402 {'seconds': (5 * 3600), 'schedule': '5hourly'},
4403 {'seconds': (30 * 60), 'schedule': '30minute'},
4404 {'seconds': (2 * 24 * 3600), 'schedule': '2DAY'},
4405 {'seconds': 3600, 'schedule': 'fake_shedule'},
4406 {'seconds': 3600, 'schedule': 'fake2'},
4407 {'seconds': 3600, 'schedule': '10fake'})
4408 @ddt.unpack
4409 def test__convert_schedule_to_seconds(self, seconds, schedule):
4410 expected_return = seconds
4411 actual_return = self.library._convert_schedule_to_seconds(schedule)
4412 self.assertEqual(expected_return, actual_return)
4414 def test_update_replica_state_no_snapmirror_share_creating(self):
4415 vserver_client = mock.Mock()
4416 self.mock_object(vserver_client, 'volume_exists',
4417 mock.Mock(return_value=True))
4418 self.mock_object(self.library,
4419 '_get_vserver',
4420 mock.Mock(return_value=(fake.VSERVER1,
4421 vserver_client)))
4422 self.mock_dm_session.get_snapmirrors = mock.Mock(return_value=[])
4423 self.mock_object(self.library,
4424 '_is_readable_replica',
4425 mock.Mock(return_value=False))
4426 replica = copy.deepcopy(fake.SHARE)
4427 replica['status'] = constants.STATUS_CREATING
4429 result = self.library.update_replica_state(
4430 None, [replica], replica, None, [], share_server=None)
4432 self.assertFalse(self.mock_dm_session.create_snapmirror.called)
4433 self.assertEqual(constants.STATUS_OUT_OF_SYNC, result)
4435 def test_update_replica_state_share_reverting_to_snapshot(self):
4436 vserver_client = mock.Mock()
4437 self.mock_object(vserver_client, 'volume_exists',
4438 mock.Mock(return_value=True))
4439 self.mock_object(self.library,
4440 '_get_vserver',
4441 mock.Mock(return_value=(fake.VSERVER1,
4442 vserver_client)))
4443 self.mock_dm_session.get_snapmirrors = mock.Mock(return_value=[])
4445 replica = copy.deepcopy(fake.SHARE)
4446 replica['status'] = constants.STATUS_REVERTING
4448 result = self.library.update_replica_state(
4449 None, [replica], replica, None, [], share_server=None)
4451 self.assertFalse(self.mock_dm_session.get_snapmirrors.called)
4452 self.assertFalse(self.mock_dm_session.create_snapmirror.called)
4453 self.assertIsNone(result)
4455 def test_update_replica_state_no_snapmirror_create_failed(self):
4456 vserver_client = mock.Mock()
4457 self.mock_object(vserver_client, 'volume_exists',
4458 mock.Mock(return_value=True))
4459 self.mock_object(self.library,
4460 '_get_vserver',
4461 mock.Mock(return_value=(fake.VSERVER1,
4462 vserver_client)))
4463 self.mock_dm_session.get_snapmirrors = mock.Mock(return_value=[])
4464 self.mock_object(self.library,
4465 '_is_readable_replica',
4466 mock.Mock(return_value=False))
4467 self.mock_object(share_utils,
4468 'extract_host',
4469 mock.Mock(return_value=fake.POOL_NAME))
4470 self.mock_object(self.library,
4471 '_is_flexgroup_pool',
4472 mock.Mock(return_value=False))
4473 self.mock_object(na_utils,
4474 'get_relationship_type',
4475 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE))
4476 self.mock_dm_session.create_snapmirror.side_effect = (
4477 netapp_api.NaApiError(code=0))
4479 replica = copy.deepcopy(fake.SHARE)
4480 replica['status'] = constants.REPLICA_STATE_OUT_OF_SYNC
4482 result = self.library.update_replica_state(
4483 None, [replica], replica, None, [], share_server=None)
4485 self.assertTrue(self.mock_dm_session.create_snapmirror.called)
4486 self.assertEqual(constants.STATUS_ERROR, result)
4488 @ddt.data(constants.STATUS_ERROR, constants.STATUS_AVAILABLE)
4489 def test_update_replica_state_no_snapmirror(self, status):
4490 vserver_client = mock.Mock()
4491 self.mock_object(vserver_client, 'volume_exists',
4492 mock.Mock(return_value=True))
4493 self.mock_object(self.library,
4494 '_get_vserver',
4495 mock.Mock(return_value=(fake.VSERVER1,
4496 vserver_client)))
4497 self.mock_dm_session.get_snapmirrors = mock.Mock(return_value=[])
4498 self.mock_object(self.library,
4499 '_is_readable_replica',
4500 mock.Mock(return_value=False))
4501 self.mock_object(share_utils,
4502 'extract_host',
4503 mock.Mock(return_value=fake.POOL_NAME))
4504 self.mock_object(self.library,
4505 '_is_flexgroup_pool',
4506 mock.Mock(return_value=False))
4507 self.mock_object(na_utils,
4508 'get_relationship_type',
4509 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE))
4511 replica = copy.deepcopy(fake.SHARE)
4512 replica['status'] = status
4514 result = self.library.update_replica_state(
4515 None, [replica], replica, None, [], share_server=None)
4517 self.assertEqual(1,
4518 self.mock_dm_session.create_snapmirror.call_count)
4519 self.assertEqual(constants.STATUS_OUT_OF_SYNC, result)
4521 def test_update_replica_state_broken_snapmirror(self):
4522 fake_snapmirror = {
4523 'mirror-state': 'broken-off',
4524 'relationship-status': 'idle',
4525 'source-vserver': fake.VSERVER2,
4526 'source-volume': 'fake_volume',
4527 'last-transfer-end-timestamp': '%s' % float(time.time() - 10000)
4528 }
4529 vserver_client = mock.Mock()
4530 self.mock_object(vserver_client, 'volume_exists',
4531 mock.Mock(return_value=True))
4532 self.mock_object(self.library,
4533 '_get_vserver',
4534 mock.Mock(return_value=(fake.VSERVER1,
4535 vserver_client)))
4536 self.mock_dm_session.get_snapmirrors = mock.Mock(
4537 return_value=[fake_snapmirror])
4538 self.mock_object(self.library,
4539 '_is_readable_replica',
4540 mock.Mock(return_value=False))
4542 result = self.library.update_replica_state(None, [fake.SHARE],
4543 fake.SHARE, None, [],
4544 share_server=None)
4546 vserver_client.resync_snapmirror_vol.assert_called_once_with(
4547 fake.VSERVER2, 'fake_volume', fake.VSERVER1, fake.SHARE['name']
4548 )
4550 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC, result)
4552 def test_update_replica_state_snapmirror_still_initializing(self):
4553 fake_snapmirror = {
4554 'mirror-state': 'uninitialized',
4555 'relationship-status': 'transferring',
4556 'source-vserver': fake.VSERVER2,
4557 'source-volume': 'fake_volume',
4558 'last-transfer-end-timestamp': '%s' % float(time.time() - 10000)
4559 }
4560 vserver_client = mock.Mock()
4561 self.mock_object(vserver_client, 'volume_exists',
4562 mock.Mock(return_value=True))
4563 self.mock_object(self.library,
4564 '_get_vserver',
4565 mock.Mock(return_value=(fake.VSERVER1,
4566 vserver_client)))
4567 self.mock_dm_session.get_snapmirrors = mock.Mock(
4568 return_value=[fake_snapmirror])
4569 self.mock_object(self.library,
4570 '_is_readable_replica',
4571 mock.Mock(return_value=False))
4573 result = self.library.update_replica_state(None, [fake.SHARE],
4574 fake.SHARE, None, [],
4575 share_server=None)
4577 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC, result)
4579 def test_update_replica_state_fail_to_get_snapmirrors(self):
4580 vserver_client = mock.Mock()
4581 self.mock_object(vserver_client, 'volume_exists',
4582 mock.Mock(return_value=True))
4583 self.mock_object(self.library,
4584 '_get_vserver',
4585 mock.Mock(return_value=(fake.VSERVER1,
4586 vserver_client)))
4587 self.mock_dm_session.get_snapmirrors.side_effect = (
4588 netapp_api.NaApiError(code=0))
4590 result = self.library.update_replica_state(None, [fake.SHARE],
4591 fake.SHARE, None, [],
4592 share_server=None)
4593 self.assertTrue(self.mock_dm_session.get_snapmirrors.called)
4594 self.assertEqual(constants.STATUS_ERROR, result)
4596 def test_update_replica_state_broken_snapmirror_resync_error(self):
4597 fake_snapmirror = {
4598 'mirror-state': 'broken-off',
4599 'relationship-status': 'idle',
4600 'source-vserver': fake.VSERVER2,
4601 'source-volume': 'fake_volume',
4602 'last-transfer-end-timestamp': '%s' % float(time.time() - 10000)
4603 }
4604 vserver_client = mock.Mock()
4605 self.mock_object(vserver_client, 'volume_exists',
4606 mock.Mock(return_value=True))
4607 self.mock_object(self.library,
4608 '_get_vserver',
4609 mock.Mock(return_value=(fake.VSERVER1,
4610 vserver_client)))
4611 self.mock_dm_session.get_snapmirrors = mock.Mock(
4612 return_value=[fake_snapmirror])
4613 self.mock_object(self.library,
4614 '_is_readable_replica',
4615 mock.Mock(return_value=False))
4616 vserver_client.resync_snapmirror_vol.side_effect = (
4617 netapp_api.NaApiError)
4619 result = self.library.update_replica_state(None, [fake.SHARE],
4620 fake.SHARE, None, [],
4621 share_server=None)
4623 vserver_client.resync_snapmirror_vol.assert_called_once_with(
4624 fake.VSERVER2, 'fake_volume', fake.VSERVER1, fake.SHARE['name']
4625 )
4627 self.assertEqual(constants.STATUS_ERROR, result)
4629 def test_update_replica_state_stale_snapmirror(self):
4630 fake_snapmirror = {
4631 'mirror-state': 'snapmirrored',
4632 'schedule': self.library.configuration.netapp_snapmirror_schedule,
4633 'last-transfer-end-timestamp': '%s' % float(
4634 timeutils.utcnow_ts() - 10000)
4635 }
4636 vserver_client = mock.Mock()
4637 self.mock_object(vserver_client, 'volume_exists',
4638 mock.Mock(return_value=True))
4639 self.mock_object(self.library,
4640 '_get_vserver',
4641 mock.Mock(return_value=(fake.VSERVER1,
4642 vserver_client)))
4643 self.mock_dm_session.get_snapmirrors = mock.Mock(
4644 return_value=[fake_snapmirror])
4645 self.mock_object(self.library,
4646 '_is_readable_replica',
4647 mock.Mock(return_value=False))
4648 mock_backend_config = fake.get_config_cmode()
4649 self.mock_object(data_motion, 'get_backend_configuration',
4650 mock.Mock(return_value=mock_backend_config))
4652 result = self.library.update_replica_state(None, [fake.SHARE],
4653 fake.SHARE, None, [],
4654 share_server=None)
4656 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC, result)
4658 def test_update_replica_state_in_sync(self):
4659 fake_snapmirror = {
4660 'mirror-state': 'snapmirrored',
4661 'schedule': self.library.configuration.netapp_snapmirror_schedule,
4662 'relationship-status': 'idle',
4663 'last-transfer-end-timestamp': '%s' % float(time.time())
4664 }
4665 vserver_client = mock.Mock()
4666 self.mock_object(vserver_client, 'volume_exists',
4667 mock.Mock(return_value=True))
4668 self.mock_object(self.library,
4669 '_get_vserver',
4670 mock.Mock(return_value=(fake.VSERVER1,
4671 vserver_client)))
4672 self.mock_dm_session.get_snapmirrors = mock.Mock(
4673 return_value=[fake_snapmirror])
4674 self.mock_object(self.library,
4675 '_is_readable_replica',
4676 mock.Mock(return_value=False))
4677 mock_backend_config = fake.get_config_cmode()
4678 self.mock_object(data_motion, 'get_backend_configuration',
4679 mock.Mock(return_value=mock_backend_config))
4681 result = self.library.update_replica_state(None, [fake.SHARE],
4682 fake.SHARE, None, [],
4683 share_server=None)
4685 (self.mock_dm_session.cleanup_previous_snapmirror_relationships
4686 .assert_not_called())
4687 self.assertEqual(constants.REPLICA_STATE_IN_SYNC, result)
4689 def test_update_replica_state_replica_change_to_in_sycn(self):
4690 fake_snapmirror = {
4691 'mirror-state': 'snapmirrored',
4692 'relationship-status': 'idle',
4693 'last-transfer-end-timestamp': '%s' % float(time.time())
4694 }
4695 # fake SHARE has replica_state set to active already
4696 active_replica = fake.SHARE
4697 out_of_sync_replica = copy.deepcopy(fake.SHARE)
4698 out_of_sync_replica['replica_state'] = (
4699 constants.REPLICA_STATE_OUT_OF_SYNC)
4700 replica_list = [out_of_sync_replica, active_replica]
4701 vserver_client = mock.Mock()
4702 self.mock_object(vserver_client, 'volume_exists',
4703 mock.Mock(return_value=True))
4704 self.mock_object(self.library,
4705 '_get_vserver',
4706 mock.Mock(return_value=(fake.VSERVER1,
4707 vserver_client)))
4708 self.mock_dm_session.get_snapmirrors = mock.Mock(
4709 return_value=[fake_snapmirror])
4710 mock_config = mock.Mock()
4711 mock_config.safe_get = mock.Mock(return_value=0)
4712 self.mock_object(data_motion, 'get_backend_configuration',
4713 mock.Mock(return_value=mock_config))
4714 self.mock_object(self.library,
4715 '_is_readable_replica',
4716 mock.Mock(return_value=False))
4718 result = self.library.update_replica_state(
4719 None, replica_list, out_of_sync_replica,
4720 None, [], share_server=None)
4722 # Expect a snapmirror cleanup as replica was in out of sync state
4723 (self.mock_dm_session.cleanup_previous_snapmirror_relationships
4724 .assert_called_once_with(out_of_sync_replica, replica_list))
4725 self.assertEqual(constants.REPLICA_STATE_IN_SYNC, result)
4727 def test_update_replica_state_backend_volume_absent(self):
4728 vserver_client = mock.Mock()
4729 self.mock_object(vserver_client, 'volume_exists',
4730 mock.Mock(return_value=False))
4731 self.mock_object(self.library,
4732 '_get_vserver',
4733 mock.Mock(return_value=(fake.VSERVER1,
4734 vserver_client)))
4736 self.assertRaises(exception.ShareResourceNotFound,
4737 self.library.update_replica_state,
4738 None, [fake.SHARE], fake.SHARE, None, [],
4739 share_server=None)
4741 def test_update_replica_state_in_sync_with_snapshots(self):
4742 fake_snapmirror = {
4743 'mirror-state': 'snapmirrored',
4744 'schedule': self.library.configuration.netapp_snapmirror_schedule,
4745 'relationship-status': 'idle',
4746 'last-transfer-end-timestamp': '%s' % float(time.time())
4747 }
4748 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
4749 fake_snapshot['share_id'] = fake.SHARE['id']
4750 fake_snapshot['provider_location'] = 'fake'
4751 snapshots = [{'share_replica_snapshot': fake_snapshot}]
4752 vserver_client = mock.Mock()
4753 self.mock_object(vserver_client, 'snapshot_exists', mock.Mock(
4754 return_value=True))
4755 self.mock_object(self.library,
4756 '_get_vserver',
4757 mock.Mock(return_value=(fake.VSERVER1,
4758 vserver_client)))
4759 self.mock_dm_session.get_snapmirrors = mock.Mock(
4760 return_value=[fake_snapmirror])
4761 self.mock_object(self.library,
4762 '_is_readable_replica',
4763 mock.Mock(return_value=False))
4764 mock_backend_config = fake.get_config_cmode()
4765 self.mock_object(data_motion, 'get_backend_configuration',
4766 mock.Mock(return_value=mock_backend_config))
4768 result = self.library.update_replica_state(None, [fake.SHARE],
4769 fake.SHARE, None, snapshots,
4770 share_server=None)
4772 (self.mock_dm_session.cleanup_previous_snapmirror_relationships
4773 .assert_not_called())
4774 self.assertEqual(constants.REPLICA_STATE_IN_SYNC, result)
4776 def test_update_replica_state_missing_snapshot(self):
4777 fake_snapmirror = {
4778 'mirror-state': 'snapmirrored',
4779 'relationship-status': 'idle',
4780 'last-transfer-end-timestamp': '%s' % float(time.time())
4781 }
4782 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
4783 fake_snapshot['share_id'] = fake.SHARE['id']
4784 snapshots = [{'share_replica_snapshot': fake_snapshot}]
4785 vserver_client = mock.Mock()
4786 self.mock_object(vserver_client, 'snapshot_exists', mock.Mock(
4787 return_value=False))
4788 self.mock_object(self.library,
4789 '_get_vserver',
4790 mock.Mock(return_value=(fake.VSERVER1,
4791 vserver_client)))
4792 self.mock_dm_session.get_snapmirrors = mock.Mock(
4793 return_value=[fake_snapmirror])
4794 self.mock_object(self.library,
4795 '_is_readable_replica',
4796 mock.Mock(return_value=False))
4797 mock_backend_config = fake.get_config_cmode()
4798 self.mock_object(data_motion, 'get_backend_configuration',
4799 mock.Mock(return_value=mock_backend_config))
4801 result = self.library.update_replica_state(None, [fake.SHARE],
4802 fake.SHARE, None, snapshots,
4803 share_server=None)
4805 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC, result)
4807 @ddt.data(True, False)
4808 def test_promote_replica(self, is_readable):
4809 self.mock_object(self.library,
4810 '_get_vserver',
4811 mock.Mock(return_value=(fake.VSERVER1,
4812 mock.Mock())))
4813 protocol_helper = mock.Mock()
4814 self.mock_object(self.library,
4815 '_get_helper',
4816 mock.Mock(return_value=protocol_helper))
4817 self.mock_object(self.library, '_create_export',
4818 mock.Mock(return_value='fake_export_location'))
4819 self.mock_object(self.library, '_unmount_orig_active_replica')
4820 self.mock_object(self.library, '_handle_qos_on_replication_change')
4821 self.mock_object(self.library,
4822 '_is_flexgroup_pool',
4823 mock.Mock(return_value=False))
4824 self.mock_object(share_types, 'get_extra_specs_from_share')
4825 self.mock_object(self.library, '_get_provisioning_options',
4826 mock.Mock(return_value={}))
4828 mock_dm_session = mock.Mock()
4829 self.mock_object(data_motion, "DataMotionSession",
4830 mock.Mock(return_value=mock_dm_session))
4831 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4832 mock.Mock(return_value=fake.VSERVER1))
4833 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
4834 mock.Mock(return_value=(fake.SHARE_NAME,
4835 fake.VSERVER1,
4836 fake.BACKEND_NAME)))
4837 mock_client = mock.Mock()
4838 self.mock_object(data_motion, "get_client_for_backend",
4839 mock.Mock(return_value=mock_client))
4840 mock_backend_config = fake.get_config_cmode()
4841 self.mock_object(data_motion, 'get_backend_configuration',
4842 mock.Mock(return_value=mock_backend_config))
4843 self.mock_object(self.library, '_get_api_client_for_backend',
4844 mock.Mock(return_value=mock_client))
4845 self.mock_object(self.client, 'cleanup_demoted_replica')
4846 self.mock_object(self.library,
4847 '_is_readable_replica',
4848 mock.Mock(return_value=is_readable))
4849 self.mock_object(self.library,
4850 '_update_autosize_attributes_after_promote_replica')
4851 replicas = self.library.promote_replica(
4852 None, [self.fake_replica, self.fake_replica_2],
4853 self.fake_replica_2, [], share_server=None)
4855 mock_dm_session.change_snapmirror_source.assert_called_once_with(
4856 self.fake_replica, self.fake_replica, self.fake_replica_2,
4857 mock.ANY, is_flexgroup=False
4858 )
4859 self.assertEqual(2, len(replicas))
4860 actual_replica_1 = list(filter(
4861 lambda x: x['id'] == self.fake_replica['id'], replicas))[0]
4862 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
4863 actual_replica_1['replica_state'])
4864 actual_replica_2 = list(filter(
4865 lambda x: x['id'] == self.fake_replica_2['id'], replicas))[0]
4866 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
4867 actual_replica_2['replica_state'])
4868 self.assertEqual('fake_export_location',
4869 actual_replica_2['export_locations'])
4870 self.assertEqual(constants.STATUS_ACTIVE,
4871 actual_replica_2['access_rules_status'])
4872 if is_readable:
4873 self.library._unmount_orig_active_replica.assert_not_called()
4874 protocol_helper.cleanup_demoted_replica.assert_not_called()
4875 self.assertEqual('fake_export_location',
4876 actual_replica_1['export_locations'])
4877 else:
4878 self.library._unmount_orig_active_replica.assert_called_once_with(
4879 self.fake_replica, fake.VSERVER1)
4880 protocol_helper.cleanup_demoted_replica.assert_called_once_with(
4881 self.fake_replica, fake.SHARE['name'])
4882 self.assertEqual([], actual_replica_1['export_locations'])
4883 self.library._handle_qos_on_replication_change.assert_called_once()
4885 def test_promote_replica_cleanup_demoted_storage_error(self):
4886 self.mock_object(self.library,
4887 '_get_vserver',
4888 mock.Mock(return_value=(fake.VSERVER1,
4889 mock.Mock())))
4890 protocol_helper = mock.Mock()
4891 self.mock_object(self.library,
4892 '_get_helper',
4893 mock.Mock(return_value=protocol_helper))
4894 self.mock_object(self.library,
4895 '_is_readable_replica',
4896 mock.Mock(return_value=False))
4897 self.mock_object(self.library, '_create_export',
4898 mock.Mock(return_value='fake_export_location'))
4899 self.mock_object(self.library, '_unmount_orig_active_replica')
4900 self.mock_object(self.library, '_handle_qos_on_replication_change')
4901 self.mock_object(self.library,
4902 '_is_flexgroup_pool',
4903 mock.Mock(return_value=False))
4905 mock_dm_session = mock.Mock()
4906 self.mock_object(data_motion, "DataMotionSession",
4907 mock.Mock(return_value=mock_dm_session))
4908 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4909 mock.Mock(return_value=fake.VSERVER1))
4910 self.mock_object(
4911 protocol_helper, 'cleanup_demoted_replica',
4912 mock.Mock(side_effect=exception.StorageCommunicationException))
4913 self.mock_object(self.library,
4914 '_update_autosize_attributes_after_promote_replica')
4915 self.mock_object(share_types, 'get_extra_specs_from_share')
4916 self.mock_object(self.library, '_get_provisioning_options',
4917 mock.Mock(return_value={}))
4918 mock_log = self.mock_object(lib_base.LOG, 'exception')
4920 self.library.promote_replica(
4921 None, [self.fake_replica, self.fake_replica_2],
4922 self.fake_replica_2, [], share_server=None)
4924 mock_dm_session.change_snapmirror_source.assert_called_once_with(
4925 self.fake_replica, self.fake_replica, self.fake_replica_2,
4926 mock.ANY, is_flexgroup=False
4927 )
4928 protocol_helper.cleanup_demoted_replica.assert_called_once_with(
4929 self.fake_replica, fake.SHARE['name'])
4930 mock_log.assert_called_once()
4932 def test_promote_replica_destination_unreachable(self):
4933 self.mock_object(self.library,
4934 '_get_vserver',
4935 mock.Mock(return_value=(fake.VSERVER1,
4936 mock.Mock())))
4937 self.mock_object(self.library,
4938 '_get_helper',
4939 mock.Mock(return_value=mock.Mock()))
4940 self.mock_object(self.library, '_unmount_orig_active_replica')
4941 self.mock_object(self.library, '_handle_qos_on_replication_change')
4943 self.mock_object(self.library, '_create_export',
4944 mock.Mock(return_value='fake_export_location'))
4945 self.mock_object(
4946 self.library, '_convert_destination_replica_to_independent',
4947 mock.Mock(side_effect=exception.StorageCommunicationException))
4948 self.mock_object(self.library,
4949 '_update_autosize_attributes_after_promote_replica')
4950 self.mock_object(share_types, 'get_extra_specs_from_share')
4951 self.mock_object(self.library, '_get_provisioning_options',
4952 mock.Mock(return_value={}))
4954 replicas = self.library.promote_replica(
4955 None, [self.fake_replica, self.fake_replica_2],
4956 self.fake_replica_2, [], share_server=None)
4958 self.assertEqual(1, len(replicas))
4959 actual_replica = replicas[0]
4960 self.assertEqual(constants.STATUS_ERROR,
4961 actual_replica['replica_state'])
4962 self.assertEqual(constants.STATUS_ERROR,
4963 actual_replica['status'])
4964 self.assertFalse(
4965 self.library._unmount_orig_active_replica.called)
4966 self.assertFalse(
4967 self.library._handle_qos_on_replication_change.called)
4969 def test_promote_replica_more_than_two_replicas(self):
4970 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
4971 fake_replica_3['id'] = fake.SHARE_ID3
4972 fake_replica_3['replica_state'] = constants.REPLICA_STATE_OUT_OF_SYNC
4973 self.mock_object(self.library,
4974 '_get_vserver',
4975 mock.Mock(return_value=(fake.VSERVER1,
4976 mock.Mock())))
4977 self.mock_object(self.library, '_unmount_orig_active_replica')
4978 self.mock_object(self.library, '_handle_qos_on_replication_change')
4979 self.mock_object(self.library,
4980 '_get_helper',
4981 mock.Mock(return_value=mock.Mock()))
4983 self.mock_object(self.library,
4984 '_is_flexgroup_pool',
4985 mock.Mock(return_value=False))
4986 self.mock_object(self.library, '_create_export',
4987 mock.Mock(return_value='fake_export_location'))
4988 mock_dm_session = mock.Mock()
4989 self.mock_object(data_motion, "DataMotionSession",
4990 mock.Mock(return_value=mock_dm_session))
4991 self.mock_object(mock_dm_session, 'get_vserver_from_share',
4992 mock.Mock(return_value=fake.VSERVER1))
4993 self.mock_object(self.library,
4994 '_is_readable_replica',
4995 mock.Mock(return_value=False))
4996 self.mock_object(self.library,
4997 '_update_autosize_attributes_after_promote_replica')
4998 self.mock_object(share_types, 'get_extra_specs_from_share')
4999 self.mock_object(self.library, '_get_provisioning_options',
5000 mock.Mock(return_value={}))
5002 replicas = self.library.promote_replica(
5003 None, [self.fake_replica, self.fake_replica_2, fake_replica_3],
5004 self.fake_replica_2, [], share_server=None)
5006 mock_dm_session.change_snapmirror_source.assert_has_calls([
5007 mock.call(fake_replica_3, self.fake_replica, self.fake_replica_2,
5008 mock.ANY, is_flexgroup=False),
5009 mock.call(self.fake_replica, self.fake_replica,
5010 self.fake_replica_2, mock.ANY, is_flexgroup=False)
5011 ], any_order=True)
5013 self.assertEqual(3, len(replicas))
5014 actual_replica_1 = list(filter(
5015 lambda x: x['id'] == self.fake_replica['id'], replicas))[0]
5016 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
5017 actual_replica_1['replica_state'])
5018 actual_replica_2 = list(filter(
5019 lambda x: x['id'] == self.fake_replica_2['id'], replicas))[0]
5020 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5021 actual_replica_2['replica_state'])
5022 self.assertEqual('fake_export_location',
5023 actual_replica_2['export_locations'])
5024 actual_replica_3 = list(filter(
5025 lambda x: x['id'] == fake_replica_3['id'], replicas))[0]
5026 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
5027 actual_replica_3['replica_state'])
5028 self.library._unmount_orig_active_replica.assert_called_once_with(
5029 self.fake_replica, fake.VSERVER1)
5030 self.library._handle_qos_on_replication_change.assert_called_once()
5032 def test_promote_replica_with_access_rules(self):
5033 self.mock_object(self.library,
5034 '_get_vserver',
5035 mock.Mock(return_value=(fake.VSERVER1,
5036 mock.Mock())))
5037 self.mock_object(self.library, '_unmount_orig_active_replica')
5038 self.mock_object(self.library, '_handle_qos_on_replication_change')
5039 mock_helper = mock.Mock()
5040 self.mock_object(self.library,
5041 '_get_helper',
5042 mock.Mock(return_value=mock_helper))
5043 self.mock_object(self.library, '_create_export',
5044 mock.Mock(return_value='fake_export_location'))
5045 self.mock_object(self.library,
5046 '_is_flexgroup_pool',
5047 mock.Mock(return_value=False))
5049 mock_dm_session = mock.Mock()
5050 self.mock_object(data_motion, "DataMotionSession",
5051 mock.Mock(return_value=mock_dm_session))
5052 self.mock_object(mock_dm_session, 'get_vserver_from_share',
5053 mock.Mock(return_value=fake.VSERVER1))
5054 self.mock_object(self.library,
5055 '_is_readable_replica',
5056 mock.Mock(return_value=False))
5057 self.mock_object(self.library,
5058 '_update_autosize_attributes_after_promote_replica')
5059 self.mock_object(share_types, 'get_extra_specs_from_share')
5060 self.mock_object(self.library, '_get_provisioning_options',
5061 mock.Mock(return_value={}))
5063 replicas = self.library.promote_replica(
5064 None, [self.fake_replica, self.fake_replica_2],
5065 self.fake_replica_2, [fake.SHARE_ACCESS], share_server=None)
5067 mock_dm_session.change_snapmirror_source.assert_has_calls([
5068 mock.call(self.fake_replica, self.fake_replica,
5069 self.fake_replica_2, mock.ANY, is_flexgroup=False)
5070 ], any_order=True)
5071 self.assertEqual(2, len(replicas))
5072 share_name = self.library._get_backend_share_name(
5073 self.fake_replica_2['id'])
5074 mock_helper.update_access.assert_called_once_with(self.fake_replica_2,
5075 share_name,
5076 [fake.SHARE_ACCESS])
5077 self.library._unmount_orig_active_replica.assert_called_once_with(
5078 self.fake_replica, fake.VSERVER1)
5079 self.library._handle_qos_on_replication_change.assert_called_once()
5081 def test_unmount_orig_active_replica(self):
5082 self.mock_object(share_utils, 'extract_host', mock.Mock(
5083 return_value=fake.MANILA_HOST_NAME))
5084 self.mock_object(data_motion, 'get_client_for_backend')
5085 self.mock_object(self.library, '_get_backend_share_name', mock.Mock(
5086 return_value=fake.SHARE_NAME))
5088 result = self.library._unmount_orig_active_replica(fake.SHARE)
5089 self.assertIsNone(result)
5091 @ddt.data({'extra_specs': {'netapp:snapshot_policy': 'none'},
5092 'have_cluster_creds': True},
5093 {'extra_specs': {'netapp:snapshot_policy': 'none'},
5094 'have_cluster_creds': True},
5095 # Test Case 2 isn't possible input
5096 {'extra_specs': {'qos': True, 'netapp:maxiops': '3000'},
5097 'have_cluster_creds': False})
5098 @ddt.unpack
5099 def test_handle_qos_on_replication_change_nothing_to_handle(
5100 self, extra_specs, have_cluster_creds):
5102 self.library._have_cluster_creds = have_cluster_creds
5103 self.mock_object(lib_base.LOG, 'exception')
5104 self.mock_object(lib_base.LOG, 'info')
5105 self.mock_object(share_types, 'get_extra_specs_from_share',
5106 mock.Mock(return_value=extra_specs))
5108 retval = self.library._handle_qos_on_replication_change(
5109 self.mock_dm_session, self.fake_replica_2, self.fake_replica,
5110 True, share_server=fake.SHARE_SERVER)
5112 self.assertIsNone(retval)
5113 lib_base.LOG.exception.assert_not_called()
5114 lib_base.LOG.info.assert_not_called()
5115 if have_cluster_creds:
5116 share_types.get_extra_specs_from_share.assert_called_once_with(
5117 self.fake_replica)
5118 else:
5119 share_types.get_extra_specs_from_share.assert_not_called()
5121 def test_handle_qos_on_replication_change_exception(self):
5122 self.library._have_cluster_creds = True
5123 extra_specs = {'qos': True, fake.QOS_MAX_EXTRA_SPEC: '3000'}
5124 vserver_client = mock.Mock()
5125 self.mock_object(lib_base.LOG, 'exception')
5126 self.mock_object(lib_base.LOG, 'info')
5127 self.mock_object(share_types, 'get_extra_specs_from_share',
5128 mock.Mock(return_value=extra_specs))
5129 self.mock_object(self.library, '_get_vserver', mock.Mock(
5130 return_value=(fake.VSERVER1, vserver_client)))
5131 self.mock_object(self.library._client, 'qos_policy_group_exists',
5132 mock.Mock(return_value=True))
5133 self.mock_object(self.library._client, 'qos_policy_group_modify',
5134 mock.Mock(side_effect=netapp_api.NaApiError))
5136 retval = self.library._handle_qos_on_replication_change(
5137 self.mock_dm_session, self.fake_replica_2, self.fake_replica, True,
5138 share_server=fake.SHARE_SERVER)
5140 self.assertIsNone(retval)
5141 (self.mock_dm_session.remove_qos_on_old_active_replica
5142 .assert_called_once_with(self.fake_replica))
5143 lib_base.LOG.exception.assert_called_once()
5144 lib_base.LOG.info.assert_not_called()
5145 vserver_client.set_qos_policy_group_for_volume.assert_not_called()
5147 @ddt.data(True, False)
5148 def test_handle_qos_on_replication_change_modify_existing_policy(self,
5149 is_dr):
5150 self.library._have_cluster_creds = True
5151 extra_specs = {'qos': True, fake.QOS_MAX_EXTRA_SPEC: '3000'}
5152 vserver_client = mock.Mock()
5153 volume_name_on_backend = self.library._get_backend_share_name(
5154 self.fake_replica_2['id'])
5155 self.mock_object(lib_base.LOG, 'exception')
5156 self.mock_object(lib_base.LOG, 'info')
5157 self.mock_object(share_types, 'get_extra_specs_from_share',
5158 mock.Mock(return_value=extra_specs))
5159 self.mock_object(self.library, '_get_vserver', mock.Mock(
5160 return_value=(fake.VSERVER1, vserver_client)))
5161 self.mock_object(self.library._client, 'qos_policy_group_exists',
5162 mock.Mock(return_value=True))
5163 self.mock_object(self.library._client, 'qos_policy_group_modify')
5164 self.mock_object(self.library, '_create_qos_policy_group')
5166 retval = self.library._handle_qos_on_replication_change(
5167 self.mock_dm_session, self.fake_replica_2, self.fake_replica,
5168 is_dr, share_server=fake.SHARE_SERVER)
5170 self.assertIsNone(retval)
5171 if is_dr:
5172 (self.mock_dm_session.remove_qos_on_old_active_replica.
5173 assert_called_once_with(self.fake_replica))
5174 else:
5175 (self.mock_dm_session.remove_qos_on_old_active_replica.
5176 assert_not_called())
5177 self.library._client.qos_policy_group_modify.assert_called_once_with(
5178 'qos_' + volume_name_on_backend, '3000iops', None)
5179 vserver_client.set_qos_policy_group_for_volume.assert_called_once_with(
5180 volume_name_on_backend, 'qos_' + volume_name_on_backend)
5181 self.library._create_qos_policy_group.assert_not_called()
5182 lib_base.LOG.exception.assert_not_called()
5183 lib_base.LOG.info.assert_called_once()
5185 def test_handle_qos_on_replication_change_create_new_policy(self):
5186 self.library._have_cluster_creds = True
5187 extra_specs = {'qos': True, fake.QOS_MAX_EXTRA_SPEC: '3000'}
5188 vserver_client = mock.Mock()
5189 self.mock_object(lib_base.LOG, 'exception')
5190 self.mock_object(lib_base.LOG, 'info')
5191 self.mock_object(share_types, 'get_extra_specs_from_share',
5192 mock.Mock(return_value=extra_specs))
5193 self.mock_object(self.library, '_get_vserver', mock.Mock(
5194 return_value=(fake.VSERVER1, vserver_client)))
5195 self.mock_object(self.library._client, 'qos_policy_group_exists',
5196 mock.Mock(return_value=False))
5197 self.mock_object(self.library._client, 'qos_policy_group_modify')
5198 self.mock_object(self.library, '_create_qos_policy_group')
5200 retval = self.library._handle_qos_on_replication_change(
5201 self.mock_dm_session, self.fake_replica_2, self.fake_replica, True,
5202 share_server=fake.SHARE_SERVER)
5204 self.assertIsNone(retval)
5205 self.library._create_qos_policy_group.assert_called_once_with(
5206 self.fake_replica_2, fake.VSERVER1, {'maxiops': '3000'})
5207 self.library._client.qos_policy_group_modify.assert_not_called()
5208 lib_base.LOG.exception.assert_not_called()
5209 lib_base.LOG.info.assert_called_once()
5211 def test_convert_destination_replica_to_independent(self):
5212 self.mock_object(self.library,
5213 '_get_vserver',
5214 mock.Mock(return_value=(fake.VSERVER1,
5215 mock.Mock())))
5216 self.mock_object(self.library,
5217 '_get_helper',
5218 mock.Mock(return_value=mock.Mock()))
5219 self.mock_object(self.library, '_create_export',
5220 mock.Mock(return_value='fake_export_location'))
5222 replica = self.library._convert_destination_replica_to_independent(
5223 None, self.mock_dm_session, self.fake_replica,
5224 self.fake_replica_2, [], share_server=None)
5226 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5227 self.fake_replica, self.fake_replica_2)
5228 self.mock_dm_session.break_snapmirror.assert_called_once_with(
5229 self.fake_replica, self.fake_replica_2,
5230 quiesce_wait_time=None)
5232 self.assertEqual('fake_export_location',
5233 replica['export_locations'])
5234 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5235 replica['replica_state'])
5237 def test_convert_destination_replica_to_independent_update_failed(self):
5238 self.mock_object(self.library,
5239 '_get_vserver',
5240 mock.Mock(return_value=(fake.VSERVER1,
5241 mock.Mock())))
5242 self.mock_object(self.library,
5243 '_get_helper',
5244 mock.Mock(return_value=mock.Mock()))
5245 self.mock_object(self.library, '_create_export',
5246 mock.Mock(return_value='fake_export_location'))
5247 self.mock_object(
5248 self.mock_dm_session, 'update_snapmirror',
5249 mock.Mock(side_effect=exception.StorageCommunicationException))
5251 replica = self.library._convert_destination_replica_to_independent(
5252 None, self.mock_dm_session, self.fake_replica,
5253 self.fake_replica_2, [], share_server=None)
5255 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5256 self.fake_replica, self.fake_replica_2)
5257 self.mock_dm_session.break_snapmirror.assert_called_once_with(
5258 self.fake_replica, self.fake_replica_2,
5259 quiesce_wait_time=None)
5261 self.assertEqual('fake_export_location',
5262 replica['export_locations'])
5263 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5264 replica['replica_state'])
5266 def test_promote_replica_fail_to_set_access_rules(self):
5267 fake_helper = mock.Mock()
5268 fake_helper.update_access.side_effect = Exception
5269 fake_access_rules = [
5270 {'access_to': "0.0.0.0",
5271 'access_level': constants.ACCESS_LEVEL_RO},
5272 {'access_to': "10.10.10.10",
5273 'access_level': constants.ACCESS_LEVEL_RW},
5274 ]
5275 self.mock_object(self.library,
5276 '_get_vserver',
5277 mock.Mock(return_value=(fake.VSERVER1,
5278 mock.Mock())))
5279 self.mock_object(self.library, '_handle_qos_on_replication_change')
5280 self.mock_object(self.library,
5281 '_get_helper',
5282 mock.Mock(return_value=fake_helper))
5283 self.mock_object(self.library, '_create_export',
5284 mock.Mock(return_value='fake_export_location'))
5285 self.mock_object(self.library,
5286 '_is_flexgroup_pool',
5287 mock.Mock(return_value=False))
5288 self.mock_object(self.library,
5289 '_is_readable_replica',
5290 mock.Mock(return_value=False))
5291 self.mock_object(self.library,
5292 '_update_autosize_attributes_after_promote_replica')
5293 self.mock_object(share_types, 'get_extra_specs_from_share')
5294 self.mock_object(self.library, '_get_provisioning_options',
5295 mock.Mock(return_value={}))
5296 replicas = self.library.promote_replica(
5297 None, [self.fake_replica, self.fake_replica_2],
5298 self.fake_replica_2, fake_access_rules, share_server=None)
5300 self.mock_dm_session.change_snapmirror_source.assert_called_once_with(
5301 self.fake_replica, self.fake_replica, self.fake_replica_2,
5302 mock.ANY, is_flexgroup=False
5303 )
5305 self.assertEqual(2, len(replicas))
5306 actual_replica_1 = list(filter(
5307 lambda x: x['id'] == self.fake_replica['id'], replicas))[0]
5308 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
5309 actual_replica_1['replica_state'])
5310 actual_replica_2 = list(filter(
5311 lambda x: x['id'] == self.fake_replica_2['id'], replicas))[0]
5312 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5313 actual_replica_2['replica_state'])
5314 self.assertEqual('fake_export_location',
5315 actual_replica_2['export_locations'])
5316 self.assertEqual(constants.SHARE_INSTANCE_RULES_SYNCING,
5317 actual_replica_2['access_rules_status'])
5318 self.library._handle_qos_on_replication_change.assert_called_once()
5320 def test_convert_destination_replica_to_independent_with_access_rules(
5321 self):
5322 fake_helper = mock.Mock()
5323 fake_helper.update_access.side_effect = Exception
5324 fake_access_rules = [
5325 {'access_to': "0.0.0.0",
5326 'access_level': constants.ACCESS_LEVEL_RO},
5327 {'access_to': "10.10.10.10",
5328 'access_level': constants.ACCESS_LEVEL_RW},
5329 ]
5330 self.mock_object(self.library,
5331 '_get_vserver',
5332 mock.Mock(return_value=(fake.VSERVER1,
5333 mock.Mock())))
5334 self.mock_object(self.library,
5335 '_get_helper',
5336 mock.Mock(return_value=fake_helper))
5337 self.mock_object(self.library, '_create_export',
5338 mock.Mock(return_value='fake_export_location'))
5340 replica = self.library._convert_destination_replica_to_independent(
5341 None, self.mock_dm_session, self.fake_replica,
5342 self.fake_replica_2, fake_access_rules, share_server=None)
5344 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5345 self.fake_replica, self.fake_replica_2)
5346 self.mock_dm_session.break_snapmirror.assert_called_once_with(
5347 self.fake_replica, self.fake_replica_2,
5348 quiesce_wait_time=None)
5350 self.assertEqual('fake_export_location',
5351 replica['export_locations'])
5352 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5353 replica['replica_state'])
5354 self.assertEqual(constants.SHARE_INSTANCE_RULES_SYNCING,
5355 replica['access_rules_status'])
5357 def test_convert_destination_replica_to_independent_failed_access_rules(
5358 self):
5359 fake_helper = mock.Mock()
5360 fake_access_rules = [
5361 {'access_to': "0.0.0.0",
5362 'access_level': constants.ACCESS_LEVEL_RO},
5363 {'access_to': "10.10.10.10",
5364 'access_level': constants.ACCESS_LEVEL_RW},
5365 ]
5366 self.mock_object(self.library,
5367 '_get_vserver',
5368 mock.Mock(return_value=(fake.VSERVER1,
5369 mock.Mock())))
5370 self.mock_object(self.library,
5371 '_get_helper',
5372 mock.Mock(return_value=fake_helper))
5373 self.mock_object(self.library, '_create_export',
5374 mock.Mock(return_value='fake_export_location'))
5376 replica = self.library._convert_destination_replica_to_independent(
5377 None, self.mock_dm_session, self.fake_replica,
5378 self.fake_replica_2, fake_access_rules, share_server=None)
5380 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5381 self.fake_replica, self.fake_replica_2)
5382 self.mock_dm_session.break_snapmirror.assert_called_once_with(
5383 self.fake_replica, self.fake_replica_2,
5384 quiesce_wait_time=None)
5386 fake_helper.assert_has_calls([
5387 mock.call.set_client(mock.ANY),
5388 mock.call.update_access(mock.ANY, mock.ANY, fake_access_rules),
5389 ])
5391 self.assertEqual('fake_export_location',
5392 replica['export_locations'])
5393 self.assertEqual(constants.REPLICA_STATE_ACTIVE,
5394 replica['replica_state'])
5395 self.assertEqual(constants.STATUS_ACTIVE,
5396 replica['access_rules_status'])
5398 @ddt.data(True, False)
5399 def test_safe_change_replica_source(self, is_dr):
5400 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5401 fake_replica_3['id'] = fake.SHARE_ID3
5402 fake_replica_3['replica_state'] = constants.REPLICA_STATE_OUT_OF_SYNC
5403 protocol_helper = mock.Mock()
5404 self.mock_object(self.library,
5405 '_get_helper',
5406 mock.Mock(return_value=protocol_helper))
5407 self.mock_object(self.library, '_create_export',
5408 mock.Mock(return_value='fake_export_location'))
5409 self.mock_object(self.library, '_unmount_orig_active_replica')
5410 self.mock_object(self.library, '_handle_qos_on_replication_change')
5412 mock_dm_session = mock.Mock()
5413 mock_dm_session.wait_for_mount_replica.return_value = None
5414 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
5415 mock.Mock(return_value=(fake.SHARE_NAME,
5416 fake.VSERVER1,
5417 fake.BACKEND_NAME)))
5418 mock_client = mock.Mock()
5419 self.mock_object(data_motion, "get_client_for_backend",
5420 mock.Mock(return_value=mock_client))
5421 mock_backend_config = fake.get_config_cmode()
5422 mock_backend_config.netapp_mount_replica_timeout = 30
5423 self.mock_object(data_motion, 'get_backend_configuration',
5424 mock.Mock(return_value=mock_backend_config))
5425 self.mock_object(self.library, '_get_api_client_for_backend',
5426 mock.Mock(return_value=mock_client))
5428 replica = self.library._safe_change_replica_source(
5429 mock_dm_session, self.fake_replica, self.fake_replica_2,
5430 fake_replica_3, [self.fake_replica, self.fake_replica_2,
5431 fake_replica_3], is_dr, [fake.SHARE_ACCESS]
5432 )
5434 self.assertEqual(constants.REPLICA_STATE_OUT_OF_SYNC,
5435 replica['replica_state'])
5436 if is_dr:
5437 self.assertEqual([], replica['export_locations'])
5438 mock_dm_session.wait_for_mount_replica.assert_not_called()
5439 else:
5440 self.assertEqual('fake_export_location',
5441 replica['export_locations'])
5442 mock_dm_session.wait_for_mount_replica.assert_called_once_with(
5443 mock_client, fake.SHARE_NAME, timeout=30)
5445 @ddt.data({'fail_create_export': False, 'fail_mount': True},
5446 {'fail_create_export': True, 'fail_mount': False})
5447 @ddt.unpack
5448 def test_safe_change_replica_source_fail_recover_readable(
5449 self, fail_create_export, fail_mount):
5451 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5452 fake_replica_3['id'] = fake.SHARE_ID3
5453 fake_replica_3['replica_state'] = constants.REPLICA_STATE_OUT_OF_SYNC
5454 protocol_helper = mock.Mock()
5455 self.mock_object(self.library,
5456 '_get_helper',
5457 mock.Mock(return_value=protocol_helper))
5458 if fail_create_export:
5459 self.mock_object(self.library, '_create_export',
5460 mock.Mock(side_effect=netapp_api.NaApiError()))
5461 else:
5462 self.mock_object(self.library, '_create_export',
5463 mock.Mock(return_value='fake_export_location'))
5464 self.mock_object(self.library, '_unmount_orig_active_replica')
5465 self.mock_object(self.library, '_handle_qos_on_replication_change')
5466 mock_dm_session = mock.Mock()
5467 if fail_mount:
5468 mock_dm_session.wait_for_mount_replica.side_effect = (
5469 netapp_api.NaApiError())
5470 else:
5471 mock_dm_session.wait_for_mount_replica.return_value = None
5472 self.mock_object(mock_dm_session, 'get_backend_info_for_share',
5473 mock.Mock(return_value=(fake.SHARE_NAME,
5474 fake.VSERVER1,
5475 fake.BACKEND_NAME)))
5476 mock_client = mock.Mock()
5477 self.mock_object(data_motion, "get_client_for_backend",
5478 mock.Mock(return_value=mock_client))
5479 mock_backend_config = fake.get_config_cmode()
5480 mock_backend_config.netapp_mount_replica_timeout = 30
5481 self.mock_object(data_motion, 'get_backend_configuration',
5482 mock.Mock(return_value=mock_backend_config))
5484 replica = self.library._safe_change_replica_source(
5485 mock_dm_session, self.fake_replica, self.fake_replica_2,
5486 fake_replica_3, [self.fake_replica, self.fake_replica_2,
5487 fake_replica_3], False, [fake.SHARE_ACCESS]
5488 )
5490 self.assertEqual(constants.STATUS_ERROR,
5491 replica['replica_state'])
5492 self.assertEqual(constants.STATUS_ERROR,
5493 replica['status'])
5495 def test_safe_change_replica_source_destination_unreachable(self):
5496 self.mock_dm_session.change_snapmirror_source.side_effect = (
5497 exception.StorageCommunicationException
5498 )
5500 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5501 fake_replica_3['id'] = fake.SHARE_ID3
5502 fake_replica_3['replica_state'] = constants.REPLICA_STATE_OUT_OF_SYNC
5503 replica = self.library._safe_change_replica_source(
5504 self.mock_dm_session, self.fake_replica, self.fake_replica_2,
5505 fake_replica_3, [self.fake_replica, self.fake_replica_2,
5506 fake_replica_3], True, [],
5507 )
5508 self.assertEqual([], replica['export_locations'])
5509 self.assertEqual(constants.STATUS_ERROR,
5510 replica['replica_state'])
5511 self.assertEqual(constants.STATUS_ERROR,
5512 replica['status'])
5514 def test_safe_change_replica_source_error(self):
5515 self.mock_dm_session.change_snapmirror_source.side_effect = (
5516 netapp_api.NaApiError(code=0)
5517 )
5519 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5520 fake_replica_3['id'] = fake.SHARE_ID3
5521 fake_replica_3['replica_state'] = constants.REPLICA_STATE_OUT_OF_SYNC
5522 replica = self.library._safe_change_replica_source(
5523 self.mock_dm_session, self.fake_replica, self.fake_replica_2,
5524 fake_replica_3, [self.fake_replica, self.fake_replica_2,
5525 fake_replica_3], True, []
5526 )
5527 self.assertEqual([], replica['export_locations'])
5528 self.assertEqual(constants.STATUS_ERROR,
5529 replica['replica_state'])
5531 def test_create_replicated_snapshot(self):
5532 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5533 fake_replica_3['id'] = fake.SHARE_ID3
5534 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5535 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5536 fake_snapshot['share_id'] = self.fake_replica['id']
5537 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5538 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5539 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5540 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5541 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5542 fake_snapshot_3['share_id'] = fake_replica_3['id']
5543 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5545 vserver_client = mock.Mock()
5546 self.mock_object(self.library,
5547 '_get_vserver',
5548 mock.Mock(return_value=(fake.VSERVER1,
5549 vserver_client)))
5551 model_list = self.library.create_replicated_snapshot(
5552 self.context, replica_list, snapshot_list,
5553 share_server=fake.SHARE_SERVER)
5555 share_name = self.library._get_backend_share_name(
5556 fake_snapshot['share_id'])
5557 snapshot_name = self.library._get_backend_snapshot_name(
5558 fake_snapshot['id'])
5559 vserver_client.create_snapshot.assert_called_once_with(share_name,
5560 snapshot_name)
5561 self.assertEqual(3, len(model_list))
5562 for snapshot in model_list:
5563 self.assertEqual(snapshot['provider_location'], snapshot_name)
5564 actual_active_snapshot = list(filter(
5565 lambda x: x['id'] == fake_snapshot['id'], model_list))[0]
5566 self.assertEqual(constants.STATUS_AVAILABLE,
5567 actual_active_snapshot['status'])
5568 actual_non_active_snapshot_list = list(filter(
5569 lambda x: x['id'] != fake_snapshot['id'], model_list))
5570 for snapshot in actual_non_active_snapshot_list:
5571 self.assertEqual(constants.STATUS_CREATING, snapshot['status'])
5572 self.mock_dm_session.update_snapmirror.assert_has_calls(
5573 [mock.call(self.fake_replica, self.fake_replica_2),
5574 mock.call(self.fake_replica, fake_replica_3)],
5575 any_order=True
5576 )
5578 def test_create_replicated_snapshot_with_creating_replica(self):
5579 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5580 fake_replica_3['id'] = fake.SHARE_ID3
5581 fake_replica_3['host'] = None
5582 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5583 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5584 fake_snapshot['share_id'] = self.fake_replica['id']
5585 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5586 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5587 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5588 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5589 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5590 fake_snapshot_3['share_id'] = fake_replica_3['id']
5591 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5593 vserver_client = mock.Mock()
5594 self.mock_object(self.library,
5595 '_get_vserver',
5596 mock.Mock(return_value=(fake.VSERVER1,
5597 vserver_client)))
5599 model_list = self.library.create_replicated_snapshot(
5600 self.context, replica_list, snapshot_list,
5601 share_server=fake.SHARE_SERVER)
5603 share_name = self.library._get_backend_share_name(
5604 fake_snapshot['share_id'])
5605 snapshot_name = self.library._get_backend_snapshot_name(
5606 fake_snapshot['id'])
5607 vserver_client.create_snapshot.assert_called_once_with(share_name,
5608 snapshot_name)
5609 self.assertEqual(3, len(model_list))
5610 for snapshot in model_list:
5611 self.assertEqual(snapshot['provider_location'], snapshot_name)
5612 actual_active_snapshot = list(filter(
5613 lambda x: x['id'] == fake_snapshot['id'], model_list))[0]
5614 self.assertEqual(constants.STATUS_AVAILABLE,
5615 actual_active_snapshot['status'])
5616 actual_non_active_snapshot_list = list(filter(
5617 lambda x: x['id'] != fake_snapshot['id'], model_list))
5618 for snapshot in actual_non_active_snapshot_list:
5619 self.assertEqual(constants.STATUS_CREATING, snapshot['status'])
5620 self.mock_dm_session.update_snapmirror.assert_has_calls(
5621 [mock.call(self.fake_replica, self.fake_replica_2)],
5622 any_order=True
5623 )
5625 @ddt.data(
5626 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND),
5627 netapp_api.NaApiError(message='not initialized'))
5628 def test_create_replicated_snapshot_no_snapmirror(self, api_exception):
5629 self.mock_dm_session.update_snapmirror.side_effect = [
5630 None,
5631 api_exception
5632 ]
5633 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5634 fake_replica_3['id'] = fake.SHARE_ID3
5635 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5636 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5637 fake_snapshot['share_id'] = self.fake_replica['id']
5638 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5639 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5640 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5641 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5642 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5643 fake_snapshot_3['share_id'] = fake_replica_3['id']
5644 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5646 vserver_client = mock.Mock()
5647 self.mock_object(self.library,
5648 '_get_vserver',
5649 mock.Mock(return_value=(fake.VSERVER1,
5650 vserver_client)))
5652 model_list = self.library.create_replicated_snapshot(
5653 self.context, replica_list, snapshot_list,
5654 share_server=fake.SHARE_SERVER)
5656 share_name = self.library._get_backend_share_name(
5657 fake_snapshot['share_id'])
5658 snapshot_name = self.library._get_backend_snapshot_name(
5659 fake_snapshot['id'])
5660 vserver_client.create_snapshot.assert_called_once_with(share_name,
5661 snapshot_name)
5662 self.assertEqual(3, len(model_list))
5663 for snapshot in model_list:
5664 self.assertEqual(snapshot['provider_location'], snapshot_name)
5665 actual_active_snapshot = list(filter(
5666 lambda x: x['id'] == fake_snapshot['id'], model_list))[0]
5667 self.assertEqual(constants.STATUS_AVAILABLE,
5668 actual_active_snapshot['status'])
5669 actual_non_active_snapshot_list = list(filter(
5670 lambda x: x['id'] != fake_snapshot['id'], model_list))
5671 for snapshot in actual_non_active_snapshot_list:
5672 self.assertEqual(constants.STATUS_CREATING, snapshot['status'])
5673 self.mock_dm_session.update_snapmirror.assert_has_calls(
5674 [mock.call(self.fake_replica, self.fake_replica_2),
5675 mock.call(self.fake_replica, fake_replica_3)],
5676 any_order=True
5677 )
5679 def test_create_replicated_snapshot_update_error(self):
5680 self.mock_dm_session.update_snapmirror.side_effect = [
5681 None,
5682 netapp_api.NaApiError()
5683 ]
5684 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5685 fake_replica_3['id'] = fake.SHARE_ID3
5686 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5687 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5688 fake_snapshot['share_id'] = self.fake_replica['id']
5689 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5690 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5691 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5692 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5693 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5694 fake_snapshot_3['share_id'] = fake_replica_3['id']
5695 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5697 vserver_client = mock.Mock()
5698 self.mock_object(self.library,
5699 '_get_vserver',
5700 mock.Mock(return_value=(fake.VSERVER1,
5701 vserver_client)))
5703 self.assertRaises(netapp_api.NaApiError,
5704 self.library.create_replicated_snapshot,
5705 self.context, replica_list, snapshot_list,
5706 share_server=fake.SHARE_SERVER)
5708 def test_delete_replicated_snapshot(self):
5709 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5710 fake_replica_3['id'] = fake.SHARE_ID3
5711 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5712 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5713 fake_snapshot['share_id'] = self.fake_replica['id']
5714 share_name = self.library._get_backend_share_name(
5715 fake_snapshot['share_id'])
5716 snapshot_name = self.library._get_backend_snapshot_name(
5717 fake_snapshot['id'])
5718 fake_snapshot['provider_location'] = snapshot_name
5719 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5720 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5721 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5722 fake_snapshot_2['provider_location'] = snapshot_name
5723 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5724 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5725 fake_snapshot_3['share_id'] = fake_replica_3['id']
5726 fake_snapshot_3['provider_location'] = snapshot_name
5728 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5730 vserver_client = mock.Mock()
5731 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
5732 self.mock_object(self.library,
5733 '_get_vserver',
5734 mock.Mock(return_value=(fake.VSERVER1,
5735 vserver_client)))
5737 self.library.delete_replicated_snapshot(
5738 self.context, replica_list, snapshot_list,
5739 share_server=fake.SHARE_SERVER)
5741 vserver_client.delete_snapshot.assert_called_once_with(share_name,
5742 snapshot_name)
5744 self.mock_dm_session.update_snapmirror.assert_has_calls(
5745 [mock.call(self.fake_replica, self.fake_replica_2),
5746 mock.call(self.fake_replica, fake_replica_3)],
5747 any_order=True
5748 )
5750 def test_delete_replicated_snapshot_replica_still_creating(self):
5751 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5752 fake_replica_3['id'] = fake.SHARE_ID3
5753 fake_replica_3['host'] = None
5754 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5755 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5756 fake_snapshot['share_id'] = self.fake_replica['id']
5757 share_name = self.library._get_backend_share_name(
5758 fake_snapshot['share_id'])
5759 snapshot_name = self.library._get_backend_snapshot_name(
5760 fake_snapshot['id'])
5761 fake_snapshot['provider_location'] = snapshot_name
5762 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5763 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5764 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5765 fake_snapshot_2['provider_location'] = snapshot_name
5766 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5767 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5768 fake_snapshot_3['share_id'] = fake_replica_3['id']
5769 fake_snapshot_3['provider_location'] = snapshot_name
5771 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5773 vserver_client = mock.Mock()
5774 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
5775 self.mock_object(self.library,
5776 '_get_vserver',
5777 mock.Mock(return_value=(fake.VSERVER1,
5778 vserver_client)))
5780 self.library.delete_replicated_snapshot(
5781 self.context, replica_list, snapshot_list,
5782 share_server=fake.SHARE_SERVER)
5784 vserver_client.delete_snapshot.assert_called_once_with(share_name,
5785 snapshot_name)
5787 self.mock_dm_session.update_snapmirror.assert_has_calls(
5788 [mock.call(self.fake_replica, self.fake_replica_2)],
5789 any_order=True
5790 )
5792 @ddt.data(
5793 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND),
5794 netapp_api.NaApiError(message='not initialized'))
5795 def test_delete_replicated_snapshot_missing_snapmirror(self,
5796 api_exception):
5797 self.mock_dm_session.update_snapmirror.side_effect = [
5798 None,
5799 api_exception
5800 ]
5801 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5802 fake_replica_3['id'] = fake.SHARE_ID3
5803 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5804 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5805 fake_snapshot['share_id'] = self.fake_replica['id']
5806 share_name = self.library._get_backend_share_name(
5807 fake_snapshot['share_id'])
5808 snapshot_name = self.library._get_backend_snapshot_name(
5809 fake_snapshot['id'])
5810 fake_snapshot['provider_location'] = snapshot_name
5811 fake_snapshot['busy'] = False
5813 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5814 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5815 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5816 fake_snapshot_2['provider_location'] = snapshot_name
5817 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5818 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5819 fake_snapshot_3['share_id'] = fake_replica_3['id']
5820 fake_snapshot_3['provider_location'] = snapshot_name
5822 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5824 vserver_client = mock.Mock()
5825 vserver_client.get_snapshot.return_value = fake_snapshot
5826 self.mock_object(self.library,
5827 '_get_vserver',
5828 mock.Mock(return_value=(fake.VSERVER1,
5829 vserver_client)))
5831 self.library.delete_replicated_snapshot(
5832 self.context, replica_list, snapshot_list,
5833 share_server=fake.SHARE_SERVER)
5835 vserver_client.delete_snapshot.assert_called_once_with(share_name,
5836 snapshot_name)
5838 self.mock_dm_session.update_snapmirror.assert_has_calls(
5839 [mock.call(self.fake_replica, self.fake_replica_2),
5840 mock.call(self.fake_replica, fake_replica_3)],
5841 any_order=True
5842 )
5844 def test_delete_replicated_snapshot_update_error(self):
5845 self.mock_dm_session.update_snapmirror.side_effect = [
5846 None,
5847 netapp_api.NaApiError()
5848 ]
5849 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
5850 fake_replica_3['id'] = fake.SHARE_ID3
5851 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
5852 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5853 fake_snapshot['share_id'] = self.fake_replica['id']
5854 snapshot_name = self.library._get_backend_snapshot_name(
5855 fake_snapshot['id'])
5856 fake_snapshot['provider_location'] = snapshot_name
5857 fake_snapshot['busy'] = False
5859 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
5860 fake_snapshot_2['id'] = uuidutils.generate_uuid()
5861 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
5862 fake_snapshot_2['provider_location'] = snapshot_name
5863 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
5864 fake_snapshot_3['id'] = uuidutils.generate_uuid()
5865 fake_snapshot_3['share_id'] = fake_replica_3['id']
5866 fake_snapshot_3['provider_location'] = snapshot_name
5868 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
5870 vserver_client = mock.Mock()
5871 vserver_client.get_snapshot.return_value = fake_snapshot
5872 self.mock_object(self.library,
5873 '_get_vserver',
5874 mock.Mock(return_value=(fake.VSERVER1,
5875 vserver_client)))
5877 self.assertRaises(netapp_api.NaApiError,
5878 self.library.delete_replicated_snapshot,
5879 self.context, replica_list, snapshot_list,
5880 share_server=fake.SHARE_SERVER)
5882 def test_update_replicated_snapshot_still_creating(self):
5883 vserver_client = mock.Mock()
5884 vserver_client.snapshot_exists.return_value = False
5885 self.mock_object(self.library,
5886 '_get_vserver',
5887 mock.Mock(return_value=(fake.VSERVER1,
5888 vserver_client)))
5889 replica_list = [self.fake_replica, self.fake_replica_2]
5890 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5891 fake_snapshot['status'] = constants.STATUS_CREATING
5892 fake_snapshot['share_id'] = self.fake_replica_2['id']
5893 snapshot_name = self.library._get_backend_snapshot_name(
5894 fake_snapshot['id'])
5895 fake_snapshot['provider_location'] = snapshot_name
5897 model_update = self.library.update_replicated_snapshot(
5898 replica_list, self.fake_replica_2, [fake_snapshot], fake_snapshot)
5900 self.assertIsNone(model_update)
5901 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5902 self.fake_replica, self.fake_replica_2
5903 )
5905 def test_update_replicated_snapshot_still_creating_no_host(self):
5906 self.fake_replica_2['host'] = None
5907 vserver_client = mock.Mock()
5908 vserver_client.snapshot_exists.return_value = False
5909 self.mock_object(self.library,
5910 '_get_vserver',
5911 mock.Mock(return_value=(fake.VSERVER1,
5912 vserver_client)))
5913 replica_list = [self.fake_replica, self.fake_replica_2]
5914 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5915 fake_snapshot['status'] = constants.STATUS_CREATING
5916 fake_snapshot['share_id'] = self.fake_replica_2['id']
5917 snapshot_name = self.library._get_backend_snapshot_name(
5918 fake_snapshot['id'])
5919 fake_snapshot['provider_location'] = snapshot_name
5921 model_update = self.library.update_replicated_snapshot(
5922 replica_list, self.fake_replica_2, [fake_snapshot], fake_snapshot)
5924 self.assertIsNone(model_update)
5925 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5926 self.fake_replica, self.fake_replica_2
5927 )
5929 @ddt.data(
5930 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND),
5931 netapp_api.NaApiError(message='not initialized'))
5932 def test_update_replicated_snapshot_no_snapmirror(self, api_exception):
5933 vserver_client = mock.Mock()
5934 vserver_client.snapshot_exists.return_value = False
5935 self.mock_dm_session.update_snapmirror.side_effect = api_exception
5936 self.mock_object(self.library,
5937 '_get_vserver',
5938 mock.Mock(return_value=(fake.VSERVER1,
5939 vserver_client)))
5940 replica_list = [self.fake_replica, self.fake_replica_2]
5941 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5942 fake_snapshot['status'] = constants.STATUS_CREATING
5943 fake_snapshot['share_id'] = self.fake_replica_2['id']
5944 snapshot_name = self.library._get_backend_snapshot_name(
5945 fake_snapshot['id'])
5946 fake_snapshot['provider_location'] = snapshot_name
5948 model_update = self.library.update_replicated_snapshot(
5949 replica_list, self.fake_replica_2, [fake_snapshot], fake_snapshot)
5951 self.assertIsNone(model_update)
5952 self.mock_dm_session.update_snapmirror.assert_called_once_with(
5953 self.fake_replica, self.fake_replica_2
5954 )
5956 def test_update_replicated_snapshot_update_error(self):
5957 vserver_client = mock.Mock()
5958 vserver_client.snapshot_exists.return_value = False
5959 self.mock_dm_session.update_snapmirror.side_effect = (
5960 netapp_api.NaApiError()
5961 )
5962 self.mock_object(self.library,
5963 '_get_vserver',
5964 mock.Mock(return_value=(fake.VSERVER1,
5965 vserver_client)))
5966 replica_list = [self.fake_replica, self.fake_replica_2]
5967 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5968 fake_snapshot['status'] = constants.STATUS_CREATING
5969 fake_snapshot['share_id'] = self.fake_replica_2['id']
5970 snapshot_name = self.library._get_backend_snapshot_name(
5971 fake_snapshot['id'])
5972 fake_snapshot['provider_location'] = snapshot_name
5974 self.assertRaises(netapp_api.NaApiError,
5975 self.library.update_replicated_snapshot,
5976 replica_list, self.fake_replica_2,
5977 [fake_snapshot], fake_snapshot)
5979 def test_update_replicated_snapshot_still_deleting(self):
5980 vserver_client = mock.Mock()
5981 vserver_client.snapshot_exists.return_value = True
5982 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
5983 self.mock_object(self.library,
5984 '_get_vserver',
5985 mock.Mock(return_value=(fake.VSERVER1,
5986 vserver_client)))
5988 replica_list = [self.fake_replica]
5989 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
5990 fake_snapshot['status'] = constants.STATUS_DELETING
5991 fake_snapshot['share_id'] = self.fake_replica['id']
5992 snapshot_name = self.library._get_backend_snapshot_name(
5993 fake_snapshot['id'])
5994 fake_snapshot['provider_location'] = snapshot_name
5996 model_update = self.library.update_replicated_snapshot(
5997 replica_list, self.fake_replica, [fake_snapshot], fake_snapshot)
5999 self.assertIsNone(model_update)
6001 def test_update_replicated_snapshot_created(self):
6002 vserver_client = mock.Mock()
6003 vserver_client.snapshot_exists.return_value = True
6004 self.mock_object(self.library,
6005 '_get_vserver',
6006 mock.Mock(return_value=(fake.VSERVER1,
6007 vserver_client)))
6008 replica_list = [self.fake_replica]
6009 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
6010 fake_snapshot['status'] = constants.STATUS_CREATING
6011 fake_snapshot['share_id'] = self.fake_replica['id']
6012 snapshot_name = self.library._get_backend_snapshot_name(
6013 fake_snapshot['id'])
6014 fake_snapshot['provider_location'] = snapshot_name
6016 model_update = self.library.update_replicated_snapshot(
6017 replica_list, self.fake_replica, [fake_snapshot], fake_snapshot)
6019 self.assertEqual(constants.STATUS_AVAILABLE, model_update['status'])
6020 self.assertEqual(snapshot_name, model_update['provider_location'])
6022 def test_update_replicated_snapshot_created_no_provider_location(self):
6023 vserver_client = mock.Mock()
6024 vserver_client.snapshot_exists.return_value = True
6025 self.mock_object(self.library,
6026 '_get_vserver',
6027 mock.Mock(return_value=(fake.VSERVER1,
6028 vserver_client)))
6029 replica_list = [self.fake_replica, self.fake_replica_2]
6030 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
6031 fake_snapshot['status'] = constants.STATUS_ACTIVE
6032 fake_snapshot['share_id'] = self.fake_replica['id']
6033 snapshot_name = self.library._get_backend_snapshot_name(
6034 fake_snapshot['id'])
6035 fake_snapshot['provider_location'] = snapshot_name
6036 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
6037 fake_snapshot_2['status'] = constants.STATUS_CREATING
6038 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
6040 model_update = self.library.update_replicated_snapshot(
6041 replica_list, self.fake_replica_2,
6042 [fake_snapshot, fake_snapshot_2], fake_snapshot_2)
6044 self.assertEqual(constants.STATUS_AVAILABLE, model_update['status'])
6045 self.assertEqual(snapshot_name, model_update['provider_location'])
6047 def test_update_replicated_snapshot_deleted(self):
6048 vserver_client = mock.Mock()
6049 vserver_client.snapshot_exists.return_value = False
6050 self.mock_object(self.library,
6051 '_get_vserver',
6052 mock.Mock(return_value=(fake.VSERVER1,
6053 vserver_client)))
6054 replica_list = [self.fake_replica]
6055 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
6056 fake_snapshot['status'] = constants.STATUS_DELETING
6057 fake_snapshot['share_id'] = self.fake_replica['id']
6058 snapshot_name = self.library._get_backend_snapshot_name(
6059 fake_snapshot['id'])
6060 fake_snapshot['provider_location'] = snapshot_name
6062 self.assertRaises(exception.SnapshotResourceNotFound,
6063 self.library.update_replicated_snapshot,
6064 replica_list, self.fake_replica, [fake_snapshot],
6065 fake_snapshot)
6067 def test_update_replicated_snapshot_no_provider_locations(self):
6068 vserver_client = mock.Mock()
6069 vserver_client.snapshot_exists.return_value = True
6070 self.mock_object(self.library,
6071 '_get_vserver',
6072 mock.Mock(return_value=(fake.VSERVER1,
6073 vserver_client)))
6074 replica_list = [self.fake_replica]
6075 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
6076 fake_snapshot['status'] = constants.STATUS_CREATING
6077 fake_snapshot['share_id'] = self.fake_replica['id']
6078 fake_snapshot['provider_location'] = None
6080 model_update = self.library.update_replicated_snapshot(
6081 replica_list, self.fake_replica, [fake_snapshot], fake_snapshot)
6083 self.assertIsNone(model_update)
6085 def _get_fake_replicas_and_snapshots(self):
6087 fake_replica_3 = copy.deepcopy(self.fake_replica_2)
6088 fake_replica_3['id'] = fake.SHARE_ID3
6089 fake_snapshot = copy.deepcopy(fake.SNAPSHOT)
6090 fake_snapshot['share_id'] = self.fake_replica['id']
6091 snapshot_name = self.library._get_backend_snapshot_name(
6092 fake_snapshot['id'])
6093 fake_snapshot['provider_location'] = snapshot_name
6094 fake_snapshot_2 = copy.deepcopy(fake.SNAPSHOT)
6095 fake_snapshot_2['id'] = uuidutils.generate_uuid()
6096 fake_snapshot_2['share_id'] = self.fake_replica_2['id']
6097 fake_snapshot_2['provider_location'] = snapshot_name
6098 fake_snapshot_3 = copy.deepcopy(fake.SNAPSHOT)
6099 fake_snapshot_3['id'] = uuidutils.generate_uuid()
6100 fake_snapshot_3['share_id'] = fake_replica_3['id']
6101 fake_snapshot_3['provider_location'] = snapshot_name
6102 replica_list = [self.fake_replica, self.fake_replica_2, fake_replica_3]
6103 snapshot_list = [fake_snapshot, fake_snapshot_2, fake_snapshot_3]
6104 return replica_list, snapshot_list
6106 @ddt.data(True, False)
6107 def test_revert_to_replicated_snapshot(self, use_snap_provider_location):
6109 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6110 fake_replica, fake_replica_2, fake_replica_3 = replica_list
6111 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6113 if not use_snap_provider_location:
6114 del fake_snapshot['provider_location']
6115 del fake_snapshot_2['provider_location']
6116 del fake_snapshot_3['provider_location']
6118 share_name = self.library._get_backend_share_name(
6119 fake_snapshot['share_id'])
6120 snapshot_name = self.library._get_backend_snapshot_name(
6121 fake_snapshot['id'])
6123 vserver_client = mock.Mock()
6124 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
6125 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6126 self.mock_object(self.library,
6127 '_get_vserver',
6128 mock.Mock(return_value=(fake.VSERVER1,
6129 vserver_client)))
6131 self.library.revert_to_replicated_snapshot(
6132 self.context, self.fake_replica, replica_list, fake_snapshot,
6133 snapshot_list, share_server=fake.SHARE_SERVER)
6135 vserver_client.get_snapshot.assert_called_once_with(
6136 share_name, snapshot_name)
6137 vserver_client.list_snapmirror_snapshots.assert_called_once_with(
6138 share_name)
6139 vserver_client.delete_snapshot.assert_called_once_with(
6140 share_name, 'sm_snap', ignore_owners=True)
6141 vserver_client.restore_snapshot.assert_called_once_with(
6142 share_name, snapshot_name)
6144 self.mock_dm_session.break_snapmirror.assert_has_calls(
6145 [mock.call(self.fake_replica, self.fake_replica_2, mount=False),
6146 mock.call(self.fake_replica, fake_replica_3, mount=False)],
6147 any_order=True)
6148 self.mock_dm_session.resync_snapmirror.assert_has_calls(
6149 [mock.call(self.fake_replica, self.fake_replica_2),
6150 mock.call(self.fake_replica, fake_replica_3)],
6151 any_order=True)
6153 def test_revert_to_replicated_snapshot_not_found(self):
6155 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6156 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6157 share_name = self.library._get_backend_share_name(
6158 fake_snapshot['share_id'])
6159 snapshot_name = self.library._get_backend_snapshot_name(
6160 fake_snapshot['id'])
6162 vserver_client = mock.Mock()
6163 vserver_client.get_snapshot.side_effect = netapp_api.NaApiError
6164 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6165 self.mock_object(self.library,
6166 '_get_vserver',
6167 mock.Mock(return_value=(fake.VSERVER1,
6168 vserver_client)))
6170 self.assertRaises(
6171 netapp_api.NaApiError, self.library.revert_to_replicated_snapshot,
6172 self.context, self.fake_replica, replica_list, fake_snapshot,
6173 snapshot_list, share_server=fake.SHARE_SERVER)
6175 vserver_client.get_snapshot.assert_called_once_with(
6176 share_name, snapshot_name)
6177 self.assertFalse(vserver_client.list_snapmirror_snapshots.called)
6178 self.assertFalse(vserver_client.delete_snapshot.called)
6179 self.assertFalse(vserver_client.restore_snapshot.called)
6180 self.assertFalse(self.mock_dm_session.break_snapmirror.called)
6181 self.assertFalse(self.mock_dm_session.resync_snapmirror.called)
6183 def test_revert_to_replicated_snapshot_snapmirror_break_error(self):
6185 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6186 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6188 vserver_client = mock.Mock()
6189 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
6190 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6191 self.mock_object(self.library,
6192 '_get_vserver',
6193 mock.Mock(return_value=(fake.VSERVER1,
6194 vserver_client)))
6195 self.mock_dm_session.break_snapmirror.side_effect = (
6196 netapp_api.NaApiError)
6198 self.assertRaises(
6199 netapp_api.NaApiError, self.library.revert_to_replicated_snapshot,
6200 self.context, self.fake_replica, replica_list, fake_snapshot,
6201 snapshot_list, share_server=fake.SHARE_SERVER)
6203 def test_revert_to_replicated_snapshot_snapmirror_break_not_found(self):
6205 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6206 fake_replica, fake_replica_2, fake_replica_3 = replica_list
6207 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6208 share_name = self.library._get_backend_share_name(
6209 fake_snapshot['share_id'])
6210 snapshot_name = self.library._get_backend_snapshot_name(
6211 fake_snapshot['id'])
6213 vserver_client = mock.Mock()
6214 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
6215 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6216 self.mock_object(self.library,
6217 '_get_vserver',
6218 mock.Mock(return_value=(fake.VSERVER1,
6219 vserver_client)))
6220 self.mock_dm_session.break_snapmirror.side_effect = (
6221 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND))
6223 self.library.revert_to_replicated_snapshot(
6224 self.context, self.fake_replica, replica_list, fake_snapshot,
6225 snapshot_list, share_server=fake.SHARE_SERVER)
6227 vserver_client.get_snapshot.assert_called_once_with(
6228 share_name, snapshot_name)
6229 vserver_client.list_snapmirror_snapshots.assert_called_once_with(
6230 share_name)
6231 vserver_client.delete_snapshot.assert_called_once_with(
6232 share_name, 'sm_snap', ignore_owners=True)
6233 vserver_client.restore_snapshot.assert_called_once_with(
6234 share_name, snapshot_name)
6236 self.mock_dm_session.break_snapmirror.assert_has_calls(
6237 [mock.call(self.fake_replica, self.fake_replica_2, mount=False),
6238 mock.call(self.fake_replica, fake_replica_3, mount=False)],
6239 any_order=True)
6240 self.mock_dm_session.resync_snapmirror.assert_has_calls(
6241 [mock.call(self.fake_replica, self.fake_replica_2),
6242 mock.call(self.fake_replica, fake_replica_3)],
6243 any_order=True)
6245 def test_revert_to_replicated_snapshot_snapmirror_resync_error(self):
6247 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6248 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6250 vserver_client = mock.Mock()
6251 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
6252 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6253 self.mock_object(self.library,
6254 '_get_vserver',
6255 mock.Mock(return_value=(fake.VSERVER1,
6256 vserver_client)))
6257 self.mock_dm_session.resync_snapmirror.side_effect = (
6258 netapp_api.NaApiError)
6260 self.assertRaises(
6261 netapp_api.NaApiError, self.library.revert_to_replicated_snapshot,
6262 self.context, self.fake_replica, replica_list, fake_snapshot,
6263 snapshot_list, share_server=fake.SHARE_SERVER)
6265 def test_revert_to_replicated_snapshot_snapmirror_resync_not_found(self):
6267 replica_list, snapshot_list = self._get_fake_replicas_and_snapshots()
6268 fake_replica, fake_replica_2, fake_replica_3 = replica_list
6269 fake_snapshot, fake_snapshot_2, fake_snapshot_3 = snapshot_list
6270 share_name = self.library._get_backend_share_name(
6271 fake_snapshot['share_id'])
6272 snapshot_name = self.library._get_backend_snapshot_name(
6273 fake_snapshot['id'])
6275 vserver_client = mock.Mock()
6276 vserver_client.get_snapshot.return_value = fake.CDOT_SNAPSHOT
6277 vserver_client.list_snapmirror_snapshots.return_value = ['sm_snap']
6278 self.mock_object(self.library,
6279 '_get_vserver',
6280 mock.Mock(return_value=(fake.VSERVER1,
6281 vserver_client)))
6282 self.mock_dm_session.resync_snapmirror.side_effect = (
6283 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND))
6285 self.library.revert_to_replicated_snapshot(
6286 self.context, self.fake_replica, replica_list, fake_snapshot,
6287 snapshot_list, share_server=fake.SHARE_SERVER)
6289 vserver_client.get_snapshot.assert_called_once_with(
6290 share_name, snapshot_name)
6291 vserver_client.list_snapmirror_snapshots.assert_called_once_with(
6292 share_name)
6293 vserver_client.delete_snapshot.assert_called_once_with(
6294 share_name, 'sm_snap', ignore_owners=True)
6295 vserver_client.restore_snapshot.assert_called_once_with(
6296 share_name, snapshot_name)
6298 self.mock_dm_session.break_snapmirror.assert_has_calls(
6299 [mock.call(self.fake_replica, self.fake_replica_2, mount=False),
6300 mock.call(self.fake_replica, fake_replica_3, mount=False)],
6301 any_order=True)
6302 self.mock_dm_session.resync_snapmirror.assert_has_calls(
6303 [mock.call(self.fake_replica, self.fake_replica_2),
6304 mock.call(self.fake_replica, fake_replica_3)],
6305 any_order=True)
6307 @ddt.data(
6308 {'replication_type': constants.REPLICATION_TYPE_READABLE,
6309 'is_readable': True},
6310 {'replication_type': constants.REPLICATION_TYPE_DR,
6311 'is_readable': False},
6312 {'replication_type': constants.REPLICATION_TYPE_WRITABLE,
6313 'is_readable': False},
6314 {'replication_type': None,
6315 'is_readable': False})
6316 @ddt.unpack
6317 def test__is_readable_replica(self, replication_type, is_readable):
6318 extra_specs = {}
6319 if replication_type:
6320 extra_specs['replication_type'] = replication_type
6321 mock_get_extra_spec = self.mock_object(
6322 share_types, 'get_extra_specs_from_share',
6323 mock.Mock(return_value=extra_specs))
6325 result = self.library._is_readable_replica(fake.SHARE)
6327 self.assertEqual(is_readable, result)
6328 mock_get_extra_spec.assert_called_once_with(fake.SHARE)
6330 def test_migration_check_compatibility_no_cluster_credentials(self):
6331 self.library._have_cluster_creds = False
6332 self.mock_object(data_motion, 'get_backend_configuration')
6333 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
6335 migration_compatibility = self.library.migration_check_compatibility(
6336 self.context, fake_share.fake_share_instance(),
6337 fake_share.fake_share_instance(), share_server=None,
6338 destination_share_server=fake.SHARE_SERVER)
6340 expected_compatibility = {
6341 'compatible': False,
6342 'writable': False,
6343 'nondisruptive': False,
6344 'preserve_metadata': False,
6345 'preserve_snapshots': False,
6346 }
6347 self.assertDictEqual(expected_compatibility, migration_compatibility)
6348 mock_warning_log.assert_called_once()
6349 self.assertFalse(data_motion.get_backend_configuration.called)
6351 @ddt.data(
6352 {'src_flexgroup': True, 'dest_flexgroup': False},
6353 {'src_flexgroup': False, 'dest_flexgroup': True})
6354 @ddt.unpack
6355 def test_migration_check_compatibility_flexgroup(self, src_flexgroup,
6356 dest_flexgroup):
6357 self.library._have_cluster_creds = True
6358 mock_dm = mock.Mock()
6359 self.mock_object(data_motion, 'DataMotionSession',
6360 mock.Mock(return_value=mock_dm))
6361 self.mock_object(self.library, 'is_flexgroup_destination_host',
6362 mock.Mock(return_value=dest_flexgroup))
6363 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6364 self.mock_object(share_utils, 'extract_host',
6365 mock.Mock(return_value=fake.POOL_NAME))
6366 self.mock_object(self.library, '_is_flexgroup_pool',
6367 mock.Mock(return_value=src_flexgroup))
6369 migration_compatibility = self.library.migration_check_compatibility(
6370 self.context, fake_share.fake_share_instance(),
6371 fake_share.fake_share_instance(), share_server=None,
6372 destination_share_server=fake.SHARE_SERVER)
6374 expected_compatibility = {
6375 'compatible': False,
6376 'writable': False,
6377 'nondisruptive': False,
6378 'preserve_metadata': False,
6379 'preserve_snapshots': False,
6380 }
6381 self.assertDictEqual(expected_compatibility, migration_compatibility)
6382 mock_exception_log.assert_called_once()
6383 self.library._is_flexgroup_pool.assert_called_once_with(fake.POOL_NAME)
6384 if src_flexgroup:
6385 self.library.is_flexgroup_destination_host.assert_not_called()
6387 @ddt.data((None, exception.NetAppException),
6388 (exception.Invalid, None))
6389 @ddt.unpack
6390 def test_migration_check_compatibility_extra_specs_invalid(
6391 self, side_effect_1, side_effect_2):
6392 self.library._have_cluster_creds = True
6393 mock_dm = mock.Mock()
6394 self.mock_object(data_motion, 'DataMotionSession',
6395 mock.Mock(return_value=mock_dm))
6396 self.mock_object(self.library, 'is_flexgroup_destination_host',
6397 mock.Mock(return_value=False))
6398 self.mock_object(self.library, '_is_flexgroup_pool',
6399 mock.Mock(return_value=False))
6400 self.mock_object(self.library, '_get_backend_share_name',
6401 mock.Mock(return_value=fake.SHARE_NAME))
6402 self.mock_object(share_utils, 'extract_host', mock.Mock(
6403 side_effect=[
6404 'destination_backend', 'destination_pool', 'source_pool']))
6405 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6406 self.mock_object(share_types, 'get_extra_specs_from_share')
6407 self.mock_object(self.library, '_check_extra_specs_validity',
6408 mock.Mock(side_effect=side_effect_1))
6409 self.mock_object(self.library,
6410 '_check_aggregate_extra_specs_validity',
6411 mock.Mock(side_effect=side_effect_2))
6412 self.mock_object(data_motion, 'get_backend_configuration')
6414 migration_compatibility = self.library.migration_check_compatibility(
6415 self.context, fake_share.fake_share_instance(),
6416 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6417 destination_share_server=None)
6419 expected_compatibility = {
6420 'compatible': False,
6421 'writable': False,
6422 'nondisruptive': False,
6423 'preserve_metadata': False,
6424 'preserve_snapshots': False,
6425 }
6426 self.assertDictEqual(expected_compatibility, migration_compatibility)
6427 mock_exception_log.assert_called_once()
6428 self.assertFalse(data_motion.get_backend_configuration.called)
6430 def test_migration_check_compatibility_invalid_qos_configuration(self):
6431 self.library._have_cluster_creds = True
6432 mock_dm = mock.Mock()
6433 self.mock_object(data_motion, 'DataMotionSession',
6434 mock.Mock(return_value=mock_dm))
6435 self.mock_object(self.library, 'is_flexgroup_destination_host',
6436 mock.Mock(return_value=False))
6437 self.mock_object(self.library, '_is_flexgroup_pool',
6438 mock.Mock(return_value=False))
6439 self.mock_object(self.library, '_get_backend_share_name',
6440 mock.Mock(return_value=fake.SHARE_NAME))
6441 self.mock_object(share_utils, 'extract_host', mock.Mock(
6442 side_effect=[
6443 'destination_backend', 'destination_pool', 'source_pool']))
6444 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6445 self.mock_object(share_types, 'get_extra_specs_from_share')
6446 self.mock_object(self.library, '_check_extra_specs_validity')
6447 self.mock_object(
6448 self.library, '_get_provisioning_options',
6449 mock.Mock(return_value=fake.PROVISIONING_OPTS_WITH_ADAPT_QOS))
6450 self.mock_object(self.library, '_get_normalized_qos_specs',
6451 mock.Mock(return_value=fake.QOS_NORMALIZED_SPEC))
6453 migration_compatibility = self.library.migration_check_compatibility(
6454 self.context, fake_share.fake_share_instance(),
6455 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6456 destination_share_server=None)
6458 expected_compatibility = {
6459 'compatible': False,
6460 'writable': False,
6461 'nondisruptive': False,
6462 'preserve_metadata': False,
6463 'preserve_snapshots': False,
6464 }
6465 self.assertDictEqual(expected_compatibility, migration_compatibility)
6466 mock_exception_log.assert_called_once()
6468 def test_migration_check_compatibility_destination_not_configured(self):
6469 self.library._have_cluster_creds = True
6470 mock_dm = mock.Mock()
6471 mock_dm = mock.Mock()
6472 self.mock_object(data_motion, 'DataMotionSession',
6473 mock.Mock(return_value=mock_dm))
6474 self.mock_object(self.library, 'is_flexgroup_destination_host',
6475 mock.Mock(return_value=False))
6476 self.mock_object(self.library, '_is_flexgroup_pool',
6477 mock.Mock(return_value=False))
6478 self.mock_object(self.library, '_get_backend_share_name',
6479 mock.Mock(return_value=fake.SHARE_NAME))
6480 self.mock_object(
6481 data_motion, 'get_backend_configuration',
6482 mock.Mock(side_effect=exception.BadConfigurationException(
6483 reason='fake_reason')))
6484 self.mock_object(self.library, '_get_vserver')
6485 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6486 self.mock_object(share_utils, 'extract_host', mock.Mock(
6487 return_value='destination_backend'))
6488 self.mock_object(share_types, 'get_extra_specs_from_share')
6489 self.mock_object(self.library, '_check_extra_specs_validity')
6490 self.mock_object(self.library, '_check_aggregate_extra_specs_validity')
6491 self.mock_object(self.library, '_get_provisioning_options',
6492 mock.Mock(return_value={}))
6493 self.mock_object(self.library, '_get_normalized_qos_specs')
6494 self.mock_object(self.library,
6495 'validate_provisioning_options_for_share')
6496 mock_vserver_compatibility_check = self.mock_object(
6497 self.library, '_check_destination_vserver_for_vol_move')
6498 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6499 mock.Mock(return_value=False))
6501 migration_compatibility = self.library.migration_check_compatibility(
6502 self.context, fake_share.fake_share_instance(),
6503 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6504 destination_share_server=None)
6506 expected_compatibility = {
6507 'compatible': False,
6508 'writable': False,
6509 'nondisruptive': False,
6510 'preserve_metadata': False,
6511 'preserve_snapshots': False,
6512 }
6513 self.assertDictEqual(expected_compatibility, migration_compatibility)
6514 mock_exception_log.assert_called_once()
6515 data_motion.get_backend_configuration.assert_called_once_with(
6516 'destination_backend')
6517 self.assertFalse(mock_vserver_compatibility_check.called)
6518 self.assertFalse(self.library._get_vserver.called)
6520 @ddt.data(
6521 utils.annotated(
6522 'dest_share_server_not_expected',
6523 (('src_vserver', None), exception.InvalidParameterValue(
6524 err='fake_err'))),
6525 utils.annotated(
6526 'src_share_server_not_expected',
6527 (exception.InvalidParameterValue(err='fake_err'),
6528 ('dest_vserver', None))))
6529 def test_migration_check_compatibility_errors(self, side_effects):
6530 self.library._have_cluster_creds = True
6531 mock_dm = mock.Mock()
6532 self.mock_object(data_motion, 'DataMotionSession',
6533 mock.Mock(return_value=mock_dm))
6534 self.mock_object(self.library, 'is_flexgroup_destination_host',
6535 mock.Mock(return_value=False))
6536 self.mock_object(self.library, '_is_flexgroup_pool',
6537 mock.Mock(return_value=False))
6538 self.mock_object(share_types, 'get_extra_specs_from_share')
6539 self.mock_object(self.library, '_check_extra_specs_validity')
6540 self.mock_object(self.library, '_check_aggregate_extra_specs_validity')
6541 self.mock_object(self.library, '_get_backend_share_name',
6542 mock.Mock(return_value=fake.SHARE_NAME))
6543 self.mock_object(self.library, '_get_provisioning_options',
6544 mock.Mock(return_value={}))
6545 self.mock_object(self.library, '_get_normalized_qos_specs')
6546 self.mock_object(self.library,
6547 'validate_provisioning_options_for_share')
6548 self.mock_object(data_motion, 'get_backend_configuration')
6549 self.mock_object(self.library, '_get_vserver',
6550 mock.Mock(side_effect=side_effects))
6551 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6552 self.mock_object(share_utils, 'extract_host', mock.Mock(
6553 return_value='destination_backend'))
6554 mock_compatibility_check = self.mock_object(
6555 self.client, 'check_volume_move')
6557 migration_compatibility = self.library.migration_check_compatibility(
6558 self.context, fake_share.fake_share_instance(),
6559 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6560 destination_share_server=None)
6562 expected_compatibility = {
6563 'compatible': False,
6564 'writable': False,
6565 'nondisruptive': False,
6566 'preserve_metadata': False,
6567 'preserve_snapshots': False,
6568 }
6569 self.assertDictEqual(expected_compatibility, migration_compatibility)
6570 mock_exception_log.assert_called_once()
6571 data_motion.get_backend_configuration.assert_called_once_with(
6572 'destination_backend')
6573 self.assertFalse(mock_compatibility_check.called)
6575 def test_migration_check_compatibility_incompatible_vservers(self):
6576 self.library._have_cluster_creds = True
6577 mock_dm = mock.Mock()
6578 self.mock_object(data_motion, 'DataMotionSession',
6579 mock.Mock(return_value=mock_dm))
6580 self.mock_object(self.library, 'is_flexgroup_destination_host',
6581 mock.Mock(return_value=False))
6582 self.mock_object(self.library, '_is_flexgroup_pool',
6583 mock.Mock(return_value=False))
6584 self.mock_object(share_types, 'get_extra_specs_from_share')
6585 self.mock_object(self.library, '_check_extra_specs_validity')
6586 self.mock_object(self.library, '_check_aggregate_extra_specs_validity')
6587 self.mock_object(self.library, '_get_backend_share_name',
6588 mock.Mock(return_value=fake.SHARE_NAME))
6589 self.mock_object(data_motion, 'get_backend_configuration')
6590 self.mock_object(self.library, '_get_provisioning_options',
6591 mock.Mock(return_value={}))
6592 self.mock_object(self.library, '_get_normalized_qos_specs')
6593 self.mock_object(self.library,
6594 'validate_provisioning_options_for_share')
6595 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6596 get_vserver_returns = [
6597 (fake.VSERVER1, mock.Mock()),
6598 (fake.VSERVER2, mock.Mock()),
6599 ]
6600 self.mock_object(self.library, '_get_vserver',
6601 mock.Mock(side_effect=get_vserver_returns))
6602 self.mock_object(share_utils, 'extract_host', mock.Mock(
6603 side_effect=[
6604 'destination_backend', 'destination_pool', 'source_pool']))
6605 mock_move_check = self.mock_object(self.client, 'check_volume_move')
6607 migration_compatibility = self.library.migration_check_compatibility(
6608 self.context, fake_share.fake_share_instance(),
6609 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6610 destination_share_server='dst_srv')
6612 expected_compatibility = {
6613 'compatible': False,
6614 'writable': False,
6615 'nondisruptive': False,
6616 'preserve_metadata': False,
6617 'preserve_snapshots': False,
6618 }
6619 self.assertDictEqual(expected_compatibility, migration_compatibility)
6620 mock_exception_log.assert_called_once()
6621 data_motion.get_backend_configuration.assert_called_once_with(
6622 'destination_backend')
6623 self.assertFalse(mock_move_check.called)
6624 self.library._get_vserver.assert_has_calls(
6625 [mock.call(share_server=fake.SHARE_SERVER),
6626 mock.call(share_server='dst_srv')])
6628 def test_migration_check_compatibility_client_error(self):
6629 self.library._have_cluster_creds = True
6630 mock_dm = mock.Mock()
6631 self.mock_object(data_motion, 'DataMotionSession',
6632 mock.Mock(return_value=mock_dm))
6633 self.mock_object(self.library, 'is_flexgroup_destination_host',
6634 mock.Mock(return_value=False))
6635 self.mock_object(self.library, '_is_flexgroup_pool',
6636 mock.Mock(return_value=False))
6637 self.mock_object(share_types, 'get_extra_specs_from_share')
6638 self.mock_object(self.library, '_check_extra_specs_validity')
6639 self.mock_object(self.library, '_check_aggregate_extra_specs_validity')
6640 self.mock_object(self.library, '_get_provisioning_options',
6641 mock.Mock(return_value={}))
6642 self.mock_object(self.library, '_get_normalized_qos_specs')
6643 self.mock_object(self.library,
6644 'validate_provisioning_options_for_share')
6645 self.mock_object(self.library, '_get_backend_share_name',
6646 mock.Mock(return_value=fake.SHARE_NAME))
6647 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6648 self.mock_object(data_motion, 'get_backend_configuration')
6649 self.mock_object(self.library, '_get_vserver',
6650 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6651 self.mock_object(share_utils, 'extract_host', mock.Mock(
6652 side_effect=[
6653 'destination_backend', 'destination_pool', 'source_pool']))
6654 mock_move_check = self.mock_object(
6655 self.client, 'check_volume_move',
6656 mock.Mock(side_effect=netapp_api.NaApiError))
6657 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6658 mock.Mock(return_value=False))
6660 migration_compatibility = self.library.migration_check_compatibility(
6661 self.context, fake_share.fake_share_instance(),
6662 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6663 destination_share_server='dst_srv')
6665 expected_compatibility = {
6666 'compatible': False,
6667 'writable': False,
6668 'nondisruptive': False,
6669 'preserve_metadata': False,
6670 'preserve_snapshots': False,
6671 }
6672 self.assertDictEqual(expected_compatibility, migration_compatibility)
6673 mock_exception_log.assert_called_once()
6674 data_motion.get_backend_configuration.assert_called_once_with(
6675 'destination_backend')
6676 mock_move_check.assert_called_once_with(
6677 fake.SHARE_NAME, fake.VSERVER1, 'destination_pool',
6678 encrypt_destination=False)
6679 self.library._get_vserver.assert_has_calls(
6680 [mock.call(share_server=fake.SHARE_SERVER),
6681 mock.call(share_server='dst_srv')])
6683 @ddt.data(False, True)
6684 def test_migration_check_compatibility(self, fpolicy):
6685 self.library._have_cluster_creds = True
6686 mock_dm = mock.Mock()
6687 self.mock_object(data_motion, 'DataMotionSession',
6688 mock.Mock(return_value=mock_dm))
6689 self.mock_object(self.library, 'is_flexgroup_destination_host',
6690 mock.Mock(return_value=False))
6691 self.mock_object(self.library, '_is_flexgroup_pool',
6692 mock.Mock(return_value=False))
6693 mock_dest_client = mock.Mock()
6694 if fpolicy:
6695 provisioning_options = copy.deepcopy(
6696 fake.PROVISIONING_OPTIONS_WITH_FPOLICY)
6697 get_vserver_side_effect = [(mock.Mock(), mock_dest_client),
6698 (fake.VSERVER1, mock.Mock())]
6699 else:
6700 get_vserver_side_effect = [(fake.VSERVER1, mock.Mock())]
6701 provisioning_options = {}
6702 self.mock_object(share_types, 'get_extra_specs_from_share')
6703 self.mock_object(self.library, '_check_extra_specs_validity')
6704 self.mock_object(self.library, '_check_aggregate_extra_specs_validity')
6705 self.mock_object(self.library, '_get_backend_share_name',
6706 mock.Mock(return_value=fake.SHARE_NAME))
6707 self.mock_object(data_motion, 'get_backend_configuration')
6708 self.mock_object(self.library, '_get_vserver',
6709 mock.Mock(side_effect=get_vserver_side_effect))
6710 self.mock_object(share_utils, 'extract_host', mock.Mock(
6711 side_effect=[
6712 'destination_backend', 'destination_pool', 'source_pool']))
6713 mock_move_check = self.mock_object(self.client, 'check_volume_move')
6714 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6715 mock.Mock(return_value=False))
6716 self.mock_object(self.library, '_get_provisioning_options',
6717 mock.Mock(return_value=provisioning_options))
6718 self.mock_object(self.library, '_get_normalized_qos_specs')
6719 self.mock_object(self.library,
6720 'validate_provisioning_options_for_share')
6721 self.mock_object(self.library,
6722 '_check_destination_vserver_for_vol_move')
6723 fpolicies = [
6724 x for x in range(1, self.library.FPOLICY_MAX_VSERVER_POLICIES + 1)]
6725 mock_fpolicy_status = self.mock_object(
6726 mock_dest_client, 'get_fpolicy_policies_status',
6727 mock.Mock(return_value=fpolicies))
6728 mock_reusable_fpolicy = self.mock_object(
6729 self.library, '_find_reusable_fpolicy_scope',
6730 mock.Mock(return_value={'fake'}))
6732 src_instance = fake_share.fake_share_instance()
6733 dst_instance = fake_share.fake_share_instance()
6734 migration_compatibility = self.library.migration_check_compatibility(
6735 self.context, src_instance, dst_instance,
6736 share_server=fake.SHARE_SERVER, destination_share_server='dst_srv')
6738 expected_compatibility = {
6739 'compatible': True,
6740 'writable': True,
6741 'nondisruptive': True,
6742 'preserve_metadata': True,
6743 'preserve_snapshots': True,
6744 }
6745 self.assertDictEqual(expected_compatibility, migration_compatibility)
6746 data_motion.get_backend_configuration.assert_called_once_with(
6747 'destination_backend')
6748 mock_move_check.assert_called_once_with(
6749 fake.SHARE_NAME, fake.VSERVER1, 'destination_pool',
6750 encrypt_destination=False)
6751 if fpolicy:
6752 self.library._get_vserver.assert_has_calls(
6753 [mock.call(share_server='dst_srv'),
6754 mock.call(share_server=fake.SHARE_SERVER)])
6755 mock_fpolicy_status.assert_called_once()
6756 mock_reusable_fpolicy.assert_called_once_with(
6757 dst_instance, mock_dest_client,
6758 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
6759 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
6760 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS
6761 )
6762 else:
6763 self.library._get_vserver.assert_called_once_with(
6764 share_server=fake.SHARE_SERVER)
6766 def test_migration_check_compatibility_destination_type_is_encrypted(self):
6767 self.library._have_cluster_creds = True
6768 mock_dm = mock.Mock()
6769 self.mock_object(data_motion, 'DataMotionSession',
6770 mock.Mock(return_value=mock_dm))
6771 self.mock_object(self.library, 'is_flexgroup_destination_host',
6772 mock.Mock(return_value=False))
6773 self.mock_object(self.library, '_is_flexgroup_pool',
6774 mock.Mock(return_value=False))
6775 self.mock_object(self.library, '_get_backend_share_name',
6776 mock.Mock(return_value=fake.SHARE_NAME))
6777 self.mock_object(data_motion, 'get_backend_configuration')
6778 self.mock_object(self.library, '_get_vserver',
6779 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6780 self.mock_object(share_utils, 'extract_host', mock.Mock(
6781 side_effect=[
6782 'destination_backend', 'destination_pool', 'source_pool']))
6783 mock_move_check = self.mock_object(self.client, 'check_volume_move')
6784 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6785 mock.Mock(return_value=True))
6786 self.mock_object(share_types, 'get_extra_specs_from_share',
6787 mock.Mock(return_value={'spec1': 'spec-data'}))
6788 self.mock_object(self.library,
6789 '_check_extra_specs_validity')
6790 self.mock_object(self.library,
6791 '_check_aggregate_extra_specs_validity')
6792 self.mock_object(self.library, '_get_provisioning_options',
6793 mock.Mock(return_value={}))
6794 self.mock_object(self.library, '_get_normalized_qos_specs')
6795 self.mock_object(self.library,
6796 'validate_provisioning_options_for_share')
6798 migration_compatibility = self.library.migration_check_compatibility(
6799 self.context, fake_share.fake_share_instance(),
6800 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6801 destination_share_server='dst_srv')
6803 expected_compatibility = {
6804 'compatible': True,
6805 'writable': True,
6806 'nondisruptive': True,
6807 'preserve_metadata': True,
6808 'preserve_snapshots': True,
6809 }
6810 self.assertDictEqual(expected_compatibility, migration_compatibility)
6811 data_motion.get_backend_configuration.assert_called_once_with(
6812 'destination_backend')
6814 mock_move_check.assert_called_once_with(
6815 fake.SHARE_NAME, fake.VSERVER1, 'destination_pool',
6816 encrypt_destination=True)
6817 self.library._get_vserver.assert_has_calls(
6818 [mock.call(share_server=fake.SHARE_SERVER),
6819 mock.call(share_server='dst_srv')])
6821 def test_migration_check_compatibility_snaplock_not_compatible(self):
6822 self.library._have_cluster_creds = True
6823 self.mock_object(self.library, '_get_backend_share_name',
6824 mock.Mock(return_value=fake.SHARE_NAME))
6825 self.mock_object(data_motion, 'get_backend_configuration')
6826 self.mock_object(self.library, '_get_vserver',
6827 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6828 self.mock_object(share_utils, 'extract_host', mock.Mock(
6829 side_effect=[
6830 'destination_backend', 'destination_pool', 'source_pool']))
6831 mock_dm = mock.Mock()
6832 self.mock_object(data_motion, 'DataMotionSession',
6833 mock.Mock(return_value=mock_dm))
6834 self.mock_object(self.library, 'is_flexgroup_destination_host',
6835 mock.Mock(return_value=False))
6836 self.mock_object(self.library, '_is_flexgroup_pool',
6837 mock.Mock(return_value=False))
6838 self.mock_object(self.library,
6839 '_is_snaplock_compatible_for_migration',
6840 mock.Mock(return_value=False)
6841 )
6842 migration_compatibility = self.library.migration_check_compatibility(
6843 self.context, fake_share.fake_share_instance(),
6844 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6845 destination_share_server='dst_srv')
6847 expected_compatibility = {
6848 'compatible': False,
6849 'writable': False,
6850 'nondisruptive': False,
6851 'preserve_metadata': False,
6852 'preserve_snapshots': False,
6853 }
6854 self.assertDictEqual(expected_compatibility, migration_compatibility)
6856 def test_migration_start(self):
6857 mock_info_log = self.mock_object(lib_base.LOG, 'info')
6858 source_snapshots = mock.Mock()
6859 snapshot_mappings = mock.Mock()
6860 self.mock_object(self.library, '_get_vserver',
6861 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6862 self.mock_object(self.library, '_get_backend_share_name',
6863 mock.Mock(return_value=fake.SHARE_NAME))
6864 self.mock_object(share_utils, 'extract_host',
6865 mock.Mock(return_value='destination_pool'))
6866 mock_move = self.mock_object(self.client, 'start_volume_move')
6867 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6868 mock.Mock(return_value=False))
6870 retval = self.library.migration_start(
6871 self.context, fake_share.fake_share_instance(),
6872 fake_share.fake_share_instance(),
6873 source_snapshots, snapshot_mappings,
6874 share_server=fake.SHARE_SERVER, destination_share_server='dst_srv')
6876 self.assertIsNone(retval)
6877 self.assertTrue(mock_info_log.called)
6878 mock_move.assert_called_once_with(
6879 fake.SHARE_NAME, fake.VSERVER1, 'destination_pool',
6880 cutover_action='wait', encrypt_destination=False)
6882 def test_migration_start_encrypted_destination(self):
6883 mock_info_log = self.mock_object(lib_base.LOG, 'info')
6884 source_snapshots = mock.Mock()
6885 snapshot_mappings = mock.Mock()
6886 self.mock_object(self.library, '_get_vserver',
6887 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6888 self.mock_object(self.library, '_get_backend_share_name',
6889 mock.Mock(return_value=fake.SHARE_NAME))
6890 self.mock_object(share_utils, 'extract_host',
6891 mock.Mock(return_value='destination_pool'))
6892 mock_move = self.mock_object(self.client, 'start_volume_move')
6893 self.mock_object(self.library, '_get_dest_flexvol_encryption_value',
6894 mock.Mock(return_value=True))
6896 retval = self.library.migration_start(
6897 self.context, fake_share.fake_share_instance(),
6898 fake_share.fake_share_instance(),
6899 source_snapshots, snapshot_mappings,
6900 share_server=fake.SHARE_SERVER, destination_share_server='dst_srv')
6902 self.assertIsNone(retval)
6903 self.assertTrue(mock_info_log.called)
6904 mock_move.assert_called_once_with(
6905 fake.SHARE_NAME, fake.VSERVER1, 'destination_pool',
6906 cutover_action='wait', encrypt_destination=True)
6908 def test_migration_continue_volume_move_failed(self):
6909 source_snapshots = mock.Mock()
6910 snapshot_mappings = mock.Mock()
6911 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
6912 self.mock_object(self.library, '_get_vserver',
6913 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6914 self.mock_object(self.library, '_get_backend_share_name',
6915 mock.Mock(return_value=fake.SHARE_NAME))
6916 mock_status_check = self.mock_object(
6917 self.client, 'get_volume_move_status',
6918 mock.Mock(return_value={'phase': 'failed', 'details': 'unknown'}))
6920 self.assertRaises(exception.NetAppException,
6921 self.library.migration_continue,
6922 self.context, fake_share.fake_share_instance(),
6923 fake_share.fake_share_instance(),
6924 source_snapshots, snapshot_mappings,
6925 share_server=None, destination_share_server=None)
6927 mock_status_check.assert_called_once_with(
6928 fake.SHARE_NAME, fake.VSERVER1)
6929 mock_exception_log.assert_called_once()
6931 @ddt.data({'phase': 'Queued', 'completed': False},
6932 {'phase': 'Finishing', 'completed': False},
6933 {'phase': 'cutover_hard_deferred', 'completed': True},
6934 {'phase': 'cutover_soft_deferred', 'completed': True},
6935 {'phase': 'completed', 'completed': True})
6936 @ddt.unpack
6937 def test_migration_continue(self, phase, completed):
6938 source_snapshots = mock.Mock()
6939 snapshot_mappings = mock.Mock()
6940 self.mock_object(self.library, '_get_vserver',
6941 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6942 self.mock_object(self.library, '_get_backend_share_name',
6943 mock.Mock(return_value=fake.SHARE_NAME))
6944 self.mock_object(self.client, 'get_volume_move_status',
6945 mock.Mock(return_value={'phase': phase}))
6947 migration_completed = self.library.migration_continue(
6948 self.context, fake_share.fake_share_instance(),
6949 fake_share.fake_share_instance(), source_snapshots,
6950 snapshot_mappings, share_server=fake.SHARE_SERVER,
6951 destination_share_server='dst_srv')
6953 self.assertEqual(completed, migration_completed)
6955 @ddt.data('cutover_hard_deferred', 'cutover_soft_deferred',
6956 'Queued', 'Replicating')
6957 def test_migration_get_progress_at_phase(self, phase):
6958 source_snapshots = mock.Mock()
6959 snapshot_mappings = mock.Mock()
6960 mock_info_log = self.mock_object(lib_base.LOG, 'info')
6961 status = {
6962 'state': 'healthy',
6963 'details': '%s:: Volume move job in progress' % phase,
6964 'phase': phase,
6965 'estimated-completion-time': '1481919246',
6966 'percent-complete': 80,
6967 }
6968 self.mock_object(self.library, '_get_vserver',
6969 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
6970 self.mock_object(self.library, '_get_backend_share_name',
6971 mock.Mock(return_value=fake.SHARE_NAME))
6972 self.mock_object(self.client, 'get_volume_move_status',
6973 mock.Mock(return_value=status))
6975 migration_progress = self.library.migration_get_progress(
6976 self.context, fake_share.fake_share_instance(),
6977 source_snapshots, snapshot_mappings,
6978 fake_share.fake_share_instance(), share_server=fake.SHARE_SERVER,
6979 destination_share_server='dst_srv')
6981 expected_progress = {
6982 'total_progress': 100 if phase.startswith('cutover') else 80,
6983 'state': 'healthy',
6984 'estimated_completion_time': '1481919246',
6985 'details': '%s:: Volume move job in progress' % phase,
6986 'phase': phase,
6987 }
6988 self.assertDictEqual(expected_progress, migration_progress)
6989 mock_info_log.assert_called_once()
6991 @ddt.data({'state': 'failed'},
6992 {'state': 'healthy'})
6993 @ddt.unpack
6994 def test_migration_cancel(self, state):
6995 source_snapshots = mock.Mock()
6996 snapshot_mappings = mock.Mock()
6997 self.library.configuration.netapp_migration_cancel_timeout = 15
6998 mock_info_log = self.mock_object(lib_base.LOG, 'info')
7000 self.mock_object(self.library, '_get_vserver',
7001 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
7002 self.mock_object(self.library, '_get_backend_share_name',
7003 mock.Mock(return_value=fake.SHARE_NAME))
7004 self.mock_object(self.client, 'abort_volume_move')
7005 self.mock_object(self.client, 'get_volume_move_status',
7006 mock.Mock(return_value={'state': state}))
7008 if state == 'failed':
7009 retval = self.library.migration_cancel(
7010 self.context, fake_share.fake_share_instance(),
7011 fake_share.fake_share_instance(), source_snapshots,
7012 snapshot_mappings, share_server=fake.SHARE_SERVER,
7013 destination_share_server='dst_srv')
7015 self.assertIsNone(retval)
7016 mock_info_log.assert_called_once()
7017 else:
7018 self.assertRaises(
7019 (exception.NetAppException),
7020 self.library.migration_cancel, self.context,
7021 fake_share.fake_share_instance(),
7022 fake_share.fake_share_instance, source_snapshots,
7023 snapshot_mappings, share_server=fake.SHARE_SERVER,
7024 destination_share_server='dst_srv')
7026 @ddt.data({'already_canceled': True, 'effect': exception.NetAppException},
7027 {'already_canceled': False, 'effect':
7028 (None, exception.NetAppException)})
7029 @ddt.unpack
7030 def test_migration_cancel_exception_volume_status(self, already_canceled,
7031 effect):
7032 source_snapshots = mock.Mock()
7033 snapshot_mappings = mock.Mock()
7034 self.library.configuration.netapp_migration_cancel_timeout = 1
7035 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
7036 mock_info_log = self.mock_object(lib_base.LOG, 'info')
7037 self.mock_object(self.library, '_get_vserver',
7038 mock.Mock(return_value=(fake.VSERVER1, mock.Mock())))
7039 self.mock_object(self.library, '_get_backend_share_name',
7040 mock.Mock(return_value=fake.SHARE_NAME))
7041 self.mock_object(self.client, 'abort_volume_move')
7042 self.mock_object(self.client, 'get_volume_move_status',
7043 mock.Mock(side_effect=effect))
7044 self.library.migration_cancel(
7045 self.context, fake_share.fake_share_instance(),
7046 fake_share.fake_share_instance(), source_snapshots,
7047 snapshot_mappings, share_server=fake.SHARE_SERVER,
7048 destination_share_server='dst_srv')
7050 mock_exception_log.assert_called_once()
7051 if not already_canceled:
7052 mock_info_log.assert_called_once()
7054 self.assertEqual(not already_canceled,
7055 self.client.abort_volume_move.called)
7057 def test_migration_complete_invalid_phase(self):
7058 source_snapshots = mock.Mock()
7059 snapshot_mappings = mock.Mock()
7060 status = {
7061 'state': 'healthy',
7062 'phase': 'Replicating',
7063 'details': 'Replicating:: Volume move operation is in progress.',
7064 }
7065 mock_exception_log = self.mock_object(lib_base.LOG, 'exception')
7066 vserver_client = mock.Mock()
7067 self.mock_object(
7068 self.library, '_get_vserver',
7069 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
7070 self.mock_object(
7071 self.library, '_get_backend_share_name',
7072 mock.Mock(side_effect=[fake.SHARE_NAME, 'new_share_name']))
7073 self.mock_object(self.library, '_get_volume_move_status',
7074 mock.Mock(return_value=status))
7075 self.mock_object(self.library, '_create_export')
7077 self.assertRaises(
7078 exception.NetAppException, self.library.migration_complete,
7079 self.context, fake_share.fake_share_instance(),
7080 fake_share.fake_share_instance, source_snapshots,
7081 snapshot_mappings, share_server=fake.SHARE_SERVER,
7082 destination_share_server='dst_srv')
7083 self.assertFalse(vserver_client.set_volume_name.called)
7084 self.assertFalse(self.library._create_export.called)
7085 mock_exception_log.assert_called_once()
7087 def test_migration_complete_timeout(self):
7088 source_snapshots = mock.Mock()
7089 snapshot_mappings = mock.Mock()
7090 self.library.configuration.netapp_volume_move_cutover_timeout = 15
7091 vol_move_side_effects = [
7092 {'phase': 'cutover_hard_deferred'},
7093 {'phase': 'Cutover'},
7094 {'phase': 'Finishing'},
7095 {'phase': 'Finishing'},
7096 ]
7097 self.mock_object(time, 'sleep')
7098 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
7099 vserver_client = mock.Mock()
7100 self.mock_object(
7101 self.library, '_get_vserver',
7102 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
7103 self.mock_object(
7104 self.library, '_get_backend_share_name',
7105 mock.Mock(side_effect=[fake.SHARE_NAME, 'new_share_name']))
7106 self.mock_object(self.library, '_get_volume_move_status', mock.Mock(
7107 side_effect=vol_move_side_effects))
7108 self.mock_object(self.library, '_create_export')
7109 src_share = fake_share.fake_share_instance(id='source-share-instance')
7110 dest_share = fake_share.fake_share_instance(id='dest-share-instance')
7112 self.assertRaises(
7113 exception.NetAppException, self.library.migration_complete,
7114 self.context, src_share, dest_share, source_snapshots,
7115 snapshot_mappings, share_server=fake.SHARE_SERVER,
7116 destination_share_server='dst_srv')
7117 self.assertFalse(vserver_client.set_volume_name.called)
7118 self.assertFalse(self.library._create_export.called)
7119 self.assertEqual(3, mock_warning_log.call_count)
7121 @ddt.data({'phase': 'cutover_hard_deferred',
7122 'provisioning_options': fake.PROVISIONING_OPTIONS_WITH_QOS,
7123 'policy_group_name': fake.QOS_POLICY_GROUP_NAME},
7124 {'phase': 'cutover_soft_deferred',
7125 'provisioning_options': fake.PROVISIONING_OPTIONS_WITH_QOS,
7126 'policy_group_name': fake.QOS_POLICY_GROUP_NAME},
7127 {'phase': 'completed',
7128 'provisioning_options': fake.PROVISIONING_OPTIONS,
7129 'policy_group_name': False},
7130 {'phase': 'completed',
7131 'provisioning_options': fake.PROVISIONING_OPTIONS_WITH_FPOLICY,
7132 'policy_group_name': False})
7133 @ddt.unpack
7134 def test_migration_complete(self, phase, provisioning_options,
7135 policy_group_name):
7136 snap = fake_share.fake_snapshot_instance(
7137 id='src-snapshot', provider_location='test-src-provider-location')
7138 dest_snap = fake_share.fake_snapshot_instance(id='dest-snapshot',
7139 as_primitive=True)
7140 extra_specs = copy.deepcopy(fake.EXTRA_SPEC)
7141 source_snapshots = [snap]
7142 snapshot_mappings = {snap['id']: dest_snap}
7143 self.library.configuration.netapp_volume_move_cutover_timeout = 15
7144 vol_move_side_effects = [
7145 {'phase': phase},
7146 {'phase': 'Cutover'},
7147 {'phase': 'Finishing'},
7148 {'phase': 'completed'},
7149 ]
7150 self.mock_object(time, 'sleep')
7151 mock_debug_log = self.mock_object(lib_base.LOG, 'debug')
7152 mock_info_log = self.mock_object(lib_base.LOG, 'info')
7153 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
7154 vserver_client = mock.Mock()
7155 self.mock_object(
7156 self.library, '_get_vserver',
7157 mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
7158 self.mock_object(
7159 self.library, '_get_backend_share_name',
7160 mock.Mock(side_effect=[fake.SHARE_NAME, 'new_share_name']))
7161 self.mock_object(self.library, '_create_export', mock.Mock(
7162 return_value=fake.NFS_EXPORTS))
7163 mock_move_status_check = self.mock_object(
7164 self.library, '_get_volume_move_status',
7165 mock.Mock(side_effect=vol_move_side_effects))
7166 self.mock_object(share_types, 'get_extra_specs_from_share',
7167 mock.Mock(return_value=extra_specs))
7168 self.mock_object(self.library, '_check_fpolicy_file_operations')
7169 self.mock_object(
7170 self.library, '_get_provisioning_options',
7171 mock.Mock(return_value=provisioning_options))
7172 self.mock_object(
7173 self.library, '_modify_or_create_qos_for_existing_share',
7174 mock.Mock(return_value=policy_group_name))
7175 mock_get_volume_snapshot_attributes = self.mock_object(
7176 vserver_client, 'get_volume_snapshot_attributes',
7177 mock.Mock(return_value={'snapshot-policy': 'fake_policy'}))
7178 self.mock_object(vserver_client, 'modify_volume')
7179 mock_create_new_fpolicy = self.mock_object(
7180 self.library, '_create_fpolicy_for_share')
7182 mock_delete_policy = self.mock_object(self.library,
7183 '_delete_fpolicy_for_share')
7185 src_share = fake_share.fake_share_instance(id='source-share-instance')
7186 dest_share = fake_share.fake_share_instance(id='dest-share-instance')
7187 dest_aggr = share_utils.extract_host(dest_share['host'], level='pool')
7189 data_updates = self.library.migration_complete(
7190 self.context, src_share, dest_share, source_snapshots,
7191 snapshot_mappings, share_server=fake.SHARE_SERVER,
7192 destination_share_server='dst_srv')
7194 self.assertEqual(fake.NFS_EXPORTS, data_updates['export_locations'])
7195 expected_dest_snap_updates = {
7196 'provider_location': snap['provider_location'],
7197 }
7198 self.assertIn(dest_snap['id'], data_updates['snapshot_updates'])
7199 self.assertEqual(expected_dest_snap_updates,
7200 data_updates['snapshot_updates'][dest_snap['id']])
7201 vserver_client.set_volume_name.assert_called_once_with(
7202 fake.SHARE_NAME, 'new_share_name')
7203 self.library._create_export.assert_called_once_with(
7204 dest_share, fake.SHARE_SERVER, fake.VSERVER1, vserver_client,
7205 clear_current_export_policy=False)
7206 mock_get_volume_snapshot_attributes.assert_called_once_with(
7207 'new_share_name')
7208 vserver_client.modify_volume.assert_called_once_with(
7209 dest_aggr, 'new_share_name', **provisioning_options)
7210 mock_info_log.assert_called_once()
7211 mock_delete_policy.assert_called_once_with(src_share, fake.VSERVER1,
7212 vserver_client)
7213 if phase != 'completed':
7214 self.assertEqual(2, mock_warning_log.call_count)
7215 self.assertFalse(mock_debug_log.called)
7216 self.assertEqual(4, mock_move_status_check.call_count)
7217 else:
7218 self.assertFalse(mock_warning_log.called)
7219 mock_debug_log.assert_called_once()
7220 mock_move_status_check.assert_called_once()
7221 if provisioning_options.get(
7222 'fpolicy_extensions_to_include') is not None:
7223 mock_create_new_fpolicy.assert_called_once_with(
7224 dest_share, fake.VSERVER1, vserver_client,
7225 **provisioning_options)
7226 else:
7227 mock_create_new_fpolicy.assert_not_called()
7229 def test_modify_or_create_qos_for_existing_share_no_qos_extra_specs(self):
7230 vserver_client = mock.Mock()
7231 self.mock_object(self.library, '_get_backend_qos_policy_group_name')
7232 self.mock_object(vserver_client, 'get_volume')
7233 self.mock_object(self.library, '_create_qos_policy_group')
7235 retval = self.library._modify_or_create_qos_for_existing_share(
7236 fake.SHARE, fake.EXTRA_SPEC, fake.VSERVER1, vserver_client)
7238 self.assertIsNone(retval)
7239 self.library._get_backend_qos_policy_group_name.assert_not_called()
7240 vserver_client.get_volume.assert_not_called()
7241 self.library._create_qos_policy_group.assert_not_called()
7243 def test_modify_or_create_qos_for_existing_share_no_existing_qos(self):
7244 vserver_client = mock.Mock()
7245 self.mock_object(self.library, '_get_backend_qos_policy_group_name')
7246 self.mock_object(vserver_client, 'get_volume',
7247 mock.Mock(return_value=fake.FLEXVOL_WITHOUT_QOS))
7248 self.mock_object(self.library, '_create_qos_policy_group')
7249 self.mock_object(self.library._client, 'qos_policy_group_modify')
7250 qos_policy_name = self.library._get_backend_qos_policy_group_name(
7251 fake.SHARE['id'])
7253 retval = self.library._modify_or_create_qos_for_existing_share(
7254 fake.SHARE, fake.EXTRA_SPEC_WITH_QOS, fake.VSERVER1,
7255 vserver_client)
7257 share_obj = {
7258 'size': 2,
7259 'id': fake.SHARE['id'],
7260 }
7261 self.assertEqual(qos_policy_name, retval)
7262 self.library._client.qos_policy_group_modify.assert_not_called()
7263 self.library._create_qos_policy_group.assert_called_once_with(
7264 share_obj, fake.VSERVER1, {'maxiops': '3000', 'miniops': '20'},
7265 vserver_client=vserver_client)
7267 @ddt.data(utils.annotated('volume_has_shared_qos_policy',
7268 (2, False, False)),
7269 utils.annotated('volume_has_shared_qos_policy',
7270 (2, False, True)),
7271 utils.annotated('volume_has_shared_qos_policy',
7272 (2, True, False)),
7273 utils.annotated('volume_has_shared_qos_policy_iops_change',
7274 (2, False, False)),
7275 utils.annotated('volume_has_shared_qos_policy_iops_change',
7276 (2, True, False)),
7277 utils.annotated('volume_has_shared_qos_policy_iops_change',
7278 (2, False, True)),
7279 utils.annotated('volume_has_nonshared_qos_policy',
7280 (1, False, False)),
7281 utils.annotated('volume_has_nonshared_qos_policy',
7282 (1, False, True)),
7283 utils.annotated('volume_has_nonshared_qos_policy',
7284 (1, True, False)),
7285 utils.annotated('volume_has_nonshared_qos_policy_iops_change',
7286 (1, False, False)),
7287 utils.annotated('volume_has_nonshared_qos_policy_iops_change',
7288 (1, False, True)),
7289 utils.annotated('volume_has_nonshared_qos_policy_iops_change',
7290 (1, True, False)))
7291 @ddt.unpack
7292 def test_modify_or_create_qos_for_existing_share(self, num_workloads,
7293 qos_max_iops_change,
7294 qos_min_iops_change):
7295 vserver_client = mock.Mock()
7296 qos_policy = copy.deepcopy(fake.QOS_POLICY_GROUP)
7297 qos_policy['num-workloads'] = num_workloads
7298 extra_specs = copy.deepcopy(fake.EXTRA_SPEC_WITH_QOS)
7299 expected_max_iops = '3000'
7300 expected_min_iops = '20'
7301 if qos_max_iops_change:
7302 expected_max_iops = '4000'
7303 extra_specs[fake.QOS_MAX_EXTRA_SPEC] = expected_max_iops
7304 if qos_min_iops_change:
7305 expected_min_iops = '50'
7306 extra_specs[fake.QOS_MIN_EXTRA_SPEC] = expected_min_iops
7308 self.mock_object(vserver_client, 'get_volume',
7309 mock.Mock(return_value=fake.FLEXVOL_WITH_QOS))
7310 self.mock_object(self.library._client, 'qos_policy_group_get',
7311 mock.Mock(return_value=qos_policy))
7312 mock_qos_policy_modify = self.mock_object(
7313 self.library._client, 'qos_policy_group_modify')
7314 mock_qos_policy_rename = self.mock_object(
7315 self.library._client, 'qos_policy_group_rename')
7316 mock_create_qos_policy = self.mock_object(
7317 self.library, '_create_qos_policy_group')
7318 new_qos_policy_name = self.library._get_backend_qos_policy_group_name(
7319 fake.SHARE['id'])
7321 retval = self.library._modify_or_create_qos_for_existing_share(
7322 fake.SHARE, extra_specs, fake.VSERVER1, vserver_client)
7324 self.assertEqual(new_qos_policy_name, retval)
7325 if num_workloads == 1:
7326 mock_create_qos_policy.assert_not_called()
7327 if qos_max_iops_change or qos_min_iops_change:
7328 mock_qos_policy_modify.assert_called_once_with(
7329 fake.QOS_POLICY_GROUP_NAME, expected_max_iops + 'iops',
7330 expected_min_iops + 'iops')
7331 else:
7332 mock_qos_policy_modify.assert_not_called()
7334 mock_qos_policy_rename.assert_called_once_with(
7335 fake.QOS_POLICY_GROUP_NAME, new_qos_policy_name)
7336 else:
7337 share_obj = {
7338 'size': 2,
7339 'id': fake.SHARE['id'],
7340 }
7341 mock_create_qos_policy.assert_called_once_with(
7342 share_obj, fake.VSERVER1,
7343 {'maxiops': expected_max_iops, 'miniops': expected_min_iops},
7344 vserver_client=vserver_client)
7345 self.library._client.qos_policy_group_modify.assert_not_called()
7346 self.library._client.qos_policy_group_rename.assert_not_called()
7348 @ddt.data(('host', True), ('pool', False), (None, False), ('fake', False))
7349 @ddt.unpack
7350 def test__is_group_cg(self, css, is_cg):
7351 share_group = mock.Mock()
7352 share_group.consistent_snapshot_support = css
7353 self.assertEqual(is_cg,
7354 self.library._is_group_cg(self.context, share_group))
7356 def test_create_group_snapshot_cg(self):
7357 share_group = mock.Mock()
7358 share_group.consistent_snapshot_support = 'host'
7359 snap_dict = {'share_group': share_group}
7360 fallback_create = mock.Mock()
7361 mock_create_cgsnapshot = self.mock_object(self.library,
7362 'create_cgsnapshot')
7363 self.library.create_group_snapshot(self.context, snap_dict,
7364 fallback_create,
7365 share_server=fake.SHARE_SERVER)
7366 mock_create_cgsnapshot.assert_called_once_with(
7367 self.context, snap_dict, share_server=fake.SHARE_SERVER)
7368 fallback_create.assert_not_called()
7370 @ddt.data('pool', None, 'fake')
7371 def test_create_group_snapshot_fallback(self, css):
7372 share_group = mock.Mock()
7373 share_group.consistent_snapshot_support = css
7374 snap_dict = {'share_group': share_group}
7375 fallback_create = mock.Mock()
7376 mock_create_cgsnapshot = self.mock_object(self.library,
7377 'create_cgsnapshot')
7378 self.library.create_group_snapshot(self.context, snap_dict,
7379 fallback_create,
7380 share_server=fake.SHARE_SERVER)
7381 mock_create_cgsnapshot.assert_not_called()
7382 fallback_create.assert_called_once_with(self.context,
7383 snap_dict,
7384 share_server=fake.SHARE_SERVER)
7386 def test_delete_group_snapshot_cg(self):
7387 share_group = mock.Mock()
7388 share_group.consistent_snapshot_support = 'host'
7389 snap_dict = {'share_group': share_group}
7390 fallback_delete = mock.Mock()
7391 mock_delete_cgsnapshot = self.mock_object(self.library,
7392 'delete_cgsnapshot')
7393 self.library.delete_group_snapshot(self.context, snap_dict,
7394 fallback_delete,
7395 share_server=fake.SHARE_SERVER)
7396 mock_delete_cgsnapshot.assert_called_once_with(
7397 self.context, snap_dict, share_server=fake.SHARE_SERVER)
7398 fallback_delete.assert_not_called()
7400 @ddt.data('pool', None, 'fake')
7401 def test_delete_group_snapshot_fallback(self, css):
7402 share_group = mock.Mock()
7403 share_group.consistent_snapshot_support = css
7404 snap_dict = {'share_group': share_group}
7405 fallback_delete = mock.Mock()
7406 mock_delete_cgsnapshot = self.mock_object(self.library,
7407 'delete_cgsnapshot')
7408 self.library.delete_group_snapshot(self.context, snap_dict,
7409 fallback_delete,
7410 share_server=fake.SHARE_SERVER)
7411 mock_delete_cgsnapshot.assert_not_called()
7412 fallback_delete.assert_called_once_with(self.context,
7413 snap_dict,
7414 share_server=fake.SHARE_SERVER)
7416 def test_create_group_from_snapshot_cg(self):
7417 share_group = mock.Mock()
7418 share_group.consistent_snapshot_support = 'host'
7419 snap_dict = {'share_group': share_group}
7420 fallback_create = mock.Mock()
7421 mock_create_cg_from_snapshot = self.mock_object(
7422 self.library, 'create_consistency_group_from_cgsnapshot')
7423 self.library.create_group_from_snapshot(self.context, share_group,
7424 snap_dict, fallback_create,
7425 share_server=fake.SHARE_SERVER)
7426 mock_create_cg_from_snapshot.assert_called_once_with(
7427 self.context, share_group, snap_dict,
7428 share_server=fake.SHARE_SERVER)
7429 fallback_create.assert_not_called()
7431 @ddt.data('pool', None, 'fake')
7432 def test_create_group_from_snapshot_fallback(self, css):
7433 share_group = mock.Mock()
7434 share_group.consistent_snapshot_support = css
7435 snap_dict = {'share_group': share_group}
7436 fallback_create = mock.Mock()
7437 mock_create_cg_from_snapshot = self.mock_object(
7438 self.library, 'create_consistency_group_from_cgsnapshot')
7439 self.library.create_group_from_snapshot(self.context, share_group,
7440 snap_dict, fallback_create,
7441 share_server=fake.SHARE_SERVER)
7442 mock_create_cg_from_snapshot.assert_not_called()
7443 fallback_create.assert_called_once_with(self.context, share_group,
7444 snap_dict,
7445 share_server=fake.SHARE_SERVER)
7447 @ddt.data('default', 'hidden', 'visible')
7448 def test_get_backend_info(self, snapdir):
7450 self.library.configuration.netapp_reset_snapdir_visibility = snapdir
7451 expected = {'snapdir_visibility': snapdir}
7453 result = self.library.get_backend_info(self.context)
7454 self.assertEqual(expected, result)
7456 @ddt.data('default', 'hidden')
7457 def test_ensure_shares(self, snapdir_cfg):
7458 shares = [
7459 fake_share.fake_share_instance(id='s-1',
7460 share_server='fake_server_1'),
7461 fake_share.fake_share_instance(id='s-2',
7462 share_server='fake_server_2'),
7463 fake_share.fake_share_instance(id='s-3',
7464 share_server='fake_server_2')
7465 ]
7467 vserver_client = mock.Mock()
7468 self.mock_object(
7469 self.library, '_get_vserver',
7470 mock.Mock(side_effect=[
7471 (fake.VSERVER1, vserver_client),
7472 (fake.VSERVER2, vserver_client),
7473 (fake.VSERVER2, vserver_client)
7474 ]))
7475 (self.library.configuration.
7476 netapp_reset_snapdir_visibility) = snapdir_cfg
7478 self.library.ensure_shares(self.context, shares)
7480 if snapdir_cfg == 'default':
7481 self.library._get_vserver.assert_not_called()
7482 vserver_client.set_volume_snapdir_access.assert_not_called()
7484 else:
7485 self.library._get_vserver.assert_has_calls([
7486 mock.call(share_server='fake_server_1'),
7487 mock.call(share_server='fake_server_2'),
7488 mock.call(share_server='fake_server_2'),
7489 ])
7491 vserver_client.set_volume_snapdir_access.assert_has_calls([
7492 mock.call('share_s_1', True),
7493 mock.call('share_s_2', True),
7494 mock.call('share_s_3', True),
7495 ])
7497 def test__check_volume_clone_split_completed(self):
7498 vserver_client = mock.Mock()
7499 mock_share_name = self.mock_object(
7500 self.library, '_get_backend_share_name',
7501 mock.Mock(return_value=fake.SHARE_NAME))
7502 vserver_client.check_volume_clone_split_completed.return_value = (
7503 fake.CDOT_SNAPSHOT_BUSY_SNAPMIRROR)
7505 self.library._check_volume_clone_split_completed(fake.SHARE,
7506 vserver_client)
7508 mock_share_name.assert_called_once_with(fake.SHARE_ID)
7509 check_call = vserver_client.check_volume_clone_split_completed
7510 check_call.assert_called_once_with(fake.SHARE_NAME)
7512 @ddt.data(constants.STATUS_ACTIVE, constants.STATUS_CREATING_FROM_SNAPSHOT)
7513 def test_get_share_status(self, status):
7514 mock_update_from_snap = self.mock_object(
7515 self.library, '_update_create_from_snapshot_status')
7516 fake.SHARE['status'] = status
7518 self.library.get_share_status(fake.SHARE, fake.SHARE_SERVER)
7520 if status == constants.STATUS_CREATING_FROM_SNAPSHOT:
7521 mock_update_from_snap.assert_called_once_with(fake.SHARE,
7522 fake.SHARE_SERVER)
7523 else:
7524 mock_update_from_snap.assert_not_called()
7526 def test_volume_rehost(self):
7527 mock_share_name = self.mock_object(
7528 self.library, '_get_backend_share_name',
7529 mock.Mock(return_value=fake.SHARE_NAME))
7530 mock_rehost = self.mock_object(self.client, 'rehost_volume')
7532 self.library.volume_rehost(fake.SHARE, fake.VSERVER1, fake.VSERVER2)
7534 mock_share_name.assert_called_once_with(fake.SHARE_ID)
7535 mock_rehost.assert_called_once_with(fake.SHARE_NAME, fake.VSERVER1,
7536 fake.VSERVER2)
7538 def test__rehost_and_mount_volume(self):
7539 mock_share_name = self.mock_object(
7540 self.library, '_get_backend_share_name',
7541 mock.Mock(return_value=fake.SHARE_NAME))
7542 mock_rehost = self.mock_object(self.library, 'volume_rehost',
7543 mock.Mock())
7544 src_vserver_client = mock.Mock()
7545 mock_unmount = self.mock_object(src_vserver_client, 'unmount_volume')
7546 dst_vserver_client = mock.Mock()
7547 mock_mount = self.mock_object(dst_vserver_client, 'mount_volume')
7549 self.library._rehost_and_mount_volume(
7550 fake.SHARE, fake.VSERVER1, src_vserver_client, fake.VSERVER2,
7551 dst_vserver_client)
7553 mock_share_name.assert_called_once_with(fake.SHARE_ID)
7554 mock_unmount.assert_called_once_with(fake.SHARE_NAME)
7555 mock_rehost.assert_called_once_with(fake.SHARE, fake.VSERVER1,
7556 fake.VSERVER2)
7557 mock_mount.assert_called_once_with(fake.SHARE_NAME,
7558 fake.MOUNT_POINT_NAME)
7560 def test__move_volume_after_splitting(self):
7561 src_share = fake_share.fake_share_instance(id='source-share-instance')
7562 dest_share = fake_share.fake_share_instance(id='dest-share-instance')
7563 cutover_action = 'defer'
7564 self.library.configuration.netapp_start_volume_move_timeout = 15
7566 self.mock_object(time, 'sleep')
7567 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
7568 mock_vol_move = self.mock_object(self.library, '_move_volume')
7570 self.library._move_volume_after_splitting(
7571 src_share, dest_share, share_server=fake.SHARE_SERVER,
7572 cutover_action=cutover_action)
7574 mock_vol_move.assert_called_once_with(src_share, dest_share,
7575 fake.SHARE_SERVER,
7576 cutover_action)
7577 self.assertEqual(0, mock_warning_log.call_count)
7579 def test__move_volume_after_splitting_timeout(self):
7580 src_share = fake_share.fake_share_instance(id='source-share-instance')
7581 dest_share = fake_share.fake_share_instance(id='dest-share-instance')
7582 self.library.configuration.netapp_start_volume_move_timeout = 15
7583 cutover_action = 'defer'
7585 self.mock_object(time, 'sleep')
7586 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
7587 undergoing_split_op_msg = (
7588 'The volume is undergoing a clone split operation.')
7589 na_api_error = netapp_api.NaApiError(code=netapp_api.EAPIERROR,
7590 message=undergoing_split_op_msg)
7591 mock_move_vol = self.mock_object(
7592 self.library, '_move_volume', mock.Mock(side_effect=na_api_error))
7594 self.assertRaises(exception.NetAppException,
7595 self.library._move_volume_after_splitting,
7596 src_share, dest_share,
7597 share_server=fake.SHARE_SERVER,
7598 cutover_action=cutover_action)
7600 self.assertEqual(3, mock_move_vol.call_count)
7601 self.assertEqual(3, mock_warning_log.call_count)
7603 def test__move_volume_after_splitting_api_not_found(self):
7604 src_share = fake_share.fake_share_instance(id='source-share-instance')
7605 dest_share = fake_share.fake_share_instance(id='dest-share-instance')
7606 self.library.configuration.netapp_start_volume_move_timeout = 15
7607 cutover_action = 'defer'
7609 self.mock_object(time, 'sleep')
7610 mock_warning_log = self.mock_object(lib_base.LOG, 'warning')
7611 na_api_error = netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND)
7612 mock_move_vol = self.mock_object(
7613 self.library, '_move_volume', mock.Mock(side_effect=na_api_error))
7615 self.assertRaises(exception.NetAppException,
7616 self.library._move_volume_after_splitting,
7617 src_share, dest_share,
7618 share_server=fake.SHARE_SERVER,
7619 cutover_action=cutover_action)
7621 mock_move_vol.assert_called_once_with(src_share, dest_share,
7622 fake.SHARE_SERVER,
7623 cutover_action)
7624 mock_warning_log.assert_not_called()
7626 @ddt.data({'total': 20, 'free': 5, 'reserved': 10, 'thin': False,
7627 'over_sub': 0, 'size': 3, 'compatible': True, 'nb_pools': 1},
7628 {'total': 20, 'free': 5, 'reserved': 10, 'thin': False,
7629 'over_sub': 0, 'size': 4, 'compatible': False, 'nb_pools': 1},
7630 {'total': 20, 'free': 5, 'reserved': 20, 'thin': False,
7631 'over_sub': 1.1, 'size': 3, 'compatible': False, 'nb_pools': 1},
7632 {'total': 20, 'free': 5, 'reserved': 10, 'thin': True,
7633 'over_sub': 2.0, 'size': 6, 'compatible': True, 'nb_pools': 1},
7634 {'total': 20, 'free': 5, 'reserved': 10, 'thin': True,
7635 'over_sub': 1.0, 'size': 4, 'compatible': False, 'nb_pools': 1},
7636 {'total': 'unknown', 'free': 5, 'reserved': 0, 'thin': False,
7637 'over_sub': 3.0, 'size': 1, 'compatible': False, 'nb_pools': 1},
7638 {'total': 20, 'free': 5, 'reserved': 10, 'thin': True,
7639 'over_sub': 1.0, 'size': 6, 'compatible': True, 'nb_pools': 2},
7640 {'total': 20, 'free': 5, 'reserved': 10, 'thin': True,
7641 'over_sub': 1.0, 'size': 7, 'compatible': False, 'nb_pools': 2},
7642 )
7643 @ddt.unpack
7644 def test__check_capacity_compatibility(self, total, free, reserved, thin,
7645 over_sub, size, compatible,
7646 nb_pools):
7647 pools = []
7648 for p in range(nb_pools):
7649 pool = copy.deepcopy(fake.POOLS[0])
7650 pool['total_capacity_gb'] = total
7651 pool['free_capacity_gb'] = free
7652 pool['reserved_percentage'] = reserved
7653 pool['max_over_subscription_ratio'] = over_sub
7654 pools.append(pool)
7656 result = self.library._check_capacity_compatibility(pools, thin, size)
7658 self.assertEqual(compatible, result)
7660 @ddt.data({'provisioning_opts': fake.PROVISIONING_OPTS_WITH_ADAPT_QOS,
7661 'qos_specs': {fake.QOS_NORMALIZED_SPEC: 3000},
7662 'extra_specs': None,
7663 'cluster_credentials': True},
7664 {'provisioning_opts': fake.PROVISIONING_OPTS_WITH_ADAPT_QOS,
7665 'qos_specs': None,
7666 'extra_specs': fake.EXTRA_SPEC_WITH_REPLICATION,
7667 'cluster_credentials': True},
7668 {'provisioning_opts': fake.PROVISIONING_OPTIONS,
7669 'qos_specs': {fake.QOS_NORMALIZED_SPEC: 3000},
7670 'extra_specs': None,
7671 'cluster_credentials': False},
7672 {'provisioning_opts': fake.PROVISIONING_OPTS_WITH_ADAPT_QOS,
7673 'qos_specs': None,
7674 'extra_specs': None,
7675 'cluster_credentials': False},
7676 {'provisioning_opts': fake.PROVISIONING_OPTIONS_INVALID_FPOLICY,
7677 'qos_specs': None,
7678 'extra_specs': None,
7679 'cluster_credentials': False},
7680 {'provisioning_opts': fake.PROVISIONING_OPTIONS_WITH_FPOLICY,
7681 'qos_specs': None,
7682 'extra_specs': {'replication_type': 'dr'},
7683 'cluster_credentials': False}
7684 )
7685 @ddt.unpack
7686 def test_validate_provisioning_options_for_share_invalid_params(
7687 self, provisioning_opts, qos_specs, extra_specs,
7688 cluster_credentials):
7689 self.library._have_cluster_creds = cluster_credentials
7691 self.assertRaises(exception.NetAppException,
7692 self.library.validate_provisioning_options_for_share,
7693 provisioning_opts, extra_specs=extra_specs,
7694 qos_specs=qos_specs)
7696 def test__get_backend_fpolicy_policy_name(self):
7697 result = self.library._get_backend_fpolicy_policy_name(
7698 fake.SHARE_ID)
7699 expected = 'fpolicy_policy_' + fake.SHARE_ID.replace('-', '_')
7701 self.assertEqual(expected, result)
7703 def test__get_backend_fpolicy_event_name(self):
7704 result = self.library._get_backend_fpolicy_event_name(
7705 fake.SHARE_ID, 'NFS')
7706 expected = 'fpolicy_event_nfs_' + fake.SHARE_ID.replace('-', '_')
7708 self.assertEqual(expected, result)
7710 @ddt.data({},
7711 {'policy-name': fake.FPOLICY_POLICY_NAME,
7712 'shares-to-include': [fake.SHARE_NAME]})
7713 def test__create_fpolicy_for_share(self, reusable_scope):
7714 vserver_client = mock.Mock()
7715 vserver_name = fake.VSERVER1
7716 new_fake_share = copy.deepcopy(fake.SHARE)
7717 new_fake_share['id'] = 'new_fake_id'
7718 new_fake_share['share_proto'] = 'CIFS'
7719 event_name = 'fpolicy_event_cifs_new_fake_id'
7720 events = [event_name]
7721 policy_name = 'fpolicy_policy_new_fake_id'
7722 shares_to_include = []
7723 if reusable_scope:
7724 shares_to_include = copy.deepcopy(
7725 reusable_scope.get('shares-to-include'))
7726 shares_to_include.append('share_new_fake_id')
7728 mock_reusable_scope = self.mock_object(
7729 self.library, '_find_reusable_fpolicy_scope',
7730 mock.Mock(return_value=reusable_scope))
7731 mock_modify_policy = self.mock_object(
7732 vserver_client, 'modify_fpolicy_scope')
7733 mock_get_policies = self.mock_object(
7734 vserver_client, 'get_fpolicy_policies_status',
7735 mock.Mock(return_value=[]))
7736 mock_create_event = self.mock_object(
7737 vserver_client, 'create_fpolicy_event')
7738 mock_enable_fpolicy = self.mock_object(
7739 vserver_client, 'enable_fpolicy_policy')
7740 mock_create_fpolicy_policy_with_scope = self.mock_object(
7741 vserver_client, 'create_fpolicy_policy_with_scope')
7743 self.library._create_fpolicy_for_share(
7744 new_fake_share, vserver_name, vserver_client,
7745 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7746 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7747 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7749 mock_reusable_scope.assert_called_once_with(
7750 new_fake_share, vserver_client,
7751 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7752 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7753 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7755 if reusable_scope:
7756 mock_modify_policy.assert_called_once_with(
7757 'share_new_fake_id', fake.FPOLICY_POLICY_NAME,
7758 shares_to_include=shares_to_include)
7759 mock_get_policies.assert_not_called()
7760 mock_create_event.assert_not_called()
7761 mock_create_fpolicy_policy_with_scope.assert_not_called()
7762 mock_enable_fpolicy.assert_not_called()
7763 else:
7764 mock_modify_policy.assert_not_called()
7766 mock_get_policies.assert_called_once()
7767 mock_create_event.assert_called_once_with(
7768 'share_new_fake_id',
7769 event_name, new_fake_share['share_proto'].lower(),
7770 fake.FPOLICY_FILE_OPERATIONS_LIST)
7771 mock_create_fpolicy_policy_with_scope.assert_called_once_with(
7772 policy_name, 'share_new_fake_id', events,
7773 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7774 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE
7775 )
7776 mock_enable_fpolicy.assert_called_once_with(
7777 'share_new_fake_id', policy_name, 1)
7779 def test__create_fpolicy_for_share_max_policies_error(self):
7780 fake_client = mock.Mock()
7781 vserver_name = fake.VSERVER1
7782 mock_reusable_scope = self.mock_object(
7783 self.library, '_find_reusable_fpolicy_scope',
7784 mock.Mock(return_value=None))
7785 policies = [
7786 x for x in range(1, self.library.FPOLICY_MAX_VSERVER_POLICIES + 1)]
7787 mock_get_policies = self.mock_object(
7788 fake_client, 'get_fpolicy_policies_status',
7789 mock.Mock(return_value=policies))
7791 self.assertRaises(
7792 exception.NetAppException,
7793 self.library._create_fpolicy_for_share,
7794 fake.SHARE, vserver_name, fake_client,
7795 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7796 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7797 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7799 mock_reusable_scope.assert_called_once_with(
7800 fake.SHARE, fake_client,
7801 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7802 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7803 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7804 mock_get_policies.assert_called_once()
7806 def test__create_fpolicy_for_share_client_error(self):
7807 fake_client = mock.Mock()
7808 vserver_name = fake.VSERVER1
7809 new_fake_share = copy.deepcopy(fake.SHARE)
7810 new_fake_share['id'] = 'new_fake_id'
7811 new_fake_share['share_proto'] = 'CIFS'
7812 event_name = 'fpolicy_event_cifs_new_fake_id'
7813 events = [event_name]
7814 policy_name = 'fpolicy_policy_new_fake_id'
7816 mock_reusable_scope = self.mock_object(
7817 self.library, '_find_reusable_fpolicy_scope',
7818 mock.Mock(return_value=None))
7819 mock_get_policies = self.mock_object(
7820 fake_client, 'get_fpolicy_policies_status',
7821 mock.Mock(return_value=[]))
7822 mock_create_event = self.mock_object(
7823 fake_client, 'create_fpolicy_event')
7824 mock_create_fpolicy_policy_with_scope = self.mock_object(
7825 fake_client, 'create_fpolicy_policy_with_scope',
7826 mock.Mock(side_effect=self._mock_api_error()))
7827 mock_delete_fpolicy = self.mock_object(
7828 fake_client, 'delete_fpolicy_policy')
7829 mock_delete_event = self.mock_object(
7830 fake_client, 'delete_fpolicy_event')
7832 self.assertRaises(
7833 exception.NetAppException,
7834 self.library._create_fpolicy_for_share,
7835 new_fake_share, vserver_name, fake_client,
7836 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7837 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7838 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7840 mock_reusable_scope.assert_called_once_with(
7841 new_fake_share, fake_client,
7842 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7843 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7844 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7845 mock_get_policies.assert_called_once()
7846 mock_create_event.assert_called_once_with(
7847 'share_new_fake_id', event_name,
7848 new_fake_share['share_proto'].lower(),
7849 fake.FPOLICY_FILE_OPERATIONS_LIST)
7850 mock_create_fpolicy_policy_with_scope.assert_called_once_with(
7851 policy_name, 'share_new_fake_id', events,
7852 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7853 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE)
7854 mock_delete_fpolicy.assert_called_once_with(
7855 'share_new_fake_id', policy_name)
7856 mock_delete_event.assert_called_once_with(
7857 'share_new_fake_id', event_name)
7859 def test__find_reusable_fpolicy_scope(self):
7860 vserver_client = mock.Mock()
7861 new_fake_share = copy.deepcopy(fake.SHARE)
7862 new_fake_share['share_proto'] = 'CIFS'
7863 reusable_scopes = [{
7864 'policy-name': fake.FPOLICY_POLICY_NAME,
7865 'file-extensions-to-include': fake.FPOLICY_EXT_TO_INCLUDE_LIST,
7866 'file-extensions-to-exclude': fake.FPOLICY_EXT_TO_EXCLUDE_LIST,
7867 'shares-to-include': ['any_other_fake_share'],
7868 }]
7869 reusable_policies = [{
7870 'policy-name': fake.FPOLICY_POLICY_NAME,
7871 'engine-name': fake.FPOLICY_ENGINE,
7872 'events': [fake.FPOLICY_EVENT_NAME]
7873 }]
7874 reusable_events = [{
7875 'event-name': fake.FPOLICY_EVENT_NAME,
7876 'protocol': new_fake_share['share_proto'].lower(),
7877 'file-operations': fake.FPOLICY_FILE_OPERATIONS_LIST
7878 }]
7879 mock_get_scopes = self.mock_object(
7880 vserver_client, 'get_fpolicy_scopes',
7881 mock.Mock(return_value=reusable_scopes))
7882 mock_get_policies = self.mock_object(
7883 vserver_client, 'get_fpolicy_policies',
7884 mock.Mock(return_value=reusable_policies))
7885 mocke_get_events = self.mock_object(
7886 vserver_client, 'get_fpolicy_events',
7887 mock.Mock(return_value=reusable_events)
7888 )
7890 result = self.library._find_reusable_fpolicy_scope(
7891 new_fake_share, vserver_client,
7892 fpolicy_extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7893 fpolicy_extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7894 fpolicy_file_operations=fake.FPOLICY_FILE_OPERATIONS)
7896 self.assertEqual(reusable_scopes[0], result)
7898 mock_get_scopes.assert_called_once_with(
7899 share_name=fake.SHARE_NAME,
7900 extensions_to_include=fake.FPOLICY_EXT_TO_INCLUDE,
7901 extensions_to_exclude=fake.FPOLICY_EXT_TO_EXCLUDE,
7902 shares_to_include=None)
7903 mock_get_policies.assert_called_once_with(
7904 share_name=fake.SHARE_NAME,
7905 policy_name=fake.FPOLICY_POLICY_NAME)
7906 mocke_get_events.assert_called_once_with(
7907 share_name=fake.SHARE_NAME,
7908 event_name=fake.FPOLICY_EVENT_NAME)
7910 @ddt.data(False, True)
7911 def test__delete_fpolicy_for_share(self, last_share):
7912 fake_vserver_client = mock.Mock()
7913 fake_vserver_name = fake.VSERVER1
7914 fake_share = copy.deepcopy(fake.SHARE)
7915 share_name = self.library._get_backend_share_name(fake.SHARE_ID)
7916 existing_shares = [share_name]
7917 if not last_share:
7918 existing_shares.append('any_other_share')
7919 scopes = [{
7920 'policy-name': fake.FPOLICY_POLICY_NAME,
7921 'file-extensions-to-include': fake.FPOLICY_EXT_TO_INCLUDE_LIST,
7922 'file-extensions-to-exclude': fake.FPOLICY_EXT_TO_EXCLUDE_LIST,
7923 'shares-to-include': existing_shares,
7924 }]
7925 shares_to_include = copy.copy(scopes[0].get('shares-to-include'))
7926 shares_to_include.remove(share_name)
7927 policies = [{
7928 'policy-name': fake.FPOLICY_POLICY_NAME,
7929 'engine-name': fake.FPOLICY_ENGINE,
7930 'events': [fake.FPOLICY_EVENT_NAME]
7931 }]
7933 mock_get_scopes = self.mock_object(
7934 fake_vserver_client, 'get_fpolicy_scopes',
7935 mock.Mock(return_value=scopes))
7936 mock_modify_scope = self.mock_object(
7937 fake_vserver_client, 'modify_fpolicy_scope')
7939 mock_disable_policy = self.mock_object(
7940 fake_vserver_client, 'disable_fpolicy_policy')
7941 mock_get_policies = self.mock_object(
7942 fake_vserver_client, 'get_fpolicy_policies',
7943 mock.Mock(return_value=policies))
7944 mock_delete_scope = self.mock_object(
7945 fake_vserver_client, 'delete_fpolicy_scope')
7946 mock_delete_policy = self.mock_object(
7947 fake_vserver_client, 'delete_fpolicy_policy')
7948 mock_delete_event = self.mock_object(
7949 fake_vserver_client, 'delete_fpolicy_event')
7951 self.library._delete_fpolicy_for_share(fake_share, fake_vserver_name,
7952 fake_vserver_client)
7954 mock_get_scopes.assert_called_once_with(
7955 share_name=fake.SHARE_NAME,
7956 shares_to_include=[share_name])
7957 if shares_to_include:
7958 mock_modify_scope.assert_called_once_with(
7959 fake.SHARE_NAME,
7960 fake.FPOLICY_POLICY_NAME, shares_to_include=shares_to_include)
7961 else:
7962 mock_disable_policy.assert_called_once_with(
7963 fake.FPOLICY_POLICY_NAME)
7964 mock_get_policies.assert_called_once_with(
7965 share_name=fake.SHARE_NAME,
7966 policy_name=fake.FPOLICY_POLICY_NAME)
7967 mock_delete_scope.assert_called_once_with(
7968 fake.FPOLICY_POLICY_NAME)
7969 mock_delete_policy.assert_called_once_with(
7970 fake.SHARE_NAME,
7971 fake.FPOLICY_POLICY_NAME)
7972 mock_delete_event.assert_called_once_with(
7973 fake.FPOLICY_EVENT_NAME)
7975 @ddt.data(True, False)
7976 def test_initialize_flexgroup_pools(self, auto_provision):
7977 self.library.configuration.netapp_enable_flexgroup = True
7978 pool = None if auto_provision else [fake.FLEXGROUP_POOL_OPT_RAW]
7979 mock_safe_get = self.mock_object(
7980 self.library.configuration, 'safe_get',
7981 mock.Mock(return_value=pool))
7982 mock_is_flex_support = self.mock_object(
7983 self.library._client, 'is_flexgroup_supported',
7984 mock.Mock(return_value=True))
7985 mock_parse = self.mock_object(
7986 na_utils, 'parse_flexgroup_pool_config',
7987 mock.Mock(return_value=fake.FLEXGROUP_POOL_OPT))
7988 aggr_set = set(fake.FLEXGROUP_POOL_AGGR)
7990 self.library._initialize_flexgroup_pools(aggr_set)
7992 mock_safe_get.assert_called_once_with('netapp_flexgroup_pools')
7993 mock_is_flex_support.assert_called_once_with()
7994 if auto_provision:
7995 self.assertEqual(self.library._flexgroup_pools,
7996 {na_utils.FLEXGROUP_DEFAULT_POOL_NAME: sorted(
7997 aggr_set)})
7998 self.assertTrue(self.library._is_flexgroup_auto)
7999 mock_parse.assert_not_called()
8000 else:
8001 self.assertEqual(self.library._flexgroup_pools,
8002 fake.FLEXGROUP_POOL_OPT)
8003 self.assertFalse(self.library._is_flexgroup_auto)
8004 mock_parse.assert_called_once_with(
8005 [fake.FLEXGROUP_POOL_OPT_RAW],
8006 cluster_aggr_set=set(fake.FLEXGROUP_POOL_AGGR), check=True)
8008 def test_initialize_flexgroup_pools_no_opt(self):
8009 self.library.configuration.netapp_enable_flexgroup = False
8010 self.mock_object(self.library.configuration,
8011 'safe_get',
8012 mock.Mock(return_value=None))
8014 self.library._initialize_flexgroup_pools(set(fake.FLEXGROUP_POOL_AGGR))
8016 self.assertEqual(self.library._flexgroup_pools, {})
8018 def test_initialize_flexgroup_pools_raise_version(self):
8019 self.library.configuration.netapp_enable_flexgroup = True
8020 self.mock_object(self.library.configuration,
8021 'safe_get',
8022 mock.Mock(return_value=[fake.FLEXGROUP_POOL_OPT_RAW]))
8023 self.mock_object(self.library._client,
8024 'is_flexgroup_supported',
8025 mock.Mock(return_value=False))
8027 self.assertRaises(exception.NetAppException,
8028 self.library._initialize_flexgroup_pools,
8029 set(fake.FLEXGROUP_POOL_AGGR))
8031 def test_initialize_flexgroup_pools_raise_no_enable_with_pool(self):
8032 self.library.configuration.netapp_enable_flexgroup = False
8033 self.mock_object(self.library.configuration,
8034 'safe_get',
8035 mock.Mock(return_value=[fake.FLEXGROUP_POOL_OPT_RAW]))
8037 self.assertRaises(exception.NetAppException,
8038 self.library._initialize_flexgroup_pools,
8039 set(fake.FLEXGROUP_POOL_AGGR))
8041 @ddt.data(True, False)
8042 def test_get_flexgroup_pool_name(self, auto_provisioned):
8044 self.library._is_flexgroup_auto = auto_provisioned
8045 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
8047 result = self.library._get_flexgroup_pool_name(
8048 fake.FLEXGROUP_POOL_AGGR)
8050 if auto_provisioned:
8051 self.assertEqual(na_utils.FLEXGROUP_DEFAULT_POOL_NAME, result)
8052 else:
8053 self.assertEqual(fake.FLEXGROUP_POOL_NAME, result)
8055 def test_get_flexgroup_pool_name_not_found(self):
8057 self.library._is_flexgroup_auto = False
8058 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
8060 result = self.library._get_flexgroup_pool_name([])
8062 self.assertEqual('', result)
8064 def test_is_flexgroup_pool(self):
8066 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
8068 result = self.library._is_flexgroup_pool(fake.FLEXGROUP_POOL_NAME)
8070 self.assertTrue(result)
8072 @ddt.data({'pool_name': fake.FLEXGROUP_POOL_NAME,
8073 'aggr_list': fake.FLEXGROUP_POOL_AGGR},
8074 {'pool_name': '',
8075 'aggr_list': []})
8076 @ddt.unpack
8077 def test_get_flexgroup_aggregate_list(self, pool_name, aggr_list):
8079 self.library._flexgroup_pools = fake.FLEXGROUP_POOL_OPT
8081 result = self.library._get_flexgroup_aggregate_list(pool_name)
8083 self.assertEqual(aggr_list, result)
8085 def test_is_flexgroup_share(self):
8086 vserver_client = mock.Mock()
8087 vserver_client.is_flexgroup_volume.return_value = True
8089 result = self.library._is_flexgroup_share(vserver_client,
8090 fake.SHARE_NAME)
8092 vserver_client.is_flexgroup_volume.assert_called_once_with(
8093 fake.SHARE_NAME)
8094 self.assertTrue(result)
8096 def test_is_flexgroup_share_raise(self):
8097 vserver_client = mock.Mock()
8098 vserver_client.is_flexgroup_volume.side_effect = (
8099 exception.NetAppException)
8101 self.assertRaises(exception.ShareNotFound,
8102 self.library._is_flexgroup_share,
8103 vserver_client, fake.SHARE_NAME)
8105 vserver_client.is_flexgroup_volume.assert_called_once_with(
8106 fake.SHARE_NAME)
8108 @ddt.data(
8109 {'enabled': True, 'flexgroup_only': False, 'is_flexvol': True},
8110 {'enabled': False, 'flexgroup_only': False, 'is_flexvol': True},
8111 {'enabled': True, 'flexgroup_only': True, 'is_flexvol': False},
8112 {'enabled': False, 'flexgroup_only': True, 'is_flexvol': True})
8113 @ddt.unpack
8114 def test_is_flexvol_pool_configured(self, enabled, flexgroup_only,
8115 is_flexvol):
8117 self.library.configuration.netapp_enable_flexgroup = enabled
8118 self.library.configuration.netapp_flexgroup_pool_only = flexgroup_only
8120 result = self.library.is_flexvol_pool_configured()
8122 self.assertEqual(is_flexvol, result)
8124 def test_get_minimum_flexgroup_size(self):
8125 self.mock_object(self.library, '_get_flexgroup_aggregate_list',
8126 mock.Mock(return_value=fake.AGGREGATES))
8128 result = self.library._get_minimum_flexgroup_size(fake.POOL_NAME)
8130 expected = (len(fake.AGGREGATES) *
8131 self.library.FLEXGROUP_MIN_SIZE_PER_AGGR)
8132 self.assertEqual(expected, result)
8133 self.library._get_flexgroup_aggregate_list.assert_called_once_with(
8134 fake.POOL_NAME)
8136 def test_is_flexgroup_destination_host_not_enabled(self):
8137 mock_config = mock.Mock()
8138 dm_session = mock.Mock()
8139 mock_get_backend = self.mock_object(
8140 dm_session, 'get_backend_name_and_config_obj',
8141 mock.Mock(return_value=('fake', mock_config)))
8142 mock_safe_get = self.mock_object(
8143 mock_config, 'safe_get', mock.Mock(return_value=False))
8145 result = self.library.is_flexgroup_destination_host(fake.HOST_NAME,
8146 dm_session)
8148 self.assertFalse(result)
8149 mock_get_backend.assert_called_once_with(fake.HOST_NAME)
8150 mock_safe_get.assert_called_once_with('netapp_enable_flexgroup')
8152 @ddt.data(None, [{'fg1': fake.AGGREGATE}])
8153 def test_is_flexgroup_destination_host_false(self, flexgroup_pools):
8154 mock_config = mock.Mock()
8155 dm_session = mock.Mock()
8156 mock_get_backend = self.mock_object(
8157 dm_session, 'get_backend_name_and_config_obj',
8158 mock.Mock(return_value=('fake', mock_config)))
8159 mock_safe_get = self.mock_object(
8160 mock_config, 'safe_get',
8161 mock.Mock(side_effect=[True, flexgroup_pools]))
8162 mock_extract = self.mock_object(
8163 share_utils, 'extract_host',
8164 mock.Mock(return_value=fake.POOL_NAME))
8165 mock_parse = self.mock_object(
8166 na_utils, 'parse_flexgroup_pool_config',
8167 mock.Mock(return_value={}))
8169 result = self.library.is_flexgroup_destination_host(fake.HOST_NAME,
8170 dm_session)
8172 self.assertFalse(result)
8173 mock_get_backend.assert_called_once_with(fake.HOST_NAME)
8174 mock_safe_get.assert_has_calls([
8175 mock.call('netapp_enable_flexgroup'),
8176 mock.call('netapp_flexgroup_pools'),
8177 ])
8178 mock_extract.assert_called_once_with(fake.HOST_NAME, level='pool')
8179 if flexgroup_pools:
8180 mock_parse.assert_called_once_with(flexgroup_pools)
8181 else:
8182 mock_parse.assert_not_called()
8184 def test_is_flexgroup_destination_host_true(self):
8185 flexgroup_pools = [{fake.POOL_NAME: fake.AGGREGATE}]
8186 mock_config = mock.Mock()
8187 dm_session = mock.Mock()
8188 mock_get_backend = self.mock_object(
8189 dm_session, 'get_backend_name_and_config_obj',
8190 mock.Mock(return_value=('fake', mock_config)))
8191 mock_safe_get = self.mock_object(
8192 mock_config, 'safe_get',
8193 mock.Mock(side_effect=[True, flexgroup_pools]))
8194 mock_extract = self.mock_object(
8195 share_utils, 'extract_host',
8196 mock.Mock(return_value=fake.POOL_NAME))
8197 mock_parse = self.mock_object(
8198 na_utils, 'parse_flexgroup_pool_config',
8199 mock.Mock(return_value=flexgroup_pools[0]))
8201 result = self.library.is_flexgroup_destination_host(fake.HOST_NAME,
8202 dm_session)
8204 self.assertTrue(result)
8205 mock_get_backend.assert_called_once_with(fake.HOST_NAME)
8206 mock_safe_get.assert_has_calls([
8207 mock.call('netapp_enable_flexgroup'),
8208 mock.call('netapp_flexgroup_pools'),
8209 ])
8210 mock_extract.assert_called_once_with(fake.HOST_NAME, level='pool')
8211 mock_parse.assert_called_once_with(flexgroup_pools)
8213 def test_create_backup_first_backup(self):
8214 vserver_client = mock.Mock()
8215 mock_dest_client = mock.Mock()
8216 self.mock_object(self.library,
8217 '_get_vserver',
8218 mock.Mock(return_value=(fake.VSERVER1,
8219 vserver_client)))
8220 self._backup_mock_common_method(mock_dest_client)
8221 self.mock_object(vserver_client,
8222 'get_snapmirror_destinations',
8223 mock.Mock(return_value=[]))
8225 vserver_peer_info = [{'vserver': fake.VSERVER1,
8226 'peer-vserver': fake.VSERVER2}]
8227 self.mock_object(vserver_client,
8228 'get_vserver_peers',
8229 mock.Mock(return_value=vserver_peer_info))
8230 snap_list = ["snap1", "snap2", "snap3"]
8231 self.mock_object(mock_dest_client,
8232 'list_volume_snapshots',
8233 mock.Mock(return_value=snap_list))
8235 share_instance = fake.SHARE_INSTANCE
8236 backup = fake.SHARE_BACKUP
8237 self.library.create_backup(self.context, share_instance, backup)
8238 (mock_dest_client.create_snapmirror_policy.
8239 assert_called_once_with(mock.ANY,
8240 policy_type='vault',
8241 discard_network_info=False,
8242 snapmirror_label=mock.ANY,
8243 keep=mock.ANY))
8245 (mock_dest_client.create_snapmirror_vol.
8246 assert_called_once_with(mock.ANY,
8247 mock.ANY,
8248 mock.ANY,
8249 mock.ANY,
8250 'extended_data_protection',
8251 policy=mock.ANY
8252 ))
8253 dm_session = data_motion.DataMotionSession()
8254 (dm_session.initialize_and_wait_snapmirror_vol.
8255 assert_called_once_with(mock.ANY,
8256 mock.ANY,
8257 mock.ANY,
8258 mock.ANY,
8259 mock.ANY,
8260 timeout=mock.ANY,
8261 ))
8262 (mock_dest_client.update_snapmirror_vol.
8263 assert_called_once_with(mock.ANY,
8264 mock.ANY,
8265 mock.ANY,
8266 mock.ANY,
8267 ))
8269 def test_create_backup_second_backup(self):
8270 vserver_client = mock.Mock()
8271 mock_dest_client = mock.Mock()
8272 self._backup_mock_common_method(mock_dest_client)
8273 self.mock_object(self.library,
8274 '_get_vserver',
8275 mock.Mock(return_value=(fake.VSERVER1,
8276 vserver_client)))
8277 snapmirror_info = [fake.SNAP_MIRROR_INFO]
8278 self.mock_object(vserver_client,
8279 'get_snapmirror_destinations',
8280 mock.Mock(return_value=snapmirror_info))
8282 share_instance = fake.SHARE_INSTANCE
8283 backup = fake.SHARE_BACKUP
8284 self.library.create_backup(self.context, share_instance, backup)
8285 mock_dest_client.create_snapmirror_policy.assert_not_called()
8286 mock_dest_client.create_snapmirror_vol.assert_not_called()
8287 (data_motion.DataMotionSession().
8288 initialize_and_wait_snapmirror_vol.assert_not_called())
8289 (mock_dest_client.update_snapmirror_vol.
8290 assert_called_once_with(mock.ANY,
8291 mock.ANY,
8292 mock.ANY,
8293 mock.ANY,
8294 ))
8296 def test_create_backup_continue(self):
8297 vserver_client = mock.Mock()
8298 mock_dest_client = mock.Mock()
8299 self._backup_mock_common_method(mock_dest_client)
8300 self.mock_object(self.library,
8301 '_get_vserver',
8302 mock.Mock(return_value=(fake.VSERVER1,
8303 vserver_client)))
8304 snapmirror_info = [fake.SNAP_MIRROR_INFO]
8305 self.mock_object(mock_dest_client,
8306 'get_snapmirrors',
8307 mock.Mock(return_value=snapmirror_info))
8308 snap_list = ["snap1", "snap2", "snap3"]
8309 self.mock_object(self.library,
8310 '_get_des_volume_backup_snapshots',
8311 mock.Mock(return_value=snap_list))
8312 share_instance = fake.SHARE_INSTANCE
8313 backup = fake.SHARE_BACKUP
8314 self.library.create_backup_continue(self.context, share_instance,
8315 backup)
8317 def test_restore_backup(self):
8318 vserver_client = mock.Mock()
8319 mock_dest_client = mock.Mock()
8320 self._backup_mock_common_method(mock_dest_client)
8321 self.mock_object(self.library,
8322 '_get_vserver',
8323 mock.Mock(return_value=(fake.VSERVER1,
8324 vserver_client)))
8325 share_instance = fake.SHARE_INSTANCE
8326 backup = fake.SHARE_BACKUP
8327 self.library.restore_backup(self.context, backup, share_instance)
8328 vserver_client.snapmirror_restore_vol.assert_called_once_with(
8329 source_path=mock.ANY,
8330 dest_path=mock.ANY,
8331 source_snapshot=mock.ANY,
8332 des_cluster=mock.ANY,
8333 )
8335 def test_restore_backup_continue(self):
8336 vserver_client = mock.Mock()
8337 self.mock_object(self.library,
8338 '_get_vserver',
8339 mock.Mock(return_value=(fake.VSERVER1,
8340 vserver_client)))
8341 self.mock_object(vserver_client,
8342 'get_snapmirrors',
8343 mock.Mock(return_value=[]))
8344 snap_list = ["restored_snap1", "snap2", "snap3"]
8345 self.mock_object(vserver_client,
8346 'list_volume_snapshots',
8347 mock.Mock(return_value=snap_list))
8348 self.mock_object(self.library,
8349 '_get_backup_snapshot_name',
8350 mock.Mock(return_value="restored_snap1"))
8351 share_instance = fake.SHARE_INSTANCE
8352 backup = fake.SHARE_BACKUP
8353 self.library.restore_backup_continue(self.context, backup,
8354 share_instance)
8356 def test_delete_backup(self):
8357 vserver_client = mock.Mock()
8358 mock_dest_client = mock.Mock()
8359 self._backup_mock_common_method(mock_dest_client)
8360 self.mock_object(self.library,
8361 '_get_vserver',
8362 mock.Mock(return_value=(fake.VSERVER1,
8363 vserver_client)))
8364 self.mock_object(mock_dest_client,
8365 'get_snapmirrors',
8366 mock.Mock(return_value=[]))
8367 snap_list = ["snap1", "snap2", "snap3"]
8368 self.mock_object(self.library,
8369 '_get_des_volume_backup_snapshots',
8370 mock.Mock(return_value=snap_list))
8371 self.mock_object(
8372 self.library, '_is_snapshot_deleted',
8373 mock.Mock(return_value=True))
8374 share_instance = fake.SHARE_INSTANCE
8375 backup = fake.SHARE_BACKUP
8376 self.library.delete_backup(self.context, share_instance, backup)
8378 def test_delete_backup_with_resource_cleanup(self):
8379 vserver_client = mock.Mock()
8380 mock_dest_client = mock.Mock()
8381 self._backup_mock_common_method(mock_dest_client)
8382 self.mock_object(self.library,
8383 '_get_vserver',
8384 mock.Mock(return_value=(fake.VSERVER1,
8385 vserver_client)))
8386 snapmirror_info = [fake.SNAP_MIRROR_INFO]
8387 self.mock_object(mock_dest_client,
8388 'get_snapmirrors',
8389 mock.Mock(return_value=snapmirror_info))
8390 snap_list = ["snap1", "snap2", "snap3"]
8391 self.mock_object(self.library,
8392 '_get_des_volume_backup_snapshots',
8393 mock.Mock(return_value=snap_list))
8394 self.mock_object(
8395 self.library, '_is_snapshot_deleted',
8396 mock.Mock(return_value=True))
8397 share_instance = fake.SHARE_INSTANCE
8398 backup = fake.SHARE_BACKUP
8399 self.library.delete_backup(self.context, share_instance, backup)
8401 def test__get_backup_snapshot_name(self):
8402 backup = fake.SHARE_BACKUP
8403 actual_result = self.library._get_backup_snapshot_name(backup,
8404 fake.SHARE_ID)
8405 backup_id = backup.get('id', "")
8406 expected_result = f"backup_{fake.SHARE_ID}_{backup_id}"
8407 self.assertEqual(actual_result, expected_result)
8409 def test__get_backend(self):
8410 backup = fake.SHARE_BACKUP
8411 self.mock_object(data_motion,
8412 'get_backup_configuration',
8413 mock.Mock(return_value=_get_config()))
8415 actual_result = self.library._get_backend(backup)
8416 self.assertEqual(actual_result, fake.BACKEND_NAME)
8418 def test__get_des_volume_backup_snapshots(self):
8419 mock_dest_client = mock.Mock()
8420 share_id = fake.SHARE_ID
8421 snap_list = [f"backup_{share_id}_snap1",
8422 f"backup_{share_id}_snap2", "snap3"]
8423 self.mock_object(mock_dest_client,
8424 'list_volume_snapshots',
8425 mock.Mock(return_value=snap_list))
8426 expected_snap_list = [f"backup_{share_id}_snap1",
8427 f"backup_{share_id}_snap2"]
8428 actual_result = self.library._get_des_volume_backup_snapshots(
8429 mock_dest_client,
8430 fake.FLEXVOL_NAME,
8431 share_id)
8432 self.assertEqual(expected_snap_list, actual_result)
8434 def test__get_volume_for_backup(self):
8435 mock_dest_client = mock.Mock()
8436 mock_src_client = mock.Mock()
8437 self.mock_object(data_motion,
8438 'get_backup_configuration',
8439 mock.Mock(return_value=_get_config()))
8440 self.library._get_volume_for_backup(fake.SHARE_BACKUP,
8441 fake.SHARE_INSTANCE,
8442 mock_src_client, mock_dest_client)
8444 def test__get_volume_for_backup_create_new_vol(self):
8445 mock_dest_client = mock.Mock()
8446 mock_src_client = mock.Mock()
8447 _get_config()
8448 backup_config = 'backup_config'
8449 fake_config = configuration.Configuration(driver.share_opts,
8450 config_group=backup_config)
8451 CONF.set_override("netapp_backup_volume", "",
8452 group=backup_config)
8453 CONF.set_override("netapp_backup_vserver", "",
8454 group=backup_config)
8455 self.mock_object(data_motion,
8456 'get_backup_configuration',
8457 mock.Mock(return_value=fake_config))
8458 vol_attr = {'name': 'fake_vol', 'size': 12345}
8459 self.mock_object(mock_src_client,
8460 'get_volume',
8461 mock.Mock(return_value=vol_attr))
8462 self.library._get_volume_for_backup(fake.SHARE_BACKUP,
8463 fake.SHARE_INSTANCE,
8464 mock_src_client, mock_dest_client)
8466 def test__get_volume_for_backup_aggr_not_found_negative(self):
8467 mock_dest_client = mock.Mock()
8468 mock_src_client = mock.Mock()
8469 _get_config()
8470 backup_config = 'backup_config'
8471 fake_config = configuration.Configuration(driver.share_opts,
8472 config_group=backup_config)
8473 CONF.set_override("netapp_backup_volume", "",
8474 group=backup_config)
8475 CONF.set_override("netapp_backup_vserver", "",
8476 group=backup_config)
8477 self.mock_object(data_motion,
8478 'get_backup_configuration',
8479 mock.Mock(return_value=fake_config))
8480 self.mock_object(self.mock_dm_session,
8481 'get_most_available_aggr_of_vserver',
8482 mock.Mock(return_value=None))
8483 self.assertRaises(
8484 exception.NetAppException,
8485 self.library._get_volume_for_backup,
8486 fake.SHARE_BACKUP,
8487 fake.SHARE_INSTANCE,
8488 mock_src_client,
8489 mock_dest_client,
8490 )
8492 def test__get_vserver_for_backup(self):
8493 mock_dest_client = mock.Mock()
8494 self.mock_object(data_motion,
8495 'get_backup_configuration',
8496 mock.Mock(return_value=_get_config()))
8498 mock_backend_config = na_fakes.create_configuration()
8499 self.mock_object(data_motion,
8500 'get_backend_configuration',
8501 mock.Mock(return_value=mock_backend_config))
8502 self.mock_object(self.library,
8503 '_get_api_client_for_backend',
8504 mock.Mock(return_value=mock_dest_client))
8506 self.library._get_vserver_for_backup(fake.SHARE_INSTANCE,
8507 fake.SHARE_BACKUP)
8509 def test__get_destination_vserver_and_vol(self):
8510 mock_dest_client = mock.Mock()
8511 snapmirror_info = [fake.SNAP_MIRROR_INFO]
8512 source_path = f"{fake.VSERVER1}:{fake.FLEXVOL_NAME}"
8513 self.mock_object(mock_dest_client,
8514 'get_snapmirror_destinations',
8515 mock.Mock(return_value=snapmirror_info))
8516 actual_result = self.library._get_destination_vserver_and_vol(
8517 mock_dest_client,
8518 source_path, validate_relation=True)
8519 expected_result = (fake.VSERVER2, fake.FLEXVOL_NAME_1)
8520 self.assertEqual(actual_result, expected_result)
8522 def test__get_destination_vserver_and_vol_negative(self):
8523 mock_dest_client = mock.Mock()
8524 snapmirror_info = [{'source-vserver': fake.VSERVER1,
8525 'source-volume': fake.FLEXVOL_NAME,
8526 'destination-vserver': fake.VSERVER2,
8527 'destination-volume': fake.FLEXVOL_NAME_1
8528 },
8529 {'source-vserver': 'fake_vs_1',
8530 'source-volume': 'fake_vol_1',
8531 'destination-vserver': 'fake_vs_2',
8532 'destination-volume': 'fake_vol_2'
8533 }
8534 ]
8535 source_path = f"{fake.VSERVER1}:{fake.FLEXVOL_NAME}"
8536 self.mock_object(mock_dest_client,
8537 'get_snapmirror_destinations',
8538 mock.Mock(return_value=snapmirror_info))
8539 self.assertRaises(
8540 exception.NetAppException,
8541 self.library._get_destination_vserver_and_vol,
8542 mock_dest_client,
8543 source_path,
8544 validate_relation=True
8545 )
8547 def test_verify_and_wait_for_snapshot_to_transfer(self):
8548 vserver_client = mock.Mock()
8549 self.mock_object(vserver_client,
8550 'get_snapshot',
8551 mock.Mock(return_value=fake.SNAPSHOT_NAME))
8552 result = self.library._verify_and_wait_for_snapshot_to_transfer(
8553 vserver_client,
8554 fake.FLEXVOL_NAME,
8555 fake.SNAPSHOT_NAME,
8556 )
8557 self.assertIsNone(result)
8559 def test_verify_and_wait_for_snapshot_to_transfer_negative(self):
8560 vserver_client = mock.Mock()
8561 self.mock_object(vserver_client,
8562 'get_snapshot',
8563 mock.Mock(side_effect=netapp_api.NaApiError))
8564 self.assertRaises(
8565 exception.NetAppException,
8566 self.library._verify_and_wait_for_snapshot_to_transfer,
8567 vserver_client,
8568 fake.FLEXVOL_NAME,
8569 fake.SNAPSHOT_NAME,
8570 timeout=10,
8571 )
8573 def test__resource_cleanup_for_backup(self):
8574 src_vserver_client = mock.Mock()
8575 des_vserver_client = mock.Mock()
8576 share_instance = fake.SHARE_INSTANCE
8577 backup = fake.SHARE_BACKUP
8578 self.mock_object(data_motion,
8579 'get_backup_configuration',
8580 mock.Mock(return_value=_get_config()))
8581 mock_backend_config = na_fakes.create_configuration()
8582 self.mock_object(data_motion,
8583 'get_backend_configuration',
8584 mock.Mock(return_value=mock_backend_config))
8585 self.mock_object(self.library,
8586 '_get_vserver',
8587 mock.Mock(return_value=(fake.VSERVER1,
8588 src_vserver_client)))
8589 self.mock_object(self.library,
8590 '_get_api_client_for_backend',
8591 mock.Mock(return_value=des_vserver_client))
8592 self.mock_object(self.library,
8593 '_get_backend_share_name',
8594 mock.Mock(return_value=fake.FLEXVOL_NAME))
8596 self.library._resource_cleanup_for_backup(backup,
8597 share_instance,
8598 fake.VSERVER2,
8599 fake.FLEXVOL_NAME_1,
8600 )
8601 (des_vserver_client.abort_snapmirror_vol.
8602 assert_called_once_with(fake.VSERVER1,
8603 fake.FLEXVOL_NAME,
8604 fake.VSERVER2,
8605 fake.FLEXVOL_NAME_1,
8606 clear_checkpoint=False
8607 ))
8608 (des_vserver_client.delete_snapmirror_vol.
8609 assert_called_once_with(fake.VSERVER1,
8610 fake.FLEXVOL_NAME,
8611 fake.VSERVER2,
8612 fake.FLEXVOL_NAME_1,
8613 ))
8614 db_session = data_motion.DataMotionSession()
8615 (db_session.wait_for_snapmirror_release_vol.
8616 assert_called_once_with(fake.VSERVER1,
8617 fake.VSERVER2,
8618 fake.FLEXVOL_NAME,
8619 fake.FLEXVOL_NAME_1,
8620 False, src_vserver_client,
8621 timeout=mock.ANY
8622 ))
8624 def test__resource_cleanup_for_backup_with_exception(self):
8625 mock_src_vserver_client = mock.Mock()
8626 mock_des_vserver_client = mock.Mock()
8627 self.mock_object(self.library,
8628 '_get_vserver',
8629 mock.Mock(return_value=(fake.VSERVER1,
8630 mock_src_vserver_client)))
8631 self._backup_mock_common_method(mock_des_vserver_client)
8632 self.mock_object(mock_des_vserver_client,
8633 'abort_snapmirror_vol',
8634 mock.Mock(side_effect=netapp_api.NaApiError))
8635 self.mock_object(mock_des_vserver_client,
8636 'delete_snapmirror_vol',
8637 mock.Mock(side_effect=netapp_api.NaApiError(
8638 code=netapp_api.EOBJECTNOTFOUND)))
8639 self.mock_object(mock_des_vserver_client,
8640 'delete_snapmirror_policy',
8641 mock.Mock(side_effect=netapp_api.NaApiError))
8642 self.mock_object(mock_src_vserver_client,
8643 'delete_vserver_peer',
8644 mock.Mock(side_effect=netapp_api.NaApiError))
8645 self.library._resource_cleanup_for_backup(fake.SHARE_BACKUP,
8646 fake.SHARE_INSTANCE,
8647 fake.VSERVER2,
8648 fake.FLEXVOL_NAME_1,
8649 )
8651 def test__resource_cleanup_for_backup_vserver_volume_none(self):
8652 mock_src_vserver_client = mock.Mock()
8653 mock_des_vserver_client = mock.Mock()
8654 self.mock_object(self.library,
8655 '_get_vserver',
8656 mock.Mock(return_value=(fake.VSERVER1,
8657 mock_src_vserver_client)))
8658 self.mock_object(self.library,
8659 '_delete_backup_vserver',
8660 mock.Mock(return_value=None))
8662 self.mock_object(mock_des_vserver_client,
8663 'delete_volume',
8664 mock.Mock(side_effect=netapp_api.NaApiError))
8666 self._backup_mock_common_method(mock_des_vserver_client)
8667 backup_config = 'backup_config'
8668 CONF.set_override("netapp_backup_volume", "",
8669 group=backup_config)
8670 CONF.set_override("netapp_backup_vserver", "",
8671 group=backup_config)
8672 self.library._resource_cleanup_for_backup(
8673 fake.SHARE_BACKUP,
8674 fake.SHARE_INSTANCE,
8675 fake.VSERVER2,
8676 fake.FLEXVOL_NAME_1,
8677 share_server=fake.SHARE_SERVER,
8678 )
8680 def test_create_backup_with_backup_type_none_negative(self):
8681 vserver_client = mock.Mock()
8682 self.mock_object(self.library,
8683 '_get_vserver',
8684 mock.Mock(return_value=(fake.VSERVER1,
8685 vserver_client)))
8686 backup = {'id': '242ff47e-518d-4b07-b3c3-0a51e6744149',
8687 'backup_options': {'backend': 'fake_ontap',
8688 'backup_type': None
8689 },
8690 }
8691 self.assertRaises(
8692 exception.BackupException,
8693 self.library.create_backup,
8694 self.context,
8695 fake.SHARE_INSTANCE,
8696 backup,
8697 )
8699 def test_create_backup_with_non_netapp_backend_negative(self):
8700 self.mock_object(data_motion,
8701 'get_backup_configuration',
8702 mock.Mock(return_value=_get_config()))
8703 self.mock_object(self.library,
8704 '_get_vserver',
8705 mock.Mock(return_value=(fake.VSERVER1,
8706 mock.Mock())))
8707 fake_config = configuration.Configuration(
8708 driver.share_opts, config_group='backup_config')
8709 CONF.set_override("netapp_storage_family", None,
8710 group='backup_config')
8711 self.mock_object(data_motion,
8712 'get_backend_configuration',
8713 mock.Mock(return_value=fake_config))
8714 self.assertRaises(
8715 exception.BackupException,
8716 self.library.create_backup,
8717 self.context,
8718 fake.SHARE_INSTANCE,
8719 fake.SHARE_BACKUP,
8720 )
8722 def test_create_backup_when_enabled_backup_types_none_negative(self):
8723 vserver_src_client = mock.Mock()
8724 vserver_dest_client = mock.Mock()
8725 self.mock_object(self.library,
8726 '_get_vserver',
8727 mock.Mock(return_value=(fake.VSERVER1,
8728 vserver_src_client)))
8729 self._backup_mock_common_method(vserver_dest_client)
8730 fake_config = configuration.Configuration(driver.share_opts,
8731 config_group='backup_config')
8732 CONF.set_override("netapp_enabled_backup_types", None,
8733 group='backup_config')
8734 self.mock_object(data_motion,
8735 'get_backend_configuration',
8736 mock.Mock(return_value=fake_config))
8737 self.assertRaises(
8738 exception.BackupException,
8739 self.library.create_backup,
8740 self.context,
8741 fake.SHARE_INSTANCE,
8742 fake.SHARE_BACKUP,
8743 )
8745 def test_create_backup_source_has_2_more_relationships_negative(self):
8746 vserver_client = mock.Mock()
8747 mock_dest_client = mock.Mock()
8748 self._backup_mock_common_method(mock_dest_client)
8749 self.mock_object(self.library,
8750 '_get_vserver',
8751 mock.Mock(return_value=(fake.VSERVER1,
8752 vserver_client)))
8753 snapmirror_info = [{'source-vserver': fake.VSERVER1,
8754 'source-volume': fake.FLEXVOL_NAME,
8755 'destination-vserver': fake.VSERVER2,
8756 'destination-volume': fake.FLEXVOL_NAME_1
8757 },
8758 {'source-vserver': 'fake_vs_1',
8759 'source-volume': 'fake_vol_1',
8760 'destination-vserver': 'fake_vs_2',
8761 'destination-volume': 'fake_vol_2'
8762 }
8763 ]
8764 self.mock_object(vserver_client,
8765 'get_snapmirror_destinations',
8766 mock.Mock(return_value=snapmirror_info))
8767 self.assertRaises(
8768 exception.NetAppException,
8769 self.library.create_backup,
8770 self.context,
8771 fake.SHARE_INSTANCE,
8772 fake.SHARE_BACKUP,
8773 )
8775 def test_create_backup_bad_backup_config_negative(self):
8776 mock_src_client = mock.Mock()
8777 mock_des_client = mock.Mock()
8778 self._backup_mock_common_method_for_negative(mock_src_client,
8779 mock_des_client)
8780 fake_config = configuration.Configuration(
8781 driver.share_opts, config_group='backup_config')
8782 CONF.set_override("netapp_backup_vserver", None,
8783 group='backup_config')
8784 self.mock_object(data_motion,
8785 'get_backup_configuration',
8786 mock.Mock(return_value=fake_config))
8787 self.assertRaises(
8788 exception.BadConfigurationException,
8789 self.library.create_backup,
8790 self.context,
8791 fake.SHARE_INSTANCE,
8792 fake.SHARE_BACKUP,
8793 )
8795 def test_create_backup_when_cluster_are_not_peered_negative(self):
8796 mock_src_client = mock.Mock()
8797 mock_des_client = mock.Mock()
8798 self._backup_mock_common_method_for_negative(mock_src_client,
8799 mock_des_client)
8800 self.mock_object(self.client,
8801 'get_cluster_peers',
8802 mock.Mock(return_value=[]))
8803 self.mock_object(mock_src_client,
8804 'get_cluster_name',
8805 mock.Mock(return_value='fake_src_cluster'))
8807 self.assertRaises(
8808 exception.NetAppException,
8809 self.library.create_backup,
8810 self.context,
8811 fake.SHARE_INSTANCE,
8812 fake.SHARE_BACKUP,
8813 )
8815 def test_create_backup_when_des_vol_creation_fail_negative(self):
8816 mock_src_client = mock.Mock()
8817 mock_des_client = mock.Mock()
8818 self._backup_mock_common_method_for_negative(mock_src_client,
8819 mock_des_client)
8820 self.mock_object(self.library,
8821 '_get_volume_for_backup',
8822 mock.Mock(side_effect=exception.NetAppException))
8823 self.mock_object(self.library,
8824 '_delete_backup_vserver',
8825 mock.Mock(return_value=[]))
8826 self.assertRaises(
8827 exception.NetAppException,
8828 self.library.create_backup,
8829 self.context,
8830 fake.SHARE_INSTANCE,
8831 fake.SHARE_BACKUP,
8832 )
8834 def test_create_backup_when_vserver_not_peered(self):
8835 mock_src_client = mock.Mock()
8836 mock_des_client = mock.Mock()
8837 mock_cluster_client = mock.Mock()
8838 self._backup_mock_common_method_for_negative(mock_src_client,
8839 mock_des_client)
8840 self.mock_object(mock_cluster_client,
8841 'get_cluster_name',
8842 mock.Mock(return_value='fake_src_cluster'))
8843 self.mock_object(mock_src_client,
8844 'get_vserver_peers',
8845 mock.Mock(return_value=[]))
8846 share_instance = fake.SHARE_INSTANCE
8847 backup = fake.SHARE_BACKUP
8848 self.library.create_backup(self.context, share_instance, backup)
8850 def test_create_backup_when_policy_creation_failed_negative(self):
8851 mock_src_client = mock.Mock()
8852 mock_des_client = mock.Mock()
8853 self._backup_mock_common_method_for_negative(mock_src_client,
8854 mock_des_client)
8856 self.mock_object(mock_des_client,
8857 'create_snapmirror_policy',
8858 mock.Mock(side_effect=netapp_api.NaApiError))
8859 self.assertRaises(
8860 netapp_api.NaApiError,
8861 self.library.create_backup,
8862 self.context,
8863 fake.SHARE_INSTANCE,
8864 fake.SHARE_BACKUP,
8865 )
8867 def test_create_backup_when_duplicate_policy_created(self):
8868 mock_src_client = mock.Mock()
8869 mock_des_client = mock.Mock()
8870 self._backup_mock_common_method_for_negative(mock_src_client,
8871 mock_des_client)
8872 msg = 'policy with this name already exists'
8873 self.mock_object(mock_des_client,
8874 'create_snapmirror_policy',
8875 mock.Mock(side_effect=netapp_api.NaApiError(
8876 message=msg)))
8877 share_instance = fake.SHARE_INSTANCE
8878 backup = fake.SHARE_BACKUP
8879 self.library.create_backup(self.context, share_instance, backup)
8881 def test_create_backup_when_snapmirror_creation_failed_negative(self):
8882 mock_src_client = mock.Mock()
8883 mock_des_client = mock.Mock()
8884 self._backup_mock_common_method_for_negative(mock_src_client,
8885 mock_des_client)
8886 self.mock_object(mock_des_client,
8887 'create_snapmirror_vol',
8888 mock.Mock(side_effect=netapp_api.NaApiError))
8889 self.assertRaises(
8890 exception.NetAppException,
8891 self.library.create_backup,
8892 self.context,
8893 fake.SHARE_INSTANCE,
8894 fake.SHARE_BACKUP,
8895 )
8897 def test_create_backup_when_invalid_backup_type_negative(self):
8898 mock_src_client = mock.Mock()
8899 self.mock_object(self.library,
8900 '_get_vserver',
8901 mock.Mock(return_value=(fake.VSERVER1,
8902 mock_src_client)))
8903 self.mock_object(self.mock_dm_session,
8904 'get_backup_configuration',
8905 mock.Mock(
8906 side_effect=exception.BadConfigurationException,
8907 ))
8908 self.assertRaises(
8909 exception.BadConfigurationException,
8910 self.library.create_backup,
8911 self.context,
8912 fake.SHARE_INSTANCE,
8913 fake.SHARE_BACKUP,
8914 )
8916 def test_create_backup_when_invalid_backend_negative(self):
8917 mock_src_client = mock.Mock()
8918 self.mock_object(self.library,
8919 '_get_vserver',
8920 mock.Mock(return_value=(fake.VSERVER1,
8921 mock_src_client)))
8922 self.mock_object(data_motion,
8923 'get_backup_configuration',
8924 mock.Mock(return_value=_get_config()))
8926 self.mock_object(self.mock_dm_session,
8927 'get_backend_configuration',
8928 mock.Mock(
8929 side_effect=exception.BadConfigurationException,
8930 ))
8931 self.assertRaises(
8932 exception.BadConfigurationException,
8933 self.library.create_backup,
8934 self.context,
8935 fake.SHARE_INSTANCE,
8936 fake.SHARE_BACKUP,
8937 )
8939 def test_create_backup_continue_with_status_inprogress(self):
8940 vserver_client = mock.Mock()
8941 mock_dest_client = mock.Mock()
8942 self._backup_mock_common_method(mock_dest_client)
8943 self.mock_object(self.library,
8944 '_get_vserver',
8945 mock.Mock(return_value=(fake.VSERVER1,
8946 vserver_client)))
8947 snapmirror_info = [{'source-vserver': fake.VSERVER1,
8948 'source-volume': fake.FLEXVOL_NAME,
8949 'destination-vserver': fake.VSERVER2,
8950 'destination-volume': fake.FLEXVOL_NAME_1,
8951 'relationship-status': "inprogress",
8952 'last-transfer-type': "update",
8953 }]
8954 self.mock_object(mock_dest_client,
8955 'get_snapmirrors',
8956 mock.Mock(return_value=snapmirror_info))
8957 snap_list = ["snap1", "snap2", "snap3"]
8958 self.mock_object(self.library,
8959 '_get_des_volume_backup_snapshots',
8960 mock.Mock(return_value=snap_list))
8961 share_instance = fake.SHARE_INSTANCE
8962 backup = fake.SHARE_BACKUP
8963 self.library.create_backup_continue(self.context, share_instance,
8964 backup)
8966 def test_create_backup_continue_with_state_not_update(self):
8967 vserver_client = mock.Mock()
8968 mock_dest_client = mock.Mock()
8969 self._backup_mock_common_method(mock_dest_client)
8970 self.mock_object(self.library,
8971 '_get_vserver',
8972 mock.Mock(return_value=(fake.VSERVER1,
8973 vserver_client)))
8974 snapmirror_info = [{'source-vserver': fake.VSERVER1,
8975 'source-volume': fake.FLEXVOL_NAME,
8976 'destination-vserver': fake.VSERVER2,
8977 'destination-volume': fake.FLEXVOL_NAME_1,
8978 'relationship-status': "idle",
8979 'last-transfer-type': "initialize",
8980 }]
8981 self.mock_object(mock_dest_client,
8982 'get_snapmirrors',
8983 mock.Mock(return_value=snapmirror_info))
8984 snap_list = ["snap1", "snap2", "snap3"]
8985 self.mock_object(self.library,
8986 '_get_des_volume_backup_snapshots',
8987 mock.Mock(return_value=snap_list))
8988 share_instance = fake.SHARE_INSTANCE
8989 backup = fake.SHARE_BACKUP
8990 self.library.create_backup_continue(self.context, share_instance,
8991 backup)
8993 def test_create_backup_continue_snapmirror_none(self):
8994 vserver_client = mock.Mock()
8995 mock_dest_client = mock.Mock()
8996 self._backup_mock_common_method(mock_dest_client)
8997 self.mock_object(self.library,
8998 '_get_vserver',
8999 mock.Mock(return_value=(fake.VSERVER1,
9000 vserver_client)))
9001 self.mock_object(vserver_client,
9002 'get_snapmirror_destinations',
9003 mock.Mock(return_value=None))
9004 share_instance = fake.SHARE_INSTANCE
9005 backup = fake.SHARE_BACKUP
9006 self.library.create_backup_continue(self.context, share_instance,
9007 backup)
9009 def test_create_backup_continue_snapmirror_none_from_destination(self):
9010 vserver_client = mock.Mock()
9011 mock_dest_client = mock.Mock()
9012 self._backup_mock_common_method(mock_dest_client)
9013 self.mock_object(self.library,
9014 '_get_vserver',
9015 mock.Mock(return_value=(fake.VSERVER1,
9016 vserver_client)))
9017 self.mock_object(mock_dest_client,
9018 'get_snapmirrors',
9019 mock.Mock(return_value=None))
9020 share_instance = fake.SHARE_INSTANCE
9021 backup = fake.SHARE_BACKUP
9022 self.library.create_backup_continue(self.context, share_instance,
9023 backup)
9025 def test_create_backup_continue_des_vserver_vol_none_negative(self):
9026 vserver_client = mock.Mock()
9027 mock_des_vserver = mock.Mock()
9028 self._backup_mock_common_method(mock_des_vserver)
9029 self.mock_object(self.library,
9030 '_get_vserver',
9031 mock.Mock(return_value=(fake.VSERVER1,
9032 vserver_client)))
9033 snapmirror_info = [fake.SNAP_MIRROR_INFO]
9034 self.mock_object(vserver_client,
9035 'get_snapmirror_destinations',
9036 mock.Mock(return_value=snapmirror_info))
9037 self.mock_object(self.library,
9038 '_get_destination_vserver_and_vol',
9039 mock.Mock(return_value=(None, None)))
9040 self.assertRaises(
9041 exception.NetAppException,
9042 self.library.create_backup_continue,
9043 self.context,
9044 fake.SHARE_INSTANCE,
9045 fake.SHARE_BACKUP,
9046 )
9048 def test_create_backup_continue_snapshot_left_from_old_relationship(self):
9049 vserver_client = mock.Mock()
9050 mock_dest_client = mock.Mock()
9051 self._backup_mock_common_method(mock_dest_client)
9052 self.mock_object(self.library,
9053 '_get_vserver',
9054 mock.Mock(return_value=(fake.VSERVER1,
9055 vserver_client)))
9056 snapmirror_info = [fake.SNAP_MIRROR_INFO]
9057 self.mock_object(mock_dest_client,
9058 'get_snapmirrors',
9059 mock.Mock(return_value=snapmirror_info))
9060 snap_list = ["snap1", "snap2"]
9061 self.mock_object(self.library,
9062 '_get_des_volume_backup_snapshots',
9063 mock.Mock(return_value=snap_list))
9065 self.library._set_volume_has_backup_before(True)
9066 share_instance = fake.SHARE_INSTANCE
9067 backup = fake.SHARE_BACKUP
9068 self.library.create_backup_continue(self.context, share_instance,
9069 backup)
9070 self.library._set_volume_has_backup_before(False)
9072 def test_create_backup_continue_relationship_not_healthy_negative(self):
9073 vserver_client = mock.Mock()
9074 mock_dest_client = mock.Mock()
9075 self._backup_mock_common_method(mock_dest_client)
9076 self.mock_object(self.library,
9077 '_get_vserver',
9078 mock.Mock(return_value=(fake.VSERVER1,
9079 vserver_client)))
9080 snapmirror_info = [
9081 {
9082 'source-vserver': fake.VSERVER1,
9083 'source-volume': fake.FLEXVOL_NAME,
9084 'destination-vserver': fake.VSERVER2,
9085 'destination-volume': fake.FLEXVOL_NAME_1,
9086 'relationship-status': "idle",
9087 'last-transfer-type': "update",
9088 'is-healthy': "false",
9089 }
9090 ]
9091 self.mock_object(mock_dest_client,
9092 'get_snapmirrors',
9093 mock.Mock(return_value=snapmirror_info))
9094 self.assertRaises(
9095 exception.NetAppException,
9096 self.library.create_backup_continue,
9097 self.context,
9098 fake.SHARE_INSTANCE,
9099 fake.SHARE_BACKUP,
9100 )
9102 def test_restore_backup_with_vserver_volume_none(self):
9103 vserver_client = mock.Mock()
9104 self.mock_object(self.library,
9105 '_get_vserver',
9106 mock.Mock(return_value=(fake.VSERVER1,
9107 vserver_client)))
9108 self.mock_object(self.library,
9109 '_get_destination_vserver_and_vol',
9110 mock.Mock(return_value=(None, None)))
9111 self.assertRaises(
9112 exception.NetAppException,
9113 self.library.restore_backup,
9114 self.context,
9115 fake.SHARE_INSTANCE,
9116 fake.SHARE_BACKUP,
9117 )
9119 def test_restore_backup_continue_with_rst_relationship(self):
9120 vserver_client = mock.Mock()
9121 self.mock_object(self.library,
9122 '_get_vserver',
9123 mock.Mock(return_value=(fake.VSERVER1,
9124 vserver_client)))
9125 self.mock_object(vserver_client,
9126 'get_snapmirrors',
9127 mock.Mock(return_value=fake.SNAP_MIRROR_INFO))
9128 snap_list = ["restored_snap1", "snap2", "snap3"]
9129 self.mock_object(self.library,
9130 '_get_des_volume_backup_snapshots',
9131 mock.Mock(return_value=snap_list))
9132 share_instance = fake.SHARE_INSTANCE
9133 backup = fake.SHARE_BACKUP
9134 self.library.restore_backup_continue(self.context, backup,
9135 share_instance)
9137 def test_restore_backup_continue_restore_failed_negative(self):
9138 vserver_client = mock.Mock()
9139 self.mock_object(self.library,
9140 '_get_vserver',
9141 mock.Mock(return_value=(fake.VSERVER1,
9142 vserver_client)))
9143 self.mock_object(vserver_client,
9144 'get_snapmirrors',
9145 mock.Mock(return_value=[]))
9146 snap_list = ["restored_snap1", "snap2", "snap3"]
9147 self.mock_object(vserver_client,
9148 'list_volume_snapshots',
9149 mock.Mock(return_value=snap_list))
9150 self.mock_object(self.library,
9151 '_get_backup_snapshot_name',
9152 mock.Mock(return_value="restored_snap_test1"))
9153 self.assertRaises(
9154 exception.NetAppException,
9155 self.library.restore_backup_continue,
9156 self.context,
9157 fake.SHARE_INSTANCE,
9158 fake.SHARE_BACKUP,
9159 )
9161 def test_delete_backup_vserver_vol_none_negative(self):
9162 vserver_client = mock.Mock()
9163 self.mock_object(self.library,
9164 '_get_vserver',
9165 mock.Mock(return_value=(fake.VSERVER1,
9166 vserver_client)))
9167 self.mock_object(self.library,
9168 '_get_destination_vserver_and_vol',
9169 mock.Mock(return_value=(None, None)))
9170 self.mock_object(self.library,
9171 '_get_backend',
9172 mock.Mock(return_value=fake.BACKEND_NAME))
9173 share_instance = fake.SHARE_INSTANCE
9174 backup = fake.SHARE_BACKUP
9175 self.library.delete_backup(self.context, backup,
9176 share_instance)
9178 def test_delete_backup_snapshot_not_found_negative(self):
9179 vserver_client = mock.Mock()
9180 mock_dest_client = mock.Mock()
9181 self.mock_object(self.library,
9182 '_get_vserver',
9183 mock.Mock(return_value=(fake.VSERVER1,
9184 vserver_client)))
9185 self.mock_object(self.library,
9186 '_get_destination_vserver_and_vol',
9187 mock.Mock(return_value=(fake.VSERVER2,
9188 fake.FLEXVOL_NAME_1)))
9189 self.mock_object(self.library,
9190 '_get_backend',
9191 mock.Mock(return_value=fake.BACKEND_NAME))
9192 self.mock_object(self.library,
9193 '_get_des_volume_backup_snapshots',
9194 mock.Mock(side_effect=netapp_api.NaApiError))
9195 self.mock_object(self.library,
9196 '_get_api_client_for_backend',
9197 mock.Mock(return_value=mock_dest_client))
9198 share_instance = fake.SHARE_INSTANCE
9199 backup = fake.SHARE_BACKUP
9200 self.library.delete_backup(self.context, backup,
9201 share_instance)
9203 def test_delete_backup_cleanup_resource(self):
9204 vserver_client = mock.Mock()
9205 mock_des_client = mock.Mock()
9206 self._backup_mock_common_method(mock_des_client)
9207 self.mock_object(self.library,
9208 '_get_vserver',
9209 mock.Mock(return_value=(fake.VSERVER1,
9210 vserver_client)))
9211 self.mock_object(mock_des_client,
9212 'get_snapmirrors',
9213 mock.Mock(return_value=fake.SNAP_MIRROR_INFO))
9214 self.mock_object(self.library,
9215 '_get_des_volume_backup_snapshots',
9216 mock.Mock(return_value=['fake_snapshot']))
9217 share_instance = fake.SHARE_INSTANCE
9218 backup = fake.SHARE_BACKUP
9219 self.library.delete_backup(self.context, backup,
9220 share_instance)
9222 def test_delete_backup_snapshot_delete_fail_negative(self):
9223 vserver_client = mock.Mock()
9224 mock_des_client = mock.Mock()
9225 self._backup_mock_common_method(mock_des_client)
9226 self.mock_object(self.library,
9227 '_get_vserver',
9228 mock.Mock(return_value=(fake.VSERVER1,
9229 vserver_client)))
9230 self.mock_object(mock_des_client,
9231 'get_snapmirrors',
9232 mock.Mock(return_value=fake.SNAP_MIRROR_INFO))
9233 self.mock_object(self.library,
9234 '_get_des_volume_backup_snapshots',
9235 mock.Mock(return_value=['fake_snapshot1',
9236 'fake_snapshot2']))
9237 self.mock_object(mock_des_client,
9238 'get_snapshot',
9239 mock.Mock(side_effect=netapp_api.NaApiError))
9240 self.mock_object(self.library,
9241 '_is_snapshot_deleted',
9242 mock.Mock(return_value=False))
9243 self.assertRaises(
9244 exception.NetAppException,
9245 self.library.delete_backup,
9246 self.context,
9247 fake.SHARE_INSTANCE,
9248 fake.SHARE_BACKUP,
9249 )
9251 def test_delete_backup_snapshot_not_exist(self):
9252 vserver_client = mock.Mock()
9253 mock_des_client = mock.Mock()
9254 self._backup_mock_common_method(mock_des_client)
9255 self._backup_mock_common_method_for_negative(vserver_client,
9256 mock_des_client)
9257 self.mock_object(self.library,
9258 '_get_des_volume_backup_snapshots',
9259 mock.Mock(return_value=['fake_snapshot1',
9260 'fake_snapshot2']))
9261 self.mock_object(self.library,
9262 '_is_snapshot_deleted',
9263 mock.Mock(return_value=True))
9264 msg = "entry doesn't exist"
9265 self.mock_object(mock_des_client,
9266 'delete_snapshot',
9267 mock.Mock(side_effect=netapp_api.NaApiError(
9268 message=msg)))
9269 self.library.delete_backup(self.context, fake.SHARE_BACKUP,
9270 fake.SHARE_INSTANCE)
9272 def test__get_backup_progress_status(self):
9273 mock_dest_client = mock.Mock()
9274 vol_attr = {'name': 'fake_vol', 'size-used': '123454'}
9275 self.mock_object(mock_dest_client,
9276 'get_volume',
9277 mock.Mock(return_value=vol_attr))
9278 snapmirror_info = {'source-vserver': fake.VSERVER1,
9279 'source-volume': fake.FLEXVOL_NAME,
9280 'destination-vserver': fake.VSERVER2,
9281 'destination-volume': fake.FLEXVOL_NAME_1,
9282 'relationship-status': "idle",
9283 'last-transfer-size': '3456',
9284 }
9285 self.library._get_backup_progress_status(mock_dest_client,
9286 [snapmirror_info])
9288 def _backup_mock_common_method(self, mock_dest_client):
9289 self.mock_object(mock_dest_client,
9290 'get_cluster_name',
9291 mock.Mock(return_value=fake.CLUSTER_NAME))
9292 self.mock_object(self.library,
9293 '_get_backend_share_name',
9294 mock.Mock(return_value=fake.SHARE_NAME))
9295 self.mock_object(self.library,
9296 '_get_api_client_for_backend',
9297 mock.Mock(return_value=mock_dest_client))
9298 self.mock_object(data_motion,
9299 'get_backend_configuration',
9300 mock.Mock(return_value=_get_config()))
9301 self.mock_object(data_motion,
9302 'get_backup_configuration',
9303 mock.Mock(return_value=_get_config()))
9305 self.mock_object(self.library,
9306 '_get_destination_vserver_and_vol',
9307 mock.Mock(return_value=(fake.VSERVER2,
9308 fake.FLEXVOL_NAME)))
9309 self.mock_object(self.library,
9310 '_get_backend',
9311 mock.Mock(return_value=fake.BACKEND_NAME))
9313 def _backup_mock_common_method_for_negative(self,
9314 mock_src_client,
9315 mock_des_client):
9316 self.mock_object(self.library,
9317 '_get_vserver',
9318 mock.Mock(return_value=(fake.VSERVER1,
9319 mock_src_client)))
9320 self._backup_mock_common_method(mock_des_client)
9321 self.mock_object(mock_src_client,
9322 'get_snapmirror_destinations',
9323 mock.Mock(return_value=[]))
9324 vserver_peer_info = [{'vserver': fake.VSERVER1,
9325 'peer-vserver': fake.VSERVER2}]
9326 self.mock_object(mock_src_client,
9327 'get_vserver_peers',
9328 mock.Mock(return_value=vserver_peer_info))
9329 snap_list = ["snap1", "snap2", "snap3"]
9330 self.mock_object(mock_des_client,
9331 'list_volume_snapshots',
9332 mock.Mock(return_value=snap_list))
9334 def test_update_share_from_metadata(self):
9335 metadata = {
9336 "snapshot_policy": "daily",
9337 }
9339 share_instance = fake.SHARE_INSTANCE
9340 mock_update_volume_snapshot_policy = self.mock_object(
9341 self.library, 'update_volume_snapshot_policy')
9343 self.library.update_share_from_metadata(self.context, share_instance,
9344 metadata)
9346 mock_update_volume_snapshot_policy.assert_called_once_with(
9347 share_instance, "daily", share_server=None)
9349 def test_update_share_network_subnet_from_metadata(self):
9350 metadata = {
9351 "showmount": "true",
9352 }
9354 mock_update_showmount = self.mock_object(
9355 self.library, 'update_showmount')
9357 self.library.update_share_network_subnet_from_metadata(
9358 self.context,
9359 'fake_share_network',
9360 'fake_share_network_subnet',
9361 fake.SHARE_SERVER,
9362 metadata)
9364 mock_update_showmount.assert_called_once_with(
9365 "true", share_server=fake.SHARE_SERVER)
9367 def test__get_aggregate_snaplock_type_cluster_scope(self):
9368 self.library._have_cluster_creds = True
9369 self.mock_object(self.client,
9370 'get_aggregate',
9371 mock.Mock(return_value={
9372 'snaplock-type': 'compliance'
9373 }))
9374 result = self.library._get_aggregate_snaplock_type(fake.AGGREGATE)
9375 self.assertEqual(result, "compliance")
9377 def test__get_aggregate_snaplock_type_vserver_scope(self):
9378 self.library._have_cluster_creds = False
9379 self.mock_object(self.client,
9380 'get_vserver_aggr_snaplock_type',
9381 mock.Mock(return_value='enterprise'))
9382 result = self.library._get_aggregate_snaplock_type(fake.AGGREGATE)
9383 self.assertEqual(result, "enterprise")
9385 def test__is_snaplock_compatible_for_migration_for_unified_aggr(self):
9386 self.library._client.features.UNIFIED_AGGR = True
9387 result = self.library._is_snaplock_compatible_for_migration(
9388 fake.AGGREGATE,
9389 fake.AGGR_POOL_NAME
9390 )
9391 self.assertTrue(result)
9393 def test__is_snaplock_compatible_for_migration_for_non_snaplock(self):
9394 self.library._client.features.UNIFIED_AGGR = False
9395 self.library._client.features.SNAPLOCK = False
9397 result = self.library._is_snaplock_compatible_for_migration(
9398 fake.AGGREGATE,
9399 fake.AGGR_POOL_NAME
9400 )
9401 self.assertTrue(result)
9403 def test__is_snaplock_compatible_for_migration_non_unified_aggr(self):
9404 self.library._client.features.UNIFIED_AGGR = False
9405 self.library._client.features.SNAPLOCK = True
9406 result = self.library._is_snaplock_compatible_for_migration(
9407 fake.AGGREGATE,
9408 fake.AGGR_POOL_NAME
9409 )
9410 self.assertTrue(result)