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

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. 

14 

15""" 

16Tests For Data Manager 

17""" 

18 

19from unittest import mock 

20 

21import ddt 

22from oslo_config import cfg 

23 

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 

36 

37 

38CONF = cfg.CONF 

39 

40 

41@ddt.ddt 

42class DataManagerTestCase(test.TestCase): 

43 """Test case for data manager.""" 

44 

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() 

56 

57 def test_init(self): 

58 manager = self.manager 

59 self.assertIsNotNone(manager) 

60 

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): 

65 

66 share = db_utils.create_share( 

67 task_state=status) 

68 

69 # mocks 

70 self.mock_object(db, 'share_get_all', mock.Mock( 

71 return_value=[share])) 

72 self.mock_object(db, 'share_update') 

73 

74 # run 

75 self.manager.init_host() 

76 

77 # asserts 

78 db.share_get_all.assert_called_once_with( 

79 utils.IsAMatcher(context.RequestContext)) 

80 

81 db.share_update.assert_called_with( 

82 utils.IsAMatcher(context.RequestContext), share['id'], 

83 {'task_state': constants.TASK_STATE_DATA_COPYING_ERROR}) 

84 

85 @ddt.data(None, Exception('fake'), exception.ShareDataCopyCancelled()) 

86 def test_migration_start(self, exc): 

87 

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)) 

100 

101 self.mock_object(data_utils, 'Copy', 

102 mock.Mock(return_value='fake_copy')) 

103 

104 if exc is None: 

105 self.manager.busy_tasks_shares[self.share['id']] = 'fake_copy' 

106 

107 self.mock_object(self.manager, '_copy_share_data', 

108 mock.Mock(side_effect=exc)) 

109 

110 self.mock_object(share_rpc.ShareAPI, 'migration_complete') 

111 

112 if exc is not None and not isinstance( 

113 exc, exception.ShareDataCopyCancelled): 

114 self.mock_object(db, 'share_update') 

115 

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) 

127 

128 db.share_update.assert_called_once_with( 

129 self.context, self.share['id'], 

130 {'task_state': constants.TASK_STATE_DATA_COPYING_ERROR}) 

131 

132 # asserts 

133 self.assertFalse(self.manager.busy_tasks_shares.get(self.share['id'])) 

134 

135 if exc: 

136 share_rpc.ShareAPI.migration_complete.assert_called_once_with( 

137 self.context, self.share.instance, 'ins2_id') 

138 

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): 

152 

153 access = db_utils.create_access(share_id=self.share['id']) 

154 

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 } 

202 

203 get_progress = {'total_progress': 100} 

204 

205 # mocks 

206 fake_copy = mock.MagicMock(cancelled=cancelled) 

207 

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])) 

215 

216 self.mock_object(helper.DataServiceHelper, 

217 'mount_share_instance_or_backup') 

218 

219 self.mock_object(fake_copy, 'run', mock.Mock(side_effect=exc)) 

220 

221 self.mock_object(fake_copy, 'get_progress', 

222 mock.Mock(return_value=get_progress)) 

223 

224 self.mock_object(helper.DataServiceHelper, 

225 'unmount_share_instance_or_backup', 

226 mock.Mock(side_effect=Exception('fake'))) 

227 

228 self.mock_object(helper.DataServiceHelper, 

229 'deny_access_to_data_service', 

230 mock.Mock(side_effect=Exception('fake'))) 

231 

232 extra_updates = None 

233 

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 ] 

250 

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) 

256 

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 ] 

271 

272 # asserts 

273 self.assertEqual( 

274 self.manager.busy_tasks_shares[self.share['id']], fake_copy) 

275 

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 

286 

287 db.share_update.assert_has_calls(update_list) 

288 

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/')]) 

293 

294 fake_copy.run.assert_called_once_with() 

295 if exc is None: 

296 fake_copy.get_progress.assert_called_once_with() 

297 

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/')]) 

302 

303 def test__copy_share_data_exception_access(self): 

304 

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 } 

319 

320 fake_copy = mock.MagicMock(cancelled=False) 

321 

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']])) 

327 

328 self.mock_object( 

329 helper.DataServiceHelper, 'allow_access_to_data_service', 

330 mock.Mock( 

331 side_effect=exception.ShareDataCopyFailed(reason='fake'))) 

332 

333 self.mock_object(helper.DataServiceHelper, 'cleanup_data_access') 

334 

335 # run 

336 self.assertRaises(exception.ShareDataCopyFailed, 

337 self.manager._copy_share_data, self.context, 

338 fake_copy, connection_info_src, connection_info_dest) 

339 

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}) 

344 

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)) 

349 

350 def test__copy_share_data_exception_mount_1(self): 

351 

352 access = db_utils.create_access(share_id=self.share['id']) 

353 

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 } 

368 

369 fake_copy = mock.MagicMock(cancelled=False) 

370 

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']])) 

376 

377 self.mock_object(helper.DataServiceHelper, 

378 'allow_access_to_data_service', 

379 mock.Mock(return_value=[access])) 

380 

381 self.mock_object(helper.DataServiceHelper, 

382 'mount_share_instance_or_backup', 

383 mock.Mock(side_effect=Exception('fake'))) 

384 

