Coverage for manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_data_motion.py: 100%
580 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 Alex Meade. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
15import copy
16import time
17from unittest import mock
19import ddt
20from oslo_config import cfg
22from manila import exception
23from manila.share import configuration
24from manila.share import driver
25from manila.share.drivers.netapp.dataontap.client import api as netapp_api
26from manila.share.drivers.netapp.dataontap.client import client_cmode
27from manila.share.drivers.netapp.dataontap.cluster_mode import data_motion
28from manila.share.drivers.netapp import options as na_opts
29from manila.share.drivers.netapp import utils as na_utils
30from manila.share import utils as share_utils
31from manila import test
32from manila.tests.share.drivers.netapp.dataontap import fakes as fake
33from manila.tests.share.drivers.netapp import fakes as na_fakes
36CONF = cfg.CONF
39@ddt.ddt
40class NetAppCDOTDataMotionTestCase(test.TestCase):
42 def setUp(self):
43 super(NetAppCDOTDataMotionTestCase, self).setUp()
44 self.backend = 'backend1'
45 self.force_rest_client = False
46 self.mock_cmode_client = self.mock_object(client_cmode,
47 "NetAppCmodeClient",
48 mock.Mock())
49 self.config = configuration.Configuration(driver.share_opts,
50 config_group=self.backend)
51 self.config.append_config_values(na_opts.netapp_cluster_opts)
52 self.config.append_config_values(na_opts.netapp_connection_opts)
53 self.config.append_config_values(na_opts.netapp_basicauth_opts)
54 self.config.append_config_values(na_opts.netapp_certificateauth_opts)
55 self.config.append_config_values(na_opts.netapp_transport_opts)
56 self.config.append_config_values(na_opts.netapp_support_opts)
57 self.config.append_config_values(na_opts.netapp_provisioning_opts)
58 self.config.append_config_values(na_opts.netapp_data_motion_opts)
59 CONF.set_override("share_backend_name", self.backend,
60 group=self.backend)
61 CONF.set_override("netapp_transport_type", "https",
62 group=self.backend)
63 CONF.set_override("netapp_login", "fake_user",
64 group=self.backend)
65 CONF.set_override("netapp_password", "fake_password",
66 group=self.backend)
67 CONF.set_override("netapp_server_hostname", "fake.hostname",
68 group=self.backend)
69 CONF.set_override("netapp_server_port", 8866,
70 group=self.backend)
71 CONF.set_override("netapp_ssl_cert_path", "/etc/ssl/certs",
72 group=self.backend)
73 CONF.set_override("netapp_private_key_file", "/fake_private_key.pem",
74 group=self.backend)
75 CONF.set_override("netapp_certificate_file", "/fake_cert.pem",
76 group=self.backend)
77 CONF.set_override("netapp_ca_certificate_file", "/fake_ca_cert.crt",
78 group=self.backend)
79 CONF.set_override("netapp_certificate_host_validation", False,
80 group=self.backend)
82 def test_get_client_for_backend(self):
83 self.mock_object(data_motion, "get_backend_configuration",
84 mock.Mock(return_value=self.config))
86 data_motion.get_client_for_backend(self.backend,
87 self.force_rest_client)
89 self.mock_cmode_client.assert_called_once_with(
90 hostname='fake.hostname', password='fake_password',
91 username='fake_user', transport_type='https', port=8866,
92 ssl_cert_path='/etc/ssl/certs', trace=mock.ANY, vserver=None,
93 private_key_file='/fake_private_key.pem',
94 certificate_file='/fake_cert.pem',
95 ca_certificate_file='/fake_ca_cert.crt',
96 certificate_host_validation=False)
98 def test_get_client_for_backend_with_vserver(self):
99 self.mock_object(data_motion, "get_backend_configuration",
100 mock.Mock(return_value=self.config))
102 CONF.set_override("netapp_vserver", 'fake_vserver',
103 group=self.backend)
105 data_motion.get_client_for_backend(self.backend)
107 self.mock_cmode_client.assert_called_once_with(
108 hostname='fake.hostname', password='fake_password',
109 username='fake_user', transport_type='https', port=8866,
110 ssl_cert_path='/etc/ssl/certs', trace=mock.ANY,
111 vserver='fake_vserver',
112 private_key_file='/fake_private_key.pem',
113 certificate_file='/fake_cert.pem',
114 ca_certificate_file='/fake_ca_cert.crt',
115 certificate_host_validation=False)
117 def test_get_client_for_host(self):
118 mock_extract_host = self.mock_object(
119 share_utils, 'extract_host',
120 mock.Mock(return_value=fake.BACKEND_NAME))
121 mock_get_client = self.mock_object(
122 data_motion, 'get_client_for_backend',
123 mock.Mock(return_value=self.mock_cmode_client))
125 returned_client = data_motion.get_client_for_host(
126 fake.HOST_NAME)
128 mock_extract_host.assert_called_once_with(
129 fake.HOST_NAME, level='backend_name')
130 mock_get_client.assert_called_once_with(fake.BACKEND_NAME)
131 self.assertEqual(returned_client, self.mock_cmode_client)
133 def test_get_config_for_backend(self):
134 self.mock_object(data_motion, "CONF")
136 CONF.set_override("netapp_vserver", 'fake_vserver',
137 group=self.backend)
139 CONF.set_override("driver_handles_share_servers", False,
140 group=self.backend)
142 config = data_motion.get_backend_configuration(self.backend)
144 self.assertEqual('fake_vserver', config.netapp_vserver)
146 def test_get_config_for_backend_different_backend_name(self):
147 self.mock_object(data_motion, "CONF")
148 CONF.set_override("netapp_vserver", 'fake_vserver',
149 group=self.backend)
150 CONF.set_override("share_backend_name", "fake_backend_name",
151 group=self.backend)
153 CONF.set_override("driver_handles_share_servers", False,
154 group=self.backend)
156 config = data_motion.get_backend_configuration(self.backend)
158 self.assertEqual('fake_vserver', config.netapp_vserver)
159 self.assertEqual('fake_backend_name', config.share_backend_name)
161 @ddt.data([], ['fake_backend1', 'fake_backend2'])
162 def test_get_config_for_backend_not_configured(self, conf_sections):
163 self.mock_object(data_motion, "CONF")
165 self.assertRaises(exception.BadConfigurationException,
166 data_motion.get_backend_configuration,
167 self.backend)
170@ddt.ddt
171class NetAppCDOTDataMotionSessionTestCase(test.TestCase):
173 def setUp(self):
174 super(NetAppCDOTDataMotionSessionTestCase, self).setUp()
176 self.sleep_patcher = mock.patch.object(time, 'sleep', lambda s: None)
177 self.sleep_patcher.start()
178 self.addCleanup(self.sleep_patcher.stop)
180 self.source_backend = 'backend1'
181 self.dest_backend = 'backend2'
183 config = configuration.Configuration(driver.share_opts,
184 config_group=self.source_backend)
185 config.append_config_values(na_opts.netapp_cluster_opts)
186 config.append_config_values(na_opts.netapp_connection_opts)
187 config.append_config_values(na_opts.netapp_basicauth_opts)
188 config.append_config_values(na_opts.netapp_certificateauth_opts)
189 config.append_config_values(na_opts.netapp_transport_opts)
190 config.append_config_values(na_opts.netapp_support_opts)
191 config.append_config_values(na_opts.netapp_provisioning_opts)
192 config.append_config_values(na_opts.netapp_data_motion_opts)
194 self.mock_object(data_motion, "get_backend_configuration",
195 mock.Mock(return_value=config))
197 self.mock_cmode_client = self.mock_object(client_cmode,
198 "NetAppCmodeClient",
199 mock.Mock())
200 self.dm_session = data_motion.DataMotionSession()
201 self.fake_src_share = copy.deepcopy(fake.SHARE)
202 self.fake_src_share_server = copy.deepcopy(fake.SHARE_SERVER)
203 self.source_vserver = 'source_vserver'
204 self.source_backend_name = (
205 self.fake_src_share_server['host'].split('@')[1])
206 self.fake_src_share_server['backend_details']['vserver_name'] = (
207 self.source_vserver
208 )
209 self.fake_src_share['share_server'] = self.fake_src_share_server
210 self.fake_src_share['id'] = 'c02d497a-236c-4852-812a-0d39373e312a'
211 self.fake_src_vol_name = 'share_c02d497a_236c_4852_812a_0d39373e312a'
212 self.fake_dest_share = copy.deepcopy(fake.SHARE)
213 self.fake_dest_share_server = copy.deepcopy(fake.SHARE_SERVER_2)
214 self.dest_vserver = 'dest_vserver'
215 self.dest_backend_name = (
216 self.fake_dest_share_server['host'].split('@')[1])
217 self.fake_dest_share_server['backend_details']['vserver_name'] = (
218 self.dest_vserver
219 )
220 self.fake_dest_share['share_server'] = self.fake_dest_share_server
221 self.fake_dest_share['id'] = '34fbaf57-745d-460f-8270-3378c2945e30'
222 self.fake_dest_vol_name = 'share_34fbaf57_745d_460f_8270_3378c2945e30'
224 self.mock_src_client = mock.Mock()
225 self.mock_dest_client = mock.Mock()
226 self.mock_object(data_motion, 'get_client_for_backend',
227 mock.Mock(side_effect=[self.mock_dest_client,
228 self.mock_src_client]))
229 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
230 mock.Mock(side_effect=[
231 (self.mock_src_client, self.source_vserver),
232 (self.mock_dest_client, self.dest_vserver)]))
234 def test_get_client_and_vserver_name(self):
235 dm_session = data_motion.DataMotionSession()
236 client = mock.Mock()
237 self.mock_object(data_motion, 'get_client_for_backend',
238 mock.Mock(return_value=client))
240 result = dm_session.get_client_and_vserver_name(fake.SHARE_SERVER)
241 expected = (client,
242 fake.SHARE_SERVER['backend_details']['vserver_name'])
244 self.assertEqual(expected, result)
245 data_motion.get_client_for_backend.assert_called_once_with(
246 fake.BACKEND_NAME, vserver_name=fake.VSERVER1
247 )
249 @ddt.data(True, False)
250 def test_create_snapmirror_mount(self, mount):
251 mock_dest_client = mock.Mock()
252 self.mock_object(data_motion, 'get_client_for_backend',
253 mock.Mock(return_value=mock_dest_client))
254 self.mock_object(self.dm_session, 'wait_for_mount_replica')
255 mock_backend_config = na_fakes.create_configuration()
256 mock_backend_config.netapp_mount_replica_timeout = 30
257 self.mock_object(data_motion, 'get_backend_configuration',
258 mock.Mock(return_value=mock_backend_config))
260 self.dm_session.create_snapmirror(self.fake_src_share,
261 self.fake_dest_share,
262 'data_protection', mount=mount)
264 mock_dest_client.create_snapmirror_vol.assert_called_once_with(
265 mock.ANY, self.fake_src_vol_name, mock.ANY,
266 self.fake_dest_vol_name, 'data_protection', schedule='hourly'
267 )
268 mock_dest_client.initialize_snapmirror_vol.assert_called_once_with(
269 mock.ANY, self.fake_src_vol_name, mock.ANY,
270 self.fake_dest_vol_name
271 )
272 if mount:
273 self.dm_session.wait_for_mount_replica.assert_called_once_with(
274 mock_dest_client, self.fake_dest_vol_name, timeout=30)
275 else:
276 self.dm_session.wait_for_mount_replica.assert_not_called()
278 def test_create_snapmirror_svm(self):
279 mock_dest_client = mock.Mock()
280 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
281 mock.Mock(return_value=(mock_dest_client,
282 self.dest_vserver)))
283 self.mock_object(self.dm_session, 'get_vserver_from_share_server',
284 mock.Mock(return_value=self.source_vserver))
285 policy_name = 'policy_' + self.dest_vserver
286 get_snapmirro_policy_name = self.mock_object(
287 self.dm_session, '_get_backend_snapmirror_policy_name_svm',
288 mock.Mock(return_value=policy_name))
290 self.dm_session.create_snapmirror_svm(self.fake_src_share_server,
291 self.fake_dest_share_server)
293 self.dm_session.get_client_and_vserver_name.assert_called_once_with(
294 self.fake_dest_share_server
295 )
296 self.dm_session.get_vserver_from_share_server.assert_called_once_with(
297 self.fake_src_share_server
298 )
299 get_snapmirro_policy_name.assert_called_once_with(
300 self.fake_dest_share_server['id'], self.dest_backend_name
301 )
302 mock_dest_client.create_snapmirror_policy.assert_called_once_with(
303 policy_name
304 )
305 mock_dest_client.create_snapmirror_svm.assert_called_once_with(
306 self.source_vserver, self.dest_vserver,
307 policy=policy_name, schedule='hourly'
308 )
309 mock_dest_client.initialize_snapmirror_svm.assert_called_once_with(
310 self.source_vserver, self.dest_vserver
311 )
313 def test_delete_snapmirror(self):
314 mock_src_client = mock.Mock()
315 mock_dest_client = mock.Mock()
316 self.mock_object(data_motion, 'get_client_for_backend',
317 mock.Mock(side_effect=[mock_dest_client,
318 mock_src_client]))
319 mock_backend_config = na_fakes.create_configuration()
320 mock_backend_config.netapp_snapmirror_release_timeout = 30
321 self.mock_object(data_motion, 'get_backend_configuration',
322 mock.Mock(return_value=mock_backend_config))
323 mock_wait_for_snapmirror_release_vol = self.mock_object(
324 self.dm_session, 'wait_for_snapmirror_release_vol')
326 self.dm_session.delete_snapmirror(self.fake_src_share,
327 self.fake_dest_share)
329 mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
330 mock.ANY, self.fake_src_vol_name, mock.ANY,
331 self.fake_dest_vol_name, clear_checkpoint=False
332 )
333 mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
334 mock.ANY, self.fake_src_vol_name, mock.ANY,
335 self.fake_dest_vol_name
336 )
337 mock_wait_for_snapmirror_release_vol.assert_called_once_with(
338 self.source_vserver, self.dest_vserver, self.fake_src_vol_name,
339 self.fake_dest_vol_name, False, mock_src_client,
340 timeout=30
341 )
343 @ddt.data(True, False)
344 def test_delete_snapmirror_svm(self, call_release):
345 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
346 mock_backend_config = na_fakes.create_configuration()
347 mock_backend_config.netapp_snapmirror_release_timeout = 30
348 self.mock_object(data_motion, 'get_backend_configuration',
349 mock.Mock(return_value=mock_backend_config))
351 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
352 self.fake_dest_share_server,
353 release=call_release)
355 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
356 self.source_vserver, self.dest_vserver
357 )
358 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
359 self.source_vserver, self.dest_vserver
360 )
361 if call_release:
362 release_mock = self.dm_session.wait_for_snapmirror_release_svm
363 release_mock.assert_called_once_with(
364 self.source_vserver, self.dest_vserver, self.mock_src_client,
365 timeout=mock_backend_config.netapp_snapmirror_release_timeout
366 )
368 def test_delete_snapmirror_does_not_exist(self):
369 """Ensure delete succeeds when the snapmirror does not exist."""
370 mock_src_client = mock.Mock()
371 mock_dest_client = mock.Mock()
372 mock_dest_client.abort_snapmirror_vol.side_effect = (
373 netapp_api.NaApiError(code=netapp_api.EAPIERROR))
374 self.mock_object(data_motion, 'get_client_for_backend',
375 mock.Mock(side_effect=[mock_dest_client,
376 mock_src_client]))
377 mock_backend_config = na_fakes.create_configuration()
378 mock_backend_config.netapp_snapmirror_release_timeout = 30
379 self.mock_object(data_motion, 'get_backend_configuration',
380 mock.Mock(return_value=mock_backend_config))
381 mock_wait_for_snapmirror_release_vol = self.mock_object(
382 self.dm_session, 'wait_for_snapmirror_release_vol')
384 self.dm_session.delete_snapmirror(self.fake_src_share,
385 self.fake_dest_share)
387 mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
388 mock.ANY, self.fake_src_vol_name, mock.ANY,
389 self.fake_dest_vol_name, clear_checkpoint=False
390 )
391 mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
392 mock.ANY, self.fake_src_vol_name, mock.ANY,
393 self.fake_dest_vol_name
394 )
395 mock_wait_for_snapmirror_release_vol.assert_called_once_with(
396 self.source_vserver, self.dest_vserver, self.fake_src_vol_name,
397 self.fake_dest_vol_name, False, mock_src_client,
398 timeout=30
399 )
401 def test_delete_snapmirror_svm_does_not_exist(self):
402 """Ensure delete succeeds when the snapmirror does not exist."""
403 self.mock_dest_client.abort_snapmirror_svm.side_effect = (
404 netapp_api.NaApiError(code=netapp_api.EAPIERROR))
405 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
406 mock_backend_config = na_fakes.create_configuration()
407 mock_backend_config.netapp_snapmirror_release_timeout = 30
408 self.mock_object(data_motion, 'get_backend_configuration',
409 mock.Mock(return_value=mock_backend_config))
411 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
412 self.fake_dest_share_server)
414 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
415 self.source_vserver, self.dest_vserver
416 )
417 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
418 self.source_vserver, self.dest_vserver
419 )
420 release_mock = self.dm_session.wait_for_snapmirror_release_svm
421 release_mock.assert_called_once_with(
422 self.source_vserver, self.dest_vserver, self.mock_src_client,
423 timeout=mock_backend_config.netapp_snapmirror_release_timeout
424 )
426 def test_delete_snapmirror_error_deleting(self):
427 """Ensure delete succeeds when the snapmirror does not exist."""
428 mock_src_client = mock.Mock()
429 mock_dest_client = mock.Mock()
430 mock_dest_client.delete_snapmirror_vol.side_effect = (
431 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT))
432 self.mock_object(data_motion, 'get_client_for_backend',
433 mock.Mock(side_effect=[mock_dest_client,
434 mock_src_client]))
435 mock_backend_config = na_fakes.create_configuration()
436 mock_backend_config.netapp_snapmirror_release_timeout = 30
437 self.mock_object(data_motion, 'get_backend_configuration',
438 mock.Mock(return_value=mock_backend_config))
439 mock_wait_for_snapmirror_release_vol = self.mock_object(
440 self.dm_session, 'wait_for_snapmirror_release_vol')
442 self.dm_session.delete_snapmirror(self.fake_src_share,
443 self.fake_dest_share)
445 mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
446 mock.ANY, self.fake_src_vol_name, mock.ANY,
447 self.fake_dest_vol_name, clear_checkpoint=False
448 )
449 mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
450 mock.ANY, self.fake_src_vol_name, mock.ANY,
451 self.fake_dest_vol_name
452 )
453 mock_wait_for_snapmirror_release_vol.assert_called_once_with(
454 self.source_vserver, self.dest_vserver, self.fake_src_vol_name,
455 self.fake_dest_vol_name, False, mock_src_client,
456 timeout=30
457 )
459 def test_delete_snapmirror_svm_error_deleting(self):
460 """Ensure delete succeeds when the snapmirror does not exist."""
461 self.mock_dest_client.delete_snapmirror_svm.side_effect = (
462 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT))
463 self.mock_object(self.dm_session, 'wait_for_snapmirror_release_svm')
464 mock_backend_config = na_fakes.create_configuration()
465 mock_backend_config.netapp_snapmirror_release_timeout = 30
466 self.mock_object(data_motion, 'get_backend_configuration',
467 mock.Mock(return_value=mock_backend_config))
469 self.dm_session.delete_snapmirror_svm(self.fake_src_share_server,
470 self.fake_dest_share_server)
472 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
473 self.source_vserver, self.dest_vserver
474 )
475 self.mock_dest_client.delete_snapmirror_svm.assert_called_once_with(
476 self.source_vserver, self.dest_vserver
477 )
478 release_mock = self.dm_session.wait_for_snapmirror_release_svm
479 release_mock.assert_called_once_with(
480 self.source_vserver, self.dest_vserver, self.mock_src_client,
481 timeout=mock_backend_config.netapp_snapmirror_release_timeout
482 )
484 def test_delete_snapmirror_without_release(self):
485 mock_src_client = mock.Mock()
486 mock_dest_client = mock.Mock()
487 self.mock_object(data_motion, 'get_client_for_backend',
488 mock.Mock(side_effect=[mock_dest_client,
489 mock_src_client]))
490 mock_wait_for_snapmirror_release_vol = self.mock_object(
491 self.dm_session, 'wait_for_snapmirror_release_vol')
493 self.dm_session.delete_snapmirror(self.fake_src_share,
494 self.fake_dest_share,
495 release=False)
497 mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
498 mock.ANY, self.fake_src_vol_name, mock.ANY,
499 self.fake_dest_vol_name, clear_checkpoint=False
500 )
501 mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
502 mock.ANY, self.fake_src_vol_name, mock.ANY,
503 self.fake_dest_vol_name
504 )
505 self.assertFalse(mock_wait_for_snapmirror_release_vol.called)
507 def test_delete_snapmirror_source_unreachable(self):
508 mock_dest_client = mock.Mock()
509 self.mock_object(data_motion, 'get_client_for_backend',
510 mock.Mock(side_effect=[mock_dest_client,
511 Exception]))
512 mock_wait_for_snapmirror_release_vol = self.mock_object(
513 self.dm_session, 'wait_for_snapmirror_release_vol')
515 self.dm_session.delete_snapmirror(self.fake_src_share,
516 self.fake_dest_share)
518 mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
519 mock.ANY, self.fake_src_vol_name, mock.ANY,
520 self.fake_dest_vol_name, clear_checkpoint=False
521 )
522 mock_dest_client.delete_snapmirror_vol.assert_called_once_with(
523 mock.ANY, self.fake_src_vol_name, mock.ANY,
524 self.fake_dest_vol_name
525 )
526 self.assertFalse(mock_wait_for_snapmirror_release_vol.called)
528 def test_break_snapmirror(self):
529 self.mock_object(self.dm_session, 'quiesce_then_abort')
531 self.dm_session.break_snapmirror(self.fake_src_share,
532 self.fake_dest_share)
534 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
535 self.source_vserver, self.fake_src_vol_name,
536 self.dest_vserver, self.fake_dest_vol_name)
538 self.dm_session.quiesce_then_abort.assert_called_once_with(
539 self.fake_src_share, self.fake_dest_share,
540 quiesce_wait_time=None)
542 self.mock_dest_client.mount_volume.assert_called_once_with(
543 self.fake_dest_vol_name)
545 def test_break_snapmirror_no_mount(self):
546 self.mock_object(self.dm_session, 'quiesce_then_abort')
548 self.dm_session.break_snapmirror(self.fake_src_share,
549 self.fake_dest_share,
550 mount=False)
552 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
553 self.source_vserver, self.fake_src_vol_name,
554 self.dest_vserver, self.fake_dest_vol_name)
556 self.dm_session.quiesce_then_abort.assert_called_once_with(
557 self.fake_src_share, self.fake_dest_share,
558 quiesce_wait_time=None)
560 self.assertFalse(self.mock_dest_client.mount_volume.called)
562 def test_break_snapmirror_wait_for_quiesced(self):
563 self.mock_object(self.dm_session, 'quiesce_then_abort')
565 self.dm_session.break_snapmirror(self.fake_src_share,
566 self.fake_dest_share)
568 self.dm_session.quiesce_then_abort.assert_called_once_with(
569 self.fake_src_share, self.fake_dest_share,
570 quiesce_wait_time=None)
572 self.mock_dest_client.break_snapmirror_vol.assert_called_once_with(
573 self.source_vserver, self.fake_src_vol_name,
574 self.dest_vserver, self.fake_dest_vol_name)
576 self.mock_dest_client.mount_volume.assert_called_once_with(
577 self.fake_dest_vol_name)
579 @ddt.data(None, 2, 30)
580 def test_quiesce_then_abort_wait_time(self, wait_time):
581 self.mock_object(time, 'sleep')
582 mock_get_snapmirrors = mock.Mock(
583 return_value=[{'relationship-status': "transferring"}])
584 self.mock_object(self.mock_dest_client, 'get_snapmirrors',
585 mock_get_snapmirrors)
586 mock_backend_config = na_fakes.create_configuration()
587 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10
588 self.mock_object(data_motion, 'get_backend_configuration',
589 mock.Mock(return_value=mock_backend_config))
591 self.dm_session.quiesce_then_abort(self.fake_src_share,
592 self.fake_dest_share,
593 quiesce_wait_time=wait_time)
595 self.mock_dest_client.get_snapmirrors.assert_called_with(
596 source_vserver=self.source_vserver,
597 dest_vserver=self.dest_vserver,
598 source_volume=self.fake_src_vol_name,
599 dest_volume=self.fake_dest_vol_name,
600 desired_attributes=['relationship-status', 'mirror-state']
601 )
603 call_count = self.mock_dest_client.get_snapmirrors.call_count
604 if wait_time:
605 if wait_time > 5:
606 self.assertEqual(wait_time / 5, call_count)
607 else:
608 self.assertEqual(1, call_count)
609 else:
610 self.assertEqual(2, call_count)
612 def test_quiesce_then_abort_timeout(self):
613 self.mock_object(time, 'sleep')
614 mock_get_snapmirrors = mock.Mock(
615 return_value=[{'relationship-status': "transferring"}])
616 self.mock_object(self.mock_dest_client, 'get_snapmirrors',
617 mock_get_snapmirrors)
618 mock_backend_config = na_fakes.create_configuration()
619 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10
620 self.mock_object(data_motion, 'get_backend_configuration',
621 mock.Mock(return_value=mock_backend_config))
623 self.dm_session.quiesce_then_abort(self.fake_src_share,
624 self.fake_dest_share)
626 self.mock_dest_client.get_snapmirrors.assert_called_with(
627 source_vserver=self.source_vserver,
628 dest_vserver=self.dest_vserver,
629 source_volume=self.fake_src_vol_name,
630 dest_volume=self.fake_dest_vol_name,
631 desired_attributes=['relationship-status', 'mirror-state']
632 )
633 self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count)
635 self.mock_dest_client.quiesce_snapmirror_vol.assert_called_with(
636 self.source_vserver, self.fake_src_vol_name,
637 self.dest_vserver, self.fake_dest_vol_name)
639 self.mock_dest_client.abort_snapmirror_vol.assert_called_once_with(
640 self.source_vserver, self.fake_src_vol_name,
641 self.dest_vserver, self.fake_dest_vol_name,
642 clear_checkpoint=False
643 )
645 def test_quiesce_then_abort_svm_timeout(self):
646 self.mock_object(time, 'sleep')
647 mock_get_snapmirrors = mock.Mock(
648 return_value=[{'relationship-status': "transferring"}])
649 self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm',
650 mock_get_snapmirrors)
651 mock_backend_config = na_fakes.create_configuration()
652 mock_backend_config.netapp_snapmirror_quiesce_timeout = 10
653 self.mock_object(data_motion, 'get_backend_configuration',
654 mock.Mock(return_value=mock_backend_config))
656 self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server,
657 self.fake_dest_share_server)
659 self.mock_dest_client.get_snapmirrors_svm.assert_called_with(
660 source_vserver=self.source_vserver,
661 dest_vserver=self.dest_vserver,
662 desired_attributes=['relationship-status', 'mirror-state']
663 )
664 self.assertEqual(2,
665 self.mock_dest_client.get_snapmirrors_svm.call_count)
667 self.mock_dest_client.quiesce_snapmirror_svm.assert_called_with(
668 self.source_vserver, self.dest_vserver)
670 self.mock_dest_client.abort_snapmirror_svm.assert_called_once_with(
671 self.source_vserver, self.dest_vserver,
672 clear_checkpoint=False
673 )
675 def test_quiesce_then_abort_wait_for_quiesced(self):
676 self.mock_object(time, 'sleep')
677 self.mock_object(self.mock_dest_client, 'get_snapmirrors',
678 mock.Mock(side_effect=[
679 [{'relationship-status': "transferring"}],
680 [{'relationship-status': "quiesced"}]]))
682 self.dm_session.quiesce_then_abort(self.fake_src_share,
683 self.fake_dest_share)
685 self.mock_dest_client.get_snapmirrors.assert_called_with(
686 source_vserver=self.source_vserver,
687 dest_vserver=self.dest_vserver,
688 source_volume=self.fake_src_vol_name,
689 dest_volume=self.fake_dest_vol_name,
690 desired_attributes=['relationship-status', 'mirror-state']
691 )
692 self.assertEqual(2, self.mock_dest_client.get_snapmirrors.call_count)
694 self.mock_dest_client.quiesce_snapmirror_vol.assert_called_once_with(
695 self.source_vserver, self.fake_src_vol_name,
696 self.dest_vserver, self.fake_dest_vol_name)
698 def test_quiesce_then_abort_svm_wait_for_quiesced(self):
699 self.mock_object(time, 'sleep')
700 self.mock_object(self.mock_dest_client, 'get_snapmirrors_svm',
701 mock.Mock(side_effect=[
702 [{'relationship-status': "transferring"}],
703 [{'relationship-status': "quiesced"}]]))
705 self.dm_session.quiesce_then_abort_svm(self.fake_src_share_server,
706 self.fake_dest_share_server)
708 self.mock_dest_client.get_snapmirrors_svm.assert_called_with(
709 source_vserver=self.source_vserver,
710 dest_vserver=self.dest_vserver,
711 desired_attributes=['relationship-status', 'mirror-state']
712 )
713 self.assertEqual(2,
714 self.mock_dest_client.get_snapmirrors_svm.call_count)
716 self.mock_dest_client.quiesce_snapmirror_svm.assert_called_once_with(
717 self.source_vserver, self.dest_vserver)
719 def test_resync_snapmirror(self):
720 self.dm_session.resync_snapmirror(self.fake_src_share,
721 self.fake_dest_share)
723 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
724 self.source_vserver, self.fake_src_vol_name,
725 self.dest_vserver, self.fake_dest_vol_name)
727 def test_change_snapmirror_source(self):
728 fake_new_src_share = copy.deepcopy(fake.SHARE)
729 fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a'
730 fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a'
731 mock_new_src_client = mock.Mock()
732 self.mock_object(self.dm_session, 'delete_snapmirror')
733 self.mock_object(data_motion, 'get_client_for_backend',
734 mock.Mock(side_effect=[self.mock_dest_client,
735 self.mock_src_client,
736 self.mock_dest_client,
737 mock_new_src_client]))
738 self.mock_object(na_utils, 'get_relationship_type',
739 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE))
741 self.dm_session.change_snapmirror_source(
742 self.fake_dest_share, self.fake_src_share, fake_new_src_share,
743 [self.fake_dest_share, self.fake_src_share, fake_new_src_share])
745 self.assertFalse(self.mock_src_client.release_snapmirror_vol.called)
747 self.assertEqual(4, self.dm_session.delete_snapmirror.call_count)
748 self.dm_session.delete_snapmirror.assert_called_with(
749 mock.ANY, mock.ANY, release=False, relationship_info_only=False
750 )
752 na_utils.get_relationship_type.assert_called_once_with(False)
753 self.mock_dest_client.create_snapmirror_vol.assert_called_once_with(
754 mock.ANY, fake_new_src_share_name, mock.ANY,
755 self.fake_dest_vol_name, na_utils.DATA_PROTECTION_TYPE,
756 schedule='hourly'
757 )
759 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
760 mock.ANY, fake_new_src_share_name, mock.ANY,
761 self.fake_dest_vol_name
762 )
764 def test_change_snapmirror_source_dhss_true(self):
765 fake_new_src_share = copy.deepcopy(self.fake_src_share)
766 fake_new_src_share['id'] = 'd02d497a-236c-4852-812a-0d39373e312a'
767 fake_new_src_share_name = 'share_d02d497a_236c_4852_812a_0d39373e312a'
768 fake_new_src_share_server = fake_new_src_share['share_server']
769 fake_new_src_ss_name = (
770 fake_new_src_share_server['backend_details']['vserver_name'])
771 self.mock_object(self.dm_session, 'delete_snapmirror')
772 self.mock_object(data_motion, 'get_client_for_backend',
773 mock.Mock(side_effect=[self.mock_dest_client,
774 self.mock_src_client]))
775 mock_backend_config = na_fakes.create_configuration()
776 mock_backend_config.driver_handles_share_servers = True
777 self.mock_object(data_motion, 'get_backend_configuration',
778 mock.Mock(return_value=mock_backend_config))
779 self.mock_object(self.mock_dest_client, 'get_vserver_peers',
780 mock.Mock(return_value=[]))
781 peer_cluster_name = 'new_src_cluster_name'
782 self.mock_object(self.mock_src_client, 'get_cluster_name',
783 mock.Mock(return_value=peer_cluster_name))
784 self.mock_object(na_utils, 'get_relationship_type',
785 mock.Mock(return_value=na_utils.DATA_PROTECTION_TYPE))
787 self.dm_session.change_snapmirror_source(
788 self.fake_dest_share, self.fake_src_share, fake_new_src_share,
789 [self.fake_dest_share, self.fake_src_share, fake_new_src_share])
791 self.assertEqual(4, self.dm_session.delete_snapmirror.call_count)
793 self.mock_dest_client.get_vserver_peers.assert_called_once_with(
794 self.dest_vserver, fake_new_src_ss_name
795 )
796 self.assertTrue(self.mock_src_client.get_cluster_name.called)
797 self.mock_dest_client.create_vserver_peer.assert_called_once_with(
798 self.dest_vserver, fake_new_src_ss_name,
799 peer_cluster_name=peer_cluster_name
800 )
801 self.mock_src_client.accept_vserver_peer.assert_called_once_with(
802 fake_new_src_ss_name, self.dest_vserver
803 )
804 na_utils.get_relationship_type.assert_called_once_with(False)
805 self.dm_session.delete_snapmirror.assert_called_with(
806 mock.ANY, mock.ANY, release=False, relationship_info_only=False
807 )
808 self.mock_dest_client.create_snapmirror_vol.assert_called_once_with(
809 mock.ANY, fake_new_src_share_name, mock.ANY,
810 self.fake_dest_vol_name, na_utils.DATA_PROTECTION_TYPE,
811 schedule='hourly'
812 )
813 self.mock_dest_client.resync_snapmirror_vol.assert_called_once_with(
814 mock.ANY, fake_new_src_share_name, mock.ANY,
815 self.fake_dest_vol_name
816 )
818 def test_get_snapmirrors(self):
819 self.mock_object(self.mock_dest_client, 'get_snapmirrors')
821 self.dm_session.get_snapmirrors(self.fake_src_share,
822 self.fake_dest_share)
824 self.mock_dest_client.get_snapmirrors.assert_called_with(
825 source_vserver=self.source_vserver,
826 dest_vserver=self.dest_vserver,
827 source_volume=self.fake_src_vol_name,
828 dest_volume=self.fake_dest_vol_name,
829 desired_attributes=['relationship-status',
830 'mirror-state',
831 'schedule',
832 'source-vserver',
833 'source-volume',
834 'last-transfer-end-timestamp',
835 'last-transfer-size',
836 'last-transfer-error']
837 )
838 self.assertEqual(1, self.mock_dest_client.get_snapmirrors.call_count)
840 def test_get_snapmirrors_svm(self):
841 mock_dest_client = mock.Mock()
842 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
843 mock.Mock(return_value=(mock_dest_client,
844 self.dest_vserver)))
845 self.mock_object(mock_dest_client, 'get_snapmirrors_svm')
847 self.dm_session.get_snapmirrors_svm(self.fake_src_share_server,
848 self.fake_dest_share_server)
850 mock_dest_client.get_snapmirrors_svm.assert_called_with(
851 source_vserver=self.source_vserver,
852 dest_vserver=self.dest_vserver,
853 desired_attributes=['relationship-status',
854 'mirror-state',
855 'last-transfer-end-timestamp']
856 )
857 self.assertEqual(1, mock_dest_client.get_snapmirrors_svm.call_count)
859 def test_get_snapmirror_destinations_svm(self):
860 mock_dest_client = mock.Mock()
861 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
862 mock.Mock(return_value=(mock_dest_client,
863 self.dest_vserver)))
864 self.mock_object(mock_dest_client, 'get_snapmirror_destinations_svm')
866 self.dm_session.get_snapmirror_destinations_svm(
867 self.fake_src_share_server, self.fake_dest_share_server)
869 mock_dest_client.get_snapmirror_destinations_svm.assert_called_with(
870 source_vserver=self.source_vserver,
871 dest_vserver=self.dest_vserver,
872 )
873 self.assertEqual(1, mock_dest_client.get_snapmirror_destinations_svm
874 .call_count)
876 def test_update_snapmirror(self):
877 self.mock_object(self.mock_dest_client, 'get_snapmirrors')
879 self.dm_session.update_snapmirror(self.fake_src_share,
880 self.fake_dest_share)
882 self.mock_dest_client.update_snapmirror_vol.assert_called_once_with(
883 self.source_vserver, self.fake_src_vol_name,
884 self.dest_vserver, self.fake_dest_vol_name)
886 def test_update_snapmirror_svm(self):
887 mock_dest_client = mock.Mock()
888 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
889 mock.Mock(return_value=(mock_dest_client,
890 self.dest_vserver)))
892 self.dm_session.update_snapmirror_svm(self.fake_src_share_server,
893 self.fake_dest_share_server)
895 mock_dest_client.update_snapmirror_svm.assert_called_once_with(
896 self.source_vserver, self.dest_vserver)
898 def test_abort_and_break_snapmirror_svm(self):
899 mock_dest_client = mock.Mock()
900 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
901 mock.Mock(return_value=(mock_dest_client,
902 self.dest_vserver)))
903 self.mock_object(self.dm_session, 'quiesce_then_abort_svm')
905 self.dm_session.quiesce_and_break_snapmirror_svm(
906 self.fake_src_share_server, self.fake_dest_share_server
907 )
909 self.dm_session.get_client_and_vserver_name.assert_called_once_with(
910 self.fake_dest_share_server
911 )
912 self.dm_session.quiesce_then_abort_svm.assert_called_once_with(
913 self.fake_src_share_server, self.fake_dest_share_server
914 )
915 mock_dest_client.break_snapmirror_svm(self.source_vserver,
916 self.dest_vserver)
918 @ddt.data({'snapmirrors': ['fake_snapmirror'],
919 'vserver_subtype': 'default'},
920 {'snapmirrors': [],
921 'vserver_subtype': 'default'},
922 {'snapmirrors': [],
923 'vserver_subtype': 'dp_destination'})
924 @ddt.unpack
925 def test_cancel_snapmirror_svm(self, snapmirrors, vserver_subtype):
926 mock_dest_client = mock.Mock()
927 self.mock_object(self.dm_session, 'get_client_and_vserver_name',
928 mock.Mock(return_value=(mock_dest_client,
929 self.dest_vserver)))
930 mock_backend_config = na_fakes.create_configuration()
931 mock_backend_config.netapp_server_migration_state_change_timeout = 30
932 self.mock_object(data_motion, 'get_backend_configuration',
933 mock.Mock(return_value=mock_backend_config))
934 self.mock_object(self.dm_session, 'get_snapmirrors_svm',
935 mock.Mock(return_value=snapmirrors))
936 self.mock_object(self.dm_session, 'quiesce_and_break_snapmirror_svm')
937 self.mock_object(self.dm_session, 'wait_for_vserver_state')
938 self.mock_object(self.dm_session, 'delete_snapmirror_svm')
939 vserver_info = copy.deepcopy(fake.VSERVER_INFO)
940 vserver_info['subtype'] = vserver_subtype
941 self.mock_object(mock_dest_client, 'get_vserver_info',
942 mock.Mock(return_value=vserver_info))
943 self.mock_object(self.dm_session, 'convert_svm_to_default_subtype')
945 self.dm_session.cancel_snapmirror_svm(self.fake_src_share_server,
946 self.fake_dest_share_server)
948 data_motion.get_backend_configuration.assert_called_once_with(
949 self.dest_backend_name
950 )
951 self.dm_session.get_client_and_vserver_name.assert_called_once_with(
952 self.fake_dest_share_server
953 )
954 self.dm_session.get_snapmirrors_svm.assert_called_once_with(
955 self.fake_src_share_server, self.fake_dest_share_server
956 )
957 if snapmirrors:
958 quiesce_mock = self.dm_session.quiesce_and_break_snapmirror_svm
959 quiesce_mock.assert_called_once_with(
960 self.fake_src_share_server, self.fake_dest_share_server
961 )
962 self.dm_session.wait_for_vserver_state.assert_called_once_with(
963 self.dest_vserver, mock_dest_client, subtype='default',
964 state='running', operational_state='stopped',
965 timeout=(mock_backend_config
966 .netapp_server_migration_state_change_timeout)
967 )
968 self.dm_session.delete_snapmirror_svm.assert_called_once_with(
969 self.fake_src_share_server, self.fake_dest_share_server
970 )
971 else:
972 mock_dest_client.get_vserver_info.assert_called_once_with(
973 self.dest_vserver
974 )
975 convert_svm = self.dm_session.convert_svm_to_default_subtype
976 if vserver_subtype == 'dp_destination':
977 convert_svm.assert_called_once_with(
978 self.dest_vserver, mock_dest_client,
979 timeout=(mock_backend_config
980 .netapp_server_migration_state_change_timeout)
981 )
982 else:
983 self.assertFalse(convert_svm.called)
985 def test_resume_snapmirror(self):
986 self.mock_object(self.mock_dest_client, 'get_snapmirrors')
988 self.dm_session.resume_snapmirror(self.fake_src_share,
989 self.fake_dest_share)
991 self.mock_dest_client.resume_snapmirror_vol.assert_called_once_with(
992 self.source_vserver, self.fake_src_vol_name,
993 self.dest_vserver, self.fake_dest_vol_name)
995 @ddt.data((None, exception.StorageCommunicationException),
996 (exception.StorageCommunicationException, None))
997 @ddt.unpack
998 def test_remove_qos_on_old_active_replica_unreachable_backend(self,
999 side_eff_1,
1000 side_eff_2):
1001 mock_source_client = mock.Mock()
1002 self.mock_object(data_motion, 'get_client_for_backend',
1003 mock.Mock(return_value=mock_source_client))
1004 self.mock_object(
1005 mock_source_client, 'set_qos_policy_group_for_volume',
1006 mock.Mock(side_effect=side_eff_1))
1007 self.mock_object(
1008 mock_source_client, 'mark_qos_policy_group_for_deletion',
1009 mock.Mock(side_effect=side_eff_2))
1010 self.mock_object(data_motion.LOG, 'exception')
1012 retval = self.dm_session.remove_qos_on_old_active_replica(
1013 self.fake_src_share)
1015 self.assertIsNone(retval)
1016 (mock_source_client.set_qos_policy_group_for_volume
1017 .assert_called_once_with(self.fake_src_vol_name, 'none'))
1018 data_motion.LOG.exception.assert_called_once()
1020 def test_remove_qos_on_old_active_replica(self):
1021 mock_source_client = mock.Mock()
1022 self.mock_object(data_motion, 'get_client_for_backend',
1023 mock.Mock(return_value=mock_source_client))
1024 self.mock_object(data_motion.LOG, 'exception')
1026 retval = self.dm_session.remove_qos_on_old_active_replica(
1027 self.fake_src_share)
1029 self.assertIsNone(retval)
1030 (mock_source_client.set_qos_policy_group_for_volume
1031 .assert_called_once_with(self.fake_src_vol_name, 'none'))
1032 data_motion.LOG.exception.assert_not_called()
1034 @ddt.data(True, False)
1035 def test_convert_svm_to_default_subtype(self, is_dest):
1036 mock_client = mock.Mock()
1037 vserver_info_default = copy.deepcopy(fake.VSERVER_INFO)
1038 vserver_info_default['subtype'] = 'default'
1039 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
1040 vserver_info_dp['subtype'] = 'dp_destination'
1041 self.mock_object(mock_client, 'get_vserver_info',
1042 mock.Mock(side_effect=[vserver_info_dp,
1043 vserver_info_default]))
1044 self.mock_object(mock_client, 'break_snapmirror_svm')
1046 self.dm_session.convert_svm_to_default_subtype(fake.VSERVER1,
1047 mock_client,
1048 is_dest_path=is_dest,
1049 timeout=20)
1051 mock_client.get_vserver_info.assert_has_calls([
1052 mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)])
1053 if is_dest:
1054 mock_client.break_snapmirror_svm.assert_called_once_with(
1055 dest_vserver=fake.VSERVER1
1056 )
1057 else:
1058 mock_client.break_snapmirror_svm.assert_called_once_with(
1059 source_vserver=fake.VSERVER1
1060 )
1062 def test_convert_svm_to_default_subtype_timeout(self):
1063 mock_client = mock.Mock()
1064 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
1065 vserver_info_dp['subtype'] = 'dp_destination'
1066 self.mock_object(mock_client, 'get_vserver_info',
1067 mock.Mock(side_effect=[vserver_info_dp]))
1068 self.mock_object(mock_client, 'break_snapmirror_svm')
1070 self.assertRaises(
1071 exception.NetAppException,
1072 self.dm_session.convert_svm_to_default_subtype,
1073 fake.VSERVER1, mock_client, is_dest_path=True, timeout=10)
1075 mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1)
1076 mock_client.break_snapmirror_svm.assert_called_once_with(
1077 dest_vserver=fake.VSERVER1)
1079 def test_wait_for_vserver_state(self,):
1080 mock_client = mock.Mock()
1081 vserver_info_default = copy.deepcopy(fake.VSERVER_INFO)
1082 vserver_info_default['subtype'] = 'default'
1083 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
1084 vserver_info_dp['subtype'] = 'dp_destination'
1085 self.mock_object(mock_client, 'get_vserver_info',
1086 mock.Mock(side_effect=[vserver_info_dp,
1087 vserver_info_default]))
1089 self.dm_session.wait_for_vserver_state(fake.VSERVER1, mock_client,
1090 state='running',
1091 operational_state='running',
1092 subtype='default', timeout=20)
1094 mock_client.get_vserver_info.assert_has_calls([
1095 mock.call(fake.VSERVER1), mock.call(fake.VSERVER1)])
1097 def test_wait_for_vserver_state_timeout(self):
1098 mock_client = mock.Mock()
1099 vserver_info_dp = copy.deepcopy(fake.VSERVER_INFO)
1100 vserver_info_dp['subtype'] = 'dp_destination'
1101 self.mock_object(mock_client, 'get_vserver_info',
1102 mock.Mock(side_effect=[vserver_info_dp]))
1104 self.assertRaises(
1105 exception.NetAppException,
1106 self.dm_session.wait_for_vserver_state,
1107 fake.VSERVER1, mock_client, state='running',
1108 operational_state='running', subtype='default', timeout=10)
1110 mock_client.get_vserver_info.assert_called_once_with(fake.VSERVER1)
1112 @ddt.data(mock.Mock(),
1113 mock.Mock(side_effect=netapp_api.NaApiError(
1114 code=netapp_api.EOBJECTNOTFOUND)))
1115 def test_wait_for_snapmirror_release_svm(self, release_snapmirror_ret):
1116 src_mock_client = mock.Mock()
1117 get_snapmirrors_mock = self.mock_object(
1118 src_mock_client, 'get_snapmirror_destinations_svm',
1119 mock.Mock(side_effect=[['fake_snapmirror'], []]))
1120 self.mock_object(src_mock_client, 'release_snapmirror_svm',
1121 release_snapmirror_ret)
1123 self.dm_session.wait_for_snapmirror_release_svm(fake.VSERVER1,
1124 fake.VSERVER2,
1125 src_mock_client,
1126 timeout=20)
1127 get_snapmirrors_mock.assert_has_calls([
1128 mock.call(source_vserver=fake.VSERVER1,
1129 dest_vserver=fake.VSERVER2),
1130 mock.call(source_vserver=fake.VSERVER1,
1131 dest_vserver=fake.VSERVER2)])
1132 src_mock_client.release_snapmirror_svm.assert_called_once_with(
1133 fake.VSERVER1, fake.VSERVER2)
1135 def test_wait_for_snapmirror_release_svm_timeout(self):
1136 src_mock_client = mock.Mock()
1137 get_snapmirrors_mock = self.mock_object(
1138 src_mock_client, 'get_snapmirror_destinations_svm',
1139 mock.Mock(side_effect=[['fake_snapmirror']]))
1140 self.mock_object(src_mock_client, 'release_snapmirror_svm')
1142 self.assertRaises(exception.NetAppException,
1143 self.dm_session.wait_for_snapmirror_release_svm,
1144 fake.VSERVER1, fake.VSERVER2,
1145 src_mock_client, timeout=10)
1147 get_snapmirrors_mock.assert_called_once_with(
1148 source_vserver=fake.VSERVER1, dest_vserver=fake.VSERVER2)
1149 src_mock_client.release_snapmirror_svm.assert_called_once_with(
1150 fake.VSERVER1, fake.VSERVER2
1151 )
1153 def test_wait_for_mount_replica(self):
1155 mock_client = mock.Mock()
1156 self.mock_object(time, 'sleep')
1157 mock_warning_log = self.mock_object(data_motion.LOG, 'warning')
1159 self.dm_session.wait_for_mount_replica(
1160 mock_client, fake.SHARE_NAME)
1162 mock_client.mount_volume.ssert_called_once_with(fake.SHARE_NAME)
1163 self.assertEqual(0, mock_warning_log.call_count)
1165 def test_wait_for_mount_replica_timeout(self):
1167 mock_client = mock.Mock()
1168 self.mock_object(time, 'sleep')
1169 mock_warning_log = self.mock_object(data_motion.LOG, 'warning')
1170 undergoing_snapmirror = (
1171 'The volume is undergoing a snapmirror initialize.')
1172 na_api_error = netapp_api.NaApiError(code=netapp_api.EAPIERROR,
1173 message=undergoing_snapmirror)
1174 mock_client.mount_volume.side_effect = na_api_error
1176 self.assertRaises(exception.NetAppException,
1177 self.dm_session.wait_for_mount_replica,
1178 mock_client, fake.SHARE_NAME, timeout=30)
1180 self.assertEqual(3, mock_client.mount_volume.call_count)
1181 self.assertEqual(3, mock_warning_log.call_count)
1183 def test_wait_for_mount_replica_api_not_found(self):
1185 mock_client = mock.Mock()
1186 self.mock_object(time, 'sleep')
1187 mock_warning_log = self.mock_object(data_motion.LOG, 'warning')
1188 na_api_error = netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND)
1189 mock_client.mount_volume.side_effect = na_api_error
1191 self.assertRaises(exception.NetAppException,
1192 self.dm_session.wait_for_mount_replica,
1193 mock_client, fake.SHARE_NAME, timeout=30)
1195 mock_client.mount_volume.assert_called_once_with(fake.SHARE_NAME)
1196 mock_warning_log.assert_not_called()
1198 @ddt.data(mock.Mock(),
1199 mock.Mock(side_effect=netapp_api.NaApiError(
1200 code=netapp_api.EOBJECTNOTFOUND)))
1201 def test_wait_for_snapmirror_release_vol(self, release_snapmirror_ret):
1202 src_mock_client = mock.Mock()
1203 get_snapmirrors_mock = self.mock_object(
1204 src_mock_client, 'get_snapmirror_destinations',
1205 mock.Mock(side_effect=[['fake_snapmirror'], []]))
1206 self.mock_object(src_mock_client, 'release_snapmirror_vol',
1207 release_snapmirror_ret)
1209 self.dm_session.wait_for_snapmirror_release_vol(fake.VSERVER1,
1210 fake.VSERVER2,
1211 fake.SHARE_NAME,
1212 fake.SHARE_NAME2,
1213 False,
1214 src_mock_client,
1215 timeout=20)
1216 get_snapmirrors_mock.assert_has_calls([
1217 mock.call(source_vserver=fake.VSERVER1,
1218 dest_vserver=fake.VSERVER2,
1219 source_volume=fake.SHARE_NAME,
1220 dest_volume=fake.SHARE_NAME2),
1221 mock.call(source_vserver=fake.VSERVER1,
1222 dest_vserver=fake.VSERVER2,
1223 source_volume=fake.SHARE_NAME,
1224 dest_volume=fake.SHARE_NAME2)])
1225 src_mock_client.release_snapmirror_vol.assert_called_once_with(
1226 fake.VSERVER1, fake.SHARE_NAME, fake.VSERVER2, fake.SHARE_NAME2,
1227 relationship_info_only=False)
1229 def test_wait_for_snapmirror_release_vol_timeout(self):
1230 src_mock_client = mock.Mock()
1231 get_snapmirrors_mock = self.mock_object(
1232 src_mock_client, 'get_snapmirror_destinations',
1233 mock.Mock(side_effect=[['fake_snapmirror']]))
1234 self.mock_object(src_mock_client, 'release_snapmirror_vol')
1236 self.assertRaises(exception.NetAppException,
1237 self.dm_session.wait_for_snapmirror_release_vol,
1238 fake.VSERVER1, fake.VSERVER2, fake.SHARE_NAME,
1239 fake.SHARE_NAME2, False, src_mock_client,
1240 timeout=10)
1242 get_snapmirrors_mock.assert_has_calls([
1243 mock.call(source_vserver=fake.VSERVER1,
1244 dest_vserver=fake.VSERVER2,
1245 source_volume=fake.SHARE_NAME,
1246 dest_volume=fake.SHARE_NAME2)])
1247 src_mock_client.release_snapmirror_vol.assert_called_once_with(
1248 fake.VSERVER1, fake.SHARE_NAME, fake.VSERVER2, fake.SHARE_NAME2,
1249 relationship_info_only=False)
1251 @ddt.data([{'id': 'src_share'}, {'id': 'dst_share'}],
1252 [{'id': 'dst_share'}])
1253 def test_cleanup_previous_snapmirror_relationships(self, replica_list):
1254 mock_src_client = mock.Mock()
1255 src_backend_info = ('src_share', 'src_vserver', 'src_backend')
1256 dst_backend_info = ('dst_share', 'dst_vserver', 'dst_backend')
1257 self.mock_object(self.dm_session, 'get_backend_info_for_share',
1258 mock.Mock(side_effect=[src_backend_info,
1259 dst_backend_info]))
1260 self.mock_object(data_motion, 'get_client_for_backend',
1261 mock.Mock(return_value=mock_src_client))
1262 self.mock_object(mock_src_client, 'release_snapmirror_vol')
1264 result = self.dm_session.cleanup_previous_snapmirror_relationships(
1265 {'id': 'src_share'}, replica_list)
1267 data_motion.get_client_for_backend.assert_called_once_with(
1268 'src_backend', vserver_name='src_vserver')
1269 self.dm_session.get_backend_info_for_share.assert_has_calls([
1270 mock.call({'id': 'src_share'}),
1271 mock.call({'id': 'dst_share'})
1272 ])
1273 mock_src_client.release_snapmirror_vol.assert_called_once_with(
1274 'src_vserver', 'src_share', 'dst_vserver', 'dst_share')
1276 self.assertIsNone(result)
1278 @ddt.data(netapp_api.NaApiError(),
1279 netapp_api.NaApiError(code=netapp_api.EOBJECTNOTFOUND),
1280 netapp_api.NaApiError(code=netapp_api.ESOURCE_IS_DIFFERENT),
1281 netapp_api.NaApiError(code='some_random_code',
1282 message="(entry doesn't exist)"),
1283 netapp_api.NaApiError(code='some_random_code',
1284 message='(actually, entry does exist!)'))
1285 def test_cleanup_previous_snapmirror_relationships_does_not_exist(
1286 self, release_exception):
1287 mock_src_client = mock.Mock()
1288 self.mock_object(self.dm_session, 'get_backend_info_for_share',
1289 mock.Mock(return_value=(
1290 mock.Mock(), mock.Mock(), mock.Mock())))
1291 self.mock_object(data_motion, 'get_client_for_backend',
1292 mock.Mock(return_value=mock_src_client))
1293 self.mock_object(mock_src_client, 'release_snapmirror_vol',
1294 mock.Mock(side_effect=release_exception))
1296 replica = {'id': 'src_share'}
1297 replica_list = [replica, {'id': 'dst_share'}]
1299 result = self.dm_session.cleanup_previous_snapmirror_relationships(
1300 replica, replica_list)
1302 mock_src_client.release_snapmirror_vol.assert_called()
1303 self.assertIsNone(result)
1305 def test_get_most_available_aggr_of_vserver(self):
1306 vserver_client = mock.Mock()
1307 aggr_space_attr = {fake.AGGREGATE: {'available': 5678},
1308 'aggr2': {'available': 2024}}
1309 self.mock_object(vserver_client,
1310 'get_vserver_aggregate_capacities',
1311 mock.Mock(return_value=aggr_space_attr))
1312 result = self.dm_session.get_most_available_aggr_of_vserver(
1313 vserver_client)
1314 self.assertEqual(result, fake.AGGREGATE)
1316 def test_initialize_and_wait_snapmirror_vol(self):
1317 vserver_client = mock.Mock()
1318 snapmirror_info = [{'source-vserver': fake.VSERVER1,
1319 'source-volume': "fake_source_vol",
1320 'destination-vserver': fake.VSERVER2,
1321 'destination-volume': "fake_des_vol",
1322 'relationship-status': "idle"}]
1323 self.mock_object(vserver_client,
1324 'get_snapmirrors',
1325 mock.Mock(return_value=snapmirror_info))
1327 (self.dm_session.
1328 initialize_and_wait_snapmirror_vol(vserver_client,
1329 fake.VSERVER1,
1330 fake.FLEXVOL_NAME,
1331 fake.VSERVER2,
1332 fake.FLEXVOL_NAME_1,
1333 source_snapshot=None,
1334 transfer_priority=None,
1335 timeout=300))
1336 (vserver_client.initialize_snapmirror_vol.
1337 assert_called_once_with(mock.ANY,
1338 mock.ANY,
1339 mock.ANY,
1340 mock.ANY,
1341 source_snapshot=mock.ANY,
1342 transfer_priority=mock.ANY,
1343 ))