Coverage for manila/tests/data/test_manager.py: 99%
386 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 2015, Hitachi Data Systems.
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.
15"""
16Tests For Data Manager
17"""
19from unittest import mock
21import ddt
22from oslo_config import cfg
24from manila.common import constants
25from manila import context
26from manila.data import helper
27from manila.data import manager
28from manila.data import utils as data_utils
29from manila import db
30from manila import exception
31from manila import quota
32from manila.share import rpcapi as share_rpc
33from manila import test
34from manila.tests import db_utils
35from manila import utils
38CONF = cfg.CONF
41@ddt.ddt
42class DataManagerTestCase(test.TestCase):
43 """Test case for data manager."""
45 def setUp(self):
46 super(DataManagerTestCase, self).setUp()
47 manager.CONF.set_default('mount_tmp_location', '/tmp/')
48 manager.CONF.set_default('backup_mount_tmp_location', '/tmp/')
49 manager.CONF.set_default(
50 'backup_driver',
51 'manila.tests.fake_backup_driver.FakeBackupDriver')
52 self.manager = manager.DataManager()
53 self.context = context.get_admin_context()
54 self.topic = 'fake_topic'
55 self.share = db_utils.create_share()
57 def test_init(self):
58 manager = self.manager
59 self.assertIsNotNone(manager)
61 @ddt.data(constants.TASK_STATE_DATA_COPYING_COMPLETING,
62 constants.TASK_STATE_DATA_COPYING_STARTING,
63 constants.TASK_STATE_DATA_COPYING_IN_PROGRESS)
64 def test_init_host(self, status):
66 share = db_utils.create_share(
67 task_state=status)
69 # mocks
70 self.mock_object(db, 'share_get_all', mock.Mock(
71 return_value=[share]))
72 self.mock_object(db, 'share_update')
74 # run
75 self.manager.init_host()
77 # asserts
78 db.share_get_all.assert_called_once_with(
79 utils.IsAMatcher(context.RequestContext))
81 db.share_update.assert_called_with(
82 utils.IsAMatcher(context.RequestContext), share['id'],
83 {'task_state': constants.TASK_STATE_DATA_COPYING_ERROR})
85 @ddt.data(None, Exception('fake'), exception.ShareDataCopyCancelled())
86 def test_migration_start(self, exc):
88 migration_info_src = {
89 'mount': 'mount_cmd_src',
90 'unmount': 'unmount_cmd_src',
91 }
92 migration_info_dest = {
93 'mount': 'mount_cmd_dest',
94 'unmount': 'unmount_cmd_dest',
95 }
96 # mocks
97 self.mock_object(db, 'share_get', mock.Mock(return_value=self.share))
98 self.mock_object(db, 'share_instance_get', mock.Mock(
99 return_value=self.share.instance))
101 self.mock_object(data_utils, 'Copy',
102 mock.Mock(return_value='fake_copy'))
104 if exc is None:
105 self.manager.busy_tasks_shares[self.share['id']] = 'fake_copy'
107 self.mock_object(self.manager, '_copy_share_data',
108 mock.Mock(side_effect=exc))
110 self.mock_object(share_rpc.ShareAPI, 'migration_complete')
112 if exc is not None and not isinstance(
113 exc, exception.ShareDataCopyCancelled):
114 self.mock_object(db, 'share_update')
116 # run
117 if exc is None or isinstance(exc, exception.ShareDataCopyCancelled):
118 self.manager.migration_start(
119 self.context, [], self.share['id'],
120 'ins1_id', 'ins2_id', migration_info_src,
121 migration_info_dest)
122 else:
123 self.assertRaises(
124 exception.ShareDataCopyFailed, self.manager.migration_start,
125 self.context, [], self.share['id'], 'ins1_id', 'ins2_id',
126 migration_info_src, migration_info_dest)
128 db.share_update.assert_called_once_with(
129 self.context, self.share['id'],
130 {'task_state': constants.TASK_STATE_DATA_COPYING_ERROR})
132 # asserts
133 self.assertFalse(self.manager.busy_tasks_shares.get(self.share['id']))
135 if exc:
136 share_rpc.ShareAPI.migration_complete.assert_called_once_with(
137 self.context, self.share.instance, 'ins2_id')
139 @ddt.data(
140 {'cancelled': False, 'exc': None, 'case': 'migration'},
141 {'cancelled': False, 'exc': Exception('fake'), 'case': 'migration'},
142 {'cancelled': True, 'exc': None, 'case': 'migration'},
143 {'cancelled': False, 'exc': None, 'case': 'backup'},
144 {'cancelled': False, 'exc': Exception('fake'), 'case': 'backup'},
145 {'cancelled': True, 'exc': None, 'case': 'backup'},
146 {'cancelled': False, 'exc': None, 'case': 'restore'},
147 {'cancelled': False, 'exc': Exception('fake'), 'case': 'restore'},
148 {'cancelled': True, 'exc': None, 'case': 'restore'},
149 )
150 @ddt.unpack
151 def test__copy_share_data(self, cancelled, exc, case):
153 access = db_utils.create_access(share_id=self.share['id'])
155 if case == 'migration':
156 connection_info_src = {
157 'mount': 'mount_cmd_src',
158 'unmount': 'unmount_cmd_src',
159 'share_id': self.share['id'],
160 'share_instance_id': 'ins1_id',
161 'mount_point': '/tmp/ins1_id',
162 }
163 connection_info_dest = {
164 'mount': 'mount_cmd_dest',
165 'unmount': 'unmount_cmd_dest',
166 'share_id': None,
167 'share_instance_id': 'ins2_id',
168 'mount_point': '/tmp/ins2_id',
169 }
170 if case == 'backup':
171 connection_info_src = {
172 'mount': 'mount_cmd_src',
173 'unmount': 'unmount_cmd_src',
174 'share_id': self.share['id'],
175 'share_instance_id': 'ins1_id',
176 'mount_point': '/tmp/ins1_id',
177 }
178 connection_info_dest = {
179 'mount': 'mount_cmd_dest',
180 'unmount': 'unmount_cmd_dest',
181 'share_id': None,
182 'share_instance_id': None,
183 'mount_point': '/tmp/backup_id',
184 'backup': True
185 }
186 if case == 'restore':
187 connection_info_src = {
188 'mount': 'mount_cmd_src',
189 'unmount': 'unmount_cmd_src',
190 'share_id': None,
191 'share_instance_id': None,
192 'mount_point': '/tmp/backup_id',
193 'restore': True
194 }
195 connection_info_dest = {
196 'mount': 'mount_cmd_dest',
197 'unmount': 'unmount_cmd_dest',
198 'share_id': self.share['id'],
199 'share_instance_id': 'ins2_id',
200 'mount_point': '/tmp/ins2_id',
201 }
203 get_progress = {'total_progress': 100}
205 # mocks
206 fake_copy = mock.MagicMock(cancelled=cancelled)
208 self.mock_object(db, 'share_update')
209 self.mock_object(db, 'share_instance_get',
210 mock.Mock(side_effect=[self.share['instance'],
211 self.share['instance']]))
212 self.mock_object(helper.DataServiceHelper,
213 'allow_access_to_data_service',
214 mock.Mock(return_value=[access]))
216 self.mock_object(helper.DataServiceHelper,
217 'mount_share_instance_or_backup')
219 self.mock_object(fake_copy, 'run', mock.Mock(side_effect=exc))
221 self.mock_object(fake_copy, 'get_progress',
222 mock.Mock(return_value=get_progress))
224 self.mock_object(helper.DataServiceHelper,
225 'unmount_share_instance_or_backup',
226 mock.Mock(side_effect=Exception('fake')))
228 self.mock_object(helper.DataServiceHelper,
229 'deny_access_to_data_service',
230 mock.Mock(side_effect=Exception('fake')))
232 extra_updates = None
234 # run
235 if cancelled:
236 self.assertRaises(
237 exception.ShareDataCopyCancelled,
238 self.manager._copy_share_data, self.context, fake_copy,
239 connection_info_src, connection_info_dest)
240 extra_updates = [
241 mock.call(
242 self.context, self.share['id'],
243 {'task_state':
244 constants.TASK_STATE_DATA_COPYING_COMPLETING}),
245 mock.call(
246 self.context, self.share['id'],
247 {'task_state':
248 constants.TASK_STATE_DATA_COPYING_CANCELLED})
249 ]
251 elif exc:
252 self.assertRaises(
253 exception.ShareDataCopyFailed, self.manager._copy_share_data,
254 self.context, fake_copy, connection_info_src,
255 connection_info_dest)
257 else:
258 self.manager._copy_share_data(
259 self.context, fake_copy, connection_info_src,
260 connection_info_dest)
261 extra_updates = [
262 mock.call(
263 self.context, self.share['id'],
264 {'task_state':
265 constants.TASK_STATE_DATA_COPYING_COMPLETING}),
266 mock.call(
267 self.context, self.share['id'],
268 {'task_state':
269 constants.TASK_STATE_DATA_COPYING_COMPLETED})
270 ]
272 # asserts
273 self.assertEqual(
274 self.manager.busy_tasks_shares[self.share['id']], fake_copy)
276 update_list = [
277 mock.call(
278 self.context, self.share['id'],
279 {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING}),
280 mock.call(
281 self.context, self.share['id'],
282 {'task_state': constants.TASK_STATE_DATA_COPYING_IN_PROGRESS}),
283 ]
284 if extra_updates:
285 update_list = update_list + extra_updates
287 db.share_update.assert_has_calls(update_list)
289 helper.DataServiceHelper.\
290 mount_share_instance_or_backup.assert_has_calls([
291 mock.call(connection_info_src, '/tmp/'),
292 mock.call(connection_info_dest, '/tmp/')])
294 fake_copy.run.assert_called_once_with()
295 if exc is None:
296 fake_copy.get_progress.assert_called_once_with()
298 helper.DataServiceHelper.\
299 unmount_share_instance_or_backup.assert_has_calls([
300 mock.call(connection_info_src, '/tmp/'),
301 mock.call(connection_info_dest, '/tmp/')])
303 def test__copy_share_data_exception_access(self):
305 connection_info_src = {
306 'mount': 'mount_cmd_src',
307 'unmount': 'unmount_cmd_src',
308 'share_id': self.share['id'],
309 'share_instance_id': 'ins1_id',
310 'mount_point': '/tmp/ins1_id',
311 }
312 connection_info_dest = {
313 'mount': 'mount_cmd_dest',
314 'unmount': 'unmount_cmd_dest',
315 'share_id': None,
316 'share_instance_id': 'ins2_id',
317 'mount_point': '/tmp/ins2_id',
318 }
320 fake_copy = mock.MagicMock(cancelled=False)
322 # mocks
323 self.mock_object(db, 'share_update')
324 self.mock_object(db, 'share_instance_get',
325 mock.Mock(side_effect=[self.share['instance'],
326 self.share['instance']]))
328 self.mock_object(
329 helper.DataServiceHelper, 'allow_access_to_data_service',
330 mock.Mock(
331 side_effect=exception.ShareDataCopyFailed(reason='fake')))
333 self.mock_object(helper.DataServiceHelper, 'cleanup_data_access')
335 # run
336 self.assertRaises(exception.ShareDataCopyFailed,
337 self.manager._copy_share_data, self.context,
338 fake_copy, connection_info_src, connection_info_dest)
340 # asserts
341 db.share_update.assert_called_once_with(
342 self.context, self.share['id'],
343 {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING})
345 (helper.DataServiceHelper.allow_access_to_data_service.
346 assert_called_once_with(
347 self.share['instance'], connection_info_src,
348 self.share['instance'], connection_info_dest))
350 def test__copy_share_data_exception_mount_1(self):
352 access = db_utils.create_access(share_id=self.share['id'])
354 connection_info_src = {
355 'mount': 'mount_cmd_src',
356 'unmount': 'unmount_cmd_src',
357 'share_id': self.share['id'],
358 'share_instance_id': 'ins1_id',
359 'mount_point': '/tmp/ins1_id',
360 }
361 connection_info_dest = {
362 'mount': 'mount_cmd_dest',
363 'unmount': 'unmount_cmd_dest',
364 'share_id': None,
365 'share_instance_id': 'ins2_id',
366 'mount_point': '/tmp/ins2_id',
367 }
369 fake_copy = mock.MagicMock(cancelled=False)
371 # mocks
372 self.mock_object(db, 'share_update')
373 self.mock_object(db, 'share_instance_get',
374 mock.Mock(side_effect=[self.share['instance'],
375 self.share['instance']]))
377 self.mock_object(helper.DataServiceHelper,
378 'allow_access_to_data_service',
379 mock.Mock(return_value=[access]))
381 self.mock_object(helper.DataServiceHelper,
382 'mount_share_instance_or_backup',
383 mock.Mock(side_effect=Exception('fake')))
385 self.mock_object(helper.DataServiceHelper, 'cleanup_data_access')
386 self.mock_object(helper.DataServiceHelper, 'cleanup_temp_folder')
388 # run
389 self.assertRaises(exception.ShareDataCopyFailed,
390 self.manager._copy_share_data, self.context,
391 fake_copy, connection_info_src, connection_info_dest)
393 # asserts
394 db.share_update.assert_called_once_with(
395 self.context, self.share['id'],
396 {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING})
398 helper.DataServiceHelper.\
399 mount_share_instance_or_backup.assert_called_once_with(
400 connection_info_src, '/tmp/')
402 helper.DataServiceHelper.cleanup_temp_folder.assert_called_once_with(
403 '/tmp/', 'ins1_id')
405 helper.DataServiceHelper.cleanup_data_access.assert_has_calls([
406 mock.call([access], self.share['instance']),
407 mock.call([access], self.share['instance'])])
409 def test__copy_share_data_exception_mount_2(self):
411 access = db_utils.create_access(share_id=self.share['id'])
413 connection_info_src = {
414 'mount': 'mount_cmd_src',
415 'unmount': 'unmount_cmd_src',
416 'share_id': self.share['id'],
417 'share_instance_id': 'ins1_id',
418 'mount_point': '/tmp/ins1_id',
419 }
420 connection_info_dest = {
421 'mount': 'mount_cmd_dest',
422 'unmount': 'unmount_cmd_dest',
423 'share_id': None,
424 'share_instance_id': 'ins2_id',
425 'mount_point': '/tmp/ins2_id',
426 }
428 fake_copy = mock.MagicMock(cancelled=False)
430 # mocks
431 self.mock_object(db, 'share_update')
432 self.mock_object(db, 'share_instance_get',
433 mock.Mock(side_effect=[self.share['instance'],
434 self.share['instance']]))
436 self.mock_object(helper.DataServiceHelper,
437 'allow_access_to_data_service',
438 mock.Mock(return_value=[access]))
440 self.mock_object(helper.DataServiceHelper,
441 'mount_share_instance_or_backup',
442 mock.Mock(side_effect=[None, Exception('fake')]))
444 self.mock_object(helper.DataServiceHelper, 'cleanup_data_access')
445 self.mock_object(helper.DataServiceHelper, 'cleanup_temp_folder')
446 self.mock_object(helper.DataServiceHelper,
447 'cleanup_unmount_temp_folder')
449 # run
450 self.assertRaises(exception.ShareDataCopyFailed,
451 self.manager._copy_share_data, self.context,
452 fake_copy, connection_info_src, connection_info_dest)
454 # asserts
455 db.share_update.assert_called_once_with(
456 self.context, self.share['id'],
457 {'task_state': constants.TASK_STATE_DATA_COPYING_STARTING})
459 helper.DataServiceHelper.\
460 mount_share_instance_or_backup.assert_has_calls([
461 mock.call(connection_info_src, '/tmp/'),
462 mock.call(connection_info_dest, '/tmp/')])
464 helper.DataServiceHelper.cleanup_unmount_temp_folder.\
465 assert_called_once_with(connection_info_src, '/tmp/')
467 helper.DataServiceHelper.cleanup_temp_folder.assert_has_calls([
468 mock.call('/tmp/', 'ins2_id'), mock.call('/tmp/', 'ins1_id')])
470 def test_data_copy_cancel(self):
472 share = db_utils.create_share()
474 self.manager.busy_tasks_shares[share['id']] = data_utils.Copy
476 # mocks
477 self.mock_object(data_utils.Copy, 'cancel')
479 # run
480 self.manager.data_copy_cancel(self.context, share['id'])
482 # asserts
483 data_utils.Copy.cancel.assert_called_once_with()
485 def test_data_copy_cancel_not_copying(self):
487 self.assertRaises(exception.InvalidShare,
488 self.manager.data_copy_cancel, self.context,
489 'fake_id')
491 def test_data_copy_get_progress(self):
493 share = db_utils.create_share()
495 self.manager.busy_tasks_shares[share['id']] = data_utils.Copy
497 expected = 'fake_progress'
499 # mocks
500 self.mock_object(data_utils.Copy, 'get_progress',
501 mock.Mock(return_value=expected))
503 # run
504 result = self.manager.data_copy_get_progress(self.context, share['id'])
506 # asserts
507 self.assertEqual(expected, result)
509 data_utils.Copy.get_progress.assert_called_once_with()
511 def test_data_copy_get_progress_not_copying(self):
513 self.assertRaises(exception.InvalidShare,
514 self.manager.data_copy_get_progress, self.context,
515 'fake_id')
517 def test_create_share_backup(self):
518 share_info = db_utils.create_share(
519 status=constants.STATUS_BACKUP_CREATING)
520 backup_info = db_utils.create_backup(
521 share_info['id'], status=constants.STATUS_CREATING)
523 # mocks
524 self.mock_object(db, 'share_update')
525 self.mock_object(db, 'share_backup_update')
526 self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
527 self.mock_object(db, 'share_backup_get',
528 mock.Mock(return_value=backup_info))
529 self.mock_object(self.manager, '_run_backup',
530 mock.Mock(side_effect=None))
531 self.manager.create_backup(self.context, backup_info)
532 db.share_update.assert_called_with(
533 self.context, share_info['id'],
534 {'status': constants.STATUS_AVAILABLE})
535 db.share_backup_update.assert_called_with(
536 self.context, backup_info['id'],
537 {'status': constants.STATUS_AVAILABLE, 'progress': '100'})
539 def test_create_share_backup_exception(self):
540 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
541 backup_info = db_utils.create_backup(
542 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
544 # mocks
545 self.mock_object(db, 'share_update')
546 self.mock_object(db, 'share_backup_update')
547 self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
548 self.mock_object(db, 'share_backup_get',
549 mock.Mock(return_value=backup_info))
550 self.mock_object(
551 self.manager, '_run_backup',
552 mock.Mock(
553 side_effect=exception.ShareDataCopyFailed(reason='fake')))
554 self.assertRaises(exception.ManilaException,
555 self.manager.create_backup,
556 self.context, backup_info)
557 db.share_update.assert_called_with(
558 self.context, share_info['id'],
559 {'status': constants.STATUS_AVAILABLE})
560 db.share_backup_update.assert_called()
562 @ddt.data(
563 ('90', False),
564 ('90', True),
565 ('100', False),
566 ('100', True)
567 )
568 @ddt.unpack
569 def test_create_share_backup_continue(self, progress, use_data_manager):
570 share_info = db_utils.create_share(
571 status=constants.STATUS_BACKUP_CREATING)
572 backup_info = db_utils.create_backup(
573 share_info['id'], status=constants.STATUS_CREATING,
574 topic=CONF.data_topic)
575 # mocks
576 self.mock_object(db, 'share_update')
577 self.mock_object(db, 'share_backup_update')
578 self.mock_object(db, 'share_get',
579 mock.Mock(return_value=share_info))
580 self.mock_object(db, 'share_backups_get_all',
581 mock.Mock(return_value=[backup_info]))
582 self.mock_object(self.manager, 'data_copy_get_progress',
583 mock.Mock(return_value={'total_progress': progress}))
584 self.mock_object(self.manager.backup_driver, 'get_backup_progress',
585 mock.Mock(return_value=progress))
587 with mock.patch.object(
588 self.manager.backup_driver, 'use_data_manager', use_data_manager
589 ):
590 self.manager.create_backup_continue(self.context)
592 if use_data_manager is True:
593 self.manager.data_copy_get_progress.assert_called_with(
594 self.context, share_info['id'])
595 else:
596 self.manager.backup_driver.get_backup_progress.\
597 assert_called_with(self.context, backup_info, share_info)
599 self.manager.create_backup_continue(self.context)
600 if progress == '100':
601 db.share_backup_update.assert_called_with(
602 self.context, backup_info['id'],
603 {'status': constants.STATUS_AVAILABLE, 'progress': '100'})
604 db.share_update.assert_called_with(
605 self.context, share_info['id'],
606 {'status': constants.STATUS_AVAILABLE})
607 else:
608 db.share_backup_update.assert_called_with(
609 self.context, backup_info['id'],
610 {'progress': progress})
612 def test_create_share_backup_continue_exception(self):
613 share_info = db_utils.create_share(
614 status=constants.STATUS_BACKUP_CREATING)
615 backup_info = db_utils.create_backup(
616 share_info['id'], status=constants.STATUS_CREATING,
617 topic=CONF.data_topic)
618 # mocks
619 self.mock_object(db, 'share_update')
620 self.mock_object(db, 'share_backup_update')
621 self.mock_object(db, 'share_backups_get_all',
622 mock.Mock(return_value=[backup_info]))
623 self.mock_object(self.manager, 'data_copy_get_progress',
624 mock.Mock(side_effect=exception.ManilaException))
626 self.manager.create_backup_continue(self.context)
628 db.share_backup_update.assert_called_with(
629 self.context, backup_info['id'],
630 {'status': constants.STATUS_ERROR, 'progress': '0'})
631 db.share_update.assert_called_with(
632 self.context, share_info['id'],
633 {'status': constants.STATUS_AVAILABLE})
635 @ddt.data(None, exception.ShareDataCopyFailed(reason='fake'))
636 def test__run_backup(self, exc):
637 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
638 backup_info = db_utils.create_backup(
639 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
640 share_instance = {
641 'export_locations': [{
642 'path': 'test_path',
643 "is_admin_only": False
644 }, ],
645 'share_proto': 'nfs',
646 }
648 # mocks
649 self.mock_object(db, 'share_instance_get',
650 mock.Mock(return_value=share_instance))
652 self.mock_object(data_utils, 'Copy',
653 mock.Mock(return_value='fake_copy'))
654 self.manager.busy_tasks_shares[self.share['id']] = 'fake_copy'
655 self.mock_object(self.manager, '_copy_share_data',
656 mock.Mock(side_effect=exc))
658 self.mock_object(self.manager, '_run_backup')
660 if exc is isinstance(exc, exception.ShareDataCopyFailed): 660 ↛ 661line 660 didn't jump to line 661 because the condition on line 660 was never true
661 self.assertRaises(exception.ShareDataCopyFailed,
662 self.manager._run_backup, self.context,
663 backup_info, share_info)
664 else:
665 self.manager._run_backup(self.context, backup_info, share_info)
667 def test_delete_share_backup(self):
668 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
669 backup_info = db_utils.create_backup(
670 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
671 # mocks
672 self.mock_object(db, 'share_backup_delete')
673 self.mock_object(db, 'share_backup_get',
674 mock.Mock(return_value=backup_info))
675 self.mock_object(utils, 'execute')
677 reservation = 'fake'
678 self.mock_object(quota.QUOTAS, 'reserve',
679 mock.Mock(return_value=reservation))
680 self.mock_object(quota.QUOTAS, 'commit')
682 self.manager.delete_backup(self.context, backup_info)
683 db.share_backup_delete.assert_called_with(
684 self.context, backup_info['id'])
686 def test_delete_share_backup_exception(self):
687 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
688 backup_info = db_utils.create_backup(
689 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
690 # mocks
691 self.mock_object(db, 'share_backup_get',
692 mock.Mock(return_value=backup_info))
693 self.mock_object(utils, 'execute')
695 self.mock_object(
696 quota.QUOTAS, 'reserve',
697 mock.Mock(side_effect=exception.ManilaException))
698 self.assertRaises(exception.ManilaException,
699 self.manager.delete_backup, self.context,
700 backup_info)
702 def test_restore_share_backup(self):
703 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
704 backup_info = db_utils.create_backup(
705 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
706 share_id = share_info['id']
708 # mocks
709 self.mock_object(db, 'share_update')
710 self.mock_object(db, 'share_backup_update')
711 self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
712 self.mock_object(db, 'share_backup_get',
713 mock.Mock(return_value=backup_info))
714 self.mock_object(self.manager, '_run_restore')
715 self.manager.restore_backup(self.context, backup_info, share_id)
716 db.share_update.assert_called_with(
717 self.context, share_info['id'],
718 {'status': constants.STATUS_AVAILABLE})
719 db.share_backup_update.assert_called_with(
720 self.context, backup_info['id'],
721 {'status': constants.STATUS_AVAILABLE, 'restore_progress': '100'})
723 def test_restore_share_backup_respects_restore_to_target(self):
724 target_share_info = db_utils.create_share(
725 status=constants.STATUS_AVAILABLE)
726 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
727 backup_info = db_utils.create_backup(
728 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
729 target_share_id = target_share_info['id']
731 # mocks
732 with mock.patch.object(self.manager.backup_driver,
733 'restore_to_target_support', False):
734 self.mock_object(self.manager, '_run_restore')
735 self.mock_object(self.manager.backup_driver, 'restore')
736 self.mock_object(db, 'share_get',
737 mock.Mock(return_value=target_share_info))
738 self.mock_object(db, 'share_backup_get',
739 mock.Mock(return_value=backup_info))
741 self.assertRaises(exception.BackupException,
742 self.manager.restore_backup, self.context,
743 backup_info, target_share_id)
744 self.manager._run_restore.assert_not_called()
745 self.manager.backup_driver.restore.assert_not_called()
747 def test_restore_share_backup_exception(self):
748 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
749 backup_info = db_utils.create_backup(
750 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
751 share_id = share_info['id']
753 # mocks
754 self.mock_object(db, 'share_update')
755 self.mock_object(db, 'share_get', mock.Mock(return_value=share_info))
756 self.mock_object(db, 'share_backup_get',
757 mock.Mock(return_value=backup_info))
758 self.mock_object(
759 self.manager, '_run_restore',
760 mock.Mock(
761 side_effect=exception.ShareDataCopyFailed(reason='fake')))
762 self.assertRaises(exception.ManilaException,
763 self.manager.restore_backup, self.context,
764 backup_info, share_id)
765 db.share_update.assert_called_with(
766 self.context, share_info['id'],
767 {'status': constants.STATUS_BACKUP_RESTORING_ERROR})
769 @ddt.data(
770 ('90', False),
771 ('90', True),
772 ('100', False),
773 ('100', True)
774 )
775 @ddt.unpack
776 def test_restore_share_backup_continue(self, progress, use_data_manager):
777 share_info = db_utils.create_share(
778 status=constants.STATUS_BACKUP_RESTORING)
779 backup_info = db_utils.create_backup(
780 share_info['id'], status=constants.STATUS_RESTORING,
781 topic=CONF.data_topic)
782 share_info['source_backup_id'] = backup_info['id']
784 # mocks
785 self.mock_object(db, 'share_update')
786 self.mock_object(db, 'share_backup_update')
787 self.mock_object(db, 'share_get_all',
788 mock.Mock(return_value=[share_info]))
789 self.mock_object(db, 'share_backups_get_all',
790 mock.Mock(return_value=[backup_info]))
791 self.mock_object(self.manager, 'data_copy_get_progress',
792 mock.Mock(return_value={'total_progress': progress}))
793 self.mock_object(self.manager.backup_driver, 'get_restore_progress',
794 mock.Mock(return_value=progress))
796 with mock.patch.object(
797 self.manager.backup_driver, 'use_data_manager', use_data_manager
798 ):
799 self.manager.restore_backup_continue(self.context)
801 if use_data_manager is True:
802 self.manager.data_copy_get_progress.assert_called_with(
803 self.context, share_info['id'])
804 else:
805 self.manager.backup_driver.get_restore_progress.\
806 assert_called_with(self.context, backup_info, share_info)
808 if progress == '100':
809 db.share_backup_update.assert_called_with(
810 self.context, backup_info['id'],
811 {'status': constants.STATUS_AVAILABLE,
812 'restore_progress': '100'})
813 db.share_update.assert_called_with(
814 self.context, share_info['id'],
815 {'status': constants.STATUS_AVAILABLE})
816 else:
817 db.share_backup_update.assert_called_with(
818 self.context, backup_info['id'],
819 {'restore_progress': progress})
821 def test_restore_share_backup_continue_exception(self):
822 share_info = db_utils.create_share(
823 status=constants.STATUS_BACKUP_RESTORING)
824 backup_info = db_utils.create_backup(
825 share_info['id'], status=constants.STATUS_RESTORING,
826 topic=CONF.data_topic)
827 share_info['source_backup_id'] = backup_info['id']
829 # mocks
830 self.mock_object(db, 'share_update')
831 self.mock_object(db, 'share_backup_update')
832 self.mock_object(db, 'share_get_all',
833 mock.Mock(return_value=[share_info]))
834 self.mock_object(db, 'share_backups_get_all',
835 mock.Mock(return_value=[backup_info]))
836 self.mock_object(self.manager, 'data_copy_get_progress',
837 mock.Mock(side_effect=exception.ManilaException))
839 self.manager.restore_backup_continue(self.context)
840 db.share_backup_update.assert_called_with(
841 self.context, backup_info['id'],
842 {'status': constants.STATUS_AVAILABLE, 'restore_progress': '0'})
843 db.share_update.assert_called_with(
844 self.context, share_info['id'],
845 {'status': constants.STATUS_BACKUP_RESTORING_ERROR})
847 @ddt.data(None, exception.ShareDataCopyFailed(reason='fake'))
848 def test__run_restore(self, exc):
849 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
850 backup_info = db_utils.create_backup(
851 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
852 share_instance = {
853 'export_locations': [{
854 'path': 'test_path',
855 "is_admin_only": False
856 }, ],
857 'share_proto': 'nfs',
858 }
860 # mocks
861 self.mock_object(db, 'share_instance_get',
862 mock.Mock(return_value=share_instance))
864 self.mock_object(data_utils, 'Copy',
865 mock.Mock(return_value='fake_copy'))
866 self.manager.busy_tasks_shares[self.share['id']] = 'fake_copy'
867 self.mock_object(self.manager, '_copy_share_data',
868 mock.Mock(side_effect=exc))
870 self.mock_object(self.manager, '_run_restore')
872 if exc is isinstance(exc, exception.ShareDataCopyFailed): 872 ↛ 873line 872 didn't jump to line 873 because the condition on line 872 was never true
873 self.assertRaises(exception.ShareDataCopyFailed,
874 self.manager._run_restore, self.context,
875 backup_info, share_info)
876 else:
877 self.manager._run_restore(self.context, backup_info, share_info)
879 def test_create_backup_respects_use_data_manager(self):
880 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
881 backup_info = db_utils.create_backup(
882 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
883 # mocks
884 self.mock_object(self.manager, '_run_backup')
885 self.mock_object(self.manager.backup_driver, 'backup')
886 self.mock_object(self.manager.db, 'share_get',
887 mock.Mock(return_value=share_info))
888 self.mock_object(self.manager.db, 'share_backup_get',
889 mock.Mock(return_value=backup_info))
890 # tests
891 with mock.patch.object(
892 self.manager.backup_driver, 'use_data_manager', False):
893 self.manager.create_backup(self.context, backup_info)
894 self.assertFalse(self.manager.backup_driver.use_data_manager)
895 self.manager._run_backup.assert_not_called()
896 self.manager.backup_driver.backup.assert_called_with(
897 self.context, backup_info, share_info)
899 def test_restore_backup_respects_use_data_manager(self):
900 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
901 share_id = share_info['id']
902 backup_info = db_utils.create_backup(
903 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
904 # mocks
905 self.mock_object(self.manager, '_run_restore')
906 self.mock_object(self.manager.backup_driver, 'restore')
907 self.mock_object(self.manager.db, 'share_get',
908 mock.Mock(return_value=share_info))
909 self.mock_object(self.manager.db, 'share_backup_get',
910 mock.Mock(return_value=backup_info))
911 # tests
912 with mock.patch.object(
913 self.manager.backup_driver, 'use_data_manager', False):
914 self.manager.restore_backup(self.context, backup_info, share_id)
915 self.assertFalse(self.manager.backup_driver.use_data_manager)
916 self.manager._run_restore.assert_not_called()
917 self.manager.backup_driver.restore.assert_called_with(
918 self.context, backup_info, share_info)
920 def test_delete_backup_respects_use_data_manager(self):
921 share_info = db_utils.create_share(status=constants.STATUS_AVAILABLE)
922 backup_info = db_utils.create_backup(
923 share_info['id'], status=constants.STATUS_AVAILABLE, size=2)
924 # mocks
925 self.mock_object(self.manager.backup_driver, 'delete')
926 self.mock_object(self.manager.db, 'share_backup_get',
927 mock.Mock(return_value=backup_info))
928 # tests
929 with mock.patch.object(
930 self.manager.backup_driver, 'use_data_manager', False):
931 self.manager.delete_backup(self.context, backup_info)
932 self.assertFalse(self.manager.backup_driver.use_data_manager)
933 self.manager.backup_driver.delete.assert_called_with(
934 self.context, backup_info)
936 def test_create_backup_continue_respects_use_data_manager(self):
937 share_info = db_utils.create_share(
938 status=constants.STATUS_BACKUP_RESTORING)
939 backup_info = db_utils.create_backup(
940 share_info['id'], status=constants.STATUS_CREATING, size=2)
941 # mocks
942 self.mock_object(self.manager, 'data_copy_get_progress')
943 self.mock_object(self.manager.backup_driver, 'get_backup_progress')
944 self.mock_object(self.manager.db, 'share_backups_get_all',
945 mock.Mock(return_value=[backup_info]))
946 self.mock_object(self.manager.db, 'share_backup_update')
947 self.mock_object(self.manager.db, 'share_get',
948 mock.Mock(return_value=share_info))
950 # tests
951 with mock.patch.object(
952 self.manager.backup_driver, 'use_data_manager', False):
953 self.manager.create_backup_continue(self.context)
954 self.assertFalse(self.manager.backup_driver.use_data_manager)
955 self.manager.data_copy_get_progress.assert_not_called()
956 self.manager.backup_driver.get_backup_progress.assert_called_with(
957 self.context, backup_info, share_info)
959 def test_restore_backup_continue_respects_use_data_manager(self):
960 share_info = db_utils.create_share(
961 status=constants.STATUS_BACKUP_RESTORING)
962 backup_info = db_utils.create_backup(
963 share_info['id'], status=constants.STATUS_BACKUP_RESTORING, size=2)
964 # mocks
965 self.mock_object(self.manager, 'data_copy_get_progress')
966 self.mock_object(self.manager.backup_driver, 'get_restore_progress')
967 self.mock_object(self.manager.db, 'share_get_all',
968 mock.Mock(return_value=[share_info]))
969 self.mock_object(self.manager.db, 'share_backups_get_all',
970 mock.Mock(return_value=[backup_info]))
971 self.mock_object(self.manager.db, 'share_backup_update')
972 # tests
973 with mock.patch.object(
974 self.manager.backup_driver, 'use_data_manager', False):
975 self.manager.restore_backup_continue(self.context)
976 self.assertFalse(self.manager.backup_driver.use_data_manager)
977 self.manager.data_copy_get_progress.assert_not_called()
978 self.manager.backup_driver.get_restore_progress.assert_called_with(
979 self.context, backup_info, share_info)