385 self.mock_object(helper.DataServiceHelper, 'cleanup_data_access') 

386 self.mock_object(helper.DataServiceHelper, 'cleanup_temp_folder') 

387 

388 # run 

389 self.assertRaises(exception.ShareDataCopyFailed, 

390 self.manager._copy_share_data, self.context, 

391 fake_copy, connection_info_src, connection_info_dest) 

392 

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}) 

397 

398 helper.DataServiceHelper.\ 

399 mount_share_instance_or_backup.assert_called_once_with( 

400 connection_info_src, '/tmp/') 

401 

402 helper.DataServiceHelper.cleanup_temp_folder.assert_called_once_with( 

403 '/tmp/', 'ins1_id') 

404 

405 helper.DataServiceHelper.cleanup_data_access.assert_has_calls([ 

406 mock.call([access], self.share['instance']), 

407 mock.call([access], self.share['instance'])]) 

408 

409 def test__copy_share_data_exception_mount_2(self): 

410 

411 access = db_utils.create_access(share_id=self.share['id']) 

412 

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 } 

427 

428 fake_copy = mock.MagicMock(cancelled=False) 

429 

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']])) 

435 

436 self.mock_object(helper.DataServiceHelper, 

437 'allow_access_to_data_service', 

438 mock.Mock(return_value=[access])) 

439 

440 self.mock_object(helper.DataServiceHelper, 

441 'mount_share_instance_or_backup', 

442 mock.Mock(side_effect=[None, Exception('fake')])) 

443 

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') 

448 

449 # run 

450 self.assertRaises(exception.ShareDataCopyFailed, 

451 self.manager._copy_share_data, self.context, 

452 fake_copy, connection_info_src, connection_info_dest) 

453 

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}) 

458 

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/')]) 

463 

464 helper.DataServiceHelper.cleanup_unmount_temp_folder.\ 

465 assert_called_once_with(connection_info_src, '/tmp/') 

466 

467 helper.DataServiceHelper.cleanup_temp_folder.assert_has_calls([ 

468 mock.call('/tmp/', 'ins2_id'), mock.call('/tmp/', 'ins1_id')]) 

469 

470 def test_data_copy_cancel(self): 

471 

472 share = db_utils.create_share() 

473 

474 self.manager.busy_tasks_shares[share['id']] = data_utils.Copy 

475 

476 # mocks 

477 self.mock_object(data_utils.Copy, 'cancel') 

478 

479 # run 

480 self.manager.data_copy_cancel(self.context, share['id']) 

481 

482 # asserts 

483 data_utils.Copy.cancel.assert_called_once_with() 

484 

485 def test_data_copy_cancel_not_copying(self): 

486 

487 self.assertRaises(exception.InvalidShare, 

488 self.manager.data_copy_cancel, self.context, 

489 'fake_id') 

490 

491 def test_data_copy_get_progress(self): 

492 

493 share = db_utils.create_share() 

494 

495 self.manager.busy_tasks_shares[share['id']] = data_utils.Copy 

496 

497 expected = 'fake_progress' 

498 

499 # mocks 

500 self.mock_object(data_utils.Copy, 'get_progress', 

501 mock.Mock(return_value=expected)) 

502 

503 # run 

504 result = self.manager.data_copy_get_progress(self.context, share['id']) 

505 

506 # asserts 

507 self.assertEqual(expected, result) 

508 

509 data_utils.Copy.get_progress.assert_called_once_with() 

510 

511 def test_data_copy_get_progress_not_copying(self): 

512 

513 self.assertRaises(exception.InvalidShare, 

514 self.manager.data_copy_get_progress, self.context, 

515 'fake_id') 

516 

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) 

522 

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'}) 

538 

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) 

543 

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() 

561 

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)) 

586 

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) 

591 

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) 

598 

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}) 

611 

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)) 

625 

626 self.manager.create_backup_continue(self.context) 

627 

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}) 

634 

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 } 

647 

648 # mocks 

649 self.mock_object(db, 'share_instance_get', 

650 mock.Mock(return_value=share_instance)) 

651 

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)) 

657 

658 self.mock_object(self.manager, '_run_backup') 

659 

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) 

666 

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') 

676 

677 reservation = 'fake' 

678 self.mock_object(quota.QUOTAS, 'reserve', 

679 mock.Mock(return_value=reservation)) 

680 self.mock_object(quota.QUOTAS, 'commit') 

681 

682 self.manager.delete_backup(self.context, backup_info) 

683 db.share_backup_delete.assert_called_with( 

684 self.context, backup_info['id']) 

685 

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') 

694 

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) 

701 

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'] 

707 

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'}) 

722 

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'] 

730 

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)) 

740 

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() 

746 

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'] 

752 

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}) 

768 

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'] 

783 

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)) 

795 

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) 

800 

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) 

807 

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}) 

820 

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'] 

828 

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)) 

838 

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}) 

846 

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 } 

859 

860 # mocks 

861 self.mock_object(db, 'share_instance_get', 

862 mock.Mock(return_value=share_instance)) 

863 

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)) 

869 

870 self.mock_object(self.manager, '_run_restore') 

871 

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) 

878 

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) 

898 

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) 

919 

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) 

935 

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)) 

949 

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) 

958 

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)